evui 3.3.9 → 3.3.12

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 (35) hide show
  1. package/dist/evui.common.js +3546 -973
  2. package/dist/evui.common.js.map +1 -1
  3. package/dist/evui.umd.js +3546 -973
  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.vue +15 -6
  9. package/src/components/chart/chart.core.js +86 -31
  10. package/src/components/chart/element/element.bar.js +7 -1
  11. package/src/components/chart/element/element.heatmap.js +213 -0
  12. package/src/components/chart/element/element.line.js +20 -9
  13. package/src/components/chart/element/element.pie.js +13 -5
  14. package/src/components/chart/element/element.scatter.js +26 -9
  15. package/src/components/chart/element/element.tip.js +154 -13
  16. package/src/components/chart/helpers/helpers.constant.js +15 -0
  17. package/src/components/chart/model/model.series.js +4 -0
  18. package/src/components/chart/model/model.store.js +160 -2
  19. package/src/components/chart/plugins/plugins.interaction.js +82 -10
  20. package/src/components/chart/plugins/plugins.legend.js +213 -42
  21. package/src/components/chart/plugins/plugins.tooltip.js +249 -6
  22. package/src/components/chart/scale/scale.js +9 -0
  23. package/src/components/chart/scale/scale.step.js +20 -5
  24. package/src/components/chart/scale/scale.time.category.js +20 -2
  25. package/src/components/chart/uses.js +20 -3
  26. package/src/components/grid/Grid.vue +276 -132
  27. package/src/components/grid/grid.filter.window.vue +1 -0
  28. package/src/components/grid/grid.pagination.vue +75 -0
  29. package/src/components/grid/grid.summary.vue +235 -0
  30. package/src/components/grid/style/grid.scss +0 -14
  31. package/src/components/grid/uses.js +158 -79
  32. package/src/components/pagination/Pagination.vue +20 -17
  33. package/src/components/treeGrid/TreeGrid.vue +253 -34
  34. package/src/components/treeGrid/TreeGridNode.vue +8 -9
  35. package/src/components/treeGrid/uses.js +152 -37
@@ -14,9 +14,15 @@ const modules = {
14
14
  const isHorizontal = !!opt.horizontal;
15
15
  const maxTipOpt = opt.maxTip;
16
16
  const selTipOpt = opt.selectItem;
17
+ const labelTipOpt = opt.selectLabel;
17
18
  let maxArgs;
19
+ let isExistSelectedLabel;
18
20
 
19
- if (selTipOpt.use && tipLocationInfo) {
21
+ if (labelTipOpt.use && labelTipOpt.showTip) {
22
+ isExistSelectedLabel = this.drawLabelTip();
23
+ }
24
+
25
+ if (selTipOpt.use && tipLocationInfo && !isExistSelectedLabel) {
20
26
  const seriesInfo = this.seriesList[tipLocationInfo?.sId];
21
27
 
22
28
  if (!seriesInfo?.show) {
@@ -45,29 +51,30 @@ const modules = {
45
51
  selArgs.text = numberWithComma(selArgs.value);
46
52
  }
47
53
 
48
- this.drawTextTip({ opt: selTipOpt, tipType: 'sel', isSamePos, ...selArgs });
54
+ this.drawTextTip({ opt: selTipOpt, tipType: 'sel', seriesOpt: seriesInfo, isSamePos, ...selArgs });
49
55
  }
50
56
 
51
57
  if (selTipOpt.showIndicator) {
52
- this.drawFixedIndicator({ opt: selTipOpt, ...selArgs });
58
+ this.drawFixedIndicator({ opt: selTipOpt, seriesOpt: seriesInfo, ...selArgs });
53
59
  }
54
60
  }
55
61
 
56
- if (tipLocationInfo && tipLocationInfo.label !== null) {
62
+ if (tipLocationInfo && tipLocationInfo?.label && tipLocationInfo?.label === 0) {
57
63
  this.lastHitInfo = tipLocationInfo;
58
64
  }
59
65
  }
60
66
 
61
- if (maxTipOpt.use) {
67
+ if (maxTipOpt.use && !isExistSelectedLabel) {
62
68
  const maxSID = this.minMax[isHorizontal ? 'x' : 'y'][0].maxSID;
63
- maxArgs = this.calculateTipInfo(this.seriesList[maxSID], 'max', null);
69
+ const seriesInfo = this.seriesList[maxSID];
70
+ maxArgs = this.calculateTipInfo(seriesInfo, 'max', null);
64
71
 
65
72
  if (maxTipOpt.use && maxArgs) {
66
73
  maxArgs.text = numberWithComma(maxArgs.value);
67
- this.drawTextTip({ opt: maxTipOpt, tipType: 'max', ...maxArgs });
74
+ this.drawTextTip({ opt: maxTipOpt, tipType: 'max', seriesOpt: seriesInfo, ...maxArgs });
68
75
 
69
76
  if (maxTipOpt.showIndicator) {
70
- this.drawFixedIndicator({ opt: maxTipOpt, ...maxArgs });
77
+ this.drawFixedIndicator({ opt: maxTipOpt, seriesOpt: seriesInfo, ...maxArgs });
71
78
  }
72
79
  }
73
80
  }
@@ -76,7 +83,8 @@ const modules = {
76
83
  /**
77
84
  * Calculate tip size and contents
78
85
  * @param {object} series series information (max series or selected series)
79
- * @param {string} tipType tip type [sel = user select, max = max value]
86
+ * @param {string} tipType tip type
87
+ * [sel = user select series, label = user select label, max = max value]
80
88
  * @param {object} hitInfo mouse hit information
81
89
  *
82
90
  * @returns {object} size and tip contents
@@ -169,6 +177,14 @@ const modules = {
169
177
  xArea - size.comboOffset,
170
178
  xsp + (size.comboOffset / 2),
171
179
  );
180
+ } else if (type === 'scatter') {
181
+ dp = Canvas.calculateX(
182
+ ldata,
183
+ graphX.graphMin,
184
+ graphX.graphMax,
185
+ xArea,
186
+ xsp,
187
+ );
172
188
  }
173
189
 
174
190
  const sizeObj = { xArea, yArea, graphX, graphY, xsp, xep, ysp };
@@ -179,8 +195,14 @@ const modules = {
179
195
  drawFixedIndicator(param) {
180
196
  const isHorizontal = !!this.options.horizontal;
181
197
  const ctx = this.bufferCtx;
182
- const { graphX, graphY, xArea, yArea, xsp, ysp, dp, type, value, opt } = param;
183
- const offset = type === 'bar' ? 0 : 3;
198
+ const { graphX, graphY, xArea, yArea, xsp, ysp, dp, type, value, opt, seriesOpt } = param;
199
+ let offset = 0;
200
+
201
+ if (type === 'line') {
202
+ offset += 3;
203
+ } else if (type === 'scatter') {
204
+ offset += seriesOpt?.pointSize ?? 0;
205
+ }
184
206
 
185
207
  let gp;
186
208
 
@@ -220,6 +242,117 @@ const modules = {
220
242
  ctx.closePath();
221
243
  },
222
244
 
245
+ /**
246
+ * Draw Selected Label Tip
247
+ * @returns {boolean} Whether drew at least one tip
248
+ */
249
+ drawLabelTip() {
250
+ const opt = this.options;
251
+ const isHorizontal = !!opt.horizontal;
252
+ const labelTipOpt = opt.selectLabel;
253
+ const { dataIndex, data, label } = this.defaultSelectLabelInfo;
254
+ let drawTip = false;
255
+
256
+ if (dataIndex.length) {
257
+ drawTip = true;
258
+
259
+ const chartRect = this.chartRect;
260
+ const labelOffset = this.labelOffset;
261
+ const aPos = {
262
+ x1: chartRect.x1 + labelOffset.left,
263
+ x2: chartRect.x2 - labelOffset.right,
264
+ y1: chartRect.y1 + labelOffset.top,
265
+ y2: chartRect.y2 - labelOffset.bottom,
266
+ };
267
+ const labelAxes = isHorizontal ? this.axesY[0] : this.axesX[0];
268
+ const valueAxes = isHorizontal ? this.axesX[0] : this.axesY[0];
269
+ const valueAxesRange = isHorizontal ? this.axesRange.x[0] : this.axesRange.y[0];
270
+ const valuePositionCalcFunction = isHorizontal ? Canvas.calculateX : Canvas.calculateY;
271
+ const labelPositionCalcFunction = isHorizontal ? Canvas.calculateY : Canvas.calculateX;
272
+
273
+ const chartWidth = chartRect.chartWidth - (labelOffset.left + labelOffset.right);
274
+ const chartHeight = chartRect.chartHeight - (labelOffset.top + labelOffset.bottom);
275
+ const valueSpace = isHorizontal ? chartWidth : chartHeight;
276
+ const valueStartPoint = aPos[valueAxes.units.rectStart];
277
+ let offset = this.options.type === 'bar' ? 4 : 6;
278
+ offset *= isHorizontal ? 1 : -1;
279
+
280
+ const seriesList = Object.keys(this.seriesList ?? {});
281
+ const visibleSeries = seriesList.filter(sId => this.seriesList[sId].show);
282
+ const isExistGrp = seriesList.some(sId => this.seriesList[sId].isExistGrp);
283
+ const groups = this.data.groups?.[0] ?? [];
284
+
285
+ let gp;
286
+ let dp;
287
+ let value;
288
+ let labelStartPoint;
289
+ let labelEndPoint;
290
+ let labelGap;
291
+ let graphX;
292
+ let lineSeries;
293
+ let sizeObj;
294
+
295
+ if (labelAxes.labels) {
296
+ labelStartPoint = aPos[labelAxes.units.rectStart];
297
+ labelEndPoint = aPos[labelAxes.units.rectEnd];
298
+ labelGap = (labelEndPoint - labelStartPoint) / labelAxes.labels.length;
299
+ } else {
300
+ graphX = this.axesSteps.x[0];
301
+ lineSeries = seriesList.find(sId => this.seriesList[sId]?.type === 'line');
302
+ sizeObj = this.seriesList[lineSeries].size;
303
+ }
304
+
305
+ data.forEach((selectedData, i) => {
306
+ if (labelTipOpt.fixedPosTop) {
307
+ value = valueAxesRange.max;
308
+ } else if (isExistGrp) {
309
+ const sumValue = visibleSeries.reduce((ac, sId) => (
310
+ groups.includes(sId) ? ac + (selectedData[sId]?.value ?? selectedData[sId]) : ac), 0);
311
+ const nonGroupValues = visibleSeries
312
+ .filter(sId => !groups.includes(sId))
313
+ .map(sId => selectedData[sId]?.value ?? selectedData[sId]);
314
+ value = Math.max(...nonGroupValues, sumValue);
315
+ } else if (visibleSeries.length) {
316
+ const visibleValue = visibleSeries
317
+ .map(sId => selectedData[sId]?.value ?? selectedData[sId]);
318
+ value = Math.max(...visibleValue);
319
+ } else {
320
+ value = valueAxesRange.max;
321
+ }
322
+
323
+ if (labelAxes.labels) {
324
+ const labelCenter = Math.round(labelStartPoint + (labelGap * dataIndex[i]));
325
+
326
+ dp = labelCenter + (labelGap / 2);
327
+ } else {
328
+ dp = labelPositionCalcFunction(
329
+ label[i],
330
+ graphX.graphMin,
331
+ graphX.graphMax,
332
+ chartWidth - sizeObj.comboOffset,
333
+ aPos.x1 + (sizeObj.comboOffset / 2),
334
+ );
335
+ }
336
+ gp = valuePositionCalcFunction(
337
+ value,
338
+ valueAxesRange.min,
339
+ valueAxesRange.max,
340
+ valueSpace,
341
+ valueStartPoint);
342
+ gp += offset;
343
+
344
+ this.showTip({
345
+ context: this.bufferCtx,
346
+ x: isHorizontal ? gp : dp,
347
+ y: isHorizontal ? dp : gp,
348
+ opt: labelTipOpt,
349
+ isSamePos: false,
350
+ });
351
+ });
352
+ }
353
+
354
+ return drawTip;
355
+ },
223
356
  /**
224
357
  * Calculate x, y position to draw text tip
225
358
  * @param {object} param object for drawing text tip
@@ -230,12 +363,20 @@ const modules = {
230
363
  const isHorizontal = !!this.options.horizontal;
231
364
  const ctx = this.bufferCtx;
232
365
  const { graphX, graphY, xArea, yArea, xsp, xep, ysp } = param;
233
- const { dp, value, text, opt, type, tipType, isSamePos } = param;
366
+ const { dp, value, text, opt, type, tipType, isSamePos, seriesOpt } = param;
234
367
 
235
368
  const arrowSize = 4;
236
369
  const maxTipHeight = 20;
237
370
  const borderRadius = 4;
238
- const offset = type === 'bar' ? 4 : 6;
371
+
372
+ let offset = 1;
373
+ if (type === 'line') {
374
+ offset += 6;
375
+ } else if (type === 'scatter') {
376
+ offset += seriesOpt?.pointSize;
377
+ } else if (type === 'bar') {
378
+ offset += 4;
379
+ }
239
380
 
240
381
  let gp;
241
382
  let tdp = dp;
@@ -128,6 +128,21 @@ export const PLOT_BAND_OPTION = {
128
128
  color: '#FAE59D',
129
129
  };
130
130
 
131
+ export const HEAT_MAP_OPTION = {
132
+ ...LINE_OPTION,
133
+ colorOpt: {
134
+ min: '#FFFFFF',
135
+ max: '#0052FF',
136
+ categoryCnt: 5,
137
+ border: '#FFFFFF',
138
+ error: '#FF0000',
139
+ },
140
+ spaces: {
141
+ x: 0,
142
+ y: 0,
143
+ },
144
+ };
145
+
131
146
 
132
147
  export const TIME_INTERVALS = {
133
148
  millisecond: {
@@ -3,6 +3,7 @@ import Scatter from '../element/element.scatter';
3
3
  import Bar from '../element/element.bar';
4
4
  import TimeBar from '../element/element.bar.time';
5
5
  import Pie from '../element/element.pie';
6
+ import HeatMap from '../element/element.heatmap';
6
7
 
7
8
  const modules = {
8
9
  /**
@@ -51,6 +52,9 @@ const modules = {
51
52
  } else if (type === 'pie') {
52
53
  this.seriesInfo.charts.pie.push(id);
53
54
  return new Pie(id, opt, index);
55
+ } else if (type === 'heatMap') {
56
+ this.seriesInfo.charts.heatMap.push(id);
57
+ return new HeatMap(id, opt, index);
54
58
  }
55
59
 
56
60
  return false;
@@ -1,5 +1,6 @@
1
1
  import { reverse } from 'lodash-es';
2
2
  import Util from '../helpers/helpers.util';
3
+ import { TIME_INTERVALS } from '../helpers/helpers.constant';
3
4
 
4
5
  const modules = {
5
6
  /**
@@ -30,6 +31,17 @@ const modules = {
30
31
  series.minMax = this.getSeriesMinMax(series.data);
31
32
  }
32
33
  });
34
+ } else if (typeKey === 'heatMap') {
35
+ seriesIDs.forEach((seriesID) => {
36
+ const series = this.seriesList[seriesID];
37
+ const sData = data[seriesID];
38
+
39
+ if (series && sData) {
40
+ series.data = this.addSeriesDSForHeatMap(sData);
41
+ series.minMax = this.getSeriesMinMaxForHeatMap(series.data, series.spaces);
42
+ series.valueOpt = this.getSeriesValueOptForHeatMap(series);
43
+ }
44
+ });
33
45
  } else {
34
46
  seriesIDs.forEach((seriesID) => {
35
47
  const series = this.seriesList[seriesID];
@@ -286,6 +298,24 @@ const modules = {
286
298
  });
287
299
  },
288
300
 
301
+ /**
302
+ * Take data to create data for each series
303
+ * @param {array} data data array for each series
304
+ * @returns {array} data info added position and etc
305
+ */
306
+ addSeriesDSForHeatMap(data) {
307
+ return data.map(item => ({
308
+ x: item.x,
309
+ y: item.y,
310
+ o: item.value,
311
+ xp: null,
312
+ yp: null,
313
+ dataColor: null,
314
+ value: item.value,
315
+ cId: null,
316
+ }));
317
+ },
318
+
289
319
  /**
290
320
  * Take data to create data object for graph
291
321
  * @param {object} gdata graph data (y-axis value for vertical chart)
@@ -384,6 +414,96 @@ const modules = {
384
414
  return def;
385
415
  },
386
416
 
417
+ adjustMinMax(max, min, opt, space) {
418
+ if ((opt.type === 'time' && opt.categoryMode) || opt.type === 'step') {
419
+ return {
420
+ max,
421
+ min,
422
+ };
423
+ }
424
+
425
+ let targetMax = max;
426
+ let targetMin = min;
427
+ if (targetMax > 0 && opt.interval && space) {
428
+ if (targetMax < (opt.interval * space)) {
429
+ targetMax += opt.interval;
430
+ }
431
+ }
432
+
433
+ let targetInterval = opt.interval;
434
+ if (opt.type === 'time') {
435
+ if (typeof targetInterval === 'string') {
436
+ targetInterval = TIME_INTERVALS[targetInterval].size;
437
+ } else if (typeof targetInterval === 'object') {
438
+ targetInterval = targetInterval.time * TIME_INTERVALS[targetInterval.unit].size;
439
+ }
440
+ }
441
+
442
+ if (!opt.startToZero || targetMin > 0) {
443
+ const targetSpace = space ? (space - 1) : (targetMax - targetMin);
444
+ const targetStep = Math.ceil((max - targetMin) / targetSpace);
445
+ targetMin = targetMin < targetStep ? 0 : targetMin - targetStep;
446
+ }
447
+
448
+ return {
449
+ max: targetMax,
450
+ min: targetMin,
451
+ };
452
+ },
453
+ /**
454
+ * Take series data to create min/max info for each series
455
+ * @param data
456
+ * @param spaces
457
+ * @returns {*|{maxDomain: null, minY: null, minX: null, maxY: null, maxX: null}}
458
+ */
459
+ getSeriesMinMaxForHeatMap(data, spaces) {
460
+ const axesXOption = this.options.axesX[0];
461
+ const axesYOption = this.options.axesY[0];
462
+ const seriesMinMax = this.getSeriesMinMax(data);
463
+
464
+ const adjustX = this.adjustMinMax(seriesMinMax.maxX, seriesMinMax.minX, axesXOption, spaces.x);
465
+ seriesMinMax.maxX = adjustX.max;
466
+ seriesMinMax.minX = adjustX.min;
467
+
468
+ const adjustY = this.adjustMinMax(seriesMinMax.maxY, seriesMinMax.minY, axesYOption, spaces.y);
469
+ seriesMinMax.maxY = adjustY.max;
470
+ seriesMinMax.minY = adjustY.min;
471
+
472
+ return seriesMinMax;
473
+ },
474
+
475
+ getSeriesValueOptForHeatMap(series) {
476
+ const data = series.data;
477
+ const colorOpt = series.colorOpt;
478
+ const colorAxis = series.colorAxis;
479
+ const categoryCnt = colorOpt.categoryCnt;
480
+
481
+ let maxValue = 0;
482
+ let isExistError = false;
483
+ data.forEach(({ value }) => {
484
+ if (maxValue < value) {
485
+ maxValue = value;
486
+ }
487
+ if (value < 0) {
488
+ isExistError = true;
489
+ }
490
+ });
491
+ const valueInterval = Math.ceil(maxValue / categoryCnt);
492
+ if (isExistError && colorAxis.length === categoryCnt) {
493
+ colorAxis.push({
494
+ id: `color#${categoryCnt}`,
495
+ value: colorOpt.error,
496
+ state: 'normal',
497
+ show: true,
498
+ });
499
+ }
500
+ return {
501
+ max: maxValue,
502
+ interval: valueInterval,
503
+ existError: isExistError,
504
+ };
505
+ },
506
+
387
507
  /**
388
508
  * Get graph items for each series by label index
389
509
  * @param {number} labelIndex label index
@@ -553,6 +673,42 @@ const modules = {
553
673
  };
554
674
  },
555
675
 
676
+ /**
677
+ * Find label info by position x and y
678
+ * @param {array} offset position x and y
679
+ *
680
+ * @returns {object} clicked label information
681
+ */
682
+ getLabelInfoByPosition(offset) {
683
+ const [x, y] = offset;
684
+ const aPos = {
685
+ x1: this.chartRect.x1 + this.labelOffset.left,
686
+ x2: this.chartRect.x2 - this.labelOffset.right,
687
+ y1: this.chartRect.y1 + this.labelOffset.top,
688
+ y2: this.chartRect.y2 - this.labelOffset.bottom,
689
+ };
690
+
691
+ const scale = this.options.horizontal ? this.axesY[0] : this.axesX[0];
692
+ const startPoint = aPos[scale.units.rectStart];
693
+ const endPoint = aPos[scale.units.rectEnd];
694
+
695
+ let labelIndex;
696
+ let hitInfo;
697
+ if (scale.labels) {
698
+ const labelGap = (endPoint - startPoint) / scale.labels.length;
699
+ const index = Math.floor(((this.options.horizontal ? y : x) - startPoint) / labelGap);
700
+ labelIndex = scale.labels.length > index ? index : -1;
701
+ } else {
702
+ hitInfo = this.getItemByPosition(offset, this.options.selectLabel.useApproximateValue);
703
+ labelIndex = hitInfo.maxIndex ?? -1;
704
+ }
705
+
706
+ return {
707
+ labelIndex,
708
+ hitInfo,
709
+ };
710
+ },
711
+
556
712
  /**
557
713
  * Create min/max information for all of data
558
714
  * @property seriesList
@@ -584,7 +740,8 @@ const modules = {
584
740
 
585
741
  if (smm && series.show) {
586
742
  if (!isHorizontal) {
587
- if (smm.minX && ((minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)))) {
743
+ if (smm.minX !== null
744
+ && ((minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)))) {
588
745
  minmax.x[axisX].min = smm.minX;
589
746
  }
590
747
  if (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min)) {
@@ -594,7 +751,8 @@ const modules = {
594
751
  if (minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)) {
595
752
  minmax.x[axisX].min = smm.minX;
596
753
  }
597
- if (smm.minY && (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min))) {
754
+ if (smm.minY !== null
755
+ && (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min))) {
598
756
  minmax.y[axisY].min = smm.minY;
599
757
  }
600
758
  }
@@ -1,5 +1,5 @@
1
1
  import { numberWithComma } from '@/common/utils';
2
- import { defaultsDeep } from 'lodash-es';
2
+ import { cloneDeep, defaultsDeep } from 'lodash-es';
3
3
 
4
4
  const modules = {
5
5
  /**
@@ -48,13 +48,17 @@ const modules = {
48
48
  this.overlayClear();
49
49
 
50
50
  if (Object.keys(hitInfo.items).length) {
51
- if (this.options.type !== 'scatter' || tooltip.use) {
51
+ if ((type !== 'scatter' && type !== 'heatMap') || tooltip.use) {
52
52
  this.drawItemsHighlight(hitInfo, ctx);
53
53
  }
54
54
 
55
55
  if (tooltip.use) {
56
56
  this.setTooltipLayoutPosition(hitInfo, e);
57
- this.drawTooltip(hitInfo, this.tooltipCtx);
57
+ if (type === 'scatter') {
58
+ this.drawTooltipForScatter(hitInfo, this.tooltipCtx);
59
+ } else {
60
+ this.drawTooltip(hitInfo, this.tooltipCtx);
61
+ }
58
62
  }
59
63
  } else if (tooltip.use) {
60
64
  this.hideTooltipDOM();
@@ -64,7 +68,7 @@ const modules = {
64
68
  this.drawSelectionArea(this.dragInfoBackup);
65
69
  }
66
70
 
67
- if (indicator.use && type !== 'pie' && type !== 'scatter') {
71
+ if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
68
72
  this.drawIndicator(offset, indicator.color);
69
73
  }
70
74
  };
@@ -139,6 +143,15 @@ const modules = {
139
143
  } = hitInfo);
140
144
  }
141
145
 
146
+ if (this.options.selectLabel.use) {
147
+ const offset = this.getMousePosition(e);
148
+ const clickedLabelInfo = this.getLabelInfoByPosition(offset);
149
+ const selected = this.selectLabel(clickedLabelInfo.labelIndex);
150
+ this.renderWithSelectLabel(selected.dataIndex);
151
+
152
+ args.selected = cloneDeep(this.defaultSelectLabelInfo);
153
+ }
154
+
142
155
  if (typeof this.listeners.click === 'function') {
143
156
  if (!this.dragInfoBackup) {
144
157
  this.listeners.click(args);
@@ -154,7 +167,7 @@ const modules = {
154
167
  this.onMouseDown = (e) => {
155
168
  const { dragSelection, type } = this.options;
156
169
 
157
- if (dragSelection.use && (type === 'scatter' || type === 'line')) {
170
+ if (dragSelection.use && (type === 'scatter' || type === 'line' || type === 'heatMap')) {
158
171
  this.removeSelectionArea();
159
172
  this.dragStart(e, type);
160
173
  }
@@ -251,9 +264,11 @@ const modules = {
251
264
  }
252
265
 
253
266
  dragInfo.xsp = Math.min(xcp, xep);
254
- dragInfo.ysp = type === 'scatter' ? Math.min(ycp, yep) : aRange.y1;
267
+ dragInfo.ysp = type === 'scatter' || type === 'heatMap' ? Math.min(ycp, yep) : aRange.y1;
255
268
  dragInfo.width = Math.ceil(Math.abs(xep - xcp));
256
- dragInfo.height = type === 'scatter' ? Math.ceil(Math.abs(yep - ycp)) : aRange.y2 - aRange.y1;
269
+ dragInfo.height = type === 'scatter' || type === 'heatMap'
270
+ ? Math.ceil(Math.abs(yep - ycp))
271
+ : aRange.y2 - aRange.y1;
257
272
 
258
273
  this.overlayClear();
259
274
  this.drawSelectionArea(dragInfo);
@@ -367,7 +382,7 @@ const modules = {
367
382
  }
368
383
 
369
384
  if (gdata !== null && gdata !== undefined) {
370
- const sName = `${series.name}`;
385
+ const sName = series.name;
371
386
  const sw = ctx ? ctx.measureText(sName).width : 1;
372
387
 
373
388
  item.name = sName;
@@ -412,7 +427,7 @@ const modules = {
412
427
  * @returns {boolean}
413
428
  */
414
429
  selectItemByData(targetInfo, chartType) {
415
- this.defaultSelectInfo = targetInfo;
430
+ this.defaultSelectItemInfo = targetInfo;
416
431
 
417
432
  let foundInfo;
418
433
  if (chartType === 'pie') {
@@ -437,9 +452,66 @@ const modules = {
437
452
  return true;
438
453
  },
439
454
 
455
+ /**
456
+ * render after select label by index list
457
+ * @param indexList {array} '[0, 1 ...]'
458
+ */
459
+ renderWithSelectLabel(indexList) {
460
+ this.defaultSelectLabelInfo.dataIndex = indexList;
461
+ this.initSelectedLabelInfo();
462
+ this.render();
463
+ },
464
+
465
+ /**
466
+ * init defaultSelectLabelInfo object.
467
+ * (set each series data and label text)
468
+ */
469
+ initSelectedLabelInfo() {
470
+ const { use, limit } = this.options.selectLabel;
471
+
472
+ if (use) {
473
+ if (!this.defaultSelectLabelInfo) {
474
+ this.defaultSelectLabelInfo = { dataIndex: [] };
475
+ }
476
+ const infoObj = this.defaultSelectLabelInfo;
477
+ infoObj.dataIndex.splice(limit);
478
+ infoObj.label = infoObj.dataIndex.map(i => this.data.labels[i]);
479
+ const dataEntries = Object.entries(this.data.data);
480
+ infoObj.data = infoObj.dataIndex.map(labelIdx => Object.fromEntries(
481
+ dataEntries.map(([sId, data]) => [sId, data[labelIdx]])));
482
+ }
483
+ },
484
+
485
+ /**
486
+ * Add or delete selected label index, according to policy and option
487
+ * (set each series data and label text)
488
+ * @param labelIndex {array} '[0, 1 ...]'
489
+ */
490
+ selectLabel(labelIndex) {
491
+ const option = this.options?.selectLabel ?? {};
492
+ const before = this.defaultSelectLabelInfo ?? { dataIndex: [] };
493
+ const after = cloneDeep(before);
494
+
495
+ if (before.dataIndex.includes(labelIndex)) {
496
+ const idx = before.dataIndex.indexOf(labelIndex);
497
+ after.dataIndex.splice(idx, 1);
498
+ } else if (labelIndex > -1) {
499
+ after.dataIndex.push(labelIndex);
500
+ if (option.limit > 0 && option.limit < after.dataIndex.length) {
501
+ if (option.useDeselectOverflow) {
502
+ after.dataIndex.splice(0, 1);
503
+ } else {
504
+ after.dataIndex.pop();
505
+ }
506
+ }
507
+ }
508
+
509
+ return after;
510
+ },
511
+
440
512
  /**
441
513
  * Find items by series within a range
442
- * @param {object} param object for find series items
514
+ * @param {object} range object for find series items
443
515
  *
444
516
  * @returns {object}
445
517
  */