adminator-admin-dashboard 2.8.1 → 4.1.5

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.
Files changed (179) hide show
  1. package/CHANGELOG.md +499 -0
  2. package/CLAUDE.md +126 -154
  3. package/README.md +321 -370
  4. package/dist/2026.js +8751 -0
  5. package/dist/2026.js.map +1 -0
  6. package/dist/404.html +36 -16
  7. package/dist/500.html +36 -16
  8. package/dist/assets/static/images/logo.svg +3 -3
  9. package/dist/basic-table.html +152 -699
  10. package/dist/blank.html +42 -507
  11. package/dist/buttons.html +152 -448
  12. package/dist/calendar.html +246 -658
  13. package/dist/charts.html +124 -658
  14. package/dist/chat.html +209 -706
  15. package/dist/compose.html +141 -618
  16. package/dist/datatable.html +467 -991
  17. package/dist/email.html +430 -943
  18. package/dist/forms.html +208 -733
  19. package/dist/google-maps.html +123 -513
  20. package/dist/index.html +436 -1041
  21. package/dist/runtime.js +1299 -0
  22. package/dist/runtime.js.map +1 -0
  23. package/dist/signin.html +92 -92
  24. package/dist/signup.html +106 -91
  25. package/dist/ui.html +268 -897
  26. package/dist/vector-maps.html +132 -511
  27. package/dist/vendor-chartjs.js +14593 -0
  28. package/dist/vendor-chartjs.js.map +1 -0
  29. package/dist/vendor-fullcalendar.js +14793 -0
  30. package/dist/vendor-fullcalendar.js.map +1 -0
  31. package/dist/vendors.js +3758 -0
  32. package/dist/vendors.js.map +1 -0
  33. package/package.json +50 -52
  34. package/src/404.html +35 -15
  35. package/src/500.html +35 -15
  36. package/src/assets/scripts/2026/Shell.js +312 -0
  37. package/src/assets/scripts/2026/calendar.js +123 -0
  38. package/src/assets/scripts/2026/charts.js +259 -0
  39. package/src/assets/scripts/2026/index.js +35 -0
  40. package/src/assets/scripts/2026/init.js +207 -0
  41. package/src/assets/scripts/2026/maps.js +78 -0
  42. package/src/assets/scripts/2026/palette.js +266 -0
  43. package/src/assets/static/images/logo.svg +3 -3
  44. package/src/assets/styles/2026/_animations.scss +14 -0
  45. package/src/assets/styles/2026/_auth.scss +215 -0
  46. package/src/assets/styles/2026/_base.scss +37 -0
  47. package/src/assets/styles/2026/_calendar.scss +380 -0
  48. package/src/assets/styles/2026/_charts.scss +44 -0
  49. package/src/assets/styles/2026/_chat.scss +350 -0
  50. package/src/assets/styles/2026/_components.scss +140 -0
  51. package/src/assets/styles/2026/_dashboard.scss +520 -0
  52. package/src/assets/styles/2026/_data.scss +130 -0
  53. package/src/assets/styles/2026/_dropdowns.scss +128 -0
  54. package/src/assets/styles/2026/_email.scss +599 -0
  55. package/src/assets/styles/2026/_error.scss +98 -0
  56. package/src/assets/styles/2026/_forms.scss +215 -0
  57. package/src/assets/styles/2026/_fullcalendar.scss +134 -0
  58. package/src/assets/styles/2026/_palette.scss +173 -0
  59. package/src/assets/styles/2026/_responsive.scss +229 -0
  60. package/src/assets/styles/2026/_shell.scss +290 -0
  61. package/src/assets/styles/2026/_tokens.scss +80 -0
  62. package/src/assets/styles/2026/_ui.scss +365 -0
  63. package/src/assets/styles/2026/index.scss +23 -0
  64. package/src/basic-table.html +153 -710
  65. package/src/blank.html +42 -517
  66. package/src/buttons.html +152 -458
  67. package/src/calendar.html +246 -668
  68. package/src/charts.html +124 -668
  69. package/src/chat.html +209 -716
  70. package/src/compose.html +142 -629
  71. package/src/datatable.html +466 -1000
  72. package/src/email.html +429 -952
  73. package/src/forms.html +207 -742
  74. package/src/google-maps.html +128 -523
  75. package/src/index.html +438 -1050
  76. package/src/signin.html +92 -92
  77. package/src/signup.html +106 -91
  78. package/src/ui.html +267 -906
  79. package/src/vector-maps.html +133 -522
  80. package/dist/1e59d2330b4c6deb84b3.ttf +0 -0
  81. package/dist/20fd1704ea223900efa9.woff2 +0 -0
  82. package/dist/29b39089170885ae2967.woff +0 -0
  83. package/dist/8b43027f47b20503057d.eot +0 -0
  84. package/dist/9bad94440d49256265a5.eot +0 -0
  85. package/dist/assets/fontawesome-webfont.svg +0 -2671
  86. package/dist/assets/themify.svg +0 -362
  87. package/dist/eda8b94308c6f538f04a.ttf +0 -0
  88. package/dist/f691f37e57f04c152e23.woff +0 -0
  89. package/dist/main.js +0 -61323
  90. package/dist/main.js.map +0 -1
  91. package/src/assets/scripts/app 2.js +0 -645
  92. package/src/assets/scripts/app.js +0 -645
  93. package/src/assets/scripts/charts/chartJS/index.js +0 -148
  94. package/src/assets/scripts/charts/easyPieChart/index.js +0 -200
  95. package/src/assets/scripts/charts/index.js +0 -3
  96. package/src/assets/scripts/charts/sparkline/index.js +0 -208
  97. package/src/assets/scripts/chat/index.js +0 -11
  98. package/src/assets/scripts/components/Chart.js +0 -1390
  99. package/src/assets/scripts/components/Sidebar.js +0 -241
  100. package/src/assets/scripts/constants/colors.js +0 -274
  101. package/src/assets/scripts/datatable/index.js +0 -379
  102. package/src/assets/scripts/datepicker/index.js +0 -302
  103. package/src/assets/scripts/email/index.js +0 -25
  104. package/src/assets/scripts/fullcalendar/index.js +0 -86
  105. package/src/assets/scripts/googleMaps/index.js +0 -93
  106. package/src/assets/scripts/index.js +0 -18
  107. package/src/assets/scripts/masonry/index.js +0 -14
  108. package/src/assets/scripts/popover/index.js +0 -109
  109. package/src/assets/scripts/scrollbar/index.js +0 -10
  110. package/src/assets/scripts/search/index.js +0 -15
  111. package/src/assets/scripts/sidebar/index.js +0 -140
  112. package/src/assets/scripts/skycons/index.js +0 -52
  113. package/src/assets/scripts/ui/index.js +0 -412
  114. package/src/assets/scripts/utils/date.js +0 -242
  115. package/src/assets/scripts/utils/dom.js +0 -349
  116. package/src/assets/scripts/utils/index.js +0 -45
  117. package/src/assets/scripts/utils/theme.js +0 -107
  118. package/src/assets/scripts/vectorMaps/index.js +0 -277
  119. package/src/assets/styles/index.scss +0 -801
  120. package/src/assets/styles/spec/components/easyPieChart.scss +0 -11
  121. package/src/assets/styles/spec/components/footer.scss +0 -4
  122. package/src/assets/styles/spec/components/forms.scss +0 -288
  123. package/src/assets/styles/spec/components/index.scss +0 -9
  124. package/src/assets/styles/spec/components/loader.scss +0 -46
  125. package/src/assets/styles/spec/components/masonry.scss +0 -1
  126. package/src/assets/styles/spec/components/pageContainer.scss +0 -255
  127. package/src/assets/styles/spec/components/progressBar.scss +0 -6
  128. package/src/assets/styles/spec/components/sidebar.scss +0 -642
  129. package/src/assets/styles/spec/components/topbar.scss +0 -455
  130. package/src/assets/styles/spec/generic/base.scss +0 -102
  131. package/src/assets/styles/spec/generic/index.scss +0 -1
  132. package/src/assets/styles/spec/index.scss +0 -4
  133. package/src/assets/styles/spec/screens/chat.scss +0 -147
  134. package/src/assets/styles/spec/screens/email.scss +0 -108
  135. package/src/assets/styles/spec/screens/index.scss +0 -2
  136. package/src/assets/styles/spec/settings/baseColors.scss +0 -103
  137. package/src/assets/styles/spec/settings/borders.scss +0 -6
  138. package/src/assets/styles/spec/settings/breakpoints.scss +0 -26
  139. package/src/assets/styles/spec/settings/fonts.scss +0 -4
  140. package/src/assets/styles/spec/settings/index.scss +0 -4
  141. package/src/assets/styles/spec/settings/materialColors.scss +0 -550
  142. package/src/assets/styles/spec/tools/index.scss +0 -1
  143. package/src/assets/styles/spec/tools/mixins/clearfix.scss +0 -15
  144. package/src/assets/styles/spec/tools/mixins/index.scss +0 -3
  145. package/src/assets/styles/spec/tools/mixins/mediaQueriesRanges.scss +0 -58
  146. package/src/assets/styles/spec/tools/mixins/placeholder.scss +0 -10
  147. package/src/assets/styles/spec/utils/colors.scss +0 -33
  148. package/src/assets/styles/spec/utils/index.scss +0 -2
  149. package/src/assets/styles/spec/utils/layout/helpers/border.scss +0 -78
  150. package/src/assets/styles/spec/utils/layout/helpers/flex.scss +0 -220
  151. package/src/assets/styles/spec/utils/layout/helpers/index.scss +0 -11
  152. package/src/assets/styles/spec/utils/layout/helpers/layout.scss +0 -137
  153. package/src/assets/styles/spec/utils/layout/helpers/lists.scss +0 -23
  154. package/src/assets/styles/spec/utils/layout/helpers/margin.scss +0 -266
  155. package/src/assets/styles/spec/utils/layout/helpers/objects.scss +0 -91
  156. package/src/assets/styles/spec/utils/layout/helpers/padding.scss +0 -147
  157. package/src/assets/styles/spec/utils/layout/helpers/positions.scss +0 -118
  158. package/src/assets/styles/spec/utils/layout/helpers/pseudo.scss +0 -6
  159. package/src/assets/styles/spec/utils/layout/helpers/sizes.scss +0 -157
  160. package/src/assets/styles/spec/utils/layout/helpers/typography.scss +0 -127
  161. package/src/assets/styles/spec/utils/layout/index.scss +0 -3
  162. package/src/assets/styles/spec/utils/layout/mixins/generateResponsive.scss +0 -25
  163. package/src/assets/styles/spec/utils/layout/mixins/index.scss +0 -2
  164. package/src/assets/styles/spec/utils/layout/mixins/mediaQueryCondition.scss +0 -28
  165. package/src/assets/styles/spec/utils/layout/utils/center.scss +0 -54
  166. package/src/assets/styles/spec/utils/layout/utils/gap.scss +0 -229
  167. package/src/assets/styles/spec/utils/layout/utils/index.scss +0 -5
  168. package/src/assets/styles/spec/utils/layout/utils/layers.scss +0 -5
  169. package/src/assets/styles/spec/utils/layout/utils/peers.scss +0 -35
  170. package/src/assets/styles/utils/mobile.scss +0 -954
  171. package/src/assets/styles/utils/theme.css +0 -97
  172. package/src/assets/styles/vendor/datepicker.scss +0 -183
  173. package/src/assets/styles/vendor/font-awesome.css +0 -2337
  174. package/src/assets/styles/vendor/fullcalendar.scss +0 -217
  175. package/src/assets/styles/vendor/index.scss +0 -8
  176. package/src/assets/styles/vendor/jquery.datatables.scss +0 -162
  177. package/src/assets/styles/vendor/perfectScrollbar.scss +0 -4
  178. package/src/assets/styles/vendor/sparkline.scss +0 -6
  179. package/src/assets/styles/vendor/themify-icons.css +0 -1081
@@ -1,1390 +0,0 @@
1
- /**
2
- * Modern Chart Component
3
- * Replaces jQuery Sparkline with Chart.js
4
- */
5
-
6
- import { Chart, registerables } from 'chart.js';
7
- import { COLORS } from '../constants/colors';
8
-
9
- // Register Chart.js components
10
- Chart.register(...registerables);
11
-
12
- class ChartComponent {
13
- constructor() {
14
- this.charts = new Map(); // Store chart instances
15
- this.debounceTimer = null;
16
- this.init();
17
- }
18
-
19
- init() {
20
- // Only disable resizing for small sparkline charts
21
- this.createSparklines();
22
- this.createOtherCharts();
23
- this.setupResizeHandler();
24
- }
25
-
26
-
27
-
28
- /**
29
- * Create sparklines (only for dashboard page)
30
- */
31
- createSparklines() {
32
- // Only create sparklines if we're on a page that has them
33
- const sparklineExists = document.getElementById('sparklinedash');
34
- if (!sparklineExists) {
35
- return;
36
- }
37
-
38
- const sparklineConfigs = [
39
- {
40
- id: 'sparklinedash',
41
- data: [0, 5, 6, 10, 9, 12, 4, 9],
42
- color: '#4caf50',
43
- },
44
- {
45
- id: 'sparklinedash2',
46
- data: [0, 5, 6, 10, 9, 12, 4, 9],
47
- color: '#9675ce',
48
- },
49
- {
50
- id: 'sparklinedash3',
51
- data: [0, 5, 6, 10, 9, 12, 4, 9],
52
- color: '#03a9f3',
53
- },
54
- {
55
- id: 'sparklinedash4',
56
- data: [0, 5, 6, 10, 9, 12, 4, 9],
57
- color: '#f96262',
58
- },
59
- ];
60
-
61
- sparklineConfigs.forEach(config => {
62
- // Only create if the target element exists
63
- if (document.getElementById(config.id)) {
64
- this.createSparklineChart(config);
65
- }
66
- });
67
- }
68
-
69
- /**
70
- * Create sparkline chart from configuration
71
- */
72
- createSparklineChart({ id, data, color }) {
73
- let canvas = document.getElementById(id);
74
-
75
- // Only proceed if we have a valid target element
76
- if (!canvas) {
77
- return;
78
- }
79
-
80
- // If element exists but isn't a canvas, replace it with canvas
81
- if (canvas.tagName !== 'CANVAS') {
82
- const parent = canvas.parentNode;
83
- if (!parent) {
84
- return;
85
- }
86
-
87
- // Create new canvas element
88
- const newCanvas = document.createElement('canvas');
89
- newCanvas.id = id;
90
- newCanvas.width = 100;
91
- newCanvas.height = 20;
92
- newCanvas.style.width = '100px';
93
- newCanvas.style.height = '20px';
94
-
95
- // Replace the span with canvas
96
- parent.replaceChild(newCanvas, canvas);
97
- canvas = newCanvas;
98
- } else {
99
- // Set canvas dimensions to match original sparkline
100
- canvas.width = 100;
101
- canvas.height = 20;
102
- canvas.style.width = '100px';
103
- canvas.style.height = '20px';
104
- }
105
-
106
- const ctx = canvas.getContext('2d');
107
-
108
- const chart = new Chart(ctx, {
109
- type: 'bar',
110
- data: {
111
- labels: data.map((_, i) => i),
112
- datasets: [{
113
- data,
114
- backgroundColor: color,
115
- borderColor: color,
116
- borderWidth: 0,
117
- barPercentage: 0.6,
118
- categoryPercentage: 0.8,
119
- }],
120
- },
121
- options: {
122
- responsive: false,
123
- maintainAspectRatio: false,
124
- animation: false,
125
- events: [],
126
- onResize: null,
127
- scales: {
128
- x: {
129
- display: false,
130
- },
131
- y: {
132
- display: false,
133
- },
134
- },
135
- plugins: {
136
- legend: {
137
- display: false,
138
- },
139
- tooltip: {
140
- enabled: false,
141
- },
142
- },
143
- elements: {
144
- bar: {
145
- borderRadius: 1,
146
- },
147
- },
148
- },
149
- });
150
-
151
- this.charts.set(id, chart);
152
- }
153
-
154
- /**
155
- * Create other chart types (only if they exist on the page)
156
- */
157
- createOtherCharts() {
158
- // Determine if we're on the dashboard or charts page
159
- const isChartsPage = document.getElementById('area-chart') !== null;
160
- const isDashboard = !isChartsPage && document.getElementById('line-chart') !== null;
161
-
162
- // Create Monthly Stats chart with enhanced dual-line data (dashboard only)
163
- if (isDashboard) {
164
- this.createMonthlyStatsChart();
165
- }
166
-
167
- // Charts page specific charts (only on charts page)
168
- if (isChartsPage) {
169
- this.createChartsPageCharts();
170
- }
171
-
172
- // Only create charts if their target elements exist
173
- if (document.getElementById('sparkline')) {
174
- this.createLineChart('sparkline', [5, 6, 7, 9, 9, 5, 3, 2, 2, 4, 6, 7]);
175
- }
176
-
177
- if (document.getElementById('compositebar')) {
178
- this.createCompositeChart('compositebar', [4, 1, 5, 7, 9, 9, 8, 7, 6, 6, 4, 7, 8, 4, 3, 2, 2, 5, 6, 7]);
179
- }
180
-
181
- // Regular sparklines with custom colors (only on pages that have them)
182
- this.createCustomSparklines();
183
-
184
- // Easy Pie Charts (only if they exist)
185
- this.createEasyPieCharts();
186
- }
187
-
188
- /**
189
- * Create enhanced Monthly Stats chart with dual lines and more data
190
- */
191
- createMonthlyStatsChart() {
192
- const canvas = document.getElementById('line-chart');
193
- if (!canvas) return;
194
-
195
- const ctx = canvas.getContext('2d');
196
-
197
- // Enhanced data for monthly stats
198
- const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
199
- const salesData = [120, 135, 145, 165, 180, 195, 210, 225, 240, 220, 200, 185];
200
- const profitData = [45, 52, 58, 62, 68, 75, 82, 88, 92, 85, 78, 72];
201
-
202
- const chart = new Chart(ctx, {
203
- type: 'line',
204
- data: {
205
- labels: months,
206
- datasets: [
207
- {
208
- label: 'Sales ($K)',
209
- data: salesData,
210
- borderColor: '#4caf50',
211
- backgroundColor: 'rgba(76, 175, 80, 0.1)',
212
- borderWidth: 3,
213
- pointRadius: 5,
214
- pointHoverRadius: 7,
215
- pointBackgroundColor: '#4caf50',
216
- pointBorderColor: '#ffffff',
217
- pointBorderWidth: 2,
218
- tension: 0.4,
219
- fill: false,
220
- },
221
- {
222
- label: 'Profit ($K)',
223
- data: profitData,
224
- borderColor: '#2196f3',
225
- backgroundColor: 'rgba(33, 150, 243, 0.1)',
226
- borderWidth: 3,
227
- pointRadius: 5,
228
- pointHoverRadius: 7,
229
- pointBackgroundColor: '#2196f3',
230
- pointBorderColor: '#ffffff',
231
- pointBorderWidth: 2,
232
- tension: 0.4,
233
- fill: false,
234
- },
235
- ],
236
- },
237
- options: {
238
- responsive: true,
239
- maintainAspectRatio: false,
240
- plugins: {
241
- legend: {
242
- display: true,
243
- position: 'top',
244
- labels: {
245
- padding: 20,
246
- font: {
247
- size: 12,
248
- weight: '600',
249
- },
250
- },
251
- },
252
- tooltip: {
253
- enabled: true,
254
- cornerRadius: 8,
255
- displayColors: true,
256
- intersect: false,
257
- mode: 'index',
258
- callbacks: {
259
- label(context) {
260
- return `${context.dataset.label }: $${ context.parsed.y }K`;
261
- },
262
- },
263
- },
264
- },
265
- scales: {
266
- x: {
267
- grid: {
268
- display: false,
269
- },
270
- ticks: {
271
- font: {
272
- size: 11,
273
- },
274
- },
275
- },
276
- y: {
277
- beginAtZero: true,
278
- grid: {
279
- borderDash: [5, 5],
280
- },
281
- ticks: {
282
- font: {
283
- size: 11,
284
- },
285
- callback(value) {
286
- return `$${ value }K`;
287
- },
288
- },
289
- },
290
- },
291
- interaction: {
292
- intersect: false,
293
- mode: 'index',
294
- },
295
- },
296
- });
297
-
298
- this.charts.set('line-chart', chart);
299
- }
300
-
301
- /**
302
- * Create line chart (only if target exists)
303
- */
304
- createLineChart(id, data) {
305
- let canvas = document.getElementById(id);
306
-
307
- // Only proceed if target element exists
308
- if (!canvas) {
309
- return;
310
- }
311
-
312
- // If element exists but isn't a canvas, replace it with canvas
313
- if (canvas.tagName !== 'CANVAS') {
314
- const parent = canvas.parentNode;
315
- if (!parent) {
316
- return;
317
- }
318
-
319
- // Create new canvas element
320
- const newCanvas = document.createElement('canvas');
321
- newCanvas.id = id;
322
- newCanvas.width = 100;
323
- newCanvas.height = 20;
324
- newCanvas.style.width = '100px';
325
- newCanvas.style.height = '20px';
326
-
327
- // Replace element with canvas
328
- parent.replaceChild(newCanvas, canvas);
329
- canvas = newCanvas;
330
- } else {
331
- canvas.width = 100;
332
- canvas.height = 20;
333
- canvas.style.width = '100px';
334
- canvas.style.height = '20px';
335
- }
336
-
337
- const ctx = canvas.getContext('2d');
338
-
339
- const chart = new Chart(ctx, {
340
- type: 'line',
341
- data: {
342
- labels: data.map((_, i) => i),
343
- datasets: [{
344
- data,
345
- borderColor: COLORS['blue-500'],
346
- backgroundColor: 'transparent',
347
- borderWidth: 1,
348
- pointRadius: 0,
349
- tension: 0.4,
350
- }],
351
- },
352
- options: {
353
- responsive: false,
354
- maintainAspectRatio: false,
355
- animation: false,
356
- events: [],
357
- onResize: null,
358
- scales: {
359
- x: { display: false },
360
- y: { display: false },
361
- },
362
- plugins: {
363
- legend: { display: false },
364
- tooltip: { enabled: false },
365
- },
366
- },
367
- });
368
-
369
- this.charts.set(id, chart);
370
- }
371
-
372
- /**
373
- * Create composite chart (only if target exists)
374
- */
375
- createCompositeChart(id, data) {
376
- let canvas = document.getElementById(id);
377
-
378
- // Only proceed if target element exists
379
- if (!canvas) {
380
- return;
381
- }
382
-
383
- // If element exists but isn't a canvas, replace it with canvas
384
- if (canvas.tagName !== 'CANVAS') {
385
- const parent = canvas.parentNode;
386
- if (!parent) {
387
- return;
388
- }
389
-
390
- // Create new canvas element
391
- const newCanvas = document.createElement('canvas');
392
- newCanvas.id = id;
393
- newCanvas.width = 100;
394
- newCanvas.height = 20;
395
- newCanvas.style.width = '100px';
396
- newCanvas.style.height = '20px';
397
-
398
- // Replace element with canvas
399
- parent.replaceChild(newCanvas, canvas);
400
- canvas = newCanvas;
401
- } else {
402
- canvas.width = 100;
403
- canvas.height = 20;
404
- canvas.style.width = '100px';
405
- canvas.style.height = '20px';
406
- }
407
-
408
- const ctx = canvas.getContext('2d');
409
-
410
- const chart = new Chart(ctx, {
411
- type: 'bar',
412
- data: {
413
- labels: data.map((_, i) => i),
414
- datasets: [
415
- {
416
- type: 'bar',
417
- data,
418
- backgroundColor: '#aaf',
419
- borderColor: '#aaf',
420
- borderWidth: 0,
421
- },
422
- {
423
- type: 'line',
424
- data,
425
- borderColor: 'red',
426
- backgroundColor: 'transparent',
427
- borderWidth: 1,
428
- pointRadius: 0,
429
- tension: 0.4,
430
- },
431
- ],
432
- },
433
- options: {
434
- responsive: false,
435
- maintainAspectRatio: false,
436
- animation: false,
437
- events: [],
438
- onResize: null,
439
- scales: {
440
- x: { display: false },
441
- y: { display: false },
442
- },
443
- plugins: {
444
- legend: { display: false },
445
- tooltip: { enabled: false },
446
- },
447
- },
448
- });
449
-
450
- this.charts.set(id, chart);
451
- }
452
-
453
- /**
454
- * Create custom sparklines for different elements (only if they exist)
455
- */
456
- createCustomSparklines() {
457
- const sparklineElements = document.querySelectorAll('.sparkline');
458
- const sparkbarElements = document.querySelectorAll('.sparkbar');
459
- const sparktriElements = document.querySelectorAll('.sparktri');
460
- const sparkdiscElements = document.querySelectorAll('.sparkdisc');
461
- const sparkbullElements = document.querySelectorAll('.sparkbull');
462
- const sparkboxElements = document.querySelectorAll('.sparkbox');
463
-
464
- // Only create if we have elements
465
- if (sparklineElements.length === 0 && sparkbarElements.length === 0 &&
466
- sparktriElements.length === 0 && sparkdiscElements.length === 0 &&
467
- sparkbullElements.length === 0 && sparkboxElements.length === 0) {
468
- return;
469
- }
470
-
471
- const values = [5, 4, 5, -2, 0, 3, -5, 6, 7, 9, 9, 5, -3, -2, 2, -4];
472
- const valuesAlt = [1, 1, 0, 1, -1, -1, 1, -1, 0, 0, 1, 1];
473
-
474
- sparklineElements.forEach((element, index) => {
475
- this.createCustomLineChart(element, values, `sparkline-${index}`);
476
- });
477
-
478
- sparkbarElements.forEach((element, index) => {
479
- this.createCustomBarChart(element, values, `sparkbar-${index}`);
480
- });
481
-
482
- sparktriElements.forEach((element, index) => {
483
- this.createTristateChart(element, valuesAlt, `sparktri-${index}`);
484
- });
485
-
486
- sparkdiscElements.forEach((element, index) => {
487
- this.createDiscreteChart(element, values, `sparkdisc-${index}`);
488
- });
489
-
490
- sparkbullElements.forEach((element, index) => {
491
- this.createBulletChart(element, values, `sparkbull-${index}`);
492
- });
493
-
494
- sparkboxElements.forEach((element, index) => {
495
- this.createBoxChart(element, values, `sparkbox-${index}`);
496
- });
497
- }
498
-
499
- /**
500
- * Create custom line chart for sparkline elements
501
- */
502
- createCustomLineChart(element, data, id) {
503
- // Create canvas if it doesn't exist
504
- let canvas = element.querySelector('canvas');
505
- if (!canvas) {
506
- canvas = document.createElement('canvas');
507
- canvas.width = 100;
508
- canvas.height = 20;
509
- canvas.style.width = '100px';
510
- canvas.style.height = '20px';
511
- element.appendChild(canvas);
512
- }
513
-
514
- const ctx = canvas.getContext('2d');
515
-
516
- const chart = new Chart(ctx, {
517
- type: 'line',
518
- data: {
519
- labels: data.map((_, i) => i),
520
- datasets: [{
521
- data,
522
- borderColor: COLORS['red-500'],
523
- backgroundColor: 'transparent',
524
- borderWidth: 2,
525
- pointRadius: 3,
526
- pointBackgroundColor: COLORS['red-500'],
527
- tension: 0.4,
528
- }],
529
- },
530
- options: {
531
- responsive: false,
532
- maintainAspectRatio: false,
533
- animation: false, // Disable animations to prevent resize triggers
534
- events: [], // Disable all events to prevent resize
535
- onResize: null, // Explicitly disable resize callback
536
- scales: {
537
- x: { display: false },
538
- y: { display: false },
539
- },
540
- plugins: {
541
- legend: { display: false },
542
- tooltip: { enabled: false }, // Disable tooltip to prevent events
543
- },
544
- },
545
- });
546
-
547
-
548
-
549
- this.charts.set(id, chart);
550
- }
551
-
552
- /**
553
- * Create custom bar chart for sparkbar elements
554
- */
555
- createCustomBarChart(element, data, id) {
556
- // Create canvas if it doesn't exist
557
- let canvas = element.querySelector('canvas');
558
- if (!canvas) {
559
- canvas = document.createElement('canvas');
560
- canvas.width = 100;
561
- canvas.height = 20;
562
- canvas.style.width = '100px';
563
- canvas.style.height = '20px';
564
- element.appendChild(canvas);
565
- }
566
-
567
- const ctx = canvas.getContext('2d');
568
-
569
- const chart = new Chart(ctx, {
570
- type: 'bar',
571
- data: {
572
- labels: data.map((_, i) => i),
573
- datasets: [{
574
- data,
575
- backgroundColor: data.map(val => val < 0 ? COLORS['deep-purple-500'] : '#39f'),
576
- borderColor: data.map(val => val < 0 ? COLORS['deep-purple-500'] : '#39f'),
577
- borderWidth: 1,
578
- barPercentage: 0.8,
579
- }],
580
- },
581
- options: {
582
- responsive: false,
583
- maintainAspectRatio: false,
584
- scales: {
585
- x: { display: false },
586
- y: { display: false },
587
- },
588
- plugins: {
589
- legend: { display: false },
590
- tooltip: {
591
- enabled: true,
592
- callbacks: {
593
- label: (context) => `${context.parsed.y}°Celsius`,
594
- },
595
- },
596
- },
597
- },
598
- });
599
-
600
- this.charts.set(id, chart);
601
- }
602
-
603
- /**
604
- * Setup resize handler for charts
605
- */
606
- setupResizeHandler() {
607
- // Setup responsive resize for large charts only
608
- window.addEventListener('resize', () => {
609
- this.debounceResize();
610
- });
611
-
612
- // Listen for sidebar toggle events
613
- window.addEventListener('sidebar:toggle', () => {
614
- this.debounceResize();
615
- });
616
- }
617
-
618
- /**
619
- * Debounced resize handler
620
- */
621
- debounceResize() {
622
- if (this.debounceTimer) {
623
- clearTimeout(this.debounceTimer);
624
- }
625
- this.debounceTimer = setTimeout(() => {
626
- this.redrawLargeChartsOnly();
627
- }, 150);
628
- }
629
-
630
- /**
631
- * Redraw only large charts, not sparklines
632
- */
633
- redrawLargeChartsOnly() {
634
- const largeChartIds = [
635
- 'line-chart', 'area-chart', 'scatter-chart', 'bar-chart',
636
- 'doughnut-chart', 'polar-chart', 'radar-chart', 'mixed-chart', 'bubble-chart',
637
- ];
638
-
639
- largeChartIds.forEach(id => {
640
- const chart = this.charts.get(id);
641
- if (chart && chart.options.responsive) {
642
- chart.resize();
643
- }
644
- });
645
- }
646
-
647
- /**
648
- * Redraw all charts (used sparingly)
649
- */
650
- redrawCharts() {
651
- this.charts.forEach((chart) => {
652
- if (chart.options.responsive) {
653
- chart.resize();
654
- }
655
- });
656
- }
657
-
658
- /**
659
- * Update chart data
660
- */
661
- updateChart(id, newData) {
662
- const chart = this.charts.get(id);
663
- if (chart) {
664
- chart.data.datasets[0].data = newData;
665
- chart.update();
666
- }
667
- }
668
-
669
- /**
670
- * Create charts for the charts.html page
671
- */
672
- createChartsPageCharts() {
673
- // Line Chart
674
- this.createLargeChart('line-chart', 'line', {
675
- labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
676
- datasets: [{
677
- label: 'Dataset 1',
678
- data: [65, 59, 80, 81, 56, 55, 40],
679
- borderColor: 'rgb(75, 192, 192)',
680
- backgroundColor: 'rgba(75, 192, 192, 0.2)',
681
- tension: 0.4,
682
- }],
683
- });
684
-
685
- // Area Chart
686
- this.createLargeChart('area-chart', 'line', {
687
- labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
688
- datasets: [{
689
- label: 'Dataset 1',
690
- data: [65, 59, 80, 81, 56, 55, 40],
691
- borderColor: 'rgb(54, 162, 235)',
692
- backgroundColor: 'rgba(54, 162, 235, 0.4)',
693
- fill: true,
694
- tension: 0.4,
695
- }],
696
- });
697
-
698
- // Scatter Chart with more data points
699
- this.createLargeChart('scatter-chart', 'scatter', {
700
- datasets: [{
701
- label: 'Dataset 1',
702
- data: [
703
- {x: -15, y: 8}, {x: -12, y: 12}, {x: -8, y: 3}, {x: -5, y: 15},
704
- {x: -2, y: 7}, {x: 0, y: 10}, {x: 3, y: 18}, {x: 6, y: 5},
705
- {x: 9, y: 22}, {x: 12, y: 8}, {x: 15, y: 14}, {x: 18, y: 19},
706
- {x: -10, y: 0}, {x: 10, y: 5}, {x: 0.5, y: 5.5}, {x: 7, y: 12},
707
- {x: -7, y: 17}, {x: 4, y: 9}, {x: 11, y: 16}, {x: -3, y: 11},
708
- ],
709
- backgroundColor: 'rgba(255, 99, 132, 0.7)',
710
- borderColor: 'rgb(255, 99, 132)',
711
- borderWidth: 1,
712
- }, {
713
- label: 'Dataset 2',
714
- data: [
715
- {x: -13, y: 4}, {x: -9, y: 8}, {x: -6, y: 13}, {x: -1, y: 6},
716
- {x: 2, y: 11}, {x: 5, y: 15}, {x: 8, y: 2}, {x: 13, y: 17},
717
- {x: 16, y: 9}, {x: -4, y: 14}, {x: 1, y: 20}, {x: 14, y: 4},
718
- ],
719
- backgroundColor: 'rgba(54, 162, 235, 0.7)',
720
- borderColor: 'rgb(54, 162, 235)',
721
- borderWidth: 1,
722
- }],
723
- });
724
-
725
- // Bar Chart
726
- this.createLargeChart('bar-chart', 'bar', {
727
- labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
728
- datasets: [{
729
- label: '# of Votes',
730
- data: [12, 19, 3, 5, 2, 3],
731
- backgroundColor: [
732
- 'rgba(255, 99, 132, 0.6)',
733
- 'rgba(54, 162, 235, 0.6)',
734
- 'rgba(255, 205, 86, 0.6)',
735
- 'rgba(75, 192, 192, 0.6)',
736
- 'rgba(153, 102, 255, 0.6)',
737
- 'rgba(255, 159, 64, 0.6)',
738
- ],
739
- borderColor: [
740
- 'rgba(255, 99, 132, 1)',
741
- 'rgba(54, 162, 235, 1)',
742
- 'rgba(255, 205, 86, 1)',
743
- 'rgba(75, 192, 192, 1)',
744
- 'rgba(153, 102, 255, 1)',
745
- 'rgba(255, 159, 64, 1)',
746
- ],
747
- borderWidth: 1,
748
- }],
749
- });
750
-
751
- // Doughnut Chart
752
- this.createLargeChart('doughnut-chart', 'doughnut', {
753
- labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
754
- datasets: [{
755
- label: 'My First Dataset',
756
- data: [300, 50, 100, 75, 120, 60],
757
- backgroundColor: [
758
- 'rgba(255, 99, 132, 0.8)',
759
- 'rgba(54, 162, 235, 0.8)',
760
- 'rgba(255, 205, 86, 0.8)',
761
- 'rgba(75, 192, 192, 0.8)',
762
- 'rgba(153, 102, 255, 0.8)',
763
- 'rgba(255, 159, 64, 0.8)',
764
- ],
765
- borderColor: [
766
- 'rgba(255, 99, 132, 1)',
767
- 'rgba(54, 162, 235, 1)',
768
- 'rgba(255, 205, 86, 1)',
769
- 'rgba(75, 192, 192, 1)',
770
- 'rgba(153, 102, 255, 1)',
771
- 'rgba(255, 159, 64, 1)',
772
- ],
773
- borderWidth: 2,
774
- hoverOffset: 10,
775
- }],
776
- });
777
-
778
- // Polar Area Chart
779
- this.createLargeChart('polar-chart', 'polarArea', {
780
- labels: ['Red', 'Green', 'Yellow', 'Grey', 'Blue'],
781
- datasets: [{
782
- label: 'My First Dataset',
783
- data: [11, 16, 7, 3, 14],
784
- backgroundColor: [
785
- 'rgba(255, 99, 132, 0.7)',
786
- 'rgba(75, 192, 192, 0.7)',
787
- 'rgba(255, 205, 86, 0.7)',
788
- 'rgba(201, 203, 207, 0.7)',
789
- 'rgba(54, 162, 235, 0.7)',
790
- ],
791
- borderColor: [
792
- 'rgb(255, 99, 132)',
793
- 'rgb(75, 192, 192)',
794
- 'rgb(255, 205, 86)',
795
- 'rgb(201, 203, 207)',
796
- 'rgb(54, 162, 235)',
797
- ],
798
- borderWidth: 2,
799
- }],
800
- });
801
-
802
- // Radar Chart
803
- this.createLargeChart('radar-chart', 'radar', {
804
- labels: ['Speed', 'Reliability', 'Comfort', 'Safety', 'Efficiency', 'Innovation'],
805
- datasets: [{
806
- label: 'Product A',
807
- data: [65, 59, 90, 81, 56, 55],
808
- fill: true,
809
- backgroundColor: 'rgba(54, 162, 235, 0.2)',
810
- borderColor: 'rgb(54, 162, 235)',
811
- borderWidth: 2,
812
- pointBackgroundColor: 'rgb(54, 162, 235)',
813
- pointBorderColor: '#fff',
814
- pointHoverBackgroundColor: '#fff',
815
- pointHoverBorderColor: 'rgb(54, 162, 235)',
816
- }, {
817
- label: 'Product B',
818
- data: [28, 48, 40, 95, 86, 27],
819
- fill: true,
820
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
821
- borderColor: 'rgb(255, 99, 132)',
822
- borderWidth: 2,
823
- pointBackgroundColor: 'rgb(255, 99, 132)',
824
- pointBorderColor: '#fff',
825
- pointHoverBackgroundColor: '#fff',
826
- pointHoverBorderColor: 'rgb(255, 99, 132)',
827
- }],
828
- });
829
-
830
- // Mixed Chart (Bar + Line)
831
- this.createLargeChart('mixed-chart', 'bar', {
832
- labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
833
- datasets: [{
834
- type: 'bar',
835
- label: 'Sales',
836
- data: [12, 19, 3, 5, 2, 3],
837
- backgroundColor: 'rgba(54, 162, 235, 0.7)',
838
- borderColor: 'rgb(54, 162, 235)',
839
- borderWidth: 1,
840
- }, {
841
- type: 'line',
842
- label: 'Revenue',
843
- data: [18, 25, 8, 15, 12, 18],
844
- fill: false,
845
- borderColor: 'rgb(255, 99, 132)',
846
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
847
- borderWidth: 3,
848
- tension: 0.4,
849
- pointRadius: 5,
850
- pointHoverRadius: 7,
851
- }],
852
- });
853
-
854
- // Bubble Chart
855
- this.createLargeChart('bubble-chart', 'bubble', {
856
- datasets: [{
857
- label: 'First Dataset',
858
- data: [
859
- {x: 20, y: 30, r: 15},
860
- {x: 40, y: 10, r: 10},
861
- {x: 30, y: 40, r: 20},
862
- {x: 50, y: 35, r: 12},
863
- {x: 10, y: 50, r: 8},
864
- {x: 60, y: 20, r: 18},
865
- {x: 25, y: 25, r: 14},
866
- ],
867
- backgroundColor: 'rgba(54, 162, 235, 0.6)',
868
- borderColor: 'rgb(54, 162, 235)',
869
- borderWidth: 2,
870
- }, {
871
- label: 'Second Dataset',
872
- data: [
873
- {x: 15, y: 45, r: 12},
874
- {x: 35, y: 15, r: 16},
875
- {x: 45, y: 25, r: 9},
876
- {x: 55, y: 45, r: 14},
877
- {x: 25, y: 35, r: 11},
878
- ],
879
- backgroundColor: 'rgba(255, 99, 132, 0.6)',
880
- borderColor: 'rgb(255, 99, 132)',
881
- borderWidth: 2,
882
- }],
883
- });
884
- }
885
-
886
- /**
887
- * Create large chart for charts page
888
- */
889
- createLargeChart(id, type, data) {
890
- const canvas = document.getElementById(id);
891
- if (!canvas) return;
892
-
893
- const ctx = canvas.getContext('2d');
894
-
895
- // Define chart-specific options
896
- const chartOptions = this.getChartOptions(type);
897
-
898
- const chart = new Chart(ctx, {
899
- type,
900
- data,
901
- options: chartOptions,
902
- });
903
-
904
- this.charts.set(id, chart);
905
- }
906
-
907
- /**
908
- * Get chart-specific options based on chart type
909
- */
910
- getChartOptions(type) {
911
- const baseOptions = {
912
- responsive: true,
913
- maintainAspectRatio: false,
914
- plugins: {
915
- legend: {
916
- display: true,
917
- position: 'top',
918
- labels: {
919
- padding: 20,
920
- font: {
921
- size: 12,
922
- weight: '600',
923
- },
924
- },
925
- },
926
- tooltip: {
927
- enabled: true,
928
- cornerRadius: 8,
929
- displayColors: true,
930
- },
931
- },
932
- };
933
-
934
- // Chart type specific configurations
935
- switch (type) {
936
- case 'doughnut':
937
- case 'pie':
938
- return {
939
- ...baseOptions,
940
- plugins: {
941
- ...baseOptions.plugins,
942
- legend: {
943
- ...baseOptions.plugins.legend,
944
- position: 'right',
945
- },
946
- },
947
- interaction: {
948
- intersect: false,
949
- },
950
- };
951
-
952
- case 'polarArea':
953
- return {
954
- ...baseOptions,
955
- scales: {
956
- r: {
957
- pointLabels: {
958
- display: true,
959
- centerPointLabels: true,
960
- font: {
961
- size: 10,
962
- },
963
- },
964
- grid: {
965
- },
966
- },
967
- },
968
- };
969
-
970
- case 'radar':
971
- return {
972
- ...baseOptions,
973
- scales: {
974
- r: {
975
- angleLines: {
976
- display: true,
977
- },
978
- grid: {
979
- },
980
- pointLabels: {
981
- font: {
982
- size: 11,
983
- },
984
- },
985
- ticks: {
986
- display: true,
987
- font: {
988
- size: 10,
989
- },
990
- },
991
- },
992
- },
993
- };
994
-
995
- case 'bubble':
996
- return {
997
- ...baseOptions,
998
- scales: {
999
- x: {
1000
- type: 'linear',
1001
- position: 'bottom',
1002
- grid: {
1003
- borderDash: [5, 5],
1004
- },
1005
- ticks: {
1006
- font: {
1007
- size: 11,
1008
- },
1009
- },
1010
- },
1011
- y: {
1012
- beginAtZero: true,
1013
- grid: {
1014
- borderDash: [5, 5],
1015
- },
1016
- ticks: {
1017
- font: {
1018
- size: 11,
1019
- },
1020
- },
1021
- },
1022
- },
1023
- plugins: {
1024
- ...baseOptions.plugins,
1025
- tooltip: {
1026
- ...baseOptions.plugins.tooltip,
1027
- callbacks: {
1028
- label(context) {
1029
- return `${context.dataset.label}: (${context.parsed.x}, ${context.parsed.y}), Size: ${context.parsed._custom}`;
1030
- },
1031
- },
1032
- },
1033
- },
1034
- };
1035
-
1036
- case 'scatter':
1037
- return {
1038
- ...baseOptions,
1039
- scales: {
1040
- x: {
1041
- type: 'linear',
1042
- position: 'bottom',
1043
- grid: {
1044
- borderDash: [5, 5],
1045
- },
1046
- ticks: {
1047
- font: {
1048
- size: 11,
1049
- },
1050
- },
1051
- },
1052
- y: {
1053
- grid: {
1054
- borderDash: [5, 5],
1055
- },
1056
- ticks: {
1057
- font: {
1058
- size: 11,
1059
- },
1060
- },
1061
- },
1062
- },
1063
- };
1064
-
1065
- default:
1066
- // For line, bar, area, mixed charts
1067
- return {
1068
- ...baseOptions,
1069
- scales: {
1070
- x: {
1071
- grid: {
1072
- borderDash: [5, 5],
1073
- },
1074
- ticks: {
1075
- font: {
1076
- size: 11,
1077
- },
1078
- },
1079
- },
1080
- y: {
1081
- beginAtZero: true,
1082
- grid: {
1083
- borderDash: [5, 5],
1084
- },
1085
- ticks: {
1086
- font: {
1087
- size: 11,
1088
- },
1089
- },
1090
- },
1091
- },
1092
- };
1093
- }
1094
- }
1095
-
1096
- /**
1097
- * Create tristate chart (for .sparktri elements)
1098
- */
1099
- createTristateChart(element, data, id) {
1100
- let canvas = element.querySelector('canvas');
1101
- if (!canvas) {
1102
- canvas = document.createElement('canvas');
1103
- canvas.width = 100;
1104
- canvas.height = 20;
1105
- canvas.style.width = '100px';
1106
- canvas.style.height = '20px';
1107
- element.appendChild(canvas);
1108
- }
1109
-
1110
- const ctx = canvas.getContext('2d');
1111
-
1112
- const chart = new Chart(ctx, {
1113
- type: 'bar',
1114
- data: {
1115
- labels: data.map((_, i) => i),
1116
- datasets: [{
1117
- data: data.map(val => Math.abs(val)),
1118
- backgroundColor: data.map(val => {
1119
- if (val > 0) return COLORS['light-blue-500'];
1120
- if (val < 0) return '#f90';
1121
- return '#000';
1122
- }),
1123
- borderColor: data.map(val => {
1124
- if (val > 0) return COLORS['light-blue-500'];
1125
- if (val < 0) return '#f90';
1126
- return '#000';
1127
- }),
1128
- borderWidth: 1,
1129
- barPercentage: 0.8,
1130
- }],
1131
- },
1132
- options: {
1133
- responsive: false,
1134
- maintainAspectRatio: false,
1135
- scales: {
1136
- x: { display: false },
1137
- y: { display: false },
1138
- },
1139
- plugins: {
1140
- legend: { display: false },
1141
- tooltip: {
1142
- enabled: true,
1143
- callbacks: {
1144
- label: (context) => `${context.parsed.y}°Celsius`,
1145
- },
1146
- },
1147
- },
1148
- },
1149
- });
1150
-
1151
- this.charts.set(id, chart);
1152
- }
1153
-
1154
- /**
1155
- * Create discrete chart (for .sparkdisc elements)
1156
- */
1157
- createDiscreteChart(element, data, id) {
1158
- let canvas = element.querySelector('canvas');
1159
- if (!canvas) {
1160
- canvas = document.createElement('canvas');
1161
- canvas.width = 100;
1162
- canvas.height = 20;
1163
- canvas.style.width = '100px';
1164
- canvas.style.height = '20px';
1165
- element.appendChild(canvas);
1166
- }
1167
-
1168
- const ctx = canvas.getContext('2d');
1169
-
1170
- const chart = new Chart(ctx, {
1171
- type: 'scatter',
1172
- data: {
1173
- datasets: [{
1174
- data: data.map((val, index) => ({x: index, y: val})),
1175
- backgroundColor: '#9f0',
1176
- borderColor: '#9f0',
1177
- pointRadius: 2,
1178
- showLine: false,
1179
- }],
1180
- },
1181
- options: {
1182
- responsive: false,
1183
- maintainAspectRatio: false,
1184
- scales: {
1185
- x: { display: false },
1186
- y: { display: false },
1187
- },
1188
- plugins: {
1189
- legend: { display: false },
1190
- tooltip: {
1191
- enabled: true,
1192
- callbacks: {
1193
- label: (context) => `${context.parsed.y}°Celsius`,
1194
- },
1195
- },
1196
- },
1197
- },
1198
- });
1199
-
1200
- this.charts.set(id, chart);
1201
- }
1202
-
1203
- /**
1204
- * Create bullet chart (for .sparkbull elements)
1205
- */
1206
- createBulletChart(element, data, id) {
1207
- let canvas = element.querySelector('canvas');
1208
- if (!canvas) {
1209
- canvas = document.createElement('canvas');
1210
- canvas.width = 100;
1211
- canvas.height = 20;
1212
- canvas.style.width = '100px';
1213
- canvas.style.height = '20px';
1214
- element.appendChild(canvas);
1215
- }
1216
-
1217
- const ctx = canvas.getContext('2d');
1218
-
1219
- // Simplified bullet chart as horizontal bar
1220
- const chart = new Chart(ctx, {
1221
- type: 'bar',
1222
- data: {
1223
- labels: [''],
1224
- datasets: [{
1225
- data: [Math.max(...data)],
1226
- backgroundColor: COLORS['amber-500'],
1227
- borderColor: COLORS['amber-500'],
1228
- borderWidth: 1,
1229
- barPercentage: 0.6,
1230
- }],
1231
- },
1232
- options: {
1233
- responsive: false,
1234
- maintainAspectRatio: false,
1235
- indexAxis: 'y',
1236
- scales: {
1237
- x: { display: false },
1238
- y: { display: false },
1239
- },
1240
- plugins: {
1241
- legend: { display: false },
1242
- tooltip: {
1243
- enabled: true,
1244
- callbacks: {
1245
- label: (context) => `${context.parsed.x}°Celsius`,
1246
- },
1247
- },
1248
- },
1249
- },
1250
- });
1251
-
1252
- this.charts.set(id, chart);
1253
- }
1254
-
1255
- /**
1256
- * Create box chart (for .sparkbox elements)
1257
- */
1258
- createBoxChart(element, data, id) {
1259
- let canvas = element.querySelector('canvas');
1260
- if (!canvas) {
1261
- canvas = document.createElement('canvas');
1262
- canvas.width = 100;
1263
- canvas.height = 20;
1264
- canvas.style.width = '100px';
1265
- canvas.style.height = '20px';
1266
- element.appendChild(canvas);
1267
- }
1268
-
1269
- const ctx = canvas.getContext('2d');
1270
-
1271
- // Box plot simplified as bar chart showing quartiles
1272
- const sortedData = [...data].sort((a, b) => a - b);
1273
- const q1 = sortedData[Math.floor(sortedData.length * 0.25)];
1274
- const median = sortedData[Math.floor(sortedData.length * 0.5)];
1275
- const q3 = sortedData[Math.floor(sortedData.length * 0.75)];
1276
-
1277
- const chart = new Chart(ctx, {
1278
- type: 'bar',
1279
- data: {
1280
- labels: ['Q1', 'Med', 'Q3'],
1281
- datasets: [{
1282
- data: [q1, median, q3],
1283
- backgroundColor: '#9f0',
1284
- borderColor: '#9f0',
1285
- borderWidth: 1,
1286
- barPercentage: 0.8,
1287
- }],
1288
- },
1289
- options: {
1290
- responsive: false,
1291
- maintainAspectRatio: false,
1292
- scales: {
1293
- x: { display: false },
1294
- y: { display: false },
1295
- },
1296
- plugins: {
1297
- legend: { display: false },
1298
- tooltip: {
1299
- enabled: true,
1300
- callbacks: {
1301
- label: (context) => `${context.parsed.y}°Celsius`,
1302
- },
1303
- },
1304
- },
1305
- },
1306
- });
1307
-
1308
- this.charts.set(id, chart);
1309
- }
1310
-
1311
- /**
1312
- * Create Easy Pie Charts (replaces jQuery Easy Pie Chart)
1313
- */
1314
- createEasyPieCharts() {
1315
- const easyPieElements = document.querySelectorAll('.easy-pie-chart');
1316
-
1317
- easyPieElements.forEach((element, index) => {
1318
- const size = parseInt(element.dataset.size) || 80;
1319
- const percent = parseInt(element.dataset.percent) || 0;
1320
- const barColor = element.dataset.barColor || '#f44336';
1321
-
1322
- // Create canvas for the pie chart
1323
- let canvas = element.querySelector('canvas');
1324
- if (!canvas) {
1325
- canvas = document.createElement('canvas');
1326
- canvas.width = size;
1327
- canvas.height = size;
1328
- canvas.style.width = `${size}px`;
1329
- canvas.style.height = `${size}px`;
1330
- element.appendChild(canvas);
1331
- }
1332
-
1333
- // Create percentage display
1334
- const percentDisplay = element.querySelector('span');
1335
- if (percentDisplay) {
1336
- percentDisplay.textContent = `${percent}%`;
1337
- percentDisplay.style.position = 'absolute';
1338
- percentDisplay.style.top = '50%';
1339
- percentDisplay.style.left = '50%';
1340
- percentDisplay.style.transform = 'translate(-50%, -50%)';
1341
- percentDisplay.style.fontSize = '14px';
1342
- percentDisplay.style.fontWeight = 'bold';
1343
- }
1344
-
1345
- // Set element position to relative for absolute positioning of text
1346
- element.style.position = 'relative';
1347
- element.style.display = 'inline-block';
1348
-
1349
- const ctx = canvas.getContext('2d');
1350
-
1351
- const chart = new Chart(ctx, {
1352
- type: 'doughnut',
1353
- data: {
1354
- datasets: [{
1355
- data: [percent, 100 - percent],
1356
- backgroundColor: [barColor, '#f0f0f0'],
1357
- borderWidth: 0,
1358
- cutout: '70%',
1359
- }],
1360
- },
1361
- options: {
1362
- responsive: false,
1363
- maintainAspectRatio: false,
1364
- plugins: {
1365
- legend: { display: false },
1366
- tooltip: { enabled: false },
1367
- },
1368
- },
1369
- });
1370
-
1371
- this.charts.set(`easy-pie-${index}`, chart);
1372
- });
1373
- }
1374
-
1375
- /**
1376
- * Destroy all charts
1377
- */
1378
- destroy() {
1379
- this.charts.forEach(chart => {
1380
- chart.destroy();
1381
- });
1382
- this.charts.clear();
1383
-
1384
- if (this.debounceTimer) {
1385
- clearTimeout(this.debounceTimer);
1386
- }
1387
- }
1388
- }
1389
-
1390
- export default ChartComponent;