chartjs-plugin-chart2music 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,456 @@
1
+ define(['chart2music'], (function (c2mChart) { 'use strict';
2
+
3
+ const calcMedian = (nums) => (nums.length % 2) ? nums[Math.floor(nums.length / 2)] : (nums[nums.length / 2] + nums[nums.length / 2 - 1]) / 2;
4
+ const fiveNumberSummary = (nums) => {
5
+ const sortedNumbers = nums.sort();
6
+ let min, max, q1, q3;
7
+ const datamin = Math.min(...sortedNumbers);
8
+ const datamax = Math.max(...sortedNumbers);
9
+ const median = calcMedian(sortedNumbers);
10
+ const length = sortedNumbers.length;
11
+ if (length % 2) {
12
+ q1 = calcMedian(sortedNumbers.slice(0, Math.floor(length / 2)));
13
+ q3 = calcMedian(sortedNumbers.slice(Math.ceil(length % 2)));
14
+ }
15
+ else {
16
+ q1 = calcMedian(sortedNumbers.slice(0, length / 2 - 1));
17
+ q3 = calcMedian(sortedNumbers.slice(length / 2));
18
+ }
19
+ const iqr = q3 - q1;
20
+ if (datamax < q3 + iqr) {
21
+ max = datamax;
22
+ }
23
+ else {
24
+ max = sortedNumbers.reverse().find((num) => num < datamax) ?? datamax;
25
+ }
26
+ if (datamin < q1 - iqr) {
27
+ min = datamin;
28
+ }
29
+ else {
30
+ min = sortedNumbers.reverse().find((num) => num < datamin) ?? datamin;
31
+ }
32
+ const outlier = sortedNumbers.filter((num) => num < min || num > max);
33
+ return {
34
+ low: min,
35
+ high: max,
36
+ median,
37
+ q1,
38
+ q3,
39
+ ...(outlier.length > 0 ? { outlier } : {})
40
+ };
41
+ };
42
+ const whichBoxData = (data) => {
43
+ return data.map((row, index) => {
44
+ if (typeof row === "object" && "min" in row) {
45
+ return {
46
+ ...row,
47
+ low: row.min,
48
+ high: row.max,
49
+ x: index,
50
+ ...("outliers" in row ? { outlier: row.outliers } : {})
51
+ };
52
+ }
53
+ if (Array.isArray(row)) {
54
+ return {
55
+ ...fiveNumberSummary(row),
56
+ x: index
57
+ };
58
+ }
59
+ });
60
+ };
61
+ const processBoxData = (data) => {
62
+ if (data.datasets.length === 1) {
63
+ return {
64
+ data: whichBoxData(data.datasets[0].data)
65
+ };
66
+ }
67
+ const groups = [];
68
+ const result = {};
69
+ data.datasets.forEach((obj, index) => {
70
+ const groupName = obj.label ?? `Group ${index + 1}`;
71
+ groups.push(groupName);
72
+ result[groupName] = whichBoxData(obj.data);
73
+ });
74
+ return { groups, data: result };
75
+ };
76
+
77
+ const chartStates = new Map();
78
+ const chartjs_c2m_converter = {
79
+ bar: "bar",
80
+ line: "line",
81
+ pie: "pie",
82
+ polarArea: "bar",
83
+ doughnut: "pie",
84
+ boxplot: "box",
85
+ radar: "bar",
86
+ wordCloud: "bar",
87
+ scatter: "scatter"
88
+ };
89
+ const processChartType = (chart) => {
90
+ const topLevelType = chart.config.type;
91
+ const panelTypes = chart.data.datasets.map(({ type }) => type ?? topLevelType);
92
+ const invalid = panelTypes.find((t) => !(t in chartjs_c2m_converter));
93
+ if (invalid) {
94
+ return {
95
+ valid: false,
96
+ invalidType: invalid
97
+ };
98
+ }
99
+ if ([...new Set(panelTypes)].length === 1) {
100
+ return {
101
+ valid: true,
102
+ c2m_types: chartjs_c2m_converter[panelTypes[0]]
103
+ };
104
+ }
105
+ return {
106
+ valid: true,
107
+ c2m_types: panelTypes.map((t) => chartjs_c2m_converter[t])
108
+ };
109
+ };
110
+ const generateAxisInfo = (chartAxisInfo, chart) => {
111
+ const axis = {};
112
+ if (chartAxisInfo?.min) {
113
+ if (typeof chartAxisInfo.min === "string") {
114
+ axis.minimum = chart.data.labels.indexOf(chartAxisInfo.min);
115
+ }
116
+ else {
117
+ axis.minimum = chartAxisInfo.min;
118
+ }
119
+ }
120
+ if (chartAxisInfo?.max) {
121
+ if (typeof chartAxisInfo.max === "string") {
122
+ axis.maximum = chart.data.labels.indexOf(chartAxisInfo.max);
123
+ }
124
+ else {
125
+ axis.maximum = chartAxisInfo.max;
126
+ }
127
+ }
128
+ const label = chartAxisInfo?.title?.text;
129
+ if (label) {
130
+ axis.label = label;
131
+ }
132
+ if (chartAxisInfo?.type === "logarithmic") {
133
+ axis.type = "log10";
134
+ }
135
+ return axis;
136
+ };
137
+ const generateAxes = (chart) => {
138
+ const axes = {
139
+ x: {
140
+ ...generateAxisInfo(chart.options?.scales?.x, chart),
141
+ valueLabels: chart.data.labels.slice(0)
142
+ },
143
+ y: {
144
+ ...generateAxisInfo(chart.options?.scales?.y, chart),
145
+ format: (value) => value.toLocaleString()
146
+ }
147
+ };
148
+ return axes;
149
+ };
150
+ const whichDataStructure = (data) => {
151
+ if (Array.isArray(data[0])) {
152
+ return data.map((arr, x) => {
153
+ let [low, high] = arr.sort();
154
+ return { x, low, high };
155
+ });
156
+ }
157
+ return data;
158
+ };
159
+ const scrubX = (data) => {
160
+ const blackboard = JSON.parse(JSON.stringify(data));
161
+ let labels = [];
162
+ if (Array.isArray(data)) {
163
+ // console.log("not grouped");
164
+ // Not grouped
165
+ blackboard.forEach((item, x) => {
166
+ if (typeof item === "object" && item !== null && "x" in item) {
167
+ labels.push(item.x);
168
+ item.x = x;
169
+ }
170
+ });
171
+ return { labels, data: blackboard };
172
+ }
173
+ };
174
+ const processData = (data, c2m_types) => {
175
+ if (c2m_types === "box") {
176
+ return processBoxData(data);
177
+ }
178
+ let groups = [];
179
+ if (data.datasets.length === 1) {
180
+ return {
181
+ data: whichDataStructure(data.datasets[0].data)
182
+ };
183
+ }
184
+ const result = {};
185
+ data.datasets.forEach((obj, index) => {
186
+ const groupName = obj.label ?? `Group ${index + 1}`;
187
+ groups.push(groupName);
188
+ result[groupName] = whichDataStructure(obj.data);
189
+ });
190
+ return { groups, data: result };
191
+ };
192
+ const determineChartTitle = (options) => {
193
+ if (options.plugins?.title?.text) {
194
+ if (Array.isArray(options.plugins.title.text)) {
195
+ return options.plugins.title.text.join(", ");
196
+ }
197
+ return options.plugins.title.text;
198
+ }
199
+ return "";
200
+ };
201
+ const determineCCElement = (canvas, provided) => {
202
+ if (provided) {
203
+ return provided;
204
+ }
205
+ const cc = document.createElement("div");
206
+ canvas.insertAdjacentElement("afterend", cc);
207
+ return cc;
208
+ };
209
+ const displayPoint = (chart) => {
210
+ if (!chartStates.has(chart)) {
211
+ return;
212
+ }
213
+ const { c2m: ref, visible_groups } = chartStates.get(chart);
214
+ const { point, index } = ref.getCurrent();
215
+ try {
216
+ const highlightElements = [];
217
+ if ("custom" in point) {
218
+ highlightElements.push({
219
+ // @ts-ignore
220
+ datasetIndex: point.custom.group,
221
+ // @ts-ignore
222
+ index: point.custom.index
223
+ });
224
+ }
225
+ else {
226
+ visible_groups.forEach((datasetIndex) => {
227
+ highlightElements.push({
228
+ datasetIndex,
229
+ index
230
+ });
231
+ });
232
+ }
233
+ chart?.setActiveElements(highlightElements);
234
+ chart?.tooltip?.setActiveElements(highlightElements, {});
235
+ chart?.update();
236
+ }
237
+ catch (e) {
238
+ // console.warn(e);
239
+ }
240
+ };
241
+ const generateChart = (chart, options) => {
242
+ const { valid, c2m_types, invalidType } = processChartType(chart);
243
+ if (!valid) {
244
+ // @ts-ignore
245
+ options.errorCallback?.(`Unable to connect chart2music to chart. The chart is of type "${invalidType}", which is not one of the supported chart types for this plugin. This plugin supports: ${Object.keys(chartjs_c2m_converter).join(", ")}`);
246
+ return;
247
+ }
248
+ let axes = generateAxes(chart);
249
+ if (chart.config.type === "wordCloud") {
250
+ delete axes.x.minimum;
251
+ delete axes.x.maximum;
252
+ delete axes.y.minimum;
253
+ delete axes.y.maximum;
254
+ if (!axes.x.label) {
255
+ axes.x.label = "Word";
256
+ }
257
+ if (!axes.y.label) {
258
+ axes.y.label = "Emphasis";
259
+ }
260
+ }
261
+ // Generate CC element
262
+ const cc = determineCCElement(chart.canvas, options.cc);
263
+ const { data, groups } = processData(chart.data, c2m_types);
264
+ // lastDataObj = JSON.stringify(data);
265
+ let scrub = scrubX(data);
266
+ if (scrub?.labels && scrub?.labels?.length > 0) { // Something was scrubbed
267
+ if (!chart.data.labels || chart.data.labels.length === 0) {
268
+ axes.x.valueLabels = scrub.labels.slice(0);
269
+ }
270
+ }
271
+ if (c2m_types === "scatter") {
272
+ delete scrub?.data;
273
+ delete axes.x.valueLabels;
274
+ }
275
+ axes = {
276
+ ...axes,
277
+ x: {
278
+ ...axes.x,
279
+ ...(options.axes?.x)
280
+ },
281
+ y: {
282
+ ...axes.y,
283
+ ...(options.axes?.y)
284
+ },
285
+ };
286
+ const c2mOptions = {
287
+ cc,
288
+ element: chart.canvas,
289
+ type: c2m_types,
290
+ data: scrub?.data ?? data,
291
+ title: determineChartTitle(chart.options),
292
+ axes,
293
+ options: {
294
+ // @ts-ignore
295
+ onFocusCallback: () => {
296
+ displayPoint(chart);
297
+ }
298
+ }
299
+ };
300
+ if (Array.isArray(c2mOptions.data)) {
301
+ if (isNaN(c2mOptions.data[0])) {
302
+ c2mOptions.data = c2mOptions.data.map((point, index) => {
303
+ return {
304
+ ...point,
305
+ custom: {
306
+ group: 0,
307
+ index
308
+ }
309
+ };
310
+ });
311
+ }
312
+ else {
313
+ c2mOptions.data = c2mOptions.data.map((num, index) => {
314
+ return {
315
+ x: index,
316
+ y: num,
317
+ custom: {
318
+ group: 0,
319
+ index
320
+ }
321
+ };
322
+ });
323
+ }
324
+ }
325
+ else {
326
+ const groups = Object.keys(c2mOptions.data);
327
+ groups.forEach((groupName, groupNumber) => {
328
+ if (!isNaN(c2mOptions.data[groupName][0])) {
329
+ c2mOptions.data[groupName] = c2mOptions.data[groupName].map((num, index) => {
330
+ return {
331
+ x: index,
332
+ y: num,
333
+ custom: {
334
+ group: groupNumber,
335
+ index
336
+ }
337
+ };
338
+ });
339
+ }
340
+ else {
341
+ c2mOptions.data[groupName] = c2mOptions.data[groupName].map((point, index) => {
342
+ return {
343
+ ...point,
344
+ custom: {
345
+ group: groupNumber,
346
+ index
347
+ }
348
+ };
349
+ });
350
+ }
351
+ });
352
+ }
353
+ // @ts-ignore
354
+ if (chart.config.options?.scales?.x?.stacked) {
355
+ // @ts-ignore
356
+ c2mOptions.options.stack = true;
357
+ }
358
+ // @ts-ignore
359
+ if (options.audioEngine) {
360
+ // @ts-ignore
361
+ c2mOptions.audioEngine = options.audioEngine;
362
+ }
363
+ if (c2mOptions.data.length === 0) {
364
+ return;
365
+ }
366
+ if (options.lang) {
367
+ c2mOptions.lang = options.lang;
368
+ }
369
+ const { err, data: c2m } = c2mChart(c2mOptions);
370
+ /* istanbul-ignore-next */
371
+ if (err) {
372
+ // @ts-ignore
373
+ options.errorCallback?.(err);
374
+ return;
375
+ }
376
+ if (!c2m) {
377
+ return;
378
+ }
379
+ chartStates.set(chart, {
380
+ c2m,
381
+ visible_groups: groups?.map((g, i) => i) ?? []
382
+ });
383
+ };
384
+ const plugin = {
385
+ id: "chartjs2music",
386
+ afterInit: (chart, args, options) => {
387
+ if (!chartStates.has(chart)) {
388
+ generateChart(chart, options);
389
+ // Remove tooltip when the chart blurs
390
+ chart.canvas.addEventListener("blur", () => {
391
+ chart.setActiveElements([]);
392
+ chart.tooltip?.setActiveElements([], {});
393
+ try {
394
+ chart.update();
395
+ }
396
+ catch (e) {
397
+ // console.warn(e);
398
+ }
399
+ });
400
+ // Show tooltip when the chart receives focus
401
+ chart.canvas.addEventListener("focus", () => {
402
+ displayPoint(chart);
403
+ });
404
+ }
405
+ },
406
+ afterDatasetUpdate: (chart, args, options) => {
407
+ if (!args.mode) {
408
+ return;
409
+ }
410
+ if (!chartStates.has(chart)) {
411
+ generateChart(chart, options);
412
+ }
413
+ const { c2m: ref, visible_groups } = chartStates.get(chart);
414
+ if (!ref) {
415
+ return;
416
+ }
417
+ // @ts-ignore
418
+ const groups = ref._groups.slice(0);
419
+ // @ts-ignore
420
+ if (ref._options.stack) {
421
+ groups.shift();
422
+ }
423
+ if (args.mode === "hide") {
424
+ const err = ref.setCategoryVisibility(groups[args.index], false);
425
+ visible_groups.splice(args.index, 1);
426
+ if (err) {
427
+ console.error(err);
428
+ }
429
+ return;
430
+ }
431
+ if (args.mode === "show") {
432
+ const err = ref.setCategoryVisibility(groups[args.index], true);
433
+ visible_groups.push(args.index);
434
+ if (err) {
435
+ console.error(err);
436
+ }
437
+ return;
438
+ }
439
+ },
440
+ afterDestroy: (chart) => {
441
+ const { c2m: ref } = chartStates.get(chart);
442
+ if (!ref) {
443
+ return;
444
+ }
445
+ ref.cleanUp();
446
+ },
447
+ defaults: {
448
+ cc: null,
449
+ audioEngine: null,
450
+ errorCallback: null
451
+ }
452
+ };
453
+
454
+ return plugin;
455
+
456
+ }));
package/dist/plugin.cjs CHANGED
@@ -5,23 +5,23 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports["default"] = void 0;
7
7
  var _chart2music = _interopRequireDefault(require("chart2music"));
8
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
9
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
9
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
10
10
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
11
11
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
12
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
13
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
14
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
15
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
16
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
16
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
17
17
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
18
18
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
19
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
19
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
20
20
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
21
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
22
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
23
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
24
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
21
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
22
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
23
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
24
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
25
25
  var calcMedian = function calcMedian(nums) {
26
26
  return nums.length % 2 ? nums[Math.floor(nums.length / 2)] : (nums[nums.length / 2] + nums[nums.length / 2 - 1]) / 2;
27
27
  };
@@ -0,0 +1 @@
1
+ declare module "chartjs-plugin-chart2music";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chartjs-plugin-chart2music",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "Chart.js plugin for Chart2Music. Turns chart.js charts into music so the blind can hear data.",
6
6
  "main": "dist/plugin.js",
@@ -9,6 +9,7 @@
9
9
  "import": "./dist/plugin.mjs",
10
10
  "require": "./dist/plugin.cjs"
11
11
  },
12
+ "types": "dist/plugin.d.ts",
12
13
  "files": [
13
14
  "dist/*"
14
15
  ],
@@ -35,32 +36,33 @@
35
36
  "build-cjs": "babel ./dist/plugin.mjs --out-file ./dist/plugin.cjs",
36
37
  "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
37
38
  "depcheck": "depcheck",
38
- "clean": "rimraf dist coverage"
39
+ "clean": "rimraf dist coverage",
40
+ "prepack": "npm run clean && npm run build"
39
41
  },
40
42
  "devDependencies": {
41
- "@babel/cli": "7.24.1",
42
- "@babel/core": "7.24.4",
43
- "@babel/plugin-transform-modules-commonjs": "7.24.1",
44
- "@babel/preset-env": "7.24.4",
45
- "@rollup/plugin-typescript": "11.1.6",
46
- "@sgratzl/chartjs-chart-boxplot": "4.3.1",
47
- "@types/jest": "29.5.12",
43
+ "@babel/cli": "7.25.6",
44
+ "@babel/core": "7.25.2",
45
+ "@babel/plugin-transform-modules-commonjs": "7.24.8",
46
+ "@babel/preset-env": "7.25.4",
47
+ "@rollup/plugin-typescript": "12.1.0",
48
+ "@sgratzl/chartjs-chart-boxplot": "4.4.2",
49
+ "@types/jest": "29.5.13",
48
50
  "canvas": "2.11.2",
49
- "chartjs-chart-wordcloud": "4.4.0",
50
- "chartjs-plugin-a11y-legend": "0.1.1",
51
+ "chartjs-chart-wordcloud": "4.4.2",
52
+ "chartjs-plugin-a11y-legend": "0.1.2",
51
53
  "cross-env": "7.0.3",
52
54
  "depcheck": "1.4.7",
53
55
  "jest": "29.7.0",
54
56
  "jest-environment-jsdom": "29.7.0",
55
- "rimraf": "5.0.5",
56
- "rollup": "4.14.0",
57
- "ts-jest": "29.1.2",
58
- "tslib": "2.6.2",
59
- "typescript": "5.4.3",
60
- "vite": "5.2.8"
57
+ "rollup": "4.22.5",
58
+ "rollup-plugin-copy": "3.5.0",
59
+ "ts-jest": "29.2.5",
60
+ "tslib": "2.7.0",
61
+ "typescript": "5.6.2",
62
+ "vite": "5.4.8"
61
63
  },
62
64
  "dependencies": {
63
- "chart.js": "4.4.2",
64
- "chart2music": "1.16.1"
65
+ "chart.js": "4.4.4",
66
+ "chart2music": "1.17.0"
65
67
  }
66
68
  }