evui 3.3.10 → 3.3.13

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 (30) hide show
  1. package/dist/evui.common.js +2439 -1032
  2. package/dist/evui.common.js.map +1 -1
  3. package/dist/evui.umd.js +2439 -1032
  4. package/dist/evui.umd.js.map +1 -1
  5. package/dist/evui.umd.min.js +1 -1
  6. package/dist/evui.umd.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/components/chart/chart.core.js +65 -24
  9. package/src/components/chart/element/element.heatmap.js +195 -51
  10. package/src/components/chart/element/element.line.js +22 -9
  11. package/src/components/chart/element/element.scatter.js +26 -9
  12. package/src/components/chart/element/element.tip.js +103 -83
  13. package/src/components/chart/helpers/helpers.constant.js +13 -11
  14. package/src/components/chart/model/model.series.js +1 -1
  15. package/src/components/chart/model/model.store.js +19 -74
  16. package/src/components/chart/plugins/plugins.interaction.js +15 -4
  17. package/src/components/chart/plugins/plugins.legend.js +6 -3
  18. package/src/components/chart/plugins/plugins.pie.js +17 -0
  19. package/src/components/chart/plugins/plugins.tooltip.js +205 -32
  20. package/src/components/chart/scale/scale.js +10 -11
  21. package/src/components/chart/scale/scale.step.js +38 -3
  22. package/src/components/chart/scale/scale.time.category.js +35 -3
  23. package/src/components/chart/uses.js +12 -0
  24. package/src/components/grid/Grid.vue +109 -36
  25. package/src/components/grid/grid.summary.vue +235 -0
  26. package/src/components/grid/style/grid.scss +0 -14
  27. package/src/components/grid/uses.js +55 -46
  28. package/src/components/treeGrid/TreeGrid.vue +269 -36
  29. package/src/components/treeGrid/TreeGridNode.vue +8 -9
  30. package/src/components/treeGrid/uses.js +152 -37
@@ -1,5 +1,6 @@
1
1
  import { numberWithComma } from '@/common/utils';
2
2
  import debounce from '@/common/utils.debounce';
3
+ import dayjs from 'dayjs';
3
4
  import Canvas from '../helpers/helpers.canvas';
4
5
  import Util from '../helpers/helpers.util';
5
6
 
@@ -310,13 +311,6 @@ const modules = {
310
311
  value,
311
312
  name,
312
313
  });
313
- } else if (this.options.type === 'heatMap') {
314
- formattedTxt = opt.formatter({
315
- x: this.options.horizontal ? hitItem.y : hitItem.x,
316
- y: this.options.horizontal ? hitItem.x : hitItem.y,
317
- name,
318
- value,
319
- });
320
314
  } else {
321
315
  formattedTxt = opt.formatter({
322
316
  x: this.options.horizontal ? value : hitItem.x,
@@ -342,18 +336,7 @@ const modules = {
342
336
 
343
337
  ctx.restore();
344
338
 
345
- // set tooltipDOM's style
346
- this.tooltipDOM.style.overflowY = 'hidden';
347
- this.tooltipDOM.style.backgroundColor = opt.backgroundColor;
348
- this.tooltipDOM.style.border = `1px solid ${opt.borderColor}`;
349
- this.tooltipDOM.style.color = opt.fontColor;
350
-
351
- if (opt.useShadow) {
352
- const shadowColor = `rgba(0, 0, 0, ${opt.shadowOpacity})`;
353
- this.tooltipDOM.style.boxShadow = `2px 2px 2px ${shadowColor}`;
354
- }
355
-
356
- this.tooltipDOM.style.display = 'block';
339
+ this.setTooltipDOMStyle(opt);
357
340
  },
358
341
 
359
342
  /**
@@ -373,12 +356,13 @@ const modules = {
373
356
  const boxPadding = { t: 8, b: 8, r: 20, l: 16 };
374
357
  const isHorizontal = this.options.horizontal;
375
358
  const opt = this.options.tooltip;
359
+ let xValue = '';
360
+ let yValue = '';
376
361
 
377
362
  // draw tooltip Title(axis label) and add style class for wrap line about too much long label.
378
- if (this.axesX.length && this.axesY.length) {
379
- this.tooltipHeaderDOM.textContent = this.options.horizontal
380
- ? `${this.axesY[hitAxis.y].getLabelFormat(hitItem.y)} / ${this.axesX[hitAxis.x].getLabelFormat(hitItem.x)}`
381
- : `${this.axesX[hitAxis.x].getLabelFormat(hitItem.x)} / ${this.axesY[hitAxis.y].getLabelFormat(hitItem.y)}`;
363
+ if (this.axesX.length) {
364
+ xValue = this.axesX[hitAxis.x].getLabelFormat(hitItem.x);
365
+ this.tooltipHeaderDOM.textContent = xValue;
382
366
  }
383
367
 
384
368
  if (opt.textOverflow) {
@@ -412,23 +396,212 @@ const modules = {
412
396
  ctx.fillStyle = hitColor;
413
397
  }
414
398
 
415
- // 1. Draw series color
399
+ // 1. Draw value color
416
400
  ctx.fillRect(itemX - 4, itemY - 12, 12, 12);
417
401
  ctx.fillStyle = opt.fontColor;
418
402
 
419
- // 2. Draw series name
403
+ // 2. Draw value y names
420
404
  ctx.textBaseline = 'Bottom';
421
- ctx.fillText(itemValue, itemX + COLOR_MARGIN, itemY);
405
+ if (this.axesY.length) {
406
+ yValue = this.axesY[hitAxis.y].getLabelFormat(hitItem.y);
407
+ ctx.fillText(yValue, itemX + COLOR_MARGIN, itemY);
408
+ }
409
+
410
+ // 3. Draw value
411
+ let formattedTxt;
412
+ if (opt.formatter) {
413
+ formattedTxt = opt.formatter({
414
+ x: xValue,
415
+ y: yValue,
416
+ value: itemValue,
417
+ });
418
+ }
419
+
420
+ if ((!opt.formatter || typeof formattedTxt !== 'string') && itemValue !== 'error') {
421
+ formattedTxt = numberWithComma(itemValue);
422
+ } else {
423
+ formattedTxt = itemValue;
424
+ }
425
+
426
+ ctx.textAlign = 'right';
427
+ ctx.fillText(formattedTxt, this.tooltipDOM.offsetWidth - boxPadding.r, itemY);
422
428
  ctx.closePath();
423
429
 
424
- // set tooltipDOM's style
430
+ this.setTooltipDOMStyle(opt);
431
+ },
432
+
433
+ /**
434
+ *
435
+ * @param hitInfo
436
+ * @param context
437
+ */
438
+ drawTooltipForScatter(hitInfo, context) {
439
+ const ctx = context;
440
+ const items = hitInfo.items;
441
+ const [, maxValue] = hitInfo.maxTip;
442
+ const seriesKeys = this.alignSeriesList(Object.keys(items));
443
+ const boxPadding = { t: 8, b: 8, r: 8, l: 8 };
444
+ const opt = this.options.tooltip;
445
+ const xAxisOpt = this.options.axesX[0];
446
+
447
+ let x = 2;
448
+ let y = 2;
449
+
450
+ x += Util.aliasPixel(x);
451
+ y += Util.aliasPixel(y);
452
+
453
+ ctx.save();
454
+ ctx.scale(this.pixelRatio, this.pixelRatio);
455
+
456
+ if (this.tooltipBodyDOM.style.overflowY === 'auto') {
457
+ boxPadding.r += SCROLL_WIDTH;
458
+ }
459
+
460
+ x += boxPadding.l;
461
+ y += boxPadding.t;
462
+
463
+ ctx.font = FONT_STYLE;
464
+
465
+ const seriesList = [];
466
+ seriesKeys.forEach((seriesName) => {
467
+ seriesList.push({
468
+ data: items[seriesName].data,
469
+ color: items[seriesName].color,
470
+ name: items[seriesName].name,
471
+ });
472
+ });
473
+
474
+ if (opt.sortByValue) {
475
+ seriesList.sort((a, b) => {
476
+ let prev = a.data.o;
477
+ let next = b.data.o;
478
+
479
+ if (prev === null || prev === undefined) {
480
+ prev = a.data.y;
481
+ }
482
+
483
+ if (next === null || next === undefined) {
484
+ next = b.data.y;
485
+ }
486
+
487
+ return next - prev;
488
+ });
489
+ }
490
+
491
+ let textLineCnt = 1;
492
+ for (let ix = 0; ix < seriesList.length; ix++) {
493
+ const gdata = seriesList[ix].data;
494
+ const color = seriesList[ix].color;
495
+ const name = seriesList[ix].name;
496
+ const xValue = gdata.x;
497
+ let yValue;
498
+ if (gdata.o === null) {
499
+ yValue = gdata.y;
500
+ } else if (!isNaN(gdata.o)) {
501
+ yValue = gdata.o;
502
+ }
503
+
504
+ let itemX = x + 4;
505
+ let itemY = y + (textLineCnt * TEXT_HEIGHT);
506
+ itemX += Util.aliasPixel(itemX);
507
+ itemY += Util.aliasPixel(itemY);
508
+
509
+ ctx.beginPath();
510
+
511
+ if (typeof color !== 'string') {
512
+ ctx.fillStyle = Canvas.createGradient(
513
+ ctx,
514
+ false,
515
+ { x: itemX - 4, y: itemY, w: 12, h: -12 },
516
+ color,
517
+ );
518
+ } else {
519
+ ctx.fillStyle = color;
520
+ }
521
+
522
+ // 1. Draw series color
523
+ ctx.fillRect(itemX - 4, itemY - 12, 12, 12);
524
+ ctx.fillStyle = opt.fontColor;
525
+
526
+ // 2. Draw series name
527
+ ctx.textBaseline = 'Bottom';
528
+ const seriesNameSpaceWidth = opt.maxWidth - Math.round(ctx.measureText(maxValue).width)
529
+ - boxPadding.l - boxPadding.r - COLOR_MARGIN - VALUE_MARGIN;
530
+ const xPos = itemX + COLOR_MARGIN;
531
+ const yPos = itemY;
532
+
533
+ if (seriesNameSpaceWidth > ctx.measureText(name).width) { // draw normally
534
+ ctx.fillText(name, xPos, yPos);
535
+ } else if (opt.textOverflow === 'wrap') { // draw with wrap
536
+ let line = '';
537
+ let yPosWithWrap = yPos;
538
+
539
+ for (let jx = 0; jx < name.length; jx++) {
540
+ const char = name[jx];
541
+ const temp = `${line}${char}`;
542
+
543
+ if (ctx.measureText(temp).width > seriesNameSpaceWidth) {
544
+ ctx.fillText(line, xPos, yPosWithWrap);
545
+ line = char;
546
+ textLineCnt += 1;
547
+ yPosWithWrap += TEXT_HEIGHT;
548
+ } else {
549
+ line = temp;
550
+ }
551
+ }
552
+ ctx.fillText(line, xPos, yPosWithWrap);
553
+ } else { // draw with ellipsis
554
+ const shortSeriesName = Util.truncateLabelWithEllipsis(name, seriesNameSpaceWidth, ctx);
555
+ ctx.fillText(shortSeriesName, xPos, yPos);
556
+ }
557
+
558
+ ctx.save();
559
+
560
+ // 3. Draw value
561
+ let formattedTxt;
562
+ if (opt.formatter) {
563
+ formattedTxt = opt.formatter({
564
+ x: xValue,
565
+ y: yValue,
566
+ name,
567
+ });
568
+ }
569
+
570
+ if (!opt.formatter || typeof formattedTxt !== 'string') {
571
+ const formattedXValue = xAxisOpt.type === 'time'
572
+ ? dayjs(xValue).format(xAxisOpt.timeFormat)
573
+ : numberWithComma(xValue);
574
+ const formattedYValue = numberWithComma(yValue);
575
+ formattedTxt = `${formattedXValue}, ${formattedYValue}`;
576
+ }
577
+
578
+ ctx.textAlign = 'right';
579
+ ctx.fillText(formattedTxt, this.tooltipDOM.offsetWidth - boxPadding.r, itemY);
580
+ ctx.restore();
581
+ ctx.closePath();
582
+
583
+ // 4. add lineSpacing
584
+ y += LINE_SPACING;
585
+ textLineCnt += 1;
586
+ }
587
+
588
+ ctx.restore();
589
+
590
+ this.setTooltipDOMStyle(opt);
591
+ },
592
+
593
+ /**
594
+ * set style properties on tooltip DOM
595
+ * @param tooltipOptions
596
+ */
597
+ setTooltipDOMStyle(tooltipOptions) {
425
598
  this.tooltipDOM.style.overflowY = 'hidden';
426
- this.tooltipDOM.style.backgroundColor = opt.backgroundColor;
427
- this.tooltipDOM.style.border = `1px solid ${opt.borderColor}`;
428
- this.tooltipDOM.style.color = opt.fontColor;
599
+ this.tooltipDOM.style.backgroundColor = tooltipOptions.backgroundColor;
600
+ this.tooltipDOM.style.border = `1px solid ${tooltipOptions.borderColor}`;
601
+ this.tooltipDOM.style.color = tooltipOptions.fontColor;
429
602
 
430
- if (opt.useShadow) {
431
- const shadowColor = `rgba(0, 0, 0, ${opt.shadowOpacity})`;
603
+ if (tooltipOptions.useShadow) {
604
+ const shadowColor = `rgba(0, 0, 0, ${tooltipOptions.shadowOpacity})`;
432
605
  this.tooltipDOM.style.boxShadow = `2px 2px 2px ${shadowColor}`;
433
606
  }
434
607
 
@@ -164,7 +164,7 @@ class Scale {
164
164
  *
165
165
  * @returns {undefined}
166
166
  */
167
- draw(chartRect, labelOffset, stepInfo, hitInfo, selectLabelInfo) {
167
+ draw(chartRect, labelOffset, stepInfo, hitInfo) {
168
168
  const ctx = this.ctx;
169
169
  const options = this.options;
170
170
  const aPos = {
@@ -239,22 +239,21 @@ class Scale {
239
239
  linePosition = labelCenter + aliasPixel;
240
240
  labelText = this.getLabelFormat(Math.min(axisMax, ticks[ix]));
241
241
 
242
- const isBlurredLabel = this.options?.selectLabel?.use
243
- && this.options?.selectLabel?.useLabelOpacity
244
- && (this.options.horizontal === (this.type === 'y'))
245
- && selectLabelInfo?.dataIndex?.length
246
- && !selectLabelInfo?.dataIndex?.includes(ix);
247
- ctx.fillStyle = Util.colorStringToRgba(this.labelStyle.color, isBlurredLabel ? 0.1 : 1);
242
+ const labelColor = this.labelStyle.color;
243
+ let defaultOpacity = 1;
244
+
245
+ if (Util.getColorStringType(labelColor) === 'RGBA') {
246
+ defaultOpacity = Util.getOpacity(labelColor);
247
+ }
248
+
249
+ ctx.fillStyle = Util.colorStringToRgba(labelColor, defaultOpacity);
248
250
 
249
251
  let labelPoint;
250
252
 
251
253
  if (this.type === 'x') {
252
254
  labelPoint = this.position === 'top' ? offsetPoint - 10 : offsetPoint + 10;
253
255
  ctx.fillText(labelText, labelCenter, labelPoint);
254
- if (!isBlurredLabel
255
- && options?.selectItem?.showLabelTip
256
- && hitInfo?.label
257
- && !this.options?.horizontal) {
256
+ if (options?.selectItem?.showLabelTip && hitInfo?.label && !this.options?.horizontal) {
258
257
  const selectedLabel = this.getLabelFormat(
259
258
  Math.min(axisMax, hitInfo.label + (0 * stepValue)),
260
259
  );
@@ -7,6 +7,7 @@ class StepScale extends Scale {
7
7
  constructor(type, opt, ctx, labels, options) {
8
8
  super(type, opt, ctx, options);
9
9
  this.labels = labels;
10
+ this.rangeMode = opt.rangeMode;
10
11
  }
11
12
 
12
13
  /**
@@ -126,11 +127,20 @@ class StepScale extends Scale {
126
127
  && (this.options.horizontal === (this.type === 'y'))
127
128
  && selectLabelInfo?.dataIndex?.length
128
129
  && !selectLabelInfo?.dataIndex?.includes(index);
129
- ctx.fillStyle = Util.colorStringToRgba(this.labelStyle.color, isBlurredLabel ? 0.1 : 1);
130
+
131
+ const labelColor = this.labelStyle.color;
132
+ let defaultOpacity = 1;
133
+
134
+ if (Util.getColorStringType(labelColor) === 'RGBA') {
135
+ defaultOpacity = Util.getOpacity(labelColor);
136
+ }
137
+
138
+ ctx.fillStyle = Util.colorStringToRgba(labelColor, isBlurredLabel ? 0.1 : defaultOpacity);
130
139
 
131
140
  if (this.type === 'x') {
132
141
  labelPoint = this.position === 'top' ? offsetPoint - 10 : offsetPoint + 10;
133
- ctx.fillText(labelText, labelCenter + (labelGap / 2), labelPoint);
142
+ const xPoint = this.rangeMode ? labelCenter : labelCenter + (labelGap / 2);
143
+ ctx.fillText(labelText, xPoint, labelPoint);
134
144
 
135
145
  if (!isBlurredLabel
136
146
  && this.options?.selectItem?.showLabelTip
@@ -160,7 +170,8 @@ class StepScale extends Scale {
160
170
  }
161
171
  } else {
162
172
  labelPoint = this.position === 'left' ? offsetPoint - 10 : offsetPoint + 10;
163
- ctx.fillText(labelText, labelPoint, labelCenter + (labelGap / 2));
173
+ const yPoint = this.rangeMode ? labelCenter : labelCenter + (labelGap / 2);
174
+ ctx.fillText(labelText, labelPoint, yPoint);
164
175
 
165
176
  if (index > 0 && this.showGrid) {
166
177
  ctx.moveTo(offsetPoint, linePosition);
@@ -170,6 +181,30 @@ class StepScale extends Scale {
170
181
  ctx.stroke();
171
182
  });
172
183
 
184
+ if (this.rangeMode) {
185
+ let labelLastText = +labels[labels.length - 1] + (+labels[1] - +labels[0]);
186
+ if (isNaN(labelLastText)) {
187
+ labelLastText = 'Max';
188
+ }
189
+ labelCenter = Math.round(startPoint + (labelGap * labels.length));
190
+ linePosition = labelCenter + aliasPixel;
191
+
192
+ if (this.type === 'x') {
193
+ ctx.fillText(labelLastText, labelCenter, labelPoint);
194
+ if (this.showGrid) {
195
+ ctx.moveTo(linePosition, offsetPoint);
196
+ ctx.lineTo(linePosition, offsetCounterPoint);
197
+ }
198
+ } else {
199
+ ctx.fillText(labelLastText, labelPoint, labelCenter);
200
+ if (this.showGrid) {
201
+ ctx.moveTo(offsetPoint, linePosition);
202
+ ctx.lineTo(offsetCounterPoint, linePosition);
203
+ }
204
+ }
205
+ ctx.stroke();
206
+ }
207
+
173
208
  ctx.closePath();
174
209
  }
175
210
 
@@ -164,7 +164,7 @@ class TimeCategoryScale extends Scale {
164
164
  }
165
165
 
166
166
  const graphGap = (endPoint - startPoint) / (labels.length || 1);
167
- if (this.categoryMode) {
167
+ if (this.categoryMode && !this.rangeMode) {
168
168
  startPoint += Math.ceil(graphGap / 2) - 2;
169
169
  }
170
170
 
@@ -176,6 +176,7 @@ class TimeCategoryScale extends Scale {
176
176
  ctx.strokeStyle = this.gridLineColor;
177
177
 
178
178
  let labelText;
179
+ let labelPoint;
179
180
  for (let ix = 0; ix < oriSteps; ix += count) {
180
181
  ticks[ix] = axisMin + (ix * stepValue);
181
182
 
@@ -188,9 +189,15 @@ class TimeCategoryScale extends Scale {
188
189
  && (this.options.horizontal === (this.type === 'y'))
189
190
  && selectLabelInfo?.dataIndex?.length
190
191
  && !selectLabelInfo?.dataIndex?.includes(ix);
191
- ctx.fillStyle = Util.colorStringToRgba(this.labelStyle.color, isBlurredLabel ? 0.1 : 1);
192
192
 
193
- let labelPoint;
193
+ const labelColor = this.labelStyle.color;
194
+ let defaultOpacity = 1;
195
+
196
+ if (Util.getColorStringType(labelColor) === 'RGBA') {
197
+ defaultOpacity = Util.getOpacity(labelColor);
198
+ }
199
+
200
+ ctx.fillStyle = Util.colorStringToRgba(labelColor, isBlurredLabel ? 0.1 : defaultOpacity);
194
201
 
195
202
  if (this.type === 'x') {
196
203
  labelPoint = this.position === 'top' ? offsetPoint - 10 : offsetPoint + 10;
@@ -235,6 +242,31 @@ class TimeCategoryScale extends Scale {
235
242
  ctx.stroke();
236
243
  }
237
244
 
245
+ if (this.categoryMode && this.rangeMode && (count * steps) === oriSteps) {
246
+ const diffTime = dayjs(labels[1]).diff(dayjs(labels[0]));
247
+ const labelLastText = this.getLabelFormat(
248
+ dayjs(labels[labels.length - 1] + diffTime),
249
+ );
250
+
251
+ labelCenter = Math.round(startPoint + (graphGap * labels.length));
252
+ linePosition = labelCenter + aliasPixel;
253
+
254
+ if (this.type === 'x') {
255
+ ctx.fillText(labelLastText, labelCenter, labelPoint);
256
+ if (this.showGrid) {
257
+ ctx.moveTo(linePosition, offsetPoint);
258
+ ctx.lineTo(linePosition, offsetCounterPoint);
259
+ }
260
+ } else {
261
+ ctx.fillText(labelLastText, labelPoint, labelCenter);
262
+ if (this.showGrid) {
263
+ ctx.moveTo(offsetPoint, linePosition);
264
+ ctx.lineTo(offsetCounterPoint, linePosition);
265
+ }
266
+ }
267
+ ctx.stroke();
268
+ }
269
+
238
270
  ctx.closePath();
239
271
  }
240
272
  }
@@ -81,6 +81,7 @@ const DEFAULT_OPTIONS = {
81
81
  indicatorColor: '#000000',
82
82
  tipBackground: '#000000',
83
83
  tipTextColor: '#FFFFFF',
84
+ useSeriesOpacity: false,
84
85
  },
85
86
  selectLabel: {
86
87
  use: false,
@@ -99,6 +100,17 @@ const DEFAULT_OPTIONS = {
99
100
  fillColor: '#38ACEC',
100
101
  opacity: 0.65,
101
102
  },
103
+ heatMapColor: {
104
+ min: '#FFFFFF',
105
+ max: '#0052FF',
106
+ categoryCnt: 5,
107
+ stroke: {
108
+ show: false,
109
+ color: '#FFFFFF',
110
+ lineWidth: 1,
111
+ },
112
+ error: '#FF0000',
113
+ },
102
114
  };
103
115
 
104
116
  const DEFAULT_DATA = {