PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.9
4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 4.2.1 All 138 releases
learnpress / assets / js / dist / admin / admin-statistic.js

admin-statistic.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.3.9, at assets/js/dist/admin/admin-statistic.js

15,738 lines 566.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ "use strict";
3 /******/ var __webpack_modules__ = ({
4
5 /***/ "./node_modules/@kurkle/color/dist/color.esm.js"
6 /*!******************************************************!*\
7 !*** ./node_modules/@kurkle/color/dist/color.esm.js ***!
8 \******************************************************/
9 (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
10
11 __webpack_require__.r(__webpack_exports__);
12 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
13 /* harmony export */ Color: () => (/* binding */ Color),
14 /* harmony export */ b2n: () => (/* binding */ b2n),
15 /* harmony export */ b2p: () => (/* binding */ b2p),
16 /* harmony export */ "default": () => (/* binding */ index_esm),
17 /* harmony export */ hexParse: () => (/* binding */ hexParse),
18 /* harmony export */ hexString: () => (/* binding */ hexString),
19 /* harmony export */ hsl2rgb: () => (/* binding */ hsl2rgb),
20 /* harmony export */ hslString: () => (/* binding */ hslString),
21 /* harmony export */ hsv2rgb: () => (/* binding */ hsv2rgb),
22 /* harmony export */ hueParse: () => (/* binding */ hueParse),
23 /* harmony export */ hwb2rgb: () => (/* binding */ hwb2rgb),
24 /* harmony export */ lim: () => (/* binding */ lim),
25 /* harmony export */ n2b: () => (/* binding */ n2b),
26 /* harmony export */ n2p: () => (/* binding */ n2p),
27 /* harmony export */ nameParse: () => (/* binding */ nameParse),
28 /* harmony export */ p2b: () => (/* binding */ p2b),
29 /* harmony export */ rgb2hsl: () => (/* binding */ rgb2hsl),
30 /* harmony export */ rgbParse: () => (/* binding */ rgbParse),
31 /* harmony export */ rgbString: () => (/* binding */ rgbString),
32 /* harmony export */ rotate: () => (/* binding */ rotate),
33 /* harmony export */ round: () => (/* binding */ round)
34 /* harmony export */ });
35 /*!
36 * @kurkle/color v0.3.4
37 * https://github.com/kurkle/color#readme
38 * (c) 2024 Jukka Kurkela
39 * Released under the MIT License
40 */
41 function round(v) {
42 return v + 0.5 | 0;
43 }
44 const lim = (v, l, h) => Math.max(Math.min(v, h), l);
45 function p2b(v) {
46 return lim(round(v * 2.55), 0, 255);
47 }
48 function b2p(v) {
49 return lim(round(v / 2.55), 0, 100);
50 }
51 function n2b(v) {
52 return lim(round(v * 255), 0, 255);
53 }
54 function b2n(v) {
55 return lim(round(v / 2.55) / 100, 0, 1);
56 }
57 function n2p(v) {
58 return lim(round(v * 100), 0, 100);
59 }
60
61 const map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15};
62 const hex = [...'0123456789ABCDEF'];
63 const h1 = b => hex[b & 0xF];
64 const h2 = b => hex[(b & 0xF0) >> 4] + hex[b & 0xF];
65 const eq = b => ((b & 0xF0) >> 4) === (b & 0xF);
66 const isShort = v => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a);
67 function hexParse(str) {
68 var len = str.length;
69 var ret;
70 if (str[0] === '#') {
71 if (len === 4 || len === 5) {
72 ret = {
73 r: 255 & map$1[str[1]] * 17,
74 g: 255 & map$1[str[2]] * 17,
75 b: 255 & map$1[str[3]] * 17,
76 a: len === 5 ? map$1[str[4]] * 17 : 255
77 };
78 } else if (len === 7 || len === 9) {
79 ret = {
80 r: map$1[str[1]] << 4 | map$1[str[2]],
81 g: map$1[str[3]] << 4 | map$1[str[4]],
82 b: map$1[str[5]] << 4 | map$1[str[6]],
83 a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255
84 };
85 }
86 }
87 return ret;
88 }
89 const alpha = (a, f) => a < 255 ? f(a) : '';
90 function hexString(v) {
91 var f = isShort(v) ? h1 : h2;
92 return v
93 ? '#' + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f)
94 : undefined;
95 }
96
97 const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;
98 function hsl2rgbn(h, s, l) {
99 const a = s * Math.min(l, 1 - l);
100 const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
101 return [f(0), f(8), f(4)];
102 }
103 function hsv2rgbn(h, s, v) {
104 const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
105 return [f(5), f(3), f(1)];
106 }
107 function hwb2rgbn(h, w, b) {
108 const rgb = hsl2rgbn(h, 1, 0.5);
109 let i;
110 if (w + b > 1) {
111 i = 1 / (w + b);
112 w *= i;
113 b *= i;
114 }
115 for (i = 0; i < 3; i++) {
116 rgb[i] *= 1 - w - b;
117 rgb[i] += w;
118 }
119 return rgb;
120 }
121 function hueValue(r, g, b, d, max) {
122 if (r === max) {
123 return ((g - b) / d) + (g < b ? 6 : 0);
124 }
125 if (g === max) {
126 return (b - r) / d + 2;
127 }
128 return (r - g) / d + 4;
129 }
130 function rgb2hsl(v) {
131 const range = 255;
132 const r = v.r / range;
133 const g = v.g / range;
134 const b = v.b / range;
135 const max = Math.max(r, g, b);
136 const min = Math.min(r, g, b);
137 const l = (max + min) / 2;
138 let h, s, d;
139 if (max !== min) {
140 d = max - min;
141 s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
142 h = hueValue(r, g, b, d, max);
143 h = h * 60 + 0.5;
144 }
145 return [h | 0, s || 0, l];
146 }
147 function calln(f, a, b, c) {
148 return (
149 Array.isArray(a)
150 ? f(a[0], a[1], a[2])
151 : f(a, b, c)
152 ).map(n2b);
153 }
154 function hsl2rgb(h, s, l) {
155 return calln(hsl2rgbn, h, s, l);
156 }
157 function hwb2rgb(h, w, b) {
158 return calln(hwb2rgbn, h, w, b);
159 }
160 function hsv2rgb(h, s, v) {
161 return calln(hsv2rgbn, h, s, v);
162 }
163 function hue(h) {
164 return (h % 360 + 360) % 360;
165 }
166 function hueParse(str) {
167 const m = HUE_RE.exec(str);
168 let a = 255;
169 let v;
170 if (!m) {
171 return;
172 }
173 if (m[5] !== v) {
174 a = m[6] ? p2b(+m[5]) : n2b(+m[5]);
175 }
176 const h = hue(+m[2]);
177 const p1 = +m[3] / 100;
178 const p2 = +m[4] / 100;
179 if (m[1] === 'hwb') {
180 v = hwb2rgb(h, p1, p2);
181 } else if (m[1] === 'hsv') {
182 v = hsv2rgb(h, p1, p2);
183 } else {
184 v = hsl2rgb(h, p1, p2);
185 }
186 return {
187 r: v[0],
188 g: v[1],
189 b: v[2],
190 a: a
191 };
192 }
193 function rotate(v, deg) {
194 var h = rgb2hsl(v);
195 h[0] = hue(h[0] + deg);
196 h = hsl2rgb(h);
197 v.r = h[0];
198 v.g = h[1];
199 v.b = h[2];
200 }
201 function hslString(v) {
202 if (!v) {
203 return;
204 }
205 const a = rgb2hsl(v);
206 const h = a[0];
207 const s = n2p(a[1]);
208 const l = n2p(a[2]);
209 return v.a < 255
210 ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})`
211 : `hsl(${h}, ${s}%, ${l}%)`;
212 }
213
214 const map = {
215 x: 'dark',
216 Z: 'light',
217 Y: 're',
218 X: 'blu',
219 W: 'gr',
220 V: 'medium',
221 U: 'slate',
222 A: 'ee',
223 T: 'ol',
224 S: 'or',
225 B: 'ra',
226 C: 'lateg',
227 D: 'ights',
228 R: 'in',
229 Q: 'turquois',
230 E: 'hi',
231 P: 'ro',
232 O: 'al',
233 N: 'le',
234 M: 'de',
235 L: 'yello',
236 F: 'en',
237 K: 'ch',
238 G: 'arks',
239 H: 'ea',
240 I: 'ightg',
241 J: 'wh'
242 };
243 const names$1 = {
244 OiceXe: 'f0f8ff',
245 antiquewEte: 'faebd7',
246 aqua: 'ffff',
247 aquamarRe: '7fffd4',
248 azuY: 'f0ffff',
249 beige: 'f5f5dc',
250 bisque: 'ffe4c4',
251 black: '0',
252 blanKedOmond: 'ffebcd',
253 Xe: 'ff',
254 XeviTet: '8a2be2',
255 bPwn: 'a52a2a',
256 burlywood: 'deb887',
257 caMtXe: '5f9ea0',
258 KartYuse: '7fff00',
259 KocTate: 'd2691e',
260 cSO: 'ff7f50',
261 cSnflowerXe: '6495ed',
262 cSnsilk: 'fff8dc',
263 crimson: 'dc143c',
264 cyan: 'ffff',
265 xXe: '8b',
266 xcyan: '8b8b',
267 xgTMnPd: 'b8860b',
268 xWay: 'a9a9a9',
269 xgYF: '6400',
270 xgYy: 'a9a9a9',
271 xkhaki: 'bdb76b',
272 xmagFta: '8b008b',
273 xTivegYF: '556b2f',
274 xSange: 'ff8c00',
275 xScEd: '9932cc',
276 xYd: '8b0000',
277 xsOmon: 'e9967a',
278 xsHgYF: '8fbc8f',
279 xUXe: '483d8b',
280 xUWay: '2f4f4f',
281 xUgYy: '2f4f4f',
282 xQe: 'ced1',
283 xviTet: '9400d3',
284 dAppRk: 'ff1493',
285 dApskyXe: 'bfff',
286 dimWay: '696969',
287 dimgYy: '696969',
288 dodgerXe: '1e90ff',
289 fiYbrick: 'b22222',
290 flSOwEte: 'fffaf0',
291 foYstWAn: '228b22',
292 fuKsia: 'ff00ff',
293 gaRsbSo: 'dcdcdc',
294 ghostwEte: 'f8f8ff',
295 gTd: 'ffd700',
296 gTMnPd: 'daa520',
297 Way: '808080',
298 gYF: '8000',
299 gYFLw: 'adff2f',
300 gYy: '808080',
301 honeyMw: 'f0fff0',
302 hotpRk: 'ff69b4',
303 RdianYd: 'cd5c5c',
304 Rdigo: '4b0082',
305 ivSy: 'fffff0',
306 khaki: 'f0e68c',
307 lavFMr: 'e6e6fa',
308 lavFMrXsh: 'fff0f5',
309 lawngYF: '7cfc00',
310 NmoncEffon: 'fffacd',
311 ZXe: 'add8e6',
312 ZcSO: 'f08080',
313 Zcyan: 'e0ffff',
314 ZgTMnPdLw: 'fafad2',
315 ZWay: 'd3d3d3',
316 ZgYF: '90ee90',
317 ZgYy: 'd3d3d3',
318 ZpRk: 'ffb6c1',
319 ZsOmon: 'ffa07a',
320 ZsHgYF: '20b2aa',
321 ZskyXe: '87cefa',
322 ZUWay: '778899',
323 ZUgYy: '778899',
324 ZstAlXe: 'b0c4de',
325 ZLw: 'ffffe0',
326 lime: 'ff00',
327 limegYF: '32cd32',
328 lRF: 'faf0e6',
329 magFta: 'ff00ff',
330 maPon: '800000',
331 VaquamarRe: '66cdaa',
332 VXe: 'cd',
333 VScEd: 'ba55d3',
334 VpurpN: '9370db',
335 VsHgYF: '3cb371',
336 VUXe: '7b68ee',
337 VsprRggYF: 'fa9a',
338 VQe: '48d1cc',
339 VviTetYd: 'c71585',
340 midnightXe: '191970',
341 mRtcYam: 'f5fffa',
342 mistyPse: 'ffe4e1',
343 moccasR: 'ffe4b5',
344 navajowEte: 'ffdead',
345 navy: '80',
346 Tdlace: 'fdf5e6',
347 Tive: '808000',
348 TivedBb: '6b8e23',
349 Sange: 'ffa500',
350 SangeYd: 'ff4500',
351 ScEd: 'da70d6',
352 pOegTMnPd: 'eee8aa',
353 pOegYF: '98fb98',
354 pOeQe: 'afeeee',
355 pOeviTetYd: 'db7093',
356 papayawEp: 'ffefd5',
357 pHKpuff: 'ffdab9',
358 peru: 'cd853f',
359 pRk: 'ffc0cb',
360 plum: 'dda0dd',
361 powMrXe: 'b0e0e6',
362 purpN: '800080',
363 YbeccapurpN: '663399',
364 Yd: 'ff0000',
365 Psybrown: 'bc8f8f',
366 PyOXe: '4169e1',
367 saddNbPwn: '8b4513',
368 sOmon: 'fa8072',
369 sandybPwn: 'f4a460',
370 sHgYF: '2e8b57',
371 sHshell: 'fff5ee',
372 siFna: 'a0522d',
373 silver: 'c0c0c0',
374 skyXe: '87ceeb',
375 UXe: '6a5acd',
376 UWay: '708090',
377 UgYy: '708090',
378 snow: 'fffafa',
379 sprRggYF: 'ff7f',
380 stAlXe: '4682b4',
381 tan: 'd2b48c',
382 teO: '8080',
383 tEstN: 'd8bfd8',
384 tomato: 'ff6347',
385 Qe: '40e0d0',
386 viTet: 'ee82ee',
387 JHt: 'f5deb3',
388 wEte: 'ffffff',
389 wEtesmoke: 'f5f5f5',
390 Lw: 'ffff00',
391 LwgYF: '9acd32'
392 };
393 function unpack() {
394 const unpacked = {};
395 const keys = Object.keys(names$1);
396 const tkeys = Object.keys(map);
397 let i, j, k, ok, nk;
398 for (i = 0; i < keys.length; i++) {
399 ok = nk = keys[i];
400 for (j = 0; j < tkeys.length; j++) {
401 k = tkeys[j];
402 nk = nk.replace(k, map[k]);
403 }
404 k = parseInt(names$1[ok], 16);
405 unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF];
406 }
407 return unpacked;
408 }
409
410 let names;
411 function nameParse(str) {
412 if (!names) {
413 names = unpack();
414 names.transparent = [0, 0, 0, 0];
415 }
416 const a = names[str.toLowerCase()];
417 return a && {
418 r: a[0],
419 g: a[1],
420 b: a[2],
421 a: a.length === 4 ? a[3] : 255
422 };
423 }
424
425 const RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;
426 function rgbParse(str) {
427 const m = RGB_RE.exec(str);
428 let a = 255;
429 let r, g, b;
430 if (!m) {
431 return;
432 }
433 if (m[7] !== r) {
434 const v = +m[7];
435 a = m[8] ? p2b(v) : lim(v * 255, 0, 255);
436 }
437 r = +m[1];
438 g = +m[3];
439 b = +m[5];
440 r = 255 & (m[2] ? p2b(r) : lim(r, 0, 255));
441 g = 255 & (m[4] ? p2b(g) : lim(g, 0, 255));
442 b = 255 & (m[6] ? p2b(b) : lim(b, 0, 255));
443 return {
444 r: r,
445 g: g,
446 b: b,
447 a: a
448 };
449 }
450 function rgbString(v) {
451 return v && (
452 v.a < 255
453 ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`
454 : `rgb(${v.r}, ${v.g}, ${v.b})`
455 );
456 }
457
458 const to = v => v <= 0.0031308 ? v * 12.92 : Math.pow(v, 1.0 / 2.4) * 1.055 - 0.055;
459 const from = v => v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
460 function interpolate(rgb1, rgb2, t) {
461 const r = from(b2n(rgb1.r));
462 const g = from(b2n(rgb1.g));
463 const b = from(b2n(rgb1.b));
464 return {
465 r: n2b(to(r + t * (from(b2n(rgb2.r)) - r))),
466 g: n2b(to(g + t * (from(b2n(rgb2.g)) - g))),
467 b: n2b(to(b + t * (from(b2n(rgb2.b)) - b))),
468 a: rgb1.a + t * (rgb2.a - rgb1.a)
469 };
470 }
471
472 function modHSL(v, i, ratio) {
473 if (v) {
474 let tmp = rgb2hsl(v);
475 tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));
476 tmp = hsl2rgb(tmp);
477 v.r = tmp[0];
478 v.g = tmp[1];
479 v.b = tmp[2];
480 }
481 }
482 function clone(v, proto) {
483 return v ? Object.assign(proto || {}, v) : v;
484 }
485 function fromObject(input) {
486 var v = {r: 0, g: 0, b: 0, a: 255};
487 if (Array.isArray(input)) {
488 if (input.length >= 3) {
489 v = {r: input[0], g: input[1], b: input[2], a: 255};
490 if (input.length > 3) {
491 v.a = n2b(input[3]);
492 }
493 }
494 } else {
495 v = clone(input, {r: 0, g: 0, b: 0, a: 1});
496 v.a = n2b(v.a);
497 }
498 return v;
499 }
500 function functionParse(str) {
501 if (str.charAt(0) === 'r') {
502 return rgbParse(str);
503 }
504 return hueParse(str);
505 }
506 class Color {
507 constructor(input) {
508 if (input instanceof Color) {
509 return input;
510 }
511 const type = typeof input;
512 let v;
513 if (type === 'object') {
514 v = fromObject(input);
515 } else if (type === 'string') {
516 v = hexParse(input) || nameParse(input) || functionParse(input);
517 }
518 this._rgb = v;
519 this._valid = !!v;
520 }
521 get valid() {
522 return this._valid;
523 }
524 get rgb() {
525 var v = clone(this._rgb);
526 if (v) {
527 v.a = b2n(v.a);
528 }
529 return v;
530 }
531 set rgb(obj) {
532 this._rgb = fromObject(obj);
533 }
534 rgbString() {
535 return this._valid ? rgbString(this._rgb) : undefined;
536 }
537 hexString() {
538 return this._valid ? hexString(this._rgb) : undefined;
539 }
540 hslString() {
541 return this._valid ? hslString(this._rgb) : undefined;
542 }
543 mix(color, weight) {
544 if (color) {
545 const c1 = this.rgb;
546 const c2 = color.rgb;
547 let w2;
548 const p = weight === w2 ? 0.5 : weight;
549 const w = 2 * p - 1;
550 const a = c1.a - c2.a;
551 const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
552 w2 = 1 - w1;
553 c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;
554 c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;
555 c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;
556 c1.a = p * c1.a + (1 - p) * c2.a;
557 this.rgb = c1;
558 }
559 return this;
560 }
561 interpolate(color, t) {
562 if (color) {
563 this._rgb = interpolate(this._rgb, color._rgb, t);
564 }
565 return this;
566 }
567 clone() {
568 return new Color(this.rgb);
569 }
570 alpha(a) {
571 this._rgb.a = n2b(a);
572 return this;
573 }
574 clearer(ratio) {
575 const rgb = this._rgb;
576 rgb.a *= 1 - ratio;
577 return this;
578 }
579 greyscale() {
580 const rgb = this._rgb;
581 const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);
582 rgb.r = rgb.g = rgb.b = val;
583 return this;
584 }
585 opaquer(ratio) {
586 const rgb = this._rgb;
587 rgb.a *= 1 + ratio;
588 return this;
589 }
590 negate() {
591 const v = this._rgb;
592 v.r = 255 - v.r;
593 v.g = 255 - v.g;
594 v.b = 255 - v.b;
595 return this;
596 }
597 lighten(ratio) {
598 modHSL(this._rgb, 2, ratio);
599 return this;
600 }
601 darken(ratio) {
602 modHSL(this._rgb, 2, -ratio);
603 return this;
604 }
605 saturate(ratio) {
606 modHSL(this._rgb, 1, ratio);
607 return this;
608 }
609 desaturate(ratio) {
610 modHSL(this._rgb, 1, -ratio);
611 return this;
612 }
613 rotate(deg) {
614 rotate(this._rgb, deg);
615 return this;
616 }
617 }
618
619 function index_esm(input) {
620 return new Color(input);
621 }
622
623
624
625
626 /***/ },
627
628 /***/ "./node_modules/chart.js/auto/auto.js"
629 /*!********************************************!*\
630 !*** ./node_modules/chart.js/auto/auto.js ***!
631 \********************************************/
632 (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
633
634 __webpack_require__.r(__webpack_exports__);
635 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
636 /* harmony export */ Animation: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Animation),
637 /* harmony export */ Animations: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Animations),
638 /* harmony export */ ArcElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.ArcElement),
639 /* harmony export */ BarController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BarController),
640 /* harmony export */ BarElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BarElement),
641 /* harmony export */ BasePlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BasePlatform),
642 /* harmony export */ BasicPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BasicPlatform),
643 /* harmony export */ BubbleController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.BubbleController),
644 /* harmony export */ CategoryScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.CategoryScale),
645 /* harmony export */ Chart: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart),
646 /* harmony export */ Colors: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Colors),
647 /* harmony export */ DatasetController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DatasetController),
648 /* harmony export */ Decimation: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Decimation),
649 /* harmony export */ DomPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DomPlatform),
650 /* harmony export */ DoughnutController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.DoughnutController),
651 /* harmony export */ Element: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Element),
652 /* harmony export */ Filler: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Filler),
653 /* harmony export */ Interaction: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Interaction),
654 /* harmony export */ Legend: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Legend),
655 /* harmony export */ LineController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LineController),
656 /* harmony export */ LineElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LineElement),
657 /* harmony export */ LinearScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LinearScale),
658 /* harmony export */ LogarithmicScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.LogarithmicScale),
659 /* harmony export */ PieController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PieController),
660 /* harmony export */ PointElement: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PointElement),
661 /* harmony export */ PolarAreaController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.PolarAreaController),
662 /* harmony export */ RadarController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.RadarController),
663 /* harmony export */ RadialLinearScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.RadialLinearScale),
664 /* harmony export */ Scale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Scale),
665 /* harmony export */ ScatterController: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.ScatterController),
666 /* harmony export */ SubTitle: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.SubTitle),
667 /* harmony export */ Ticks: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Ticks),
668 /* harmony export */ TimeScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.TimeScale),
669 /* harmony export */ TimeSeriesScale: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.TimeSeriesScale),
670 /* harmony export */ Title: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Title),
671 /* harmony export */ Tooltip: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Tooltip),
672 /* harmony export */ _adapters: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__._adapters),
673 /* harmony export */ _detectPlatform: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__._detectPlatform),
674 /* harmony export */ animator: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.animator),
675 /* harmony export */ controllers: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.controllers),
676 /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
677 /* harmony export */ defaults: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.defaults),
678 /* harmony export */ elements: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.elements),
679 /* harmony export */ layouts: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.layouts),
680 /* harmony export */ plugins: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.plugins),
681 /* harmony export */ registerables: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registerables),
682 /* harmony export */ registry: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registry),
683 /* harmony export */ scales: () => (/* reexport safe */ _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.scales)
684 /* harmony export */ });
685 /* harmony import */ var _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../dist/chart.js */ "./node_modules/chart.js/dist/chart.js");
686
687
688 _dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart.register(..._dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.registerables);
689
690
691 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_dist_chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart);
692
693
694 /***/ },
695
696 /***/ "./node_modules/chart.js/dist/chart.js"
697 /*!*********************************************!*\
698 !*** ./node_modules/chart.js/dist/chart.js ***!
699 \*********************************************/
700 (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
701
702 __webpack_require__.r(__webpack_exports__);
703 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
704 /* harmony export */ Animation: () => (/* binding */ Animation),
705 /* harmony export */ Animations: () => (/* binding */ Animations),
706 /* harmony export */ ArcElement: () => (/* binding */ ArcElement),
707 /* harmony export */ BarController: () => (/* binding */ BarController),
708 /* harmony export */ BarElement: () => (/* binding */ BarElement),
709 /* harmony export */ BasePlatform: () => (/* binding */ BasePlatform),
710 /* harmony export */ BasicPlatform: () => (/* binding */ BasicPlatform),
711 /* harmony export */ BubbleController: () => (/* binding */ BubbleController),
712 /* harmony export */ CategoryScale: () => (/* binding */ CategoryScale),
713 /* harmony export */ Chart: () => (/* binding */ Chart),
714 /* harmony export */ Colors: () => (/* binding */ plugin_colors),
715 /* harmony export */ DatasetController: () => (/* binding */ DatasetController),
716 /* harmony export */ Decimation: () => (/* binding */ plugin_decimation),
717 /* harmony export */ DomPlatform: () => (/* binding */ DomPlatform),
718 /* harmony export */ DoughnutController: () => (/* binding */ DoughnutController),
719 /* harmony export */ Element: () => (/* binding */ Element),
720 /* harmony export */ Filler: () => (/* binding */ index),
721 /* harmony export */ Interaction: () => (/* binding */ Interaction),
722 /* harmony export */ Legend: () => (/* binding */ plugin_legend),
723 /* harmony export */ LineController: () => (/* binding */ LineController),
724 /* harmony export */ LineElement: () => (/* binding */ LineElement),
725 /* harmony export */ LinearScale: () => (/* binding */ LinearScale),
726 /* harmony export */ LogarithmicScale: () => (/* binding */ LogarithmicScale),
727 /* harmony export */ PieController: () => (/* binding */ PieController),
728 /* harmony export */ PointElement: () => (/* binding */ PointElement),
729 /* harmony export */ PolarAreaController: () => (/* binding */ PolarAreaController),
730 /* harmony export */ RadarController: () => (/* binding */ RadarController),
731 /* harmony export */ RadialLinearScale: () => (/* binding */ RadialLinearScale),
732 /* harmony export */ Scale: () => (/* binding */ Scale),
733 /* harmony export */ ScatterController: () => (/* binding */ ScatterController),
734 /* harmony export */ SubTitle: () => (/* binding */ plugin_subtitle),
735 /* harmony export */ Ticks: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM),
736 /* harmony export */ TimeScale: () => (/* binding */ TimeScale),
737 /* harmony export */ TimeSeriesScale: () => (/* binding */ TimeSeriesScale),
738 /* harmony export */ Title: () => (/* binding */ plugin_title),
739 /* harmony export */ Tooltip: () => (/* binding */ plugin_tooltip),
740 /* harmony export */ _adapters: () => (/* binding */ adapters),
741 /* harmony export */ _detectPlatform: () => (/* binding */ _detectPlatform),
742 /* harmony export */ animator: () => (/* binding */ animator),
743 /* harmony export */ controllers: () => (/* binding */ controllers),
744 /* harmony export */ defaults: () => (/* reexport safe */ _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d),
745 /* harmony export */ elements: () => (/* binding */ elements),
746 /* harmony export */ layouts: () => (/* binding */ layouts),
747 /* harmony export */ plugins: () => (/* binding */ plugins),
748 /* harmony export */ registerables: () => (/* binding */ registerables),
749 /* harmony export */ registry: () => (/* binding */ registry),
750 /* harmony export */ scales: () => (/* binding */ scales)
751 /* harmony export */ });
752 /* harmony import */ var _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunks/helpers.dataset.js */ "./node_modules/chart.js/dist/chunks/helpers.dataset.js");
753 /*!
754 * Chart.js v4.5.1
755 * https://www.chartjs.org
756 * (c) 2025 Chart.js Contributors
757 * Released under the MIT License
758 */
759
760
761
762 class Animator {
763 constructor(){
764 this._request = null;
765 this._charts = new Map();
766 this._running = false;
767 this._lastDate = undefined;
768 }
769 _notify(chart, anims, date, type) {
770 const callbacks = anims.listeners[type];
771 const numSteps = anims.duration;
772 callbacks.forEach((fn)=>fn({
773 chart,
774 initial: anims.initial,
775 numSteps,
776 currentStep: Math.min(date - anims.start, numSteps)
777 }));
778 }
779 _refresh() {
780 if (this._request) {
781 return;
782 }
783 this._running = true;
784 this._request = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.r.call(window, ()=>{
785 this._update();
786 this._request = null;
787 if (this._running) {
788 this._refresh();
789 }
790 });
791 }
792 _update(date = Date.now()) {
793 let remaining = 0;
794 this._charts.forEach((anims, chart)=>{
795 if (!anims.running || !anims.items.length) {
796 return;
797 }
798 const items = anims.items;
799 let i = items.length - 1;
800 let draw = false;
801 let item;
802 for(; i >= 0; --i){
803 item = items[i];
804 if (item._active) {
805 if (item._total > anims.duration) {
806 anims.duration = item._total;
807 }
808 item.tick(date);
809 draw = true;
810 } else {
811 items[i] = items[items.length - 1];
812 items.pop();
813 }
814 }
815 if (draw) {
816 chart.draw();
817 this._notify(chart, anims, date, 'progress');
818 }
819 if (!items.length) {
820 anims.running = false;
821 this._notify(chart, anims, date, 'complete');
822 anims.initial = false;
823 }
824 remaining += items.length;
825 });
826 this._lastDate = date;
827 if (remaining === 0) {
828 this._running = false;
829 }
830 }
831 _getAnims(chart) {
832 const charts = this._charts;
833 let anims = charts.get(chart);
834 if (!anims) {
835 anims = {
836 running: false,
837 initial: true,
838 items: [],
839 listeners: {
840 complete: [],
841 progress: []
842 }
843 };
844 charts.set(chart, anims);
845 }
846 return anims;
847 }
848 listen(chart, event, cb) {
849 this._getAnims(chart).listeners[event].push(cb);
850 }
851 add(chart, items) {
852 if (!items || !items.length) {
853 return;
854 }
855 this._getAnims(chart).items.push(...items);
856 }
857 has(chart) {
858 return this._getAnims(chart).items.length > 0;
859 }
860 start(chart) {
861 const anims = this._charts.get(chart);
862 if (!anims) {
863 return;
864 }
865 anims.running = true;
866 anims.start = Date.now();
867 anims.duration = anims.items.reduce((acc, cur)=>Math.max(acc, cur._duration), 0);
868 this._refresh();
869 }
870 running(chart) {
871 if (!this._running) {
872 return false;
873 }
874 const anims = this._charts.get(chart);
875 if (!anims || !anims.running || !anims.items.length) {
876 return false;
877 }
878 return true;
879 }
880 stop(chart) {
881 const anims = this._charts.get(chart);
882 if (!anims || !anims.items.length) {
883 return;
884 }
885 const items = anims.items;
886 let i = items.length - 1;
887 for(; i >= 0; --i){
888 items[i].cancel();
889 }
890 anims.items = [];
891 this._notify(chart, anims, Date.now(), 'complete');
892 }
893 remove(chart) {
894 return this._charts.delete(chart);
895 }
896 }
897 var animator = /* #__PURE__ */ new Animator();
898
899 const transparent = 'transparent';
900 const interpolators = {
901 boolean (from, to, factor) {
902 return factor > 0.5 ? to : from;
903 },
904 color (from, to, factor) {
905 const c0 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.c)(from || transparent);
906 const c1 = c0.valid && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.c)(to || transparent);
907 return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to;
908 },
909 number (from, to, factor) {
910 return from + (to - from) * factor;
911 }
912 };
913 class Animation {
914 constructor(cfg, target, prop, to){
915 const currentValue = target[prop];
916 to = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([
917 cfg.to,
918 to,
919 currentValue,
920 cfg.from
921 ]);
922 const from = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([
923 cfg.from,
924 currentValue,
925 to
926 ]);
927 this._active = true;
928 this._fn = cfg.fn || interpolators[cfg.type || typeof from];
929 this._easing = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.e[cfg.easing] || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.e.linear;
930 this._start = Math.floor(Date.now() + (cfg.delay || 0));
931 this._duration = this._total = Math.floor(cfg.duration);
932 this._loop = !!cfg.loop;
933 this._target = target;
934 this._prop = prop;
935 this._from = from;
936 this._to = to;
937 this._promises = undefined;
938 }
939 active() {
940 return this._active;
941 }
942 update(cfg, to, date) {
943 if (this._active) {
944 this._notify(false);
945 const currentValue = this._target[this._prop];
946 const elapsed = date - this._start;
947 const remain = this._duration - elapsed;
948 this._start = date;
949 this._duration = Math.floor(Math.max(remain, cfg.duration));
950 this._total += elapsed;
951 this._loop = !!cfg.loop;
952 this._to = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([
953 cfg.to,
954 to,
955 currentValue,
956 cfg.from
957 ]);
958 this._from = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([
959 cfg.from,
960 currentValue,
961 to
962 ]);
963 }
964 }
965 cancel() {
966 if (this._active) {
967 this.tick(Date.now());
968 this._active = false;
969 this._notify(false);
970 }
971 }
972 tick(date) {
973 const elapsed = date - this._start;
974 const duration = this._duration;
975 const prop = this._prop;
976 const from = this._from;
977 const loop = this._loop;
978 const to = this._to;
979 let factor;
980 this._active = from !== to && (loop || elapsed < duration);
981 if (!this._active) {
982 this._target[prop] = to;
983 this._notify(true);
984 return;
985 }
986 if (elapsed < 0) {
987 this._target[prop] = from;
988 return;
989 }
990 factor = elapsed / duration % 2;
991 factor = loop && factor > 1 ? 2 - factor : factor;
992 factor = this._easing(Math.min(1, Math.max(0, factor)));
993 this._target[prop] = this._fn(from, to, factor);
994 }
995 wait() {
996 const promises = this._promises || (this._promises = []);
997 return new Promise((res, rej)=>{
998 promises.push({
999 res,
1000 rej
1001 });
1002 });
1003 }
1004 _notify(resolved) {
1005 const method = resolved ? 'res' : 'rej';
1006 const promises = this._promises || [];
1007 for(let i = 0; i < promises.length; i++){
1008 promises[i][method]();
1009 }
1010 }
1011 }
1012
1013 class Animations {
1014 constructor(chart, config){
1015 this._chart = chart;
1016 this._properties = new Map();
1017 this.configure(config);
1018 }
1019 configure(config) {
1020 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(config)) {
1021 return;
1022 }
1023 const animationOptions = Object.keys(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.animation);
1024 const animatedProps = this._properties;
1025 Object.getOwnPropertyNames(config).forEach((key)=>{
1026 const cfg = config[key];
1027 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(cfg)) {
1028 return;
1029 }
1030 const resolved = {};
1031 for (const option of animationOptions){
1032 resolved[option] = cfg[option];
1033 }
1034 ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(cfg.properties) && cfg.properties || [
1035 key
1036 ]).forEach((prop)=>{
1037 if (prop === key || !animatedProps.has(prop)) {
1038 animatedProps.set(prop, resolved);
1039 }
1040 });
1041 });
1042 }
1043 _animateOptions(target, values) {
1044 const newOptions = values.options;
1045 const options = resolveTargetOptions(target, newOptions);
1046 if (!options) {
1047 return [];
1048 }
1049 const animations = this._createAnimations(options, newOptions);
1050 if (newOptions.$shared) {
1051 awaitAll(target.options.$animations, newOptions).then(()=>{
1052 target.options = newOptions;
1053 }, ()=>{
1054 });
1055 }
1056 return animations;
1057 }
1058 _createAnimations(target, values) {
1059 const animatedProps = this._properties;
1060 const animations = [];
1061 const running = target.$animations || (target.$animations = {});
1062 const props = Object.keys(values);
1063 const date = Date.now();
1064 let i;
1065 for(i = props.length - 1; i >= 0; --i){
1066 const prop = props[i];
1067 if (prop.charAt(0) === '$') {
1068 continue;
1069 }
1070 if (prop === 'options') {
1071 animations.push(...this._animateOptions(target, values));
1072 continue;
1073 }
1074 const value = values[prop];
1075 let animation = running[prop];
1076 const cfg = animatedProps.get(prop);
1077 if (animation) {
1078 if (cfg && animation.active()) {
1079 animation.update(cfg, value, date);
1080 continue;
1081 } else {
1082 animation.cancel();
1083 }
1084 }
1085 if (!cfg || !cfg.duration) {
1086 target[prop] = value;
1087 continue;
1088 }
1089 running[prop] = animation = new Animation(cfg, target, prop, value);
1090 animations.push(animation);
1091 }
1092 return animations;
1093 }
1094 update(target, values) {
1095 if (this._properties.size === 0) {
1096 Object.assign(target, values);
1097 return;
1098 }
1099 const animations = this._createAnimations(target, values);
1100 if (animations.length) {
1101 animator.add(this._chart, animations);
1102 return true;
1103 }
1104 }
1105 }
1106 function awaitAll(animations, properties) {
1107 const running = [];
1108 const keys = Object.keys(properties);
1109 for(let i = 0; i < keys.length; i++){
1110 const anim = animations[keys[i]];
1111 if (anim && anim.active()) {
1112 running.push(anim.wait());
1113 }
1114 }
1115 return Promise.all(running);
1116 }
1117 function resolveTargetOptions(target, newOptions) {
1118 if (!newOptions) {
1119 return;
1120 }
1121 let options = target.options;
1122 if (!options) {
1123 target.options = newOptions;
1124 return;
1125 }
1126 if (options.$shared) {
1127 target.options = options = Object.assign({}, options, {
1128 $shared: false,
1129 $animations: {}
1130 });
1131 }
1132 return options;
1133 }
1134
1135 function scaleClip(scale, allowedOverflow) {
1136 const opts = scale && scale.options || {};
1137 const reverse = opts.reverse;
1138 const min = opts.min === undefined ? allowedOverflow : 0;
1139 const max = opts.max === undefined ? allowedOverflow : 0;
1140 return {
1141 start: reverse ? max : min,
1142 end: reverse ? min : max
1143 };
1144 }
1145 function defaultClip(xScale, yScale, allowedOverflow) {
1146 if (allowedOverflow === false) {
1147 return false;
1148 }
1149 const x = scaleClip(xScale, allowedOverflow);
1150 const y = scaleClip(yScale, allowedOverflow);
1151 return {
1152 top: y.end,
1153 right: x.end,
1154 bottom: y.start,
1155 left: x.start
1156 };
1157 }
1158 function toClip(value) {
1159 let t, r, b, l;
1160 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value)) {
1161 t = value.top;
1162 r = value.right;
1163 b = value.bottom;
1164 l = value.left;
1165 } else {
1166 t = r = b = l = value;
1167 }
1168 return {
1169 top: t,
1170 right: r,
1171 bottom: b,
1172 left: l,
1173 disabled: value === false
1174 };
1175 }
1176 function getSortedDatasetIndices(chart, filterVisible) {
1177 const keys = [];
1178 const metasets = chart._getSortedDatasetMetas(filterVisible);
1179 let i, ilen;
1180 for(i = 0, ilen = metasets.length; i < ilen; ++i){
1181 keys.push(metasets[i].index);
1182 }
1183 return keys;
1184 }
1185 function applyStack(stack, value, dsIndex, options = {}) {
1186 const keys = stack.keys;
1187 const singleMode = options.mode === 'single';
1188 let i, ilen, datasetIndex, otherValue;
1189 if (value === null) {
1190 return;
1191 }
1192 let found = false;
1193 for(i = 0, ilen = keys.length; i < ilen; ++i){
1194 datasetIndex = +keys[i];
1195 if (datasetIndex === dsIndex) {
1196 found = true;
1197 if (options.all) {
1198 continue;
1199 }
1200 break;
1201 }
1202 otherValue = stack.values[datasetIndex];
1203 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(otherValue) && (singleMode || value === 0 || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) === (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(otherValue))) {
1204 value += otherValue;
1205 }
1206 }
1207 if (!found && !options.all) {
1208 return 0;
1209 }
1210 return value;
1211 }
1212 function convertObjectDataToArray(data, meta) {
1213 const { iScale , vScale } = meta;
1214 const iAxisKey = iScale.axis === 'x' ? 'x' : 'y';
1215 const vAxisKey = vScale.axis === 'x' ? 'x' : 'y';
1216 const keys = Object.keys(data);
1217 const adata = new Array(keys.length);
1218 let i, ilen, key;
1219 for(i = 0, ilen = keys.length; i < ilen; ++i){
1220 key = keys[i];
1221 adata[i] = {
1222 [iAxisKey]: key,
1223 [vAxisKey]: data[key]
1224 };
1225 }
1226 return adata;
1227 }
1228 function isStacked(scale, meta) {
1229 const stacked = scale && scale.options.stacked;
1230 return stacked || stacked === undefined && meta.stack !== undefined;
1231 }
1232 function getStackKey(indexScale, valueScale, meta) {
1233 return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;
1234 }
1235 function getUserBounds(scale) {
1236 const { min , max , minDefined , maxDefined } = scale.getUserBounds();
1237 return {
1238 min: minDefined ? min : Number.NEGATIVE_INFINITY,
1239 max: maxDefined ? max : Number.POSITIVE_INFINITY
1240 };
1241 }
1242 function getOrCreateStack(stacks, stackKey, indexValue) {
1243 const subStack = stacks[stackKey] || (stacks[stackKey] = {});
1244 return subStack[indexValue] || (subStack[indexValue] = {});
1245 }
1246 function getLastIndexInStack(stack, vScale, positive, type) {
1247 for (const meta of vScale.getMatchingVisibleMetas(type).reverse()){
1248 const value = stack[meta.index];
1249 if (positive && value > 0 || !positive && value < 0) {
1250 return meta.index;
1251 }
1252 }
1253 return null;
1254 }
1255 function updateStacks(controller, parsed) {
1256 const { chart , _cachedMeta: meta } = controller;
1257 const stacks = chart._stacks || (chart._stacks = {});
1258 const { iScale , vScale , index: datasetIndex } = meta;
1259 const iAxis = iScale.axis;
1260 const vAxis = vScale.axis;
1261 const key = getStackKey(iScale, vScale, meta);
1262 const ilen = parsed.length;
1263 let stack;
1264 for(let i = 0; i < ilen; ++i){
1265 const item = parsed[i];
1266 const { [iAxis]: index , [vAxis]: value } = item;
1267 const itemStacks = item._stacks || (item._stacks = {});
1268 stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
1269 stack[datasetIndex] = value;
1270 stack._top = getLastIndexInStack(stack, vScale, true, meta.type);
1271 stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);
1272 const visualValues = stack._visualValues || (stack._visualValues = {});
1273 visualValues[datasetIndex] = value;
1274 }
1275 }
1276 function getFirstScaleId(chart, axis) {
1277 const scales = chart.scales;
1278 return Object.keys(scales).filter((key)=>scales[key].axis === axis).shift();
1279 }
1280 function createDatasetContext(parent, index) {
1281 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
1282 active: false,
1283 dataset: undefined,
1284 datasetIndex: index,
1285 index,
1286 mode: 'default',
1287 type: 'dataset'
1288 });
1289 }
1290 function createDataContext(parent, index, element) {
1291 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
1292 active: false,
1293 dataIndex: index,
1294 parsed: undefined,
1295 raw: undefined,
1296 element,
1297 index,
1298 mode: 'default',
1299 type: 'data'
1300 });
1301 }
1302 function clearStacks(meta, items) {
1303 const datasetIndex = meta.controller.index;
1304 const axis = meta.vScale && meta.vScale.axis;
1305 if (!axis) {
1306 return;
1307 }
1308 items = items || meta._parsed;
1309 for (const parsed of items){
1310 const stacks = parsed._stacks;
1311 if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) {
1312 return;
1313 }
1314 delete stacks[axis][datasetIndex];
1315 if (stacks[axis]._visualValues !== undefined && stacks[axis]._visualValues[datasetIndex] !== undefined) {
1316 delete stacks[axis]._visualValues[datasetIndex];
1317 }
1318 }
1319 }
1320 const isDirectUpdateMode = (mode)=>mode === 'reset' || mode === 'none';
1321 const cloneIfNotShared = (cached, shared)=>shared ? cached : Object.assign({}, cached);
1322 const createStack = (canStack, meta, chart)=>canStack && !meta.hidden && meta._stacked && {
1323 keys: getSortedDatasetIndices(chart, true),
1324 values: null
1325 };
1326 class DatasetController {
1327 static defaults = {};
1328 static datasetElementType = null;
1329 static dataElementType = null;
1330 constructor(chart, datasetIndex){
1331 this.chart = chart;
1332 this._ctx = chart.ctx;
1333 this.index = datasetIndex;
1334 this._cachedDataOpts = {};
1335 this._cachedMeta = this.getMeta();
1336 this._type = this._cachedMeta.type;
1337 this.options = undefined;
1338 this._parsing = false;
1339 this._data = undefined;
1340 this._objectData = undefined;
1341 this._sharedOptions = undefined;
1342 this._drawStart = undefined;
1343 this._drawCount = undefined;
1344 this.enableOptionSharing = false;
1345 this.supportsDecimation = false;
1346 this.$context = undefined;
1347 this._syncList = [];
1348 this.datasetElementType = new.target.datasetElementType;
1349 this.dataElementType = new.target.dataElementType;
1350 this.initialize();
1351 }
1352 initialize() {
1353 const meta = this._cachedMeta;
1354 this.configure();
1355 this.linkScales();
1356 meta._stacked = isStacked(meta.vScale, meta);
1357 this.addElements();
1358 if (this.options.fill && !this.chart.isPluginEnabled('filler')) {
1359 console.warn("Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options");
1360 }
1361 }
1362 updateIndex(datasetIndex) {
1363 if (this.index !== datasetIndex) {
1364 clearStacks(this._cachedMeta);
1365 }
1366 this.index = datasetIndex;
1367 }
1368 linkScales() {
1369 const chart = this.chart;
1370 const meta = this._cachedMeta;
1371 const dataset = this.getDataset();
1372 const chooseId = (axis, x, y, r)=>axis === 'x' ? x : axis === 'r' ? r : y;
1373 const xid = meta.xAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.xAxisID, getFirstScaleId(chart, 'x'));
1374 const yid = meta.yAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.yAxisID, getFirstScaleId(chart, 'y'));
1375 const rid = meta.rAxisID = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.rAxisID, getFirstScaleId(chart, 'r'));
1376 const indexAxis = meta.indexAxis;
1377 const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);
1378 const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);
1379 meta.xScale = this.getScaleForId(xid);
1380 meta.yScale = this.getScaleForId(yid);
1381 meta.rScale = this.getScaleForId(rid);
1382 meta.iScale = this.getScaleForId(iid);
1383 meta.vScale = this.getScaleForId(vid);
1384 }
1385 getDataset() {
1386 return this.chart.data.datasets[this.index];
1387 }
1388 getMeta() {
1389 return this.chart.getDatasetMeta(this.index);
1390 }
1391 getScaleForId(scaleID) {
1392 return this.chart.scales[scaleID];
1393 }
1394 _getOtherScale(scale) {
1395 const meta = this._cachedMeta;
1396 return scale === meta.iScale ? meta.vScale : meta.iScale;
1397 }
1398 reset() {
1399 this._update('reset');
1400 }
1401 _destroy() {
1402 const meta = this._cachedMeta;
1403 if (this._data) {
1404 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.u)(this._data, this);
1405 }
1406 if (meta._stacked) {
1407 clearStacks(meta);
1408 }
1409 }
1410 _dataCheck() {
1411 const dataset = this.getDataset();
1412 const data = dataset.data || (dataset.data = []);
1413 const _data = this._data;
1414 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data)) {
1415 const meta = this._cachedMeta;
1416 this._data = convertObjectDataToArray(data, meta);
1417 } else if (_data !== data) {
1418 if (_data) {
1419 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.u)(_data, this);
1420 const meta = this._cachedMeta;
1421 clearStacks(meta);
1422 meta._parsed = [];
1423 }
1424 if (data && Object.isExtensible(data)) {
1425 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.l)(data, this);
1426 }
1427 this._syncList = [];
1428 this._data = data;
1429 }
1430 }
1431 addElements() {
1432 const meta = this._cachedMeta;
1433 this._dataCheck();
1434 if (this.datasetElementType) {
1435 meta.dataset = new this.datasetElementType();
1436 }
1437 }
1438 buildOrUpdateElements(resetNewElements) {
1439 const meta = this._cachedMeta;
1440 const dataset = this.getDataset();
1441 let stackChanged = false;
1442 this._dataCheck();
1443 const oldStacked = meta._stacked;
1444 meta._stacked = isStacked(meta.vScale, meta);
1445 if (meta.stack !== dataset.stack) {
1446 stackChanged = true;
1447 clearStacks(meta);
1448 meta.stack = dataset.stack;
1449 }
1450 this._resyncElements(resetNewElements);
1451 if (stackChanged || oldStacked !== meta._stacked) {
1452 updateStacks(this, meta._parsed);
1453 meta._stacked = isStacked(meta.vScale, meta);
1454 }
1455 }
1456 configure() {
1457 const config = this.chart.config;
1458 const scopeKeys = config.datasetScopeKeys(this._type);
1459 const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);
1460 this.options = config.createResolver(scopes, this.getContext());
1461 this._parsing = this.options.parsing;
1462 this._cachedDataOpts = {};
1463 }
1464 parse(start, count) {
1465 const { _cachedMeta: meta , _data: data } = this;
1466 const { iScale , _stacked } = meta;
1467 const iAxis = iScale.axis;
1468 let sorted = start === 0 && count === data.length ? true : meta._sorted;
1469 let prev = start > 0 && meta._parsed[start - 1];
1470 let i, cur, parsed;
1471 if (this._parsing === false) {
1472 meta._parsed = data;
1473 meta._sorted = true;
1474 parsed = data;
1475 } else {
1476 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(data[start])) {
1477 parsed = this.parseArrayData(meta, data, start, count);
1478 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) {
1479 parsed = this.parseObjectData(meta, data, start, count);
1480 } else {
1481 parsed = this.parsePrimitiveData(meta, data, start, count);
1482 }
1483 const isNotInOrderComparedToPrev = ()=>cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis];
1484 for(i = 0; i < count; ++i){
1485 meta._parsed[i + start] = cur = parsed[i];
1486 if (sorted) {
1487 if (isNotInOrderComparedToPrev()) {
1488 sorted = false;
1489 }
1490 prev = cur;
1491 }
1492 }
1493 meta._sorted = sorted;
1494 }
1495 if (_stacked) {
1496 updateStacks(this, parsed);
1497 }
1498 }
1499 parsePrimitiveData(meta, data, start, count) {
1500 const { iScale , vScale } = meta;
1501 const iAxis = iScale.axis;
1502 const vAxis = vScale.axis;
1503 const labels = iScale.getLabels();
1504 const singleScale = iScale === vScale;
1505 const parsed = new Array(count);
1506 let i, ilen, index;
1507 for(i = 0, ilen = count; i < ilen; ++i){
1508 index = i + start;
1509 parsed[i] = {
1510 [iAxis]: singleScale || iScale.parse(labels[index], index),
1511 [vAxis]: vScale.parse(data[index], index)
1512 };
1513 }
1514 return parsed;
1515 }
1516 parseArrayData(meta, data, start, count) {
1517 const { xScale , yScale } = meta;
1518 const parsed = new Array(count);
1519 let i, ilen, index, item;
1520 for(i = 0, ilen = count; i < ilen; ++i){
1521 index = i + start;
1522 item = data[index];
1523 parsed[i] = {
1524 x: xScale.parse(item[0], index),
1525 y: yScale.parse(item[1], index)
1526 };
1527 }
1528 return parsed;
1529 }
1530 parseObjectData(meta, data, start, count) {
1531 const { xScale , yScale } = meta;
1532 const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing;
1533 const parsed = new Array(count);
1534 let i, ilen, index, item;
1535 for(i = 0, ilen = count; i < ilen; ++i){
1536 index = i + start;
1537 item = data[index];
1538 parsed[i] = {
1539 x: xScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, xAxisKey), index),
1540 y: yScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, yAxisKey), index)
1541 };
1542 }
1543 return parsed;
1544 }
1545 getParsed(index) {
1546 return this._cachedMeta._parsed[index];
1547 }
1548 getDataElement(index) {
1549 return this._cachedMeta.data[index];
1550 }
1551 applyStack(scale, parsed, mode) {
1552 const chart = this.chart;
1553 const meta = this._cachedMeta;
1554 const value = parsed[scale.axis];
1555 const stack = {
1556 keys: getSortedDatasetIndices(chart, true),
1557 values: parsed._stacks[scale.axis]._visualValues
1558 };
1559 return applyStack(stack, value, meta.index, {
1560 mode
1561 });
1562 }
1563 updateRangeFromParsed(range, scale, parsed, stack) {
1564 const parsedValue = parsed[scale.axis];
1565 let value = parsedValue === null ? NaN : parsedValue;
1566 const values = stack && parsed._stacks[scale.axis];
1567 if (stack && values) {
1568 stack.values = values;
1569 value = applyStack(stack, parsedValue, this._cachedMeta.index);
1570 }
1571 range.min = Math.min(range.min, value);
1572 range.max = Math.max(range.max, value);
1573 }
1574 getMinMax(scale, canStack) {
1575 const meta = this._cachedMeta;
1576 const _parsed = meta._parsed;
1577 const sorted = meta._sorted && scale === meta.iScale;
1578 const ilen = _parsed.length;
1579 const otherScale = this._getOtherScale(scale);
1580 const stack = createStack(canStack, meta, this.chart);
1581 const range = {
1582 min: Number.POSITIVE_INFINITY,
1583 max: Number.NEGATIVE_INFINITY
1584 };
1585 const { min: otherMin , max: otherMax } = getUserBounds(otherScale);
1586 let i, parsed;
1587 function _skip() {
1588 parsed = _parsed[i];
1589 const otherValue = parsed[otherScale.axis];
1590 return !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;
1591 }
1592 for(i = 0; i < ilen; ++i){
1593 if (_skip()) {
1594 continue;
1595 }
1596 this.updateRangeFromParsed(range, scale, parsed, stack);
1597 if (sorted) {
1598 break;
1599 }
1600 }
1601 if (sorted) {
1602 for(i = ilen - 1; i >= 0; --i){
1603 if (_skip()) {
1604 continue;
1605 }
1606 this.updateRangeFromParsed(range, scale, parsed, stack);
1607 break;
1608 }
1609 }
1610 return range;
1611 }
1612 getAllParsedValues(scale) {
1613 const parsed = this._cachedMeta._parsed;
1614 const values = [];
1615 let i, ilen, value;
1616 for(i = 0, ilen = parsed.length; i < ilen; ++i){
1617 value = parsed[i][scale.axis];
1618 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) {
1619 values.push(value);
1620 }
1621 }
1622 return values;
1623 }
1624 getMaxOverflow() {
1625 return false;
1626 }
1627 getLabelAndValue(index) {
1628 const meta = this._cachedMeta;
1629 const iScale = meta.iScale;
1630 const vScale = meta.vScale;
1631 const parsed = this.getParsed(index);
1632 return {
1633 label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',
1634 value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''
1635 };
1636 }
1637 _update(mode) {
1638 const meta = this._cachedMeta;
1639 this.update(mode || 'default');
1640 meta._clip = toClip((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));
1641 }
1642 update(mode) {}
1643 draw() {
1644 const ctx = this._ctx;
1645 const chart = this.chart;
1646 const meta = this._cachedMeta;
1647 const elements = meta.data || [];
1648 const area = chart.chartArea;
1649 const active = [];
1650 const start = this._drawStart || 0;
1651 const count = this._drawCount || elements.length - start;
1652 const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop;
1653 let i;
1654 if (meta.dataset) {
1655 meta.dataset.draw(ctx, area, start, count);
1656 }
1657 for(i = start; i < start + count; ++i){
1658 const element = elements[i];
1659 if (element.hidden) {
1660 continue;
1661 }
1662 if (element.active && drawActiveElementsOnTop) {
1663 active.push(element);
1664 } else {
1665 element.draw(ctx, area);
1666 }
1667 }
1668 for(i = 0; i < active.length; ++i){
1669 active[i].draw(ctx, area);
1670 }
1671 }
1672 getStyle(index, active) {
1673 const mode = active ? 'active' : 'default';
1674 return index === undefined && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode);
1675 }
1676 getContext(index, active, mode) {
1677 const dataset = this.getDataset();
1678 let context;
1679 if (index >= 0 && index < this._cachedMeta.data.length) {
1680 const element = this._cachedMeta.data[index];
1681 context = element.$context || (element.$context = createDataContext(this.getContext(), index, element));
1682 context.parsed = this.getParsed(index);
1683 context.raw = dataset.data[index];
1684 context.index = context.dataIndex = index;
1685 } else {
1686 context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index));
1687 context.dataset = dataset;
1688 context.index = context.datasetIndex = this.index;
1689 }
1690 context.active = !!active;
1691 context.mode = mode;
1692 return context;
1693 }
1694 resolveDatasetElementOptions(mode) {
1695 return this._resolveElementOptions(this.datasetElementType.id, mode);
1696 }
1697 resolveDataElementOptions(index, mode) {
1698 return this._resolveElementOptions(this.dataElementType.id, mode, index);
1699 }
1700 _resolveElementOptions(elementType, mode = 'default', index) {
1701 const active = mode === 'active';
1702 const cache = this._cachedDataOpts;
1703 const cacheKey = elementType + '-' + mode;
1704 const cached = cache[cacheKey];
1705 const sharing = this.enableOptionSharing && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(index);
1706 if (cached) {
1707 return cloneIfNotShared(cached, sharing);
1708 }
1709 const config = this.chart.config;
1710 const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);
1711 const prefixes = active ? [
1712 `${elementType}Hover`,
1713 'hover',
1714 elementType,
1715 ''
1716 ] : [
1717 elementType,
1718 ''
1719 ];
1720 const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
1721 const names = Object.keys(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.elements[elementType]);
1722 const context = ()=>this.getContext(index, active, mode);
1723 const values = config.resolveNamedOptions(scopes, names, context, prefixes);
1724 if (values.$shared) {
1725 values.$shared = sharing;
1726 cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));
1727 }
1728 return values;
1729 }
1730 _resolveAnimations(index, transition, active) {
1731 const chart = this.chart;
1732 const cache = this._cachedDataOpts;
1733 const cacheKey = `animation-${transition}`;
1734 const cached = cache[cacheKey];
1735 if (cached) {
1736 return cached;
1737 }
1738 let options;
1739 if (chart.options.animation !== false) {
1740 const config = this.chart.config;
1741 const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);
1742 const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
1743 options = config.createResolver(scopes, this.getContext(index, active, transition));
1744 }
1745 const animations = new Animations(chart, options && options.animations);
1746 if (options && options._cacheable) {
1747 cache[cacheKey] = Object.freeze(animations);
1748 }
1749 return animations;
1750 }
1751 getSharedOptions(options) {
1752 if (!options.$shared) {
1753 return;
1754 }
1755 return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));
1756 }
1757 includeOptions(mode, sharedOptions) {
1758 return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;
1759 }
1760 _getSharedOptions(start, mode) {
1761 const firstOpts = this.resolveDataElementOptions(start, mode);
1762 const previouslySharedOptions = this._sharedOptions;
1763 const sharedOptions = this.getSharedOptions(firstOpts);
1764 const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions;
1765 this.updateSharedOptions(sharedOptions, mode, firstOpts);
1766 return {
1767 sharedOptions,
1768 includeOptions
1769 };
1770 }
1771 updateElement(element, index, properties, mode) {
1772 if (isDirectUpdateMode(mode)) {
1773 Object.assign(element, properties);
1774 } else {
1775 this._resolveAnimations(index, mode).update(element, properties);
1776 }
1777 }
1778 updateSharedOptions(sharedOptions, mode, newOptions) {
1779 if (sharedOptions && !isDirectUpdateMode(mode)) {
1780 this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions);
1781 }
1782 }
1783 _setStyle(element, index, mode, active) {
1784 element.active = active;
1785 const options = this.getStyle(index, active);
1786 this._resolveAnimations(index, mode, active).update(element, {
1787 options: !active && this.getSharedOptions(options) || options
1788 });
1789 }
1790 removeHoverStyle(element, datasetIndex, index) {
1791 this._setStyle(element, index, 'active', false);
1792 }
1793 setHoverStyle(element, datasetIndex, index) {
1794 this._setStyle(element, index, 'active', true);
1795 }
1796 _removeDatasetHoverStyle() {
1797 const element = this._cachedMeta.dataset;
1798 if (element) {
1799 this._setStyle(element, undefined, 'active', false);
1800 }
1801 }
1802 _setDatasetHoverStyle() {
1803 const element = this._cachedMeta.dataset;
1804 if (element) {
1805 this._setStyle(element, undefined, 'active', true);
1806 }
1807 }
1808 _resyncElements(resetNewElements) {
1809 const data = this._data;
1810 const elements = this._cachedMeta.data;
1811 for (const [method, arg1, arg2] of this._syncList){
1812 this[method](arg1, arg2);
1813 }
1814 this._syncList = [];
1815 const numMeta = elements.length;
1816 const numData = data.length;
1817 const count = Math.min(numData, numMeta);
1818 if (count) {
1819 this.parse(0, count);
1820 }
1821 if (numData > numMeta) {
1822 this._insertElements(numMeta, numData - numMeta, resetNewElements);
1823 } else if (numData < numMeta) {
1824 this._removeElements(numData, numMeta - numData);
1825 }
1826 }
1827 _insertElements(start, count, resetNewElements = true) {
1828 const meta = this._cachedMeta;
1829 const data = meta.data;
1830 const end = start + count;
1831 let i;
1832 const move = (arr)=>{
1833 arr.length += count;
1834 for(i = arr.length - 1; i >= end; i--){
1835 arr[i] = arr[i - count];
1836 }
1837 };
1838 move(data);
1839 for(i = start; i < end; ++i){
1840 data[i] = new this.dataElementType();
1841 }
1842 if (this._parsing) {
1843 move(meta._parsed);
1844 }
1845 this.parse(start, count);
1846 if (resetNewElements) {
1847 this.updateElements(data, start, count, 'reset');
1848 }
1849 }
1850 updateElements(element, start, count, mode) {}
1851 _removeElements(start, count) {
1852 const meta = this._cachedMeta;
1853 if (this._parsing) {
1854 const removed = meta._parsed.splice(start, count);
1855 if (meta._stacked) {
1856 clearStacks(meta, removed);
1857 }
1858 }
1859 meta.data.splice(start, count);
1860 }
1861 _sync(args) {
1862 if (this._parsing) {
1863 this._syncList.push(args);
1864 } else {
1865 const [method, arg1, arg2] = args;
1866 this[method](arg1, arg2);
1867 }
1868 this.chart._dataChanges.push([
1869 this.index,
1870 ...args
1871 ]);
1872 }
1873 _onDataPush() {
1874 const count = arguments.length;
1875 this._sync([
1876 '_insertElements',
1877 this.getDataset().data.length - count,
1878 count
1879 ]);
1880 }
1881 _onDataPop() {
1882 this._sync([
1883 '_removeElements',
1884 this._cachedMeta.data.length - 1,
1885 1
1886 ]);
1887 }
1888 _onDataShift() {
1889 this._sync([
1890 '_removeElements',
1891 0,
1892 1
1893 ]);
1894 }
1895 _onDataSplice(start, count) {
1896 if (count) {
1897 this._sync([
1898 '_removeElements',
1899 start,
1900 count
1901 ]);
1902 }
1903 const newCount = arguments.length - 2;
1904 if (newCount) {
1905 this._sync([
1906 '_insertElements',
1907 start,
1908 newCount
1909 ]);
1910 }
1911 }
1912 _onDataUnshift() {
1913 this._sync([
1914 '_insertElements',
1915 0,
1916 arguments.length
1917 ]);
1918 }
1919 }
1920
1921 function getAllScaleValues(scale, type) {
1922 if (!scale._cache.$bar) {
1923 const visibleMetas = scale.getMatchingVisibleMetas(type);
1924 let values = [];
1925 for(let i = 0, ilen = visibleMetas.length; i < ilen; i++){
1926 values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale));
1927 }
1928 scale._cache.$bar = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort((a, b)=>a - b));
1929 }
1930 return scale._cache.$bar;
1931 }
1932 function computeMinSampleSize(meta) {
1933 const scale = meta.iScale;
1934 const values = getAllScaleValues(scale, meta.type);
1935 let min = scale._length;
1936 let i, ilen, curr, prev;
1937 const updateMinAndPrev = ()=>{
1938 if (curr === 32767 || curr === -32768) {
1939 return;
1940 }
1941 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(prev)) {
1942 min = Math.min(min, Math.abs(curr - prev) || min);
1943 }
1944 prev = curr;
1945 };
1946 for(i = 0, ilen = values.length; i < ilen; ++i){
1947 curr = scale.getPixelForValue(values[i]);
1948 updateMinAndPrev();
1949 }
1950 prev = undefined;
1951 for(i = 0, ilen = scale.ticks.length; i < ilen; ++i){
1952 curr = scale.getPixelForTick(i);
1953 updateMinAndPrev();
1954 }
1955 return min;
1956 }
1957 function computeFitCategoryTraits(index, ruler, options, stackCount) {
1958 const thickness = options.barThickness;
1959 let size, ratio;
1960 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(thickness)) {
1961 size = ruler.min * options.categoryPercentage;
1962 ratio = options.barPercentage;
1963 } else {
1964 size = thickness * stackCount;
1965 ratio = 1;
1966 }
1967 return {
1968 chunk: size / stackCount,
1969 ratio,
1970 start: ruler.pixels[index] - size / 2
1971 };
1972 }
1973 function computeFlexCategoryTraits(index, ruler, options, stackCount) {
1974 const pixels = ruler.pixels;
1975 const curr = pixels[index];
1976 let prev = index > 0 ? pixels[index - 1] : null;
1977 let next = index < pixels.length - 1 ? pixels[index + 1] : null;
1978 const percent = options.categoryPercentage;
1979 if (prev === null) {
1980 prev = curr - (next === null ? ruler.end - ruler.start : next - curr);
1981 }
1982 if (next === null) {
1983 next = curr + curr - prev;
1984 }
1985 const start = curr - (curr - Math.min(prev, next)) / 2 * percent;
1986 const size = Math.abs(next - prev) / 2 * percent;
1987 return {
1988 chunk: size / stackCount,
1989 ratio: options.barPercentage,
1990 start
1991 };
1992 }
1993 function parseFloatBar(entry, item, vScale, i) {
1994 const startValue = vScale.parse(entry[0], i);
1995 const endValue = vScale.parse(entry[1], i);
1996 const min = Math.min(startValue, endValue);
1997 const max = Math.max(startValue, endValue);
1998 let barStart = min;
1999 let barEnd = max;
2000 if (Math.abs(min) > Math.abs(max)) {
2001 barStart = max;
2002 barEnd = min;
2003 }
2004 item[vScale.axis] = barEnd;
2005 item._custom = {
2006 barStart,
2007 barEnd,
2008 start: startValue,
2009 end: endValue,
2010 min,
2011 max
2012 };
2013 }
2014 function parseValue(entry, item, vScale, i) {
2015 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(entry)) {
2016 parseFloatBar(entry, item, vScale, i);
2017 } else {
2018 item[vScale.axis] = vScale.parse(entry, i);
2019 }
2020 return item;
2021 }
2022 function parseArrayOrPrimitive(meta, data, start, count) {
2023 const iScale = meta.iScale;
2024 const vScale = meta.vScale;
2025 const labels = iScale.getLabels();
2026 const singleScale = iScale === vScale;
2027 const parsed = [];
2028 let i, ilen, item, entry;
2029 for(i = start, ilen = start + count; i < ilen; ++i){
2030 entry = data[i];
2031 item = {};
2032 item[iScale.axis] = singleScale || iScale.parse(labels[i], i);
2033 parsed.push(parseValue(entry, item, vScale, i));
2034 }
2035 return parsed;
2036 }
2037 function isFloatBar(custom) {
2038 return custom && custom.barStart !== undefined && custom.barEnd !== undefined;
2039 }
2040 function barSign(size, vScale, actualBase) {
2041 if (size !== 0) {
2042 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(size);
2043 }
2044 return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
2045 }
2046 function borderProps(properties) {
2047 let reverse, start, end, top, bottom;
2048 if (properties.horizontal) {
2049 reverse = properties.base > properties.x;
2050 start = 'left';
2051 end = 'right';
2052 } else {
2053 reverse = properties.base < properties.y;
2054 start = 'bottom';
2055 end = 'top';
2056 }
2057 if (reverse) {
2058 top = 'end';
2059 bottom = 'start';
2060 } else {
2061 top = 'start';
2062 bottom = 'end';
2063 }
2064 return {
2065 start,
2066 end,
2067 reverse,
2068 top,
2069 bottom
2070 };
2071 }
2072 function setBorderSkipped(properties, options, stack, index) {
2073 let edge = options.borderSkipped;
2074 const res = {};
2075 if (!edge) {
2076 properties.borderSkipped = res;
2077 return;
2078 }
2079 if (edge === true) {
2080 properties.borderSkipped = {
2081 top: true,
2082 right: true,
2083 bottom: true,
2084 left: true
2085 };
2086 return;
2087 }
2088 const { start , end , reverse , top , bottom } = borderProps(properties);
2089 if (edge === 'middle' && stack) {
2090 properties.enableBorderRadius = true;
2091 if ((stack._top || 0) === index) {
2092 edge = top;
2093 } else if ((stack._bottom || 0) === index) {
2094 edge = bottom;
2095 } else {
2096 res[parseEdge(bottom, start, end, reverse)] = true;
2097 edge = top;
2098 }
2099 }
2100 res[parseEdge(edge, start, end, reverse)] = true;
2101 properties.borderSkipped = res;
2102 }
2103 function parseEdge(edge, a, b, reverse) {
2104 if (reverse) {
2105 edge = swap(edge, a, b);
2106 edge = startEnd(edge, b, a);
2107 } else {
2108 edge = startEnd(edge, a, b);
2109 }
2110 return edge;
2111 }
2112 function swap(orig, v1, v2) {
2113 return orig === v1 ? v2 : orig === v2 ? v1 : orig;
2114 }
2115 function startEnd(v, start, end) {
2116 return v === 'start' ? start : v === 'end' ? end : v;
2117 }
2118 function setInflateAmount(properties, { inflateAmount }, ratio) {
2119 properties.inflateAmount = inflateAmount === 'auto' ? ratio === 1 ? 0.33 : 0 : inflateAmount;
2120 }
2121 class BarController extends DatasetController {
2122 static id = 'bar';
2123 static defaults = {
2124 datasetElementType: false,
2125 dataElementType: 'bar',
2126 categoryPercentage: 0.8,
2127 barPercentage: 0.9,
2128 grouped: true,
2129 animations: {
2130 numbers: {
2131 type: 'number',
2132 properties: [
2133 'x',
2134 'y',
2135 'base',
2136 'width',
2137 'height'
2138 ]
2139 }
2140 }
2141 };
2142 static overrides = {
2143 scales: {
2144 _index_: {
2145 type: 'category',
2146 offset: true,
2147 grid: {
2148 offset: true
2149 }
2150 },
2151 _value_: {
2152 type: 'linear',
2153 beginAtZero: true
2154 }
2155 }
2156 };
2157 parsePrimitiveData(meta, data, start, count) {
2158 return parseArrayOrPrimitive(meta, data, start, count);
2159 }
2160 parseArrayData(meta, data, start, count) {
2161 return parseArrayOrPrimitive(meta, data, start, count);
2162 }
2163 parseObjectData(meta, data, start, count) {
2164 const { iScale , vScale } = meta;
2165 const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing;
2166 const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey;
2167 const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey;
2168 const parsed = [];
2169 let i, ilen, item, obj;
2170 for(i = start, ilen = start + count; i < ilen; ++i){
2171 obj = data[i];
2172 item = {};
2173 item[iScale.axis] = iScale.parse((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, iAxisKey), i);
2174 parsed.push(parseValue((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, vAxisKey), item, vScale, i));
2175 }
2176 return parsed;
2177 }
2178 updateRangeFromParsed(range, scale, parsed, stack) {
2179 super.updateRangeFromParsed(range, scale, parsed, stack);
2180 const custom = parsed._custom;
2181 if (custom && scale === this._cachedMeta.vScale) {
2182 range.min = Math.min(range.min, custom.min);
2183 range.max = Math.max(range.max, custom.max);
2184 }
2185 }
2186 getMaxOverflow() {
2187 return 0;
2188 }
2189 getLabelAndValue(index) {
2190 const meta = this._cachedMeta;
2191 const { iScale , vScale } = meta;
2192 const parsed = this.getParsed(index);
2193 const custom = parsed._custom;
2194 const value = isFloatBar(custom) ? '[' + custom.start + ', ' + custom.end + ']' : '' + vScale.getLabelForValue(parsed[vScale.axis]);
2195 return {
2196 label: '' + iScale.getLabelForValue(parsed[iScale.axis]),
2197 value
2198 };
2199 }
2200 initialize() {
2201 this.enableOptionSharing = true;
2202 super.initialize();
2203 const meta = this._cachedMeta;
2204 meta.stack = this.getDataset().stack;
2205 }
2206 update(mode) {
2207 const meta = this._cachedMeta;
2208 this.updateElements(meta.data, 0, meta.data.length, mode);
2209 }
2210 updateElements(bars, start, count, mode) {
2211 const reset = mode === 'reset';
2212 const { index , _cachedMeta: { vScale } } = this;
2213 const base = vScale.getBasePixel();
2214 const horizontal = vScale.isHorizontal();
2215 const ruler = this._getRuler();
2216 const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);
2217 for(let i = start; i < start + count; i++){
2218 const parsed = this.getParsed(i);
2219 const vpixels = reset || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vScale.axis]) ? {
2220 base,
2221 head: base
2222 } : this._calculateBarValuePixels(i);
2223 const ipixels = this._calculateBarIndexPixels(i, ruler);
2224 const stack = (parsed._stacks || {})[vScale.axis];
2225 const properties = {
2226 horizontal,
2227 base: vpixels.base,
2228 enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom,
2229 x: horizontal ? vpixels.head : ipixels.center,
2230 y: horizontal ? ipixels.center : vpixels.head,
2231 height: horizontal ? ipixels.size : Math.abs(vpixels.size),
2232 width: horizontal ? Math.abs(vpixels.size) : ipixels.size
2233 };
2234 if (includeOptions) {
2235 properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
2236 }
2237 const options = properties.options || bars[i].options;
2238 setBorderSkipped(properties, options, stack, index);
2239 setInflateAmount(properties, options, ruler.ratio);
2240 this.updateElement(bars[i], i, properties, mode);
2241 }
2242 }
2243 _getStacks(last, dataIndex) {
2244 const { iScale } = this._cachedMeta;
2245 const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta)=>meta.controller.options.grouped);
2246 const stacked = iScale.options.stacked;
2247 const stacks = [];
2248 const currentParsed = this._cachedMeta.controller.getParsed(dataIndex);
2249 const iScaleValue = currentParsed && currentParsed[iScale.axis];
2250 const skipNull = (meta)=>{
2251 const parsed = meta._parsed.find((item)=>item[iScale.axis] === iScaleValue);
2252 const val = parsed && parsed[meta.vScale.axis];
2253 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(val) || isNaN(val)) {
2254 return true;
2255 }
2256 };
2257 for (const meta of metasets){
2258 if (dataIndex !== undefined && skipNull(meta)) {
2259 continue;
2260 }
2261 if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === undefined && meta.stack === undefined) {
2262 stacks.push(meta.stack);
2263 }
2264 if (meta.index === last) {
2265 break;
2266 }
2267 }
2268 if (!stacks.length) {
2269 stacks.push(undefined);
2270 }
2271 return stacks;
2272 }
2273 _getStackCount(index) {
2274 return this._getStacks(undefined, index).length;
2275 }
2276 _getAxisCount() {
2277 return this._getAxis().length;
2278 }
2279 getFirstScaleIdForIndexAxis() {
2280 const scales = this.chart.scales;
2281 const indexScaleId = this.chart.options.indexAxis;
2282 return Object.keys(scales).filter((key)=>scales[key].axis === indexScaleId).shift();
2283 }
2284 _getAxis() {
2285 const axis = {};
2286 const firstScaleAxisId = this.getFirstScaleIdForIndexAxis();
2287 for (const dataset of this.chart.data.datasets){
2288 axis[(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.options.indexAxis === 'x' ? dataset.xAxisID : dataset.yAxisID, firstScaleAxisId)] = true;
2289 }
2290 return Object.keys(axis);
2291 }
2292 _getStackIndex(datasetIndex, name, dataIndex) {
2293 const stacks = this._getStacks(datasetIndex, dataIndex);
2294 const index = name !== undefined ? stacks.indexOf(name) : -1;
2295 return index === -1 ? stacks.length - 1 : index;
2296 }
2297 _getRuler() {
2298 const opts = this.options;
2299 const meta = this._cachedMeta;
2300 const iScale = meta.iScale;
2301 const pixels = [];
2302 let i, ilen;
2303 for(i = 0, ilen = meta.data.length; i < ilen; ++i){
2304 pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));
2305 }
2306 const barThickness = opts.barThickness;
2307 const min = barThickness || computeMinSampleSize(meta);
2308 return {
2309 min,
2310 pixels,
2311 start: iScale._startPixel,
2312 end: iScale._endPixel,
2313 stackCount: this._getStackCount(),
2314 scale: iScale,
2315 grouped: opts.grouped,
2316 ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage
2317 };
2318 }
2319 _calculateBarValuePixels(index) {
2320 const { _cachedMeta: { vScale , _stacked , index: datasetIndex } , options: { base: baseValue , minBarLength } } = this;
2321 const actualBase = baseValue || 0;
2322 const parsed = this.getParsed(index);
2323 const custom = parsed._custom;
2324 const floating = isFloatBar(custom);
2325 let value = parsed[vScale.axis];
2326 let start = 0;
2327 let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;
2328 let head, size;
2329 if (length !== value) {
2330 start = length - value;
2331 length = value;
2332 }
2333 if (floating) {
2334 value = custom.barStart;
2335 length = custom.barEnd - custom.barStart;
2336 if (value !== 0 && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) !== (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(custom.barEnd)) {
2337 start = 0;
2338 }
2339 start += value;
2340 }
2341 const startValue = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(baseValue) && !floating ? baseValue : start;
2342 let base = vScale.getPixelForValue(startValue);
2343 if (this.chart.getDataVisibility(index)) {
2344 head = vScale.getPixelForValue(start + length);
2345 } else {
2346 head = base;
2347 }
2348 size = head - base;
2349 if (Math.abs(size) < minBarLength) {
2350 size = barSign(size, vScale, actualBase) * minBarLength;
2351 if (value === actualBase) {
2352 base -= size / 2;
2353 }
2354 const startPixel = vScale.getPixelForDecimal(0);
2355 const endPixel = vScale.getPixelForDecimal(1);
2356 const min = Math.min(startPixel, endPixel);
2357 const max = Math.max(startPixel, endPixel);
2358 base = Math.max(Math.min(base, max), min);
2359 head = base + size;
2360 if (_stacked && !floating) {
2361 parsed._stacks[vScale.axis]._visualValues[datasetIndex] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base);
2362 }
2363 }
2364 if (base === vScale.getPixelForValue(actualBase)) {
2365 const halfGrid = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(size) * vScale.getLineWidthForValue(actualBase) / 2;
2366 base += halfGrid;
2367 size -= halfGrid;
2368 }
2369 return {
2370 size,
2371 base,
2372 head,
2373 center: head + size / 2
2374 };
2375 }
2376 _calculateBarIndexPixels(index, ruler) {
2377 const scale = ruler.scale;
2378 const options = this.options;
2379 const skipNull = options.skipNull;
2380 const maxBarThickness = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.maxBarThickness, Infinity);
2381 let center, size;
2382 const axisCount = this._getAxisCount();
2383 if (ruler.grouped) {
2384 const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
2385 const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options, stackCount * axisCount) : computeFitCategoryTraits(index, ruler, options, stackCount * axisCount);
2386 const axisID = this.chart.options.indexAxis === 'x' ? this.getDataset().xAxisID : this.getDataset().yAxisID;
2387 const axisNumber = this._getAxis().indexOf((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(axisID, this.getFirstScaleIdForIndexAxis()));
2388 const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined) + axisNumber;
2389 center = range.start + range.chunk * stackIndex + range.chunk / 2;
2390 size = Math.min(maxBarThickness, range.chunk * range.ratio);
2391 } else {
2392 center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);
2393 size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
2394 }
2395 return {
2396 base: center - size / 2,
2397 head: center + size / 2,
2398 center,
2399 size
2400 };
2401 }
2402 draw() {
2403 const meta = this._cachedMeta;
2404 const vScale = meta.vScale;
2405 const rects = meta.data;
2406 const ilen = rects.length;
2407 let i = 0;
2408 for(; i < ilen; ++i){
2409 if (this.getParsed(i)[vScale.axis] !== null && !rects[i].hidden) {
2410 rects[i].draw(this._ctx);
2411 }
2412 }
2413 }
2414 }
2415
2416 class BubbleController extends DatasetController {
2417 static id = 'bubble';
2418 static defaults = {
2419 datasetElementType: false,
2420 dataElementType: 'point',
2421 animations: {
2422 numbers: {
2423 type: 'number',
2424 properties: [
2425 'x',
2426 'y',
2427 'borderWidth',
2428 'radius'
2429 ]
2430 }
2431 }
2432 };
2433 static overrides = {
2434 scales: {
2435 x: {
2436 type: 'linear'
2437 },
2438 y: {
2439 type: 'linear'
2440 }
2441 }
2442 };
2443 initialize() {
2444 this.enableOptionSharing = true;
2445 super.initialize();
2446 }
2447 parsePrimitiveData(meta, data, start, count) {
2448 const parsed = super.parsePrimitiveData(meta, data, start, count);
2449 for(let i = 0; i < parsed.length; i++){
2450 parsed[i]._custom = this.resolveDataElementOptions(i + start).radius;
2451 }
2452 return parsed;
2453 }
2454 parseArrayData(meta, data, start, count) {
2455 const parsed = super.parseArrayData(meta, data, start, count);
2456 for(let i = 0; i < parsed.length; i++){
2457 const item = data[start + i];
2458 parsed[i]._custom = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(item[2], this.resolveDataElementOptions(i + start).radius);
2459 }
2460 return parsed;
2461 }
2462 parseObjectData(meta, data, start, count) {
2463 const parsed = super.parseObjectData(meta, data, start, count);
2464 for(let i = 0; i < parsed.length; i++){
2465 const item = data[start + i];
2466 parsed[i]._custom = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(item && item.r && +item.r, this.resolveDataElementOptions(i + start).radius);
2467 }
2468 return parsed;
2469 }
2470 getMaxOverflow() {
2471 const data = this._cachedMeta.data;
2472 let max = 0;
2473 for(let i = data.length - 1; i >= 0; --i){
2474 max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);
2475 }
2476 return max > 0 && max;
2477 }
2478 getLabelAndValue(index) {
2479 const meta = this._cachedMeta;
2480 const labels = this.chart.data.labels || [];
2481 const { xScale , yScale } = meta;
2482 const parsed = this.getParsed(index);
2483 const x = xScale.getLabelForValue(parsed.x);
2484 const y = yScale.getLabelForValue(parsed.y);
2485 const r = parsed._custom;
2486 return {
2487 label: labels[index] || '',
2488 value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')'
2489 };
2490 }
2491 update(mode) {
2492 const points = this._cachedMeta.data;
2493 this.updateElements(points, 0, points.length, mode);
2494 }
2495 updateElements(points, start, count, mode) {
2496 const reset = mode === 'reset';
2497 const { iScale , vScale } = this._cachedMeta;
2498 const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);
2499 const iAxis = iScale.axis;
2500 const vAxis = vScale.axis;
2501 for(let i = start; i < start + count; i++){
2502 const point = points[i];
2503 const parsed = !reset && this.getParsed(i);
2504 const properties = {};
2505 const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]);
2506 const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]);
2507 properties.skip = isNaN(iPixel) || isNaN(vPixel);
2508 if (includeOptions) {
2509 properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);
2510 if (reset) {
2511 properties.options.radius = 0;
2512 }
2513 }
2514 this.updateElement(point, i, properties, mode);
2515 }
2516 }
2517 resolveDataElementOptions(index, mode) {
2518 const parsed = this.getParsed(index);
2519 let values = super.resolveDataElementOptions(index, mode);
2520 if (values.$shared) {
2521 values = Object.assign({}, values, {
2522 $shared: false
2523 });
2524 }
2525 const radius = values.radius;
2526 if (mode !== 'active') {
2527 values.radius = 0;
2528 }
2529 values.radius += (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(parsed && parsed._custom, radius);
2530 return values;
2531 }
2532 }
2533
2534 function getRatioAndOffset(rotation, circumference, cutout) {
2535 let ratioX = 1;
2536 let ratioY = 1;
2537 let offsetX = 0;
2538 let offsetY = 0;
2539 if (circumference < _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T) {
2540 const startAngle = rotation;
2541 const endAngle = startAngle + circumference;
2542 const startX = Math.cos(startAngle);
2543 const startY = Math.sin(startAngle);
2544 const endX = Math.cos(endAngle);
2545 const endY = Math.sin(endAngle);
2546 const calcMax = (angle, a, b)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout);
2547 const calcMin = (angle, a, b)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout);
2548 const maxX = calcMax(0, startX, endX);
2549 const maxY = calcMax(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY);
2550 const minX = calcMin(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P, startX, endX);
2551 const minY = calcMin(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY);
2552 ratioX = (maxX - minX) / 2;
2553 ratioY = (maxY - minY) / 2;
2554 offsetX = -(maxX + minX) / 2;
2555 offsetY = -(maxY + minY) / 2;
2556 }
2557 return {
2558 ratioX,
2559 ratioY,
2560 offsetX,
2561 offsetY
2562 };
2563 }
2564 class DoughnutController extends DatasetController {
2565 static id = 'doughnut';
2566 static defaults = {
2567 datasetElementType: false,
2568 dataElementType: 'arc',
2569 animation: {
2570 animateRotate: true,
2571 animateScale: false
2572 },
2573 animations: {
2574 numbers: {
2575 type: 'number',
2576 properties: [
2577 'circumference',
2578 'endAngle',
2579 'innerRadius',
2580 'outerRadius',
2581 'startAngle',
2582 'x',
2583 'y',
2584 'offset',
2585 'borderWidth',
2586 'spacing'
2587 ]
2588 }
2589 },
2590 cutout: '50%',
2591 rotation: 0,
2592 circumference: 360,
2593 radius: '100%',
2594 spacing: 0,
2595 indexAxis: 'r'
2596 };
2597 static descriptors = {
2598 _scriptable: (name)=>name !== 'spacing',
2599 _indexable: (name)=>name !== 'spacing' && !name.startsWith('borderDash') && !name.startsWith('hoverBorderDash')
2600 };
2601 static overrides = {
2602 aspectRatio: 1,
2603 plugins: {
2604 legend: {
2605 labels: {
2606 generateLabels (chart) {
2607 const data = chart.data;
2608 const { labels: { pointStyle , textAlign , color , useBorderRadius , borderRadius } } = chart.legend.options;
2609 if (data.labels.length && data.datasets.length) {
2610 return data.labels.map((label, i)=>{
2611 const meta = chart.getDatasetMeta(0);
2612 const style = meta.controller.getStyle(i);
2613 return {
2614 text: label,
2615 fillStyle: style.backgroundColor,
2616 fontColor: color,
2617 hidden: !chart.getDataVisibility(i),
2618 lineDash: style.borderDash,
2619 lineDashOffset: style.borderDashOffset,
2620 lineJoin: style.borderJoinStyle,
2621 lineWidth: style.borderWidth,
2622 strokeStyle: style.borderColor,
2623 textAlign: textAlign,
2624 pointStyle: pointStyle,
2625 borderRadius: useBorderRadius && (borderRadius || style.borderRadius),
2626 index: i
2627 };
2628 });
2629 }
2630 return [];
2631 }
2632 },
2633 onClick (e, legendItem, legend) {
2634 legend.chart.toggleDataVisibility(legendItem.index);
2635 legend.chart.update();
2636 }
2637 }
2638 }
2639 };
2640 constructor(chart, datasetIndex){
2641 super(chart, datasetIndex);
2642 this.enableOptionSharing = true;
2643 this.innerRadius = undefined;
2644 this.outerRadius = undefined;
2645 this.offsetX = undefined;
2646 this.offsetY = undefined;
2647 }
2648 linkScales() {}
2649 parse(start, count) {
2650 const data = this.getDataset().data;
2651 const meta = this._cachedMeta;
2652 if (this._parsing === false) {
2653 meta._parsed = data;
2654 } else {
2655 let getter = (i)=>+data[i];
2656 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) {
2657 const { key ='value' } = this._parsing;
2658 getter = (i)=>+(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(data[i], key);
2659 }
2660 let i, ilen;
2661 for(i = start, ilen = start + count; i < ilen; ++i){
2662 meta._parsed[i] = getter(i);
2663 }
2664 }
2665 }
2666 _getRotation() {
2667 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.rotation - 90);
2668 }
2669 _getCircumference() {
2670 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.circumference);
2671 }
2672 _getRotationExtents() {
2673 let min = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T;
2674 let max = -_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T;
2675 for(let i = 0; i < this.chart.data.datasets.length; ++i){
2676 if (this.chart.isDatasetVisible(i) && this.chart.getDatasetMeta(i).type === this._type) {
2677 const controller = this.chart.getDatasetMeta(i).controller;
2678 const rotation = controller._getRotation();
2679 const circumference = controller._getCircumference();
2680 min = Math.min(min, rotation);
2681 max = Math.max(max, rotation + circumference);
2682 }
2683 }
2684 return {
2685 rotation: min,
2686 circumference: max - min
2687 };
2688 }
2689 update(mode) {
2690 const chart = this.chart;
2691 const { chartArea } = chart;
2692 const meta = this._cachedMeta;
2693 const arcs = meta.data;
2694 const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;
2695 const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);
2696 const cutout = Math.min((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.m)(this.options.cutout, maxSize), 1);
2697 const chartWeight = this._getRingWeight(this.index);
2698 const { circumference , rotation } = this._getRotationExtents();
2699 const { ratioX , ratioY , offsetX , offsetY } = getRatioAndOffset(rotation, circumference, cutout);
2700 const maxWidth = (chartArea.width - spacing) / ratioX;
2701 const maxHeight = (chartArea.height - spacing) / ratioY;
2702 const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
2703 const outerRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.n)(this.options.radius, maxRadius);
2704 const innerRadius = Math.max(outerRadius * cutout, 0);
2705 const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();
2706 this.offsetX = offsetX * outerRadius;
2707 this.offsetY = offsetY * outerRadius;
2708 meta.total = this.calculateTotal();
2709 this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);
2710 this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);
2711 this.updateElements(arcs, 0, arcs.length, mode);
2712 }
2713 _circumference(i, reset) {
2714 const opts = this.options;
2715 const meta = this._cachedMeta;
2716 const circumference = this._getCircumference();
2717 if (reset && opts.animation.animateRotate || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {
2718 return 0;
2719 }
2720 return this.calculateCircumference(meta._parsed[i] * circumference / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);
2721 }
2722 updateElements(arcs, start, count, mode) {
2723 const reset = mode === 'reset';
2724 const chart = this.chart;
2725 const chartArea = chart.chartArea;
2726 const opts = chart.options;
2727 const animationOpts = opts.animation;
2728 const centerX = (chartArea.left + chartArea.right) / 2;
2729 const centerY = (chartArea.top + chartArea.bottom) / 2;
2730 const animateScale = reset && animationOpts.animateScale;
2731 const innerRadius = animateScale ? 0 : this.innerRadius;
2732 const outerRadius = animateScale ? 0 : this.outerRadius;
2733 const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);
2734 let startAngle = this._getRotation();
2735 let i;
2736 for(i = 0; i < start; ++i){
2737 startAngle += this._circumference(i, reset);
2738 }
2739 for(i = start; i < start + count; ++i){
2740 const circumference = this._circumference(i, reset);
2741 const arc = arcs[i];
2742 const properties = {
2743 x: centerX + this.offsetX,
2744 y: centerY + this.offsetY,
2745 startAngle,
2746 endAngle: startAngle + circumference,
2747 circumference,
2748 outerRadius,
2749 innerRadius
2750 };
2751 if (includeOptions) {
2752 properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);
2753 }
2754 startAngle += circumference;
2755 this.updateElement(arc, i, properties, mode);
2756 }
2757 }
2758 calculateTotal() {
2759 const meta = this._cachedMeta;
2760 const metaData = meta.data;
2761 let total = 0;
2762 let i;
2763 for(i = 0; i < metaData.length; i++){
2764 const value = meta._parsed[i];
2765 if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {
2766 total += Math.abs(value);
2767 }
2768 }
2769 return total;
2770 }
2771 calculateCircumference(value) {
2772 const total = this._cachedMeta.total;
2773 if (total > 0 && !isNaN(value)) {
2774 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T * (Math.abs(value) / total);
2775 }
2776 return 0;
2777 }
2778 getLabelAndValue(index) {
2779 const meta = this._cachedMeta;
2780 const chart = this.chart;
2781 const labels = chart.data.labels || [];
2782 const value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index], chart.options.locale);
2783 return {
2784 label: labels[index] || '',
2785 value
2786 };
2787 }
2788 getMaxBorderWidth(arcs) {
2789 let max = 0;
2790 const chart = this.chart;
2791 let i, ilen, meta, controller, options;
2792 if (!arcs) {
2793 for(i = 0, ilen = chart.data.datasets.length; i < ilen; ++i){
2794 if (chart.isDatasetVisible(i)) {
2795 meta = chart.getDatasetMeta(i);
2796 arcs = meta.data;
2797 controller = meta.controller;
2798 break;
2799 }
2800 }
2801 }
2802 if (!arcs) {
2803 return 0;
2804 }
2805 for(i = 0, ilen = arcs.length; i < ilen; ++i){
2806 options = controller.resolveDataElementOptions(i);
2807 if (options.borderAlign !== 'inner') {
2808 max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0);
2809 }
2810 }
2811 return max;
2812 }
2813 getMaxOffset(arcs) {
2814 let max = 0;
2815 for(let i = 0, ilen = arcs.length; i < ilen; ++i){
2816 const options = this.resolveDataElementOptions(i);
2817 max = Math.max(max, options.offset || 0, options.hoverOffset || 0);
2818 }
2819 return max;
2820 }
2821 _getRingWeightOffset(datasetIndex) {
2822 let ringWeightOffset = 0;
2823 for(let i = 0; i < datasetIndex; ++i){
2824 if (this.chart.isDatasetVisible(i)) {
2825 ringWeightOffset += this._getRingWeight(i);
2826 }
2827 }
2828 return ringWeightOffset;
2829 }
2830 _getRingWeight(datasetIndex) {
2831 return Math.max((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.data.datasets[datasetIndex].weight, 1), 0);
2832 }
2833 _getVisibleDatasetWeightTotal() {
2834 return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;
2835 }
2836 }
2837
2838 class LineController extends DatasetController {
2839 static id = 'line';
2840 static defaults = {
2841 datasetElementType: 'line',
2842 dataElementType: 'point',
2843 showLine: true,
2844 spanGaps: false
2845 };
2846 static overrides = {
2847 scales: {
2848 _index_: {
2849 type: 'category'
2850 },
2851 _value_: {
2852 type: 'linear'
2853 }
2854 }
2855 };
2856 initialize() {
2857 this.enableOptionSharing = true;
2858 this.supportsDecimation = true;
2859 super.initialize();
2860 }
2861 update(mode) {
2862 const meta = this._cachedMeta;
2863 const { dataset: line , data: points = [] , _dataset } = meta;
2864 const animationsDisabled = this.chart._animationsDisabled;
2865 let { start , count } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled);
2866 this._drawStart = start;
2867 this._drawCount = count;
2868 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) {
2869 start = 0;
2870 count = points.length;
2871 }
2872 line._chart = this.chart;
2873 line._datasetIndex = this.index;
2874 line._decimated = !!_dataset._decimated;
2875 line.points = points;
2876 const options = this.resolveDatasetElementOptions(mode);
2877 if (!this.options.showLine) {
2878 options.borderWidth = 0;
2879 }
2880 options.segment = this.options.segment;
2881 this.updateElement(line, undefined, {
2882 animated: !animationsDisabled,
2883 options
2884 }, mode);
2885 this.updateElements(points, start, count, mode);
2886 }
2887 updateElements(points, start, count, mode) {
2888 const reset = mode === 'reset';
2889 const { iScale , vScale , _stacked , _dataset } = this._cachedMeta;
2890 const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode);
2891 const iAxis = iScale.axis;
2892 const vAxis = vScale.axis;
2893 const { spanGaps , segment } = this.options;
2894 const maxGapLength = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
2895 const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';
2896 const end = start + count;
2897 const pointsCount = points.length;
2898 let prevParsed = start > 0 && this.getParsed(start - 1);
2899 for(let i = 0; i < pointsCount; ++i){
2900 const point = points[i];
2901 const properties = directUpdate ? point : {};
2902 if (i < start || i >= end) {
2903 properties.skip = true;
2904 continue;
2905 }
2906 const parsed = this.getParsed(i);
2907 const nullData = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]);
2908 const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);
2909 const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);
2910 properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;
2911 properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;
2912 if (segment) {
2913 properties.parsed = parsed;
2914 properties.raw = _dataset.data[i];
2915 }
2916 if (includeOptions) {
2917 properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);
2918 }
2919 if (!directUpdate) {
2920 this.updateElement(point, i, properties, mode);
2921 }
2922 prevParsed = parsed;
2923 }
2924 }
2925 getMaxOverflow() {
2926 const meta = this._cachedMeta;
2927 const dataset = meta.dataset;
2928 const border = dataset.options && dataset.options.borderWidth || 0;
2929 const data = meta.data || [];
2930 if (!data.length) {
2931 return border;
2932 }
2933 const firstPoint = data[0].size(this.resolveDataElementOptions(0));
2934 const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));
2935 return Math.max(border, firstPoint, lastPoint) / 2;
2936 }
2937 draw() {
2938 const meta = this._cachedMeta;
2939 meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis);
2940 super.draw();
2941 }
2942 }
2943
2944 class PolarAreaController extends DatasetController {
2945 static id = 'polarArea';
2946 static defaults = {
2947 dataElementType: 'arc',
2948 animation: {
2949 animateRotate: true,
2950 animateScale: true
2951 },
2952 animations: {
2953 numbers: {
2954 type: 'number',
2955 properties: [
2956 'x',
2957 'y',
2958 'startAngle',
2959 'endAngle',
2960 'innerRadius',
2961 'outerRadius'
2962 ]
2963 }
2964 },
2965 indexAxis: 'r',
2966 startAngle: 0
2967 };
2968 static overrides = {
2969 aspectRatio: 1,
2970 plugins: {
2971 legend: {
2972 labels: {
2973 generateLabels (chart) {
2974 const data = chart.data;
2975 if (data.labels.length && data.datasets.length) {
2976 const { labels: { pointStyle , color } } = chart.legend.options;
2977 return data.labels.map((label, i)=>{
2978 const meta = chart.getDatasetMeta(0);
2979 const style = meta.controller.getStyle(i);
2980 return {
2981 text: label,
2982 fillStyle: style.backgroundColor,
2983 strokeStyle: style.borderColor,
2984 fontColor: color,
2985 lineWidth: style.borderWidth,
2986 pointStyle: pointStyle,
2987 hidden: !chart.getDataVisibility(i),
2988 index: i
2989 };
2990 });
2991 }
2992 return [];
2993 }
2994 },
2995 onClick (e, legendItem, legend) {
2996 legend.chart.toggleDataVisibility(legendItem.index);
2997 legend.chart.update();
2998 }
2999 }
3000 },
3001 scales: {
3002 r: {
3003 type: 'radialLinear',
3004 angleLines: {
3005 display: false
3006 },
3007 beginAtZero: true,
3008 grid: {
3009 circular: true
3010 },
3011 pointLabels: {
3012 display: false
3013 },
3014 startAngle: 0
3015 }
3016 }
3017 };
3018 constructor(chart, datasetIndex){
3019 super(chart, datasetIndex);
3020 this.innerRadius = undefined;
3021 this.outerRadius = undefined;
3022 }
3023 getLabelAndValue(index) {
3024 const meta = this._cachedMeta;
3025 const chart = this.chart;
3026 const labels = chart.data.labels || [];
3027 const value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index].r, chart.options.locale);
3028 return {
3029 label: labels[index] || '',
3030 value
3031 };
3032 }
3033 parseObjectData(meta, data, start, count) {
3034 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count);
3035 }
3036 update(mode) {
3037 const arcs = this._cachedMeta.data;
3038 this._updateRadius();
3039 this.updateElements(arcs, 0, arcs.length, mode);
3040 }
3041 getMinMax() {
3042 const meta = this._cachedMeta;
3043 const range = {
3044 min: Number.POSITIVE_INFINITY,
3045 max: Number.NEGATIVE_INFINITY
3046 };
3047 meta.data.forEach((element, index)=>{
3048 const parsed = this.getParsed(index).r;
3049 if (!isNaN(parsed) && this.chart.getDataVisibility(index)) {
3050 if (parsed < range.min) {
3051 range.min = parsed;
3052 }
3053 if (parsed > range.max) {
3054 range.max = parsed;
3055 }
3056 }
3057 });
3058 return range;
3059 }
3060 _updateRadius() {
3061 const chart = this.chart;
3062 const chartArea = chart.chartArea;
3063 const opts = chart.options;
3064 const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
3065 const outerRadius = Math.max(minSize / 2, 0);
3066 const innerRadius = Math.max(opts.cutoutPercentage ? outerRadius / 100 * opts.cutoutPercentage : 1, 0);
3067 const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();
3068 this.outerRadius = outerRadius - radiusLength * this.index;
3069 this.innerRadius = this.outerRadius - radiusLength;
3070 }
3071 updateElements(arcs, start, count, mode) {
3072 const reset = mode === 'reset';
3073 const chart = this.chart;
3074 const opts = chart.options;
3075 const animationOpts = opts.animation;
3076 const scale = this._cachedMeta.rScale;
3077 const centerX = scale.xCenter;
3078 const centerY = scale.yCenter;
3079 const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P;
3080 let angle = datasetStartAngle;
3081 let i;
3082 const defaultAngle = 360 / this.countVisibleElements();
3083 for(i = 0; i < start; ++i){
3084 angle += this._computeAngle(i, mode, defaultAngle);
3085 }
3086 for(i = start; i < start + count; i++){
3087 const arc = arcs[i];
3088 let startAngle = angle;
3089 let endAngle = angle + this._computeAngle(i, mode, defaultAngle);
3090 let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(this.getParsed(i).r) : 0;
3091 angle = endAngle;
3092 if (reset) {
3093 if (animationOpts.animateScale) {
3094 outerRadius = 0;
3095 }
3096 if (animationOpts.animateRotate) {
3097 startAngle = endAngle = datasetStartAngle;
3098 }
3099 }
3100 const properties = {
3101 x: centerX,
3102 y: centerY,
3103 innerRadius: 0,
3104 outerRadius,
3105 startAngle,
3106 endAngle,
3107 options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)
3108 };
3109 this.updateElement(arc, i, properties, mode);
3110 }
3111 }
3112 countVisibleElements() {
3113 const meta = this._cachedMeta;
3114 let count = 0;
3115 meta.data.forEach((element, index)=>{
3116 if (!isNaN(this.getParsed(index).r) && this.chart.getDataVisibility(index)) {
3117 count++;
3118 }
3119 });
3120 return count;
3121 }
3122 _computeAngle(index, mode, defaultAngle) {
3123 return this.chart.getDataVisibility(index) ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0;
3124 }
3125 }
3126
3127 class PieController extends DoughnutController {
3128 static id = 'pie';
3129 static defaults = {
3130 cutout: 0,
3131 rotation: 0,
3132 circumference: 360,
3133 radius: '100%'
3134 };
3135 }
3136
3137 class RadarController extends DatasetController {
3138 static id = 'radar';
3139 static defaults = {
3140 datasetElementType: 'line',
3141 dataElementType: 'point',
3142 indexAxis: 'r',
3143 showLine: true,
3144 elements: {
3145 line: {
3146 fill: 'start'
3147 }
3148 }
3149 };
3150 static overrides = {
3151 aspectRatio: 1,
3152 scales: {
3153 r: {
3154 type: 'radialLinear'
3155 }
3156 }
3157 };
3158 getLabelAndValue(index) {
3159 const vScale = this._cachedMeta.vScale;
3160 const parsed = this.getParsed(index);
3161 return {
3162 label: vScale.getLabels()[index],
3163 value: '' + vScale.getLabelForValue(parsed[vScale.axis])
3164 };
3165 }
3166 parseObjectData(meta, data, start, count) {
3167 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count);
3168 }
3169 update(mode) {
3170 const meta = this._cachedMeta;
3171 const line = meta.dataset;
3172 const points = meta.data || [];
3173 const labels = meta.iScale.getLabels();
3174 line.points = points;
3175 if (mode !== 'resize') {
3176 const options = this.resolveDatasetElementOptions(mode);
3177 if (!this.options.showLine) {
3178 options.borderWidth = 0;
3179 }
3180 const properties = {
3181 _loop: true,
3182 _fullLoop: labels.length === points.length,
3183 options
3184 };
3185 this.updateElement(line, undefined, properties, mode);
3186 }
3187 this.updateElements(points, 0, points.length, mode);
3188 }
3189 updateElements(points, start, count, mode) {
3190 const scale = this._cachedMeta.rScale;
3191 const reset = mode === 'reset';
3192 for(let i = start; i < start + count; i++){
3193 const point = points[i];
3194 const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);
3195 const pointPosition = scale.getPointPositionForValue(i, this.getParsed(i).r);
3196 const x = reset ? scale.xCenter : pointPosition.x;
3197 const y = reset ? scale.yCenter : pointPosition.y;
3198 const properties = {
3199 x,
3200 y,
3201 angle: pointPosition.angle,
3202 skip: isNaN(x) || isNaN(y),
3203 options
3204 };
3205 this.updateElement(point, i, properties, mode);
3206 }
3207 }
3208 }
3209
3210 class ScatterController extends DatasetController {
3211 static id = 'scatter';
3212 static defaults = {
3213 datasetElementType: false,
3214 dataElementType: 'point',
3215 showLine: false,
3216 fill: false
3217 };
3218 static overrides = {
3219 interaction: {
3220 mode: 'point'
3221 },
3222 scales: {
3223 x: {
3224 type: 'linear'
3225 },
3226 y: {
3227 type: 'linear'
3228 }
3229 }
3230 };
3231 getLabelAndValue(index) {
3232 const meta = this._cachedMeta;
3233 const labels = this.chart.data.labels || [];
3234 const { xScale , yScale } = meta;
3235 const parsed = this.getParsed(index);
3236 const x = xScale.getLabelForValue(parsed.x);
3237 const y = yScale.getLabelForValue(parsed.y);
3238 return {
3239 label: labels[index] || '',
3240 value: '(' + x + ', ' + y + ')'
3241 };
3242 }
3243 update(mode) {
3244 const meta = this._cachedMeta;
3245 const { data: points = [] } = meta;
3246 const animationsDisabled = this.chart._animationsDisabled;
3247 let { start , count } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled);
3248 this._drawStart = start;
3249 this._drawCount = count;
3250 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) {
3251 start = 0;
3252 count = points.length;
3253 }
3254 if (this.options.showLine) {
3255 if (!this.datasetElementType) {
3256 this.addElements();
3257 }
3258 const { dataset: line , _dataset } = meta;
3259 line._chart = this.chart;
3260 line._datasetIndex = this.index;
3261 line._decimated = !!_dataset._decimated;
3262 line.points = points;
3263 const options = this.resolveDatasetElementOptions(mode);
3264 options.segment = this.options.segment;
3265 this.updateElement(line, undefined, {
3266 animated: !animationsDisabled,
3267 options
3268 }, mode);
3269 } else if (this.datasetElementType) {
3270 delete meta.dataset;
3271 this.datasetElementType = false;
3272 }
3273 this.updateElements(points, start, count, mode);
3274 }
3275 addElements() {
3276 const { showLine } = this.options;
3277 if (!this.datasetElementType && showLine) {
3278 this.datasetElementType = this.chart.registry.getElement('line');
3279 }
3280 super.addElements();
3281 }
3282 updateElements(points, start, count, mode) {
3283 const reset = mode === 'reset';
3284 const { iScale , vScale , _stacked , _dataset } = this._cachedMeta;
3285 const firstOpts = this.resolveDataElementOptions(start, mode);
3286 const sharedOptions = this.getSharedOptions(firstOpts);
3287 const includeOptions = this.includeOptions(mode, sharedOptions);
3288 const iAxis = iScale.axis;
3289 const vAxis = vScale.axis;
3290 const { spanGaps , segment } = this.options;
3291 const maxGapLength = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
3292 const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';
3293 let prevParsed = start > 0 && this.getParsed(start - 1);
3294 for(let i = start; i < start + count; ++i){
3295 const point = points[i];
3296 const parsed = this.getParsed(i);
3297 const properties = directUpdate ? point : {};
3298 const nullData = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]);
3299 const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);
3300 const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);
3301 properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;
3302 properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;
3303 if (segment) {
3304 properties.parsed = parsed;
3305 properties.raw = _dataset.data[i];
3306 }
3307 if (includeOptions) {
3308 properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);
3309 }
3310 if (!directUpdate) {
3311 this.updateElement(point, i, properties, mode);
3312 }
3313 prevParsed = parsed;
3314 }
3315 this.updateSharedOptions(sharedOptions, mode, firstOpts);
3316 }
3317 getMaxOverflow() {
3318 const meta = this._cachedMeta;
3319 const data = meta.data || [];
3320 if (!this.options.showLine) {
3321 let max = 0;
3322 for(let i = data.length - 1; i >= 0; --i){
3323 max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);
3324 }
3325 return max > 0 && max;
3326 }
3327 const dataset = meta.dataset;
3328 const border = dataset.options && dataset.options.borderWidth || 0;
3329 if (!data.length) {
3330 return border;
3331 }
3332 const firstPoint = data[0].size(this.resolveDataElementOptions(0));
3333 const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));
3334 return Math.max(border, firstPoint, lastPoint) / 2;
3335 }
3336 }
3337
3338 var controllers = /*#__PURE__*/Object.freeze({
3339 __proto__: null,
3340 BarController: BarController,
3341 BubbleController: BubbleController,
3342 DoughnutController: DoughnutController,
3343 LineController: LineController,
3344 PieController: PieController,
3345 PolarAreaController: PolarAreaController,
3346 RadarController: RadarController,
3347 ScatterController: ScatterController
3348 });
3349
3350 /**
3351 * @namespace Chart._adapters
3352 * @since 2.8.0
3353 * @private
3354 */ function abstract() {
3355 throw new Error('This method is not implemented: Check that a complete date adapter is provided.');
3356 }
3357 /**
3358 * Date adapter (current used by the time scale)
3359 * @namespace Chart._adapters._date
3360 * @memberof Chart._adapters
3361 * @private
3362 */ class DateAdapterBase {
3363 /**
3364 * Override default date adapter methods.
3365 * Accepts type parameter to define options type.
3366 * @example
3367 * Chart._adapters._date.override<{myAdapterOption: string}>({
3368 * init() {
3369 * console.log(this.options.myAdapterOption);
3370 * }
3371 * })
3372 */ static override(members) {
3373 Object.assign(DateAdapterBase.prototype, members);
3374 }
3375 options;
3376 constructor(options){
3377 this.options = options || {};
3378 }
3379 // eslint-disable-next-line @typescript-eslint/no-empty-function
3380 init() {}
3381 formats() {
3382 return abstract();
3383 }
3384 parse() {
3385 return abstract();
3386 }
3387 format() {
3388 return abstract();
3389 }
3390 add() {
3391 return abstract();
3392 }
3393 diff() {
3394 return abstract();
3395 }
3396 startOf() {
3397 return abstract();
3398 }
3399 endOf() {
3400 return abstract();
3401 }
3402 }
3403 var adapters = {
3404 _date: DateAdapterBase
3405 };
3406
3407 function binarySearch(metaset, axis, value, intersect) {
3408 const { controller , data , _sorted } = metaset;
3409 const iScale = controller._cachedMeta.iScale;
3410 const spanGaps = metaset.dataset ? metaset.dataset.options ? metaset.dataset.options.spanGaps : null : null;
3411 if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) {
3412 const lookupMethod = iScale._reversePixels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.A : _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B;
3413 if (!intersect) {
3414 const result = lookupMethod(data, axis, value);
3415 if (spanGaps) {
3416 const { vScale } = controller._cachedMeta;
3417 const { _parsed } = metaset;
3418 const distanceToDefinedLo = _parsed.slice(0, result.lo + 1).reverse().findIndex((point)=>!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(point[vScale.axis]));
3419 result.lo -= Math.max(0, distanceToDefinedLo);
3420 const distanceToDefinedHi = _parsed.slice(result.hi).findIndex((point)=>!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(point[vScale.axis]));
3421 result.hi += Math.max(0, distanceToDefinedHi);
3422 }
3423 return result;
3424 } else if (controller._sharedOptions) {
3425 const el = data[0];
3426 const range = typeof el.getRange === 'function' && el.getRange(axis);
3427 if (range) {
3428 const start = lookupMethod(data, axis, value - range);
3429 const end = lookupMethod(data, axis, value + range);
3430 return {
3431 lo: start.lo,
3432 hi: end.hi
3433 };
3434 }
3435 }
3436 }
3437 return {
3438 lo: 0,
3439 hi: data.length - 1
3440 };
3441 }
3442 function evaluateInteractionItems(chart, axis, position, handler, intersect) {
3443 const metasets = chart.getSortedVisibleDatasetMetas();
3444 const value = position[axis];
3445 for(let i = 0, ilen = metasets.length; i < ilen; ++i){
3446 const { index , data } = metasets[i];
3447 const { lo , hi } = binarySearch(metasets[i], axis, value, intersect);
3448 for(let j = lo; j <= hi; ++j){
3449 const element = data[j];
3450 if (!element.skip) {
3451 handler(element, index, j);
3452 }
3453 }
3454 }
3455 }
3456 function getDistanceMetricForAxis(axis) {
3457 const useX = axis.indexOf('x') !== -1;
3458 const useY = axis.indexOf('y') !== -1;
3459 return function(pt1, pt2) {
3460 const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
3461 const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
3462 return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
3463 };
3464 }
3465 function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {
3466 const items = [];
3467 if (!includeInvisible && !chart.isPointInArea(position)) {
3468 return items;
3469 }
3470 const evaluationFunc = function(element, datasetIndex, index) {
3471 if (!includeInvisible && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(element, chart.chartArea, 0)) {
3472 return;
3473 }
3474 if (element.inRange(position.x, position.y, useFinalPosition)) {
3475 items.push({
3476 element,
3477 datasetIndex,
3478 index
3479 });
3480 }
3481 };
3482 evaluateInteractionItems(chart, axis, position, evaluationFunc, true);
3483 return items;
3484 }
3485 function getNearestRadialItems(chart, position, axis, useFinalPosition) {
3486 let items = [];
3487 function evaluationFunc(element, datasetIndex, index) {
3488 const { startAngle , endAngle } = element.getProps([
3489 'startAngle',
3490 'endAngle'
3491 ], useFinalPosition);
3492 const { angle } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.D)(element, {
3493 x: position.x,
3494 y: position.y
3495 });
3496 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle)) {
3497 items.push({
3498 element,
3499 datasetIndex,
3500 index
3501 });
3502 }
3503 }
3504 evaluateInteractionItems(chart, axis, position, evaluationFunc);
3505 return items;
3506 }
3507 function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
3508 let items = [];
3509 const distanceMetric = getDistanceMetricForAxis(axis);
3510 let minDistance = Number.POSITIVE_INFINITY;
3511 function evaluationFunc(element, datasetIndex, index) {
3512 const inRange = element.inRange(position.x, position.y, useFinalPosition);
3513 if (intersect && !inRange) {
3514 return;
3515 }
3516 const center = element.getCenterPoint(useFinalPosition);
3517 const pointInArea = !!includeInvisible || chart.isPointInArea(center);
3518 if (!pointInArea && !inRange) {
3519 return;
3520 }
3521 const distance = distanceMetric(position, center);
3522 if (distance < minDistance) {
3523 items = [
3524 {
3525 element,
3526 datasetIndex,
3527 index
3528 }
3529 ];
3530 minDistance = distance;
3531 } else if (distance === minDistance) {
3532 items.push({
3533 element,
3534 datasetIndex,
3535 index
3536 });
3537 }
3538 }
3539 evaluateInteractionItems(chart, axis, position, evaluationFunc);
3540 return items;
3541 }
3542 function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
3543 if (!includeInvisible && !chart.isPointInArea(position)) {
3544 return [];
3545 }
3546 return axis === 'r' && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);
3547 }
3548 function getAxisItems(chart, position, axis, intersect, useFinalPosition) {
3549 const items = [];
3550 const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange';
3551 let intersectsItem = false;
3552 evaluateInteractionItems(chart, axis, position, (element, datasetIndex, index)=>{
3553 if (element[rangeMethod] && element[rangeMethod](position[axis], useFinalPosition)) {
3554 items.push({
3555 element,
3556 datasetIndex,
3557 index
3558 });
3559 intersectsItem = intersectsItem || element.inRange(position.x, position.y, useFinalPosition);
3560 }
3561 });
3562 if (intersect && !intersectsItem) {
3563 return [];
3564 }
3565 return items;
3566 }
3567 var Interaction = {
3568 evaluateInteractionItems,
3569 modes: {
3570 index (chart, e, options, useFinalPosition) {
3571 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3572 const axis = options.axis || 'x';
3573 const includeInvisible = options.includeInvisible || false;
3574 const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
3575 const elements = [];
3576 if (!items.length) {
3577 return [];
3578 }
3579 chart.getSortedVisibleDatasetMetas().forEach((meta)=>{
3580 const index = items[0].index;
3581 const element = meta.data[index];
3582 if (element && !element.skip) {
3583 elements.push({
3584 element,
3585 datasetIndex: meta.index,
3586 index
3587 });
3588 }
3589 });
3590 return elements;
3591 },
3592 dataset (chart, e, options, useFinalPosition) {
3593 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3594 const axis = options.axis || 'xy';
3595 const includeInvisible = options.includeInvisible || false;
3596 let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
3597 if (items.length > 0) {
3598 const datasetIndex = items[0].datasetIndex;
3599 const data = chart.getDatasetMeta(datasetIndex).data;
3600 items = [];
3601 for(let i = 0; i < data.length; ++i){
3602 items.push({
3603 element: data[i],
3604 datasetIndex,
3605 index: i
3606 });
3607 }
3608 }
3609 return items;
3610 },
3611 point (chart, e, options, useFinalPosition) {
3612 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3613 const axis = options.axis || 'xy';
3614 const includeInvisible = options.includeInvisible || false;
3615 return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);
3616 },
3617 nearest (chart, e, options, useFinalPosition) {
3618 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3619 const axis = options.axis || 'xy';
3620 const includeInvisible = options.includeInvisible || false;
3621 return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);
3622 },
3623 x (chart, e, options, useFinalPosition) {
3624 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3625 return getAxisItems(chart, position, 'x', options.intersect, useFinalPosition);
3626 },
3627 y (chart, e, options, useFinalPosition) {
3628 const position = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart);
3629 return getAxisItems(chart, position, 'y', options.intersect, useFinalPosition);
3630 }
3631 }
3632 };
3633
3634 const STATIC_POSITIONS = [
3635 'left',
3636 'top',
3637 'right',
3638 'bottom'
3639 ];
3640 function filterByPosition(array, position) {
3641 return array.filter((v)=>v.pos === position);
3642 }
3643 function filterDynamicPositionByAxis(array, axis) {
3644 return array.filter((v)=>STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis);
3645 }
3646 function sortByWeight(array, reverse) {
3647 return array.sort((a, b)=>{
3648 const v0 = reverse ? b : a;
3649 const v1 = reverse ? a : b;
3650 return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;
3651 });
3652 }
3653 function wrapBoxes(boxes) {
3654 const layoutBoxes = [];
3655 let i, ilen, box, pos, stack, stackWeight;
3656 for(i = 0, ilen = (boxes || []).length; i < ilen; ++i){
3657 box = boxes[i];
3658 ({ position: pos , options: { stack , stackWeight =1 } } = box);
3659 layoutBoxes.push({
3660 index: i,
3661 box,
3662 pos,
3663 horizontal: box.isHorizontal(),
3664 weight: box.weight,
3665 stack: stack && pos + stack,
3666 stackWeight
3667 });
3668 }
3669 return layoutBoxes;
3670 }
3671 function buildStacks(layouts) {
3672 const stacks = {};
3673 for (const wrap of layouts){
3674 const { stack , pos , stackWeight } = wrap;
3675 if (!stack || !STATIC_POSITIONS.includes(pos)) {
3676 continue;
3677 }
3678 const _stack = stacks[stack] || (stacks[stack] = {
3679 count: 0,
3680 placed: 0,
3681 weight: 0,
3682 size: 0
3683 });
3684 _stack.count++;
3685 _stack.weight += stackWeight;
3686 }
3687 return stacks;
3688 }
3689 function setLayoutDims(layouts, params) {
3690 const stacks = buildStacks(layouts);
3691 const { vBoxMaxWidth , hBoxMaxHeight } = params;
3692 let i, ilen, layout;
3693 for(i = 0, ilen = layouts.length; i < ilen; ++i){
3694 layout = layouts[i];
3695 const { fullSize } = layout.box;
3696 const stack = stacks[layout.stack];
3697 const factor = stack && layout.stackWeight / stack.weight;
3698 if (layout.horizontal) {
3699 layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;
3700 layout.height = hBoxMaxHeight;
3701 } else {
3702 layout.width = vBoxMaxWidth;
3703 layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;
3704 }
3705 }
3706 return stacks;
3707 }
3708 function buildLayoutBoxes(boxes) {
3709 const layoutBoxes = wrapBoxes(boxes);
3710 const fullSize = sortByWeight(layoutBoxes.filter((wrap)=>wrap.box.fullSize), true);
3711 const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true);
3712 const right = sortByWeight(filterByPosition(layoutBoxes, 'right'));
3713 const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true);
3714 const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom'));
3715 const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x');
3716 const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y');
3717 return {
3718 fullSize,
3719 leftAndTop: left.concat(top),
3720 rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal),
3721 chartArea: filterByPosition(layoutBoxes, 'chartArea'),
3722 vertical: left.concat(right).concat(centerVertical),
3723 horizontal: top.concat(bottom).concat(centerHorizontal)
3724 };
3725 }
3726 function getCombinedMax(maxPadding, chartArea, a, b) {
3727 return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);
3728 }
3729 function updateMaxPadding(maxPadding, boxPadding) {
3730 maxPadding.top = Math.max(maxPadding.top, boxPadding.top);
3731 maxPadding.left = Math.max(maxPadding.left, boxPadding.left);
3732 maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);
3733 maxPadding.right = Math.max(maxPadding.right, boxPadding.right);
3734 }
3735 function updateDims(chartArea, params, layout, stacks) {
3736 const { pos , box } = layout;
3737 const maxPadding = chartArea.maxPadding;
3738 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(pos)) {
3739 if (layout.size) {
3740 chartArea[pos] -= layout.size;
3741 }
3742 const stack = stacks[layout.stack] || {
3743 size: 0,
3744 count: 1
3745 };
3746 stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);
3747 layout.size = stack.size / stack.count;
3748 chartArea[pos] += layout.size;
3749 }
3750 if (box.getPadding) {
3751 updateMaxPadding(maxPadding, box.getPadding());
3752 }
3753 const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right'));
3754 const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom'));
3755 const widthChanged = newWidth !== chartArea.w;
3756 const heightChanged = newHeight !== chartArea.h;
3757 chartArea.w = newWidth;
3758 chartArea.h = newHeight;
3759 return layout.horizontal ? {
3760 same: widthChanged,
3761 other: heightChanged
3762 } : {
3763 same: heightChanged,
3764 other: widthChanged
3765 };
3766 }
3767 function handleMaxPadding(chartArea) {
3768 const maxPadding = chartArea.maxPadding;
3769 function updatePos(pos) {
3770 const change = Math.max(maxPadding[pos] - chartArea[pos], 0);
3771 chartArea[pos] += change;
3772 return change;
3773 }
3774 chartArea.y += updatePos('top');
3775 chartArea.x += updatePos('left');
3776 updatePos('right');
3777 updatePos('bottom');
3778 }
3779 function getMargins(horizontal, chartArea) {
3780 const maxPadding = chartArea.maxPadding;
3781 function marginForPositions(positions) {
3782 const margin = {
3783 left: 0,
3784 top: 0,
3785 right: 0,
3786 bottom: 0
3787 };
3788 positions.forEach((pos)=>{
3789 margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);
3790 });
3791 return margin;
3792 }
3793 return horizontal ? marginForPositions([
3794 'left',
3795 'right'
3796 ]) : marginForPositions([
3797 'top',
3798 'bottom'
3799 ]);
3800 }
3801 function fitBoxes(boxes, chartArea, params, stacks) {
3802 const refitBoxes = [];
3803 let i, ilen, layout, box, refit, changed;
3804 for(i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i){
3805 layout = boxes[i];
3806 box = layout.box;
3807 box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));
3808 const { same , other } = updateDims(chartArea, params, layout, stacks);
3809 refit |= same && refitBoxes.length;
3810 changed = changed || other;
3811 if (!box.fullSize) {
3812 refitBoxes.push(layout);
3813 }
3814 }
3815 return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;
3816 }
3817 function setBoxDims(box, left, top, width, height) {
3818 box.top = top;
3819 box.left = left;
3820 box.right = left + width;
3821 box.bottom = top + height;
3822 box.width = width;
3823 box.height = height;
3824 }
3825 function placeBoxes(boxes, chartArea, params, stacks) {
3826 const userPadding = params.padding;
3827 let { x , y } = chartArea;
3828 for (const layout of boxes){
3829 const box = layout.box;
3830 const stack = stacks[layout.stack] || {
3831 count: 1,
3832 placed: 0,
3833 weight: 1
3834 };
3835 const weight = layout.stackWeight / stack.weight || 1;
3836 if (layout.horizontal) {
3837 const width = chartArea.w * weight;
3838 const height = stack.size || box.height;
3839 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) {
3840 y = stack.start;
3841 }
3842 if (box.fullSize) {
3843 setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height);
3844 } else {
3845 setBoxDims(box, chartArea.left + stack.placed, y, width, height);
3846 }
3847 stack.start = y;
3848 stack.placed += width;
3849 y = box.bottom;
3850 } else {
3851 const height = chartArea.h * weight;
3852 const width = stack.size || box.width;
3853 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) {
3854 x = stack.start;
3855 }
3856 if (box.fullSize) {
3857 setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top);
3858 } else {
3859 setBoxDims(box, x, chartArea.top + stack.placed, width, height);
3860 }
3861 stack.start = x;
3862 stack.placed += height;
3863 x = box.right;
3864 }
3865 }
3866 chartArea.x = x;
3867 chartArea.y = y;
3868 }
3869 var layouts = {
3870 addBox (chart, item) {
3871 if (!chart.boxes) {
3872 chart.boxes = [];
3873 }
3874 item.fullSize = item.fullSize || false;
3875 item.position = item.position || 'top';
3876 item.weight = item.weight || 0;
3877 item._layers = item._layers || function() {
3878 return [
3879 {
3880 z: 0,
3881 draw (chartArea) {
3882 item.draw(chartArea);
3883 }
3884 }
3885 ];
3886 };
3887 chart.boxes.push(item);
3888 },
3889 removeBox (chart, layoutItem) {
3890 const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
3891 if (index !== -1) {
3892 chart.boxes.splice(index, 1);
3893 }
3894 },
3895 configure (chart, item, options) {
3896 item.fullSize = options.fullSize;
3897 item.position = options.position;
3898 item.weight = options.weight;
3899 },
3900 update (chart, width, height, minPadding) {
3901 if (!chart) {
3902 return;
3903 }
3904 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(chart.options.layout.padding);
3905 const availableWidth = Math.max(width - padding.width, 0);
3906 const availableHeight = Math.max(height - padding.height, 0);
3907 const boxes = buildLayoutBoxes(chart.boxes);
3908 const verticalBoxes = boxes.vertical;
3909 const horizontalBoxes = boxes.horizontal;
3910 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(chart.boxes, (box)=>{
3911 if (typeof box.beforeLayout === 'function') {
3912 box.beforeLayout();
3913 }
3914 });
3915 const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap)=>wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;
3916 const params = Object.freeze({
3917 outerWidth: width,
3918 outerHeight: height,
3919 padding,
3920 availableWidth,
3921 availableHeight,
3922 vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,
3923 hBoxMaxHeight: availableHeight / 2
3924 });
3925 const maxPadding = Object.assign({}, padding);
3926 updateMaxPadding(maxPadding, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(minPadding));
3927 const chartArea = Object.assign({
3928 maxPadding,
3929 w: availableWidth,
3930 h: availableHeight,
3931 x: padding.left,
3932 y: padding.top
3933 }, padding);
3934 const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);
3935 fitBoxes(boxes.fullSize, chartArea, params, stacks);
3936 fitBoxes(verticalBoxes, chartArea, params, stacks);
3937 if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {
3938 fitBoxes(verticalBoxes, chartArea, params, stacks);
3939 }
3940 handleMaxPadding(chartArea);
3941 placeBoxes(boxes.leftAndTop, chartArea, params, stacks);
3942 chartArea.x += chartArea.w;
3943 chartArea.y += chartArea.h;
3944 placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);
3945 chart.chartArea = {
3946 left: chartArea.left,
3947 top: chartArea.top,
3948 right: chartArea.left + chartArea.w,
3949 bottom: chartArea.top + chartArea.h,
3950 height: chartArea.h,
3951 width: chartArea.w
3952 };
3953 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(boxes.chartArea, (layout)=>{
3954 const box = layout.box;
3955 Object.assign(box, chart.chartArea);
3956 box.update(chartArea.w, chartArea.h, {
3957 left: 0,
3958 top: 0,
3959 right: 0,
3960 bottom: 0
3961 });
3962 });
3963 }
3964 };
3965
3966 class BasePlatform {
3967 acquireContext(canvas, aspectRatio) {}
3968 releaseContext(context) {
3969 return false;
3970 }
3971 addEventListener(chart, type, listener) {}
3972 removeEventListener(chart, type, listener) {}
3973 getDevicePixelRatio() {
3974 return 1;
3975 }
3976 getMaximumSize(element, width, height, aspectRatio) {
3977 width = Math.max(0, width || element.width);
3978 height = height || element.height;
3979 return {
3980 width,
3981 height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)
3982 };
3983 }
3984 isAttached(canvas) {
3985 return true;
3986 }
3987 updateConfig(config) {
3988 }
3989 }
3990
3991 class BasicPlatform extends BasePlatform {
3992 acquireContext(item) {
3993 return item && item.getContext && item.getContext('2d') || null;
3994 }
3995 updateConfig(config) {
3996 config.options.animation = false;
3997 }
3998 }
3999
4000 const EXPANDO_KEY = '$chartjs';
4001 const EVENT_TYPES = {
4002 touchstart: 'mousedown',
4003 touchmove: 'mousemove',
4004 touchend: 'mouseup',
4005 pointerenter: 'mouseenter',
4006 pointerdown: 'mousedown',
4007 pointermove: 'mousemove',
4008 pointerup: 'mouseup',
4009 pointerleave: 'mouseout',
4010 pointerout: 'mouseout'
4011 };
4012 const isNullOrEmpty = (value)=>value === null || value === '';
4013 function initCanvas(canvas, aspectRatio) {
4014 const style = canvas.style;
4015 const renderHeight = canvas.getAttribute('height');
4016 const renderWidth = canvas.getAttribute('width');
4017 canvas[EXPANDO_KEY] = {
4018 initial: {
4019 height: renderHeight,
4020 width: renderWidth,
4021 style: {
4022 display: style.display,
4023 height: style.height,
4024 width: style.width
4025 }
4026 }
4027 };
4028 style.display = style.display || 'block';
4029 style.boxSizing = style.boxSizing || 'border-box';
4030 if (isNullOrEmpty(renderWidth)) {
4031 const displayWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'width');
4032 if (displayWidth !== undefined) {
4033 canvas.width = displayWidth;
4034 }
4035 }
4036 if (isNullOrEmpty(renderHeight)) {
4037 if (canvas.style.height === '') {
4038 canvas.height = canvas.width / (aspectRatio || 2);
4039 } else {
4040 const displayHeight = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'height');
4041 if (displayHeight !== undefined) {
4042 canvas.height = displayHeight;
4043 }
4044 }
4045 }
4046 return canvas;
4047 }
4048 const eventListenerOptions = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.K ? {
4049 passive: true
4050 } : false;
4051 function addListener(node, type, listener) {
4052 if (node) {
4053 node.addEventListener(type, listener, eventListenerOptions);
4054 }
4055 }
4056 function removeListener(chart, type, listener) {
4057 if (chart && chart.canvas) {
4058 chart.canvas.removeEventListener(type, listener, eventListenerOptions);
4059 }
4060 }
4061 function fromNativeEvent(event, chart) {
4062 const type = EVENT_TYPES[event.type] || event.type;
4063 const { x , y } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.z)(event, chart);
4064 return {
4065 type,
4066 chart,
4067 native: event,
4068 x: x !== undefined ? x : null,
4069 y: y !== undefined ? y : null
4070 };
4071 }
4072 function nodeListContains(nodeList, canvas) {
4073 for (const node of nodeList){
4074 if (node === canvas || node.contains(canvas)) {
4075 return true;
4076 }
4077 }
4078 }
4079 function createAttachObserver(chart, type, listener) {
4080 const canvas = chart.canvas;
4081 const observer = new MutationObserver((entries)=>{
4082 let trigger = false;
4083 for (const entry of entries){
4084 trigger = trigger || nodeListContains(entry.addedNodes, canvas);
4085 trigger = trigger && !nodeListContains(entry.removedNodes, canvas);
4086 }
4087 if (trigger) {
4088 listener();
4089 }
4090 });
4091 observer.observe(document, {
4092 childList: true,
4093 subtree: true
4094 });
4095 return observer;
4096 }
4097 function createDetachObserver(chart, type, listener) {
4098 const canvas = chart.canvas;
4099 const observer = new MutationObserver((entries)=>{
4100 let trigger = false;
4101 for (const entry of entries){
4102 trigger = trigger || nodeListContains(entry.removedNodes, canvas);
4103 trigger = trigger && !nodeListContains(entry.addedNodes, canvas);
4104 }
4105 if (trigger) {
4106 listener();
4107 }
4108 });
4109 observer.observe(document, {
4110 childList: true,
4111 subtree: true
4112 });
4113 return observer;
4114 }
4115 const drpListeningCharts = new Map();
4116 let oldDevicePixelRatio = 0;
4117 function onWindowResize() {
4118 const dpr = window.devicePixelRatio;
4119 if (dpr === oldDevicePixelRatio) {
4120 return;
4121 }
4122 oldDevicePixelRatio = dpr;
4123 drpListeningCharts.forEach((resize, chart)=>{
4124 if (chart.currentDevicePixelRatio !== dpr) {
4125 resize();
4126 }
4127 });
4128 }
4129 function listenDevicePixelRatioChanges(chart, resize) {
4130 if (!drpListeningCharts.size) {
4131 window.addEventListener('resize', onWindowResize);
4132 }
4133 drpListeningCharts.set(chart, resize);
4134 }
4135 function unlistenDevicePixelRatioChanges(chart) {
4136 drpListeningCharts.delete(chart);
4137 if (!drpListeningCharts.size) {
4138 window.removeEventListener('resize', onWindowResize);
4139 }
4140 }
4141 function createResizeObserver(chart, type, listener) {
4142 const canvas = chart.canvas;
4143 const container = canvas && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas);
4144 if (!container) {
4145 return;
4146 }
4147 const resize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.L)((width, height)=>{
4148 const w = container.clientWidth;
4149 listener(width, height);
4150 if (w < container.clientWidth) {
4151 listener();
4152 }
4153 }, window);
4154 const observer = new ResizeObserver((entries)=>{
4155 const entry = entries[0];
4156 const width = entry.contentRect.width;
4157 const height = entry.contentRect.height;
4158 if (width === 0 && height === 0) {
4159 return;
4160 }
4161 resize(width, height);
4162 });
4163 observer.observe(container);
4164 listenDevicePixelRatioChanges(chart, resize);
4165 return observer;
4166 }
4167 function releaseObserver(chart, type, observer) {
4168 if (observer) {
4169 observer.disconnect();
4170 }
4171 if (type === 'resize') {
4172 unlistenDevicePixelRatioChanges(chart);
4173 }
4174 }
4175 function createProxyAndListen(chart, type, listener) {
4176 const canvas = chart.canvas;
4177 const proxy = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.L)((event)=>{
4178 if (chart.ctx !== null) {
4179 listener(fromNativeEvent(event, chart));
4180 }
4181 }, chart);
4182 addListener(canvas, type, proxy);
4183 return proxy;
4184 }
4185 class DomPlatform extends BasePlatform {
4186 acquireContext(canvas, aspectRatio) {
4187 const context = canvas && canvas.getContext && canvas.getContext('2d');
4188 if (context && context.canvas === canvas) {
4189 initCanvas(canvas, aspectRatio);
4190 return context;
4191 }
4192 return null;
4193 }
4194 releaseContext(context) {
4195 const canvas = context.canvas;
4196 if (!canvas[EXPANDO_KEY]) {
4197 return false;
4198 }
4199 const initial = canvas[EXPANDO_KEY].initial;
4200 [
4201 'height',
4202 'width'
4203 ].forEach((prop)=>{
4204 const value = initial[prop];
4205 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {
4206 canvas.removeAttribute(prop);
4207 } else {
4208 canvas.setAttribute(prop, value);
4209 }
4210 });
4211 const style = initial.style || {};
4212 Object.keys(style).forEach((key)=>{
4213 canvas.style[key] = style[key];
4214 });
4215 canvas.width = canvas.width;
4216 delete canvas[EXPANDO_KEY];
4217 return true;
4218 }
4219 addEventListener(chart, type, listener) {
4220 this.removeEventListener(chart, type);
4221 const proxies = chart.$proxies || (chart.$proxies = {});
4222 const handlers = {
4223 attach: createAttachObserver,
4224 detach: createDetachObserver,
4225 resize: createResizeObserver
4226 };
4227 const handler = handlers[type] || createProxyAndListen;
4228 proxies[type] = handler(chart, type, listener);
4229 }
4230 removeEventListener(chart, type) {
4231 const proxies = chart.$proxies || (chart.$proxies = {});
4232 const proxy = proxies[type];
4233 if (!proxy) {
4234 return;
4235 }
4236 const handlers = {
4237 attach: releaseObserver,
4238 detach: releaseObserver,
4239 resize: releaseObserver
4240 };
4241 const handler = handlers[type] || removeListener;
4242 handler(chart, type, proxy);
4243 proxies[type] = undefined;
4244 }
4245 getDevicePixelRatio() {
4246 return window.devicePixelRatio;
4247 }
4248 getMaximumSize(canvas, width, height, aspectRatio) {
4249 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.G)(canvas, width, height, aspectRatio);
4250 }
4251 isAttached(canvas) {
4252 const container = canvas && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas);
4253 return !!(container && container.isConnected);
4254 }
4255 }
4256
4257 function _detectPlatform(canvas) {
4258 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.M)() || typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) {
4259 return BasicPlatform;
4260 }
4261 return DomPlatform;
4262 }
4263
4264 class Element {
4265 static defaults = {};
4266 static defaultRoutes = undefined;
4267 x;
4268 y;
4269 active = false;
4270 options;
4271 $animations;
4272 tooltipPosition(useFinalPosition) {
4273 const { x , y } = this.getProps([
4274 'x',
4275 'y'
4276 ], useFinalPosition);
4277 return {
4278 x,
4279 y
4280 };
4281 }
4282 hasValue() {
4283 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.x) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.y);
4284 }
4285 getProps(props, final) {
4286 const anims = this.$animations;
4287 if (!final || !anims) {
4288 // let's not create an object, if not needed
4289 return this;
4290 }
4291 const ret = {};
4292 props.forEach((prop)=>{
4293 ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];
4294 });
4295 return ret;
4296 }
4297 }
4298
4299 function autoSkip(scale, ticks) {
4300 const tickOpts = scale.options.ticks;
4301 const determinedMaxTicks = determineMaxTicks(scale);
4302 const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks);
4303 const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
4304 const numMajorIndices = majorIndices.length;
4305 const first = majorIndices[0];
4306 const last = majorIndices[numMajorIndices - 1];
4307 const newTicks = [];
4308 if (numMajorIndices > ticksLimit) {
4309 skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
4310 return newTicks;
4311 }
4312 const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);
4313 if (numMajorIndices > 0) {
4314 let i, ilen;
4315 const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;
4316 skip(ticks, newTicks, spacing, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
4317 for(i = 0, ilen = numMajorIndices - 1; i < ilen; i++){
4318 skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);
4319 }
4320 skip(ticks, newTicks, spacing, last, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
4321 return newTicks;
4322 }
4323 skip(ticks, newTicks, spacing);
4324 return newTicks;
4325 }
4326 function determineMaxTicks(scale) {
4327 const offset = scale.options.offset;
4328 const tickLength = scale._tickSize();
4329 const maxScale = scale._length / tickLength + (offset ? 0 : 1);
4330 const maxChart = scale._maxLength / tickLength;
4331 return Math.floor(Math.min(maxScale, maxChart));
4332 }
4333 function calculateSpacing(majorIndices, ticks, ticksLimit) {
4334 const evenMajorSpacing = getEvenSpacing(majorIndices);
4335 const spacing = ticks.length / ticksLimit;
4336 if (!evenMajorSpacing) {
4337 return Math.max(spacing, 1);
4338 }
4339 const factors = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.N)(evenMajorSpacing);
4340 for(let i = 0, ilen = factors.length - 1; i < ilen; i++){
4341 const factor = factors[i];
4342 if (factor > spacing) {
4343 return factor;
4344 }
4345 }
4346 return Math.max(spacing, 1);
4347 }
4348 function getMajorIndices(ticks) {
4349 const result = [];
4350 let i, ilen;
4351 for(i = 0, ilen = ticks.length; i < ilen; i++){
4352 if (ticks[i].major) {
4353 result.push(i);
4354 }
4355 }
4356 return result;
4357 }
4358 function skipMajors(ticks, newTicks, majorIndices, spacing) {
4359 let count = 0;
4360 let next = majorIndices[0];
4361 let i;
4362 spacing = Math.ceil(spacing);
4363 for(i = 0; i < ticks.length; i++){
4364 if (i === next) {
4365 newTicks.push(ticks[i]);
4366 count++;
4367 next = majorIndices[count * spacing];
4368 }
4369 }
4370 }
4371 function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
4372 const start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorStart, 0);
4373 const end = Math.min((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorEnd, ticks.length), ticks.length);
4374 let count = 0;
4375 let length, i, next;
4376 spacing = Math.ceil(spacing);
4377 if (majorEnd) {
4378 length = majorEnd - majorStart;
4379 spacing = length / Math.floor(length / spacing);
4380 }
4381 next = start;
4382 while(next < 0){
4383 count++;
4384 next = Math.round(start + count * spacing);
4385 }
4386 for(i = Math.max(start, 0); i < end; i++){
4387 if (i === next) {
4388 newTicks.push(ticks[i]);
4389 count++;
4390 next = Math.round(start + count * spacing);
4391 }
4392 }
4393 }
4394 function getEvenSpacing(arr) {
4395 const len = arr.length;
4396 let i, diff;
4397 if (len < 2) {
4398 return false;
4399 }
4400 for(diff = arr[0], i = 1; i < len; ++i){
4401 if (arr[i] - arr[i - 1] !== diff) {
4402 return false;
4403 }
4404 }
4405 return diff;
4406 }
4407
4408 const reverseAlign = (align)=>align === 'left' ? 'right' : align === 'right' ? 'left' : align;
4409 const offsetFromEdge = (scale, edge, offset)=>edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset;
4410 const getTicksLimit = (ticksLength, maxTicksLimit)=>Math.min(maxTicksLimit || ticksLength, ticksLength);
4411 function sample(arr, numItems) {
4412 const result = [];
4413 const increment = arr.length / numItems;
4414 const len = arr.length;
4415 let i = 0;
4416 for(; i < len; i += increment){
4417 result.push(arr[Math.floor(i)]);
4418 }
4419 return result;
4420 }
4421 function getPixelForGridLine(scale, index, offsetGridLines) {
4422 const length = scale.ticks.length;
4423 const validIndex = Math.min(index, length - 1);
4424 const start = scale._startPixel;
4425 const end = scale._endPixel;
4426 const epsilon = 1e-6;
4427 let lineValue = scale.getPixelForTick(validIndex);
4428 let offset;
4429 if (offsetGridLines) {
4430 if (length === 1) {
4431 offset = Math.max(lineValue - start, end - lineValue);
4432 } else if (index === 0) {
4433 offset = (scale.getPixelForTick(1) - lineValue) / 2;
4434 } else {
4435 offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2;
4436 }
4437 lineValue += validIndex < index ? offset : -offset;
4438 if (lineValue < start - epsilon || lineValue > end + epsilon) {
4439 return;
4440 }
4441 }
4442 return lineValue;
4443 }
4444 function garbageCollect(caches, length) {
4445 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(caches, (cache)=>{
4446 const gc = cache.gc;
4447 const gcLen = gc.length / 2;
4448 let i;
4449 if (gcLen > length) {
4450 for(i = 0; i < gcLen; ++i){
4451 delete cache.data[gc[i]];
4452 }
4453 gc.splice(0, gcLen);
4454 }
4455 });
4456 }
4457 function getTickMarkLength(options) {
4458 return options.drawTicks ? options.tickLength : 0;
4459 }
4460 function getTitleHeight(options, fallback) {
4461 if (!options.display) {
4462 return 0;
4463 }
4464 const font = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.font, fallback);
4465 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);
4466 const lines = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(options.text) ? options.text.length : 1;
4467 return lines * font.lineHeight + padding.height;
4468 }
4469 function createScaleContext(parent, scale) {
4470 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
4471 scale,
4472 type: 'scale'
4473 });
4474 }
4475 function createTickContext(parent, index, tick) {
4476 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
4477 tick,
4478 index,
4479 type: 'tick'
4480 });
4481 }
4482 function titleAlign(align, position, reverse) {
4483 let ret = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(align);
4484 if (reverse && position !== 'right' || !reverse && position === 'right') {
4485 ret = reverseAlign(ret);
4486 }
4487 return ret;
4488 }
4489 function titleArgs(scale, offset, position, align) {
4490 const { top , left , bottom , right , chart } = scale;
4491 const { chartArea , scales } = chart;
4492 let rotation = 0;
4493 let maxWidth, titleX, titleY;
4494 const height = bottom - top;
4495 const width = right - left;
4496 if (scale.isHorizontal()) {
4497 titleX = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right);
4498 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
4499 const positionAxisID = Object.keys(position)[0];
4500 const value = position[positionAxisID];
4501 titleY = scales[positionAxisID].getPixelForValue(value) + height - offset;
4502 } else if (position === 'center') {
4503 titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset;
4504 } else {
4505 titleY = offsetFromEdge(scale, position, offset);
4506 }
4507 maxWidth = right - left;
4508 } else {
4509 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
4510 const positionAxisID = Object.keys(position)[0];
4511 const value = position[positionAxisID];
4512 titleX = scales[positionAxisID].getPixelForValue(value) - width + offset;
4513 } else if (position === 'center') {
4514 titleX = (chartArea.left + chartArea.right) / 2 - width + offset;
4515 } else {
4516 titleX = offsetFromEdge(scale, position, offset);
4517 }
4518 titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top);
4519 rotation = position === 'left' ? -_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H : _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H;
4520 }
4521 return {
4522 titleX,
4523 titleY,
4524 maxWidth,
4525 rotation
4526 };
4527 }
4528 class Scale extends Element {
4529 constructor(cfg){
4530 super();
4531 this.id = cfg.id;
4532 this.type = cfg.type;
4533 this.options = undefined;
4534 this.ctx = cfg.ctx;
4535 this.chart = cfg.chart;
4536 this.top = undefined;
4537 this.bottom = undefined;
4538 this.left = undefined;
4539 this.right = undefined;
4540 this.width = undefined;
4541 this.height = undefined;
4542 this._margins = {
4543 left: 0,
4544 right: 0,
4545 top: 0,
4546 bottom: 0
4547 };
4548 this.maxWidth = undefined;
4549 this.maxHeight = undefined;
4550 this.paddingTop = undefined;
4551 this.paddingBottom = undefined;
4552 this.paddingLeft = undefined;
4553 this.paddingRight = undefined;
4554 this.axis = undefined;
4555 this.labelRotation = undefined;
4556 this.min = undefined;
4557 this.max = undefined;
4558 this._range = undefined;
4559 this.ticks = [];
4560 this._gridLineItems = null;
4561 this._labelItems = null;
4562 this._labelSizes = null;
4563 this._length = 0;
4564 this._maxLength = 0;
4565 this._longestTextCache = {};
4566 this._startPixel = undefined;
4567 this._endPixel = undefined;
4568 this._reversePixels = false;
4569 this._userMax = undefined;
4570 this._userMin = undefined;
4571 this._suggestedMax = undefined;
4572 this._suggestedMin = undefined;
4573 this._ticksLength = 0;
4574 this._borderValue = 0;
4575 this._cache = {};
4576 this._dataLimitsCached = false;
4577 this.$context = undefined;
4578 }
4579 init(options) {
4580 this.options = options.setContext(this.getContext());
4581 this.axis = options.axis;
4582 this._userMin = this.parse(options.min);
4583 this._userMax = this.parse(options.max);
4584 this._suggestedMin = this.parse(options.suggestedMin);
4585 this._suggestedMax = this.parse(options.suggestedMax);
4586 }
4587 parse(raw, index) {
4588 return raw;
4589 }
4590 getUserBounds() {
4591 let { _userMin , _userMax , _suggestedMin , _suggestedMax } = this;
4592 _userMin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, Number.POSITIVE_INFINITY);
4593 _userMax = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, Number.NEGATIVE_INFINITY);
4594 _suggestedMin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMin, Number.POSITIVE_INFINITY);
4595 _suggestedMax = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMax, Number.NEGATIVE_INFINITY);
4596 return {
4597 min: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, _suggestedMin),
4598 max: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, _suggestedMax),
4599 minDefined: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMin),
4600 maxDefined: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMax)
4601 };
4602 }
4603 getMinMax(canStack) {
4604 let { min , max , minDefined , maxDefined } = this.getUserBounds();
4605 let range;
4606 if (minDefined && maxDefined) {
4607 return {
4608 min,
4609 max
4610 };
4611 }
4612 const metas = this.getMatchingVisibleMetas();
4613 for(let i = 0, ilen = metas.length; i < ilen; ++i){
4614 range = metas[i].controller.getMinMax(this, canStack);
4615 if (!minDefined) {
4616 min = Math.min(min, range.min);
4617 }
4618 if (!maxDefined) {
4619 max = Math.max(max, range.max);
4620 }
4621 }
4622 min = maxDefined && min > max ? max : min;
4623 max = minDefined && min > max ? min : max;
4624 return {
4625 min: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, min)),
4626 max: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, max))
4627 };
4628 }
4629 getPadding() {
4630 return {
4631 left: this.paddingLeft || 0,
4632 top: this.paddingTop || 0,
4633 right: this.paddingRight || 0,
4634 bottom: this.paddingBottom || 0
4635 };
4636 }
4637 getTicks() {
4638 return this.ticks;
4639 }
4640 getLabels() {
4641 const data = this.chart.data;
4642 return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];
4643 }
4644 getLabelItems(chartArea = this.chart.chartArea) {
4645 const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
4646 return items;
4647 }
4648 beforeLayout() {
4649 this._cache = {};
4650 this._dataLimitsCached = false;
4651 }
4652 beforeUpdate() {
4653 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeUpdate, [
4654 this
4655 ]);
4656 }
4657 update(maxWidth, maxHeight, margins) {
4658 const { beginAtZero , grace , ticks: tickOpts } = this.options;
4659 const sampleSize = tickOpts.sampleSize;
4660 this.beforeUpdate();
4661 this.maxWidth = maxWidth;
4662 this.maxHeight = maxHeight;
4663 this._margins = margins = Object.assign({
4664 left: 0,
4665 right: 0,
4666 top: 0,
4667 bottom: 0
4668 }, margins);
4669 this.ticks = null;
4670 this._labelSizes = null;
4671 this._gridLineItems = null;
4672 this._labelItems = null;
4673 this.beforeSetDimensions();
4674 this.setDimensions();
4675 this.afterSetDimensions();
4676 this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom;
4677 if (!this._dataLimitsCached) {
4678 this.beforeDataLimits();
4679 this.determineDataLimits();
4680 this.afterDataLimits();
4681 this._range = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.R)(this, grace, beginAtZero);
4682 this._dataLimitsCached = true;
4683 }
4684 this.beforeBuildTicks();
4685 this.ticks = this.buildTicks() || [];
4686 this.afterBuildTicks();
4687 const samplingEnabled = sampleSize < this.ticks.length;
4688 this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);
4689 this.configure();
4690 this.beforeCalculateLabelRotation();
4691 this.calculateLabelRotation();
4692 this.afterCalculateLabelRotation();
4693 if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {
4694 this.ticks = autoSkip(this, this.ticks);
4695 this._labelSizes = null;
4696 this.afterAutoSkip();
4697 }
4698 if (samplingEnabled) {
4699 this._convertTicksToLabels(this.ticks);
4700 }
4701 this.beforeFit();
4702 this.fit();
4703 this.afterFit();
4704 this.afterUpdate();
4705 }
4706 configure() {
4707 let reversePixels = this.options.reverse;
4708 let startPixel, endPixel;
4709 if (this.isHorizontal()) {
4710 startPixel = this.left;
4711 endPixel = this.right;
4712 } else {
4713 startPixel = this.top;
4714 endPixel = this.bottom;
4715 reversePixels = !reversePixels;
4716 }
4717 this._startPixel = startPixel;
4718 this._endPixel = endPixel;
4719 this._reversePixels = reversePixels;
4720 this._length = endPixel - startPixel;
4721 this._alignToPixels = this.options.alignToPixels;
4722 }
4723 afterUpdate() {
4724 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterUpdate, [
4725 this
4726 ]);
4727 }
4728 beforeSetDimensions() {
4729 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeSetDimensions, [
4730 this
4731 ]);
4732 }
4733 setDimensions() {
4734 if (this.isHorizontal()) {
4735 this.width = this.maxWidth;
4736 this.left = 0;
4737 this.right = this.width;
4738 } else {
4739 this.height = this.maxHeight;
4740 this.top = 0;
4741 this.bottom = this.height;
4742 }
4743 this.paddingLeft = 0;
4744 this.paddingTop = 0;
4745 this.paddingRight = 0;
4746 this.paddingBottom = 0;
4747 }
4748 afterSetDimensions() {
4749 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterSetDimensions, [
4750 this
4751 ]);
4752 }
4753 _callHooks(name) {
4754 this.chart.notifyPlugins(name, this.getContext());
4755 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options[name], [
4756 this
4757 ]);
4758 }
4759 beforeDataLimits() {
4760 this._callHooks('beforeDataLimits');
4761 }
4762 determineDataLimits() {}
4763 afterDataLimits() {
4764 this._callHooks('afterDataLimits');
4765 }
4766 beforeBuildTicks() {
4767 this._callHooks('beforeBuildTicks');
4768 }
4769 buildTicks() {
4770 return [];
4771 }
4772 afterBuildTicks() {
4773 this._callHooks('afterBuildTicks');
4774 }
4775 beforeTickToLabelConversion() {
4776 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeTickToLabelConversion, [
4777 this
4778 ]);
4779 }
4780 generateTickLabels(ticks) {
4781 const tickOpts = this.options.ticks;
4782 let i, ilen, tick;
4783 for(i = 0, ilen = ticks.length; i < ilen; i++){
4784 tick = ticks[i];
4785 tick.label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(tickOpts.callback, [
4786 tick.value,
4787 i,
4788 ticks
4789 ], this);
4790 }
4791 }
4792 afterTickToLabelConversion() {
4793 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterTickToLabelConversion, [
4794 this
4795 ]);
4796 }
4797 beforeCalculateLabelRotation() {
4798 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeCalculateLabelRotation, [
4799 this
4800 ]);
4801 }
4802 calculateLabelRotation() {
4803 const options = this.options;
4804 const tickOpts = options.ticks;
4805 const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit);
4806 const minRotation = tickOpts.minRotation || 0;
4807 const maxRotation = tickOpts.maxRotation;
4808 let labelRotation = minRotation;
4809 let tickWidth, maxHeight, maxLabelDiagonal;
4810 if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {
4811 this.labelRotation = minRotation;
4812 return;
4813 }
4814 const labelSizes = this._getLabelSizes();
4815 const maxLabelWidth = labelSizes.widest.width;
4816 const maxLabelHeight = labelSizes.highest.height;
4817 const maxWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(this.chart.width - maxLabelWidth, 0, this.maxWidth);
4818 tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);
4819 if (maxLabelWidth + 6 > tickWidth) {
4820 tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));
4821 maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);
4822 maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);
4823 labelRotation = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)(Math.min(Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxLabelHeight / maxLabelDiagonal, -1, 1))));
4824 labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));
4825 }
4826 this.labelRotation = labelRotation;
4827 }
4828 afterCalculateLabelRotation() {
4829 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterCalculateLabelRotation, [
4830 this
4831 ]);
4832 }
4833 afterAutoSkip() {}
4834 beforeFit() {
4835 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeFit, [
4836 this
4837 ]);
4838 }
4839 fit() {
4840 const minSize = {
4841 width: 0,
4842 height: 0
4843 };
4844 const { chart , options: { ticks: tickOpts , title: titleOpts , grid: gridOpts } } = this;
4845 const display = this._isVisible();
4846 const isHorizontal = this.isHorizontal();
4847 if (display) {
4848 const titleHeight = getTitleHeight(titleOpts, chart.options.font);
4849 if (isHorizontal) {
4850 minSize.width = this.maxWidth;
4851 minSize.height = getTickMarkLength(gridOpts) + titleHeight;
4852 } else {
4853 minSize.height = this.maxHeight;
4854 minSize.width = getTickMarkLength(gridOpts) + titleHeight;
4855 }
4856 if (tickOpts.display && this.ticks.length) {
4857 const { first , last , widest , highest } = this._getLabelSizes();
4858 const tickPadding = tickOpts.padding * 2;
4859 const angleRadians = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);
4860 const cos = Math.cos(angleRadians);
4861 const sin = Math.sin(angleRadians);
4862 if (isHorizontal) {
4863 const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;
4864 minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);
4865 } else {
4866 const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;
4867 minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);
4868 }
4869 this._calculatePadding(first, last, sin, cos);
4870 }
4871 }
4872 this._handleMargins();
4873 if (isHorizontal) {
4874 this.width = this._length = chart.width - this._margins.left - this._margins.right;
4875 this.height = minSize.height;
4876 } else {
4877 this.width = minSize.width;
4878 this.height = this._length = chart.height - this._margins.top - this._margins.bottom;
4879 }
4880 }
4881 _calculatePadding(first, last, sin, cos) {
4882 const { ticks: { align , padding } , position } = this.options;
4883 const isRotated = this.labelRotation !== 0;
4884 const labelsBelowTicks = position !== 'top' && this.axis === 'x';
4885 if (this.isHorizontal()) {
4886 const offsetLeft = this.getPixelForTick(0) - this.left;
4887 const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);
4888 let paddingLeft = 0;
4889 let paddingRight = 0;
4890 if (isRotated) {
4891 if (labelsBelowTicks) {
4892 paddingLeft = cos * first.width;
4893 paddingRight = sin * last.height;
4894 } else {
4895 paddingLeft = sin * first.height;
4896 paddingRight = cos * last.width;
4897 }
4898 } else if (align === 'start') {
4899 paddingRight = last.width;
4900 } else if (align === 'end') {
4901 paddingLeft = first.width;
4902 } else if (align !== 'inner') {
4903 paddingLeft = first.width / 2;
4904 paddingRight = last.width / 2;
4905 }
4906 this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);
4907 this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);
4908 } else {
4909 let paddingTop = last.height / 2;
4910 let paddingBottom = first.height / 2;
4911 if (align === 'start') {
4912 paddingTop = 0;
4913 paddingBottom = first.height;
4914 } else if (align === 'end') {
4915 paddingTop = last.height;
4916 paddingBottom = 0;
4917 }
4918 this.paddingTop = paddingTop + padding;
4919 this.paddingBottom = paddingBottom + padding;
4920 }
4921 }
4922 _handleMargins() {
4923 if (this._margins) {
4924 this._margins.left = Math.max(this.paddingLeft, this._margins.left);
4925 this._margins.top = Math.max(this.paddingTop, this._margins.top);
4926 this._margins.right = Math.max(this.paddingRight, this._margins.right);
4927 this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);
4928 }
4929 }
4930 afterFit() {
4931 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterFit, [
4932 this
4933 ]);
4934 }
4935 isHorizontal() {
4936 const { axis , position } = this.options;
4937 return position === 'top' || position === 'bottom' || axis === 'x';
4938 }
4939 isFullSize() {
4940 return this.options.fullSize;
4941 }
4942 _convertTicksToLabels(ticks) {
4943 this.beforeTickToLabelConversion();
4944 this.generateTickLabels(ticks);
4945 let i, ilen;
4946 for(i = 0, ilen = ticks.length; i < ilen; i++){
4947 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(ticks[i].label)) {
4948 ticks.splice(i, 1);
4949 ilen--;
4950 i--;
4951 }
4952 }
4953 this.afterTickToLabelConversion();
4954 }
4955 _getLabelSizes() {
4956 let labelSizes = this._labelSizes;
4957 if (!labelSizes) {
4958 const sampleSize = this.options.ticks.sampleSize;
4959 let ticks = this.ticks;
4960 if (sampleSize < ticks.length) {
4961 ticks = sample(ticks, sampleSize);
4962 }
4963 this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit);
4964 }
4965 return labelSizes;
4966 }
4967 _computeLabelSizes(ticks, length, maxTicksLimit) {
4968 const { ctx , _longestTextCache: caches } = this;
4969 const widths = [];
4970 const heights = [];
4971 const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit));
4972 let widestLabelSize = 0;
4973 let highestLabelSize = 0;
4974 let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel;
4975 for(i = 0; i < length; i += increment){
4976 label = ticks[i].label;
4977 tickFont = this._resolveTickFontOptions(i);
4978 ctx.font = fontString = tickFont.string;
4979 cache = caches[fontString] = caches[fontString] || {
4980 data: {},
4981 gc: []
4982 };
4983 lineHeight = tickFont.lineHeight;
4984 width = height = 0;
4985 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(label) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) {
4986 width = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, label);
4987 height = lineHeight;
4988 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) {
4989 for(j = 0, jlen = label.length; j < jlen; ++j){
4990 nestedLabel = label[j];
4991 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(nestedLabel) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(nestedLabel)) {
4992 width = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, nestedLabel);
4993 height += lineHeight;
4994 }
4995 }
4996 }
4997 widths.push(width);
4998 heights.push(height);
4999 widestLabelSize = Math.max(width, widestLabelSize);
5000 highestLabelSize = Math.max(height, highestLabelSize);
5001 }
5002 garbageCollect(caches, length);
5003 const widest = widths.indexOf(widestLabelSize);
5004 const highest = heights.indexOf(highestLabelSize);
5005 const valueAt = (idx)=>({
5006 width: widths[idx] || 0,
5007 height: heights[idx] || 0
5008 });
5009 return {
5010 first: valueAt(0),
5011 last: valueAt(length - 1),
5012 widest: valueAt(widest),
5013 highest: valueAt(highest),
5014 widths,
5015 heights
5016 };
5017 }
5018 getLabelForValue(value) {
5019 return value;
5020 }
5021 getPixelForValue(value, index) {
5022 return NaN;
5023 }
5024 getValueForPixel(pixel) {}
5025 getPixelForTick(index) {
5026 const ticks = this.ticks;
5027 if (index < 0 || index > ticks.length - 1) {
5028 return null;
5029 }
5030 return this.getPixelForValue(ticks[index].value);
5031 }
5032 getPixelForDecimal(decimal) {
5033 if (this._reversePixels) {
5034 decimal = 1 - decimal;
5035 }
5036 const pixel = this._startPixel + decimal * this._length;
5037 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.W)(this._alignToPixels ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(this.chart, pixel, 0) : pixel);
5038 }
5039 getDecimalForPixel(pixel) {
5040 const decimal = (pixel - this._startPixel) / this._length;
5041 return this._reversePixels ? 1 - decimal : decimal;
5042 }
5043 getBasePixel() {
5044 return this.getPixelForValue(this.getBaseValue());
5045 }
5046 getBaseValue() {
5047 const { min , max } = this;
5048 return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0;
5049 }
5050 getContext(index) {
5051 const ticks = this.ticks || [];
5052 if (index >= 0 && index < ticks.length) {
5053 const tick = ticks[index];
5054 return tick.$context || (tick.$context = createTickContext(this.getContext(), index, tick));
5055 }
5056 return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this));
5057 }
5058 _tickSize() {
5059 const optionTicks = this.options.ticks;
5060 const rot = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);
5061 const cos = Math.abs(Math.cos(rot));
5062 const sin = Math.abs(Math.sin(rot));
5063 const labelSizes = this._getLabelSizes();
5064 const padding = optionTicks.autoSkipPadding || 0;
5065 const w = labelSizes ? labelSizes.widest.width + padding : 0;
5066 const h = labelSizes ? labelSizes.highest.height + padding : 0;
5067 return this.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin;
5068 }
5069 _isVisible() {
5070 const display = this.options.display;
5071 if (display !== 'auto') {
5072 return !!display;
5073 }
5074 return this.getMatchingVisibleMetas().length > 0;
5075 }
5076 _computeGridLineItems(chartArea) {
5077 const axis = this.axis;
5078 const chart = this.chart;
5079 const options = this.options;
5080 const { grid , position , border } = options;
5081 const offset = grid.offset;
5082 const isHorizontal = this.isHorizontal();
5083 const ticks = this.ticks;
5084 const ticksLength = ticks.length + (offset ? 1 : 0);
5085 const tl = getTickMarkLength(grid);
5086 const items = [];
5087 const borderOpts = border.setContext(this.getContext());
5088 const axisWidth = borderOpts.display ? borderOpts.width : 0;
5089 const axisHalfWidth = axisWidth / 2;
5090 const alignBorderValue = function(pixel) {
5091 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, pixel, axisWidth);
5092 };
5093 let borderValue, i, lineValue, alignedLineValue;
5094 let tx1, ty1, tx2, ty2, x1, y1, x2, y2;
5095 if (position === 'top') {
5096 borderValue = alignBorderValue(this.bottom);
5097 ty1 = this.bottom - tl;
5098 ty2 = borderValue - axisHalfWidth;
5099 y1 = alignBorderValue(chartArea.top) + axisHalfWidth;
5100 y2 = chartArea.bottom;
5101 } else if (position === 'bottom') {
5102 borderValue = alignBorderValue(this.top);
5103 y1 = chartArea.top;
5104 y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;
5105 ty1 = borderValue + axisHalfWidth;
5106 ty2 = this.top + tl;
5107 } else if (position === 'left') {
5108 borderValue = alignBorderValue(this.right);
5109 tx1 = this.right - tl;
5110 tx2 = borderValue - axisHalfWidth;
5111 x1 = alignBorderValue(chartArea.left) + axisHalfWidth;
5112 x2 = chartArea.right;
5113 } else if (position === 'right') {
5114 borderValue = alignBorderValue(this.left);
5115 x1 = chartArea.left;
5116 x2 = alignBorderValue(chartArea.right) - axisHalfWidth;
5117 tx1 = borderValue + axisHalfWidth;
5118 tx2 = this.left + tl;
5119 } else if (axis === 'x') {
5120 if (position === 'center') {
5121 borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);
5122 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
5123 const positionAxisID = Object.keys(position)[0];
5124 const value = position[positionAxisID];
5125 borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
5126 }
5127 y1 = chartArea.top;
5128 y2 = chartArea.bottom;
5129 ty1 = borderValue + axisHalfWidth;
5130 ty2 = ty1 + tl;
5131 } else if (axis === 'y') {
5132 if (position === 'center') {
5133 borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);
5134 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
5135 const positionAxisID = Object.keys(position)[0];
5136 const value = position[positionAxisID];
5137 borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
5138 }
5139 tx1 = borderValue - axisHalfWidth;
5140 tx2 = tx1 - tl;
5141 x1 = chartArea.left;
5142 x2 = chartArea.right;
5143 }
5144 const limit = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.maxTicksLimit, ticksLength);
5145 const step = Math.max(1, Math.ceil(ticksLength / limit));
5146 for(i = 0; i < ticksLength; i += step){
5147 const context = this.getContext(i);
5148 const optsAtIndex = grid.setContext(context);
5149 const optsAtIndexBorder = border.setContext(context);
5150 const lineWidth = optsAtIndex.lineWidth;
5151 const lineColor = optsAtIndex.color;
5152 const borderDash = optsAtIndexBorder.dash || [];
5153 const borderDashOffset = optsAtIndexBorder.dashOffset;
5154 const tickWidth = optsAtIndex.tickWidth;
5155 const tickColor = optsAtIndex.tickColor;
5156 const tickBorderDash = optsAtIndex.tickBorderDash || [];
5157 const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;
5158 lineValue = getPixelForGridLine(this, i, offset);
5159 if (lineValue === undefined) {
5160 continue;
5161 }
5162 alignedLineValue = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, lineValue, lineWidth);
5163 if (isHorizontal) {
5164 tx1 = tx2 = x1 = x2 = alignedLineValue;
5165 } else {
5166 ty1 = ty2 = y1 = y2 = alignedLineValue;
5167 }
5168 items.push({
5169 tx1,
5170 ty1,
5171 tx2,
5172 ty2,
5173 x1,
5174 y1,
5175 x2,
5176 y2,
5177 width: lineWidth,
5178 color: lineColor,
5179 borderDash,
5180 borderDashOffset,
5181 tickWidth,
5182 tickColor,
5183 tickBorderDash,
5184 tickBorderDashOffset
5185 });
5186 }
5187 this._ticksLength = ticksLength;
5188 this._borderValue = borderValue;
5189 return items;
5190 }
5191 _computeLabelItems(chartArea) {
5192 const axis = this.axis;
5193 const options = this.options;
5194 const { position , ticks: optionTicks } = options;
5195 const isHorizontal = this.isHorizontal();
5196 const ticks = this.ticks;
5197 const { align , crossAlign , padding , mirror } = optionTicks;
5198 const tl = getTickMarkLength(options.grid);
5199 const tickAndPadding = tl + padding;
5200 const hTickAndPadding = mirror ? -padding : tickAndPadding;
5201 const rotation = -(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);
5202 const items = [];
5203 let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
5204 let textBaseline = 'middle';
5205 if (position === 'top') {
5206 y = this.bottom - hTickAndPadding;
5207 textAlign = this._getXAxisLabelAlignment();
5208 } else if (position === 'bottom') {
5209 y = this.top + hTickAndPadding;
5210 textAlign = this._getXAxisLabelAlignment();
5211 } else if (position === 'left') {
5212 const ret = this._getYAxisLabelAlignment(tl);
5213 textAlign = ret.textAlign;
5214 x = ret.x;
5215 } else if (position === 'right') {
5216 const ret = this._getYAxisLabelAlignment(tl);
5217 textAlign = ret.textAlign;
5218 x = ret.x;
5219 } else if (axis === 'x') {
5220 if (position === 'center') {
5221 y = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding;
5222 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
5223 const positionAxisID = Object.keys(position)[0];
5224 const value = position[positionAxisID];
5225 y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
5226 }
5227 textAlign = this._getXAxisLabelAlignment();
5228 } else if (axis === 'y') {
5229 if (position === 'center') {
5230 x = (chartArea.left + chartArea.right) / 2 - tickAndPadding;
5231 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
5232 const positionAxisID = Object.keys(position)[0];
5233 const value = position[positionAxisID];
5234 x = this.chart.scales[positionAxisID].getPixelForValue(value);
5235 }
5236 textAlign = this._getYAxisLabelAlignment(tl).textAlign;
5237 }
5238 if (axis === 'y') {
5239 if (align === 'start') {
5240 textBaseline = 'top';
5241 } else if (align === 'end') {
5242 textBaseline = 'bottom';
5243 }
5244 }
5245 const labelSizes = this._getLabelSizes();
5246 for(i = 0, ilen = ticks.length; i < ilen; ++i){
5247 tick = ticks[i];
5248 label = tick.label;
5249 const optsAtIndex = optionTicks.setContext(this.getContext(i));
5250 pixel = this.getPixelForTick(i) + optionTicks.labelOffset;
5251 font = this._resolveTickFontOptions(i);
5252 lineHeight = font.lineHeight;
5253 lineCount = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label.length : 1;
5254 const halfCount = lineCount / 2;
5255 const color = optsAtIndex.color;
5256 const strokeColor = optsAtIndex.textStrokeColor;
5257 const strokeWidth = optsAtIndex.textStrokeWidth;
5258 let tickTextAlign = textAlign;
5259 if (isHorizontal) {
5260 x = pixel;
5261 if (textAlign === 'inner') {
5262 if (i === ilen - 1) {
5263 tickTextAlign = !this.options.reverse ? 'right' : 'left';
5264 } else if (i === 0) {
5265 tickTextAlign = !this.options.reverse ? 'left' : 'right';
5266 } else {
5267 tickTextAlign = 'center';
5268 }
5269 }
5270 if (position === 'top') {
5271 if (crossAlign === 'near' || rotation !== 0) {
5272 textOffset = -lineCount * lineHeight + lineHeight / 2;
5273 } else if (crossAlign === 'center') {
5274 textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;
5275 } else {
5276 textOffset = -labelSizes.highest.height + lineHeight / 2;
5277 }
5278 } else {
5279 if (crossAlign === 'near' || rotation !== 0) {
5280 textOffset = lineHeight / 2;
5281 } else if (crossAlign === 'center') {
5282 textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;
5283 } else {
5284 textOffset = labelSizes.highest.height - lineCount * lineHeight;
5285 }
5286 }
5287 if (mirror) {
5288 textOffset *= -1;
5289 }
5290 if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) {
5291 x += lineHeight / 2 * Math.sin(rotation);
5292 }
5293 } else {
5294 y = pixel;
5295 textOffset = (1 - lineCount) * lineHeight / 2;
5296 }
5297 let backdrop;
5298 if (optsAtIndex.showLabelBackdrop) {
5299 const labelPadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding);
5300 const height = labelSizes.heights[i];
5301 const width = labelSizes.widths[i];
5302 let top = textOffset - labelPadding.top;
5303 let left = 0 - labelPadding.left;
5304 switch(textBaseline){
5305 case 'middle':
5306 top -= height / 2;
5307 break;
5308 case 'bottom':
5309 top -= height;
5310 break;
5311 }
5312 switch(textAlign){
5313 case 'center':
5314 left -= width / 2;
5315 break;
5316 case 'right':
5317 left -= width;
5318 break;
5319 case 'inner':
5320 if (i === ilen - 1) {
5321 left -= width;
5322 } else if (i > 0) {
5323 left -= width / 2;
5324 }
5325 break;
5326 }
5327 backdrop = {
5328 left,
5329 top,
5330 width: width + labelPadding.width,
5331 height: height + labelPadding.height,
5332 color: optsAtIndex.backdropColor
5333 };
5334 }
5335 items.push({
5336 label,
5337 font,
5338 textOffset,
5339 options: {
5340 rotation,
5341 color,
5342 strokeColor,
5343 strokeWidth,
5344 textAlign: tickTextAlign,
5345 textBaseline,
5346 translation: [
5347 x,
5348 y
5349 ],
5350 backdrop
5351 }
5352 });
5353 }
5354 return items;
5355 }
5356 _getXAxisLabelAlignment() {
5357 const { position , ticks } = this.options;
5358 const rotation = -(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation);
5359 if (rotation) {
5360 return position === 'top' ? 'left' : 'right';
5361 }
5362 let align = 'center';
5363 if (ticks.align === 'start') {
5364 align = 'left';
5365 } else if (ticks.align === 'end') {
5366 align = 'right';
5367 } else if (ticks.align === 'inner') {
5368 align = 'inner';
5369 }
5370 return align;
5371 }
5372 _getYAxisLabelAlignment(tl) {
5373 const { position , ticks: { crossAlign , mirror , padding } } = this.options;
5374 const labelSizes = this._getLabelSizes();
5375 const tickAndPadding = tl + padding;
5376 const widest = labelSizes.widest.width;
5377 let textAlign;
5378 let x;
5379 if (position === 'left') {
5380 if (mirror) {
5381 x = this.right + padding;
5382 if (crossAlign === 'near') {
5383 textAlign = 'left';
5384 } else if (crossAlign === 'center') {
5385 textAlign = 'center';
5386 x += widest / 2;
5387 } else {
5388 textAlign = 'right';
5389 x += widest;
5390 }
5391 } else {
5392 x = this.right - tickAndPadding;
5393 if (crossAlign === 'near') {
5394 textAlign = 'right';
5395 } else if (crossAlign === 'center') {
5396 textAlign = 'center';
5397 x -= widest / 2;
5398 } else {
5399 textAlign = 'left';
5400 x = this.left;
5401 }
5402 }
5403 } else if (position === 'right') {
5404 if (mirror) {
5405 x = this.left + padding;
5406 if (crossAlign === 'near') {
5407 textAlign = 'right';
5408 } else if (crossAlign === 'center') {
5409 textAlign = 'center';
5410 x -= widest / 2;
5411 } else {
5412 textAlign = 'left';
5413 x -= widest;
5414 }
5415 } else {
5416 x = this.left + tickAndPadding;
5417 if (crossAlign === 'near') {
5418 textAlign = 'left';
5419 } else if (crossAlign === 'center') {
5420 textAlign = 'center';
5421 x += widest / 2;
5422 } else {
5423 textAlign = 'right';
5424 x = this.right;
5425 }
5426 }
5427 } else {
5428 textAlign = 'right';
5429 }
5430 return {
5431 textAlign,
5432 x
5433 };
5434 }
5435 _computeLabelArea() {
5436 if (this.options.ticks.mirror) {
5437 return;
5438 }
5439 const chart = this.chart;
5440 const position = this.options.position;
5441 if (position === 'left' || position === 'right') {
5442 return {
5443 top: 0,
5444 left: this.left,
5445 bottom: chart.height,
5446 right: this.right
5447 };
5448 }
5449 if (position === 'top' || position === 'bottom') {
5450 return {
5451 top: this.top,
5452 left: 0,
5453 bottom: this.bottom,
5454 right: chart.width
5455 };
5456 }
5457 }
5458 drawBackground() {
5459 const { ctx , options: { backgroundColor } , left , top , width , height } = this;
5460 if (backgroundColor) {
5461 ctx.save();
5462 ctx.fillStyle = backgroundColor;
5463 ctx.fillRect(left, top, width, height);
5464 ctx.restore();
5465 }
5466 }
5467 getLineWidthForValue(value) {
5468 const grid = this.options.grid;
5469 if (!this._isVisible() || !grid.display) {
5470 return 0;
5471 }
5472 const ticks = this.ticks;
5473 const index = ticks.findIndex((t)=>t.value === value);
5474 if (index >= 0) {
5475 const opts = grid.setContext(this.getContext(index));
5476 return opts.lineWidth;
5477 }
5478 return 0;
5479 }
5480 drawGrid(chartArea) {
5481 const grid = this.options.grid;
5482 const ctx = this.ctx;
5483 const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));
5484 let i, ilen;
5485 const drawLine = (p1, p2, style)=>{
5486 if (!style.width || !style.color) {
5487 return;
5488 }
5489 ctx.save();
5490 ctx.lineWidth = style.width;
5491 ctx.strokeStyle = style.color;
5492 ctx.setLineDash(style.borderDash || []);
5493 ctx.lineDashOffset = style.borderDashOffset;
5494 ctx.beginPath();
5495 ctx.moveTo(p1.x, p1.y);
5496 ctx.lineTo(p2.x, p2.y);
5497 ctx.stroke();
5498 ctx.restore();
5499 };
5500 if (grid.display) {
5501 for(i = 0, ilen = items.length; i < ilen; ++i){
5502 const item = items[i];
5503 if (grid.drawOnChartArea) {
5504 drawLine({
5505 x: item.x1,
5506 y: item.y1
5507 }, {
5508 x: item.x2,
5509 y: item.y2
5510 }, item);
5511 }
5512 if (grid.drawTicks) {
5513 drawLine({
5514 x: item.tx1,
5515 y: item.ty1
5516 }, {
5517 x: item.tx2,
5518 y: item.ty2
5519 }, {
5520 color: item.tickColor,
5521 width: item.tickWidth,
5522 borderDash: item.tickBorderDash,
5523 borderDashOffset: item.tickBorderDashOffset
5524 });
5525 }
5526 }
5527 }
5528 }
5529 drawBorder() {
5530 const { chart , ctx , options: { border , grid } } = this;
5531 const borderOpts = border.setContext(this.getContext());
5532 const axisWidth = border.display ? borderOpts.width : 0;
5533 if (!axisWidth) {
5534 return;
5535 }
5536 const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;
5537 const borderValue = this._borderValue;
5538 let x1, x2, y1, y2;
5539 if (this.isHorizontal()) {
5540 x1 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.left, axisWidth) - axisWidth / 2;
5541 x2 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.right, lastLineWidth) + lastLineWidth / 2;
5542 y1 = y2 = borderValue;
5543 } else {
5544 y1 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.top, axisWidth) - axisWidth / 2;
5545 y2 = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;
5546 x1 = x2 = borderValue;
5547 }
5548 ctx.save();
5549 ctx.lineWidth = borderOpts.width;
5550 ctx.strokeStyle = borderOpts.color;
5551 ctx.beginPath();
5552 ctx.moveTo(x1, y1);
5553 ctx.lineTo(x2, y2);
5554 ctx.stroke();
5555 ctx.restore();
5556 }
5557 drawLabels(chartArea) {
5558 const optionTicks = this.options.ticks;
5559 if (!optionTicks.display) {
5560 return;
5561 }
5562 const ctx = this.ctx;
5563 const area = this._computeLabelArea();
5564 if (area) {
5565 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area);
5566 }
5567 const items = this.getLabelItems(chartArea);
5568 for (const item of items){
5569 const renderTextOptions = item.options;
5570 const tickFont = item.font;
5571 const label = item.label;
5572 const y = item.textOffset;
5573 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, label, 0, y, tickFont, renderTextOptions);
5574 }
5575 if (area) {
5576 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);
5577 }
5578 }
5579 drawTitle() {
5580 const { ctx , options: { position , title , reverse } } = this;
5581 if (!title.display) {
5582 return;
5583 }
5584 const font = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(title.font);
5585 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(title.padding);
5586 const align = title.align;
5587 let offset = font.lineHeight / 2;
5588 if (position === 'bottom' || position === 'center' || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) {
5589 offset += padding.bottom;
5590 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(title.text)) {
5591 offset += font.lineHeight * (title.text.length - 1);
5592 }
5593 } else {
5594 offset += padding.top;
5595 }
5596 const { titleX , titleY , maxWidth , rotation } = titleArgs(this, offset, position, align);
5597 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, title.text, 0, 0, font, {
5598 color: title.color,
5599 maxWidth,
5600 rotation,
5601 textAlign: titleAlign(align, position, reverse),
5602 textBaseline: 'middle',
5603 translation: [
5604 titleX,
5605 titleY
5606 ]
5607 });
5608 }
5609 draw(chartArea) {
5610 if (!this._isVisible()) {
5611 return;
5612 }
5613 this.drawBackground();
5614 this.drawGrid(chartArea);
5615 this.drawBorder();
5616 this.drawTitle();
5617 this.drawLabels(chartArea);
5618 }
5619 _layers() {
5620 const opts = this.options;
5621 const tz = opts.ticks && opts.ticks.z || 0;
5622 const gz = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.grid && opts.grid.z, -1);
5623 const bz = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.border && opts.border.z, 0);
5624 if (!this._isVisible() || this.draw !== Scale.prototype.draw) {
5625 return [
5626 {
5627 z: tz,
5628 draw: (chartArea)=>{
5629 this.draw(chartArea);
5630 }
5631 }
5632 ];
5633 }
5634 return [
5635 {
5636 z: gz,
5637 draw: (chartArea)=>{
5638 this.drawBackground();
5639 this.drawGrid(chartArea);
5640 this.drawTitle();
5641 }
5642 },
5643 {
5644 z: bz,
5645 draw: ()=>{
5646 this.drawBorder();
5647 }
5648 },
5649 {
5650 z: tz,
5651 draw: (chartArea)=>{
5652 this.drawLabels(chartArea);
5653 }
5654 }
5655 ];
5656 }
5657 getMatchingVisibleMetas(type) {
5658 const metas = this.chart.getSortedVisibleDatasetMetas();
5659 const axisID = this.axis + 'AxisID';
5660 const result = [];
5661 let i, ilen;
5662 for(i = 0, ilen = metas.length; i < ilen; ++i){
5663 const meta = metas[i];
5664 if (meta[axisID] === this.id && (!type || meta.type === type)) {
5665 result.push(meta);
5666 }
5667 }
5668 return result;
5669 }
5670 _resolveTickFontOptions(index) {
5671 const opts = this.options.ticks.setContext(this.getContext(index));
5672 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);
5673 }
5674 _maxDigits() {
5675 const fontSize = this._resolveTickFontOptions(0).lineHeight;
5676 return (this.isHorizontal() ? this.width : this.height) / fontSize;
5677 }
5678 }
5679
5680 class TypedRegistry {
5681 constructor(type, scope, override){
5682 this.type = type;
5683 this.scope = scope;
5684 this.override = override;
5685 this.items = Object.create(null);
5686 }
5687 isForType(type) {
5688 return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
5689 }
5690 register(item) {
5691 const proto = Object.getPrototypeOf(item);
5692 let parentScope;
5693 if (isIChartComponent(proto)) {
5694 parentScope = this.register(proto);
5695 }
5696 const items = this.items;
5697 const id = item.id;
5698 const scope = this.scope + '.' + id;
5699 if (!id) {
5700 throw new Error('class does not have id: ' + item);
5701 }
5702 if (id in items) {
5703 return scope;
5704 }
5705 items[id] = item;
5706 registerDefaults(item, scope, parentScope);
5707 if (this.override) {
5708 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.override(item.id, item.overrides);
5709 }
5710 return scope;
5711 }
5712 get(id) {
5713 return this.items[id];
5714 }
5715 unregister(item) {
5716 const items = this.items;
5717 const id = item.id;
5718 const scope = this.scope;
5719 if (id in items) {
5720 delete items[id];
5721 }
5722 if (scope && id in _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d[scope]) {
5723 delete _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d[scope][id];
5724 if (this.override) {
5725 delete _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[id];
5726 }
5727 }
5728 }
5729 }
5730 function registerDefaults(item, scope, parentScope) {
5731 const itemDefaults = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a4)(Object.create(null), [
5732 parentScope ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.get(parentScope) : {},
5733 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.get(scope),
5734 item.defaults
5735 ]);
5736 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.set(scope, itemDefaults);
5737 if (item.defaultRoutes) {
5738 routeDefaults(scope, item.defaultRoutes);
5739 }
5740 if (item.descriptors) {
5741 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.describe(scope, item.descriptors);
5742 }
5743 }
5744 function routeDefaults(scope, routes) {
5745 Object.keys(routes).forEach((property)=>{
5746 const propertyParts = property.split('.');
5747 const sourceName = propertyParts.pop();
5748 const sourceScope = [
5749 scope
5750 ].concat(propertyParts).join('.');
5751 const parts = routes[property].split('.');
5752 const targetName = parts.pop();
5753 const targetScope = parts.join('.');
5754 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.route(sourceScope, sourceName, targetScope, targetName);
5755 });
5756 }
5757 function isIChartComponent(proto) {
5758 return 'id' in proto && 'defaults' in proto;
5759 }
5760
5761 class Registry {
5762 constructor(){
5763 this.controllers = new TypedRegistry(DatasetController, 'datasets', true);
5764 this.elements = new TypedRegistry(Element, 'elements');
5765 this.plugins = new TypedRegistry(Object, 'plugins');
5766 this.scales = new TypedRegistry(Scale, 'scales');
5767 this._typedRegistries = [
5768 this.controllers,
5769 this.scales,
5770 this.elements
5771 ];
5772 }
5773 add(...args) {
5774 this._each('register', args);
5775 }
5776 remove(...args) {
5777 this._each('unregister', args);
5778 }
5779 addControllers(...args) {
5780 this._each('register', args, this.controllers);
5781 }
5782 addElements(...args) {
5783 this._each('register', args, this.elements);
5784 }
5785 addPlugins(...args) {
5786 this._each('register', args, this.plugins);
5787 }
5788 addScales(...args) {
5789 this._each('register', args, this.scales);
5790 }
5791 getController(id) {
5792 return this._get(id, this.controllers, 'controller');
5793 }
5794 getElement(id) {
5795 return this._get(id, this.elements, 'element');
5796 }
5797 getPlugin(id) {
5798 return this._get(id, this.plugins, 'plugin');
5799 }
5800 getScale(id) {
5801 return this._get(id, this.scales, 'scale');
5802 }
5803 removeControllers(...args) {
5804 this._each('unregister', args, this.controllers);
5805 }
5806 removeElements(...args) {
5807 this._each('unregister', args, this.elements);
5808 }
5809 removePlugins(...args) {
5810 this._each('unregister', args, this.plugins);
5811 }
5812 removeScales(...args) {
5813 this._each('unregister', args, this.scales);
5814 }
5815 _each(method, args, typedRegistry) {
5816 [
5817 ...args
5818 ].forEach((arg)=>{
5819 const reg = typedRegistry || this._getRegistryForType(arg);
5820 if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) {
5821 this._exec(method, reg, arg);
5822 } else {
5823 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(arg, (item)=>{
5824 const itemReg = typedRegistry || this._getRegistryForType(item);
5825 this._exec(method, itemReg, item);
5826 });
5827 }
5828 });
5829 }
5830 _exec(method, registry, component) {
5831 const camelMethod = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a5)(method);
5832 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['before' + camelMethod], [], component);
5833 registry[method](component);
5834 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['after' + camelMethod], [], component);
5835 }
5836 _getRegistryForType(type) {
5837 for(let i = 0; i < this._typedRegistries.length; i++){
5838 const reg = this._typedRegistries[i];
5839 if (reg.isForType(type)) {
5840 return reg;
5841 }
5842 }
5843 return this.plugins;
5844 }
5845 _get(id, typedRegistry, type) {
5846 const item = typedRegistry.get(id);
5847 if (item === undefined) {
5848 throw new Error('"' + id + '" is not a registered ' + type + '.');
5849 }
5850 return item;
5851 }
5852 }
5853 var registry = /* #__PURE__ */ new Registry();
5854
5855 class PluginService {
5856 constructor(){
5857 this._init = undefined;
5858 }
5859 notify(chart, hook, args, filter) {
5860 if (hook === 'beforeInit') {
5861 this._init = this._createDescriptors(chart, true);
5862 this._notify(this._init, chart, 'install');
5863 }
5864 if (this._init === undefined) {
5865 return;
5866 }
5867 const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);
5868 const result = this._notify(descriptors, chart, hook, args);
5869 if (hook === 'afterDestroy') {
5870 this._notify(descriptors, chart, 'stop');
5871 this._notify(this._init, chart, 'uninstall');
5872 this._init = undefined;
5873 }
5874 return result;
5875 }
5876 _notify(descriptors, chart, hook, args) {
5877 args = args || {};
5878 for (const descriptor of descriptors){
5879 const plugin = descriptor.plugin;
5880 const method = plugin[hook];
5881 const params = [
5882 chart,
5883 args,
5884 descriptor.options
5885 ];
5886 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(method, params, plugin) === false && args.cancelable) {
5887 return false;
5888 }
5889 }
5890 return true;
5891 }
5892 invalidate() {
5893 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(this._cache)) {
5894 this._oldCache = this._cache;
5895 this._cache = undefined;
5896 }
5897 }
5898 _descriptors(chart) {
5899 if (this._cache) {
5900 return this._cache;
5901 }
5902 const descriptors = this._cache = this._createDescriptors(chart);
5903 this._notifyStateChanges(chart);
5904 return descriptors;
5905 }
5906 _createDescriptors(chart, all) {
5907 const config = chart && chart.config;
5908 const options = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(config.options && config.options.plugins, {});
5909 const plugins = allPlugins(config);
5910 return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);
5911 }
5912 _notifyStateChanges(chart) {
5913 const previousDescriptors = this._oldCache || [];
5914 const descriptors = this._cache;
5915 const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.plugin.id === y.plugin.id));
5916 this._notify(diff(previousDescriptors, descriptors), chart, 'stop');
5917 this._notify(diff(descriptors, previousDescriptors), chart, 'start');
5918 }
5919 }
5920 function allPlugins(config) {
5921 const localIds = {};
5922 const plugins = [];
5923 const keys = Object.keys(registry.plugins.items);
5924 for(let i = 0; i < keys.length; i++){
5925 plugins.push(registry.getPlugin(keys[i]));
5926 }
5927 const local = config.plugins || [];
5928 for(let i = 0; i < local.length; i++){
5929 const plugin = local[i];
5930 if (plugins.indexOf(plugin) === -1) {
5931 plugins.push(plugin);
5932 localIds[plugin.id] = true;
5933 }
5934 }
5935 return {
5936 plugins,
5937 localIds
5938 };
5939 }
5940 function getOpts(options, all) {
5941 if (!all && options === false) {
5942 return null;
5943 }
5944 if (options === true) {
5945 return {};
5946 }
5947 return options;
5948 }
5949 function createDescriptors(chart, { plugins , localIds }, options, all) {
5950 const result = [];
5951 const context = chart.getContext();
5952 for (const plugin of plugins){
5953 const id = plugin.id;
5954 const opts = getOpts(options[id], all);
5955 if (opts === null) {
5956 continue;
5957 }
5958 result.push({
5959 plugin,
5960 options: pluginOpts(chart.config, {
5961 plugin,
5962 local: localIds[id]
5963 }, opts, context)
5964 });
5965 }
5966 return result;
5967 }
5968 function pluginOpts(config, { plugin , local }, opts, context) {
5969 const keys = config.pluginScopeKeys(plugin);
5970 const scopes = config.getOptionScopes(opts, keys);
5971 if (local && plugin.defaults) {
5972 scopes.push(plugin.defaults);
5973 }
5974 return config.createResolver(scopes, context, [
5975 ''
5976 ], {
5977 scriptable: false,
5978 indexable: false,
5979 allKeys: true
5980 });
5981 }
5982
5983 function getIndexAxis(type, options) {
5984 const datasetDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {};
5985 const datasetOptions = (options.datasets || {})[type] || {};
5986 return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';
5987 }
5988 function getAxisFromDefaultScaleID(id, indexAxis) {
5989 let axis = id;
5990 if (id === '_index_') {
5991 axis = indexAxis;
5992 } else if (id === '_value_') {
5993 axis = indexAxis === 'x' ? 'y' : 'x';
5994 }
5995 return axis;
5996 }
5997 function getDefaultScaleIDFromAxis(axis, indexAxis) {
5998 return axis === indexAxis ? '_index_' : '_value_';
5999 }
6000 function idMatchesAxis(id) {
6001 if (id === 'x' || id === 'y' || id === 'r') {
6002 return id;
6003 }
6004 }
6005 function axisFromPosition(position) {
6006 if (position === 'top' || position === 'bottom') {
6007 return 'x';
6008 }
6009 if (position === 'left' || position === 'right') {
6010 return 'y';
6011 }
6012 }
6013 function determineAxis(id, ...scaleOptions) {
6014 if (idMatchesAxis(id)) {
6015 return id;
6016 }
6017 for (const opts of scaleOptions){
6018 const axis = opts.axis || axisFromPosition(opts.position) || id.length > 1 && idMatchesAxis(id[0].toLowerCase());
6019 if (axis) {
6020 return axis;
6021 }
6022 }
6023 throw new Error(`Cannot determine type of '${id}' axis. Please provide 'axis' or 'position' option.`);
6024 }
6025 function getAxisFromDataset(id, axis, dataset) {
6026 if (dataset[axis + 'AxisID'] === id) {
6027 return {
6028 axis
6029 };
6030 }
6031 }
6032 function retrieveAxisFromDatasets(id, config) {
6033 if (config.data && config.data.datasets) {
6034 const boundDs = config.data.datasets.filter((d)=>d.xAxisID === id || d.yAxisID === id);
6035 if (boundDs.length) {
6036 return getAxisFromDataset(id, 'x', boundDs[0]) || getAxisFromDataset(id, 'y', boundDs[0]);
6037 }
6038 }
6039 return {};
6040 }
6041 function mergeScaleConfig(config, options) {
6042 const chartDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[config.type] || {
6043 scales: {}
6044 };
6045 const configScales = options.scales || {};
6046 const chartIndexAxis = getIndexAxis(config.type, options);
6047 const scales = Object.create(null);
6048 Object.keys(configScales).forEach((id)=>{
6049 const scaleConf = configScales[id];
6050 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(scaleConf)) {
6051 return console.error(`Invalid scale configuration for scale: ${id}`);
6052 }
6053 if (scaleConf._proxy) {
6054 return console.warn(`Ignoring resolver passed as options for scale: ${id}`);
6055 }
6056 const axis = determineAxis(id, scaleConf, retrieveAxisFromDatasets(id, config), _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scaleConf.type]);
6057 const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);
6058 const defaultScaleOptions = chartDefaults.scales || {};
6059 scales[id] = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(Object.create(null), [
6060 {
6061 axis
6062 },
6063 scaleConf,
6064 defaultScaleOptions[axis],
6065 defaultScaleOptions[defaultId]
6066 ]);
6067 });
6068 config.data.datasets.forEach((dataset)=>{
6069 const type = dataset.type || config.type;
6070 const indexAxis = dataset.indexAxis || getIndexAxis(type, options);
6071 const datasetDefaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {};
6072 const defaultScaleOptions = datasetDefaults.scales || {};
6073 Object.keys(defaultScaleOptions).forEach((defaultID)=>{
6074 const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);
6075 const id = dataset[axis + 'AxisID'] || axis;
6076 scales[id] = scales[id] || Object.create(null);
6077 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scales[id], [
6078 {
6079 axis
6080 },
6081 configScales[id],
6082 defaultScaleOptions[defaultID]
6083 ]);
6084 });
6085 });
6086 Object.keys(scales).forEach((key)=>{
6087 const scale = scales[key];
6088 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scale, [
6089 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scale.type],
6090 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.scale
6091 ]);
6092 });
6093 return scales;
6094 }
6095 function initOptions(config) {
6096 const options = config.options || (config.options = {});
6097 options.plugins = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.plugins, {});
6098 options.scales = mergeScaleConfig(config, options);
6099 }
6100 function initData(data) {
6101 data = data || {};
6102 data.datasets = data.datasets || [];
6103 data.labels = data.labels || [];
6104 return data;
6105 }
6106 function initConfig(config) {
6107 config = config || {};
6108 config.data = initData(config.data);
6109 initOptions(config);
6110 return config;
6111 }
6112 const keyCache = new Map();
6113 const keysCached = new Set();
6114 function cachedKeys(cacheKey, generate) {
6115 let keys = keyCache.get(cacheKey);
6116 if (!keys) {
6117 keys = generate();
6118 keyCache.set(cacheKey, keys);
6119 keysCached.add(keys);
6120 }
6121 return keys;
6122 }
6123 const addIfFound = (set, obj, key)=>{
6124 const opts = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, key);
6125 if (opts !== undefined) {
6126 set.add(opts);
6127 }
6128 };
6129 class Config {
6130 constructor(config){
6131 this._config = initConfig(config);
6132 this._scopeCache = new Map();
6133 this._resolverCache = new Map();
6134 }
6135 get platform() {
6136 return this._config.platform;
6137 }
6138 get type() {
6139 return this._config.type;
6140 }
6141 set type(type) {
6142 this._config.type = type;
6143 }
6144 get data() {
6145 return this._config.data;
6146 }
6147 set data(data) {
6148 this._config.data = initData(data);
6149 }
6150 get options() {
6151 return this._config.options;
6152 }
6153 set options(options) {
6154 this._config.options = options;
6155 }
6156 get plugins() {
6157 return this._config.plugins;
6158 }
6159 update() {
6160 const config = this._config;
6161 this.clearCache();
6162 initOptions(config);
6163 }
6164 clearCache() {
6165 this._scopeCache.clear();
6166 this._resolverCache.clear();
6167 }
6168 datasetScopeKeys(datasetType) {
6169 return cachedKeys(datasetType, ()=>[
6170 [
6171 `datasets.${datasetType}`,
6172 ''
6173 ]
6174 ]);
6175 }
6176 datasetAnimationScopeKeys(datasetType, transition) {
6177 return cachedKeys(`${datasetType}.transition.${transition}`, ()=>[
6178 [
6179 `datasets.${datasetType}.transitions.${transition}`,
6180 `transitions.${transition}`
6181 ],
6182 [
6183 `datasets.${datasetType}`,
6184 ''
6185 ]
6186 ]);
6187 }
6188 datasetElementScopeKeys(datasetType, elementType) {
6189 return cachedKeys(`${datasetType}-${elementType}`, ()=>[
6190 [
6191 `datasets.${datasetType}.elements.${elementType}`,
6192 `datasets.${datasetType}`,
6193 `elements.${elementType}`,
6194 ''
6195 ]
6196 ]);
6197 }
6198 pluginScopeKeys(plugin) {
6199 const id = plugin.id;
6200 const type = this.type;
6201 return cachedKeys(`${type}-plugin-${id}`, ()=>[
6202 [
6203 `plugins.${id}`,
6204 ...plugin.additionalOptionScopes || []
6205 ]
6206 ]);
6207 }
6208 _cachedScopes(mainScope, resetCache) {
6209 const _scopeCache = this._scopeCache;
6210 let cache = _scopeCache.get(mainScope);
6211 if (!cache || resetCache) {
6212 cache = new Map();
6213 _scopeCache.set(mainScope, cache);
6214 }
6215 return cache;
6216 }
6217 getOptionScopes(mainScope, keyLists, resetCache) {
6218 const { options , type } = this;
6219 const cache = this._cachedScopes(mainScope, resetCache);
6220 const cached = cache.get(keyLists);
6221 if (cached) {
6222 return cached;
6223 }
6224 const scopes = new Set();
6225 keyLists.forEach((keys)=>{
6226 if (mainScope) {
6227 scopes.add(mainScope);
6228 keys.forEach((key)=>addIfFound(scopes, mainScope, key));
6229 }
6230 keys.forEach((key)=>addIfFound(scopes, options, key));
6231 keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {}, key));
6232 keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d, key));
6233 keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a6, key));
6234 });
6235 const array = Array.from(scopes);
6236 if (array.length === 0) {
6237 array.push(Object.create(null));
6238 }
6239 if (keysCached.has(keyLists)) {
6240 cache.set(keyLists, array);
6241 }
6242 return array;
6243 }
6244 chartOptionScopes() {
6245 const { options , type } = this;
6246 return [
6247 options,
6248 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {},
6249 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {},
6250 {
6251 type
6252 },
6253 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d,
6254 _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a6
6255 ];
6256 }
6257 resolveNamedOptions(scopes, names, context, prefixes = [
6258 ''
6259 ]) {
6260 const result = {
6261 $shared: true
6262 };
6263 const { resolver , subPrefixes } = getResolver(this._resolverCache, scopes, prefixes);
6264 let options = resolver;
6265 if (needContext(resolver, names)) {
6266 result.$shared = false;
6267 context = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(context) ? context() : context;
6268 const subResolver = this.createResolver(scopes, context, subPrefixes);
6269 options = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, subResolver);
6270 }
6271 for (const prop of names){
6272 result[prop] = options[prop];
6273 }
6274 return result;
6275 }
6276 createResolver(scopes, context, prefixes = [
6277 ''
6278 ], descriptorDefaults) {
6279 const { resolver } = getResolver(this._resolverCache, scopes, prefixes);
6280 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(context) ? (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, undefined, descriptorDefaults) : resolver;
6281 }
6282 }
6283 function getResolver(resolverCache, scopes, prefixes) {
6284 let cache = resolverCache.get(scopes);
6285 if (!cache) {
6286 cache = new Map();
6287 resolverCache.set(scopes, cache);
6288 }
6289 const cacheKey = prefixes.join();
6290 let cached = cache.get(cacheKey);
6291 if (!cached) {
6292 const resolver = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a9)(scopes, prefixes);
6293 cached = {
6294 resolver,
6295 subPrefixes: prefixes.filter((p)=>!p.toLowerCase().includes('hover'))
6296 };
6297 cache.set(cacheKey, cached);
6298 }
6299 return cached;
6300 }
6301 const hasFunction = (value)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value) && Object.getOwnPropertyNames(value).some((key)=>(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value[key]));
6302 function needContext(proxy, names) {
6303 const { isScriptable , isIndexable } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aa)(proxy);
6304 for (const prop of names){
6305 const scriptable = isScriptable(prop);
6306 const indexable = isIndexable(prop);
6307 const value = (indexable || scriptable) && proxy[prop];
6308 if (scriptable && ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value) || hasFunction(value)) || indexable && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(value)) {
6309 return true;
6310 }
6311 }
6312 return false;
6313 }
6314
6315 var version = "4.5.1";
6316
6317 const KNOWN_POSITIONS = [
6318 'top',
6319 'bottom',
6320 'left',
6321 'right',
6322 'chartArea'
6323 ];
6324 function positionIsHorizontal(position, axis) {
6325 return position === 'top' || position === 'bottom' || KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x';
6326 }
6327 function compare2Level(l1, l2) {
6328 return function(a, b) {
6329 return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1];
6330 };
6331 }
6332 function onAnimationsComplete(context) {
6333 const chart = context.chart;
6334 const animationOptions = chart.options.animation;
6335 chart.notifyPlugins('afterRender');
6336 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onComplete, [
6337 context
6338 ], chart);
6339 }
6340 function onAnimationProgress(context) {
6341 const chart = context.chart;
6342 const animationOptions = chart.options.animation;
6343 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onProgress, [
6344 context
6345 ], chart);
6346 }
6347 function getCanvas(item) {
6348 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.M)() && typeof item === 'string') {
6349 item = document.getElementById(item);
6350 } else if (item && item.length) {
6351 item = item[0];
6352 }
6353 if (item && item.canvas) {
6354 item = item.canvas;
6355 }
6356 return item;
6357 }
6358 const instances = {};
6359 const getChart = (key)=>{
6360 const canvas = getCanvas(key);
6361 return Object.values(instances).filter((c)=>c.canvas === canvas).pop();
6362 };
6363 function moveNumericKeys(obj, start, move) {
6364 const keys = Object.keys(obj);
6365 for (const key of keys){
6366 const intKey = +key;
6367 if (intKey >= start) {
6368 const value = obj[key];
6369 delete obj[key];
6370 if (move > 0 || intKey > start) {
6371 obj[intKey + move] = value;
6372 }
6373 }
6374 }
6375 }
6376 function determineLastEvent(e, lastEvent, inChartArea, isClick) {
6377 if (!inChartArea || e.type === 'mouseout') {
6378 return null;
6379 }
6380 if (isClick) {
6381 return lastEvent;
6382 }
6383 return e;
6384 }
6385 class Chart {
6386 static defaults = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d;
6387 static instances = instances;
6388 static overrides = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a3;
6389 static registry = registry;
6390 static version = version;
6391 static getChart = getChart;
6392 static register(...items) {
6393 registry.add(...items);
6394 invalidatePlugins();
6395 }
6396 static unregister(...items) {
6397 registry.remove(...items);
6398 invalidatePlugins();
6399 }
6400 constructor(item, userConfig){
6401 const config = this.config = new Config(userConfig);
6402 const initialCanvas = getCanvas(item);
6403 const existingChart = getChart(initialCanvas);
6404 if (existingChart) {
6405 throw new Error('Canvas is already in use. Chart with ID \'' + existingChart.id + '\'' + ' must be destroyed before the canvas with ID \'' + existingChart.canvas.id + '\' can be reused.');
6406 }
6407 const options = config.createResolver(config.chartOptionScopes(), this.getContext());
6408 this.platform = new (config.platform || _detectPlatform(initialCanvas))();
6409 this.platform.updateConfig(config);
6410 const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);
6411 const canvas = context && context.canvas;
6412 const height = canvas && canvas.height;
6413 const width = canvas && canvas.width;
6414 this.id = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ac)();
6415 this.ctx = context;
6416 this.canvas = canvas;
6417 this.width = width;
6418 this.height = height;
6419 this._options = options;
6420 this._aspectRatio = this.aspectRatio;
6421 this._layers = [];
6422 this._metasets = [];
6423 this._stacks = undefined;
6424 this.boxes = [];
6425 this.currentDevicePixelRatio = undefined;
6426 this.chartArea = undefined;
6427 this._active = [];
6428 this._lastEvent = undefined;
6429 this._listeners = {};
6430 this._responsiveListeners = undefined;
6431 this._sortedMetasets = [];
6432 this.scales = {};
6433 this._plugins = new PluginService();
6434 this.$proxies = {};
6435 this._hiddenIndices = {};
6436 this.attached = false;
6437 this._animationsDisabled = undefined;
6438 this.$context = undefined;
6439 this._doResize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ad)((mode)=>this.update(mode), options.resizeDelay || 0);
6440 this._dataChanges = [];
6441 instances[this.id] = this;
6442 if (!context || !canvas) {
6443 console.error("Failed to create chart: can't acquire context from the given item");
6444 return;
6445 }
6446 animator.listen(this, 'complete', onAnimationsComplete);
6447 animator.listen(this, 'progress', onAnimationProgress);
6448 this._initialize();
6449 if (this.attached) {
6450 this.update();
6451 }
6452 }
6453 get aspectRatio() {
6454 const { options: { aspectRatio , maintainAspectRatio } , width , height , _aspectRatio } = this;
6455 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(aspectRatio)) {
6456 return aspectRatio;
6457 }
6458 if (maintainAspectRatio && _aspectRatio) {
6459 return _aspectRatio;
6460 }
6461 return height ? width / height : null;
6462 }
6463 get data() {
6464 return this.config.data;
6465 }
6466 set data(data) {
6467 this.config.data = data;
6468 }
6469 get options() {
6470 return this._options;
6471 }
6472 set options(options) {
6473 this.config.options = options;
6474 }
6475 get registry() {
6476 return registry;
6477 }
6478 _initialize() {
6479 this.notifyPlugins('beforeInit');
6480 if (this.options.responsive) {
6481 this.resize();
6482 } else {
6483 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, this.options.devicePixelRatio);
6484 }
6485 this.bindEvents();
6486 this.notifyPlugins('afterInit');
6487 return this;
6488 }
6489 clear() {
6490 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.af)(this.canvas, this.ctx);
6491 return this;
6492 }
6493 stop() {
6494 animator.stop(this);
6495 return this;
6496 }
6497 resize(width, height) {
6498 if (!animator.running(this)) {
6499 this._resize(width, height);
6500 } else {
6501 this._resizeBeforeDraw = {
6502 width,
6503 height
6504 };
6505 }
6506 }
6507 _resize(width, height) {
6508 const options = this.options;
6509 const canvas = this.canvas;
6510 const aspectRatio = options.maintainAspectRatio && this.aspectRatio;
6511 const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);
6512 const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();
6513 const mode = this.width ? 'resize' : 'attach';
6514 this.width = newSize.width;
6515 this.height = newSize.height;
6516 this._aspectRatio = this.aspectRatio;
6517 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, newRatio, true)) {
6518 return;
6519 }
6520 this.notifyPlugins('resize', {
6521 size: newSize
6522 });
6523 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onResize, [
6524 this,
6525 newSize
6526 ], this);
6527 if (this.attached) {
6528 if (this._doResize(mode)) {
6529 this.render();
6530 }
6531 }
6532 }
6533 ensureScalesHaveIDs() {
6534 const options = this.options;
6535 const scalesOptions = options.scales || {};
6536 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(scalesOptions, (axisOptions, axisID)=>{
6537 axisOptions.id = axisID;
6538 });
6539 }
6540 buildOrUpdateScales() {
6541 const options = this.options;
6542 const scaleOpts = options.scales;
6543 const scales = this.scales;
6544 const updated = Object.keys(scales).reduce((obj, id)=>{
6545 obj[id] = false;
6546 return obj;
6547 }, {});
6548 let items = [];
6549 if (scaleOpts) {
6550 items = items.concat(Object.keys(scaleOpts).map((id)=>{
6551 const scaleOptions = scaleOpts[id];
6552 const axis = determineAxis(id, scaleOptions);
6553 const isRadial = axis === 'r';
6554 const isHorizontal = axis === 'x';
6555 return {
6556 options: scaleOptions,
6557 dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left',
6558 dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear'
6559 };
6560 }));
6561 }
6562 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(items, (item)=>{
6563 const scaleOptions = item.options;
6564 const id = scaleOptions.id;
6565 const axis = determineAxis(id, scaleOptions);
6566 const scaleType = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(scaleOptions.type, item.dtype);
6567 if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {
6568 scaleOptions.position = item.dposition;
6569 }
6570 updated[id] = true;
6571 let scale = null;
6572 if (id in scales && scales[id].type === scaleType) {
6573 scale = scales[id];
6574 } else {
6575 const scaleClass = registry.getScale(scaleType);
6576 scale = new scaleClass({
6577 id,
6578 type: scaleType,
6579 ctx: this.ctx,
6580 chart: this
6581 });
6582 scales[scale.id] = scale;
6583 }
6584 scale.init(scaleOptions, options);
6585 });
6586 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(updated, (hasUpdated, id)=>{
6587 if (!hasUpdated) {
6588 delete scales[id];
6589 }
6590 });
6591 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(scales, (scale)=>{
6592 layouts.configure(this, scale, scale.options);
6593 layouts.addBox(this, scale);
6594 });
6595 }
6596 _updateMetasets() {
6597 const metasets = this._metasets;
6598 const numData = this.data.datasets.length;
6599 const numMeta = metasets.length;
6600 metasets.sort((a, b)=>a.index - b.index);
6601 if (numMeta > numData) {
6602 for(let i = numData; i < numMeta; ++i){
6603 this._destroyDatasetMeta(i);
6604 }
6605 metasets.splice(numData, numMeta - numData);
6606 }
6607 this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
6608 }
6609 _removeUnreferencedMetasets() {
6610 const { _metasets: metasets , data: { datasets } } = this;
6611 if (metasets.length > datasets.length) {
6612 delete this._stacks;
6613 }
6614 metasets.forEach((meta, index)=>{
6615 if (datasets.filter((x)=>x === meta._dataset).length === 0) {
6616 this._destroyDatasetMeta(index);
6617 }
6618 });
6619 }
6620 buildOrUpdateControllers() {
6621 const newControllers = [];
6622 const datasets = this.data.datasets;
6623 let i, ilen;
6624 this._removeUnreferencedMetasets();
6625 for(i = 0, ilen = datasets.length; i < ilen; i++){
6626 const dataset = datasets[i];
6627 let meta = this.getDatasetMeta(i);
6628 const type = dataset.type || this.config.type;
6629 if (meta.type && meta.type !== type) {
6630 this._destroyDatasetMeta(i);
6631 meta = this.getDatasetMeta(i);
6632 }
6633 meta.type = type;
6634 meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);
6635 meta.order = dataset.order || 0;
6636 meta.index = i;
6637 meta.label = '' + dataset.label;
6638 meta.visible = this.isDatasetVisible(i);
6639 if (meta.controller) {
6640 meta.controller.updateIndex(i);
6641 meta.controller.linkScales();
6642 } else {
6643 const ControllerClass = registry.getController(type);
6644 const { datasetElementType , dataElementType } = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type];
6645 Object.assign(ControllerClass, {
6646 dataElementType: registry.getElement(dataElementType),
6647 datasetElementType: datasetElementType && registry.getElement(datasetElementType)
6648 });
6649 meta.controller = new ControllerClass(this, i);
6650 newControllers.push(meta.controller);
6651 }
6652 }
6653 this._updateMetasets();
6654 return newControllers;
6655 }
6656 _resetElements() {
6657 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.data.datasets, (dataset, datasetIndex)=>{
6658 this.getDatasetMeta(datasetIndex).controller.reset();
6659 }, this);
6660 }
6661 reset() {
6662 this._resetElements();
6663 this.notifyPlugins('reset');
6664 }
6665 update(mode) {
6666 const config = this.config;
6667 config.update();
6668 const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());
6669 const animsDisabled = this._animationsDisabled = !options.animation;
6670 this._updateScales();
6671 this._checkEventBindings();
6672 this._updateHiddenIndices();
6673 this._plugins.invalidate();
6674 if (this.notifyPlugins('beforeUpdate', {
6675 mode,
6676 cancelable: true
6677 }) === false) {
6678 return;
6679 }
6680 const newControllers = this.buildOrUpdateControllers();
6681 this.notifyPlugins('beforeElementsUpdate');
6682 let minPadding = 0;
6683 for(let i = 0, ilen = this.data.datasets.length; i < ilen; i++){
6684 const { controller } = this.getDatasetMeta(i);
6685 const reset = !animsDisabled && newControllers.indexOf(controller) === -1;
6686 controller.buildOrUpdateElements(reset);
6687 minPadding = Math.max(+controller.getMaxOverflow(), minPadding);
6688 }
6689 minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;
6690 this._updateLayout(minPadding);
6691 if (!animsDisabled) {
6692 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(newControllers, (controller)=>{
6693 controller.reset();
6694 });
6695 }
6696 this._updateDatasets(mode);
6697 this.notifyPlugins('afterUpdate', {
6698 mode
6699 });
6700 this._layers.sort(compare2Level('z', '_idx'));
6701 const { _active , _lastEvent } = this;
6702 if (_lastEvent) {
6703 this._eventHandler(_lastEvent, true);
6704 } else if (_active.length) {
6705 this._updateHoverStyles(_active, _active, true);
6706 }
6707 this.render();
6708 }
6709 _updateScales() {
6710 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.scales, (scale)=>{
6711 layouts.removeBox(this, scale);
6712 });
6713 this.ensureScalesHaveIDs();
6714 this.buildOrUpdateScales();
6715 }
6716 _checkEventBindings() {
6717 const options = this.options;
6718 const existingEvents = new Set(Object.keys(this._listeners));
6719 const newEvents = new Set(options.events);
6720 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ag)(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {
6721 this.unbindEvents();
6722 this.bindEvents();
6723 }
6724 }
6725 _updateHiddenIndices() {
6726 const { _hiddenIndices } = this;
6727 const changes = this._getUniformDataChanges() || [];
6728 for (const { method , start , count } of changes){
6729 const move = method === '_removeElements' ? -count : count;
6730 moveNumericKeys(_hiddenIndices, start, move);
6731 }
6732 }
6733 _getUniformDataChanges() {
6734 const _dataChanges = this._dataChanges;
6735 if (!_dataChanges || !_dataChanges.length) {
6736 return;
6737 }
6738 this._dataChanges = [];
6739 const datasetCount = this.data.datasets.length;
6740 const makeSet = (idx)=>new Set(_dataChanges.filter((c)=>c[0] === idx).map((c, i)=>i + ',' + c.splice(1).join(',')));
6741 const changeSet = makeSet(0);
6742 for(let i = 1; i < datasetCount; i++){
6743 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ag)(changeSet, makeSet(i))) {
6744 return;
6745 }
6746 }
6747 return Array.from(changeSet).map((c)=>c.split(',')).map((a)=>({
6748 method: a[1],
6749 start: +a[2],
6750 count: +a[3]
6751 }));
6752 }
6753 _updateLayout(minPadding) {
6754 if (this.notifyPlugins('beforeLayout', {
6755 cancelable: true
6756 }) === false) {
6757 return;
6758 }
6759 layouts.update(this, this.width, this.height, minPadding);
6760 const area = this.chartArea;
6761 const noArea = area.width <= 0 || area.height <= 0;
6762 this._layers = [];
6763 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.boxes, (box)=>{
6764 if (noArea && box.position === 'chartArea') {
6765 return;
6766 }
6767 if (box.configure) {
6768 box.configure();
6769 }
6770 this._layers.push(...box._layers());
6771 }, this);
6772 this._layers.forEach((item, index)=>{
6773 item._idx = index;
6774 });
6775 this.notifyPlugins('afterLayout');
6776 }
6777 _updateDatasets(mode) {
6778 if (this.notifyPlugins('beforeDatasetsUpdate', {
6779 mode,
6780 cancelable: true
6781 }) === false) {
6782 return;
6783 }
6784 for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){
6785 this.getDatasetMeta(i).controller.configure();
6786 }
6787 for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){
6788 this._updateDataset(i, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a7)(mode) ? mode({
6789 datasetIndex: i
6790 }) : mode);
6791 }
6792 this.notifyPlugins('afterDatasetsUpdate', {
6793 mode
6794 });
6795 }
6796 _updateDataset(index, mode) {
6797 const meta = this.getDatasetMeta(index);
6798 const args = {
6799 meta,
6800 index,
6801 mode,
6802 cancelable: true
6803 };
6804 if (this.notifyPlugins('beforeDatasetUpdate', args) === false) {
6805 return;
6806 }
6807 meta.controller._update(mode);
6808 args.cancelable = false;
6809 this.notifyPlugins('afterDatasetUpdate', args);
6810 }
6811 render() {
6812 if (this.notifyPlugins('beforeRender', {
6813 cancelable: true
6814 }) === false) {
6815 return;
6816 }
6817 if (animator.has(this)) {
6818 if (this.attached && !animator.running(this)) {
6819 animator.start(this);
6820 }
6821 } else {
6822 this.draw();
6823 onAnimationsComplete({
6824 chart: this
6825 });
6826 }
6827 }
6828 draw() {
6829 let i;
6830 if (this._resizeBeforeDraw) {
6831 const { width , height } = this._resizeBeforeDraw;
6832 this._resizeBeforeDraw = null;
6833 this._resize(width, height);
6834 }
6835 this.clear();
6836 if (this.width <= 0 || this.height <= 0) {
6837 return;
6838 }
6839 if (this.notifyPlugins('beforeDraw', {
6840 cancelable: true
6841 }) === false) {
6842 return;
6843 }
6844 const layers = this._layers;
6845 for(i = 0; i < layers.length && layers[i].z <= 0; ++i){
6846 layers[i].draw(this.chartArea);
6847 }
6848 this._drawDatasets();
6849 for(; i < layers.length; ++i){
6850 layers[i].draw(this.chartArea);
6851 }
6852 this.notifyPlugins('afterDraw');
6853 }
6854 _getSortedDatasetMetas(filterVisible) {
6855 const metasets = this._sortedMetasets;
6856 const result = [];
6857 let i, ilen;
6858 for(i = 0, ilen = metasets.length; i < ilen; ++i){
6859 const meta = metasets[i];
6860 if (!filterVisible || meta.visible) {
6861 result.push(meta);
6862 }
6863 }
6864 return result;
6865 }
6866 getSortedVisibleDatasetMetas() {
6867 return this._getSortedDatasetMetas(true);
6868 }
6869 _drawDatasets() {
6870 if (this.notifyPlugins('beforeDatasetsDraw', {
6871 cancelable: true
6872 }) === false) {
6873 return;
6874 }
6875 const metasets = this.getSortedVisibleDatasetMetas();
6876 for(let i = metasets.length - 1; i >= 0; --i){
6877 this._drawDataset(metasets[i]);
6878 }
6879 this.notifyPlugins('afterDatasetsDraw');
6880 }
6881 _drawDataset(meta) {
6882 const ctx = this.ctx;
6883 const args = {
6884 meta,
6885 index: meta.index,
6886 cancelable: true
6887 };
6888 const clip = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ah)(this, meta);
6889 if (this.notifyPlugins('beforeDatasetDraw', args) === false) {
6890 return;
6891 }
6892 if (clip) {
6893 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, clip);
6894 }
6895 meta.controller.draw();
6896 if (clip) {
6897 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);
6898 }
6899 args.cancelable = false;
6900 this.notifyPlugins('afterDatasetDraw', args);
6901 }
6902 isPointInArea(point) {
6903 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(point, this.chartArea, this._minPadding);
6904 }
6905 getElementsAtEventForMode(e, mode, options, useFinalPosition) {
6906 const method = Interaction.modes[mode];
6907 if (typeof method === 'function') {
6908 return method(this, e, options, useFinalPosition);
6909 }
6910 return [];
6911 }
6912 getDatasetMeta(datasetIndex) {
6913 const dataset = this.data.datasets[datasetIndex];
6914 const metasets = this._metasets;
6915 let meta = metasets.filter((x)=>x && x._dataset === dataset).pop();
6916 if (!meta) {
6917 meta = {
6918 type: null,
6919 data: [],
6920 dataset: null,
6921 controller: null,
6922 hidden: null,
6923 xAxisID: null,
6924 yAxisID: null,
6925 order: dataset && dataset.order || 0,
6926 index: datasetIndex,
6927 _dataset: dataset,
6928 _parsed: [],
6929 _sorted: false
6930 };
6931 metasets.push(meta);
6932 }
6933 return meta;
6934 }
6935 getContext() {
6936 return this.$context || (this.$context = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(null, {
6937 chart: this,
6938 type: 'chart'
6939 }));
6940 }
6941 getVisibleDatasetCount() {
6942 return this.getSortedVisibleDatasetMetas().length;
6943 }
6944 isDatasetVisible(datasetIndex) {
6945 const dataset = this.data.datasets[datasetIndex];
6946 if (!dataset) {
6947 return false;
6948 }
6949 const meta = this.getDatasetMeta(datasetIndex);
6950 return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden;
6951 }
6952 setDatasetVisibility(datasetIndex, visible) {
6953 const meta = this.getDatasetMeta(datasetIndex);
6954 meta.hidden = !visible;
6955 }
6956 toggleDataVisibility(index) {
6957 this._hiddenIndices[index] = !this._hiddenIndices[index];
6958 }
6959 getDataVisibility(index) {
6960 return !this._hiddenIndices[index];
6961 }
6962 _updateVisibility(datasetIndex, dataIndex, visible) {
6963 const mode = visible ? 'show' : 'hide';
6964 const meta = this.getDatasetMeta(datasetIndex);
6965 const anims = meta.controller._resolveAnimations(undefined, mode);
6966 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.h)(dataIndex)) {
6967 meta.data[dataIndex].hidden = !visible;
6968 this.update();
6969 } else {
6970 this.setDatasetVisibility(datasetIndex, visible);
6971 anims.update(meta, {
6972 visible
6973 });
6974 this.update((ctx)=>ctx.datasetIndex === datasetIndex ? mode : undefined);
6975 }
6976 }
6977 hide(datasetIndex, dataIndex) {
6978 this._updateVisibility(datasetIndex, dataIndex, false);
6979 }
6980 show(datasetIndex, dataIndex) {
6981 this._updateVisibility(datasetIndex, dataIndex, true);
6982 }
6983 _destroyDatasetMeta(datasetIndex) {
6984 const meta = this._metasets[datasetIndex];
6985 if (meta && meta.controller) {
6986 meta.controller._destroy();
6987 }
6988 delete this._metasets[datasetIndex];
6989 }
6990 _stop() {
6991 let i, ilen;
6992 this.stop();
6993 animator.remove(this);
6994 for(i = 0, ilen = this.data.datasets.length; i < ilen; ++i){
6995 this._destroyDatasetMeta(i);
6996 }
6997 }
6998 destroy() {
6999 this.notifyPlugins('beforeDestroy');
7000 const { canvas , ctx } = this;
7001 this._stop();
7002 this.config.clearCache();
7003 if (canvas) {
7004 this.unbindEvents();
7005 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.af)(canvas, ctx);
7006 this.platform.releaseContext(ctx);
7007 this.canvas = null;
7008 this.ctx = null;
7009 }
7010 delete instances[this.id];
7011 this.notifyPlugins('afterDestroy');
7012 }
7013 toBase64Image(...args) {
7014 return this.canvas.toDataURL(...args);
7015 }
7016 bindEvents() {
7017 this.bindUserEvents();
7018 if (this.options.responsive) {
7019 this.bindResponsiveEvents();
7020 } else {
7021 this.attached = true;
7022 }
7023 }
7024 bindUserEvents() {
7025 const listeners = this._listeners;
7026 const platform = this.platform;
7027 const _add = (type, listener)=>{
7028 platform.addEventListener(this, type, listener);
7029 listeners[type] = listener;
7030 };
7031 const listener = (e, x, y)=>{
7032 e.offsetX = x;
7033 e.offsetY = y;
7034 this._eventHandler(e);
7035 };
7036 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.options.events, (type)=>_add(type, listener));
7037 }
7038 bindResponsiveEvents() {
7039 if (!this._responsiveListeners) {
7040 this._responsiveListeners = {};
7041 }
7042 const listeners = this._responsiveListeners;
7043 const platform = this.platform;
7044 const _add = (type, listener)=>{
7045 platform.addEventListener(this, type, listener);
7046 listeners[type] = listener;
7047 };
7048 const _remove = (type, listener)=>{
7049 if (listeners[type]) {
7050 platform.removeEventListener(this, type, listener);
7051 delete listeners[type];
7052 }
7053 };
7054 const listener = (width, height)=>{
7055 if (this.canvas) {
7056 this.resize(width, height);
7057 }
7058 };
7059 let detached;
7060 const attached = ()=>{
7061 _remove('attach', attached);
7062 this.attached = true;
7063 this.resize();
7064 _add('resize', listener);
7065 _add('detach', detached);
7066 };
7067 detached = ()=>{
7068 this.attached = false;
7069 _remove('resize', listener);
7070 this._stop();
7071 this._resize(0, 0);
7072 _add('attach', attached);
7073 };
7074 if (platform.isAttached(this.canvas)) {
7075 attached();
7076 } else {
7077 detached();
7078 }
7079 }
7080 unbindEvents() {
7081 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._listeners, (listener, type)=>{
7082 this.platform.removeEventListener(this, type, listener);
7083 });
7084 this._listeners = {};
7085 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._responsiveListeners, (listener, type)=>{
7086 this.platform.removeEventListener(this, type, listener);
7087 });
7088 this._responsiveListeners = undefined;
7089 }
7090 updateHoverStyle(items, mode, enabled) {
7091 const prefix = enabled ? 'set' : 'remove';
7092 let meta, item, i, ilen;
7093 if (mode === 'dataset') {
7094 meta = this.getDatasetMeta(items[0].datasetIndex);
7095 meta.controller['_' + prefix + 'DatasetHoverStyle']();
7096 }
7097 for(i = 0, ilen = items.length; i < ilen; ++i){
7098 item = items[i];
7099 const controller = item && this.getDatasetMeta(item.datasetIndex).controller;
7100 if (controller) {
7101 controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index);
7102 }
7103 }
7104 }
7105 getActiveElements() {
7106 return this._active || [];
7107 }
7108 setActiveElements(activeElements) {
7109 const lastActive = this._active || [];
7110 const active = activeElements.map(({ datasetIndex , index })=>{
7111 const meta = this.getDatasetMeta(datasetIndex);
7112 if (!meta) {
7113 throw new Error('No dataset found at index ' + datasetIndex);
7114 }
7115 return {
7116 datasetIndex,
7117 element: meta.data[index],
7118 index
7119 };
7120 });
7121 const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive);
7122 if (changed) {
7123 this._active = active;
7124 this._lastEvent = null;
7125 this._updateHoverStyles(active, lastActive);
7126 }
7127 }
7128 notifyPlugins(hook, args, filter) {
7129 return this._plugins.notify(this, hook, args, filter);
7130 }
7131 isPluginEnabled(pluginId) {
7132 return this._plugins._cache.filter((p)=>p.plugin.id === pluginId).length === 1;
7133 }
7134 _updateHoverStyles(active, lastActive, replay) {
7135 const hoverOptions = this.options.hover;
7136 const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.datasetIndex === y.datasetIndex && x.index === y.index));
7137 const deactivated = diff(lastActive, active);
7138 const activated = replay ? active : diff(active, lastActive);
7139 if (deactivated.length) {
7140 this.updateHoverStyle(deactivated, hoverOptions.mode, false);
7141 }
7142 if (activated.length && hoverOptions.mode) {
7143 this.updateHoverStyle(activated, hoverOptions.mode, true);
7144 }
7145 }
7146 _eventHandler(e, replay) {
7147 const args = {
7148 event: e,
7149 replay,
7150 cancelable: true,
7151 inChartArea: this.isPointInArea(e)
7152 };
7153 const eventFilter = (plugin)=>(plugin.options.events || this.options.events).includes(e.native.type);
7154 if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) {
7155 return;
7156 }
7157 const changed = this._handleEvent(e, replay, args.inChartArea);
7158 args.cancelable = false;
7159 this.notifyPlugins('afterEvent', args, eventFilter);
7160 if (changed || args.changed) {
7161 this.render();
7162 }
7163 return this;
7164 }
7165 _handleEvent(e, replay, inChartArea) {
7166 const { _active: lastActive = [] , options } = this;
7167 const useFinalPosition = replay;
7168 const active = this._getActiveElements(e, lastActive, inChartArea, useFinalPosition);
7169 const isClick = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aj)(e);
7170 const lastEvent = determineLastEvent(e, this._lastEvent, inChartArea, isClick);
7171 if (inChartArea) {
7172 this._lastEvent = null;
7173 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onHover, [
7174 e,
7175 active,
7176 this
7177 ], this);
7178 if (isClick) {
7179 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onClick, [
7180 e,
7181 active,
7182 this
7183 ], this);
7184 }
7185 }
7186 const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive);
7187 if (changed || replay) {
7188 this._active = active;
7189 this._updateHoverStyles(active, lastActive, replay);
7190 }
7191 this._lastEvent = lastEvent;
7192 return changed;
7193 }
7194 _getActiveElements(e, lastActive, inChartArea, useFinalPosition) {
7195 if (e.type === 'mouseout') {
7196 return [];
7197 }
7198 if (!inChartArea) {
7199 return lastActive;
7200 }
7201 const hoverOptions = this.options.hover;
7202 return this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);
7203 }
7204 }
7205 function invalidatePlugins() {
7206 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(Chart.instances, (chart)=>chart._plugins.invalidate());
7207 }
7208
7209 function clipSelf(ctx, element, endAngle) {
7210 const { startAngle , x , y , outerRadius , innerRadius , options } = element;
7211 const { borderWidth , borderJoinStyle } = options;
7212 const outerAngleClip = Math.min(borderWidth / outerRadius, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));
7213 ctx.beginPath();
7214 ctx.arc(x, y, outerRadius - borderWidth / 2, startAngle + outerAngleClip / 2, endAngle - outerAngleClip / 2);
7215 if (innerRadius > 0) {
7216 const innerAngleClip = Math.min(borderWidth / innerRadius, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));
7217 ctx.arc(x, y, innerRadius + borderWidth / 2, endAngle - innerAngleClip / 2, startAngle + innerAngleClip / 2, true);
7218 } else {
7219 const clipWidth = Math.min(borderWidth / 2, outerRadius * (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(startAngle - endAngle));
7220 if (borderJoinStyle === 'round') {
7221 ctx.arc(x, y, clipWidth, endAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2, startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2, true);
7222 } else if (borderJoinStyle === 'bevel') {
7223 const r = 2 * clipWidth * clipWidth;
7224 const endX = -r * Math.cos(endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + x;
7225 const endY = -r * Math.sin(endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + y;
7226 const startX = r * Math.cos(startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + x;
7227 const startY = r * Math.sin(startAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / 2) + y;
7228 ctx.lineTo(endX, endY);
7229 ctx.lineTo(startX, startY);
7230 }
7231 }
7232 ctx.closePath();
7233 ctx.moveTo(0, 0);
7234 ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
7235 ctx.clip('evenodd');
7236 }
7237 function clipArc(ctx, element, endAngle) {
7238 const { startAngle , pixelMargin , x , y , outerRadius , innerRadius } = element;
7239 let angleMargin = pixelMargin / outerRadius;
7240 // Draw an inner border by clipping the arc and drawing a double-width border
7241 // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
7242 ctx.beginPath();
7243 ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);
7244 if (innerRadius > pixelMargin) {
7245 angleMargin = pixelMargin / innerRadius;
7246 ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);
7247 } else {
7248 ctx.arc(x, y, pixelMargin, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);
7249 }
7250 ctx.closePath();
7251 ctx.clip();
7252 }
7253 function toRadiusCorners(value) {
7254 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.am)(value, [
7255 'outerStart',
7256 'outerEnd',
7257 'innerStart',
7258 'innerEnd'
7259 ]);
7260 }
7261 /**
7262 * Parse border radius from the provided options
7263 */ function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) {
7264 const o = toRadiusCorners(arc.options.borderRadius);
7265 const halfThickness = (outerRadius - innerRadius) / 2;
7266 const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2);
7267 // Outer limits are complicated. We want to compute the available angular distance at
7268 // a radius of outerRadius - borderRadius because for small angular distances, this term limits.
7269 // We compute at r = outerRadius - borderRadius because this circle defines the center of the border corners.
7270 //
7271 // If the borderRadius is large, that value can become negative.
7272 // This causes the outer borders to lose their radius entirely, which is rather unexpected. To solve that, if borderRadius > outerRadius
7273 // we know that the thickness term will dominate and compute the limits at that point
7274 const computeOuterLimit = (val)=>{
7275 const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2;
7276 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(val, 0, Math.min(halfThickness, outerArcLimit));
7277 };
7278 return {
7279 outerStart: computeOuterLimit(o.outerStart),
7280 outerEnd: computeOuterLimit(o.outerEnd),
7281 innerStart: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerStart, 0, innerLimit),
7282 innerEnd: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerEnd, 0, innerLimit)
7283 };
7284 }
7285 /**
7286 * Convert (r, 𝜃) to (x, y)
7287 */ function rThetaToXY(r, theta, x, y) {
7288 return {
7289 x: x + r * Math.cos(theta),
7290 y: y + r * Math.sin(theta)
7291 };
7292 }
7293 /**
7294 * Path the arc, respecting border radius by separating into left and right halves.
7295 *
7296 * Start End
7297 *
7298 * 1--->a--->2 Outer
7299 * / \
7300 * 8 3
7301 * | |
7302 * | |
7303 * 7 4
7304 * \ /
7305 * 6<---b<---5 Inner
7306 */ function pathArc(ctx, element, offset, spacing, end, circular) {
7307 const { x , y , startAngle: start , pixelMargin , innerRadius: innerR } = element;
7308 const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0);
7309 const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0;
7310 let spacingOffset = 0;
7311 const alpha = end - start;
7312 if (spacing) {
7313 // When spacing is present, it is the same for all items
7314 // So we adjust the start and end angle of the arc such that
7315 // the distance is the same as it would be without the spacing
7316 const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;
7317 const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;
7318 const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;
7319 const adjustedAngle = avNogSpacingRadius !== 0 ? alpha * avNogSpacingRadius / (avNogSpacingRadius + spacing) : alpha;
7320 spacingOffset = (alpha - adjustedAngle) / 2;
7321 }
7322 const beta = Math.max(0.001, alpha * outerRadius - offset / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P) / outerRadius;
7323 const angleOffset = (alpha - beta) / 2;
7324 const startAngle = start + angleOffset + spacingOffset;
7325 const endAngle = end - angleOffset - spacingOffset;
7326 const { outerStart , outerEnd , innerStart , innerEnd } = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle);
7327 const outerStartAdjustedRadius = outerRadius - outerStart;
7328 const outerEndAdjustedRadius = outerRadius - outerEnd;
7329 const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius;
7330 const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius;
7331 const innerStartAdjustedRadius = innerRadius + innerStart;
7332 const innerEndAdjustedRadius = innerRadius + innerEnd;
7333 const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius;
7334 const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius;
7335 ctx.beginPath();
7336 if (circular) {
7337 // The first arc segments from point 1 to point a to point 2
7338 const outerMidAdjustedAngle = (outerStartAdjustedAngle + outerEndAdjustedAngle) / 2;
7339 ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerMidAdjustedAngle);
7340 ctx.arc(x, y, outerRadius, outerMidAdjustedAngle, outerEndAdjustedAngle);
7341 // The corner segment from point 2 to point 3
7342 if (outerEnd > 0) {
7343 const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y);
7344 ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);
7345 }
7346 // The line from point 3 to point 4
7347 const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y);
7348 ctx.lineTo(p4.x, p4.y);
7349 // The corner segment from point 4 to point 5
7350 if (innerEnd > 0) {
7351 const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y);
7352 ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, innerEndAdjustedAngle + Math.PI);
7353 }
7354 // The inner arc from point 5 to point b to point 6
7355 const innerMidAdjustedAngle = (endAngle - innerEnd / innerRadius + (startAngle + innerStart / innerRadius)) / 2;
7356 ctx.arc(x, y, innerRadius, endAngle - innerEnd / innerRadius, innerMidAdjustedAngle, true);
7357 ctx.arc(x, y, innerRadius, innerMidAdjustedAngle, startAngle + innerStart / innerRadius, true);
7358 // The corner segment from point 6 to point 7
7359 if (innerStart > 0) {
7360 const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y);
7361 ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H);
7362 }
7363 // The line from point 7 to point 8
7364 const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y);
7365 ctx.lineTo(p8.x, p8.y);
7366 // The corner segment from point 8 to point 1
7367 if (outerStart > 0) {
7368 const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y);
7369 ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H, outerStartAdjustedAngle);
7370 }
7371 } else {
7372 ctx.moveTo(x, y);
7373 const outerStartX = Math.cos(outerStartAdjustedAngle) * outerRadius + x;
7374 const outerStartY = Math.sin(outerStartAdjustedAngle) * outerRadius + y;
7375 ctx.lineTo(outerStartX, outerStartY);
7376 const outerEndX = Math.cos(outerEndAdjustedAngle) * outerRadius + x;
7377 const outerEndY = Math.sin(outerEndAdjustedAngle) * outerRadius + y;
7378 ctx.lineTo(outerEndX, outerEndY);
7379 }
7380 ctx.closePath();
7381 }
7382 function drawArc(ctx, element, offset, spacing, circular) {
7383 const { fullCircles , startAngle , circumference } = element;
7384 let endAngle = element.endAngle;
7385 if (fullCircles) {
7386 pathArc(ctx, element, offset, spacing, endAngle, circular);
7387 for(let i = 0; i < fullCircles; ++i){
7388 ctx.fill();
7389 }
7390 if (!isNaN(circumference)) {
7391 endAngle = startAngle + (circumference % _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);
7392 }
7393 }
7394 pathArc(ctx, element, offset, spacing, endAngle, circular);
7395 ctx.fill();
7396 return endAngle;
7397 }
7398 function drawBorder(ctx, element, offset, spacing, circular) {
7399 const { fullCircles , startAngle , circumference , options } = element;
7400 const { borderWidth , borderJoinStyle , borderDash , borderDashOffset , borderRadius } = options;
7401 const inner = options.borderAlign === 'inner';
7402 if (!borderWidth) {
7403 return;
7404 }
7405 ctx.setLineDash(borderDash || []);
7406 ctx.lineDashOffset = borderDashOffset;
7407 if (inner) {
7408 ctx.lineWidth = borderWidth * 2;
7409 ctx.lineJoin = borderJoinStyle || 'round';
7410 } else {
7411 ctx.lineWidth = borderWidth;
7412 ctx.lineJoin = borderJoinStyle || 'bevel';
7413 }
7414 let endAngle = element.endAngle;
7415 if (fullCircles) {
7416 pathArc(ctx, element, offset, spacing, endAngle, circular);
7417 for(let i = 0; i < fullCircles; ++i){
7418 ctx.stroke();
7419 }
7420 if (!isNaN(circumference)) {
7421 endAngle = startAngle + (circumference % _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);
7422 }
7423 }
7424 if (inner) {
7425 clipArc(ctx, element, endAngle);
7426 }
7427 if (options.selfJoin && endAngle - startAngle >= _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P && borderRadius === 0 && borderJoinStyle !== 'miter') {
7428 clipSelf(ctx, element, endAngle);
7429 }
7430 if (!fullCircles) {
7431 pathArc(ctx, element, offset, spacing, endAngle, circular);
7432 ctx.stroke();
7433 }
7434 }
7435 class ArcElement extends Element {
7436 static id = 'arc';
7437 static defaults = {
7438 borderAlign: 'center',
7439 borderColor: '#fff',
7440 borderDash: [],
7441 borderDashOffset: 0,
7442 borderJoinStyle: undefined,
7443 borderRadius: 0,
7444 borderWidth: 2,
7445 offset: 0,
7446 spacing: 0,
7447 angle: undefined,
7448 circular: true,
7449 selfJoin: false
7450 };
7451 static defaultRoutes = {
7452 backgroundColor: 'backgroundColor'
7453 };
7454 static descriptors = {
7455 _scriptable: true,
7456 _indexable: (name)=>name !== 'borderDash'
7457 };
7458 circumference;
7459 endAngle;
7460 fullCircles;
7461 innerRadius;
7462 outerRadius;
7463 pixelMargin;
7464 startAngle;
7465 constructor(cfg){
7466 super();
7467 this.options = undefined;
7468 this.circumference = undefined;
7469 this.startAngle = undefined;
7470 this.endAngle = undefined;
7471 this.innerRadius = undefined;
7472 this.outerRadius = undefined;
7473 this.pixelMargin = 0;
7474 this.fullCircles = 0;
7475 if (cfg) {
7476 Object.assign(this, cfg);
7477 }
7478 }
7479 inRange(chartX, chartY, useFinalPosition) {
7480 const point = this.getProps([
7481 'x',
7482 'y'
7483 ], useFinalPosition);
7484 const { angle , distance } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.D)(point, {
7485 x: chartX,
7486 y: chartY
7487 });
7488 const { startAngle , endAngle , innerRadius , outerRadius , circumference } = this.getProps([
7489 'startAngle',
7490 'endAngle',
7491 'innerRadius',
7492 'outerRadius',
7493 'circumference'
7494 ], useFinalPosition);
7495 const rAdjust = (this.options.spacing + this.options.borderWidth) / 2;
7496 const _circumference = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(circumference, endAngle - startAngle);
7497 const nonZeroBetween = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle) && startAngle !== endAngle;
7498 const betweenAngles = _circumference >= _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T || nonZeroBetween;
7499 const withinRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(distance, innerRadius + rAdjust, outerRadius + rAdjust);
7500 return betweenAngles && withinRadius;
7501 }
7502 getCenterPoint(useFinalPosition) {
7503 const { x , y , startAngle , endAngle , innerRadius , outerRadius } = this.getProps([
7504 'x',
7505 'y',
7506 'startAngle',
7507 'endAngle',
7508 'innerRadius',
7509 'outerRadius'
7510 ], useFinalPosition);
7511 const { offset , spacing } = this.options;
7512 const halfAngle = (startAngle + endAngle) / 2;
7513 const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2;
7514 return {
7515 x: x + Math.cos(halfAngle) * halfRadius,
7516 y: y + Math.sin(halfAngle) * halfRadius
7517 };
7518 }
7519 tooltipPosition(useFinalPosition) {
7520 return this.getCenterPoint(useFinalPosition);
7521 }
7522 draw(ctx) {
7523 const { options , circumference } = this;
7524 const offset = (options.offset || 0) / 4;
7525 const spacing = (options.spacing || 0) / 2;
7526 const circular = options.circular;
7527 this.pixelMargin = options.borderAlign === 'inner' ? 0.33 : 0;
7528 this.fullCircles = circumference > _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T ? Math.floor(circumference / _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T) : 0;
7529 if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {
7530 return;
7531 }
7532 ctx.save();
7533 const halfAngle = (this.startAngle + this.endAngle) / 2;
7534 ctx.translate(Math.cos(halfAngle) * offset, Math.sin(halfAngle) * offset);
7535 const fix = 1 - Math.sin(Math.min(_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P, circumference || 0));
7536 const radiusOffset = offset * fix;
7537 ctx.fillStyle = options.backgroundColor;
7538 ctx.strokeStyle = options.borderColor;
7539 drawArc(ctx, this, radiusOffset, spacing, circular);
7540 drawBorder(ctx, this, radiusOffset, spacing, circular);
7541 ctx.restore();
7542 }
7543 }
7544
7545 function setStyle(ctx, options, style = options) {
7546 ctx.lineCap = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderCapStyle, options.borderCapStyle);
7547 ctx.setLineDash((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDash, options.borderDash));
7548 ctx.lineDashOffset = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDashOffset, options.borderDashOffset);
7549 ctx.lineJoin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderJoinStyle, options.borderJoinStyle);
7550 ctx.lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderWidth, options.borderWidth);
7551 ctx.strokeStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderColor, options.borderColor);
7552 }
7553 function lineTo(ctx, previous, target) {
7554 ctx.lineTo(target.x, target.y);
7555 }
7556 function getLineMethod(options) {
7557 if (options.stepped) {
7558 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.at;
7559 }
7560 if (options.tension || options.cubicInterpolationMode === 'monotone') {
7561 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.au;
7562 }
7563 return lineTo;
7564 }
7565 function pathVars(points, segment, params = {}) {
7566 const count = points.length;
7567 const { start: paramsStart = 0 , end: paramsEnd = count - 1 } = params;
7568 const { start: segmentStart , end: segmentEnd } = segment;
7569 const start = Math.max(paramsStart, segmentStart);
7570 const end = Math.min(paramsEnd, segmentEnd);
7571 const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd;
7572 return {
7573 count,
7574 start,
7575 loop: segment.loop,
7576 ilen: end < start && !outside ? count + end - start : end - start
7577 };
7578 }
7579 function pathSegment(ctx, line, segment, params) {
7580 const { points , options } = line;
7581 const { count , start , loop , ilen } = pathVars(points, segment, params);
7582 const lineMethod = getLineMethod(options);
7583 let { move =true , reverse } = params || {};
7584 let i, point, prev;
7585 for(i = 0; i <= ilen; ++i){
7586 point = points[(start + (reverse ? ilen - i : i)) % count];
7587 if (point.skip) {
7588 continue;
7589 } else if (move) {
7590 ctx.moveTo(point.x, point.y);
7591 move = false;
7592 } else {
7593 lineMethod(ctx, prev, point, reverse, options.stepped);
7594 }
7595 prev = point;
7596 }
7597 if (loop) {
7598 point = points[(start + (reverse ? ilen : 0)) % count];
7599 lineMethod(ctx, prev, point, reverse, options.stepped);
7600 }
7601 return !!loop;
7602 }
7603 function fastPathSegment(ctx, line, segment, params) {
7604 const points = line.points;
7605 const { count , start , ilen } = pathVars(points, segment, params);
7606 const { move =true , reverse } = params || {};
7607 let avgX = 0;
7608 let countX = 0;
7609 let i, point, prevX, minY, maxY, lastY;
7610 const pointIndex = (index)=>(start + (reverse ? ilen - index : index)) % count;
7611 const drawX = ()=>{
7612 if (minY !== maxY) {
7613 ctx.lineTo(avgX, maxY);
7614 ctx.lineTo(avgX, minY);
7615 ctx.lineTo(avgX, lastY);
7616 }
7617 };
7618 if (move) {
7619 point = points[pointIndex(0)];
7620 ctx.moveTo(point.x, point.y);
7621 }
7622 for(i = 0; i <= ilen; ++i){
7623 point = points[pointIndex(i)];
7624 if (point.skip) {
7625 continue;
7626 }
7627 const x = point.x;
7628 const y = point.y;
7629 const truncX = x | 0;
7630 if (truncX === prevX) {
7631 if (y < minY) {
7632 minY = y;
7633 } else if (y > maxY) {
7634 maxY = y;
7635 }
7636 avgX = (countX * avgX + x) / ++countX;
7637 } else {
7638 drawX();
7639 ctx.lineTo(x, y);
7640 prevX = truncX;
7641 countX = 0;
7642 minY = maxY = y;
7643 }
7644 lastY = y;
7645 }
7646 drawX();
7647 }
7648 function _getSegmentMethod(line) {
7649 const opts = line.options;
7650 const borderDash = opts.borderDash && opts.borderDash.length;
7651 const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash;
7652 return useFastPath ? fastPathSegment : pathSegment;
7653 }
7654 function _getInterpolationMethod(options) {
7655 if (options.stepped) {
7656 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aq;
7657 }
7658 if (options.tension || options.cubicInterpolationMode === 'monotone') {
7659 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ar;
7660 }
7661 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.as;
7662 }
7663 function strokePathWithCache(ctx, line, start, count) {
7664 let path = line._path;
7665 if (!path) {
7666 path = line._path = new Path2D();
7667 if (line.path(path, start, count)) {
7668 path.closePath();
7669 }
7670 }
7671 setStyle(ctx, line.options);
7672 ctx.stroke(path);
7673 }
7674 function strokePathDirect(ctx, line, start, count) {
7675 const { segments , options } = line;
7676 const segmentMethod = _getSegmentMethod(line);
7677 for (const segment of segments){
7678 setStyle(ctx, options, segment.style);
7679 ctx.beginPath();
7680 if (segmentMethod(ctx, line, segment, {
7681 start,
7682 end: start + count - 1
7683 })) {
7684 ctx.closePath();
7685 }
7686 ctx.stroke();
7687 }
7688 }
7689 const usePath2D = typeof Path2D === 'function';
7690 function draw(ctx, line, start, count) {
7691 if (usePath2D && !line.options.segment) {
7692 strokePathWithCache(ctx, line, start, count);
7693 } else {
7694 strokePathDirect(ctx, line, start, count);
7695 }
7696 }
7697 class LineElement extends Element {
7698 static id = 'line';
7699 static defaults = {
7700 borderCapStyle: 'butt',
7701 borderDash: [],
7702 borderDashOffset: 0,
7703 borderJoinStyle: 'miter',
7704 borderWidth: 3,
7705 capBezierPoints: true,
7706 cubicInterpolationMode: 'default',
7707 fill: false,
7708 spanGaps: false,
7709 stepped: false,
7710 tension: 0
7711 };
7712 static defaultRoutes = {
7713 backgroundColor: 'backgroundColor',
7714 borderColor: 'borderColor'
7715 };
7716 static descriptors = {
7717 _scriptable: true,
7718 _indexable: (name)=>name !== 'borderDash' && name !== 'fill'
7719 };
7720 constructor(cfg){
7721 super();
7722 this.animated = true;
7723 this.options = undefined;
7724 this._chart = undefined;
7725 this._loop = undefined;
7726 this._fullLoop = undefined;
7727 this._path = undefined;
7728 this._points = undefined;
7729 this._segments = undefined;
7730 this._decimated = false;
7731 this._pointsUpdated = false;
7732 this._datasetIndex = undefined;
7733 if (cfg) {
7734 Object.assign(this, cfg);
7735 }
7736 }
7737 updateControlPoints(chartArea, indexAxis) {
7738 const options = this.options;
7739 if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) {
7740 const loop = options.spanGaps ? this._loop : this._fullLoop;
7741 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.an)(this._points, options, chartArea, loop, indexAxis);
7742 this._pointsUpdated = true;
7743 }
7744 }
7745 set points(points) {
7746 this._points = points;
7747 delete this._segments;
7748 delete this._path;
7749 this._pointsUpdated = false;
7750 }
7751 get points() {
7752 return this._points;
7753 }
7754 get segments() {
7755 return this._segments || (this._segments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ao)(this, this.options.segment));
7756 }
7757 first() {
7758 const segments = this.segments;
7759 const points = this.points;
7760 return segments.length && points[segments[0].start];
7761 }
7762 last() {
7763 const segments = this.segments;
7764 const points = this.points;
7765 const count = segments.length;
7766 return count && points[segments[count - 1].end];
7767 }
7768 interpolate(point, property) {
7769 const options = this.options;
7770 const value = point[property];
7771 const points = this.points;
7772 const segments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ap)(this, {
7773 property,
7774 start: value,
7775 end: value
7776 });
7777 if (!segments.length) {
7778 return;
7779 }
7780 const result = [];
7781 const _interpolate = _getInterpolationMethod(options);
7782 let i, ilen;
7783 for(i = 0, ilen = segments.length; i < ilen; ++i){
7784 const { start , end } = segments[i];
7785 const p1 = points[start];
7786 const p2 = points[end];
7787 if (p1 === p2) {
7788 result.push(p1);
7789 continue;
7790 }
7791 const t = Math.abs((value - p1[property]) / (p2[property] - p1[property]));
7792 const interpolated = _interpolate(p1, p2, t, options.stepped);
7793 interpolated[property] = point[property];
7794 result.push(interpolated);
7795 }
7796 return result.length === 1 ? result[0] : result;
7797 }
7798 pathSegment(ctx, segment, params) {
7799 const segmentMethod = _getSegmentMethod(this);
7800 return segmentMethod(ctx, this, segment, params);
7801 }
7802 path(ctx, start, count) {
7803 const segments = this.segments;
7804 const segmentMethod = _getSegmentMethod(this);
7805 let loop = this._loop;
7806 start = start || 0;
7807 count = count || this.points.length - start;
7808 for (const segment of segments){
7809 loop &= segmentMethod(ctx, this, segment, {
7810 start,
7811 end: start + count - 1
7812 });
7813 }
7814 return !!loop;
7815 }
7816 draw(ctx, chartArea, start, count) {
7817 const options = this.options || {};
7818 const points = this.points || [];
7819 if (points.length && options.borderWidth) {
7820 ctx.save();
7821 draw(ctx, this, start, count);
7822 ctx.restore();
7823 }
7824 if (this.animated) {
7825 this._pointsUpdated = false;
7826 this._path = undefined;
7827 }
7828 }
7829 }
7830
7831 function inRange$1(el, pos, axis, useFinalPosition) {
7832 const options = el.options;
7833 const { [axis]: value } = el.getProps([
7834 axis
7835 ], useFinalPosition);
7836 return Math.abs(pos - value) < options.radius + options.hitRadius;
7837 }
7838 class PointElement extends Element {
7839 static id = 'point';
7840 parsed;
7841 skip;
7842 stop;
7843 /**
7844 * @type {any}
7845 */ static defaults = {
7846 borderWidth: 1,
7847 hitRadius: 1,
7848 hoverBorderWidth: 1,
7849 hoverRadius: 4,
7850 pointStyle: 'circle',
7851 radius: 3,
7852 rotation: 0
7853 };
7854 /**
7855 * @type {any}
7856 */ static defaultRoutes = {
7857 backgroundColor: 'backgroundColor',
7858 borderColor: 'borderColor'
7859 };
7860 constructor(cfg){
7861 super();
7862 this.options = undefined;
7863 this.parsed = undefined;
7864 this.skip = undefined;
7865 this.stop = undefined;
7866 if (cfg) {
7867 Object.assign(this, cfg);
7868 }
7869 }
7870 inRange(mouseX, mouseY, useFinalPosition) {
7871 const options = this.options;
7872 const { x , y } = this.getProps([
7873 'x',
7874 'y'
7875 ], useFinalPosition);
7876 return Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2) < Math.pow(options.hitRadius + options.radius, 2);
7877 }
7878 inXRange(mouseX, useFinalPosition) {
7879 return inRange$1(this, mouseX, 'x', useFinalPosition);
7880 }
7881 inYRange(mouseY, useFinalPosition) {
7882 return inRange$1(this, mouseY, 'y', useFinalPosition);
7883 }
7884 getCenterPoint(useFinalPosition) {
7885 const { x , y } = this.getProps([
7886 'x',
7887 'y'
7888 ], useFinalPosition);
7889 return {
7890 x,
7891 y
7892 };
7893 }
7894 size(options) {
7895 options = options || this.options || {};
7896 let radius = options.radius || 0;
7897 radius = Math.max(radius, radius && options.hoverRadius || 0);
7898 const borderWidth = radius && options.borderWidth || 0;
7899 return (radius + borderWidth) * 2;
7900 }
7901 draw(ctx, area) {
7902 const options = this.options;
7903 if (this.skip || options.radius < 0.1 || !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)(this, area, this.size(options) / 2)) {
7904 return;
7905 }
7906 ctx.strokeStyle = options.borderColor;
7907 ctx.lineWidth = options.borderWidth;
7908 ctx.fillStyle = options.backgroundColor;
7909 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, options, this.x, this.y);
7910 }
7911 getRange() {
7912 const options = this.options || {};
7913 // @ts-expect-error Fallbacks should never be hit in practice
7914 return options.radius + options.hitRadius;
7915 }
7916 }
7917
7918 function getBarBounds(bar, useFinalPosition) {
7919 const { x , y , base , width , height } = bar.getProps([
7920 'x',
7921 'y',
7922 'base',
7923 'width',
7924 'height'
7925 ], useFinalPosition);
7926 let left, right, top, bottom, half;
7927 if (bar.horizontal) {
7928 half = height / 2;
7929 left = Math.min(x, base);
7930 right = Math.max(x, base);
7931 top = y - half;
7932 bottom = y + half;
7933 } else {
7934 half = width / 2;
7935 left = x - half;
7936 right = x + half;
7937 top = Math.min(y, base);
7938 bottom = Math.max(y, base);
7939 }
7940 return {
7941 left,
7942 top,
7943 right,
7944 bottom
7945 };
7946 }
7947 function skipOrLimit(skip, value, min, max) {
7948 return skip ? 0 : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(value, min, max);
7949 }
7950 function parseBorderWidth(bar, maxW, maxH) {
7951 const value = bar.options.borderWidth;
7952 const skip = bar.borderSkipped;
7953 const o = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ax)(value);
7954 return {
7955 t: skipOrLimit(skip.top, o.top, 0, maxH),
7956 r: skipOrLimit(skip.right, o.right, 0, maxW),
7957 b: skipOrLimit(skip.bottom, o.bottom, 0, maxH),
7958 l: skipOrLimit(skip.left, o.left, 0, maxW)
7959 };
7960 }
7961 function parseBorderRadius(bar, maxW, maxH) {
7962 const { enableBorderRadius } = bar.getProps([
7963 'enableBorderRadius'
7964 ]);
7965 const value = bar.options.borderRadius;
7966 const o = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(value);
7967 const maxR = Math.min(maxW, maxH);
7968 const skip = bar.borderSkipped;
7969 const enableBorder = enableBorderRadius || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(value);
7970 return {
7971 topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR),
7972 topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR),
7973 bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR),
7974 bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR)
7975 };
7976 }
7977 function boundingRects(bar) {
7978 const bounds = getBarBounds(bar);
7979 const width = bounds.right - bounds.left;
7980 const height = bounds.bottom - bounds.top;
7981 const border = parseBorderWidth(bar, width / 2, height / 2);
7982 const radius = parseBorderRadius(bar, width / 2, height / 2);
7983 return {
7984 outer: {
7985 x: bounds.left,
7986 y: bounds.top,
7987 w: width,
7988 h: height,
7989 radius
7990 },
7991 inner: {
7992 x: bounds.left + border.l,
7993 y: bounds.top + border.t,
7994 w: width - border.l - border.r,
7995 h: height - border.t - border.b,
7996 radius: {
7997 topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
7998 topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
7999 bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),
8000 bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r))
8001 }
8002 }
8003 };
8004 }
8005 function inRange(bar, x, y, useFinalPosition) {
8006 const skipX = x === null;
8007 const skipY = y === null;
8008 const skipBoth = skipX && skipY;
8009 const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);
8010 return bounds && (skipX || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, bounds.left, bounds.right)) && (skipY || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, bounds.top, bounds.bottom));
8011 }
8012 function hasRadius(radius) {
8013 return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
8014 }
8015 function addNormalRectPath(ctx, rect) {
8016 ctx.rect(rect.x, rect.y, rect.w, rect.h);
8017 }
8018 function inflateRect(rect, amount, refRect = {}) {
8019 const x = rect.x !== refRect.x ? -amount : 0;
8020 const y = rect.y !== refRect.y ? -amount : 0;
8021 const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x;
8022 const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y;
8023 return {
8024 x: rect.x + x,
8025 y: rect.y + y,
8026 w: rect.w + w,
8027 h: rect.h + h,
8028 radius: rect.radius
8029 };
8030 }
8031 class BarElement extends Element {
8032 static id = 'bar';
8033 static defaults = {
8034 borderSkipped: 'start',
8035 borderWidth: 0,
8036 borderRadius: 0,
8037 inflateAmount: 'auto',
8038 pointStyle: undefined
8039 };
8040 static defaultRoutes = {
8041 backgroundColor: 'backgroundColor',
8042 borderColor: 'borderColor'
8043 };
8044 constructor(cfg){
8045 super();
8046 this.options = undefined;
8047 this.horizontal = undefined;
8048 this.base = undefined;
8049 this.width = undefined;
8050 this.height = undefined;
8051 this.inflateAmount = undefined;
8052 if (cfg) {
8053 Object.assign(this, cfg);
8054 }
8055 }
8056 draw(ctx) {
8057 const { inflateAmount , options: { borderColor , backgroundColor } } = this;
8058 const { inner , outer } = boundingRects(this);
8059 const addRectPath = hasRadius(outer.radius) ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw : addNormalRectPath;
8060 ctx.save();
8061 if (outer.w !== inner.w || outer.h !== inner.h) {
8062 ctx.beginPath();
8063 addRectPath(ctx, inflateRect(outer, inflateAmount, inner));
8064 ctx.clip();
8065 addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));
8066 ctx.fillStyle = borderColor;
8067 ctx.fill('evenodd');
8068 }
8069 ctx.beginPath();
8070 addRectPath(ctx, inflateRect(inner, inflateAmount));
8071 ctx.fillStyle = backgroundColor;
8072 ctx.fill();
8073 ctx.restore();
8074 }
8075 inRange(mouseX, mouseY, useFinalPosition) {
8076 return inRange(this, mouseX, mouseY, useFinalPosition);
8077 }
8078 inXRange(mouseX, useFinalPosition) {
8079 return inRange(this, mouseX, null, useFinalPosition);
8080 }
8081 inYRange(mouseY, useFinalPosition) {
8082 return inRange(this, null, mouseY, useFinalPosition);
8083 }
8084 getCenterPoint(useFinalPosition) {
8085 const { x , y , base , horizontal } = this.getProps([
8086 'x',
8087 'y',
8088 'base',
8089 'horizontal'
8090 ], useFinalPosition);
8091 return {
8092 x: horizontal ? (x + base) / 2 : x,
8093 y: horizontal ? y : (y + base) / 2
8094 };
8095 }
8096 getRange(axis) {
8097 return axis === 'x' ? this.width / 2 : this.height / 2;
8098 }
8099 }
8100
8101 var elements = /*#__PURE__*/Object.freeze({
8102 __proto__: null,
8103 ArcElement: ArcElement,
8104 BarElement: BarElement,
8105 LineElement: LineElement,
8106 PointElement: PointElement
8107 });
8108
8109 const BORDER_COLORS = [
8110 'rgb(54, 162, 235)',
8111 'rgb(255, 99, 132)',
8112 'rgb(255, 159, 64)',
8113 'rgb(255, 205, 86)',
8114 'rgb(75, 192, 192)',
8115 'rgb(153, 102, 255)',
8116 'rgb(201, 203, 207)' // grey
8117 ];
8118 // Border colors with 50% transparency
8119 const BACKGROUND_COLORS = /* #__PURE__ */ BORDER_COLORS.map((color)=>color.replace('rgb(', 'rgba(').replace(')', ', 0.5)'));
8120 function getBorderColor(i) {
8121 return BORDER_COLORS[i % BORDER_COLORS.length];
8122 }
8123 function getBackgroundColor(i) {
8124 return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length];
8125 }
8126 function colorizeDefaultDataset(dataset, i) {
8127 dataset.borderColor = getBorderColor(i);
8128 dataset.backgroundColor = getBackgroundColor(i);
8129 return ++i;
8130 }
8131 function colorizeDoughnutDataset(dataset, i) {
8132 dataset.backgroundColor = dataset.data.map(()=>getBorderColor(i++));
8133 return i;
8134 }
8135 function colorizePolarAreaDataset(dataset, i) {
8136 dataset.backgroundColor = dataset.data.map(()=>getBackgroundColor(i++));
8137 return i;
8138 }
8139 function getColorizer(chart) {
8140 let i = 0;
8141 return (dataset, datasetIndex)=>{
8142 const controller = chart.getDatasetMeta(datasetIndex).controller;
8143 if (controller instanceof DoughnutController) {
8144 i = colorizeDoughnutDataset(dataset, i);
8145 } else if (controller instanceof PolarAreaController) {
8146 i = colorizePolarAreaDataset(dataset, i);
8147 } else if (controller) {
8148 i = colorizeDefaultDataset(dataset, i);
8149 }
8150 };
8151 }
8152 function containsColorsDefinitions(descriptors) {
8153 let k;
8154 for(k in descriptors){
8155 if (descriptors[k].borderColor || descriptors[k].backgroundColor) {
8156 return true;
8157 }
8158 }
8159 return false;
8160 }
8161 function containsColorsDefinition(descriptor) {
8162 return descriptor && (descriptor.borderColor || descriptor.backgroundColor);
8163 }
8164 function containsDefaultColorsDefenitions() {
8165 return _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.borderColor !== 'rgba(0,0,0,0.1)' || _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.backgroundColor !== 'rgba(0,0,0,0.1)';
8166 }
8167 var plugin_colors = {
8168 id: 'colors',
8169 defaults: {
8170 enabled: true,
8171 forceOverride: false
8172 },
8173 beforeLayout (chart, _args, options) {
8174 if (!options.enabled) {
8175 return;
8176 }
8177 const { data: { datasets } , options: chartOptions } = chart.config;
8178 const { elements } = chartOptions;
8179 const containsColorDefenition = containsColorsDefinitions(datasets) || containsColorsDefinition(chartOptions) || elements && containsColorsDefinitions(elements) || containsDefaultColorsDefenitions();
8180 if (!options.forceOverride && containsColorDefenition) {
8181 return;
8182 }
8183 const colorizer = getColorizer(chart);
8184 datasets.forEach(colorizer);
8185 }
8186 };
8187
8188 function lttbDecimation(data, start, count, availableWidth, options) {
8189 const samples = options.samples || availableWidth;
8190 if (samples >= count) {
8191 return data.slice(start, start + count);
8192 }
8193 const decimated = [];
8194 const bucketWidth = (count - 2) / (samples - 2);
8195 let sampledIndex = 0;
8196 const endIndex = start + count - 1;
8197 let a = start;
8198 let i, maxAreaPoint, maxArea, area, nextA;
8199 decimated[sampledIndex++] = data[a];
8200 for(i = 0; i < samples - 2; i++){
8201 let avgX = 0;
8202 let avgY = 0;
8203 let j;
8204 const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start;
8205 const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start;
8206 const avgRangeLength = avgRangeEnd - avgRangeStart;
8207 for(j = avgRangeStart; j < avgRangeEnd; j++){
8208 avgX += data[j].x;
8209 avgY += data[j].y;
8210 }
8211 avgX /= avgRangeLength;
8212 avgY /= avgRangeLength;
8213 const rangeOffs = Math.floor(i * bucketWidth) + 1 + start;
8214 const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start;
8215 const { x: pointAx , y: pointAy } = data[a];
8216 maxArea = area = -1;
8217 for(j = rangeOffs; j < rangeTo; j++){
8218 area = 0.5 * Math.abs((pointAx - avgX) * (data[j].y - pointAy) - (pointAx - data[j].x) * (avgY - pointAy));
8219 if (area > maxArea) {
8220 maxArea = area;
8221 maxAreaPoint = data[j];
8222 nextA = j;
8223 }
8224 }
8225 decimated[sampledIndex++] = maxAreaPoint;
8226 a = nextA;
8227 }
8228 decimated[sampledIndex++] = data[endIndex];
8229 return decimated;
8230 }
8231 function minMaxDecimation(data, start, count, availableWidth) {
8232 let avgX = 0;
8233 let countX = 0;
8234 let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY;
8235 const decimated = [];
8236 const endIndex = start + count - 1;
8237 const xMin = data[start].x;
8238 const xMax = data[endIndex].x;
8239 const dx = xMax - xMin;
8240 for(i = start; i < start + count; ++i){
8241 point = data[i];
8242 x = (point.x - xMin) / dx * availableWidth;
8243 y = point.y;
8244 const truncX = x | 0;
8245 if (truncX === prevX) {
8246 if (y < minY) {
8247 minY = y;
8248 minIndex = i;
8249 } else if (y > maxY) {
8250 maxY = y;
8251 maxIndex = i;
8252 }
8253 avgX = (countX * avgX + point.x) / ++countX;
8254 } else {
8255 const lastIndex = i - 1;
8256 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(minIndex) && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(maxIndex)) {
8257 const intermediateIndex1 = Math.min(minIndex, maxIndex);
8258 const intermediateIndex2 = Math.max(minIndex, maxIndex);
8259 if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) {
8260 decimated.push({
8261 ...data[intermediateIndex1],
8262 x: avgX
8263 });
8264 }
8265 if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) {
8266 decimated.push({
8267 ...data[intermediateIndex2],
8268 x: avgX
8269 });
8270 }
8271 }
8272 if (i > 0 && lastIndex !== startIndex) {
8273 decimated.push(data[lastIndex]);
8274 }
8275 decimated.push(point);
8276 prevX = truncX;
8277 countX = 0;
8278 minY = maxY = y;
8279 minIndex = maxIndex = startIndex = i;
8280 }
8281 }
8282 return decimated;
8283 }
8284 function cleanDecimatedDataset(dataset) {
8285 if (dataset._decimated) {
8286 const data = dataset._data;
8287 delete dataset._decimated;
8288 delete dataset._data;
8289 Object.defineProperty(dataset, 'data', {
8290 configurable: true,
8291 enumerable: true,
8292 writable: true,
8293 value: data
8294 });
8295 }
8296 }
8297 function cleanDecimatedData(chart) {
8298 chart.data.datasets.forEach((dataset)=>{
8299 cleanDecimatedDataset(dataset);
8300 });
8301 }
8302 function getStartAndCountOfVisiblePointsSimplified(meta, points) {
8303 const pointCount = points.length;
8304 let start = 0;
8305 let count;
8306 const { iScale } = meta;
8307 const { min , max , minDefined , maxDefined } = iScale.getUserBounds();
8308 if (minDefined) {
8309 start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, min).lo, 0, pointCount - 1);
8310 }
8311 if (maxDefined) {
8312 count = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, max).hi + 1, start, pointCount) - start;
8313 } else {
8314 count = pointCount - start;
8315 }
8316 return {
8317 start,
8318 count
8319 };
8320 }
8321 var plugin_decimation = {
8322 id: 'decimation',
8323 defaults: {
8324 algorithm: 'min-max',
8325 enabled: false
8326 },
8327 beforeElementsUpdate: (chart, args, options)=>{
8328 if (!options.enabled) {
8329 cleanDecimatedData(chart);
8330 return;
8331 }
8332 const availableWidth = chart.width;
8333 chart.data.datasets.forEach((dataset, datasetIndex)=>{
8334 const { _data , indexAxis } = dataset;
8335 const meta = chart.getDatasetMeta(datasetIndex);
8336 const data = _data || dataset.data;
8337 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a)([
8338 indexAxis,
8339 chart.options.indexAxis
8340 ]) === 'y') {
8341 return;
8342 }
8343 if (!meta.controller.supportsDecimation) {
8344 return;
8345 }
8346 const xAxis = chart.scales[meta.xAxisID];
8347 if (xAxis.type !== 'linear' && xAxis.type !== 'time') {
8348 return;
8349 }
8350 if (chart.options.parsing) {
8351 return;
8352 }
8353 let { start , count } = getStartAndCountOfVisiblePointsSimplified(meta, data);
8354 const threshold = options.threshold || 4 * availableWidth;
8355 if (count <= threshold) {
8356 cleanDecimatedDataset(dataset);
8357 return;
8358 }
8359 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(_data)) {
8360 dataset._data = data;
8361 delete dataset.data;
8362 Object.defineProperty(dataset, 'data', {
8363 configurable: true,
8364 enumerable: true,
8365 get: function() {
8366 return this._decimated;
8367 },
8368 set: function(d) {
8369 this._data = d;
8370 }
8371 });
8372 }
8373 let decimated;
8374 switch(options.algorithm){
8375 case 'lttb':
8376 decimated = lttbDecimation(data, start, count, availableWidth, options);
8377 break;
8378 case 'min-max':
8379 decimated = minMaxDecimation(data, start, count, availableWidth);
8380 break;
8381 default:
8382 throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`);
8383 }
8384 dataset._decimated = decimated;
8385 });
8386 },
8387 destroy (chart) {
8388 cleanDecimatedData(chart);
8389 }
8390 };
8391
8392 function _segments(line, target, property) {
8393 const segments = line.segments;
8394 const points = line.points;
8395 const tpoints = target.points;
8396 const parts = [];
8397 for (const segment of segments){
8398 let { start , end } = segment;
8399 end = _findSegmentEnd(start, end, points);
8400 const bounds = _getBounds(property, points[start], points[end], segment.loop);
8401 if (!target.segments) {
8402 parts.push({
8403 source: segment,
8404 target: bounds,
8405 start: points[start],
8406 end: points[end]
8407 });
8408 continue;
8409 }
8410 const targetSegments = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ap)(target, bounds);
8411 for (const tgt of targetSegments){
8412 const subBounds = _getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop);
8413 const fillSources = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.az)(segment, points, subBounds);
8414 for (const fillSource of fillSources){
8415 parts.push({
8416 source: fillSource,
8417 target: tgt,
8418 start: {
8419 [property]: _getEdge(bounds, subBounds, 'start', Math.max)
8420 },
8421 end: {
8422 [property]: _getEdge(bounds, subBounds, 'end', Math.min)
8423 }
8424 });
8425 }
8426 }
8427 }
8428 return parts;
8429 }
8430 function _getBounds(property, first, last, loop) {
8431 if (loop) {
8432 return;
8433 }
8434 let start = first[property];
8435 let end = last[property];
8436 if (property === 'angle') {
8437 start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(start);
8438 end = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(end);
8439 }
8440 return {
8441 property,
8442 start,
8443 end
8444 };
8445 }
8446 function _pointsFromSegments(boundary, line) {
8447 const { x =null , y =null } = boundary || {};
8448 const linePoints = line.points;
8449 const points = [];
8450 line.segments.forEach(({ start , end })=>{
8451 end = _findSegmentEnd(start, end, linePoints);
8452 const first = linePoints[start];
8453 const last = linePoints[end];
8454 if (y !== null) {
8455 points.push({
8456 x: first.x,
8457 y
8458 });
8459 points.push({
8460 x: last.x,
8461 y
8462 });
8463 } else if (x !== null) {
8464 points.push({
8465 x,
8466 y: first.y
8467 });
8468 points.push({
8469 x,
8470 y: last.y
8471 });
8472 }
8473 });
8474 return points;
8475 }
8476 function _findSegmentEnd(start, end, points) {
8477 for(; end > start; end--){
8478 const point = points[end];
8479 if (!isNaN(point.x) && !isNaN(point.y)) {
8480 break;
8481 }
8482 }
8483 return end;
8484 }
8485 function _getEdge(a, b, prop, fn) {
8486 if (a && b) {
8487 return fn(a[prop], b[prop]);
8488 }
8489 return a ? a[prop] : b ? b[prop] : 0;
8490 }
8491
8492 function _createBoundaryLine(boundary, line) {
8493 let points = [];
8494 let _loop = false;
8495 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(boundary)) {
8496 _loop = true;
8497 points = boundary;
8498 } else {
8499 points = _pointsFromSegments(boundary, line);
8500 }
8501 return points.length ? new LineElement({
8502 points,
8503 options: {
8504 tension: 0
8505 },
8506 _loop,
8507 _fullLoop: _loop
8508 }) : null;
8509 }
8510 function _shouldApplyFill(source) {
8511 return source && source.fill !== false;
8512 }
8513
8514 function _resolveTarget(sources, index, propagate) {
8515 const source = sources[index];
8516 let fill = source.fill;
8517 const visited = [
8518 index
8519 ];
8520 let target;
8521 if (!propagate) {
8522 return fill;
8523 }
8524 while(fill !== false && visited.indexOf(fill) === -1){
8525 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) {
8526 return fill;
8527 }
8528 target = sources[fill];
8529 if (!target) {
8530 return false;
8531 }
8532 if (target.visible) {
8533 return fill;
8534 }
8535 visited.push(fill);
8536 fill = target.fill;
8537 }
8538 return false;
8539 }
8540 function _decodeFill(line, index, count) {
8541 const fill = parseFillOption(line);
8542 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {
8543 return isNaN(fill.value) ? false : fill;
8544 }
8545 let target = parseFloat(fill);
8546 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(target) && Math.floor(target) === target) {
8547 return decodeTargetIndex(fill[0], index, target, count);
8548 }
8549 return [
8550 'origin',
8551 'start',
8552 'end',
8553 'stack',
8554 'shape'
8555 ].indexOf(fill) >= 0 && fill;
8556 }
8557 function decodeTargetIndex(firstCh, index, target, count) {
8558 if (firstCh === '-' || firstCh === '+') {
8559 target = index + target;
8560 }
8561 if (target === index || target < 0 || target >= count) {
8562 return false;
8563 }
8564 return target;
8565 }
8566 function _getTargetPixel(fill, scale) {
8567 let pixel = null;
8568 if (fill === 'start') {
8569 pixel = scale.bottom;
8570 } else if (fill === 'end') {
8571 pixel = scale.top;
8572 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {
8573 pixel = scale.getPixelForValue(fill.value);
8574 } else if (scale.getBasePixel) {
8575 pixel = scale.getBasePixel();
8576 }
8577 return pixel;
8578 }
8579 function _getTargetValue(fill, scale, startValue) {
8580 let value;
8581 if (fill === 'start') {
8582 value = startValue;
8583 } else if (fill === 'end') {
8584 value = scale.options.reverse ? scale.min : scale.max;
8585 } else if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) {
8586 value = fill.value;
8587 } else {
8588 value = scale.getBaseValue();
8589 }
8590 return value;
8591 }
8592 function parseFillOption(line) {
8593 const options = line.options;
8594 const fillOption = options.fill;
8595 let fill = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(fillOption && fillOption.target, fillOption);
8596 if (fill === undefined) {
8597 fill = !!options.backgroundColor;
8598 }
8599 if (fill === false || fill === null) {
8600 return false;
8601 }
8602 if (fill === true) {
8603 return 'origin';
8604 }
8605 return fill;
8606 }
8607
8608 function _buildStackLine(source) {
8609 const { scale , index , line } = source;
8610 const points = [];
8611 const segments = line.segments;
8612 const sourcePoints = line.points;
8613 const linesBelow = getLinesBelow(scale, index);
8614 linesBelow.push(_createBoundaryLine({
8615 x: null,
8616 y: scale.bottom
8617 }, line));
8618 for(let i = 0; i < segments.length; i++){
8619 const segment = segments[i];
8620 for(let j = segment.start; j <= segment.end; j++){
8621 addPointsBelow(points, sourcePoints[j], linesBelow);
8622 }
8623 }
8624 return new LineElement({
8625 points,
8626 options: {}
8627 });
8628 }
8629 function getLinesBelow(scale, index) {
8630 const below = [];
8631 const metas = scale.getMatchingVisibleMetas('line');
8632 for(let i = 0; i < metas.length; i++){
8633 const meta = metas[i];
8634 if (meta.index === index) {
8635 break;
8636 }
8637 if (!meta.hidden) {
8638 below.unshift(meta.dataset);
8639 }
8640 }
8641 return below;
8642 }
8643 function addPointsBelow(points, sourcePoint, linesBelow) {
8644 const postponed = [];
8645 for(let j = 0; j < linesBelow.length; j++){
8646 const line = linesBelow[j];
8647 const { first , last , point } = findPoint(line, sourcePoint, 'x');
8648 if (!point || first && last) {
8649 continue;
8650 }
8651 if (first) {
8652 postponed.unshift(point);
8653 } else {
8654 points.push(point);
8655 if (!last) {
8656 break;
8657 }
8658 }
8659 }
8660 points.push(...postponed);
8661 }
8662 function findPoint(line, sourcePoint, property) {
8663 const point = line.interpolate(sourcePoint, property);
8664 if (!point) {
8665 return {};
8666 }
8667 const pointValue = point[property];
8668 const segments = line.segments;
8669 const linePoints = line.points;
8670 let first = false;
8671 let last = false;
8672 for(let i = 0; i < segments.length; i++){
8673 const segment = segments[i];
8674 const firstValue = linePoints[segment.start][property];
8675 const lastValue = linePoints[segment.end][property];
8676 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(pointValue, firstValue, lastValue)) {
8677 first = pointValue === firstValue;
8678 last = pointValue === lastValue;
8679 break;
8680 }
8681 }
8682 return {
8683 first,
8684 last,
8685 point
8686 };
8687 }
8688
8689 class simpleArc {
8690 constructor(opts){
8691 this.x = opts.x;
8692 this.y = opts.y;
8693 this.radius = opts.radius;
8694 }
8695 pathSegment(ctx, bounds, opts) {
8696 const { x , y , radius } = this;
8697 bounds = bounds || {
8698 start: 0,
8699 end: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T
8700 };
8701 ctx.arc(x, y, radius, bounds.end, bounds.start, true);
8702 return !opts.bounds;
8703 }
8704 interpolate(point) {
8705 const { x , y , radius } = this;
8706 const angle = point.angle;
8707 return {
8708 x: x + Math.cos(angle) * radius,
8709 y: y + Math.sin(angle) * radius,
8710 angle
8711 };
8712 }
8713 }
8714
8715 function _getTarget(source) {
8716 const { chart , fill , line } = source;
8717 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) {
8718 return getLineByIndex(chart, fill);
8719 }
8720 if (fill === 'stack') {
8721 return _buildStackLine(source);
8722 }
8723 if (fill === 'shape') {
8724 return true;
8725 }
8726 const boundary = computeBoundary(source);
8727 if (boundary instanceof simpleArc) {
8728 return boundary;
8729 }
8730 return _createBoundaryLine(boundary, line);
8731 }
8732 function getLineByIndex(chart, index) {
8733 const meta = chart.getDatasetMeta(index);
8734 const visible = meta && chart.isDatasetVisible(index);
8735 return visible ? meta.dataset : null;
8736 }
8737 function computeBoundary(source) {
8738 const scale = source.scale || {};
8739 if (scale.getPointPositionForValue) {
8740 return computeCircularBoundary(source);
8741 }
8742 return computeLinearBoundary(source);
8743 }
8744 function computeLinearBoundary(source) {
8745 const { scale ={} , fill } = source;
8746 const pixel = _getTargetPixel(fill, scale);
8747 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(pixel)) {
8748 const horizontal = scale.isHorizontal();
8749 return {
8750 x: horizontal ? pixel : null,
8751 y: horizontal ? null : pixel
8752 };
8753 }
8754 return null;
8755 }
8756 function computeCircularBoundary(source) {
8757 const { scale , fill } = source;
8758 const options = scale.options;
8759 const length = scale.getLabels().length;
8760 const start = options.reverse ? scale.max : scale.min;
8761 const value = _getTargetValue(fill, scale, start);
8762 const target = [];
8763 if (options.grid.circular) {
8764 const center = scale.getPointPositionForValue(0, start);
8765 return new simpleArc({
8766 x: center.x,
8767 y: center.y,
8768 radius: scale.getDistanceFromCenterForValue(value)
8769 });
8770 }
8771 for(let i = 0; i < length; ++i){
8772 target.push(scale.getPointPositionForValue(i, value));
8773 }
8774 return target;
8775 }
8776
8777 function _drawfill(ctx, source, area) {
8778 const target = _getTarget(source);
8779 const { chart , index , line , scale , axis } = source;
8780 const lineOpts = line.options;
8781 const fillOption = lineOpts.fill;
8782 const color = lineOpts.backgroundColor;
8783 const { above =color , below =color } = fillOption || {};
8784 const meta = chart.getDatasetMeta(index);
8785 const clip = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ah)(chart, meta);
8786 if (target && line.points.length) {
8787 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area);
8788 doFill(ctx, {
8789 line,
8790 target,
8791 above,
8792 below,
8793 area,
8794 scale,
8795 axis,
8796 clip
8797 });
8798 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);
8799 }
8800 }
8801 function doFill(ctx, cfg) {
8802 const { line , target , above , below , area , scale , clip } = cfg;
8803 const property = line._loop ? 'angle' : cfg.axis;
8804 ctx.save();
8805 let fillColor = below;
8806 if (below !== above) {
8807 if (property === 'x') {
8808 clipVertical(ctx, target, area.top);
8809 fill(ctx, {
8810 line,
8811 target,
8812 color: above,
8813 scale,
8814 property,
8815 clip
8816 });
8817 ctx.restore();
8818 ctx.save();
8819 clipVertical(ctx, target, area.bottom);
8820 } else if (property === 'y') {
8821 clipHorizontal(ctx, target, area.left);
8822 fill(ctx, {
8823 line,
8824 target,
8825 color: below,
8826 scale,
8827 property,
8828 clip
8829 });
8830 ctx.restore();
8831 ctx.save();
8832 clipHorizontal(ctx, target, area.right);
8833 fillColor = above;
8834 }
8835 }
8836 fill(ctx, {
8837 line,
8838 target,
8839 color: fillColor,
8840 scale,
8841 property,
8842 clip
8843 });
8844 ctx.restore();
8845 }
8846 function clipVertical(ctx, target, clipY) {
8847 const { segments , points } = target;
8848 let first = true;
8849 let lineLoop = false;
8850 ctx.beginPath();
8851 for (const segment of segments){
8852 const { start , end } = segment;
8853 const firstPoint = points[start];
8854 const lastPoint = points[_findSegmentEnd(start, end, points)];
8855 if (first) {
8856 ctx.moveTo(firstPoint.x, firstPoint.y);
8857 first = false;
8858 } else {
8859 ctx.lineTo(firstPoint.x, clipY);
8860 ctx.lineTo(firstPoint.x, firstPoint.y);
8861 }
8862 lineLoop = !!target.pathSegment(ctx, segment, {
8863 move: lineLoop
8864 });
8865 if (lineLoop) {
8866 ctx.closePath();
8867 } else {
8868 ctx.lineTo(lastPoint.x, clipY);
8869 }
8870 }
8871 ctx.lineTo(target.first().x, clipY);
8872 ctx.closePath();
8873 ctx.clip();
8874 }
8875 function clipHorizontal(ctx, target, clipX) {
8876 const { segments , points } = target;
8877 let first = true;
8878 let lineLoop = false;
8879 ctx.beginPath();
8880 for (const segment of segments){
8881 const { start , end } = segment;
8882 const firstPoint = points[start];
8883 const lastPoint = points[_findSegmentEnd(start, end, points)];
8884 if (first) {
8885 ctx.moveTo(firstPoint.x, firstPoint.y);
8886 first = false;
8887 } else {
8888 ctx.lineTo(clipX, firstPoint.y);
8889 ctx.lineTo(firstPoint.x, firstPoint.y);
8890 }
8891 lineLoop = !!target.pathSegment(ctx, segment, {
8892 move: lineLoop
8893 });
8894 if (lineLoop) {
8895 ctx.closePath();
8896 } else {
8897 ctx.lineTo(clipX, lastPoint.y);
8898 }
8899 }
8900 ctx.lineTo(clipX, target.first().y);
8901 ctx.closePath();
8902 ctx.clip();
8903 }
8904 function fill(ctx, cfg) {
8905 const { line , target , property , color , scale , clip } = cfg;
8906 const segments = _segments(line, target, property);
8907 for (const { source: src , target: tgt , start , end } of segments){
8908 const { style: { backgroundColor =color } = {} } = src;
8909 const notShape = target !== true;
8910 ctx.save();
8911 ctx.fillStyle = backgroundColor;
8912 clipBounds(ctx, scale, clip, notShape && _getBounds(property, start, end));
8913 ctx.beginPath();
8914 const lineLoop = !!line.pathSegment(ctx, src);
8915 let loop;
8916 if (notShape) {
8917 if (lineLoop) {
8918 ctx.closePath();
8919 } else {
8920 interpolatedLineTo(ctx, target, end, property);
8921 }
8922 const targetLoop = !!target.pathSegment(ctx, tgt, {
8923 move: lineLoop,
8924 reverse: true
8925 });
8926 loop = lineLoop && targetLoop;
8927 if (!loop) {
8928 interpolatedLineTo(ctx, target, start, property);
8929 }
8930 }
8931 ctx.closePath();
8932 ctx.fill(loop ? 'evenodd' : 'nonzero');
8933 ctx.restore();
8934 }
8935 }
8936 function clipBounds(ctx, scale, clip, bounds) {
8937 const chartArea = scale.chart.chartArea;
8938 const { property , start , end } = bounds || {};
8939 if (property === 'x' || property === 'y') {
8940 let left, top, right, bottom;
8941 if (property === 'x') {
8942 left = start;
8943 top = chartArea.top;
8944 right = end;
8945 bottom = chartArea.bottom;
8946 } else {
8947 left = chartArea.left;
8948 top = start;
8949 right = chartArea.right;
8950 bottom = end;
8951 }
8952 ctx.beginPath();
8953 if (clip) {
8954 left = Math.max(left, clip.left);
8955 right = Math.min(right, clip.right);
8956 top = Math.max(top, clip.top);
8957 bottom = Math.min(bottom, clip.bottom);
8958 }
8959 ctx.rect(left, top, right - left, bottom - top);
8960 ctx.clip();
8961 }
8962 }
8963 function interpolatedLineTo(ctx, target, point, property) {
8964 const interpolatedPoint = target.interpolate(point, property);
8965 if (interpolatedPoint) {
8966 ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y);
8967 }
8968 }
8969
8970 var index = {
8971 id: 'filler',
8972 afterDatasetsUpdate (chart, _args, options) {
8973 const count = (chart.data.datasets || []).length;
8974 const sources = [];
8975 let meta, i, line, source;
8976 for(i = 0; i < count; ++i){
8977 meta = chart.getDatasetMeta(i);
8978 line = meta.dataset;
8979 source = null;
8980 if (line && line.options && line instanceof LineElement) {
8981 source = {
8982 visible: chart.isDatasetVisible(i),
8983 index: i,
8984 fill: _decodeFill(line, i, count),
8985 chart,
8986 axis: meta.controller.options.indexAxis,
8987 scale: meta.vScale,
8988 line
8989 };
8990 }
8991 meta.$filler = source;
8992 sources.push(source);
8993 }
8994 for(i = 0; i < count; ++i){
8995 source = sources[i];
8996 if (!source || source.fill === false) {
8997 continue;
8998 }
8999 source.fill = _resolveTarget(sources, i, options.propagate);
9000 }
9001 },
9002 beforeDraw (chart, _args, options) {
9003 const draw = options.drawTime === 'beforeDraw';
9004 const metasets = chart.getSortedVisibleDatasetMetas();
9005 const area = chart.chartArea;
9006 for(let i = metasets.length - 1; i >= 0; --i){
9007 const source = metasets[i].$filler;
9008 if (!source) {
9009 continue;
9010 }
9011 source.line.updateControlPoints(area, source.axis);
9012 if (draw && source.fill) {
9013 _drawfill(chart.ctx, source, area);
9014 }
9015 }
9016 },
9017 beforeDatasetsDraw (chart, _args, options) {
9018 if (options.drawTime !== 'beforeDatasetsDraw') {
9019 return;
9020 }
9021 const metasets = chart.getSortedVisibleDatasetMetas();
9022 for(let i = metasets.length - 1; i >= 0; --i){
9023 const source = metasets[i].$filler;
9024 if (_shouldApplyFill(source)) {
9025 _drawfill(chart.ctx, source, chart.chartArea);
9026 }
9027 }
9028 },
9029 beforeDatasetDraw (chart, args, options) {
9030 const source = args.meta.$filler;
9031 if (!_shouldApplyFill(source) || options.drawTime !== 'beforeDatasetDraw') {
9032 return;
9033 }
9034 _drawfill(chart.ctx, source, chart.chartArea);
9035 },
9036 defaults: {
9037 propagate: true,
9038 drawTime: 'beforeDatasetDraw'
9039 }
9040 };
9041
9042 const getBoxSize = (labelOpts, fontSize)=>{
9043 let { boxHeight =fontSize , boxWidth =fontSize } = labelOpts;
9044 if (labelOpts.usePointStyle) {
9045 boxHeight = Math.min(boxHeight, fontSize);
9046 boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);
9047 }
9048 return {
9049 boxWidth,
9050 boxHeight,
9051 itemHeight: Math.max(fontSize, boxHeight)
9052 };
9053 };
9054 const itemsEqual = (a, b)=>a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index;
9055 class Legend extends Element {
9056 constructor(config){
9057 super();
9058 this._added = false;
9059 this.legendHitBoxes = [];
9060 this._hoveredItem = null;
9061 this.doughnutMode = false;
9062 this.chart = config.chart;
9063 this.options = config.options;
9064 this.ctx = config.ctx;
9065 this.legendItems = undefined;
9066 this.columnSizes = undefined;
9067 this.lineWidths = undefined;
9068 this.maxHeight = undefined;
9069 this.maxWidth = undefined;
9070 this.top = undefined;
9071 this.bottom = undefined;
9072 this.left = undefined;
9073 this.right = undefined;
9074 this.height = undefined;
9075 this.width = undefined;
9076 this._margins = undefined;
9077 this.position = undefined;
9078 this.weight = undefined;
9079 this.fullSize = undefined;
9080 }
9081 update(maxWidth, maxHeight, margins) {
9082 this.maxWidth = maxWidth;
9083 this.maxHeight = maxHeight;
9084 this._margins = margins;
9085 this.setDimensions();
9086 this.buildLabels();
9087 this.fit();
9088 }
9089 setDimensions() {
9090 if (this.isHorizontal()) {
9091 this.width = this.maxWidth;
9092 this.left = this._margins.left;
9093 this.right = this.width;
9094 } else {
9095 this.height = this.maxHeight;
9096 this.top = this._margins.top;
9097 this.bottom = this.height;
9098 }
9099 }
9100 buildLabels() {
9101 const labelOpts = this.options.labels || {};
9102 let legendItems = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(labelOpts.generateLabels, [
9103 this.chart
9104 ], this) || [];
9105 if (labelOpts.filter) {
9106 legendItems = legendItems.filter((item)=>labelOpts.filter(item, this.chart.data));
9107 }
9108 if (labelOpts.sort) {
9109 legendItems = legendItems.sort((a, b)=>labelOpts.sort(a, b, this.chart.data));
9110 }
9111 if (this.options.reverse) {
9112 legendItems.reverse();
9113 }
9114 this.legendItems = legendItems;
9115 }
9116 fit() {
9117 const { options , ctx } = this;
9118 if (!options.display) {
9119 this.width = this.height = 0;
9120 return;
9121 }
9122 const labelOpts = options.labels;
9123 const labelFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font);
9124 const fontSize = labelFont.size;
9125 const titleHeight = this._computeTitleHeight();
9126 const { boxWidth , itemHeight } = getBoxSize(labelOpts, fontSize);
9127 let width, height;
9128 ctx.font = labelFont.string;
9129 if (this.isHorizontal()) {
9130 width = this.maxWidth;
9131 height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
9132 } else {
9133 height = this.maxHeight;
9134 width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10;
9135 }
9136 this.width = Math.min(width, options.maxWidth || this.maxWidth);
9137 this.height = Math.min(height, options.maxHeight || this.maxHeight);
9138 }
9139 _fitRows(titleHeight, fontSize, boxWidth, itemHeight) {
9140 const { ctx , maxWidth , options: { labels: { padding } } } = this;
9141 const hitboxes = this.legendHitBoxes = [];
9142 const lineWidths = this.lineWidths = [
9143 0
9144 ];
9145 const lineHeight = itemHeight + padding;
9146 let totalHeight = titleHeight;
9147 ctx.textAlign = 'left';
9148 ctx.textBaseline = 'middle';
9149 let row = -1;
9150 let top = -lineHeight;
9151 this.legendItems.forEach((legendItem, i)=>{
9152 const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width;
9153 if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {
9154 totalHeight += lineHeight;
9155 lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;
9156 top += lineHeight;
9157 row++;
9158 }
9159 hitboxes[i] = {
9160 left: 0,
9161 top,
9162 row,
9163 width: itemWidth,
9164 height: itemHeight
9165 };
9166 lineWidths[lineWidths.length - 1] += itemWidth + padding;
9167 });
9168 return totalHeight;
9169 }
9170 _fitCols(titleHeight, labelFont, boxWidth, _itemHeight) {
9171 const { ctx , maxHeight , options: { labels: { padding } } } = this;
9172 const hitboxes = this.legendHitBoxes = [];
9173 const columnSizes = this.columnSizes = [];
9174 const heightLimit = maxHeight - titleHeight;
9175 let totalWidth = padding;
9176 let currentColWidth = 0;
9177 let currentColHeight = 0;
9178 let left = 0;
9179 let col = 0;
9180 this.legendItems.forEach((legendItem, i)=>{
9181 const { itemWidth , itemHeight } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight);
9182 if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {
9183 totalWidth += currentColWidth + padding;
9184 columnSizes.push({
9185 width: currentColWidth,
9186 height: currentColHeight
9187 });
9188 left += currentColWidth + padding;
9189 col++;
9190 currentColWidth = currentColHeight = 0;
9191 }
9192 hitboxes[i] = {
9193 left,
9194 top: currentColHeight,
9195 col,
9196 width: itemWidth,
9197 height: itemHeight
9198 };
9199 currentColWidth = Math.max(currentColWidth, itemWidth);
9200 currentColHeight += itemHeight + padding;
9201 });
9202 totalWidth += currentColWidth;
9203 columnSizes.push({
9204 width: currentColWidth,
9205 height: currentColHeight
9206 });
9207 return totalWidth;
9208 }
9209 adjustHitBoxes() {
9210 if (!this.options.display) {
9211 return;
9212 }
9213 const titleHeight = this._computeTitleHeight();
9214 const { legendHitBoxes: hitboxes , options: { align , labels: { padding } , rtl } } = this;
9215 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(rtl, this.left, this.width);
9216 if (this.isHorizontal()) {
9217 let row = 0;
9218 let left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]);
9219 for (const hitbox of hitboxes){
9220 if (row !== hitbox.row) {
9221 row = hitbox.row;
9222 left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]);
9223 }
9224 hitbox.top += this.top + titleHeight + padding;
9225 hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);
9226 left += hitbox.width + padding;
9227 }
9228 } else {
9229 let col = 0;
9230 let top = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
9231 for (const hitbox of hitboxes){
9232 if (hitbox.col !== col) {
9233 col = hitbox.col;
9234 top = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
9235 }
9236 hitbox.top = top;
9237 hitbox.left += this.left + padding;
9238 hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);
9239 top += hitbox.height + padding;
9240 }
9241 }
9242 }
9243 isHorizontal() {
9244 return this.options.position === 'top' || this.options.position === 'bottom';
9245 }
9246 draw() {
9247 if (this.options.display) {
9248 const ctx = this.ctx;
9249 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, this);
9250 this._draw();
9251 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx);
9252 }
9253 }
9254 _draw() {
9255 const { options: opts , columnSizes , lineWidths , ctx } = this;
9256 const { align , labels: labelOpts } = opts;
9257 const defaultColor = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.color;
9258 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(opts.rtl, this.left, this.width);
9259 const labelFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font);
9260 const { padding } = labelOpts;
9261 const fontSize = labelFont.size;
9262 const halfFontSize = fontSize / 2;
9263 let cursor;
9264 this.drawTitle();
9265 ctx.textAlign = rtlHelper.textAlign('left');
9266 ctx.textBaseline = 'middle';
9267 ctx.lineWidth = 0.5;
9268 ctx.font = labelFont.string;
9269 const { boxWidth , boxHeight , itemHeight } = getBoxSize(labelOpts, fontSize);
9270 const drawLegendBox = function(x, y, legendItem) {
9271 if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {
9272 return;
9273 }
9274 ctx.save();
9275 const lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineWidth, 1);
9276 ctx.fillStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.fillStyle, defaultColor);
9277 ctx.lineCap = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineCap, 'butt');
9278 ctx.lineDashOffset = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDashOffset, 0);
9279 ctx.lineJoin = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineJoin, 'miter');
9280 ctx.lineWidth = lineWidth;
9281 ctx.strokeStyle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.strokeStyle, defaultColor);
9282 ctx.setLineDash((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDash, []));
9283 if (labelOpts.usePointStyle) {
9284 const drawOptions = {
9285 radius: boxHeight * Math.SQRT2 / 2,
9286 pointStyle: legendItem.pointStyle,
9287 rotation: legendItem.rotation,
9288 borderWidth: lineWidth
9289 };
9290 const centerX = rtlHelper.xPlus(x, boxWidth / 2);
9291 const centerY = y + halfFontSize;
9292 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aE)(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth);
9293 } else {
9294 const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);
9295 const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);
9296 const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(legendItem.borderRadius);
9297 ctx.beginPath();
9298 if (Object.values(borderRadius).some((v)=>v !== 0)) {
9299 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {
9300 x: xBoxLeft,
9301 y: yBoxTop,
9302 w: boxWidth,
9303 h: boxHeight,
9304 radius: borderRadius
9305 });
9306 } else {
9307 ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);
9308 }
9309 ctx.fill();
9310 if (lineWidth !== 0) {
9311 ctx.stroke();
9312 }
9313 }
9314 ctx.restore();
9315 };
9316 const fillText = function(x, y, legendItem) {
9317 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, legendItem.text, x, y + itemHeight / 2, labelFont, {
9318 strikethrough: legendItem.hidden,
9319 textAlign: rtlHelper.textAlign(legendItem.textAlign)
9320 });
9321 };
9322 const isHorizontal = this.isHorizontal();
9323 const titleHeight = this._computeTitleHeight();
9324 if (isHorizontal) {
9325 cursor = {
9326 x: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[0]),
9327 y: this.top + padding + titleHeight,
9328 line: 0
9329 };
9330 } else {
9331 cursor = {
9332 x: this.left + padding,
9333 y: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),
9334 line: 0
9335 };
9336 }
9337 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aB)(this.ctx, opts.textDirection);
9338 const lineHeight = itemHeight + padding;
9339 this.legendItems.forEach((legendItem, i)=>{
9340 ctx.strokeStyle = legendItem.fontColor;
9341 ctx.fillStyle = legendItem.fontColor;
9342 const textWidth = ctx.measureText(legendItem.text).width;
9343 const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));
9344 const width = boxWidth + halfFontSize + textWidth;
9345 let x = cursor.x;
9346 let y = cursor.y;
9347 rtlHelper.setWidth(this.width);
9348 if (isHorizontal) {
9349 if (i > 0 && x + width + padding > this.right) {
9350 y = cursor.y += lineHeight;
9351 cursor.line++;
9352 x = cursor.x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[cursor.line]);
9353 }
9354 } else if (i > 0 && y + lineHeight > this.bottom) {
9355 x = cursor.x = x + columnSizes[cursor.line].width + padding;
9356 cursor.line++;
9357 y = cursor.y = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);
9358 }
9359 const realX = rtlHelper.x(x);
9360 drawLegendBox(realX, y, legendItem);
9361 x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aC)(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);
9362 fillText(rtlHelper.x(x), y, legendItem);
9363 if (isHorizontal) {
9364 cursor.x += width + padding;
9365 } else if (typeof legendItem.text !== 'string') {
9366 const fontLineHeight = labelFont.lineHeight;
9367 cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight) + padding;
9368 } else {
9369 cursor.y += lineHeight;
9370 }
9371 });
9372 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aD)(this.ctx, opts.textDirection);
9373 }
9374 drawTitle() {
9375 const opts = this.options;
9376 const titleOpts = opts.title;
9377 const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font);
9378 const titlePadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding);
9379 if (!titleOpts.display) {
9380 return;
9381 }
9382 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(opts.rtl, this.left, this.width);
9383 const ctx = this.ctx;
9384 const position = titleOpts.position;
9385 const halfFontSize = titleFont.size / 2;
9386 const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;
9387 let y;
9388 let left = this.left;
9389 let maxWidth = this.width;
9390 if (this.isHorizontal()) {
9391 maxWidth = Math.max(...this.lineWidths);
9392 y = this.top + topPaddingPlusHalfFontSize;
9393 left = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, left, this.right - maxWidth);
9394 } else {
9395 const maxHeight = this.columnSizes.reduce((acc, size)=>Math.max(acc, size.height), 0);
9396 y = topPaddingPlusHalfFontSize + (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());
9397 }
9398 const x = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(position, left, left + maxWidth);
9399 ctx.textAlign = rtlHelper.textAlign((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(position));
9400 ctx.textBaseline = 'middle';
9401 ctx.strokeStyle = titleOpts.color;
9402 ctx.fillStyle = titleOpts.color;
9403 ctx.font = titleFont.string;
9404 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, titleOpts.text, x, y, titleFont);
9405 }
9406 _computeTitleHeight() {
9407 const titleOpts = this.options.title;
9408 const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font);
9409 const titlePadding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding);
9410 return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;
9411 }
9412 _getLegendItemAt(x, y) {
9413 let i, hitBox, lh;
9414 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, this.left, this.right) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, this.top, this.bottom)) {
9415 lh = this.legendHitBoxes;
9416 for(i = 0; i < lh.length; ++i){
9417 hitBox = lh[i];
9418 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(x, hitBox.left, hitBox.left + hitBox.width) && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ak)(y, hitBox.top, hitBox.top + hitBox.height)) {
9419 return this.legendItems[i];
9420 }
9421 }
9422 }
9423 return null;
9424 }
9425 handleEvent(e) {
9426 const opts = this.options;
9427 if (!isListened(e.type, opts)) {
9428 return;
9429 }
9430 const hoveredItem = this._getLegendItemAt(e.x, e.y);
9431 if (e.type === 'mousemove' || e.type === 'mouseout') {
9432 const previous = this._hoveredItem;
9433 const sameItem = itemsEqual(previous, hoveredItem);
9434 if (previous && !sameItem) {
9435 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onLeave, [
9436 e,
9437 previous,
9438 this
9439 ], this);
9440 }
9441 this._hoveredItem = hoveredItem;
9442 if (hoveredItem && !sameItem) {
9443 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onHover, [
9444 e,
9445 hoveredItem,
9446 this
9447 ], this);
9448 }
9449 } else if (hoveredItem) {
9450 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onClick, [
9451 e,
9452 hoveredItem,
9453 this
9454 ], this);
9455 }
9456 }
9457 }
9458 function calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) {
9459 const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx);
9460 const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight);
9461 return {
9462 itemWidth,
9463 itemHeight
9464 };
9465 }
9466 function calculateItemWidth(legendItem, boxWidth, labelFont, ctx) {
9467 let legendItemText = legendItem.text;
9468 if (legendItemText && typeof legendItemText !== 'string') {
9469 legendItemText = legendItemText.reduce((a, b)=>a.length > b.length ? a : b);
9470 }
9471 return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width;
9472 }
9473 function calculateItemHeight(_itemHeight, legendItem, fontLineHeight) {
9474 let itemHeight = _itemHeight;
9475 if (typeof legendItem.text !== 'string') {
9476 itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight);
9477 }
9478 return itemHeight;
9479 }
9480 function calculateLegendItemHeight(legendItem, fontLineHeight) {
9481 const labelHeight = legendItem.text ? legendItem.text.length : 0;
9482 return fontLineHeight * labelHeight;
9483 }
9484 function isListened(type, opts) {
9485 if ((type === 'mousemove' || type === 'mouseout') && (opts.onHover || opts.onLeave)) {
9486 return true;
9487 }
9488 if (opts.onClick && (type === 'click' || type === 'mouseup')) {
9489 return true;
9490 }
9491 return false;
9492 }
9493 var plugin_legend = {
9494 id: 'legend',
9495 _element: Legend,
9496 start (chart, _args, options) {
9497 const legend = chart.legend = new Legend({
9498 ctx: chart.ctx,
9499 options,
9500 chart
9501 });
9502 layouts.configure(chart, legend, options);
9503 layouts.addBox(chart, legend);
9504 },
9505 stop (chart) {
9506 layouts.removeBox(chart, chart.legend);
9507 delete chart.legend;
9508 },
9509 beforeUpdate (chart, _args, options) {
9510 const legend = chart.legend;
9511 layouts.configure(chart, legend, options);
9512 legend.options = options;
9513 },
9514 afterUpdate (chart) {
9515 const legend = chart.legend;
9516 legend.buildLabels();
9517 legend.adjustHitBoxes();
9518 },
9519 afterEvent (chart, args) {
9520 if (!args.replay) {
9521 chart.legend.handleEvent(args.event);
9522 }
9523 },
9524 defaults: {
9525 display: true,
9526 position: 'top',
9527 align: 'center',
9528 fullSize: true,
9529 reverse: false,
9530 weight: 1000,
9531 onClick (e, legendItem, legend) {
9532 const index = legendItem.datasetIndex;
9533 const ci = legend.chart;
9534 if (ci.isDatasetVisible(index)) {
9535 ci.hide(index);
9536 legendItem.hidden = true;
9537 } else {
9538 ci.show(index);
9539 legendItem.hidden = false;
9540 }
9541 },
9542 onHover: null,
9543 onLeave: null,
9544 labels: {
9545 color: (ctx)=>ctx.chart.options.color,
9546 boxWidth: 40,
9547 padding: 10,
9548 generateLabels (chart) {
9549 const datasets = chart.data.datasets;
9550 const { labels: { usePointStyle , pointStyle , textAlign , color , useBorderRadius , borderRadius } } = chart.legend.options;
9551 return chart._getSortedDatasetMetas().map((meta)=>{
9552 const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
9553 const borderWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(style.borderWidth);
9554 return {
9555 text: datasets[meta.index].label,
9556 fillStyle: style.backgroundColor,
9557 fontColor: color,
9558 hidden: !meta.visible,
9559 lineCap: style.borderCapStyle,
9560 lineDash: style.borderDash,
9561 lineDashOffset: style.borderDashOffset,
9562 lineJoin: style.borderJoinStyle,
9563 lineWidth: (borderWidth.width + borderWidth.height) / 4,
9564 strokeStyle: style.borderColor,
9565 pointStyle: pointStyle || style.pointStyle,
9566 rotation: style.rotation,
9567 textAlign: textAlign || style.textAlign,
9568 borderRadius: useBorderRadius && (borderRadius || style.borderRadius),
9569 datasetIndex: meta.index
9570 };
9571 }, this);
9572 }
9573 },
9574 title: {
9575 color: (ctx)=>ctx.chart.options.color,
9576 display: false,
9577 position: 'center',
9578 text: ''
9579 }
9580 },
9581 descriptors: {
9582 _scriptable: (name)=>!name.startsWith('on'),
9583 labels: {
9584 _scriptable: (name)=>![
9585 'generateLabels',
9586 'filter',
9587 'sort'
9588 ].includes(name)
9589 }
9590 }
9591 };
9592
9593 class Title extends Element {
9594 constructor(config){
9595 super();
9596 this.chart = config.chart;
9597 this.options = config.options;
9598 this.ctx = config.ctx;
9599 this._padding = undefined;
9600 this.top = undefined;
9601 this.bottom = undefined;
9602 this.left = undefined;
9603 this.right = undefined;
9604 this.width = undefined;
9605 this.height = undefined;
9606 this.position = undefined;
9607 this.weight = undefined;
9608 this.fullSize = undefined;
9609 }
9610 update(maxWidth, maxHeight) {
9611 const opts = this.options;
9612 this.left = 0;
9613 this.top = 0;
9614 if (!opts.display) {
9615 this.width = this.height = this.right = this.bottom = 0;
9616 return;
9617 }
9618 this.width = this.right = maxWidth;
9619 this.height = this.bottom = maxHeight;
9620 const lineCount = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(opts.text) ? opts.text.length : 1;
9621 this._padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.padding);
9622 const textSize = lineCount * (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font).lineHeight + this._padding.height;
9623 if (this.isHorizontal()) {
9624 this.height = textSize;
9625 } else {
9626 this.width = textSize;
9627 }
9628 }
9629 isHorizontal() {
9630 const pos = this.options.position;
9631 return pos === 'top' || pos === 'bottom';
9632 }
9633 _drawArgs(offset) {
9634 const { top , left , bottom , right , options } = this;
9635 const align = options.align;
9636 let rotation = 0;
9637 let maxWidth, titleX, titleY;
9638 if (this.isHorizontal()) {
9639 titleX = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right);
9640 titleY = top + offset;
9641 maxWidth = right - left;
9642 } else {
9643 if (options.position === 'left') {
9644 titleX = left + offset;
9645 titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top);
9646 rotation = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P * -0.5;
9647 } else {
9648 titleX = right - offset;
9649 titleY = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, top, bottom);
9650 rotation = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P * 0.5;
9651 }
9652 maxWidth = bottom - top;
9653 }
9654 return {
9655 titleX,
9656 titleY,
9657 maxWidth,
9658 rotation
9659 };
9660 }
9661 draw() {
9662 const ctx = this.ctx;
9663 const opts = this.options;
9664 if (!opts.display) {
9665 return;
9666 }
9667 const fontOpts = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);
9668 const lineHeight = fontOpts.lineHeight;
9669 const offset = lineHeight / 2 + this._padding.top;
9670 const { titleX , titleY , maxWidth , rotation } = this._drawArgs(offset);
9671 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, opts.text, 0, 0, fontOpts, {
9672 color: opts.color,
9673 maxWidth,
9674 rotation,
9675 textAlign: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a1)(opts.align),
9676 textBaseline: 'middle',
9677 translation: [
9678 titleX,
9679 titleY
9680 ]
9681 });
9682 }
9683 }
9684 function createTitle(chart, titleOpts) {
9685 const title = new Title({
9686 ctx: chart.ctx,
9687 options: titleOpts,
9688 chart
9689 });
9690 layouts.configure(chart, title, titleOpts);
9691 layouts.addBox(chart, title);
9692 chart.titleBlock = title;
9693 }
9694 var plugin_title = {
9695 id: 'title',
9696 _element: Title,
9697 start (chart, _args, options) {
9698 createTitle(chart, options);
9699 },
9700 stop (chart) {
9701 const titleBlock = chart.titleBlock;
9702 layouts.removeBox(chart, titleBlock);
9703 delete chart.titleBlock;
9704 },
9705 beforeUpdate (chart, _args, options) {
9706 const title = chart.titleBlock;
9707 layouts.configure(chart, title, options);
9708 title.options = options;
9709 },
9710 defaults: {
9711 align: 'center',
9712 display: false,
9713 font: {
9714 weight: 'bold'
9715 },
9716 fullSize: true,
9717 padding: 10,
9718 position: 'top',
9719 text: '',
9720 weight: 2000
9721 },
9722 defaultRoutes: {
9723 color: 'color'
9724 },
9725 descriptors: {
9726 _scriptable: true,
9727 _indexable: false
9728 }
9729 };
9730
9731 const map = new WeakMap();
9732 var plugin_subtitle = {
9733 id: 'subtitle',
9734 start (chart, _args, options) {
9735 const title = new Title({
9736 ctx: chart.ctx,
9737 options,
9738 chart
9739 });
9740 layouts.configure(chart, title, options);
9741 layouts.addBox(chart, title);
9742 map.set(chart, title);
9743 },
9744 stop (chart) {
9745 layouts.removeBox(chart, map.get(chart));
9746 map.delete(chart);
9747 },
9748 beforeUpdate (chart, _args, options) {
9749 const title = map.get(chart);
9750 layouts.configure(chart, title, options);
9751 title.options = options;
9752 },
9753 defaults: {
9754 align: 'center',
9755 display: false,
9756 font: {
9757 weight: 'normal'
9758 },
9759 fullSize: true,
9760 padding: 0,
9761 position: 'top',
9762 text: '',
9763 weight: 1500
9764 },
9765 defaultRoutes: {
9766 color: 'color'
9767 },
9768 descriptors: {
9769 _scriptable: true,
9770 _indexable: false
9771 }
9772 };
9773
9774 const positioners = {
9775 average (items) {
9776 if (!items.length) {
9777 return false;
9778 }
9779 let i, len;
9780 let xSet = new Set();
9781 let y = 0;
9782 let count = 0;
9783 for(i = 0, len = items.length; i < len; ++i){
9784 const el = items[i].element;
9785 if (el && el.hasValue()) {
9786 const pos = el.tooltipPosition();
9787 xSet.add(pos.x);
9788 y += pos.y;
9789 ++count;
9790 }
9791 }
9792 if (count === 0 || xSet.size === 0) {
9793 return false;
9794 }
9795 const xAverage = [
9796 ...xSet
9797 ].reduce((a, b)=>a + b) / xSet.size;
9798 return {
9799 x: xAverage,
9800 y: y / count
9801 };
9802 },
9803 nearest (items, eventPosition) {
9804 if (!items.length) {
9805 return false;
9806 }
9807 let x = eventPosition.x;
9808 let y = eventPosition.y;
9809 let minDistance = Number.POSITIVE_INFINITY;
9810 let i, len, nearestElement;
9811 for(i = 0, len = items.length; i < len; ++i){
9812 const el = items[i].element;
9813 if (el && el.hasValue()) {
9814 const center = el.getCenterPoint();
9815 const d = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aF)(eventPosition, center);
9816 if (d < minDistance) {
9817 minDistance = d;
9818 nearestElement = el;
9819 }
9820 }
9821 }
9822 if (nearestElement) {
9823 const tp = nearestElement.tooltipPosition();
9824 x = tp.x;
9825 y = tp.y;
9826 }
9827 return {
9828 x,
9829 y
9830 };
9831 }
9832 };
9833 function pushOrConcat(base, toPush) {
9834 if (toPush) {
9835 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(toPush)) {
9836 Array.prototype.push.apply(base, toPush);
9837 } else {
9838 base.push(toPush);
9839 }
9840 }
9841 return base;
9842 }
9843 function splitNewlines(str) {
9844 if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) {
9845 return str.split('\n');
9846 }
9847 return str;
9848 }
9849 function createTooltipItem(chart, item) {
9850 const { element , datasetIndex , index } = item;
9851 const controller = chart.getDatasetMeta(datasetIndex).controller;
9852 const { label , value } = controller.getLabelAndValue(index);
9853 return {
9854 chart,
9855 label,
9856 parsed: controller.getParsed(index),
9857 raw: chart.data.datasets[datasetIndex].data[index],
9858 formattedValue: value,
9859 dataset: controller.getDataset(),
9860 dataIndex: index,
9861 datasetIndex,
9862 element
9863 };
9864 }
9865 function getTooltipSize(tooltip, options) {
9866 const ctx = tooltip.chart.ctx;
9867 const { body , footer , title } = tooltip;
9868 const { boxWidth , boxHeight } = options;
9869 const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);
9870 const titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont);
9871 const footerFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont);
9872 const titleLineCount = title.length;
9873 const footerLineCount = footer.length;
9874 const bodyLineItemCount = body.length;
9875 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);
9876 let height = padding.height;
9877 let width = 0;
9878 let combinedBodyLength = body.reduce((count, bodyItem)=>count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);
9879 combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;
9880 if (titleLineCount) {
9881 height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom;
9882 }
9883 if (combinedBodyLength) {
9884 const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;
9885 height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing;
9886 }
9887 if (footerLineCount) {
9888 height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing;
9889 }
9890 let widthPadding = 0;
9891 const maxLineWidth = function(line) {
9892 width = Math.max(width, ctx.measureText(line).width + widthPadding);
9893 };
9894 ctx.save();
9895 ctx.font = titleFont.string;
9896 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.title, maxLineWidth);
9897 ctx.font = bodyFont.string;
9898 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);
9899 widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0;
9900 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(body, (bodyItem)=>{
9901 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, maxLineWidth);
9902 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.lines, maxLineWidth);
9903 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, maxLineWidth);
9904 });
9905 widthPadding = 0;
9906 ctx.font = footerFont.string;
9907 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.footer, maxLineWidth);
9908 ctx.restore();
9909 width += padding.width;
9910 return {
9911 width,
9912 height
9913 };
9914 }
9915 function determineYAlign(chart, size) {
9916 const { y , height } = size;
9917 if (y < height / 2) {
9918 return 'top';
9919 } else if (y > chart.height - height / 2) {
9920 return 'bottom';
9921 }
9922 return 'center';
9923 }
9924 function doesNotFitWithAlign(xAlign, chart, options, size) {
9925 const { x , width } = size;
9926 const caret = options.caretSize + options.caretPadding;
9927 if (xAlign === 'left' && x + width + caret > chart.width) {
9928 return true;
9929 }
9930 if (xAlign === 'right' && x - width - caret < 0) {
9931 return true;
9932 }
9933 }
9934 function determineXAlign(chart, options, size, yAlign) {
9935 const { x , width } = size;
9936 const { width: chartWidth , chartArea: { left , right } } = chart;
9937 let xAlign = 'center';
9938 if (yAlign === 'center') {
9939 xAlign = x <= (left + right) / 2 ? 'left' : 'right';
9940 } else if (x <= width / 2) {
9941 xAlign = 'left';
9942 } else if (x >= chartWidth - width / 2) {
9943 xAlign = 'right';
9944 }
9945 if (doesNotFitWithAlign(xAlign, chart, options, size)) {
9946 xAlign = 'center';
9947 }
9948 return xAlign;
9949 }
9950 function determineAlignment(chart, options, size) {
9951 const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size);
9952 return {
9953 xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign),
9954 yAlign
9955 };
9956 }
9957 function alignX(size, xAlign) {
9958 let { x , width } = size;
9959 if (xAlign === 'right') {
9960 x -= width;
9961 } else if (xAlign === 'center') {
9962 x -= width / 2;
9963 }
9964 return x;
9965 }
9966 function alignY(size, yAlign, paddingAndSize) {
9967 let { y , height } = size;
9968 if (yAlign === 'top') {
9969 y += paddingAndSize;
9970 } else if (yAlign === 'bottom') {
9971 y -= height + paddingAndSize;
9972 } else {
9973 y -= height / 2;
9974 }
9975 return y;
9976 }
9977 function getBackgroundPoint(options, size, alignment, chart) {
9978 const { caretSize , caretPadding , cornerRadius } = options;
9979 const { xAlign , yAlign } = alignment;
9980 const paddingAndSize = caretSize + caretPadding;
9981 const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(cornerRadius);
9982 let x = alignX(size, xAlign);
9983 const y = alignY(size, yAlign, paddingAndSize);
9984 if (yAlign === 'center') {
9985 if (xAlign === 'left') {
9986 x += paddingAndSize;
9987 } else if (xAlign === 'right') {
9988 x -= paddingAndSize;
9989 }
9990 } else if (xAlign === 'left') {
9991 x -= Math.max(topLeft, bottomLeft) + caretSize;
9992 } else if (xAlign === 'right') {
9993 x += Math.max(topRight, bottomRight) + caretSize;
9994 }
9995 return {
9996 x: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(x, 0, chart.width - size.width),
9997 y: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(y, 0, chart.height - size.height)
9998 };
9999 }
10000 function getAlignedX(tooltip, align, options) {
10001 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);
10002 return align === 'center' ? tooltip.x + tooltip.width / 2 : align === 'right' ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left;
10003 }
10004 function getBeforeAfterBodyLines(callback) {
10005 return pushOrConcat([], splitNewlines(callback));
10006 }
10007 function createTooltipContext(parent, tooltip, tooltipItems) {
10008 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
10009 tooltip,
10010 tooltipItems,
10011 type: 'tooltip'
10012 });
10013 }
10014 function overrideCallbacks(callbacks, context) {
10015 const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;
10016 return override ? callbacks.override(override) : callbacks;
10017 }
10018 const defaultCallbacks = {
10019 beforeTitle: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10020 title (tooltipItems) {
10021 if (tooltipItems.length > 0) {
10022 const item = tooltipItems[0];
10023 const labels = item.chart.data.labels;
10024 const labelCount = labels ? labels.length : 0;
10025 if (this && this.options && this.options.mode === 'dataset') {
10026 return item.dataset.label || '';
10027 } else if (item.label) {
10028 return item.label;
10029 } else if (labelCount > 0 && item.dataIndex < labelCount) {
10030 return labels[item.dataIndex];
10031 }
10032 }
10033 return '';
10034 },
10035 afterTitle: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10036 beforeBody: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10037 beforeLabel: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10038 label (tooltipItem) {
10039 if (this && this.options && this.options.mode === 'dataset') {
10040 return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue;
10041 }
10042 let label = tooltipItem.dataset.label || '';
10043 if (label) {
10044 label += ': ';
10045 }
10046 const value = tooltipItem.formattedValue;
10047 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {
10048 label += value;
10049 }
10050 return label;
10051 },
10052 labelColor (tooltipItem) {
10053 const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
10054 const options = meta.controller.getStyle(tooltipItem.dataIndex);
10055 return {
10056 borderColor: options.borderColor,
10057 backgroundColor: options.backgroundColor,
10058 borderWidth: options.borderWidth,
10059 borderDash: options.borderDash,
10060 borderDashOffset: options.borderDashOffset,
10061 borderRadius: 0
10062 };
10063 },
10064 labelTextColor () {
10065 return this.options.bodyColor;
10066 },
10067 labelPointStyle (tooltipItem) {
10068 const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
10069 const options = meta.controller.getStyle(tooltipItem.dataIndex);
10070 return {
10071 pointStyle: options.pointStyle,
10072 rotation: options.rotation
10073 };
10074 },
10075 afterLabel: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10076 afterBody: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10077 beforeFooter: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10078 footer: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG,
10079 afterFooter: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aG
10080 };
10081 function invokeCallbackWithFallback(callbacks, name, ctx, arg) {
10082 const result = callbacks[name].call(ctx, arg);
10083 if (typeof result === 'undefined') {
10084 return defaultCallbacks[name].call(ctx, arg);
10085 }
10086 return result;
10087 }
10088 class Tooltip extends Element {
10089 static positioners = positioners;
10090 constructor(config){
10091 super();
10092 this.opacity = 0;
10093 this._active = [];
10094 this._eventPosition = undefined;
10095 this._size = undefined;
10096 this._cachedAnimations = undefined;
10097 this._tooltipItems = [];
10098 this.$animations = undefined;
10099 this.$context = undefined;
10100 this.chart = config.chart;
10101 this.options = config.options;
10102 this.dataPoints = undefined;
10103 this.title = undefined;
10104 this.beforeBody = undefined;
10105 this.body = undefined;
10106 this.afterBody = undefined;
10107 this.footer = undefined;
10108 this.xAlign = undefined;
10109 this.yAlign = undefined;
10110 this.x = undefined;
10111 this.y = undefined;
10112 this.height = undefined;
10113 this.width = undefined;
10114 this.caretX = undefined;
10115 this.caretY = undefined;
10116 this.labelColors = undefined;
10117 this.labelPointStyles = undefined;
10118 this.labelTextColors = undefined;
10119 }
10120 initialize(options) {
10121 this.options = options;
10122 this._cachedAnimations = undefined;
10123 this.$context = undefined;
10124 }
10125 _resolveAnimations() {
10126 const cached = this._cachedAnimations;
10127 if (cached) {
10128 return cached;
10129 }
10130 const chart = this.chart;
10131 const options = this.options.setContext(this.getContext());
10132 const opts = options.enabled && chart.options.animation && options.animations;
10133 const animations = new Animations(this.chart, opts);
10134 if (opts._cacheable) {
10135 this._cachedAnimations = Object.freeze(animations);
10136 }
10137 return animations;
10138 }
10139 getContext() {
10140 return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems));
10141 }
10142 getTitle(context, options) {
10143 const { callbacks } = options;
10144 const beforeTitle = invokeCallbackWithFallback(callbacks, 'beforeTitle', this, context);
10145 const title = invokeCallbackWithFallback(callbacks, 'title', this, context);
10146 const afterTitle = invokeCallbackWithFallback(callbacks, 'afterTitle', this, context);
10147 let lines = [];
10148 lines = pushOrConcat(lines, splitNewlines(beforeTitle));
10149 lines = pushOrConcat(lines, splitNewlines(title));
10150 lines = pushOrConcat(lines, splitNewlines(afterTitle));
10151 return lines;
10152 }
10153 getBeforeBody(tooltipItems, options) {
10154 return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'beforeBody', this, tooltipItems));
10155 }
10156 getBody(tooltipItems, options) {
10157 const { callbacks } = options;
10158 const bodyItems = [];
10159 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{
10160 const bodyItem = {
10161 before: [],
10162 lines: [],
10163 after: []
10164 };
10165 const scoped = overrideCallbacks(callbacks, context);
10166 pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, 'beforeLabel', this, context)));
10167 pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, 'label', this, context));
10168 pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, 'afterLabel', this, context)));
10169 bodyItems.push(bodyItem);
10170 });
10171 return bodyItems;
10172 }
10173 getAfterBody(tooltipItems, options) {
10174 return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'afterBody', this, tooltipItems));
10175 }
10176 getFooter(tooltipItems, options) {
10177 const { callbacks } = options;
10178 const beforeFooter = invokeCallbackWithFallback(callbacks, 'beforeFooter', this, tooltipItems);
10179 const footer = invokeCallbackWithFallback(callbacks, 'footer', this, tooltipItems);
10180 const afterFooter = invokeCallbackWithFallback(callbacks, 'afterFooter', this, tooltipItems);
10181 let lines = [];
10182 lines = pushOrConcat(lines, splitNewlines(beforeFooter));
10183 lines = pushOrConcat(lines, splitNewlines(footer));
10184 lines = pushOrConcat(lines, splitNewlines(afterFooter));
10185 return lines;
10186 }
10187 _createItems(options) {
10188 const active = this._active;
10189 const data = this.chart.data;
10190 const labelColors = [];
10191 const labelPointStyles = [];
10192 const labelTextColors = [];
10193 let tooltipItems = [];
10194 let i, len;
10195 for(i = 0, len = active.length; i < len; ++i){
10196 tooltipItems.push(createTooltipItem(this.chart, active[i]));
10197 }
10198 if (options.filter) {
10199 tooltipItems = tooltipItems.filter((element, index, array)=>options.filter(element, index, array, data));
10200 }
10201 if (options.itemSort) {
10202 tooltipItems = tooltipItems.sort((a, b)=>options.itemSort(a, b, data));
10203 }
10204 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{
10205 const scoped = overrideCallbacks(options.callbacks, context);
10206 labelColors.push(invokeCallbackWithFallback(scoped, 'labelColor', this, context));
10207 labelPointStyles.push(invokeCallbackWithFallback(scoped, 'labelPointStyle', this, context));
10208 labelTextColors.push(invokeCallbackWithFallback(scoped, 'labelTextColor', this, context));
10209 });
10210 this.labelColors = labelColors;
10211 this.labelPointStyles = labelPointStyles;
10212 this.labelTextColors = labelTextColors;
10213 this.dataPoints = tooltipItems;
10214 return tooltipItems;
10215 }
10216 update(changed, replay) {
10217 const options = this.options.setContext(this.getContext());
10218 const active = this._active;
10219 let properties;
10220 let tooltipItems = [];
10221 if (!active.length) {
10222 if (this.opacity !== 0) {
10223 properties = {
10224 opacity: 0
10225 };
10226 }
10227 } else {
10228 const position = positioners[options.position].call(this, active, this._eventPosition);
10229 tooltipItems = this._createItems(options);
10230 this.title = this.getTitle(tooltipItems, options);
10231 this.beforeBody = this.getBeforeBody(tooltipItems, options);
10232 this.body = this.getBody(tooltipItems, options);
10233 this.afterBody = this.getAfterBody(tooltipItems, options);
10234 this.footer = this.getFooter(tooltipItems, options);
10235 const size = this._size = getTooltipSize(this, options);
10236 const positionAndSize = Object.assign({}, position, size);
10237 const alignment = determineAlignment(this.chart, options, positionAndSize);
10238 const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart);
10239 this.xAlign = alignment.xAlign;
10240 this.yAlign = alignment.yAlign;
10241 properties = {
10242 opacity: 1,
10243 x: backgroundPoint.x,
10244 y: backgroundPoint.y,
10245 width: size.width,
10246 height: size.height,
10247 caretX: position.x,
10248 caretY: position.y
10249 };
10250 }
10251 this._tooltipItems = tooltipItems;
10252 this.$context = undefined;
10253 if (properties) {
10254 this._resolveAnimations().update(this, properties);
10255 }
10256 if (changed && options.external) {
10257 options.external.call(this, {
10258 chart: this.chart,
10259 tooltip: this,
10260 replay
10261 });
10262 }
10263 }
10264 drawCaret(tooltipPoint, ctx, size, options) {
10265 const caretPosition = this.getCaretPosition(tooltipPoint, size, options);
10266 ctx.lineTo(caretPosition.x1, caretPosition.y1);
10267 ctx.lineTo(caretPosition.x2, caretPosition.y2);
10268 ctx.lineTo(caretPosition.x3, caretPosition.y3);
10269 }
10270 getCaretPosition(tooltipPoint, size, options) {
10271 const { xAlign , yAlign } = this;
10272 const { caretSize , cornerRadius } = options;
10273 const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(cornerRadius);
10274 const { x: ptX , y: ptY } = tooltipPoint;
10275 const { width , height } = size;
10276 let x1, x2, x3, y1, y2, y3;
10277 if (yAlign === 'center') {
10278 y2 = ptY + height / 2;
10279 if (xAlign === 'left') {
10280 x1 = ptX;
10281 x2 = x1 - caretSize;
10282 y1 = y2 + caretSize;
10283 y3 = y2 - caretSize;
10284 } else {
10285 x1 = ptX + width;
10286 x2 = x1 + caretSize;
10287 y1 = y2 - caretSize;
10288 y3 = y2 + caretSize;
10289 }
10290 x3 = x1;
10291 } else {
10292 if (xAlign === 'left') {
10293 x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize;
10294 } else if (xAlign === 'right') {
10295 x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;
10296 } else {
10297 x2 = this.caretX;
10298 }
10299 if (yAlign === 'top') {
10300 y1 = ptY;
10301 y2 = y1 - caretSize;
10302 x1 = x2 - caretSize;
10303 x3 = x2 + caretSize;
10304 } else {
10305 y1 = ptY + height;
10306 y2 = y1 + caretSize;
10307 x1 = x2 + caretSize;
10308 x3 = x2 - caretSize;
10309 }
10310 y3 = y1;
10311 }
10312 return {
10313 x1,
10314 x2,
10315 x3,
10316 y1,
10317 y2,
10318 y3
10319 };
10320 }
10321 drawTitle(pt, ctx, options) {
10322 const title = this.title;
10323 const length = title.length;
10324 let titleFont, titleSpacing, i;
10325 if (length) {
10326 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);
10327 pt.x = getAlignedX(this, options.titleAlign, options);
10328 ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
10329 ctx.textBaseline = 'middle';
10330 titleFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont);
10331 titleSpacing = options.titleSpacing;
10332 ctx.fillStyle = options.titleColor;
10333 ctx.font = titleFont.string;
10334 for(i = 0; i < length; ++i){
10335 ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);
10336 pt.y += titleFont.lineHeight + titleSpacing;
10337 if (i + 1 === length) {
10338 pt.y += options.titleMarginBottom - titleSpacing;
10339 }
10340 }
10341 }
10342 }
10343 _drawColorBox(ctx, pt, i, rtlHelper, options) {
10344 const labelColor = this.labelColors[i];
10345 const labelPointStyle = this.labelPointStyles[i];
10346 const { boxHeight , boxWidth } = options;
10347 const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);
10348 const colorX = getAlignedX(this, 'left', options);
10349 const rtlColorX = rtlHelper.x(colorX);
10350 const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
10351 const colorY = pt.y + yOffSet;
10352 if (options.usePointStyle) {
10353 const drawOptions = {
10354 radius: Math.min(boxWidth, boxHeight) / 2,
10355 pointStyle: labelPointStyle.pointStyle,
10356 rotation: labelPointStyle.rotation,
10357 borderWidth: 1
10358 };
10359 const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;
10360 const centerY = colorY + boxHeight / 2;
10361 ctx.strokeStyle = options.multiKeyBackground;
10362 ctx.fillStyle = options.multiKeyBackground;
10363 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, drawOptions, centerX, centerY);
10364 ctx.strokeStyle = labelColor.borderColor;
10365 ctx.fillStyle = labelColor.backgroundColor;
10366 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.av)(ctx, drawOptions, centerX, centerY);
10367 } else {
10368 ctx.lineWidth = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.i)(labelColor.borderWidth) ? Math.max(...Object.values(labelColor.borderWidth)) : labelColor.borderWidth || 1;
10369 ctx.strokeStyle = labelColor.borderColor;
10370 ctx.setLineDash(labelColor.borderDash || []);
10371 ctx.lineDashOffset = labelColor.borderDashOffset || 0;
10372 const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth);
10373 const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2);
10374 const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(labelColor.borderRadius);
10375 if (Object.values(borderRadius).some((v)=>v !== 0)) {
10376 ctx.beginPath();
10377 ctx.fillStyle = options.multiKeyBackground;
10378 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {
10379 x: outerX,
10380 y: colorY,
10381 w: boxWidth,
10382 h: boxHeight,
10383 radius: borderRadius
10384 });
10385 ctx.fill();
10386 ctx.stroke();
10387 ctx.fillStyle = labelColor.backgroundColor;
10388 ctx.beginPath();
10389 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {
10390 x: innerX,
10391 y: colorY + 1,
10392 w: boxWidth - 2,
10393 h: boxHeight - 2,
10394 radius: borderRadius
10395 });
10396 ctx.fill();
10397 } else {
10398 ctx.fillStyle = options.multiKeyBackground;
10399 ctx.fillRect(outerX, colorY, boxWidth, boxHeight);
10400 ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);
10401 ctx.fillStyle = labelColor.backgroundColor;
10402 ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);
10403 }
10404 }
10405 ctx.fillStyle = this.labelTextColors[i];
10406 }
10407 drawBody(pt, ctx, options) {
10408 const { body } = this;
10409 const { bodySpacing , bodyAlign , displayColors , boxHeight , boxWidth , boxPadding } = options;
10410 const bodyFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont);
10411 let bodyLineHeight = bodyFont.lineHeight;
10412 let xLinePadding = 0;
10413 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);
10414 const fillLineOfText = function(line) {
10415 ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);
10416 pt.y += bodyLineHeight + bodySpacing;
10417 };
10418 const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);
10419 let bodyItem, textColor, lines, i, j, ilen, jlen;
10420 ctx.textAlign = bodyAlign;
10421 ctx.textBaseline = 'middle';
10422 ctx.font = bodyFont.string;
10423 pt.x = getAlignedX(this, bodyAlignForCalculation, options);
10424 ctx.fillStyle = options.bodyColor;
10425 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.beforeBody, fillLineOfText);
10426 xLinePadding = displayColors && bodyAlignForCalculation !== 'right' ? bodyAlign === 'center' ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0;
10427 for(i = 0, ilen = body.length; i < ilen; ++i){
10428 bodyItem = body[i];
10429 textColor = this.labelTextColors[i];
10430 ctx.fillStyle = textColor;
10431 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, fillLineOfText);
10432 lines = bodyItem.lines;
10433 if (displayColors && lines.length) {
10434 this._drawColorBox(ctx, pt, i, rtlHelper, options);
10435 bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
10436 }
10437 for(j = 0, jlen = lines.length; j < jlen; ++j){
10438 fillLineOfText(lines[j]);
10439 bodyLineHeight = bodyFont.lineHeight;
10440 }
10441 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, fillLineOfText);
10442 }
10443 xLinePadding = 0;
10444 bodyLineHeight = bodyFont.lineHeight;
10445 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.afterBody, fillLineOfText);
10446 pt.y -= bodySpacing;
10447 }
10448 drawFooter(pt, ctx, options) {
10449 const footer = this.footer;
10450 const length = footer.length;
10451 let footerFont, i;
10452 if (length) {
10453 const rtlHelper = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aA)(options.rtl, this.x, this.width);
10454 pt.x = getAlignedX(this, options.footerAlign, options);
10455 pt.y += options.footerMarginTop;
10456 ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
10457 ctx.textBaseline = 'middle';
10458 footerFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont);
10459 ctx.fillStyle = options.footerColor;
10460 ctx.font = footerFont.string;
10461 for(i = 0; i < length; ++i){
10462 ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);
10463 pt.y += footerFont.lineHeight + options.footerSpacing;
10464 }
10465 }
10466 }
10467 drawBackground(pt, ctx, tooltipSize, options) {
10468 const { xAlign , yAlign } = this;
10469 const { x , y } = pt;
10470 const { width , height } = tooltipSize;
10471 const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(options.cornerRadius);
10472 ctx.fillStyle = options.backgroundColor;
10473 ctx.strokeStyle = options.borderColor;
10474 ctx.lineWidth = options.borderWidth;
10475 ctx.beginPath();
10476 ctx.moveTo(x + topLeft, y);
10477 if (yAlign === 'top') {
10478 this.drawCaret(pt, ctx, tooltipSize, options);
10479 }
10480 ctx.lineTo(x + width - topRight, y);
10481 ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);
10482 if (yAlign === 'center' && xAlign === 'right') {
10483 this.drawCaret(pt, ctx, tooltipSize, options);
10484 }
10485 ctx.lineTo(x + width, y + height - bottomRight);
10486 ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);
10487 if (yAlign === 'bottom') {
10488 this.drawCaret(pt, ctx, tooltipSize, options);
10489 }
10490 ctx.lineTo(x + bottomLeft, y + height);
10491 ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);
10492 if (yAlign === 'center' && xAlign === 'left') {
10493 this.drawCaret(pt, ctx, tooltipSize, options);
10494 }
10495 ctx.lineTo(x, y + topLeft);
10496 ctx.quadraticCurveTo(x, y, x + topLeft, y);
10497 ctx.closePath();
10498 ctx.fill();
10499 if (options.borderWidth > 0) {
10500 ctx.stroke();
10501 }
10502 }
10503 _updateAnimationTarget(options) {
10504 const chart = this.chart;
10505 const anims = this.$animations;
10506 const animX = anims && anims.x;
10507 const animY = anims && anims.y;
10508 if (animX || animY) {
10509 const position = positioners[options.position].call(this, this._active, this._eventPosition);
10510 if (!position) {
10511 return;
10512 }
10513 const size = this._size = getTooltipSize(this, options);
10514 const positionAndSize = Object.assign({}, position, this._size);
10515 const alignment = determineAlignment(chart, options, positionAndSize);
10516 const point = getBackgroundPoint(options, positionAndSize, alignment, chart);
10517 if (animX._to !== point.x || animY._to !== point.y) {
10518 this.xAlign = alignment.xAlign;
10519 this.yAlign = alignment.yAlign;
10520 this.width = size.width;
10521 this.height = size.height;
10522 this.caretX = position.x;
10523 this.caretY = position.y;
10524 this._resolveAnimations().update(this, point);
10525 }
10526 }
10527 }
10528 _willRender() {
10529 return !!this.opacity;
10530 }
10531 draw(ctx) {
10532 const options = this.options.setContext(this.getContext());
10533 let opacity = this.opacity;
10534 if (!opacity) {
10535 return;
10536 }
10537 this._updateAnimationTarget(options);
10538 const tooltipSize = {
10539 width: this.width,
10540 height: this.height
10541 };
10542 const pt = {
10543 x: this.x,
10544 y: this.y
10545 };
10546 opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;
10547 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding);
10548 const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;
10549 if (options.enabled && hasTooltipContent) {
10550 ctx.save();
10551 ctx.globalAlpha = opacity;
10552 this.drawBackground(pt, ctx, tooltipSize, options);
10553 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aB)(ctx, options.textDirection);
10554 pt.y += padding.top;
10555 this.drawTitle(pt, ctx, options);
10556 this.drawBody(pt, ctx, options);
10557 this.drawFooter(pt, ctx, options);
10558 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aD)(ctx, options.textDirection);
10559 ctx.restore();
10560 }
10561 }
10562 getActiveElements() {
10563 return this._active || [];
10564 }
10565 setActiveElements(activeElements, eventPosition) {
10566 const lastActive = this._active;
10567 const active = activeElements.map(({ datasetIndex , index })=>{
10568 const meta = this.chart.getDatasetMeta(datasetIndex);
10569 if (!meta) {
10570 throw new Error('Cannot find a dataset at index ' + datasetIndex);
10571 }
10572 return {
10573 datasetIndex,
10574 element: meta.data[index],
10575 index
10576 };
10577 });
10578 const changed = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(lastActive, active);
10579 const positionChanged = this._positionChanged(active, eventPosition);
10580 if (changed || positionChanged) {
10581 this._active = active;
10582 this._eventPosition = eventPosition;
10583 this._ignoreReplayEvents = true;
10584 this.update(true);
10585 }
10586 }
10587 handleEvent(e, replay, inChartArea = true) {
10588 if (replay && this._ignoreReplayEvents) {
10589 return false;
10590 }
10591 this._ignoreReplayEvents = false;
10592 const options = this.options;
10593 const lastActive = this._active || [];
10594 const active = this._getActiveElements(e, lastActive, replay, inChartArea);
10595 const positionChanged = this._positionChanged(active, e);
10596 const changed = replay || !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ai)(active, lastActive) || positionChanged;
10597 if (changed) {
10598 this._active = active;
10599 if (options.enabled || options.external) {
10600 this._eventPosition = {
10601 x: e.x,
10602 y: e.y
10603 };
10604 this.update(true, replay);
10605 }
10606 }
10607 return changed;
10608 }
10609 _getActiveElements(e, lastActive, replay, inChartArea) {
10610 const options = this.options;
10611 if (e.type === 'mouseout') {
10612 return [];
10613 }
10614 if (!inChartArea) {
10615 return lastActive.filter((i)=>this.chart.data.datasets[i.datasetIndex] && this.chart.getDatasetMeta(i.datasetIndex).controller.getParsed(i.index) !== undefined);
10616 }
10617 const active = this.chart.getElementsAtEventForMode(e, options.mode, options, replay);
10618 if (options.reverse) {
10619 active.reverse();
10620 }
10621 return active;
10622 }
10623 _positionChanged(active, e) {
10624 const { caretX , caretY , options } = this;
10625 const position = positioners[options.position].call(this, active, e);
10626 return position !== false && (caretX !== position.x || caretY !== position.y);
10627 }
10628 }
10629 var plugin_tooltip = {
10630 id: 'tooltip',
10631 _element: Tooltip,
10632 positioners,
10633 afterInit (chart, _args, options) {
10634 if (options) {
10635 chart.tooltip = new Tooltip({
10636 chart,
10637 options
10638 });
10639 }
10640 },
10641 beforeUpdate (chart, _args, options) {
10642 if (chart.tooltip) {
10643 chart.tooltip.initialize(options);
10644 }
10645 },
10646 reset (chart, _args, options) {
10647 if (chart.tooltip) {
10648 chart.tooltip.initialize(options);
10649 }
10650 },
10651 afterDraw (chart) {
10652 const tooltip = chart.tooltip;
10653 if (tooltip && tooltip._willRender()) {
10654 const args = {
10655 tooltip
10656 };
10657 if (chart.notifyPlugins('beforeTooltipDraw', {
10658 ...args,
10659 cancelable: true
10660 }) === false) {
10661 return;
10662 }
10663 tooltip.draw(chart.ctx);
10664 chart.notifyPlugins('afterTooltipDraw', args);
10665 }
10666 },
10667 afterEvent (chart, args) {
10668 if (chart.tooltip) {
10669 const useFinalPosition = args.replay;
10670 if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) {
10671 args.changed = true;
10672 }
10673 }
10674 },
10675 defaults: {
10676 enabled: true,
10677 external: null,
10678 position: 'average',
10679 backgroundColor: 'rgba(0,0,0,0.8)',
10680 titleColor: '#fff',
10681 titleFont: {
10682 weight: 'bold'
10683 },
10684 titleSpacing: 2,
10685 titleMarginBottom: 6,
10686 titleAlign: 'left',
10687 bodyColor: '#fff',
10688 bodySpacing: 2,
10689 bodyFont: {},
10690 bodyAlign: 'left',
10691 footerColor: '#fff',
10692 footerSpacing: 2,
10693 footerMarginTop: 6,
10694 footerFont: {
10695 weight: 'bold'
10696 },
10697 footerAlign: 'left',
10698 padding: 6,
10699 caretPadding: 2,
10700 caretSize: 5,
10701 cornerRadius: 6,
10702 boxHeight: (ctx, opts)=>opts.bodyFont.size,
10703 boxWidth: (ctx, opts)=>opts.bodyFont.size,
10704 multiKeyBackground: '#fff',
10705 displayColors: true,
10706 boxPadding: 0,
10707 borderColor: 'rgba(0,0,0,0)',
10708 borderWidth: 0,
10709 animation: {
10710 duration: 400,
10711 easing: 'easeOutQuart'
10712 },
10713 animations: {
10714 numbers: {
10715 type: 'number',
10716 properties: [
10717 'x',
10718 'y',
10719 'width',
10720 'height',
10721 'caretX',
10722 'caretY'
10723 ]
10724 },
10725 opacity: {
10726 easing: 'linear',
10727 duration: 200
10728 }
10729 },
10730 callbacks: defaultCallbacks
10731 },
10732 defaultRoutes: {
10733 bodyFont: 'font',
10734 footerFont: 'font',
10735 titleFont: 'font'
10736 },
10737 descriptors: {
10738 _scriptable: (name)=>name !== 'filter' && name !== 'itemSort' && name !== 'external',
10739 _indexable: false,
10740 callbacks: {
10741 _scriptable: false,
10742 _indexable: false
10743 },
10744 animation: {
10745 _fallback: false
10746 },
10747 animations: {
10748 _fallback: 'animation'
10749 }
10750 },
10751 additionalOptionScopes: [
10752 'interaction'
10753 ]
10754 };
10755
10756 var plugins = /*#__PURE__*/Object.freeze({
10757 __proto__: null,
10758 Colors: plugin_colors,
10759 Decimation: plugin_decimation,
10760 Filler: index,
10761 Legend: plugin_legend,
10762 SubTitle: plugin_subtitle,
10763 Title: plugin_title,
10764 Tooltip: plugin_tooltip
10765 });
10766
10767 const addIfString = (labels, raw, index, addedLabels)=>{
10768 if (typeof raw === 'string') {
10769 index = labels.push(raw) - 1;
10770 addedLabels.unshift({
10771 index,
10772 label: raw
10773 });
10774 } else if (isNaN(raw)) {
10775 index = null;
10776 }
10777 return index;
10778 };
10779 function findOrAddLabel(labels, raw, index, addedLabels) {
10780 const first = labels.indexOf(raw);
10781 if (first === -1) {
10782 return addIfString(labels, raw, index, addedLabels);
10783 }
10784 const last = labels.lastIndexOf(raw);
10785 return first !== last ? index : first;
10786 }
10787 const validIndex = (index, max)=>index === null ? null : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(Math.round(index), 0, max);
10788 function _getLabelForValue(value) {
10789 const labels = this.getLabels();
10790 if (value >= 0 && value < labels.length) {
10791 return labels[value];
10792 }
10793 return value;
10794 }
10795 class CategoryScale extends Scale {
10796 static id = 'category';
10797 static defaults = {
10798 ticks: {
10799 callback: _getLabelForValue
10800 }
10801 };
10802 constructor(cfg){
10803 super(cfg);
10804 this._startValue = undefined;
10805 this._valueRange = 0;
10806 this._addedLabels = [];
10807 }
10808 init(scaleOptions) {
10809 const added = this._addedLabels;
10810 if (added.length) {
10811 const labels = this.getLabels();
10812 for (const { index , label } of added){
10813 if (labels[index] === label) {
10814 labels.splice(index, 1);
10815 }
10816 }
10817 this._addedLabels = [];
10818 }
10819 super.init(scaleOptions);
10820 }
10821 parse(raw, index) {
10822 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) {
10823 return null;
10824 }
10825 const labels = this.getLabels();
10826 index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(index, raw), this._addedLabels);
10827 return validIndex(index, labels.length - 1);
10828 }
10829 determineDataLimits() {
10830 const { minDefined , maxDefined } = this.getUserBounds();
10831 let { min , max } = this.getMinMax(true);
10832 if (this.options.bounds === 'ticks') {
10833 if (!minDefined) {
10834 min = 0;
10835 }
10836 if (!maxDefined) {
10837 max = this.getLabels().length - 1;
10838 }
10839 }
10840 this.min = min;
10841 this.max = max;
10842 }
10843 buildTicks() {
10844 const min = this.min;
10845 const max = this.max;
10846 const offset = this.options.offset;
10847 const ticks = [];
10848 let labels = this.getLabels();
10849 labels = min === 0 && max === labels.length - 1 ? labels : labels.slice(min, max + 1);
10850 this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);
10851 this._startValue = this.min - (offset ? 0.5 : 0);
10852 for(let value = min; value <= max; value++){
10853 ticks.push({
10854 value
10855 });
10856 }
10857 return ticks;
10858 }
10859 getLabelForValue(value) {
10860 return _getLabelForValue.call(this, value);
10861 }
10862 configure() {
10863 super.configure();
10864 if (!this.isHorizontal()) {
10865 this._reversePixels = !this._reversePixels;
10866 }
10867 }
10868 getPixelForValue(value) {
10869 if (typeof value !== 'number') {
10870 value = this.parse(value);
10871 }
10872 return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
10873 }
10874 getPixelForTick(index) {
10875 const ticks = this.ticks;
10876 if (index < 0 || index > ticks.length - 1) {
10877 return null;
10878 }
10879 return this.getPixelForValue(ticks[index].value);
10880 }
10881 getValueForPixel(pixel) {
10882 return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);
10883 }
10884 getBasePixel() {
10885 return this.bottom;
10886 }
10887 }
10888
10889 function generateTicks$1(generationOptions, dataRange) {
10890 const ticks = [];
10891 const MIN_SPACING = 1e-14;
10892 const { bounds , step , min , max , precision , count , maxTicks , maxDigits , includeBounds } = generationOptions;
10893 const unit = step || 1;
10894 const maxSpaces = maxTicks - 1;
10895 const { min: rmin , max: rmax } = dataRange;
10896 const minDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(min);
10897 const maxDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(max);
10898 const countDefined = !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(count);
10899 const minSpacing = (rmax - rmin) / (maxDigits + 1);
10900 let spacing = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aI)((rmax - rmin) / maxSpaces / unit) * unit;
10901 let factor, niceMin, niceMax, numSpaces;
10902 if (spacing < MIN_SPACING && !minDefined && !maxDefined) {
10903 return [
10904 {
10905 value: rmin
10906 },
10907 {
10908 value: rmax
10909 }
10910 ];
10911 }
10912 numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
10913 if (numSpaces > maxSpaces) {
10914 spacing = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aI)(numSpaces * spacing / maxSpaces / unit) * unit;
10915 }
10916 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision)) {
10917 factor = Math.pow(10, precision);
10918 spacing = Math.ceil(spacing * factor) / factor;
10919 }
10920 if (bounds === 'ticks') {
10921 niceMin = Math.floor(rmin / spacing) * spacing;
10922 niceMax = Math.ceil(rmax / spacing) * spacing;
10923 } else {
10924 niceMin = rmin;
10925 niceMax = rmax;
10926 }
10927 if (minDefined && maxDefined && step && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aJ)((max - min) / step, spacing / 1000)) {
10928 numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks));
10929 spacing = (max - min) / numSpaces;
10930 niceMin = min;
10931 niceMax = max;
10932 } else if (countDefined) {
10933 niceMin = minDefined ? min : niceMin;
10934 niceMax = maxDefined ? max : niceMax;
10935 numSpaces = count - 1;
10936 spacing = (niceMax - niceMin) / numSpaces;
10937 } else {
10938 numSpaces = (niceMax - niceMin) / spacing;
10939 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(numSpaces, Math.round(numSpaces), spacing / 1000)) {
10940 numSpaces = Math.round(numSpaces);
10941 } else {
10942 numSpaces = Math.ceil(numSpaces);
10943 }
10944 }
10945 const decimalPlaces = Math.max((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aL)(spacing), (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aL)(niceMin));
10946 factor = Math.pow(10, (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision) ? decimalPlaces : precision);
10947 niceMin = Math.round(niceMin * factor) / factor;
10948 niceMax = Math.round(niceMax * factor) / factor;
10949 let j = 0;
10950 if (minDefined) {
10951 if (includeBounds && niceMin !== min) {
10952 ticks.push({
10953 value: min
10954 });
10955 if (niceMin < min) {
10956 j++;
10957 }
10958 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) {
10959 j++;
10960 }
10961 } else if (niceMin < min) {
10962 j++;
10963 }
10964 }
10965 for(; j < numSpaces; ++j){
10966 const tickValue = Math.round((niceMin + j * spacing) * factor) / factor;
10967 if (maxDefined && tickValue > max) {
10968 break;
10969 }
10970 ticks.push({
10971 value: tickValue
10972 });
10973 }
10974 if (maxDefined && includeBounds && niceMax !== max) {
10975 if (ticks.length && (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aK)(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) {
10976 ticks[ticks.length - 1].value = max;
10977 } else {
10978 ticks.push({
10979 value: max
10980 });
10981 }
10982 } else if (!maxDefined || niceMax === max) {
10983 ticks.push({
10984 value: niceMax
10985 });
10986 }
10987 return ticks;
10988 }
10989 function relativeLabelSize(value, minSpacing, { horizontal , minRotation }) {
10990 const rad = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(minRotation);
10991 const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001;
10992 const length = 0.75 * minSpacing * ('' + value).length;
10993 return Math.min(minSpacing / ratio, length);
10994 }
10995 class LinearScaleBase extends Scale {
10996 constructor(cfg){
10997 super(cfg);
10998 this.start = undefined;
10999 this.end = undefined;
11000 this._startValue = undefined;
11001 this._endValue = undefined;
11002 this._valueRange = 0;
11003 }
11004 parse(raw, index) {
11005 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) {
11006 return null;
11007 }
11008 if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) {
11009 return null;
11010 }
11011 return +raw;
11012 }
11013 handleTickRangeOptions() {
11014 const { beginAtZero } = this.options;
11015 const { minDefined , maxDefined } = this.getUserBounds();
11016 let { min , max } = this;
11017 const setMin = (v)=>min = minDefined ? min : v;
11018 const setMax = (v)=>max = maxDefined ? max : v;
11019 if (beginAtZero) {
11020 const minSign = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(min);
11021 const maxSign = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.s)(max);
11022 if (minSign < 0 && maxSign < 0) {
11023 setMax(0);
11024 } else if (minSign > 0 && maxSign > 0) {
11025 setMin(0);
11026 }
11027 }
11028 if (min === max) {
11029 let offset = max === 0 ? 1 : Math.abs(max * 0.05);
11030 setMax(max + offset);
11031 if (!beginAtZero) {
11032 setMin(min - offset);
11033 }
11034 }
11035 this.min = min;
11036 this.max = max;
11037 }
11038 getTickLimit() {
11039 const tickOpts = this.options.ticks;
11040 let { maxTicksLimit , stepSize } = tickOpts;
11041 let maxTicks;
11042 if (stepSize) {
11043 maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;
11044 if (maxTicks > 1000) {
11045 console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);
11046 maxTicks = 1000;
11047 }
11048 } else {
11049 maxTicks = this.computeTickLimit();
11050 maxTicksLimit = maxTicksLimit || 11;
11051 }
11052 if (maxTicksLimit) {
11053 maxTicks = Math.min(maxTicksLimit, maxTicks);
11054 }
11055 return maxTicks;
11056 }
11057 computeTickLimit() {
11058 return Number.POSITIVE_INFINITY;
11059 }
11060 buildTicks() {
11061 const opts = this.options;
11062 const tickOpts = opts.ticks;
11063 let maxTicks = this.getTickLimit();
11064 maxTicks = Math.max(2, maxTicks);
11065 const numericGeneratorOptions = {
11066 maxTicks,
11067 bounds: opts.bounds,
11068 min: opts.min,
11069 max: opts.max,
11070 precision: tickOpts.precision,
11071 step: tickOpts.stepSize,
11072 count: tickOpts.count,
11073 maxDigits: this._maxDigits(),
11074 horizontal: this.isHorizontal(),
11075 minRotation: tickOpts.minRotation || 0,
11076 includeBounds: tickOpts.includeBounds !== false
11077 };
11078 const dataRange = this._range || this;
11079 const ticks = generateTicks$1(numericGeneratorOptions, dataRange);
11080 if (opts.bounds === 'ticks') {
11081 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aH)(ticks, this, 'value');
11082 }
11083 if (opts.reverse) {
11084 ticks.reverse();
11085 this.start = this.max;
11086 this.end = this.min;
11087 } else {
11088 this.start = this.min;
11089 this.end = this.max;
11090 }
11091 return ticks;
11092 }
11093 configure() {
11094 const ticks = this.ticks;
11095 let start = this.min;
11096 let end = this.max;
11097 super.configure();
11098 if (this.options.offset && ticks.length) {
11099 const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;
11100 start -= offset;
11101 end += offset;
11102 }
11103 this._startValue = start;
11104 this._endValue = end;
11105 this._valueRange = end - start;
11106 }
11107 getLabelForValue(value) {
11108 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format);
11109 }
11110 }
11111
11112 class LinearScale extends LinearScaleBase {
11113 static id = 'linear';
11114 static defaults = {
11115 ticks: {
11116 callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.numeric
11117 }
11118 };
11119 determineDataLimits() {
11120 const { min , max } = this.getMinMax(true);
11121 this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? min : 0;
11122 this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? max : 1;
11123 this.handleTickRangeOptions();
11124 }
11125 computeTickLimit() {
11126 const horizontal = this.isHorizontal();
11127 const length = horizontal ? this.width : this.height;
11128 const minRotation = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.ticks.minRotation);
11129 const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001;
11130 const tickFont = this._resolveTickFontOptions(0);
11131 return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));
11132 }
11133 getPixelForValue(value) {
11134 return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
11135 }
11136 getValueForPixel(pixel) {
11137 return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;
11138 }
11139 }
11140
11141 const log10Floor = (v)=>Math.floor((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(v));
11142 const changeExponent = (v, m)=>Math.pow(10, log10Floor(v) + m);
11143 function isMajor(tickVal) {
11144 const remain = tickVal / Math.pow(10, log10Floor(tickVal));
11145 return remain === 1;
11146 }
11147 function steps(min, max, rangeExp) {
11148 const rangeStep = Math.pow(10, rangeExp);
11149 const start = Math.floor(min / rangeStep);
11150 const end = Math.ceil(max / rangeStep);
11151 return end - start;
11152 }
11153 function startExp(min, max) {
11154 const range = max - min;
11155 let rangeExp = log10Floor(range);
11156 while(steps(min, max, rangeExp) > 10){
11157 rangeExp++;
11158 }
11159 while(steps(min, max, rangeExp) < 10){
11160 rangeExp--;
11161 }
11162 return Math.min(rangeExp, log10Floor(min));
11163 }
11164 function generateTicks(generationOptions, { min , max }) {
11165 min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, min);
11166 const ticks = [];
11167 const minExp = log10Floor(min);
11168 let exp = startExp(min, max);
11169 let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
11170 const stepSize = Math.pow(10, exp);
11171 const base = minExp > exp ? Math.pow(10, minExp) : 0;
11172 const start = Math.round((min - base) * precision) / precision;
11173 const offset = Math.floor((min - base) / stepSize / 10) * stepSize * 10;
11174 let significand = Math.floor((start - offset) / Math.pow(10, exp));
11175 let value = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision);
11176 while(value < max){
11177 ticks.push({
11178 value,
11179 major: isMajor(value),
11180 significand
11181 });
11182 if (significand >= 10) {
11183 significand = significand < 15 ? 15 : 20;
11184 } else {
11185 significand++;
11186 }
11187 if (significand >= 20) {
11188 exp++;
11189 significand = 2;
11190 precision = exp >= 0 ? 1 : precision;
11191 }
11192 value = Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision;
11193 }
11194 const lastTick = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.max, value);
11195 ticks.push({
11196 value: lastTick,
11197 major: isMajor(lastTick),
11198 significand
11199 });
11200 return ticks;
11201 }
11202 class LogarithmicScale extends Scale {
11203 static id = 'logarithmic';
11204 static defaults = {
11205 ticks: {
11206 callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.logarithmic,
11207 major: {
11208 enabled: true
11209 }
11210 }
11211 };
11212 constructor(cfg){
11213 super(cfg);
11214 this.start = undefined;
11215 this.end = undefined;
11216 this._startValue = undefined;
11217 this._valueRange = 0;
11218 }
11219 parse(raw, index) {
11220 const value = LinearScaleBase.prototype.parse.apply(this, [
11221 raw,
11222 index
11223 ]);
11224 if (value === 0) {
11225 this._zero = true;
11226 return undefined;
11227 }
11228 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value) && value > 0 ? value : null;
11229 }
11230 determineDataLimits() {
11231 const { min , max } = this.getMinMax(true);
11232 this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? Math.max(0, min) : null;
11233 this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? Math.max(0, max) : null;
11234 if (this.options.beginAtZero) {
11235 this._zero = true;
11236 }
11237 if (this._zero && this.min !== this._suggestedMin && !(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(this._userMin)) {
11238 this.min = min === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0);
11239 }
11240 this.handleTickRangeOptions();
11241 }
11242 handleTickRangeOptions() {
11243 const { minDefined , maxDefined } = this.getUserBounds();
11244 let min = this.min;
11245 let max = this.max;
11246 const setMin = (v)=>min = minDefined ? min : v;
11247 const setMax = (v)=>max = maxDefined ? max : v;
11248 if (min === max) {
11249 if (min <= 0) {
11250 setMin(1);
11251 setMax(10);
11252 } else {
11253 setMin(changeExponent(min, -1));
11254 setMax(changeExponent(max, +1));
11255 }
11256 }
11257 if (min <= 0) {
11258 setMin(changeExponent(max, -1));
11259 }
11260 if (max <= 0) {
11261 setMax(changeExponent(min, +1));
11262 }
11263 this.min = min;
11264 this.max = max;
11265 }
11266 buildTicks() {
11267 const opts = this.options;
11268 const generationOptions = {
11269 min: this._userMin,
11270 max: this._userMax
11271 };
11272 const ticks = generateTicks(generationOptions, this);
11273 if (opts.bounds === 'ticks') {
11274 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aH)(ticks, this, 'value');
11275 }
11276 if (opts.reverse) {
11277 ticks.reverse();
11278 this.start = this.max;
11279 this.end = this.min;
11280 } else {
11281 this.start = this.min;
11282 this.end = this.max;
11283 }
11284 return ticks;
11285 }
11286 getLabelForValue(value) {
11287 return value === undefined ? '0' : (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format);
11288 }
11289 configure() {
11290 const start = this.min;
11291 super.configure();
11292 this._startValue = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(start);
11293 this._valueRange = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(this.max) - (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(start);
11294 }
11295 getPixelForValue(value) {
11296 if (value === undefined || value === 0) {
11297 value = this.min;
11298 }
11299 if (value === null || isNaN(value)) {
11300 return NaN;
11301 }
11302 return this.getPixelForDecimal(value === this.min ? 0 : ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aN)(value) - this._startValue) / this._valueRange);
11303 }
11304 getValueForPixel(pixel) {
11305 const decimal = this.getDecimalForPixel(pixel);
11306 return Math.pow(10, this._startValue + decimal * this._valueRange);
11307 }
11308 }
11309
11310 function getTickBackdropHeight(opts) {
11311 const tickOpts = opts.ticks;
11312 if (tickOpts.display && opts.display) {
11313 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(tickOpts.backdropPadding);
11314 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(tickOpts.font && tickOpts.font.size, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.d.font.size) + padding.height;
11315 }
11316 return 0;
11317 }
11318 function measureLabelSize(ctx, font, label) {
11319 label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label : [
11320 label
11321 ];
11322 return {
11323 w: (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aO)(ctx, font.string, label),
11324 h: label.length * font.lineHeight
11325 };
11326 }
11327 function determineLimits(angle, pos, size, min, max) {
11328 if (angle === min || angle === max) {
11329 return {
11330 start: pos - size / 2,
11331 end: pos + size / 2
11332 };
11333 } else if (angle < min || angle > max) {
11334 return {
11335 start: pos - size,
11336 end: pos
11337 };
11338 }
11339 return {
11340 start: pos,
11341 end: pos + size
11342 };
11343 }
11344 function fitWithPointLabels(scale) {
11345 const orig = {
11346 l: scale.left + scale._padding.left,
11347 r: scale.right - scale._padding.right,
11348 t: scale.top + scale._padding.top,
11349 b: scale.bottom - scale._padding.bottom
11350 };
11351 const limits = Object.assign({}, orig);
11352 const labelSizes = [];
11353 const padding = [];
11354 const valueCount = scale._pointLabels.length;
11355 const pointLabelOpts = scale.options.pointLabels;
11356 const additionalAngle = pointLabelOpts.centerPointLabels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0;
11357 for(let i = 0; i < valueCount; i++){
11358 const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i));
11359 padding[i] = opts.padding;
11360 const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i], additionalAngle);
11361 const plFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font);
11362 const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]);
11363 labelSizes[i] = textSize;
11364 const angleRadians = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(scale.getIndexAngle(i) + additionalAngle);
11365 const angle = Math.round((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)(angleRadians));
11366 const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
11367 const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
11368 updateLimits(limits, orig, angleRadians, hLimits, vLimits);
11369 }
11370 scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b);
11371 scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);
11372 }
11373 function updateLimits(limits, orig, angle, hLimits, vLimits) {
11374 const sin = Math.abs(Math.sin(angle));
11375 const cos = Math.abs(Math.cos(angle));
11376 let x = 0;
11377 let y = 0;
11378 if (hLimits.start < orig.l) {
11379 x = (orig.l - hLimits.start) / sin;
11380 limits.l = Math.min(limits.l, orig.l - x);
11381 } else if (hLimits.end > orig.r) {
11382 x = (hLimits.end - orig.r) / sin;
11383 limits.r = Math.max(limits.r, orig.r + x);
11384 }
11385 if (vLimits.start < orig.t) {
11386 y = (orig.t - vLimits.start) / cos;
11387 limits.t = Math.min(limits.t, orig.t - y);
11388 } else if (vLimits.end > orig.b) {
11389 y = (vLimits.end - orig.b) / cos;
11390 limits.b = Math.max(limits.b, orig.b + y);
11391 }
11392 }
11393 function createPointLabelItem(scale, index, itemOpts) {
11394 const outerDistance = scale.drawingArea;
11395 const { extra , additionalAngle , padding , size } = itemOpts;
11396 const pointLabelPosition = scale.getPointPosition(index, outerDistance + extra + padding, additionalAngle);
11397 const angle = Math.round((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.U)((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(pointLabelPosition.angle + _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H)));
11398 const y = yForAngle(pointLabelPosition.y, size.h, angle);
11399 const textAlign = getTextAlignForAngle(angle);
11400 const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);
11401 return {
11402 visible: true,
11403 x: pointLabelPosition.x,
11404 y,
11405 textAlign,
11406 left,
11407 top: y,
11408 right: left + size.w,
11409 bottom: y + size.h
11410 };
11411 }
11412 function isNotOverlapped(item, area) {
11413 if (!area) {
11414 return true;
11415 }
11416 const { left , top , right , bottom } = item;
11417 const apexesInArea = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({
11418 x: left,
11419 y: top
11420 }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({
11421 x: left,
11422 y: bottom
11423 }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({
11424 x: right,
11425 y: top
11426 }, area) || (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.C)({
11427 x: right,
11428 y: bottom
11429 }, area);
11430 return !apexesInArea;
11431 }
11432 function buildPointLabelItems(scale, labelSizes, padding) {
11433 const items = [];
11434 const valueCount = scale._pointLabels.length;
11435 const opts = scale.options;
11436 const { centerPointLabels , display } = opts.pointLabels;
11437 const itemOpts = {
11438 extra: getTickBackdropHeight(opts) / 2,
11439 additionalAngle: centerPointLabels ? _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0
11440 };
11441 let area;
11442 for(let i = 0; i < valueCount; i++){
11443 itemOpts.padding = padding[i];
11444 itemOpts.size = labelSizes[i];
11445 const item = createPointLabelItem(scale, i, itemOpts);
11446 items.push(item);
11447 if (display === 'auto') {
11448 item.visible = isNotOverlapped(item, area);
11449 if (item.visible) {
11450 area = item;
11451 }
11452 }
11453 }
11454 return items;
11455 }
11456 function getTextAlignForAngle(angle) {
11457 if (angle === 0 || angle === 180) {
11458 return 'center';
11459 } else if (angle < 180) {
11460 return 'left';
11461 }
11462 return 'right';
11463 }
11464 function leftForTextAlign(x, w, align) {
11465 if (align === 'right') {
11466 x -= w;
11467 } else if (align === 'center') {
11468 x -= w / 2;
11469 }
11470 return x;
11471 }
11472 function yForAngle(y, h, angle) {
11473 if (angle === 90 || angle === 270) {
11474 y -= h / 2;
11475 } else if (angle > 270 || angle < 90) {
11476 y -= h;
11477 }
11478 return y;
11479 }
11480 function drawPointLabelBox(ctx, opts, item) {
11481 const { left , top , right , bottom } = item;
11482 const { backdropColor } = opts;
11483 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(backdropColor)) {
11484 const borderRadius = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ay)(opts.borderRadius);
11485 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.backdropPadding);
11486 ctx.fillStyle = backdropColor;
11487 const backdropLeft = left - padding.left;
11488 const backdropTop = top - padding.top;
11489 const backdropWidth = right - left + padding.width;
11490 const backdropHeight = bottom - top + padding.height;
11491 if (Object.values(borderRadius).some((v)=>v !== 0)) {
11492 ctx.beginPath();
11493 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aw)(ctx, {
11494 x: backdropLeft,
11495 y: backdropTop,
11496 w: backdropWidth,
11497 h: backdropHeight,
11498 radius: borderRadius
11499 });
11500 ctx.fill();
11501 } else {
11502 ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight);
11503 }
11504 }
11505 }
11506 function drawPointLabels(scale, labelCount) {
11507 const { ctx , options: { pointLabels } } = scale;
11508 for(let i = labelCount - 1; i >= 0; i--){
11509 const item = scale._pointLabelItems[i];
11510 if (!item.visible) {
11511 continue;
11512 }
11513 const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i));
11514 drawPointLabelBox(ctx, optsAtIndex, item);
11515 const plFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font);
11516 const { x , y , textAlign } = item;
11517 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, scale._pointLabels[i], x, y + plFont.lineHeight / 2, plFont, {
11518 color: optsAtIndex.color,
11519 textAlign: textAlign,
11520 textBaseline: 'middle'
11521 });
11522 }
11523 }
11524 function pathRadiusLine(scale, radius, circular, labelCount) {
11525 const { ctx } = scale;
11526 if (circular) {
11527 ctx.arc(scale.xCenter, scale.yCenter, radius, 0, _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T);
11528 } else {
11529 let pointPosition = scale.getPointPosition(0, radius);
11530 ctx.moveTo(pointPosition.x, pointPosition.y);
11531 for(let i = 1; i < labelCount; i++){
11532 pointPosition = scale.getPointPosition(i, radius);
11533 ctx.lineTo(pointPosition.x, pointPosition.y);
11534 }
11535 }
11536 }
11537 function drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) {
11538 const ctx = scale.ctx;
11539 const circular = gridLineOpts.circular;
11540 const { color , lineWidth } = gridLineOpts;
11541 if (!circular && !labelCount || !color || !lineWidth || radius < 0) {
11542 return;
11543 }
11544 ctx.save();
11545 ctx.strokeStyle = color;
11546 ctx.lineWidth = lineWidth;
11547 ctx.setLineDash(borderOpts.dash || []);
11548 ctx.lineDashOffset = borderOpts.dashOffset;
11549 ctx.beginPath();
11550 pathRadiusLine(scale, radius, circular, labelCount);
11551 ctx.closePath();
11552 ctx.stroke();
11553 ctx.restore();
11554 }
11555 function createPointLabelContext(parent, index, label) {
11556 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, {
11557 label,
11558 index,
11559 type: 'pointLabel'
11560 });
11561 }
11562 class RadialLinearScale extends LinearScaleBase {
11563 static id = 'radialLinear';
11564 static defaults = {
11565 display: true,
11566 animate: true,
11567 position: 'chartArea',
11568 angleLines: {
11569 display: true,
11570 lineWidth: 1,
11571 borderDash: [],
11572 borderDashOffset: 0.0
11573 },
11574 grid: {
11575 circular: false
11576 },
11577 startAngle: 0,
11578 ticks: {
11579 showLabelBackdrop: true,
11580 callback: _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aM.formatters.numeric
11581 },
11582 pointLabels: {
11583 backdropColor: undefined,
11584 backdropPadding: 2,
11585 display: true,
11586 font: {
11587 size: 10
11588 },
11589 callback (label) {
11590 return label;
11591 },
11592 padding: 5,
11593 centerPointLabels: false
11594 }
11595 };
11596 static defaultRoutes = {
11597 'angleLines.color': 'borderColor',
11598 'pointLabels.color': 'color',
11599 'ticks.color': 'color'
11600 };
11601 static descriptors = {
11602 angleLines: {
11603 _fallback: 'grid'
11604 }
11605 };
11606 constructor(cfg){
11607 super(cfg);
11608 this.xCenter = undefined;
11609 this.yCenter = undefined;
11610 this.drawingArea = undefined;
11611 this._pointLabels = [];
11612 this._pointLabelItems = [];
11613 }
11614 setDimensions() {
11615 const padding = this._padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(getTickBackdropHeight(this.options) / 2);
11616 const w = this.width = this.maxWidth - padding.width;
11617 const h = this.height = this.maxHeight - padding.height;
11618 this.xCenter = Math.floor(this.left + w / 2 + padding.left);
11619 this.yCenter = Math.floor(this.top + h / 2 + padding.top);
11620 this.drawingArea = Math.floor(Math.min(w, h) / 2);
11621 }
11622 determineDataLimits() {
11623 const { min , max } = this.getMinMax(false);
11624 this.min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : 0;
11625 this.max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : 0;
11626 this.handleTickRangeOptions();
11627 }
11628 computeTickLimit() {
11629 return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));
11630 }
11631 generateTickLabels(ticks) {
11632 LinearScaleBase.prototype.generateTickLabels.call(this, ticks);
11633 this._pointLabels = this.getLabels().map((value, index)=>{
11634 const label = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.pointLabels.callback, [
11635 value,
11636 index
11637 ], this);
11638 return label || label === 0 ? label : '';
11639 }).filter((v, i)=>this.chart.getDataVisibility(i));
11640 }
11641 fit() {
11642 const opts = this.options;
11643 if (opts.display && opts.pointLabels.display) {
11644 fitWithPointLabels(this);
11645 } else {
11646 this.setCenterPoint(0, 0, 0, 0);
11647 }
11648 }
11649 setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {
11650 this.xCenter += Math.floor((leftMovement - rightMovement) / 2);
11651 this.yCenter += Math.floor((topMovement - bottomMovement) / 2);
11652 this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement));
11653 }
11654 getIndexAngle(index) {
11655 const angleMultiplier = _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.T / (this._pointLabels.length || 1);
11656 const startAngle = this.options.startAngle || 0;
11657 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.al)(index * angleMultiplier + (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(startAngle));
11658 }
11659 getDistanceFromCenterForValue(value) {
11660 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) {
11661 return NaN;
11662 }
11663 const scalingFactor = this.drawingArea / (this.max - this.min);
11664 if (this.options.reverse) {
11665 return (this.max - value) * scalingFactor;
11666 }
11667 return (value - this.min) * scalingFactor;
11668 }
11669 getValueForDistanceFromCenter(distance) {
11670 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(distance)) {
11671 return NaN;
11672 }
11673 const scaledDistance = distance / (this.drawingArea / (this.max - this.min));
11674 return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;
11675 }
11676 getPointLabelContext(index) {
11677 const pointLabels = this._pointLabels || [];
11678 if (index >= 0 && index < pointLabels.length) {
11679 const pointLabel = pointLabels[index];
11680 return createPointLabelContext(this.getContext(), index, pointLabel);
11681 }
11682 }
11683 getPointPosition(index, distanceFromCenter, additionalAngle = 0) {
11684 const angle = this.getIndexAngle(index) - _chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.H + additionalAngle;
11685 return {
11686 x: Math.cos(angle) * distanceFromCenter + this.xCenter,
11687 y: Math.sin(angle) * distanceFromCenter + this.yCenter,
11688 angle
11689 };
11690 }
11691 getPointPositionForValue(index, value) {
11692 return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
11693 }
11694 getBasePosition(index) {
11695 return this.getPointPositionForValue(index || 0, this.getBaseValue());
11696 }
11697 getPointLabelPosition(index) {
11698 const { left , top , right , bottom } = this._pointLabelItems[index];
11699 return {
11700 left,
11701 top,
11702 right,
11703 bottom
11704 };
11705 }
11706 drawBackground() {
11707 const { backgroundColor , grid: { circular } } = this.options;
11708 if (backgroundColor) {
11709 const ctx = this.ctx;
11710 ctx.save();
11711 ctx.beginPath();
11712 pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length);
11713 ctx.closePath();
11714 ctx.fillStyle = backgroundColor;
11715 ctx.fill();
11716 ctx.restore();
11717 }
11718 }
11719 drawGrid() {
11720 const ctx = this.ctx;
11721 const opts = this.options;
11722 const { angleLines , grid , border } = opts;
11723 const labelCount = this._pointLabels.length;
11724 let i, offset, position;
11725 if (opts.pointLabels.display) {
11726 drawPointLabels(this, labelCount);
11727 }
11728 if (grid.display) {
11729 this.ticks.forEach((tick, index)=>{
11730 if (index !== 0 || index === 0 && this.min < 0) {
11731 offset = this.getDistanceFromCenterForValue(tick.value);
11732 const context = this.getContext(index);
11733 const optsAtIndex = grid.setContext(context);
11734 const optsAtIndexBorder = border.setContext(context);
11735 drawRadiusLine(this, optsAtIndex, offset, labelCount, optsAtIndexBorder);
11736 }
11737 });
11738 }
11739 if (angleLines.display) {
11740 ctx.save();
11741 for(i = labelCount - 1; i >= 0; i--){
11742 const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));
11743 const { color , lineWidth } = optsAtIndex;
11744 if (!lineWidth || !color) {
11745 continue;
11746 }
11747 ctx.lineWidth = lineWidth;
11748 ctx.strokeStyle = color;
11749 ctx.setLineDash(optsAtIndex.borderDash);
11750 ctx.lineDashOffset = optsAtIndex.borderDashOffset;
11751 offset = this.getDistanceFromCenterForValue(opts.reverse ? this.min : this.max);
11752 position = this.getPointPosition(i, offset);
11753 ctx.beginPath();
11754 ctx.moveTo(this.xCenter, this.yCenter);
11755 ctx.lineTo(position.x, position.y);
11756 ctx.stroke();
11757 }
11758 ctx.restore();
11759 }
11760 }
11761 drawBorder() {}
11762 drawLabels() {
11763 const ctx = this.ctx;
11764 const opts = this.options;
11765 const tickOpts = opts.ticks;
11766 if (!tickOpts.display) {
11767 return;
11768 }
11769 const startAngle = this.getIndexAngle(0);
11770 let offset, width;
11771 ctx.save();
11772 ctx.translate(this.xCenter, this.yCenter);
11773 ctx.rotate(startAngle);
11774 ctx.textAlign = 'center';
11775 ctx.textBaseline = 'middle';
11776 this.ticks.forEach((tick, index)=>{
11777 if (index === 0 && this.min >= 0 && !opts.reverse) {
11778 return;
11779 }
11780 const optsAtIndex = tickOpts.setContext(this.getContext(index));
11781 const tickFont = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font);
11782 offset = this.getDistanceFromCenterForValue(this.ticks[index].value);
11783 if (optsAtIndex.showLabelBackdrop) {
11784 ctx.font = tickFont.string;
11785 width = ctx.measureText(tick.label).width;
11786 ctx.fillStyle = optsAtIndex.backdropColor;
11787 const padding = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding);
11788 ctx.fillRect(-width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height);
11789 }
11790 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, tick.label, 0, -offset, tickFont, {
11791 color: optsAtIndex.color,
11792 strokeColor: optsAtIndex.textStrokeColor,
11793 strokeWidth: optsAtIndex.textStrokeWidth
11794 });
11795 });
11796 ctx.restore();
11797 }
11798 drawTitle() {}
11799 }
11800
11801 const INTERVALS = {
11802 millisecond: {
11803 common: true,
11804 size: 1,
11805 steps: 1000
11806 },
11807 second: {
11808 common: true,
11809 size: 1000,
11810 steps: 60
11811 },
11812 minute: {
11813 common: true,
11814 size: 60000,
11815 steps: 60
11816 },
11817 hour: {
11818 common: true,
11819 size: 3600000,
11820 steps: 24
11821 },
11822 day: {
11823 common: true,
11824 size: 86400000,
11825 steps: 30
11826 },
11827 week: {
11828 common: false,
11829 size: 604800000,
11830 steps: 4
11831 },
11832 month: {
11833 common: true,
11834 size: 2.628e9,
11835 steps: 12
11836 },
11837 quarter: {
11838 common: false,
11839 size: 7.884e9,
11840 steps: 4
11841 },
11842 year: {
11843 common: true,
11844 size: 3.154e10
11845 }
11846 };
11847 const UNITS = /* #__PURE__ */ Object.keys(INTERVALS);
11848 function sorter(a, b) {
11849 return a - b;
11850 }
11851 function parse(scale, input) {
11852 if ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.k)(input)) {
11853 return null;
11854 }
11855 const adapter = scale._adapter;
11856 const { parser , round , isoWeekday } = scale._parseOpts;
11857 let value = input;
11858 if (typeof parser === 'function') {
11859 value = parser(value);
11860 }
11861 if (!(0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) {
11862 value = typeof parser === 'string' ? adapter.parse(value, parser) : adapter.parse(value);
11863 }
11864 if (value === null) {
11865 return null;
11866 }
11867 if (round) {
11868 value = round === 'week' && ((0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, 'isoWeek', isoWeekday) : adapter.startOf(value, round);
11869 }
11870 return +value;
11871 }
11872 function determineUnitForAutoTicks(minUnit, min, max, capacity) {
11873 const ilen = UNITS.length;
11874 for(let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i){
11875 const interval = INTERVALS[UNITS[i]];
11876 const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;
11877 if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
11878 return UNITS[i];
11879 }
11880 }
11881 return UNITS[ilen - 1];
11882 }
11883 function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {
11884 for(let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--){
11885 const unit = UNITS[i];
11886 if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) {
11887 return unit;
11888 }
11889 }
11890 return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
11891 }
11892 function determineMajorUnit(unit) {
11893 for(let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i){
11894 if (INTERVALS[UNITS[i]].common) {
11895 return UNITS[i];
11896 }
11897 }
11898 }
11899 function addTick(ticks, time, timestamps) {
11900 if (!timestamps) {
11901 ticks[time] = true;
11902 } else if (timestamps.length) {
11903 const { lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aQ)(timestamps, time);
11904 const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];
11905 ticks[timestamp] = true;
11906 }
11907 }
11908 function setMajorTicks(scale, ticks, map, majorUnit) {
11909 const adapter = scale._adapter;
11910 const first = +adapter.startOf(ticks[0].value, majorUnit);
11911 const last = ticks[ticks.length - 1].value;
11912 let major, index;
11913 for(major = first; major <= last; major = +adapter.add(major, 1, majorUnit)){
11914 index = map[major];
11915 if (index >= 0) {
11916 ticks[index].major = true;
11917 }
11918 }
11919 return ticks;
11920 }
11921 function ticksFromTimestamps(scale, values, majorUnit) {
11922 const ticks = [];
11923 const map = {};
11924 const ilen = values.length;
11925 let i, value;
11926 for(i = 0; i < ilen; ++i){
11927 value = values[i];
11928 map[value] = i;
11929 ticks.push({
11930 value,
11931 major: false
11932 });
11933 }
11934 return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map, majorUnit);
11935 }
11936 class TimeScale extends Scale {
11937 static id = 'time';
11938 static defaults = {
11939 bounds: 'data',
11940 adapters: {},
11941 time: {
11942 parser: false,
11943 unit: false,
11944 round: false,
11945 isoWeekday: false,
11946 minUnit: 'millisecond',
11947 displayFormats: {}
11948 },
11949 ticks: {
11950 source: 'auto',
11951 callback: false,
11952 major: {
11953 enabled: false
11954 }
11955 }
11956 };
11957 constructor(props){
11958 super(props);
11959 this._cache = {
11960 data: [],
11961 labels: [],
11962 all: []
11963 };
11964 this._unit = 'day';
11965 this._majorUnit = undefined;
11966 this._offsets = {};
11967 this._normalized = false;
11968 this._parseOpts = undefined;
11969 }
11970 init(scaleOpts, opts = {}) {
11971 const time = scaleOpts.time || (scaleOpts.time = {});
11972 const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date);
11973 adapter.init(opts);
11974 (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.ab)(time.displayFormats, adapter.formats());
11975 this._parseOpts = {
11976 parser: time.parser,
11977 round: time.round,
11978 isoWeekday: time.isoWeekday
11979 };
11980 super.init(scaleOpts);
11981 this._normalized = opts.normalized;
11982 }
11983 parse(raw, index) {
11984 if (raw === undefined) {
11985 return null;
11986 }
11987 return parse(this, raw);
11988 }
11989 beforeLayout() {
11990 super.beforeLayout();
11991 this._cache = {
11992 data: [],
11993 labels: [],
11994 all: []
11995 };
11996 }
11997 determineDataLimits() {
11998 const options = this.options;
11999 const adapter = this._adapter;
12000 const unit = options.time.unit || 'day';
12001 let { min , max , minDefined , maxDefined } = this.getUserBounds();
12002 function _applyBounds(bounds) {
12003 if (!minDefined && !isNaN(bounds.min)) {
12004 min = Math.min(min, bounds.min);
12005 }
12006 if (!maxDefined && !isNaN(bounds.max)) {
12007 max = Math.max(max, bounds.max);
12008 }
12009 }
12010 if (!minDefined || !maxDefined) {
12011 _applyBounds(this._getLabelBounds());
12012 if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {
12013 _applyBounds(this.getMinMax(false));
12014 }
12015 }
12016 min = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);
12017 max = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;
12018 this.min = Math.min(min, max - 1);
12019 this.max = Math.max(min + 1, max);
12020 }
12021 _getLabelBounds() {
12022 const arr = this.getLabelTimestamps();
12023 let min = Number.POSITIVE_INFINITY;
12024 let max = Number.NEGATIVE_INFINITY;
12025 if (arr.length) {
12026 min = arr[0];
12027 max = arr[arr.length - 1];
12028 }
12029 return {
12030 min,
12031 max
12032 };
12033 }
12034 buildTicks() {
12035 const options = this.options;
12036 const timeOpts = options.time;
12037 const tickOpts = options.ticks;
12038 const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate();
12039 if (options.bounds === 'ticks' && timestamps.length) {
12040 this.min = this._userMin || timestamps[0];
12041 this.max = this._userMax || timestamps[timestamps.length - 1];
12042 }
12043 const min = this.min;
12044 const max = this.max;
12045 const ticks = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.aP)(timestamps, min, max);
12046 this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));
12047 this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined : determineMajorUnit(this._unit);
12048 this.initOffsets(timestamps);
12049 if (options.reverse) {
12050 ticks.reverse();
12051 }
12052 return ticksFromTimestamps(this, ticks, this._majorUnit);
12053 }
12054 afterAutoSkip() {
12055 if (this.options.offsetAfterAutoskip) {
12056 this.initOffsets(this.ticks.map((tick)=>+tick.value));
12057 }
12058 }
12059 initOffsets(timestamps = []) {
12060 let start = 0;
12061 let end = 0;
12062 let first, last;
12063 if (this.options.offset && timestamps.length) {
12064 first = this.getDecimalForValue(timestamps[0]);
12065 if (timestamps.length === 1) {
12066 start = 1 - first;
12067 } else {
12068 start = (this.getDecimalForValue(timestamps[1]) - first) / 2;
12069 }
12070 last = this.getDecimalForValue(timestamps[timestamps.length - 1]);
12071 if (timestamps.length === 1) {
12072 end = last;
12073 } else {
12074 end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
12075 }
12076 }
12077 const limit = timestamps.length < 3 ? 0.5 : 0.25;
12078 start = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(start, 0, limit);
12079 end = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.S)(end, 0, limit);
12080 this._offsets = {
12081 start,
12082 end,
12083 factor: 1 / (start + 1 + end)
12084 };
12085 }
12086 _generate() {
12087 const adapter = this._adapter;
12088 const min = this.min;
12089 const max = this.max;
12090 const options = this.options;
12091 const timeOpts = options.time;
12092 const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));
12093 const stepSize = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.stepSize, 1);
12094 const weekday = minor === 'week' ? timeOpts.isoWeekday : false;
12095 const hasWeekday = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.x)(weekday) || weekday === true;
12096 const ticks = {};
12097 let first = min;
12098 let time, count;
12099 if (hasWeekday) {
12100 first = +adapter.startOf(first, 'isoWeek', weekday);
12101 }
12102 first = +adapter.startOf(first, hasWeekday ? 'day' : minor);
12103 if (adapter.diff(max, min, minor) > 100000 * stepSize) {
12104 throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);
12105 }
12106 const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();
12107 for(time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++){
12108 addTick(ticks, time, timestamps);
12109 }
12110 if (time === max || options.bounds === 'ticks' || count === 1) {
12111 addTick(ticks, time, timestamps);
12112 }
12113 return Object.keys(ticks).sort(sorter).map((x)=>+x);
12114 }
12115 getLabelForValue(value) {
12116 const adapter = this._adapter;
12117 const timeOpts = this.options.time;
12118 if (timeOpts.tooltipFormat) {
12119 return adapter.format(value, timeOpts.tooltipFormat);
12120 }
12121 return adapter.format(value, timeOpts.displayFormats.datetime);
12122 }
12123 format(value, format) {
12124 const options = this.options;
12125 const formats = options.time.displayFormats;
12126 const unit = this._unit;
12127 const fmt = format || formats[unit];
12128 return this._adapter.format(value, fmt);
12129 }
12130 _tickFormatFunction(time, index, ticks, format) {
12131 const options = this.options;
12132 const formatter = options.ticks.callback;
12133 if (formatter) {
12134 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.Q)(formatter, [
12135 time,
12136 index,
12137 ticks
12138 ], this);
12139 }
12140 const formats = options.time.displayFormats;
12141 const unit = this._unit;
12142 const majorUnit = this._majorUnit;
12143 const minorFormat = unit && formats[unit];
12144 const majorFormat = majorUnit && formats[majorUnit];
12145 const tick = ticks[index];
12146 const major = majorUnit && majorFormat && tick && tick.major;
12147 return this._adapter.format(time, format || (major ? majorFormat : minorFormat));
12148 }
12149 generateTickLabels(ticks) {
12150 let i, ilen, tick;
12151 for(i = 0, ilen = ticks.length; i < ilen; ++i){
12152 tick = ticks[i];
12153 tick.label = this._tickFormatFunction(tick.value, i, ticks);
12154 }
12155 }
12156 getDecimalForValue(value) {
12157 return value === null ? NaN : (value - this.min) / (this.max - this.min);
12158 }
12159 getPixelForValue(value) {
12160 const offsets = this._offsets;
12161 const pos = this.getDecimalForValue(value);
12162 return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);
12163 }
12164 getValueForPixel(pixel) {
12165 const offsets = this._offsets;
12166 const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
12167 return this.min + pos * (this.max - this.min);
12168 }
12169 _getLabelSize(label) {
12170 const ticksOpts = this.options.ticks;
12171 const tickLabelWidth = this.ctx.measureText(label).width;
12172 const angle = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
12173 const cosRotation = Math.cos(angle);
12174 const sinRotation = Math.sin(angle);
12175 const tickFontSize = this._resolveTickFontOptions(0).size;
12176 return {
12177 w: tickLabelWidth * cosRotation + tickFontSize * sinRotation,
12178 h: tickLabelWidth * sinRotation + tickFontSize * cosRotation
12179 };
12180 }
12181 _getLabelCapacity(exampleTime) {
12182 const timeOpts = this.options.time;
12183 const displayFormats = timeOpts.displayFormats;
12184 const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;
12185 const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [
12186 exampleTime
12187 ], this._majorUnit), format);
12188 const size = this._getLabelSize(exampleLabel);
12189 const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;
12190 return capacity > 0 ? capacity : 1;
12191 }
12192 getDataTimestamps() {
12193 let timestamps = this._cache.data || [];
12194 let i, ilen;
12195 if (timestamps.length) {
12196 return timestamps;
12197 }
12198 const metas = this.getMatchingVisibleMetas();
12199 if (this._normalized && metas.length) {
12200 return this._cache.data = metas[0].controller.getAllParsedValues(this);
12201 }
12202 for(i = 0, ilen = metas.length; i < ilen; ++i){
12203 timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));
12204 }
12205 return this._cache.data = this.normalize(timestamps);
12206 }
12207 getLabelTimestamps() {
12208 const timestamps = this._cache.labels || [];
12209 let i, ilen;
12210 if (timestamps.length) {
12211 return timestamps;
12212 }
12213 const labels = this.getLabels();
12214 for(i = 0, ilen = labels.length; i < ilen; ++i){
12215 timestamps.push(parse(this, labels[i]));
12216 }
12217 return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps);
12218 }
12219 normalize(values) {
12220 return (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort(sorter));
12221 }
12222 }
12223
12224 function interpolate(table, val, reverse) {
12225 let lo = 0;
12226 let hi = table.length - 1;
12227 let prevSource, nextSource, prevTarget, nextTarget;
12228 if (reverse) {
12229 if (val >= table[lo].pos && val <= table[hi].pos) {
12230 ({ lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'pos', val));
12231 }
12232 ({ pos: prevSource , time: prevTarget } = table[lo]);
12233 ({ pos: nextSource , time: nextTarget } = table[hi]);
12234 } else {
12235 if (val >= table[lo].time && val <= table[hi].time) {
12236 ({ lo , hi } = (0,_chunks_helpers_dataset_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'time', val));
12237 }
12238 ({ time: prevSource , pos: prevTarget } = table[lo]);
12239 ({ time: nextSource , pos: nextTarget } = table[hi]);
12240 }
12241 const span = nextSource - prevSource;
12242 return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;
12243 }
12244 class TimeSeriesScale extends TimeScale {
12245 static id = 'timeseries';
12246 static defaults = TimeScale.defaults;
12247 constructor(props){
12248 super(props);
12249 this._table = [];
12250 this._minPos = undefined;
12251 this._tableRange = undefined;
12252 }
12253 initOffsets() {
12254 const timestamps = this._getTimestampsForTable();
12255 const table = this._table = this.buildLookupTable(timestamps);
12256 this._minPos = interpolate(table, this.min);
12257 this._tableRange = interpolate(table, this.max) - this._minPos;
12258 super.initOffsets(timestamps);
12259 }
12260 buildLookupTable(timestamps) {
12261 const { min , max } = this;
12262 const items = [];
12263 const table = [];
12264 let i, ilen, prev, curr, next;
12265 for(i = 0, ilen = timestamps.length; i < ilen; ++i){
12266 curr = timestamps[i];
12267 if (curr >= min && curr <= max) {
12268 items.push(curr);
12269 }
12270 }
12271 if (items.length < 2) {
12272 return [
12273 {
12274 time: min,
12275 pos: 0
12276 },
12277 {
12278 time: max,
12279 pos: 1
12280 }
12281 ];
12282 }
12283 for(i = 0, ilen = items.length; i < ilen; ++i){
12284 next = items[i + 1];
12285 prev = items[i - 1];
12286 curr = items[i];
12287 if (Math.round((next + prev) / 2) !== curr) {
12288 table.push({
12289 time: curr,
12290 pos: i / (ilen - 1)
12291 });
12292 }
12293 }
12294 return table;
12295 }
12296 _generate() {
12297 const min = this.min;
12298 const max = this.max;
12299 let timestamps = super.getDataTimestamps();
12300 if (!timestamps.includes(min) || !timestamps.length) {
12301 timestamps.splice(0, 0, min);
12302 }
12303 if (!timestamps.includes(max) || timestamps.length === 1) {
12304 timestamps.push(max);
12305 }
12306 return timestamps.sort((a, b)=>a - b);
12307 }
12308 _getTimestampsForTable() {
12309 let timestamps = this._cache.all || [];
12310 if (timestamps.length) {
12311 return timestamps;
12312 }
12313 const data = this.getDataTimestamps();
12314 const label = this.getLabelTimestamps();
12315 if (data.length && label.length) {
12316 timestamps = this.normalize(data.concat(label));
12317 } else {
12318 timestamps = data.length ? data : label;
12319 }
12320 timestamps = this._cache.all = timestamps;
12321 return timestamps;
12322 }
12323 getDecimalForValue(value) {
12324 return (interpolate(this._table, value) - this._minPos) / this._tableRange;
12325 }
12326 getValueForPixel(pixel) {
12327 const offsets = this._offsets;
12328 const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
12329 return interpolate(this._table, decimal * this._tableRange + this._minPos, true);
12330 }
12331 }
12332
12333 var scales = /*#__PURE__*/Object.freeze({
12334 __proto__: null,
12335 CategoryScale: CategoryScale,
12336 LinearScale: LinearScale,
12337 LogarithmicScale: LogarithmicScale,
12338 RadialLinearScale: RadialLinearScale,
12339 TimeScale: TimeScale,
12340 TimeSeriesScale: TimeSeriesScale
12341 });
12342
12343 const registerables = [
12344 controllers,
12345 elements,
12346 plugins,
12347 scales
12348 ];
12349
12350
12351 //# sourceMappingURL=chart.js.map
12352
12353
12354 /***/ },
12355
12356 /***/ "./node_modules/chart.js/dist/chunks/helpers.dataset.js"
12357 /*!**************************************************************!*\
12358 !*** ./node_modules/chart.js/dist/chunks/helpers.dataset.js ***!
12359 \**************************************************************/
12360 (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
12361
12362 __webpack_require__.r(__webpack_exports__);
12363 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
12364 /* harmony export */ $: () => (/* binding */ unclipArea),
12365 /* harmony export */ A: () => (/* binding */ _rlookupByKey),
12366 /* harmony export */ B: () => (/* binding */ _lookupByKey),
12367 /* harmony export */ C: () => (/* binding */ _isPointInArea),
12368 /* harmony export */ D: () => (/* binding */ getAngleFromPoint),
12369 /* harmony export */ E: () => (/* binding */ toPadding),
12370 /* harmony export */ F: () => (/* binding */ each),
12371 /* harmony export */ G: () => (/* binding */ getMaximumSize),
12372 /* harmony export */ H: () => (/* binding */ HALF_PI),
12373 /* harmony export */ I: () => (/* binding */ _getParentNode),
12374 /* harmony export */ J: () => (/* binding */ readUsedSize),
12375 /* harmony export */ K: () => (/* binding */ supportsEventListenerOptions),
12376 /* harmony export */ L: () => (/* binding */ throttled),
12377 /* harmony export */ M: () => (/* binding */ _isDomSupported),
12378 /* harmony export */ N: () => (/* binding */ _factorize),
12379 /* harmony export */ O: () => (/* binding */ finiteOrDefault),
12380 /* harmony export */ P: () => (/* binding */ PI),
12381 /* harmony export */ Q: () => (/* binding */ callback),
12382 /* harmony export */ R: () => (/* binding */ _addGrace),
12383 /* harmony export */ S: () => (/* binding */ _limitValue),
12384 /* harmony export */ T: () => (/* binding */ TAU),
12385 /* harmony export */ U: () => (/* binding */ toDegrees),
12386 /* harmony export */ V: () => (/* binding */ _measureText),
12387 /* harmony export */ W: () => (/* binding */ _int16Range),
12388 /* harmony export */ X: () => (/* binding */ _alignPixel),
12389 /* harmony export */ Y: () => (/* binding */ clipArea),
12390 /* harmony export */ Z: () => (/* binding */ renderText),
12391 /* harmony export */ _: () => (/* binding */ _arrayUnique),
12392 /* harmony export */ a: () => (/* binding */ resolve),
12393 /* harmony export */ a$: () => (/* binding */ getStyle),
12394 /* harmony export */ a0: () => (/* binding */ toFont),
12395 /* harmony export */ a1: () => (/* binding */ _toLeftRightCenter),
12396 /* harmony export */ a2: () => (/* binding */ _alignStartEnd),
12397 /* harmony export */ a3: () => (/* binding */ overrides),
12398 /* harmony export */ a4: () => (/* binding */ merge),
12399 /* harmony export */ a5: () => (/* binding */ _capitalize),
12400 /* harmony export */ a6: () => (/* binding */ descriptors),
12401 /* harmony export */ a7: () => (/* binding */ isFunction),
12402 /* harmony export */ a8: () => (/* binding */ _attachContext),
12403 /* harmony export */ a9: () => (/* binding */ _createResolver),
12404 /* harmony export */ aA: () => (/* binding */ getRtlAdapter),
12405 /* harmony export */ aB: () => (/* binding */ overrideTextDirection),
12406 /* harmony export */ aC: () => (/* binding */ _textX),
12407 /* harmony export */ aD: () => (/* binding */ restoreTextDirection),
12408 /* harmony export */ aE: () => (/* binding */ drawPointLegend),
12409 /* harmony export */ aF: () => (/* binding */ distanceBetweenPoints),
12410 /* harmony export */ aG: () => (/* binding */ noop),
12411 /* harmony export */ aH: () => (/* binding */ _setMinAndMaxByKey),
12412 /* harmony export */ aI: () => (/* binding */ niceNum),
12413 /* harmony export */ aJ: () => (/* binding */ almostWhole),
12414 /* harmony export */ aK: () => (/* binding */ almostEquals),
12415 /* harmony export */ aL: () => (/* binding */ _decimalPlaces),
12416 /* harmony export */ aM: () => (/* binding */ Ticks),
12417 /* harmony export */ aN: () => (/* binding */ log10),
12418 /* harmony export */ aO: () => (/* binding */ _longestText),
12419 /* harmony export */ aP: () => (/* binding */ _filterBetween),
12420 /* harmony export */ aQ: () => (/* binding */ _lookup),
12421 /* harmony export */ aR: () => (/* binding */ isPatternOrGradient),
12422 /* harmony export */ aS: () => (/* binding */ getHoverColor),
12423 /* harmony export */ aT: () => (/* binding */ clone),
12424 /* harmony export */ aU: () => (/* binding */ _merger),
12425 /* harmony export */ aV: () => (/* binding */ _mergerIf),
12426 /* harmony export */ aW: () => (/* binding */ _deprecated),
12427 /* harmony export */ aX: () => (/* binding */ _splitKey),
12428 /* harmony export */ aY: () => (/* binding */ toFontString),
12429 /* harmony export */ aZ: () => (/* binding */ splineCurve),
12430 /* harmony export */ a_: () => (/* binding */ splineCurveMonotone),
12431 /* harmony export */ aa: () => (/* binding */ _descriptors),
12432 /* harmony export */ ab: () => (/* binding */ mergeIf),
12433 /* harmony export */ ac: () => (/* binding */ uid),
12434 /* harmony export */ ad: () => (/* binding */ debounce),
12435 /* harmony export */ ae: () => (/* binding */ retinaScale),
12436 /* harmony export */ af: () => (/* binding */ clearCanvas),
12437 /* harmony export */ ag: () => (/* binding */ setsEqual),
12438 /* harmony export */ ah: () => (/* binding */ getDatasetClipArea),
12439 /* harmony export */ ai: () => (/* binding */ _elementsEqual),
12440 /* harmony export */ aj: () => (/* binding */ _isClickEvent),
12441 /* harmony export */ ak: () => (/* binding */ _isBetween),
12442 /* harmony export */ al: () => (/* binding */ _normalizeAngle),
12443 /* harmony export */ am: () => (/* binding */ _readValueToProps),
12444 /* harmony export */ an: () => (/* binding */ _updateBezierControlPoints),
12445 /* harmony export */ ao: () => (/* binding */ _computeSegments),
12446 /* harmony export */ ap: () => (/* binding */ _boundSegments),
12447 /* harmony export */ aq: () => (/* binding */ _steppedInterpolation),
12448 /* harmony export */ ar: () => (/* binding */ _bezierInterpolation),
12449 /* harmony export */ as: () => (/* binding */ _pointInLine),
12450 /* harmony export */ at: () => (/* binding */ _steppedLineTo),
12451 /* harmony export */ au: () => (/* binding */ _bezierCurveTo),
12452 /* harmony export */ av: () => (/* binding */ drawPoint),
12453 /* harmony export */ aw: () => (/* binding */ addRoundedRectPath),
12454 /* harmony export */ ax: () => (/* binding */ toTRBL),
12455 /* harmony export */ ay: () => (/* binding */ toTRBLCorners),
12456 /* harmony export */ az: () => (/* binding */ _boundSegment),
12457 /* harmony export */ b: () => (/* binding */ isArray),
12458 /* harmony export */ b0: () => (/* binding */ fontString),
12459 /* harmony export */ b1: () => (/* binding */ toLineHeight),
12460 /* harmony export */ b2: () => (/* binding */ PITAU),
12461 /* harmony export */ b3: () => (/* binding */ INFINITY),
12462 /* harmony export */ b4: () => (/* binding */ RAD_PER_DEG),
12463 /* harmony export */ b5: () => (/* binding */ QUARTER_PI),
12464 /* harmony export */ b6: () => (/* binding */ TWO_THIRDS_PI),
12465 /* harmony export */ b7: () => (/* binding */ _angleDiff),
12466 /* harmony export */ c: () => (/* binding */ color),
12467 /* harmony export */ d: () => (/* binding */ defaults),
12468 /* harmony export */ e: () => (/* binding */ effects),
12469 /* harmony export */ f: () => (/* binding */ resolveObjectKey),
12470 /* harmony export */ g: () => (/* binding */ isNumberFinite),
12471 /* harmony export */ h: () => (/* binding */ defined),
12472 /* harmony export */ i: () => (/* binding */ isObject),
12473 /* harmony export */ j: () => (/* binding */ createContext),
12474 /* harmony export */ k: () => (/* binding */ isNullOrUndef),
12475 /* harmony export */ l: () => (/* binding */ listenArrayEvents),
12476 /* harmony export */ m: () => (/* binding */ toPercentage),
12477 /* harmony export */ n: () => (/* binding */ toDimension),
12478 /* harmony export */ o: () => (/* binding */ formatNumber),
12479 /* harmony export */ p: () => (/* binding */ _angleBetween),
12480 /* harmony export */ q: () => (/* binding */ _getStartAndCountOfVisiblePoints),
12481 /* harmony export */ r: () => (/* binding */ requestAnimFrame),
12482 /* harmony export */ s: () => (/* binding */ sign),
12483 /* harmony export */ t: () => (/* binding */ toRadians),
12484 /* harmony export */ u: () => (/* binding */ unlistenArrayEvents),
12485 /* harmony export */ v: () => (/* binding */ valueOrDefault),
12486 /* harmony export */ w: () => (/* binding */ _scaleRangesChanged),
12487 /* harmony export */ x: () => (/* binding */ isNumber),
12488 /* harmony export */ y: () => (/* binding */ _parseObjectDataRadialScale),
12489 /* harmony export */ z: () => (/* binding */ getRelativePosition)
12490 /* harmony export */ });
12491 /* harmony import */ var _kurkle_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kurkle/color */ "./node_modules/@kurkle/color/dist/color.esm.js");
12492 /*!
12493 * Chart.js v4.5.1
12494 * https://www.chartjs.org
12495 * (c) 2025 Chart.js Contributors
12496 * Released under the MIT License
12497 */
12498
12499
12500 /**
12501 * @namespace Chart.helpers
12502 */ /**
12503 * An empty function that can be used, for example, for optional callback.
12504 */ function noop() {
12505 /* noop */ }
12506 /**
12507 * Returns a unique id, sequentially generated from a global variable.
12508 */ const uid = (()=>{
12509 let id = 0;
12510 return ()=>id++;
12511 })();
12512 /**
12513 * Returns true if `value` is neither null nor undefined, else returns false.
12514 * @param value - The value to test.
12515 * @since 2.7.0
12516 */ function isNullOrUndef(value) {
12517 return value === null || value === undefined;
12518 }
12519 /**
12520 * Returns true if `value` is an array (including typed arrays), else returns false.
12521 * @param value - The value to test.
12522 * @function
12523 */ function isArray(value) {
12524 if (Array.isArray && Array.isArray(value)) {
12525 return true;
12526 }
12527 const type = Object.prototype.toString.call(value);
12528 if (type.slice(0, 7) === '[object' && type.slice(-6) === 'Array]') {
12529 return true;
12530 }
12531 return false;
12532 }
12533 /**
12534 * Returns true if `value` is an object (excluding null), else returns false.
12535 * @param value - The value to test.
12536 * @since 2.7.0
12537 */ function isObject(value) {
12538 return value !== null && Object.prototype.toString.call(value) === '[object Object]';
12539 }
12540 /**
12541 * Returns true if `value` is a finite number, else returns false
12542 * @param value - The value to test.
12543 */ function isNumberFinite(value) {
12544 return (typeof value === 'number' || value instanceof Number) && isFinite(+value);
12545 }
12546 /**
12547 * Returns `value` if finite, else returns `defaultValue`.
12548 * @param value - The value to return if defined.
12549 * @param defaultValue - The value to return if `value` is not finite.
12550 */ function finiteOrDefault(value, defaultValue) {
12551 return isNumberFinite(value) ? value : defaultValue;
12552 }
12553 /**
12554 * Returns `value` if defined, else returns `defaultValue`.
12555 * @param value - The value to return if defined.
12556 * @param defaultValue - The value to return if `value` is undefined.
12557 */ function valueOrDefault(value, defaultValue) {
12558 return typeof value === 'undefined' ? defaultValue : value;
12559 }
12560 const toPercentage = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 : +value / dimension;
12561 const toDimension = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 * dimension : +value;
12562 /**
12563 * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the
12564 * value returned by `fn`. If `fn` is not a function, this method returns undefined.
12565 * @param fn - The function to call.
12566 * @param args - The arguments with which `fn` should be called.
12567 * @param [thisArg] - The value of `this` provided for the call to `fn`.
12568 */ function callback(fn, args, thisArg) {
12569 if (fn && typeof fn.call === 'function') {
12570 return fn.apply(thisArg, args);
12571 }
12572 }
12573 function each(loopable, fn, thisArg, reverse) {
12574 let i, len, keys;
12575 if (isArray(loopable)) {
12576 len = loopable.length;
12577 if (reverse) {
12578 for(i = len - 1; i >= 0; i--){
12579 fn.call(thisArg, loopable[i], i);
12580 }
12581 } else {
12582 for(i = 0; i < len; i++){
12583 fn.call(thisArg, loopable[i], i);
12584 }
12585 }
12586 } else if (isObject(loopable)) {
12587 keys = Object.keys(loopable);
12588 len = keys.length;
12589 for(i = 0; i < len; i++){
12590 fn.call(thisArg, loopable[keys[i]], keys[i]);
12591 }
12592 }
12593 }
12594 /**
12595 * Returns true if the `a0` and `a1` arrays have the same content, else returns false.
12596 * @param a0 - The array to compare
12597 * @param a1 - The array to compare
12598 * @private
12599 */ function _elementsEqual(a0, a1) {
12600 let i, ilen, v0, v1;
12601 if (!a0 || !a1 || a0.length !== a1.length) {
12602 return false;
12603 }
12604 for(i = 0, ilen = a0.length; i < ilen; ++i){
12605 v0 = a0[i];
12606 v1 = a1[i];
12607 if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {
12608 return false;
12609 }
12610 }
12611 return true;
12612 }
12613 /**
12614 * Returns a deep copy of `source` without keeping references on objects and arrays.
12615 * @param source - The value to clone.
12616 */ function clone(source) {
12617 if (isArray(source)) {
12618 return source.map(clone);
12619 }
12620 if (isObject(source)) {
12621 const target = Object.create(null);
12622 const keys = Object.keys(source);
12623 const klen = keys.length;
12624 let k = 0;
12625 for(; k < klen; ++k){
12626 target[keys[k]] = clone(source[keys[k]]);
12627 }
12628 return target;
12629 }
12630 return source;
12631 }
12632 function isValidKey(key) {
12633 return [
12634 '__proto__',
12635 'prototype',
12636 'constructor'
12637 ].indexOf(key) === -1;
12638 }
12639 /**
12640 * The default merger when Chart.helpers.merge is called without merger option.
12641 * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.
12642 * @private
12643 */ function _merger(key, target, source, options) {
12644 if (!isValidKey(key)) {
12645 return;
12646 }
12647 const tval = target[key];
12648 const sval = source[key];
12649 if (isObject(tval) && isObject(sval)) {
12650 // eslint-disable-next-line @typescript-eslint/no-use-before-define
12651 merge(tval, sval, options);
12652 } else {
12653 target[key] = clone(sval);
12654 }
12655 }
12656 function merge(target, source, options) {
12657 const sources = isArray(source) ? source : [
12658 source
12659 ];
12660 const ilen = sources.length;
12661 if (!isObject(target)) {
12662 return target;
12663 }
12664 options = options || {};
12665 const merger = options.merger || _merger;
12666 let current;
12667 for(let i = 0; i < ilen; ++i){
12668 current = sources[i];
12669 if (!isObject(current)) {
12670 continue;
12671 }
12672 const keys = Object.keys(current);
12673 for(let k = 0, klen = keys.length; k < klen; ++k){
12674 merger(keys[k], target, current, options);
12675 }
12676 }
12677 return target;
12678 }
12679 function mergeIf(target, source) {
12680 // eslint-disable-next-line @typescript-eslint/no-use-before-define
12681 return merge(target, source, {
12682 merger: _mergerIf
12683 });
12684 }
12685 /**
12686 * Merges source[key] in target[key] only if target[key] is undefined.
12687 * @private
12688 */ function _mergerIf(key, target, source) {
12689 if (!isValidKey(key)) {
12690 return;
12691 }
12692 const tval = target[key];
12693 const sval = source[key];
12694 if (isObject(tval) && isObject(sval)) {
12695 mergeIf(tval, sval);
12696 } else if (!Object.prototype.hasOwnProperty.call(target, key)) {
12697 target[key] = clone(sval);
12698 }
12699 }
12700 /**
12701 * @private
12702 */ function _deprecated(scope, value, previous, current) {
12703 if (value !== undefined) {
12704 console.warn(scope + ': "' + previous + '" is deprecated. Please use "' + current + '" instead');
12705 }
12706 }
12707 // resolveObjectKey resolver cache
12708 const keyResolvers = {
12709 // Chart.helpers.core resolveObjectKey should resolve empty key to root object
12710 '': (v)=>v,
12711 // default resolvers
12712 x: (o)=>o.x,
12713 y: (o)=>o.y
12714 };
12715 /**
12716 * @private
12717 */ function _splitKey(key) {
12718 const parts = key.split('.');
12719 const keys = [];
12720 let tmp = '';
12721 for (const part of parts){
12722 tmp += part;
12723 if (tmp.endsWith('\\')) {
12724 tmp = tmp.slice(0, -1) + '.';
12725 } else {
12726 keys.push(tmp);
12727 tmp = '';
12728 }
12729 }
12730 return keys;
12731 }
12732 function _getKeyResolver(key) {
12733 const keys = _splitKey(key);
12734 return (obj)=>{
12735 for (const k of keys){
12736 if (k === '') {
12737 break;
12738 }
12739 obj = obj && obj[k];
12740 }
12741 return obj;
12742 };
12743 }
12744 function resolveObjectKey(obj, key) {
12745 const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key));
12746 return resolver(obj);
12747 }
12748 /**
12749 * @private
12750 */ function _capitalize(str) {
12751 return str.charAt(0).toUpperCase() + str.slice(1);
12752 }
12753 const defined = (value)=>typeof value !== 'undefined';
12754 const isFunction = (value)=>typeof value === 'function';
12755 // Adapted from https://stackoverflow.com/questions/31128855/comparing-ecma6-sets-for-equality#31129384
12756 const setsEqual = (a, b)=>{
12757 if (a.size !== b.size) {
12758 return false;
12759 }
12760 for (const item of a){
12761 if (!b.has(item)) {
12762 return false;
12763 }
12764 }
12765 return true;
12766 };
12767 /**
12768 * @param e - The event
12769 * @private
12770 */ function _isClickEvent(e) {
12771 return e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu';
12772 }
12773
12774 /**
12775 * @alias Chart.helpers.math
12776 * @namespace
12777 */ const PI = Math.PI;
12778 const TAU = 2 * PI;
12779 const PITAU = TAU + PI;
12780 const INFINITY = Number.POSITIVE_INFINITY;
12781 const RAD_PER_DEG = PI / 180;
12782 const HALF_PI = PI / 2;
12783 const QUARTER_PI = PI / 4;
12784 const TWO_THIRDS_PI = PI * 2 / 3;
12785 const log10 = Math.log10;
12786 const sign = Math.sign;
12787 function almostEquals(x, y, epsilon) {
12788 return Math.abs(x - y) < epsilon;
12789 }
12790 /**
12791 * Implementation of the nice number algorithm used in determining where axis labels will go
12792 */ function niceNum(range) {
12793 const roundedRange = Math.round(range);
12794 range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range;
12795 const niceRange = Math.pow(10, Math.floor(log10(range)));
12796 const fraction = range / niceRange;
12797 const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;
12798 return niceFraction * niceRange;
12799 }
12800 /**
12801 * Returns an array of factors sorted from 1 to sqrt(value)
12802 * @private
12803 */ function _factorize(value) {
12804 const result = [];
12805 const sqrt = Math.sqrt(value);
12806 let i;
12807 for(i = 1; i < sqrt; i++){
12808 if (value % i === 0) {
12809 result.push(i);
12810 result.push(value / i);
12811 }
12812 }
12813 if (sqrt === (sqrt | 0)) {
12814 result.push(sqrt);
12815 }
12816 result.sort((a, b)=>a - b).pop();
12817 return result;
12818 }
12819 /**
12820 * Verifies that attempting to coerce n to string or number won't throw a TypeError.
12821 */ function isNonPrimitive(n) {
12822 return typeof n === 'symbol' || typeof n === 'object' && n !== null && !(Symbol.toPrimitive in n || 'toString' in n || 'valueOf' in n);
12823 }
12824 function isNumber(n) {
12825 return !isNonPrimitive(n) && !isNaN(parseFloat(n)) && isFinite(n);
12826 }
12827 function almostWhole(x, epsilon) {
12828 const rounded = Math.round(x);
12829 return rounded - epsilon <= x && rounded + epsilon >= x;
12830 }
12831 /**
12832 * @private
12833 */ function _setMinAndMaxByKey(array, target, property) {
12834 let i, ilen, value;
12835 for(i = 0, ilen = array.length; i < ilen; i++){
12836 value = array[i][property];
12837 if (!isNaN(value)) {
12838 target.min = Math.min(target.min, value);
12839 target.max = Math.max(target.max, value);
12840 }
12841 }
12842 }
12843 function toRadians(degrees) {
12844 return degrees * (PI / 180);
12845 }
12846 function toDegrees(radians) {
12847 return radians * (180 / PI);
12848 }
12849 /**
12850 * Returns the number of decimal places
12851 * i.e. the number of digits after the decimal point, of the value of this Number.
12852 * @param x - A number.
12853 * @returns The number of decimal places.
12854 * @private
12855 */ function _decimalPlaces(x) {
12856 if (!isNumberFinite(x)) {
12857 return;
12858 }
12859 let e = 1;
12860 let p = 0;
12861 while(Math.round(x * e) / e !== x){
12862 e *= 10;
12863 p++;
12864 }
12865 return p;
12866 }
12867 // Gets the angle from vertical upright to the point about a centre.
12868 function getAngleFromPoint(centrePoint, anglePoint) {
12869 const distanceFromXCenter = anglePoint.x - centrePoint.x;
12870 const distanceFromYCenter = anglePoint.y - centrePoint.y;
12871 const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
12872 let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
12873 if (angle < -0.5 * PI) {
12874 angle += TAU; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
12875 }
12876 return {
12877 angle,
12878 distance: radialDistanceFromCenter
12879 };
12880 }
12881 function distanceBetweenPoints(pt1, pt2) {
12882 return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
12883 }
12884 /**
12885 * Shortest distance between angles, in either direction.
12886 * @private
12887 */ function _angleDiff(a, b) {
12888 return (a - b + PITAU) % TAU - PI;
12889 }
12890 /**
12891 * Normalize angle to be between 0 and 2*PI
12892 * @private
12893 */ function _normalizeAngle(a) {
12894 return (a % TAU + TAU) % TAU;
12895 }
12896 /**
12897 * @private
12898 */ function _angleBetween(angle, start, end, sameAngleIsFullCircle) {
12899 const a = _normalizeAngle(angle);
12900 const s = _normalizeAngle(start);
12901 const e = _normalizeAngle(end);
12902 const angleToStart = _normalizeAngle(s - a);
12903 const angleToEnd = _normalizeAngle(e - a);
12904 const startToAngle = _normalizeAngle(a - s);
12905 const endToAngle = _normalizeAngle(a - e);
12906 return a === s || a === e || sameAngleIsFullCircle && s === e || angleToStart > angleToEnd && startToAngle < endToAngle;
12907 }
12908 /**
12909 * Limit `value` between `min` and `max`
12910 * @param value
12911 * @param min
12912 * @param max
12913 * @private
12914 */ function _limitValue(value, min, max) {
12915 return Math.max(min, Math.min(max, value));
12916 }
12917 /**
12918 * @param {number} value
12919 * @private
12920 */ function _int16Range(value) {
12921 return _limitValue(value, -32768, 32767);
12922 }
12923 /**
12924 * @param value
12925 * @param start
12926 * @param end
12927 * @param [epsilon]
12928 * @private
12929 */ function _isBetween(value, start, end, epsilon = 1e-6) {
12930 return value >= Math.min(start, end) - epsilon && value <= Math.max(start, end) + epsilon;
12931 }
12932
12933 function _lookup(table, value, cmp) {
12934 cmp = cmp || ((index)=>table[index] < value);
12935 let hi = table.length - 1;
12936 let lo = 0;
12937 let mid;
12938 while(hi - lo > 1){
12939 mid = lo + hi >> 1;
12940 if (cmp(mid)) {
12941 lo = mid;
12942 } else {
12943 hi = mid;
12944 }
12945 }
12946 return {
12947 lo,
12948 hi
12949 };
12950 }
12951 /**
12952 * Binary search
12953 * @param table - the table search. must be sorted!
12954 * @param key - property name for the value in each entry
12955 * @param value - value to find
12956 * @param last - lookup last index
12957 * @private
12958 */ const _lookupByKey = (table, key, value, last)=>_lookup(table, value, last ? (index)=>{
12959 const ti = table[index][key];
12960 return ti < value || ti === value && table[index + 1][key] === value;
12961 } : (index)=>table[index][key] < value);
12962 /**
12963 * Reverse binary search
12964 * @param table - the table search. must be sorted!
12965 * @param key - property name for the value in each entry
12966 * @param value - value to find
12967 * @private
12968 */ const _rlookupByKey = (table, key, value)=>_lookup(table, value, (index)=>table[index][key] >= value);
12969 /**
12970 * Return subset of `values` between `min` and `max` inclusive.
12971 * Values are assumed to be in sorted order.
12972 * @param values - sorted array of values
12973 * @param min - min value
12974 * @param max - max value
12975 */ function _filterBetween(values, min, max) {
12976 let start = 0;
12977 let end = values.length;
12978 while(start < end && values[start] < min){
12979 start++;
12980 }
12981 while(end > start && values[end - 1] > max){
12982 end--;
12983 }
12984 return start > 0 || end < values.length ? values.slice(start, end) : values;
12985 }
12986 const arrayEvents = [
12987 'push',
12988 'pop',
12989 'shift',
12990 'splice',
12991 'unshift'
12992 ];
12993 function listenArrayEvents(array, listener) {
12994 if (array._chartjs) {
12995 array._chartjs.listeners.push(listener);
12996 return;
12997 }
12998 Object.defineProperty(array, '_chartjs', {
12999 configurable: true,
13000 enumerable: false,
13001 value: {
13002 listeners: [
13003 listener
13004 ]
13005 }
13006 });
13007 arrayEvents.forEach((key)=>{
13008 const method = '_onData' + _capitalize(key);
13009 const base = array[key];
13010 Object.defineProperty(array, key, {
13011 configurable: true,
13012 enumerable: false,
13013 value (...args) {
13014 const res = base.apply(this, args);
13015 array._chartjs.listeners.forEach((object)=>{
13016 if (typeof object[method] === 'function') {
13017 object[method](...args);
13018 }
13019 });
13020 return res;
13021 }
13022 });
13023 });
13024 }
13025 function unlistenArrayEvents(array, listener) {
13026 const stub = array._chartjs;
13027 if (!stub) {
13028 return;
13029 }
13030 const listeners = stub.listeners;
13031 const index = listeners.indexOf(listener);
13032 if (index !== -1) {
13033 listeners.splice(index, 1);
13034 }
13035 if (listeners.length > 0) {
13036 return;
13037 }
13038 arrayEvents.forEach((key)=>{
13039 delete array[key];
13040 });
13041 delete array._chartjs;
13042 }
13043 /**
13044 * @param items
13045 */ function _arrayUnique(items) {
13046 const set = new Set(items);
13047 if (set.size === items.length) {
13048 return items;
13049 }
13050 return Array.from(set);
13051 }
13052
13053 function fontString(pixelSize, fontStyle, fontFamily) {
13054 return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
13055 }
13056 /**
13057 * Request animation polyfill
13058 */ const requestAnimFrame = function() {
13059 if (typeof window === 'undefined') {
13060 return function(callback) {
13061 return callback();
13062 };
13063 }
13064 return window.requestAnimationFrame;
13065 }();
13066 /**
13067 * Throttles calling `fn` once per animation frame
13068 * Latest arguments are used on the actual call
13069 */ function throttled(fn, thisArg) {
13070 let argsToUse = [];
13071 let ticking = false;
13072 return function(...args) {
13073 // Save the args for use later
13074 argsToUse = args;
13075 if (!ticking) {
13076 ticking = true;
13077 requestAnimFrame.call(window, ()=>{
13078 ticking = false;
13079 fn.apply(thisArg, argsToUse);
13080 });
13081 }
13082 };
13083 }
13084 /**
13085 * Debounces calling `fn` for `delay` ms
13086 */ function debounce(fn, delay) {
13087 let timeout;
13088 return function(...args) {
13089 if (delay) {
13090 clearTimeout(timeout);
13091 timeout = setTimeout(fn, delay, args);
13092 } else {
13093 fn.apply(this, args);
13094 }
13095 return delay;
13096 };
13097 }
13098 /**
13099 * Converts 'start' to 'left', 'end' to 'right' and others to 'center'
13100 * @private
13101 */ const _toLeftRightCenter = (align)=>align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';
13102 /**
13103 * Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center`
13104 * @private
13105 */ const _alignStartEnd = (align, start, end)=>align === 'start' ? start : align === 'end' ? end : (start + end) / 2;
13106 /**
13107 * Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left`
13108 * @private
13109 */ const _textX = (align, left, right, rtl)=>{
13110 const check = rtl ? 'left' : 'right';
13111 return align === check ? right : align === 'center' ? (left + right) / 2 : left;
13112 };
13113 /**
13114 * Return start and count of visible points.
13115 * @private
13116 */ function _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) {
13117 const pointCount = points.length;
13118 let start = 0;
13119 let count = pointCount;
13120 if (meta._sorted) {
13121 const { iScale , vScale , _parsed } = meta;
13122 const spanGaps = meta.dataset ? meta.dataset.options ? meta.dataset.options.spanGaps : null : null;
13123 const axis = iScale.axis;
13124 const { min , max , minDefined , maxDefined } = iScale.getUserBounds();
13125 if (minDefined) {
13126 start = Math.min(// @ts-expect-error Need to type _parsed
13127 _lookupByKey(_parsed, axis, min).lo, // @ts-expect-error Need to fix types on _lookupByKey
13128 animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo);
13129 if (spanGaps) {
13130 const distanceToDefinedLo = _parsed.slice(0, start + 1).reverse().findIndex((point)=>!isNullOrUndef(point[vScale.axis]));
13131 start -= Math.max(0, distanceToDefinedLo);
13132 }
13133 start = _limitValue(start, 0, pointCount - 1);
13134 }
13135 if (maxDefined) {
13136 let end = Math.max(// @ts-expect-error Need to type _parsed
13137 _lookupByKey(_parsed, iScale.axis, max, true).hi + 1, // @ts-expect-error Need to fix types on _lookupByKey
13138 animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1);
13139 if (spanGaps) {
13140 const distanceToDefinedHi = _parsed.slice(end - 1).findIndex((point)=>!isNullOrUndef(point[vScale.axis]));
13141 end += Math.max(0, distanceToDefinedHi);
13142 }
13143 count = _limitValue(end, start, pointCount) - start;
13144 } else {
13145 count = pointCount - start;
13146 }
13147 }
13148 return {
13149 start,
13150 count
13151 };
13152 }
13153 /**
13154 * Checks if the scale ranges have changed.
13155 * @param {object} meta - dataset meta.
13156 * @returns {boolean}
13157 * @private
13158 */ function _scaleRangesChanged(meta) {
13159 const { xScale , yScale , _scaleRanges } = meta;
13160 const newRanges = {
13161 xmin: xScale.min,
13162 xmax: xScale.max,
13163 ymin: yScale.min,
13164 ymax: yScale.max
13165 };
13166 if (!_scaleRanges) {
13167 meta._scaleRanges = newRanges;
13168 return true;
13169 }
13170 const changed = _scaleRanges.xmin !== xScale.min || _scaleRanges.xmax !== xScale.max || _scaleRanges.ymin !== yScale.min || _scaleRanges.ymax !== yScale.max;
13171 Object.assign(_scaleRanges, newRanges);
13172 return changed;
13173 }
13174
13175 const atEdge = (t)=>t === 0 || t === 1;
13176 const elasticIn = (t, s, p)=>-(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p));
13177 const elasticOut = (t, s, p)=>Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1;
13178 /**
13179 * Easing functions adapted from Robert Penner's easing equations.
13180 * @namespace Chart.helpers.easing.effects
13181 * @see http://www.robertpenner.com/easing/
13182 */ const effects = {
13183 linear: (t)=>t,
13184 easeInQuad: (t)=>t * t,
13185 easeOutQuad: (t)=>-t * (t - 2),
13186 easeInOutQuad: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1),
13187 easeInCubic: (t)=>t * t * t,
13188 easeOutCubic: (t)=>(t -= 1) * t * t + 1,
13189 easeInOutCubic: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2),
13190 easeInQuart: (t)=>t * t * t * t,
13191 easeOutQuart: (t)=>-((t -= 1) * t * t * t - 1),
13192 easeInOutQuart: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2),
13193 easeInQuint: (t)=>t * t * t * t * t,
13194 easeOutQuint: (t)=>(t -= 1) * t * t * t * t + 1,
13195 easeInOutQuint: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2),
13196 easeInSine: (t)=>-Math.cos(t * HALF_PI) + 1,
13197 easeOutSine: (t)=>Math.sin(t * HALF_PI),
13198 easeInOutSine: (t)=>-0.5 * (Math.cos(PI * t) - 1),
13199 easeInExpo: (t)=>t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),
13200 easeOutExpo: (t)=>t === 1 ? 1 : -Math.pow(2, -10 * t) + 1,
13201 easeInOutExpo: (t)=>atEdge(t) ? t : t < 0.5 ? 0.5 * Math.pow(2, 10 * (t * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2),
13202 easeInCirc: (t)=>t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1),
13203 easeOutCirc: (t)=>Math.sqrt(1 - (t -= 1) * t),
13204 easeInOutCirc: (t)=>(t /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),
13205 easeInElastic: (t)=>atEdge(t) ? t : elasticIn(t, 0.075, 0.3),
13206 easeOutElastic: (t)=>atEdge(t) ? t : elasticOut(t, 0.075, 0.3),
13207 easeInOutElastic (t) {
13208 const s = 0.1125;
13209 const p = 0.45;
13210 return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p);
13211 },
13212 easeInBack (t) {
13213 const s = 1.70158;
13214 return t * t * ((s + 1) * t - s);
13215 },
13216 easeOutBack (t) {
13217 const s = 1.70158;
13218 return (t -= 1) * t * ((s + 1) * t + s) + 1;
13219 },
13220 easeInOutBack (t) {
13221 let s = 1.70158;
13222 if ((t /= 0.5) < 1) {
13223 return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));
13224 }
13225 return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);
13226 },
13227 easeInBounce: (t)=>1 - effects.easeOutBounce(1 - t),
13228 easeOutBounce (t) {
13229 const m = 7.5625;
13230 const d = 2.75;
13231 if (t < 1 / d) {
13232 return m * t * t;
13233 }
13234 if (t < 2 / d) {
13235 return m * (t -= 1.5 / d) * t + 0.75;
13236 }
13237 if (t < 2.5 / d) {
13238 return m * (t -= 2.25 / d) * t + 0.9375;
13239 }
13240 return m * (t -= 2.625 / d) * t + 0.984375;
13241 },
13242 easeInOutBounce: (t)=>t < 0.5 ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5
13243 };
13244
13245 function isPatternOrGradient(value) {
13246 if (value && typeof value === 'object') {
13247 const type = value.toString();
13248 return type === '[object CanvasPattern]' || type === '[object CanvasGradient]';
13249 }
13250 return false;
13251 }
13252 function color(value) {
13253 return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value);
13254 }
13255 function getHoverColor(value) {
13256 return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value).saturate(0.5).darken(0.1).hexString();
13257 }
13258
13259 const numbers = [
13260 'x',
13261 'y',
13262 'borderWidth',
13263 'radius',
13264 'tension'
13265 ];
13266 const colors = [
13267 'color',
13268 'borderColor',
13269 'backgroundColor'
13270 ];
13271 function applyAnimationsDefaults(defaults) {
13272 defaults.set('animation', {
13273 delay: undefined,
13274 duration: 1000,
13275 easing: 'easeOutQuart',
13276 fn: undefined,
13277 from: undefined,
13278 loop: undefined,
13279 to: undefined,
13280 type: undefined
13281 });
13282 defaults.describe('animation', {
13283 _fallback: false,
13284 _indexable: false,
13285 _scriptable: (name)=>name !== 'onProgress' && name !== 'onComplete' && name !== 'fn'
13286 });
13287 defaults.set('animations', {
13288 colors: {
13289 type: 'color',
13290 properties: colors
13291 },
13292 numbers: {
13293 type: 'number',
13294 properties: numbers
13295 }
13296 });
13297 defaults.describe('animations', {
13298 _fallback: 'animation'
13299 });
13300 defaults.set('transitions', {
13301 active: {
13302 animation: {
13303 duration: 400
13304 }
13305 },
13306 resize: {
13307 animation: {
13308 duration: 0
13309 }
13310 },
13311 show: {
13312 animations: {
13313 colors: {
13314 from: 'transparent'
13315 },
13316 visible: {
13317 type: 'boolean',
13318 duration: 0
13319 }
13320 }
13321 },
13322 hide: {
13323 animations: {
13324 colors: {
13325 to: 'transparent'
13326 },
13327 visible: {
13328 type: 'boolean',
13329 easing: 'linear',
13330 fn: (v)=>v | 0
13331 }
13332 }
13333 }
13334 });
13335 }
13336
13337 function applyLayoutsDefaults(defaults) {
13338 defaults.set('layout', {
13339 autoPadding: true,
13340 padding: {
13341 top: 0,
13342 right: 0,
13343 bottom: 0,
13344 left: 0
13345 }
13346 });
13347 }
13348
13349 const intlCache = new Map();
13350 function getNumberFormat(locale, options) {
13351 options = options || {};
13352 const cacheKey = locale + JSON.stringify(options);
13353 let formatter = intlCache.get(cacheKey);
13354 if (!formatter) {
13355 formatter = new Intl.NumberFormat(locale, options);
13356 intlCache.set(cacheKey, formatter);
13357 }
13358 return formatter;
13359 }
13360 function formatNumber(num, locale, options) {
13361 return getNumberFormat(locale, options).format(num);
13362 }
13363
13364 const formatters = {
13365 values (value) {
13366 return isArray(value) ? value : '' + value;
13367 },
13368 numeric (tickValue, index, ticks) {
13369 if (tickValue === 0) {
13370 return '0';
13371 }
13372 const locale = this.chart.options.locale;
13373 let notation;
13374 let delta = tickValue;
13375 if (ticks.length > 1) {
13376 const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
13377 if (maxTick < 1e-4 || maxTick > 1e+15) {
13378 notation = 'scientific';
13379 }
13380 delta = calculateDelta(tickValue, ticks);
13381 }
13382 const logDelta = log10(Math.abs(delta));
13383 const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);
13384 const options = {
13385 notation,
13386 minimumFractionDigits: numDecimal,
13387 maximumFractionDigits: numDecimal
13388 };
13389 Object.assign(options, this.options.ticks.format);
13390 return formatNumber(tickValue, locale, options);
13391 },
13392 logarithmic (tickValue, index, ticks) {
13393 if (tickValue === 0) {
13394 return '0';
13395 }
13396 const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue)));
13397 if ([
13398 1,
13399 2,
13400 3,
13401 5,
13402 10,
13403 15
13404 ].includes(remain) || index > 0.8 * ticks.length) {
13405 return formatters.numeric.call(this, tickValue, index, ticks);
13406 }
13407 return '';
13408 }
13409 };
13410 function calculateDelta(tickValue, ticks) {
13411 let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
13412 if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {
13413 delta = tickValue - Math.floor(tickValue);
13414 }
13415 return delta;
13416 }
13417 var Ticks = {
13418 formatters
13419 };
13420
13421 function applyScaleDefaults(defaults) {
13422 defaults.set('scale', {
13423 display: true,
13424 offset: false,
13425 reverse: false,
13426 beginAtZero: false,
13427 bounds: 'ticks',
13428 clip: true,
13429 grace: 0,
13430 grid: {
13431 display: true,
13432 lineWidth: 1,
13433 drawOnChartArea: true,
13434 drawTicks: true,
13435 tickLength: 8,
13436 tickWidth: (_ctx, options)=>options.lineWidth,
13437 tickColor: (_ctx, options)=>options.color,
13438 offset: false
13439 },
13440 border: {
13441 display: true,
13442 dash: [],
13443 dashOffset: 0.0,
13444 width: 1
13445 },
13446 title: {
13447 display: false,
13448 text: '',
13449 padding: {
13450 top: 4,
13451 bottom: 4
13452 }
13453 },
13454 ticks: {
13455 minRotation: 0,
13456 maxRotation: 50,
13457 mirror: false,
13458 textStrokeWidth: 0,
13459 textStrokeColor: '',
13460 padding: 3,
13461 display: true,
13462 autoSkip: true,
13463 autoSkipPadding: 3,
13464 labelOffset: 0,
13465 callback: Ticks.formatters.values,
13466 minor: {},
13467 major: {},
13468 align: 'center',
13469 crossAlign: 'near',
13470 showLabelBackdrop: false,
13471 backdropColor: 'rgba(255, 255, 255, 0.75)',
13472 backdropPadding: 2
13473 }
13474 });
13475 defaults.route('scale.ticks', 'color', '', 'color');
13476 defaults.route('scale.grid', 'color', '', 'borderColor');
13477 defaults.route('scale.border', 'color', '', 'borderColor');
13478 defaults.route('scale.title', 'color', '', 'color');
13479 defaults.describe('scale', {
13480 _fallback: false,
13481 _scriptable: (name)=>!name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser',
13482 _indexable: (name)=>name !== 'borderDash' && name !== 'tickBorderDash' && name !== 'dash'
13483 });
13484 defaults.describe('scales', {
13485 _fallback: 'scale'
13486 });
13487 defaults.describe('scale.ticks', {
13488 _scriptable: (name)=>name !== 'backdropPadding' && name !== 'callback',
13489 _indexable: (name)=>name !== 'backdropPadding'
13490 });
13491 }
13492
13493 const overrides = Object.create(null);
13494 const descriptors = Object.create(null);
13495 function getScope$1(node, key) {
13496 if (!key) {
13497 return node;
13498 }
13499 const keys = key.split('.');
13500 for(let i = 0, n = keys.length; i < n; ++i){
13501 const k = keys[i];
13502 node = node[k] || (node[k] = Object.create(null));
13503 }
13504 return node;
13505 }
13506 function set(root, scope, values) {
13507 if (typeof scope === 'string') {
13508 return merge(getScope$1(root, scope), values);
13509 }
13510 return merge(getScope$1(root, ''), scope);
13511 }
13512 class Defaults {
13513 constructor(_descriptors, _appliers){
13514 this.animation = undefined;
13515 this.backgroundColor = 'rgba(0,0,0,0.1)';
13516 this.borderColor = 'rgba(0,0,0,0.1)';
13517 this.color = '#666';
13518 this.datasets = {};
13519 this.devicePixelRatio = (context)=>context.chart.platform.getDevicePixelRatio();
13520 this.elements = {};
13521 this.events = [
13522 'mousemove',
13523 'mouseout',
13524 'click',
13525 'touchstart',
13526 'touchmove'
13527 ];
13528 this.font = {
13529 family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
13530 size: 12,
13531 style: 'normal',
13532 lineHeight: 1.2,
13533 weight: null
13534 };
13535 this.hover = {};
13536 this.hoverBackgroundColor = (ctx, options)=>getHoverColor(options.backgroundColor);
13537 this.hoverBorderColor = (ctx, options)=>getHoverColor(options.borderColor);
13538 this.hoverColor = (ctx, options)=>getHoverColor(options.color);
13539 this.indexAxis = 'x';
13540 this.interaction = {
13541 mode: 'nearest',
13542 intersect: true,
13543 includeInvisible: false
13544 };
13545 this.maintainAspectRatio = true;
13546 this.onHover = null;
13547 this.onClick = null;
13548 this.parsing = true;
13549 this.plugins = {};
13550 this.responsive = true;
13551 this.scale = undefined;
13552 this.scales = {};
13553 this.showLine = true;
13554 this.drawActiveElementsOnTop = true;
13555 this.describe(_descriptors);
13556 this.apply(_appliers);
13557 }
13558 set(scope, values) {
13559 return set(this, scope, values);
13560 }
13561 get(scope) {
13562 return getScope$1(this, scope);
13563 }
13564 describe(scope, values) {
13565 return set(descriptors, scope, values);
13566 }
13567 override(scope, values) {
13568 return set(overrides, scope, values);
13569 }
13570 route(scope, name, targetScope, targetName) {
13571 const scopeObject = getScope$1(this, scope);
13572 const targetScopeObject = getScope$1(this, targetScope);
13573 const privateName = '_' + name;
13574 Object.defineProperties(scopeObject, {
13575 [privateName]: {
13576 value: scopeObject[name],
13577 writable: true
13578 },
13579 [name]: {
13580 enumerable: true,
13581 get () {
13582 const local = this[privateName];
13583 const target = targetScopeObject[targetName];
13584 if (isObject(local)) {
13585 return Object.assign({}, target, local);
13586 }
13587 return valueOrDefault(local, target);
13588 },
13589 set (value) {
13590 this[privateName] = value;
13591 }
13592 }
13593 });
13594 }
13595 apply(appliers) {
13596 appliers.forEach((apply)=>apply(this));
13597 }
13598 }
13599 var defaults = /* #__PURE__ */ new Defaults({
13600 _scriptable: (name)=>!name.startsWith('on'),
13601 _indexable: (name)=>name !== 'events',
13602 hover: {
13603 _fallback: 'interaction'
13604 },
13605 interaction: {
13606 _scriptable: false,
13607 _indexable: false
13608 }
13609 }, [
13610 applyAnimationsDefaults,
13611 applyLayoutsDefaults,
13612 applyScaleDefaults
13613 ]);
13614
13615 /**
13616 * Converts the given font object into a CSS font string.
13617 * @param font - A font object.
13618 * @return The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font
13619 * @private
13620 */ function toFontString(font) {
13621 if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {
13622 return null;
13623 }
13624 return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family;
13625 }
13626 /**
13627 * @private
13628 */ function _measureText(ctx, data, gc, longest, string) {
13629 let textWidth = data[string];
13630 if (!textWidth) {
13631 textWidth = data[string] = ctx.measureText(string).width;
13632 gc.push(string);
13633 }
13634 if (textWidth > longest) {
13635 longest = textWidth;
13636 }
13637 return longest;
13638 }
13639 /**
13640 * @private
13641 */ // eslint-disable-next-line complexity
13642 function _longestText(ctx, font, arrayOfThings, cache) {
13643 cache = cache || {};
13644 let data = cache.data = cache.data || {};
13645 let gc = cache.garbageCollect = cache.garbageCollect || [];
13646 if (cache.font !== font) {
13647 data = cache.data = {};
13648 gc = cache.garbageCollect = [];
13649 cache.font = font;
13650 }
13651 ctx.save();
13652 ctx.font = font;
13653 let longest = 0;
13654 const ilen = arrayOfThings.length;
13655 let i, j, jlen, thing, nestedThing;
13656 for(i = 0; i < ilen; i++){
13657 thing = arrayOfThings[i];
13658 // Undefined strings and arrays should not be measured
13659 if (thing !== undefined && thing !== null && !isArray(thing)) {
13660 longest = _measureText(ctx, data, gc, longest, thing);
13661 } else if (isArray(thing)) {
13662 // if it is an array lets measure each element
13663 // to do maybe simplify this function a bit so we can do this more recursively?
13664 for(j = 0, jlen = thing.length; j < jlen; j++){
13665 nestedThing = thing[j];
13666 // Undefined strings and arrays should not be measured
13667 if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) {
13668 longest = _measureText(ctx, data, gc, longest, nestedThing);
13669 }
13670 }
13671 }
13672 }
13673 ctx.restore();
13674 const gcLen = gc.length / 2;
13675 if (gcLen > arrayOfThings.length) {
13676 for(i = 0; i < gcLen; i++){
13677 delete data[gc[i]];
13678 }
13679 gc.splice(0, gcLen);
13680 }
13681 return longest;
13682 }
13683 /**
13684 * Returns the aligned pixel value to avoid anti-aliasing blur
13685 * @param chart - The chart instance.
13686 * @param pixel - A pixel value.
13687 * @param width - The width of the element.
13688 * @returns The aligned pixel value.
13689 * @private
13690 */ function _alignPixel(chart, pixel, width) {
13691 const devicePixelRatio = chart.currentDevicePixelRatio;
13692 const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;
13693 return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;
13694 }
13695 /**
13696 * Clears the entire canvas.
13697 */ function clearCanvas(canvas, ctx) {
13698 if (!ctx && !canvas) {
13699 return;
13700 }
13701 ctx = ctx || canvas.getContext('2d');
13702 ctx.save();
13703 // canvas.width and canvas.height do not consider the canvas transform,
13704 // while clearRect does
13705 ctx.resetTransform();
13706 ctx.clearRect(0, 0, canvas.width, canvas.height);
13707 ctx.restore();
13708 }
13709 function drawPoint(ctx, options, x, y) {
13710 // eslint-disable-next-line @typescript-eslint/no-use-before-define
13711 drawPointLegend(ctx, options, x, y, null);
13712 }
13713 // eslint-disable-next-line complexity
13714 function drawPointLegend(ctx, options, x, y, w) {
13715 let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW;
13716 const style = options.pointStyle;
13717 const rotation = options.rotation;
13718 const radius = options.radius;
13719 let rad = (rotation || 0) * RAD_PER_DEG;
13720 if (style && typeof style === 'object') {
13721 type = style.toString();
13722 if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
13723 ctx.save();
13724 ctx.translate(x, y);
13725 ctx.rotate(rad);
13726 ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);
13727 ctx.restore();
13728 return;
13729 }
13730 }
13731 if (isNaN(radius) || radius <= 0) {
13732 return;
13733 }
13734 ctx.beginPath();
13735 switch(style){
13736 // Default includes circle
13737 default:
13738 if (w) {
13739 ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU);
13740 } else {
13741 ctx.arc(x, y, radius, 0, TAU);
13742 }
13743 ctx.closePath();
13744 break;
13745 case 'triangle':
13746 width = w ? w / 2 : radius;
13747 ctx.moveTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
13748 rad += TWO_THIRDS_PI;
13749 ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
13750 rad += TWO_THIRDS_PI;
13751 ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
13752 ctx.closePath();
13753 break;
13754 case 'rectRounded':
13755 // NOTE: the rounded rect implementation changed to use `arc` instead of
13756 // `quadraticCurveTo` since it generates better results when rect is
13757 // almost a circle. 0.516 (instead of 0.5) produces results with visually
13758 // closer proportion to the previous impl and it is inscribed in the
13759 // circle with `radius`. For more details, see the following PRs:
13760 // https://github.com/chartjs/Chart.js/issues/5597
13761 // https://github.com/chartjs/Chart.js/issues/5858
13762 cornerRadius = radius * 0.516;
13763 size = radius - cornerRadius;
13764 xOffset = Math.cos(rad + QUARTER_PI) * size;
13765 xOffsetW = Math.cos(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);
13766 yOffset = Math.sin(rad + QUARTER_PI) * size;
13767 yOffsetW = Math.sin(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);
13768 ctx.arc(x - xOffsetW, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);
13769 ctx.arc(x + yOffsetW, y - xOffset, cornerRadius, rad - HALF_PI, rad);
13770 ctx.arc(x + xOffsetW, y + yOffset, cornerRadius, rad, rad + HALF_PI);
13771 ctx.arc(x - yOffsetW, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);
13772 ctx.closePath();
13773 break;
13774 case 'rect':
13775 if (!rotation) {
13776 size = Math.SQRT1_2 * radius;
13777 width = w ? w / 2 : size;
13778 ctx.rect(x - width, y - size, 2 * width, 2 * size);
13779 break;
13780 }
13781 rad += QUARTER_PI;
13782 /* falls through */ case 'rectRot':
13783 xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
13784 xOffset = Math.cos(rad) * radius;
13785 yOffset = Math.sin(rad) * radius;
13786 yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
13787 ctx.moveTo(x - xOffsetW, y - yOffset);
13788 ctx.lineTo(x + yOffsetW, y - xOffset);
13789 ctx.lineTo(x + xOffsetW, y + yOffset);
13790 ctx.lineTo(x - yOffsetW, y + xOffset);
13791 ctx.closePath();
13792 break;
13793 case 'crossRot':
13794 rad += QUARTER_PI;
13795 /* falls through */ case 'cross':
13796 xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
13797 xOffset = Math.cos(rad) * radius;
13798 yOffset = Math.sin(rad) * radius;
13799 yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
13800 ctx.moveTo(x - xOffsetW, y - yOffset);
13801 ctx.lineTo(x + xOffsetW, y + yOffset);
13802 ctx.moveTo(x + yOffsetW, y - xOffset);
13803 ctx.lineTo(x - yOffsetW, y + xOffset);
13804 break;
13805 case 'star':
13806 xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
13807 xOffset = Math.cos(rad) * radius;
13808 yOffset = Math.sin(rad) * radius;
13809 yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
13810 ctx.moveTo(x - xOffsetW, y - yOffset);
13811 ctx.lineTo(x + xOffsetW, y + yOffset);
13812 ctx.moveTo(x + yOffsetW, y - xOffset);
13813 ctx.lineTo(x - yOffsetW, y + xOffset);
13814 rad += QUARTER_PI;
13815 xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
13816 xOffset = Math.cos(rad) * radius;
13817 yOffset = Math.sin(rad) * radius;
13818 yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
13819 ctx.moveTo(x - xOffsetW, y - yOffset);
13820 ctx.lineTo(x + xOffsetW, y + yOffset);
13821 ctx.moveTo(x + yOffsetW, y - xOffset);
13822 ctx.lineTo(x - yOffsetW, y + xOffset);
13823 break;
13824 case 'line':
13825 xOffset = w ? w / 2 : Math.cos(rad) * radius;
13826 yOffset = Math.sin(rad) * radius;
13827 ctx.moveTo(x - xOffset, y - yOffset);
13828 ctx.lineTo(x + xOffset, y + yOffset);
13829 break;
13830 case 'dash':
13831 ctx.moveTo(x, y);
13832 ctx.lineTo(x + Math.cos(rad) * (w ? w / 2 : radius), y + Math.sin(rad) * radius);
13833 break;
13834 case false:
13835 ctx.closePath();
13836 break;
13837 }
13838 ctx.fill();
13839 if (options.borderWidth > 0) {
13840 ctx.stroke();
13841 }
13842 }
13843 /**
13844 * Returns true if the point is inside the rectangle
13845 * @param point - The point to test
13846 * @param area - The rectangle
13847 * @param margin - allowed margin
13848 * @private
13849 */ function _isPointInArea(point, area, margin) {
13850 margin = margin || 0.5; // margin - default is to match rounded decimals
13851 return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin;
13852 }
13853 function clipArea(ctx, area) {
13854 ctx.save();
13855 ctx.beginPath();
13856 ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
13857 ctx.clip();
13858 }
13859 function unclipArea(ctx) {
13860 ctx.restore();
13861 }
13862 /**
13863 * @private
13864 */ function _steppedLineTo(ctx, previous, target, flip, mode) {
13865 if (!previous) {
13866 return ctx.lineTo(target.x, target.y);
13867 }
13868 if (mode === 'middle') {
13869 const midpoint = (previous.x + target.x) / 2.0;
13870 ctx.lineTo(midpoint, previous.y);
13871 ctx.lineTo(midpoint, target.y);
13872 } else if (mode === 'after' !== !!flip) {
13873 ctx.lineTo(previous.x, target.y);
13874 } else {
13875 ctx.lineTo(target.x, previous.y);
13876 }
13877 ctx.lineTo(target.x, target.y);
13878 }
13879 /**
13880 * @private
13881 */ function _bezierCurveTo(ctx, previous, target, flip) {
13882 if (!previous) {
13883 return ctx.lineTo(target.x, target.y);
13884 }
13885 ctx.bezierCurveTo(flip ? previous.cp1x : previous.cp2x, flip ? previous.cp1y : previous.cp2y, flip ? target.cp2x : target.cp1x, flip ? target.cp2y : target.cp1y, target.x, target.y);
13886 }
13887 function setRenderOpts(ctx, opts) {
13888 if (opts.translation) {
13889 ctx.translate(opts.translation[0], opts.translation[1]);
13890 }
13891 if (!isNullOrUndef(opts.rotation)) {
13892 ctx.rotate(opts.rotation);
13893 }
13894 if (opts.color) {
13895 ctx.fillStyle = opts.color;
13896 }
13897 if (opts.textAlign) {
13898 ctx.textAlign = opts.textAlign;
13899 }
13900 if (opts.textBaseline) {
13901 ctx.textBaseline = opts.textBaseline;
13902 }
13903 }
13904 function decorateText(ctx, x, y, line, opts) {
13905 if (opts.strikethrough || opts.underline) {
13906 /**
13907 * Now that IE11 support has been dropped, we can use more
13908 * of the TextMetrics object. The actual bounding boxes
13909 * are unflagged in Chrome, Firefox, Edge, and Safari so they
13910 * can be safely used.
13911 * See https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics#Browser_compatibility
13912 */ const metrics = ctx.measureText(line);
13913 const left = x - metrics.actualBoundingBoxLeft;
13914 const right = x + metrics.actualBoundingBoxRight;
13915 const top = y - metrics.actualBoundingBoxAscent;
13916 const bottom = y + metrics.actualBoundingBoxDescent;
13917 const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom;
13918 ctx.strokeStyle = ctx.fillStyle;
13919 ctx.beginPath();
13920 ctx.lineWidth = opts.decorationWidth || 2;
13921 ctx.moveTo(left, yDecoration);
13922 ctx.lineTo(right, yDecoration);
13923 ctx.stroke();
13924 }
13925 }
13926 function drawBackdrop(ctx, opts) {
13927 const oldColor = ctx.fillStyle;
13928 ctx.fillStyle = opts.color;
13929 ctx.fillRect(opts.left, opts.top, opts.width, opts.height);
13930 ctx.fillStyle = oldColor;
13931 }
13932 /**
13933 * Render text onto the canvas
13934 */ function renderText(ctx, text, x, y, font, opts = {}) {
13935 const lines = isArray(text) ? text : [
13936 text
13937 ];
13938 const stroke = opts.strokeWidth > 0 && opts.strokeColor !== '';
13939 let i, line;
13940 ctx.save();
13941 ctx.font = font.string;
13942 setRenderOpts(ctx, opts);
13943 for(i = 0; i < lines.length; ++i){
13944 line = lines[i];
13945 if (opts.backdrop) {
13946 drawBackdrop(ctx, opts.backdrop);
13947 }
13948 if (stroke) {
13949 if (opts.strokeColor) {
13950 ctx.strokeStyle = opts.strokeColor;
13951 }
13952 if (!isNullOrUndef(opts.strokeWidth)) {
13953 ctx.lineWidth = opts.strokeWidth;
13954 }
13955 ctx.strokeText(line, x, y, opts.maxWidth);
13956 }
13957 ctx.fillText(line, x, y, opts.maxWidth);
13958 decorateText(ctx, x, y, line, opts);
13959 y += Number(font.lineHeight);
13960 }
13961 ctx.restore();
13962 }
13963 /**
13964 * Add a path of a rectangle with rounded corners to the current sub-path
13965 * @param ctx - Context
13966 * @param rect - Bounding rect
13967 */ function addRoundedRectPath(ctx, rect) {
13968 const { x , y , w , h , radius } = rect;
13969 // top left arc
13970 ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, 1.5 * PI, PI, true);
13971 // line from top left to bottom left
13972 ctx.lineTo(x, y + h - radius.bottomLeft);
13973 // bottom left arc
13974 ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);
13975 // line from bottom left to bottom right
13976 ctx.lineTo(x + w - radius.bottomRight, y + h);
13977 // bottom right arc
13978 ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);
13979 // line from bottom right to top right
13980 ctx.lineTo(x + w, y + radius.topRight);
13981 // top right arc
13982 ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true);
13983 // line from top right to top left
13984 ctx.lineTo(x + radius.topLeft, y);
13985 }
13986
13987 const LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
13988 const FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;
13989 /**
13990 * @alias Chart.helpers.options
13991 * @namespace
13992 */ /**
13993 * Converts the given line height `value` in pixels for a specific font `size`.
13994 * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
13995 * @param size - The font size (in pixels) used to resolve relative `value`.
13996 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
13997 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
13998 * @since 2.7.0
13999 */ function toLineHeight(value, size) {
14000 const matches = ('' + value).match(LINE_HEIGHT);
14001 if (!matches || matches[1] === 'normal') {
14002 return size * 1.2;
14003 }
14004 value = +matches[2];
14005 switch(matches[3]){
14006 case 'px':
14007 return value;
14008 case '%':
14009 value /= 100;
14010 break;
14011 }
14012 return size * value;
14013 }
14014 const numberOrZero = (v)=>+v || 0;
14015 function _readValueToProps(value, props) {
14016 const ret = {};
14017 const objProps = isObject(props);
14018 const keys = objProps ? Object.keys(props) : props;
14019 const read = isObject(value) ? objProps ? (prop)=>valueOrDefault(value[prop], value[props[prop]]) : (prop)=>value[prop] : ()=>value;
14020 for (const prop of keys){
14021 ret[prop] = numberOrZero(read(prop));
14022 }
14023 return ret;
14024 }
14025 /**
14026 * Converts the given value into a TRBL object.
14027 * @param value - If a number, set the value to all TRBL component,
14028 * else, if an object, use defined properties and sets undefined ones to 0.
14029 * x / y are shorthands for same value for left/right and top/bottom.
14030 * @returns The padding values (top, right, bottom, left)
14031 * @since 3.0.0
14032 */ function toTRBL(value) {
14033 return _readValueToProps(value, {
14034 top: 'y',
14035 right: 'x',
14036 bottom: 'y',
14037 left: 'x'
14038 });
14039 }
14040 /**
14041 * Converts the given value into a TRBL corners object (similar with css border-radius).
14042 * @param value - If a number, set the value to all TRBL corner components,
14043 * else, if an object, use defined properties and sets undefined ones to 0.
14044 * @returns The TRBL corner values (topLeft, topRight, bottomLeft, bottomRight)
14045 * @since 3.0.0
14046 */ function toTRBLCorners(value) {
14047 return _readValueToProps(value, [
14048 'topLeft',
14049 'topRight',
14050 'bottomLeft',
14051 'bottomRight'
14052 ]);
14053 }
14054 /**
14055 * Converts the given value into a padding object with pre-computed width/height.
14056 * @param value - If a number, set the value to all TRBL component,
14057 * else, if an object, use defined properties and sets undefined ones to 0.
14058 * x / y are shorthands for same value for left/right and top/bottom.
14059 * @returns The padding values (top, right, bottom, left, width, height)
14060 * @since 2.7.0
14061 */ function toPadding(value) {
14062 const obj = toTRBL(value);
14063 obj.width = obj.left + obj.right;
14064 obj.height = obj.top + obj.bottom;
14065 return obj;
14066 }
14067 /**
14068 * Parses font options and returns the font object.
14069 * @param options - A object that contains font options to be parsed.
14070 * @param fallback - A object that contains fallback font options.
14071 * @return The font object.
14072 * @private
14073 */ function toFont(options, fallback) {
14074 options = options || {};
14075 fallback = fallback || defaults.font;
14076 let size = valueOrDefault(options.size, fallback.size);
14077 if (typeof size === 'string') {
14078 size = parseInt(size, 10);
14079 }
14080 let style = valueOrDefault(options.style, fallback.style);
14081 if (style && !('' + style).match(FONT_STYLE)) {
14082 console.warn('Invalid font style specified: "' + style + '"');
14083 style = undefined;
14084 }
14085 const font = {
14086 family: valueOrDefault(options.family, fallback.family),
14087 lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),
14088 size,
14089 style,
14090 weight: valueOrDefault(options.weight, fallback.weight),
14091 string: ''
14092 };
14093 font.string = toFontString(font);
14094 return font;
14095 }
14096 /**
14097 * Evaluates the given `inputs` sequentially and returns the first defined value.
14098 * @param inputs - An array of values, falling back to the last value.
14099 * @param context - If defined and the current value is a function, the value
14100 * is called with `context` as first argument and the result becomes the new input.
14101 * @param index - If defined and the current value is an array, the value
14102 * at `index` become the new input.
14103 * @param info - object to return information about resolution in
14104 * @param info.cacheable - Will be set to `false` if option is not cacheable.
14105 * @since 2.7.0
14106 */ function resolve(inputs, context, index, info) {
14107 let cacheable = true;
14108 let i, ilen, value;
14109 for(i = 0, ilen = inputs.length; i < ilen; ++i){
14110 value = inputs[i];
14111 if (value === undefined) {
14112 continue;
14113 }
14114 if (context !== undefined && typeof value === 'function') {
14115 value = value(context);
14116 cacheable = false;
14117 }
14118 if (index !== undefined && isArray(value)) {
14119 value = value[index % value.length];
14120 cacheable = false;
14121 }
14122 if (value !== undefined) {
14123 if (info && !cacheable) {
14124 info.cacheable = false;
14125 }
14126 return value;
14127 }
14128 }
14129 }
14130 /**
14131 * @param minmax
14132 * @param grace
14133 * @param beginAtZero
14134 * @private
14135 */ function _addGrace(minmax, grace, beginAtZero) {
14136 const { min , max } = minmax;
14137 const change = toDimension(grace, (max - min) / 2);
14138 const keepZero = (value, add)=>beginAtZero && value === 0 ? 0 : value + add;
14139 return {
14140 min: keepZero(min, -Math.abs(change)),
14141 max: keepZero(max, change)
14142 };
14143 }
14144 function createContext(parentContext, context) {
14145 return Object.assign(Object.create(parentContext), context);
14146 }
14147
14148 /**
14149 * Creates a Proxy for resolving raw values for options.
14150 * @param scopes - The option scopes to look for values, in resolution order
14151 * @param prefixes - The prefixes for values, in resolution order.
14152 * @param rootScopes - The root option scopes
14153 * @param fallback - Parent scopes fallback
14154 * @param getTarget - callback for getting the target for changed values
14155 * @returns Proxy
14156 * @private
14157 */ function _createResolver(scopes, prefixes = [
14158 ''
14159 ], rootScopes, fallback, getTarget = ()=>scopes[0]) {
14160 const finalRootScopes = rootScopes || scopes;
14161 if (typeof fallback === 'undefined') {
14162 fallback = _resolve('_fallback', scopes);
14163 }
14164 const cache = {
14165 [Symbol.toStringTag]: 'Object',
14166 _cacheable: true,
14167 _scopes: scopes,
14168 _rootScopes: finalRootScopes,
14169 _fallback: fallback,
14170 _getTarget: getTarget,
14171 override: (scope)=>_createResolver([
14172 scope,
14173 ...scopes
14174 ], prefixes, finalRootScopes, fallback)
14175 };
14176 return new Proxy(cache, {
14177 /**
14178 * A trap for the delete operator.
14179 */ deleteProperty (target, prop) {
14180 delete target[prop]; // remove from cache
14181 delete target._keys; // remove cached keys
14182 delete scopes[0][prop]; // remove from top level scope
14183 return true;
14184 },
14185 /**
14186 * A trap for getting property values.
14187 */ get (target, prop) {
14188 return _cached(target, prop, ()=>_resolveWithPrefixes(prop, prefixes, scopes, target));
14189 },
14190 /**
14191 * A trap for Object.getOwnPropertyDescriptor.
14192 * Also used by Object.hasOwnProperty.
14193 */ getOwnPropertyDescriptor (target, prop) {
14194 return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);
14195 },
14196 /**
14197 * A trap for Object.getPrototypeOf.
14198 */ getPrototypeOf () {
14199 return Reflect.getPrototypeOf(scopes[0]);
14200 },
14201 /**
14202 * A trap for the in operator.
14203 */ has (target, prop) {
14204 return getKeysFromAllScopes(target).includes(prop);
14205 },
14206 /**
14207 * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
14208 */ ownKeys (target) {
14209 return getKeysFromAllScopes(target);
14210 },
14211 /**
14212 * A trap for setting property values.
14213 */ set (target, prop, value) {
14214 const storage = target._storage || (target._storage = getTarget());
14215 target[prop] = storage[prop] = value; // set to top level scope + cache
14216 delete target._keys; // remove cached keys
14217 return true;
14218 }
14219 });
14220 }
14221 /**
14222 * Returns an Proxy for resolving option values with context.
14223 * @param proxy - The Proxy returned by `_createResolver`
14224 * @param context - Context object for scriptable/indexable options
14225 * @param subProxy - The proxy provided for scriptable options
14226 * @param descriptorDefaults - Defaults for descriptors
14227 * @private
14228 */ function _attachContext(proxy, context, subProxy, descriptorDefaults) {
14229 const cache = {
14230 _cacheable: false,
14231 _proxy: proxy,
14232 _context: context,
14233 _subProxy: subProxy,
14234 _stack: new Set(),
14235 _descriptors: _descriptors(proxy, descriptorDefaults),
14236 setContext: (ctx)=>_attachContext(proxy, ctx, subProxy, descriptorDefaults),
14237 override: (scope)=>_attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)
14238 };
14239 return new Proxy(cache, {
14240 /**
14241 * A trap for the delete operator.
14242 */ deleteProperty (target, prop) {
14243 delete target[prop]; // remove from cache
14244 delete proxy[prop]; // remove from proxy
14245 return true;
14246 },
14247 /**
14248 * A trap for getting property values.
14249 */ get (target, prop, receiver) {
14250 return _cached(target, prop, ()=>_resolveWithContext(target, prop, receiver));
14251 },
14252 /**
14253 * A trap for Object.getOwnPropertyDescriptor.
14254 * Also used by Object.hasOwnProperty.
14255 */ getOwnPropertyDescriptor (target, prop) {
14256 return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {
14257 enumerable: true,
14258 configurable: true
14259 } : undefined : Reflect.getOwnPropertyDescriptor(proxy, prop);
14260 },
14261 /**
14262 * A trap for Object.getPrototypeOf.
14263 */ getPrototypeOf () {
14264 return Reflect.getPrototypeOf(proxy);
14265 },
14266 /**
14267 * A trap for the in operator.
14268 */ has (target, prop) {
14269 return Reflect.has(proxy, prop);
14270 },
14271 /**
14272 * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
14273 */ ownKeys () {
14274 return Reflect.ownKeys(proxy);
14275 },
14276 /**
14277 * A trap for setting property values.
14278 */ set (target, prop, value) {
14279 proxy[prop] = value; // set to proxy
14280 delete target[prop]; // remove from cache
14281 return true;
14282 }
14283 });
14284 }
14285 /**
14286 * @private
14287 */ function _descriptors(proxy, defaults = {
14288 scriptable: true,
14289 indexable: true
14290 }) {
14291 const { _scriptable =defaults.scriptable , _indexable =defaults.indexable , _allKeys =defaults.allKeys } = proxy;
14292 return {
14293 allKeys: _allKeys,
14294 scriptable: _scriptable,
14295 indexable: _indexable,
14296 isScriptable: isFunction(_scriptable) ? _scriptable : ()=>_scriptable,
14297 isIndexable: isFunction(_indexable) ? _indexable : ()=>_indexable
14298 };
14299 }
14300 const readKey = (prefix, name)=>prefix ? prefix + _capitalize(name) : name;
14301 const needsSubResolver = (prop, value)=>isObject(value) && prop !== 'adapters' && (Object.getPrototypeOf(value) === null || value.constructor === Object);
14302 function _cached(target, prop, resolve) {
14303 if (Object.prototype.hasOwnProperty.call(target, prop) || prop === 'constructor') {
14304 return target[prop];
14305 }
14306 const value = resolve();
14307 // cache the resolved value
14308 target[prop] = value;
14309 return value;
14310 }
14311 function _resolveWithContext(target, prop, receiver) {
14312 const { _proxy , _context , _subProxy , _descriptors: descriptors } = target;
14313 let value = _proxy[prop]; // resolve from proxy
14314 // resolve with context
14315 if (isFunction(value) && descriptors.isScriptable(prop)) {
14316 value = _resolveScriptable(prop, value, target, receiver);
14317 }
14318 if (isArray(value) && value.length) {
14319 value = _resolveArray(prop, value, target, descriptors.isIndexable);
14320 }
14321 if (needsSubResolver(prop, value)) {
14322 // if the resolved value is an object, create a sub resolver for it
14323 value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors);
14324 }
14325 return value;
14326 }
14327 function _resolveScriptable(prop, getValue, target, receiver) {
14328 const { _proxy , _context , _subProxy , _stack } = target;
14329 if (_stack.has(prop)) {
14330 throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop);
14331 }
14332 _stack.add(prop);
14333 let value = getValue(_context, _subProxy || receiver);
14334 _stack.delete(prop);
14335 if (needsSubResolver(prop, value)) {
14336 // When scriptable option returns an object, create a resolver on that.
14337 value = createSubResolver(_proxy._scopes, _proxy, prop, value);
14338 }
14339 return value;
14340 }
14341 function _resolveArray(prop, value, target, isIndexable) {
14342 const { _proxy , _context , _subProxy , _descriptors: descriptors } = target;
14343 if (typeof _context.index !== 'undefined' && isIndexable(prop)) {
14344 return value[_context.index % value.length];
14345 } else if (isObject(value[0])) {
14346 // Array of objects, return array or resolvers
14347 const arr = value;
14348 const scopes = _proxy._scopes.filter((s)=>s !== arr);
14349 value = [];
14350 for (const item of arr){
14351 const resolver = createSubResolver(scopes, _proxy, prop, item);
14352 value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors));
14353 }
14354 }
14355 return value;
14356 }
14357 function resolveFallback(fallback, prop, value) {
14358 return isFunction(fallback) ? fallback(prop, value) : fallback;
14359 }
14360 const getScope = (key, parent)=>key === true ? parent : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined;
14361 function addScopes(set, parentScopes, key, parentFallback, value) {
14362 for (const parent of parentScopes){
14363 const scope = getScope(key, parent);
14364 if (scope) {
14365 set.add(scope);
14366 const fallback = resolveFallback(scope._fallback, key, value);
14367 if (typeof fallback !== 'undefined' && fallback !== key && fallback !== parentFallback) {
14368 // When we reach the descriptor that defines a new _fallback, return that.
14369 // The fallback will resume to that new scope.
14370 return fallback;
14371 }
14372 } else if (scope === false && typeof parentFallback !== 'undefined' && key !== parentFallback) {
14373 // Fallback to `false` results to `false`, when falling back to different key.
14374 // For example `interaction` from `hover` or `plugins.tooltip` and `animation` from `animations`
14375 return null;
14376 }
14377 }
14378 return false;
14379 }
14380 function createSubResolver(parentScopes, resolver, prop, value) {
14381 const rootScopes = resolver._rootScopes;
14382 const fallback = resolveFallback(resolver._fallback, prop, value);
14383 const allScopes = [
14384 ...parentScopes,
14385 ...rootScopes
14386 ];
14387 const set = new Set();
14388 set.add(value);
14389 let key = addScopesFromKey(set, allScopes, prop, fallback || prop, value);
14390 if (key === null) {
14391 return false;
14392 }
14393 if (typeof fallback !== 'undefined' && fallback !== prop) {
14394 key = addScopesFromKey(set, allScopes, fallback, key, value);
14395 if (key === null) {
14396 return false;
14397 }
14398 }
14399 return _createResolver(Array.from(set), [
14400 ''
14401 ], rootScopes, fallback, ()=>subGetTarget(resolver, prop, value));
14402 }
14403 function addScopesFromKey(set, allScopes, key, fallback, item) {
14404 while(key){
14405 key = addScopes(set, allScopes, key, fallback, item);
14406 }
14407 return key;
14408 }
14409 function subGetTarget(resolver, prop, value) {
14410 const parent = resolver._getTarget();
14411 if (!(prop in parent)) {
14412 parent[prop] = {};
14413 }
14414 const target = parent[prop];
14415 if (isArray(target) && isObject(value)) {
14416 // For array of objects, the object is used to store updated values
14417 return value;
14418 }
14419 return target || {};
14420 }
14421 function _resolveWithPrefixes(prop, prefixes, scopes, proxy) {
14422 let value;
14423 for (const prefix of prefixes){
14424 value = _resolve(readKey(prefix, prop), scopes);
14425 if (typeof value !== 'undefined') {
14426 return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value;
14427 }
14428 }
14429 }
14430 function _resolve(key, scopes) {
14431 for (const scope of scopes){
14432 if (!scope) {
14433 continue;
14434 }
14435 const value = scope[key];
14436 if (typeof value !== 'undefined') {
14437 return value;
14438 }
14439 }
14440 }
14441 function getKeysFromAllScopes(target) {
14442 let keys = target._keys;
14443 if (!keys) {
14444 keys = target._keys = resolveKeysFromAllScopes(target._scopes);
14445 }
14446 return keys;
14447 }
14448 function resolveKeysFromAllScopes(scopes) {
14449 const set = new Set();
14450 for (const scope of scopes){
14451 for (const key of Object.keys(scope).filter((k)=>!k.startsWith('_'))){
14452 set.add(key);
14453 }
14454 }
14455 return Array.from(set);
14456 }
14457 function _parseObjectDataRadialScale(meta, data, start, count) {
14458 const { iScale } = meta;
14459 const { key ='r' } = this._parsing;
14460 const parsed = new Array(count);
14461 let i, ilen, index, item;
14462 for(i = 0, ilen = count; i < ilen; ++i){
14463 index = i + start;
14464 item = data[index];
14465 parsed[i] = {
14466 r: iScale.parse(resolveObjectKey(item, key), index)
14467 };
14468 }
14469 return parsed;
14470 }
14471
14472 const EPSILON = Number.EPSILON || 1e-14;
14473 const getPoint = (points, i)=>i < points.length && !points[i].skip && points[i];
14474 const getValueAxis = (indexAxis)=>indexAxis === 'x' ? 'y' : 'x';
14475 function splineCurve(firstPoint, middlePoint, afterPoint, t) {
14476 // Props to Rob Spencer at scaled innovation for his post on splining between points
14477 // http://scaledinnovation.com/analytics/splines/aboutSplines.html
14478 // This function must also respect "skipped" points
14479 const previous = firstPoint.skip ? middlePoint : firstPoint;
14480 const current = middlePoint;
14481 const next = afterPoint.skip ? middlePoint : afterPoint;
14482 const d01 = distanceBetweenPoints(current, previous);
14483 const d12 = distanceBetweenPoints(next, current);
14484 let s01 = d01 / (d01 + d12);
14485 let s12 = d12 / (d01 + d12);
14486 // If all points are the same, s01 & s02 will be inf
14487 s01 = isNaN(s01) ? 0 : s01;
14488 s12 = isNaN(s12) ? 0 : s12;
14489 const fa = t * s01; // scaling factor for triangle Ta
14490 const fb = t * s12;
14491 return {
14492 previous: {
14493 x: current.x - fa * (next.x - previous.x),
14494 y: current.y - fa * (next.y - previous.y)
14495 },
14496 next: {
14497 x: current.x + fb * (next.x - previous.x),
14498 y: current.y + fb * (next.y - previous.y)
14499 }
14500 };
14501 }
14502 /**
14503 * Adjust tangents to ensure monotonic properties
14504 */ function monotoneAdjust(points, deltaK, mK) {
14505 const pointsLen = points.length;
14506 let alphaK, betaK, tauK, squaredMagnitude, pointCurrent;
14507 let pointAfter = getPoint(points, 0);
14508 for(let i = 0; i < pointsLen - 1; ++i){
14509 pointCurrent = pointAfter;
14510 pointAfter = getPoint(points, i + 1);
14511 if (!pointCurrent || !pointAfter) {
14512 continue;
14513 }
14514 if (almostEquals(deltaK[i], 0, EPSILON)) {
14515 mK[i] = mK[i + 1] = 0;
14516 continue;
14517 }
14518 alphaK = mK[i] / deltaK[i];
14519 betaK = mK[i + 1] / deltaK[i];
14520 squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
14521 if (squaredMagnitude <= 9) {
14522 continue;
14523 }
14524 tauK = 3 / Math.sqrt(squaredMagnitude);
14525 mK[i] = alphaK * tauK * deltaK[i];
14526 mK[i + 1] = betaK * tauK * deltaK[i];
14527 }
14528 }
14529 function monotoneCompute(points, mK, indexAxis = 'x') {
14530 const valueAxis = getValueAxis(indexAxis);
14531 const pointsLen = points.length;
14532 let delta, pointBefore, pointCurrent;
14533 let pointAfter = getPoint(points, 0);
14534 for(let i = 0; i < pointsLen; ++i){
14535 pointBefore = pointCurrent;
14536 pointCurrent = pointAfter;
14537 pointAfter = getPoint(points, i + 1);
14538 if (!pointCurrent) {
14539 continue;
14540 }
14541 const iPixel = pointCurrent[indexAxis];
14542 const vPixel = pointCurrent[valueAxis];
14543 if (pointBefore) {
14544 delta = (iPixel - pointBefore[indexAxis]) / 3;
14545 pointCurrent[`cp1${indexAxis}`] = iPixel - delta;
14546 pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i];
14547 }
14548 if (pointAfter) {
14549 delta = (pointAfter[indexAxis] - iPixel) / 3;
14550 pointCurrent[`cp2${indexAxis}`] = iPixel + delta;
14551 pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i];
14552 }
14553 }
14554 }
14555 /**
14556 * This function calculates Bézier control points in a similar way than |splineCurve|,
14557 * but preserves monotonicity of the provided data and ensures no local extremums are added
14558 * between the dataset discrete points due to the interpolation.
14559 * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
14560 */ function splineCurveMonotone(points, indexAxis = 'x') {
14561 const valueAxis = getValueAxis(indexAxis);
14562 const pointsLen = points.length;
14563 const deltaK = Array(pointsLen).fill(0);
14564 const mK = Array(pointsLen);
14565 // Calculate slopes (deltaK) and initialize tangents (mK)
14566 let i, pointBefore, pointCurrent;
14567 let pointAfter = getPoint(points, 0);
14568 for(i = 0; i < pointsLen; ++i){
14569 pointBefore = pointCurrent;
14570 pointCurrent = pointAfter;
14571 pointAfter = getPoint(points, i + 1);
14572 if (!pointCurrent) {
14573 continue;
14574 }
14575 if (pointAfter) {
14576 const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis];
14577 // In the case of two points that appear at the same x pixel, slopeDeltaX is 0
14578 deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0;
14579 }
14580 mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : sign(deltaK[i - 1]) !== sign(deltaK[i]) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2;
14581 }
14582 monotoneAdjust(points, deltaK, mK);
14583 monotoneCompute(points, mK, indexAxis);
14584 }
14585 function capControlPoint(pt, min, max) {
14586 return Math.max(Math.min(pt, max), min);
14587 }
14588 function capBezierPoints(points, area) {
14589 let i, ilen, point, inArea, inAreaPrev;
14590 let inAreaNext = _isPointInArea(points[0], area);
14591 for(i = 0, ilen = points.length; i < ilen; ++i){
14592 inAreaPrev = inArea;
14593 inArea = inAreaNext;
14594 inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area);
14595 if (!inArea) {
14596 continue;
14597 }
14598 point = points[i];
14599 if (inAreaPrev) {
14600 point.cp1x = capControlPoint(point.cp1x, area.left, area.right);
14601 point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom);
14602 }
14603 if (inAreaNext) {
14604 point.cp2x = capControlPoint(point.cp2x, area.left, area.right);
14605 point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom);
14606 }
14607 }
14608 }
14609 /**
14610 * @private
14611 */ function _updateBezierControlPoints(points, options, area, loop, indexAxis) {
14612 let i, ilen, point, controlPoints;
14613 // Only consider points that are drawn in case the spanGaps option is used
14614 if (options.spanGaps) {
14615 points = points.filter((pt)=>!pt.skip);
14616 }
14617 if (options.cubicInterpolationMode === 'monotone') {
14618 splineCurveMonotone(points, indexAxis);
14619 } else {
14620 let prev = loop ? points[points.length - 1] : points[0];
14621 for(i = 0, ilen = points.length; i < ilen; ++i){
14622 point = points[i];
14623 controlPoints = splineCurve(prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension);
14624 point.cp1x = controlPoints.previous.x;
14625 point.cp1y = controlPoints.previous.y;
14626 point.cp2x = controlPoints.next.x;
14627 point.cp2y = controlPoints.next.y;
14628 prev = point;
14629 }
14630 }
14631 if (options.capBezierPoints) {
14632 capBezierPoints(points, area);
14633 }
14634 }
14635
14636 /**
14637 * @private
14638 */ function _isDomSupported() {
14639 return typeof window !== 'undefined' && typeof document !== 'undefined';
14640 }
14641 /**
14642 * @private
14643 */ function _getParentNode(domNode) {
14644 let parent = domNode.parentNode;
14645 if (parent && parent.toString() === '[object ShadowRoot]') {
14646 parent = parent.host;
14647 }
14648 return parent;
14649 }
14650 /**
14651 * convert max-width/max-height values that may be percentages into a number
14652 * @private
14653 */ function parseMaxStyle(styleValue, node, parentProperty) {
14654 let valueInPixels;
14655 if (typeof styleValue === 'string') {
14656 valueInPixels = parseInt(styleValue, 10);
14657 if (styleValue.indexOf('%') !== -1) {
14658 // percentage * size in dimension
14659 valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
14660 }
14661 } else {
14662 valueInPixels = styleValue;
14663 }
14664 return valueInPixels;
14665 }
14666 const getComputedStyle = (element)=>element.ownerDocument.defaultView.getComputedStyle(element, null);
14667 function getStyle(el, property) {
14668 return getComputedStyle(el).getPropertyValue(property);
14669 }
14670 const positions = [
14671 'top',
14672 'right',
14673 'bottom',
14674 'left'
14675 ];
14676 function getPositionedStyle(styles, style, suffix) {
14677 const result = {};
14678 suffix = suffix ? '-' + suffix : '';
14679 for(let i = 0; i < 4; i++){
14680 const pos = positions[i];
14681 result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;
14682 }
14683 result.width = result.left + result.right;
14684 result.height = result.top + result.bottom;
14685 return result;
14686 }
14687 const useOffsetPos = (x, y, target)=>(x > 0 || y > 0) && (!target || !target.shadowRoot);
14688 /**
14689 * @param e
14690 * @param canvas
14691 * @returns Canvas position
14692 */ function getCanvasPosition(e, canvas) {
14693 const touches = e.touches;
14694 const source = touches && touches.length ? touches[0] : e;
14695 const { offsetX , offsetY } = source;
14696 let box = false;
14697 let x, y;
14698 if (useOffsetPos(offsetX, offsetY, e.target)) {
14699 x = offsetX;
14700 y = offsetY;
14701 } else {
14702 const rect = canvas.getBoundingClientRect();
14703 x = source.clientX - rect.left;
14704 y = source.clientY - rect.top;
14705 box = true;
14706 }
14707 return {
14708 x,
14709 y,
14710 box
14711 };
14712 }
14713 /**
14714 * Gets an event's x, y coordinates, relative to the chart area
14715 * @param event
14716 * @param chart
14717 * @returns x and y coordinates of the event
14718 */ function getRelativePosition(event, chart) {
14719 if ('native' in event) {
14720 return event;
14721 }
14722 const { canvas , currentDevicePixelRatio } = chart;
14723 const style = getComputedStyle(canvas);
14724 const borderBox = style.boxSizing === 'border-box';
14725 const paddings = getPositionedStyle(style, 'padding');
14726 const borders = getPositionedStyle(style, 'border', 'width');
14727 const { x , y , box } = getCanvasPosition(event, canvas);
14728 const xOffset = paddings.left + (box && borders.left);
14729 const yOffset = paddings.top + (box && borders.top);
14730 let { width , height } = chart;
14731 if (borderBox) {
14732 width -= paddings.width + borders.width;
14733 height -= paddings.height + borders.height;
14734 }
14735 return {
14736 x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio),
14737 y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio)
14738 };
14739 }
14740 function getContainerSize(canvas, width, height) {
14741 let maxWidth, maxHeight;
14742 if (width === undefined || height === undefined) {
14743 const container = canvas && _getParentNode(canvas);
14744 if (!container) {
14745 width = canvas.clientWidth;
14746 height = canvas.clientHeight;
14747 } else {
14748 const rect = container.getBoundingClientRect(); // this is the border box of the container
14749 const containerStyle = getComputedStyle(container);
14750 const containerBorder = getPositionedStyle(containerStyle, 'border', 'width');
14751 const containerPadding = getPositionedStyle(containerStyle, 'padding');
14752 width = rect.width - containerPadding.width - containerBorder.width;
14753 height = rect.height - containerPadding.height - containerBorder.height;
14754 maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth');
14755 maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight');
14756 }
14757 }
14758 return {
14759 width,
14760 height,
14761 maxWidth: maxWidth || INFINITY,
14762 maxHeight: maxHeight || INFINITY
14763 };
14764 }
14765 const round1 = (v)=>Math.round(v * 10) / 10;
14766 // eslint-disable-next-line complexity
14767 function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {
14768 const style = getComputedStyle(canvas);
14769 const margins = getPositionedStyle(style, 'margin');
14770 const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY;
14771 const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY;
14772 const containerSize = getContainerSize(canvas, bbWidth, bbHeight);
14773 let { width , height } = containerSize;
14774 if (style.boxSizing === 'content-box') {
14775 const borders = getPositionedStyle(style, 'border', 'width');
14776 const paddings = getPositionedStyle(style, 'padding');
14777 width -= paddings.width + borders.width;
14778 height -= paddings.height + borders.height;
14779 }
14780 width = Math.max(0, width - margins.width);
14781 height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height);
14782 width = round1(Math.min(width, maxWidth, containerSize.maxWidth));
14783 height = round1(Math.min(height, maxHeight, containerSize.maxHeight));
14784 if (width && !height) {
14785 // https://github.com/chartjs/Chart.js/issues/4659
14786 // If the canvas has width, but no height, default to aspectRatio of 2 (canvas default)
14787 height = round1(width / 2);
14788 }
14789 const maintainHeight = bbWidth !== undefined || bbHeight !== undefined;
14790 if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) {
14791 height = containerSize.height;
14792 width = round1(Math.floor(height * aspectRatio));
14793 }
14794 return {
14795 width,
14796 height
14797 };
14798 }
14799 /**
14800 * @param chart
14801 * @param forceRatio
14802 * @param forceStyle
14803 * @returns True if the canvas context size or transformation has changed.
14804 */ function retinaScale(chart, forceRatio, forceStyle) {
14805 const pixelRatio = forceRatio || 1;
14806 const deviceHeight = round1(chart.height * pixelRatio);
14807 const deviceWidth = round1(chart.width * pixelRatio);
14808 chart.height = round1(chart.height);
14809 chart.width = round1(chart.width);
14810 const canvas = chart.canvas;
14811 // If no style has been set on the canvas, the render size is used as display size,
14812 // making the chart visually bigger, so let's enforce it to the "correct" values.
14813 // See https://github.com/chartjs/Chart.js/issues/3575
14814 if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) {
14815 canvas.style.height = `${chart.height}px`;
14816 canvas.style.width = `${chart.width}px`;
14817 }
14818 if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) {
14819 chart.currentDevicePixelRatio = pixelRatio;
14820 canvas.height = deviceHeight;
14821 canvas.width = deviceWidth;
14822 chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
14823 return true;
14824 }
14825 return false;
14826 }
14827 /**
14828 * Detects support for options object argument in addEventListener.
14829 * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
14830 * @private
14831 */ const supportsEventListenerOptions = function() {
14832 let passiveSupported = false;
14833 try {
14834 const options = {
14835 get passive () {
14836 passiveSupported = true;
14837 return false;
14838 }
14839 };
14840 if (_isDomSupported()) {
14841 window.addEventListener('test', null, options);
14842 window.removeEventListener('test', null, options);
14843 }
14844 } catch (e) {
14845 // continue regardless of error
14846 }
14847 return passiveSupported;
14848 }();
14849 /**
14850 * The "used" size is the final value of a dimension property after all calculations have
14851 * been performed. This method uses the computed style of `element` but returns undefined
14852 * if the computed style is not expressed in pixels. That can happen in some cases where
14853 * `element` has a size relative to its parent and this last one is not yet displayed,
14854 * for example because of `display: none` on a parent node.
14855 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
14856 * @returns Size in pixels or undefined if unknown.
14857 */ function readUsedSize(element, property) {
14858 const value = getStyle(element, property);
14859 const matches = value && value.match(/^(\d+)(\.\d+)?px$/);
14860 return matches ? +matches[1] : undefined;
14861 }
14862
14863 /**
14864 * @private
14865 */ function _pointInLine(p1, p2, t, mode) {
14866 return {
14867 x: p1.x + t * (p2.x - p1.x),
14868 y: p1.y + t * (p2.y - p1.y)
14869 };
14870 }
14871 /**
14872 * @private
14873 */ function _steppedInterpolation(p1, p2, t, mode) {
14874 return {
14875 x: p1.x + t * (p2.x - p1.x),
14876 y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y : mode === 'after' ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y
14877 };
14878 }
14879 /**
14880 * @private
14881 */ function _bezierInterpolation(p1, p2, t, mode) {
14882 const cp1 = {
14883 x: p1.cp2x,
14884 y: p1.cp2y
14885 };
14886 const cp2 = {
14887 x: p2.cp1x,
14888 y: p2.cp1y
14889 };
14890 const a = _pointInLine(p1, cp1, t);
14891 const b = _pointInLine(cp1, cp2, t);
14892 const c = _pointInLine(cp2, p2, t);
14893 const d = _pointInLine(a, b, t);
14894 const e = _pointInLine(b, c, t);
14895 return _pointInLine(d, e, t);
14896 }
14897
14898 const getRightToLeftAdapter = function(rectX, width) {
14899 return {
14900 x (x) {
14901 return rectX + rectX + width - x;
14902 },
14903 setWidth (w) {
14904 width = w;
14905 },
14906 textAlign (align) {
14907 if (align === 'center') {
14908 return align;
14909 }
14910 return align === 'right' ? 'left' : 'right';
14911 },
14912 xPlus (x, value) {
14913 return x - value;
14914 },
14915 leftForLtr (x, itemWidth) {
14916 return x - itemWidth;
14917 }
14918 };
14919 };
14920 const getLeftToRightAdapter = function() {
14921 return {
14922 x (x) {
14923 return x;
14924 },
14925 setWidth (w) {},
14926 textAlign (align) {
14927 return align;
14928 },
14929 xPlus (x, value) {
14930 return x + value;
14931 },
14932 leftForLtr (x, _itemWidth) {
14933 return x;
14934 }
14935 };
14936 };
14937 function getRtlAdapter(rtl, rectX, width) {
14938 return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();
14939 }
14940 function overrideTextDirection(ctx, direction) {
14941 let style, original;
14942 if (direction === 'ltr' || direction === 'rtl') {
14943 style = ctx.canvas.style;
14944 original = [
14945 style.getPropertyValue('direction'),
14946 style.getPropertyPriority('direction')
14947 ];
14948 style.setProperty('direction', direction, 'important');
14949 ctx.prevTextDirection = original;
14950 }
14951 }
14952 function restoreTextDirection(ctx, original) {
14953 if (original !== undefined) {
14954 delete ctx.prevTextDirection;
14955 ctx.canvas.style.setProperty('direction', original[0], original[1]);
14956 }
14957 }
14958
14959 function propertyFn(property) {
14960 if (property === 'angle') {
14961 return {
14962 between: _angleBetween,
14963 compare: _angleDiff,
14964 normalize: _normalizeAngle
14965 };
14966 }
14967 return {
14968 between: _isBetween,
14969 compare: (a, b)=>a - b,
14970 normalize: (x)=>x
14971 };
14972 }
14973 function normalizeSegment({ start , end , count , loop , style }) {
14974 return {
14975 start: start % count,
14976 end: end % count,
14977 loop: loop && (end - start + 1) % count === 0,
14978 style
14979 };
14980 }
14981 function getSegment(segment, points, bounds) {
14982 const { property , start: startBound , end: endBound } = bounds;
14983 const { between , normalize } = propertyFn(property);
14984 const count = points.length;
14985 let { start , end , loop } = segment;
14986 let i, ilen;
14987 if (loop) {
14988 start += count;
14989 end += count;
14990 for(i = 0, ilen = count; i < ilen; ++i){
14991 if (!between(normalize(points[start % count][property]), startBound, endBound)) {
14992 break;
14993 }
14994 start--;
14995 end--;
14996 }
14997 start %= count;
14998 end %= count;
14999 }
15000 if (end < start) {
15001 end += count;
15002 }
15003 return {
15004 start,
15005 end,
15006 loop,
15007 style: segment.style
15008 };
15009 }
15010 function _boundSegment(segment, points, bounds) {
15011 if (!bounds) {
15012 return [
15013 segment
15014 ];
15015 }
15016 const { property , start: startBound , end: endBound } = bounds;
15017 const count = points.length;
15018 const { compare , between , normalize } = propertyFn(property);
15019 const { start , end , loop , style } = getSegment(segment, points, bounds);
15020 const result = [];
15021 let inside = false;
15022 let subStart = null;
15023 let value, point, prevValue;
15024 const startIsBefore = ()=>between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0;
15025 const endIsBefore = ()=>compare(endBound, value) === 0 || between(endBound, prevValue, value);
15026 const shouldStart = ()=>inside || startIsBefore();
15027 const shouldStop = ()=>!inside || endIsBefore();
15028 for(let i = start, prev = start; i <= end; ++i){
15029 point = points[i % count];
15030 if (point.skip) {
15031 continue;
15032 }
15033 value = normalize(point[property]);
15034 if (value === prevValue) {
15035 continue;
15036 }
15037 inside = between(value, startBound, endBound);
15038 if (subStart === null && shouldStart()) {
15039 subStart = compare(value, startBound) === 0 ? i : prev;
15040 }
15041 if (subStart !== null && shouldStop()) {
15042 result.push(normalizeSegment({
15043 start: subStart,
15044 end: i,
15045 loop,
15046 count,
15047 style
15048 }));
15049 subStart = null;
15050 }
15051 prev = i;
15052 prevValue = value;
15053 }
15054 if (subStart !== null) {
15055 result.push(normalizeSegment({
15056 start: subStart,
15057 end,
15058 loop,
15059 count,
15060 style
15061 }));
15062 }
15063 return result;
15064 }
15065 function _boundSegments(line, bounds) {
15066 const result = [];
15067 const segments = line.segments;
15068 for(let i = 0; i < segments.length; i++){
15069 const sub = _boundSegment(segments[i], line.points, bounds);
15070 if (sub.length) {
15071 result.push(...sub);
15072 }
15073 }
15074 return result;
15075 }
15076 function findStartAndEnd(points, count, loop, spanGaps) {
15077 let start = 0;
15078 let end = count - 1;
15079 if (loop && !spanGaps) {
15080 while(start < count && !points[start].skip){
15081 start++;
15082 }
15083 }
15084 while(start < count && points[start].skip){
15085 start++;
15086 }
15087 start %= count;
15088 if (loop) {
15089 end += start;
15090 }
15091 while(end > start && points[end % count].skip){
15092 end--;
15093 }
15094 end %= count;
15095 return {
15096 start,
15097 end
15098 };
15099 }
15100 function solidSegments(points, start, max, loop) {
15101 const count = points.length;
15102 const result = [];
15103 let last = start;
15104 let prev = points[start];
15105 let end;
15106 for(end = start + 1; end <= max; ++end){
15107 const cur = points[end % count];
15108 if (cur.skip || cur.stop) {
15109 if (!prev.skip) {
15110 loop = false;
15111 result.push({
15112 start: start % count,
15113 end: (end - 1) % count,
15114 loop
15115 });
15116 start = last = cur.stop ? end : null;
15117 }
15118 } else {
15119 last = end;
15120 if (prev.skip) {
15121 start = end;
15122 }
15123 }
15124 prev = cur;
15125 }
15126 if (last !== null) {
15127 result.push({
15128 start: start % count,
15129 end: last % count,
15130 loop
15131 });
15132 }
15133 return result;
15134 }
15135 function _computeSegments(line, segmentOptions) {
15136 const points = line.points;
15137 const spanGaps = line.options.spanGaps;
15138 const count = points.length;
15139 if (!count) {
15140 return [];
15141 }
15142 const loop = !!line._loop;
15143 const { start , end } = findStartAndEnd(points, count, loop, spanGaps);
15144 if (spanGaps === true) {
15145 return splitByStyles(line, [
15146 {
15147 start,
15148 end,
15149 loop
15150 }
15151 ], points, segmentOptions);
15152 }
15153 const max = end < start ? end + count : end;
15154 const completeLoop = !!line._fullLoop && start === 0 && end === count - 1;
15155 return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions);
15156 }
15157 function splitByStyles(line, segments, points, segmentOptions) {
15158 if (!segmentOptions || !segmentOptions.setContext || !points) {
15159 return segments;
15160 }
15161 return doSplitByStyles(line, segments, points, segmentOptions);
15162 }
15163 function doSplitByStyles(line, segments, points, segmentOptions) {
15164 const chartContext = line._chart.getContext();
15165 const baseStyle = readStyle(line.options);
15166 const { _datasetIndex: datasetIndex , options: { spanGaps } } = line;
15167 const count = points.length;
15168 const result = [];
15169 let prevStyle = baseStyle;
15170 let start = segments[0].start;
15171 let i = start;
15172 function addStyle(s, e, l, st) {
15173 const dir = spanGaps ? -1 : 1;
15174 if (s === e) {
15175 return;
15176 }
15177 s += count;
15178 while(points[s % count].skip){
15179 s -= dir;
15180 }
15181 while(points[e % count].skip){
15182 e += dir;
15183 }
15184 if (s % count !== e % count) {
15185 result.push({
15186 start: s % count,
15187 end: e % count,
15188 loop: l,
15189 style: st
15190 });
15191 prevStyle = st;
15192 start = e % count;
15193 }
15194 }
15195 for (const segment of segments){
15196 start = spanGaps ? start : segment.start;
15197 let prev = points[start % count];
15198 let style;
15199 for(i = start + 1; i <= segment.end; i++){
15200 const pt = points[i % count];
15201 style = readStyle(segmentOptions.setContext(createContext(chartContext, {
15202 type: 'segment',
15203 p0: prev,
15204 p1: pt,
15205 p0DataIndex: (i - 1) % count,
15206 p1DataIndex: i % count,
15207 datasetIndex
15208 })));
15209 if (styleChanged(style, prevStyle)) {
15210 addStyle(start, i - 1, segment.loop, prevStyle);
15211 }
15212 prev = pt;
15213 prevStyle = style;
15214 }
15215 if (start < i - 1) {
15216 addStyle(start, i - 1, segment.loop, prevStyle);
15217 }
15218 }
15219 return result;
15220 }
15221 function readStyle(options) {
15222 return {
15223 backgroundColor: options.backgroundColor,
15224 borderCapStyle: options.borderCapStyle,
15225 borderDash: options.borderDash,
15226 borderDashOffset: options.borderDashOffset,
15227 borderJoinStyle: options.borderJoinStyle,
15228 borderWidth: options.borderWidth,
15229 borderColor: options.borderColor
15230 };
15231 }
15232 function styleChanged(style, prevStyle) {
15233 if (!prevStyle) {
15234 return false;
15235 }
15236 const cache = [];
15237 const replacer = function(key, value) {
15238 if (!isPatternOrGradient(value)) {
15239 return value;
15240 }
15241 if (!cache.includes(value)) {
15242 cache.push(value);
15243 }
15244 return cache.indexOf(value);
15245 };
15246 return JSON.stringify(style, replacer) !== JSON.stringify(prevStyle, replacer);
15247 }
15248
15249 function getSizeForArea(scale, chartArea, field) {
15250 return scale.options.clip ? scale[field] : chartArea[field];
15251 }
15252 function getDatasetArea(meta, chartArea) {
15253 const { xScale , yScale } = meta;
15254 if (xScale && yScale) {
15255 return {
15256 left: getSizeForArea(xScale, chartArea, 'left'),
15257 right: getSizeForArea(xScale, chartArea, 'right'),
15258 top: getSizeForArea(yScale, chartArea, 'top'),
15259 bottom: getSizeForArea(yScale, chartArea, 'bottom')
15260 };
15261 }
15262 return chartArea;
15263 }
15264 function getDatasetClipArea(chart, meta) {
15265 const clip = meta._clip;
15266 if (clip.disabled) {
15267 return false;
15268 }
15269 const area = getDatasetArea(meta, chart.chartArea);
15270 return {
15271 left: clip.left === false ? 0 : area.left - (clip.left === true ? 0 : clip.left),
15272 right: clip.right === false ? chart.width : area.right + (clip.right === true ? 0 : clip.right),
15273 top: clip.top === false ? 0 : area.top - (clip.top === true ? 0 : clip.top),
15274 bottom: clip.bottom === false ? chart.height : area.bottom + (clip.bottom === true ? 0 : clip.bottom)
15275 };
15276 }
15277
15278
15279 //# sourceMappingURL=helpers.dataset.js.map
15280
15281
15282 /***/ }
15283
15284 /******/ });
15285 /************************************************************************/
15286 /******/ // The module cache
15287 /******/ var __webpack_module_cache__ = {};
15288 /******/
15289 /******/ // The require function
15290 /******/ function __webpack_require__(moduleId) {
15291 /******/ // Check if module is in cache
15292 /******/ var cachedModule = __webpack_module_cache__[moduleId];
15293 /******/ if (cachedModule !== undefined) {
15294 /******/ return cachedModule.exports;
15295 /******/ }
15296 /******/ // Create a new module (and put it into the cache)
15297 /******/ var module = __webpack_module_cache__[moduleId] = {
15298 /******/ // no module.id needed
15299 /******/ // no module.loaded needed
15300 /******/ exports: {}
15301 /******/ };
15302 /******/
15303 /******/ // Execute the module function
15304 /******/ if (!(moduleId in __webpack_modules__)) {
15305 /******/ delete __webpack_module_cache__[moduleId];
15306 /******/ var e = new Error("Cannot find module '" + moduleId + "'");
15307 /******/ e.code = 'MODULE_NOT_FOUND';
15308 /******/ throw e;
15309 /******/ }
15310 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
15311 /******/
15312 /******/ // Return the exports of the module
15313 /******/ return module.exports;
15314 /******/ }
15315 /******/
15316 /************************************************************************/
15317 /******/ /* webpack/runtime/define property getters */
15318 /******/ (() => {
15319 /******/ // define getter functions for harmony exports
15320 /******/ __webpack_require__.d = (exports, definition) => {
15321 /******/ for(var key in definition) {
15322 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
15323 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
15324 /******/ }
15325 /******/ }
15326 /******/ };
15327 /******/ })();
15328 /******/
15329 /******/ /* webpack/runtime/hasOwnProperty shorthand */
15330 /******/ (() => {
15331 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
15332 /******/ })();
15333 /******/
15334 /******/ /* webpack/runtime/make namespace object */
15335 /******/ (() => {
15336 /******/ // define __esModule on exports
15337 /******/ __webpack_require__.r = (exports) => {
15338 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
15339 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
15340 /******/ }
15341 /******/ Object.defineProperty(exports, '__esModule', { value: true });
15342 /******/ };
15343 /******/ })();
15344 /******/
15345 /************************************************************************/
15346 var __webpack_exports__ = {};
15347 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
15348 (() => {
15349 /*!************************************************!*\
15350 !*** ./assets/src/js/admin/admin-statistic.js ***!
15351 \************************************************/
15352 __webpack_require__.r(__webpack_exports__);
15353 /* harmony import */ var chart_js_auto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! chart.js/auto */ "./node_modules/chart.js/auto/auto.js");
15354 /**
15355 * Statistics chart.
15356 *
15357 * @since 4.2.5.5
15358 * @version 1.0.0
15359 */
15360
15361
15362 document.addEventListener('DOMContentLoaded', function () {
15363 const lpStatisticsLoad = () => {
15364 const elementLoad = document.querySelector('input.statistics-type');
15365 if (!elementLoad) {
15366 return;
15367 }
15368 if (elementLoad.value === 'orders-statistics') {
15369 orderLoadData();
15370 } else if (elementLoad.value === 'overview-statistics') {
15371 overviewLoadData();
15372 } else if (elementLoad.value === 'courses-statistics') {
15373 courseLoadData();
15374 } else if (elementLoad.value === 'users-statistics') {
15375 userLoadData();
15376 }
15377 };
15378 const overviewLoadData = (filterType = 'today', date = '') => {
15379 wp.apiFetch({
15380 path: wp.url.addQueryArgs('lp/v1/statistics/overviews-statistics', {
15381 filtertype: filterType,
15382 date
15383 }),
15384 method: 'GET'
15385 }).then(res => {
15386 const {
15387 data,
15388 status,
15389 message
15390 } = res;
15391 if (status === 'error') {
15392 throw new Error(message || 'Error');
15393 }
15394 const configChartOverview = {
15395 options: {
15396 scales: {
15397 y: {
15398 min: 0,
15399 ticks: {
15400 callback(value, index, ticks) {
15401 return '$' + value;
15402 }
15403 }
15404 }
15405 }
15406 }
15407 };
15408 initStatisticChart('net-sales-chart-content', data.chart_data, configChartOverview);
15409 document.querySelector('.total-sales').textContent = data.total_sales;
15410 document.querySelector('.total-orders').textContent = data.total_orders;
15411 document.querySelector('.total-courses').textContent = data.total_courses;
15412 document.querySelector('.total-instructors').textContent = data.total_instructors;
15413 document.querySelector('.total-students').textContent = data.total_students;
15414 if (data.top_courses.length > 0) {
15415 const topCourses = data.top_courses,
15416 topCoursesWrap = document.querySelector('.top-course-sold');
15417 for (let i = 0; i < topCourses.length; i++) {
15418 topCoursesWrap.insertAdjacentHTML('beforeend', `<li>${topCourses[i].course_name} - ${topCourses[i].course_count}</li>`);
15419 }
15420 }
15421 if (data.top_categories.length > 0) {
15422 const topCategories = data.top_categories,
15423 topCategoriesWrap = document.querySelector('.top-category-sold');
15424 for (let i = 0; i < topCategories.length; i++) {
15425 topCategoriesWrap.insertAdjacentHTML('beforeend', `<li>${topCategories[i].term_name} - ${topCategories[i].term_count}</li>`);
15426 }
15427 }
15428 }).catch(err => {
15429 console.log(err);
15430 }).finally(() => {});
15431 };
15432 const orderLoadData = (filterType = 'today', date = '') => {
15433 wp.apiFetch({
15434 path: wp.url.addQueryArgs('lp/v1/statistics/order-statistics', {
15435 filtertype: filterType,
15436 date
15437 }),
15438 method: 'GET'
15439 }).then(res => {
15440 const {
15441 data,
15442 status,
15443 message
15444 } = res;
15445 if (status === 'error') {
15446 throw new Error(message || 'Error');
15447 }
15448 initStatisticChart('orders-chart-content', data.chart_data);
15449 // chartEle.style.display = 'block';
15450 if (data.statistics.length > 0) {
15451 let totalOrder = 0;
15452 for (let i = data.statistics.length - 1; i >= 0; i--) {
15453 const v = data.statistics[i];
15454 if (v.order_status == 'completed') {
15455 document.querySelector('.completed-order-count').textContent = v.count_order;
15456 totalOrder += parseInt(v.count_order);
15457 } else if (v.order_status == 'pending') {
15458 document.querySelector('.pending-order-count').textContent = v.count_order;
15459 totalOrder += parseInt(v.count_order);
15460 } else if (v.order_status == 'processing') {
15461 document.querySelector('.processing-order-count').textContent = v.count_order;
15462 totalOrder += parseInt(v.count_order);
15463 } else if (v.order_status == 'cancelled') {
15464 document.querySelector('.cancelled-order-count').textContent = v.count_order;
15465 totalOrder += parseInt(v.count_order);
15466 } else if (v.order_status == 'failed') {
15467 document.querySelector('.failed-order-count').textContent = v.count_order;
15468 totalOrder += parseInt(v.count_order);
15469 }
15470 }
15471 document.querySelector('.total-order-count').textContent = totalOrder;
15472 } else {
15473 document.querySelectorAll('.statistics-item-count').forEach(ele => {
15474 ele.textContent = 0;
15475 });
15476 }
15477 }).catch(err => {
15478 console.log(err);
15479 }).finally(() => {});
15480 };
15481 const courseLoadData = (filterType = 'today', date = '') => {
15482 wp.apiFetch({
15483 path: wp.url.addQueryArgs('lp/v1/statistics/course-statistics', {
15484 filtertype: filterType,
15485 date
15486 }),
15487 method: 'GET'
15488 }).then(res => {
15489 const {
15490 data,
15491 status,
15492 message
15493 } = res;
15494 if (status === 'error') {
15495 throw new Error(message || 'Error');
15496 }
15497 initStatisticChart('course-chart-content', data.chart_data);
15498 if (data.courses.length > 0) {
15499 let totalCourse = 0;
15500 for (let i = 0; i < data.courses.length; i++) {
15501 const v = data.courses[i];
15502 if (v.course_status == 'publish') {
15503 document.querySelector('.statistics-courses.published').textContent = v.course_count;
15504 totalCourse += parseInt(v.course_count);
15505 } else if (v.course_status == 'pending') {
15506 document.querySelector('.statistics-courses.pending').textContent = v.course_count;
15507 totalCourse += parseInt(v.course_count);
15508 } else if (v.course_status == 'future') {
15509 document.querySelector('.statistics-courses.future').textContent = v.course_count;
15510 totalCourse += parseInt(v.course_count);
15511 }
15512 }
15513 document.querySelector('.statistics-courses.total').textContent = totalCourse;
15514 } else {
15515 document.querySelectorAll('.statistics-courses').forEach(ele => {
15516 ele.textContent = 0;
15517 });
15518 }
15519 if (data.items.length > 0) {
15520 for (let i = 0; i < data.items.length; i++) {
15521 const v = data.items[i];
15522 if (v.item_type == 'lp_lesson') {
15523 document.querySelector('.statistics-items.lessons').textContent = v.item_count;
15524 } else if (v.item_type == 'lp_quiz') {
15525 document.querySelector('.statistics-items.quizes').textContent = v.item_count;
15526 } else if (v.item_type == 'lp_assignment') {
15527 document.querySelector('.statistics-items.assignment').textContent = v.item_count;
15528 }
15529 }
15530 } else {
15531 document.querySelectorAll('.statistics-items').forEach(ele => {
15532 ele.textContent = 0;
15533 });
15534 }
15535 }).catch(err => {
15536 console.log(err);
15537 }).finally(() => {});
15538 };
15539 const userLoadData = (filterType = 'today', date = '') => {
15540 wp.apiFetch({
15541 path: wp.url.addQueryArgs('lp/v1/statistics/user-statistics', {
15542 filtertype: filterType,
15543 date
15544 }),
15545 method: 'GET'
15546 }).then(res => {
15547 const {
15548 data,
15549 status,
15550 message
15551 } = res;
15552 if (status === 'error') {
15553 throw new Error(message || 'Error');
15554 }
15555 initStatisticChart('user-chart-content', data.chart_data);
15556 const totalUserActived = 0;
15557 document.querySelector('.statistics-instructors').textContent = data.total_instructors;
15558 document.querySelector('.statistics-students').textContent = data.total_students;
15559 document.querySelector('.statistics-user-actived').textContent = data.total_instructors + data.total_students;
15560 document.querySelector('.statistics-not-started').textContent = data.user_not_start_course;
15561 if (data.user_course_statused.length > 0) {
15562 let userGraduration = data.user_course_statused,
15563 userFinished = 0;
15564 for (let i = 0; i < userGraduration.length; i++) {
15565 if (userGraduration[i].graduation_status === 'in-progress') {
15566 document.querySelector('.statistics-graduration.in-progress').textContent = userGraduration[i].user_count;
15567 } else {
15568 userFinished += parseInt(userGraduration[i].user_count);
15569 }
15570 }
15571 document.querySelector('.statistics-graduration.finished').textContent = userFinished;
15572 } else {
15573 document.querySelectorAll('.statistics-graduration').forEach(ele => {
15574 ele.textContent = 0;
15575 });
15576 }
15577 if (Object.keys(data.top_enrolled_instructor).length > 0) {
15578 const topInstructor = data.top_enrolled_instructor,
15579 topInstructorWrap = document.querySelector('.top-intructor-by-student');
15580 Object.keys(topInstructor).forEach(function (key) {
15581 // console.log(key, topInstructor[key]);
15582 topInstructorWrap.insertAdjacentHTML('beforeend', `<li>${topInstructor[key].name} - ${topInstructor[key].students}</li>`);
15583 });
15584 }
15585 if (data.top_enrolled_courses.length > 0) {
15586 const topCourse = data.top_enrolled_courses,
15587 topCourseWrap = document.querySelector('.top-course-by-student');
15588 for (let i = 0; i < topCourse.length; i++) {
15589 topCourseWrap.insertAdjacentHTML('beforeend', `<li>${topCourse[i].course_name} - ${topCourse[i].enrolled_user}</li>`);
15590 }
15591 }
15592 }).catch(err => {
15593 console.log(err);
15594 }).finally(() => {});
15595 };
15596 const generateChart = (chartEle = '', data = [], config = {}) => {
15597 const canvas = document.getElementById(chartEle);
15598 const chart_data = {
15599 labels: data.labels,
15600 datasets: [{
15601 label: data.line_label,
15602 borderColor: 'rgb(49 74 199)',
15603 borderWidth: 2,
15604 data: data.data,
15605 backgroundColor: 'rgb(49 74 199)'
15606 }]
15607 };
15608 const configDefault = {
15609 type: 'line',
15610 data: chart_data,
15611 options: {
15612 responsive: true,
15613 maintainAspectRatio: false,
15614 aspectRatio: 0.8,
15615 plugins: {
15616 legend: {
15617 display: false
15618 }
15619 },
15620 scales: {
15621 y: {
15622 min: 0
15623 },
15624 x: {
15625 title: {
15626 display: true,
15627 text: data.x_label,
15628 align: 'end'
15629 }
15630 }
15631 }
15632 }
15633 };
15634 const configChart = {
15635 ...configDefault,
15636 ...config
15637 };
15638 configChart.options = {
15639 ...configDefault.options,
15640 ...config.options
15641 };
15642
15643 // console.log( configChart );
15644
15645 const chart = new chart_js_auto__WEBPACK_IMPORTED_MODULE_0__["default"](canvas, configChart);
15646 return chart;
15647 };
15648 const loadLpSkeletonAnimations = (show = false) => {
15649 if (show) {
15650 document.querySelectorAll('.lp-skeleton-animation').forEach(animation => {
15651 animation.style.display = 'block';
15652 });
15653 } else {
15654 document.querySelectorAll('.lp-skeleton-animation').forEach(animation => {
15655 animation.style.display = 'none';
15656 });
15657 }
15658 };
15659 document.querySelectorAll('.btn-filter-time').forEach(btn => {
15660 btn.addEventListener('click', () => {
15661 document.querySelectorAll('.btn-filter-time').forEach(ele => ele.classList.remove('active'));
15662 btn.classList.add('active');
15663 const filterType = btn.dataset.filter;
15664 if (filterType == 'custom') {
15665 document.querySelector('.custom-filter-time').style.display = 'flex';
15666 } else {
15667 const elementLoad = document.querySelector('input.statistics-type');
15668 if (elementLoad) {
15669 document.querySelector('.statistics-content canvas').style.display = 'none';
15670 loadLpSkeletonAnimations(true);
15671 if (elementLoad.value == 'orders-statistics') {
15672 orderLoadData(filterType);
15673 } else if (elementLoad.value == 'overview-statistics') {
15674 document.querySelector('.top-category-sold').innerHTML = '';
15675 document.querySelector('.top-course-sold').innerHTML = '';
15676 overviewLoadData(filterType);
15677 } else if (elementLoad.value == 'courses-statistics') {
15678 courseLoadData(filterType);
15679 } else if (elementLoad.value == 'users-statistics') {
15680 document.querySelector('.top-course-by-student').innerHTML = '';
15681 document.querySelector('.top-intructor-by-student').innerHTML = '';
15682 userLoadData(filterType);
15683 }
15684 }
15685 }
15686 });
15687 });
15688 document.querySelector('.custom-filter-btn').addEventListener('click', e => {
15689 const time1 = document.querySelector('#ct-filter-1').value,
15690 time2 = document.querySelector('#ct-filter-2').value;
15691 if (!time1 || !time2) {
15692 alert('Choose date');
15693 } else {
15694 const elementLoad = document.querySelector('input.statistics-type');
15695 document.querySelector('.statistics-content canvas').style.display = 'none';
15696 loadLpSkeletonAnimations(true);
15697 if (elementLoad) {
15698 if (elementLoad.value === 'orders-statistics') {
15699 orderLoadData('custom', `${time1}+${time2}`);
15700 } else if (elementLoad.value === 'overview-statistics') {
15701 document.querySelector('.top-category-sold').innerHTML = '';
15702 document.querySelector('.top-course-sold').innerHTML = '';
15703 overviewLoadData('custom', `${time1}+${time2}`);
15704 } else if (elementLoad.value === 'courses-statistics') {
15705 courseLoadData('custom', `${time1}+${time2}`);
15706 } else if (elementLoad.value === 'users-statistics') {
15707 userLoadData('custom', `${time1}+${time2}`);
15708 }
15709 }
15710 }
15711 });
15712 lpStatisticsLoad();
15713 const initStatisticChart = (chartID = '', chartData = [], chartConfig = false) => {
15714 let chart = chart_js_auto__WEBPACK_IMPORTED_MODULE_0__["default"].getChart(chartID);
15715 const chartEle = document.getElementById(chartID);
15716
15717 // console.log( data );
15718 chartEle.style.display = 'block';
15719 loadLpSkeletonAnimations();
15720 if (chart === undefined) {
15721 if (chartConfig) {
15722 chart = generateChart(chartID, chartData, chartConfig);
15723 } else {
15724 chart = generateChart(chartID, chartData);
15725 }
15726 } else {
15727 chart.data.labels = chartData.labels;
15728 chart.data.datasets[0].data = chartData.data;
15729 chart.config.options.scales.x.title.text = chartData.x_label;
15730 chart.update();
15731 }
15732 };
15733 });
15734 })();
15735
15736 /******/ })()
15737 ;
15738 //# sourceMappingURL=admin-statistic.js.map