evui 3.4.202 → 3.4.204

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.
@@ -11174,7 +11174,7 @@ module.exports = exports;
11174
11174
  /***/ "9224":
11175
11175
  /***/ (function(module) {
11176
11176
 
11177
- module.exports = JSON.parse("{\"a\":\"3.4.202\"}");
11177
+ module.exports = JSON.parse("{\"a\":\"3.4.204\"}");
11178
11178
 
11179
11179
  /***/ }),
11180
11180
 
@@ -41715,6 +41715,9 @@ var TIME_INTERVALS = {
41715
41715
 
41716
41716
 
41717
41717
 
41718
+
41719
+
41720
+
41718
41721
 
41719
41722
 
41720
41723
  var element_line_Line = /*#__PURE__*/function () {
@@ -42104,77 +42107,166 @@ var element_line_Line = /*#__PURE__*/function () {
42104
42107
  var gdata = this.data.filter(function (data) {
42105
42108
  return !helpers_util.isNullOrUndefined(data.x);
42106
42109
  });
42107
- var SPARE_XP = 0.5;
42108
42110
  var isLinearInterpolation = this.useLinearInterpolation();
42109
42111
 
42110
42112
  if (gdata !== null && gdata !== void 0 && gdata.length) {
42111
42113
  if (typeof dataIndex === 'number' && this.show) {
42112
42114
  item.data = gdata[dataIndex];
42113
42115
  item.index = dataIndex;
42116
+
42117
+ if (item.data) {
42118
+ var point = gdata[dataIndex];
42119
+ var yDist = Math.abs(yp - point.yp);
42120
+ var directHitThreshold = 15; // 직접 히트 임계값
42121
+
42122
+ if (yDist <= directHitThreshold) {
42123
+ item.hit = true;
42124
+ }
42125
+ }
42114
42126
  } else if (typeof this.beforeFindItemIndex === 'number' && this.show && useSelectLabelOrItem) {
42115
42127
  item.data = gdata[this.beforeFindItemIndex];
42116
42128
  item.index = this.beforeFindItemIndex;
42117
42129
  } else {
42118
- var _gdata$;
42119
-
42120
- var s = 0;
42121
- var e = gdata.length - 1;
42122
- var xpInterval = ((_gdata$ = gdata[1]) === null || _gdata$ === void 0 ? void 0 : _gdata$.xp) - gdata[0].xp < 6 ? 1.5 : 6;
42123
-
42124
- while (s <= e) {
42125
- var m = Math.floor((s + e) / 2);
42126
- var x = gdata[m].xp;
42127
- var y = gdata[m].yp;
42128
-
42129
- if (x - xpInterval < xp && xp < x + xpInterval) {
42130
- var _gdata$m, _gdata$xp, _gdata, _gdata2, _gdata3;
42131
-
42132
- var curXpInterval = ((_gdata$m = gdata[m]) === null || _gdata$m === void 0 ? void 0 : _gdata$m.xp) - ((_gdata$xp = (_gdata = gdata[m - 1]) === null || _gdata === void 0 ? void 0 : _gdata.xp) !== null && _gdata$xp !== void 0 ? _gdata$xp : 0);
42133
-
42134
- if ((_gdata2 = gdata[m - 1]) !== null && _gdata2 !== void 0 && _gdata2.xp && (_gdata3 = gdata[m + 1]) !== null && _gdata3 !== void 0 && _gdata3.xp && curXpInterval > 0) {
42135
- var leftXp = xp - gdata[m - 1].xp;
42136
- var midXp = Math.abs(xp - gdata[m].xp);
42137
- var rightXp = gdata[m + 1].xp - xp;
42138
-
42139
- if (Math.abs(this.beforeMouseXp - xp) >= curXpInterval - SPARE_XP && (this.beforeFindItemIndex === m || midXp === rightXp || midXp === leftXp)) {
42140
- if (this.beforeMouseXp - xp > 0) {
42141
- item.data = gdata[this.beforeFindItemIndex - 1];
42142
- item.index = this.beforeFindItemIndex - 1;
42143
- } else if (this.beforeMouseXp - xp < 0) {
42144
- item.data = gdata[this.beforeFindItemIndex + 1];
42145
- item.index = this.beforeFindItemIndex + 1;
42146
- } else if (this.beforeMouseYp !== yp) {
42147
- item.data = gdata[this.beforeFindItemIndex];
42148
- item.index = this.beforeFindItemIndex;
42149
- }
42150
- } else {
42151
- var closeXp = Math.min(leftXp, midXp, rightXp);
42152
-
42153
- if (closeXp === leftXp) {
42154
- item.data = gdata[m - 1];
42155
- item.index = m - 1;
42156
- } else if (closeXp === rightXp) {
42157
- item.data = gdata[m + 1];
42158
- item.index = m + 1;
42159
- } else {
42160
- item.data = gdata[m];
42161
- item.index = m;
42162
- }
42130
+ // Axis 트리거 방식: X축 위치에서 가장 가까운 데이터 포인트 찾기
42131
+ var closestXDistance = Infinity;
42132
+ var closestIndex = -1; // null이 아닌 유효한 데이터만 필터링
42133
+
42134
+ var validData = [];
42135
+ gdata.forEach(function (point, idx) {
42136
+ if (point.xp !== null && point.yp !== null && point.o !== null) {
42137
+ validData.push(_objectSpread2(_objectSpread2({}, point), {}, {
42138
+ originalIndex: idx
42139
+ }));
42140
+ }
42141
+ });
42142
+
42143
+ if (validData.length === 0) {
42144
+ return item;
42145
+ } // 이진 탐색으로 가장 가까운 포인트 찾기
42146
+
42147
+
42148
+ var left = 0;
42149
+ var right = validData.length - 1;
42150
+
42151
+ while (left <= right) {
42152
+ var mid = Math.floor((left + right) / 2);
42153
+ var _point = validData[mid];
42154
+ var xDistance = Math.abs(xp - _point.xp);
42155
+
42156
+ if (xDistance < closestXDistance) {
42157
+ closestXDistance = xDistance;
42158
+ closestIndex = _point.originalIndex;
42159
+ }
42160
+
42161
+ if (_point.xp < xp) {
42162
+ left = mid + 1; // 다음 포인트도 확인
42163
+
42164
+ if (left < validData.length) {
42165
+ var nextDistance = Math.abs(xp - validData[left].xp);
42166
+
42167
+ if (nextDistance < closestXDistance) {
42168
+ closestXDistance = nextDistance;
42169
+ closestIndex = validData[left].originalIndex;
42163
42170
  }
42164
- } else {
42165
- item.data = gdata[m];
42166
- item.index = m;
42167
42171
  }
42172
+ } else if (_point.xp > xp) {
42173
+ right = mid - 1; // 이전 포인트도 확인
42168
42174
 
42169
- if (y - 6 <= yp && yp <= y + 6) {
42170
- item.hit = true;
42171
- }
42175
+ if (right >= 0) {
42176
+ var prevDistance = Math.abs(xp - validData[right].xp);
42172
42177
 
42178
+ if (prevDistance < closestXDistance) {
42179
+ closestXDistance = prevDistance;
42180
+ closestIndex = validData[right].originalIndex;
42181
+ }
42182
+ }
42183
+ } else {
42184
+ // 정확히 일치하는 경우
42173
42185
  break;
42174
- } else if (x + xpInterval > xp) {
42175
- e = m - 1;
42186
+ }
42187
+ } // 이진 탐색 후 주변 포인트 추가 확인 (정확도 향상)
42188
+
42189
+
42190
+ var foundIdx = validData.findIndex(function (p) {
42191
+ return p.originalIndex === closestIndex;
42192
+ });
42193
+
42194
+ if (foundIdx !== -1) {
42195
+ // 앞뒤 2개씩 추가 확인
42196
+ for (var i = Math.max(0, foundIdx - 2); i <= Math.min(validData.length - 1, foundIdx + 2); i++) {
42197
+ var _point2 = validData[i];
42198
+
42199
+ var _xDistance = Math.abs(xp - _point2.xp);
42200
+
42201
+ if (_xDistance < closestXDistance) {
42202
+ closestXDistance = _xDistance;
42203
+ closestIndex = _point2.originalIndex;
42204
+ }
42205
+ }
42206
+ } // 가장 가까운 포인트 설정
42207
+
42208
+
42209
+ if (closestIndex !== -1) {
42210
+ // 데이터 간격 계산 - 모든 데이터(null 포함)의 평균 간격 사용
42211
+ var avgInterval = 50;
42212
+
42213
+ if (gdata.length > 1) {
42214
+ var intervals = [];
42215
+
42216
+ for (var _i = 1; _i < gdata.length; _i++) {
42217
+ if (gdata[_i].xp !== null && gdata[_i - 1].xp !== null) {
42218
+ intervals.push(Math.abs(gdata[_i].xp - gdata[_i - 1].xp));
42219
+ }
42220
+ }
42221
+
42222
+ if (intervals.length > 0) {
42223
+ avgInterval = intervals.reduce(function (a, b) {
42224
+ return a + b;
42225
+ }, 0) / intervals.length;
42226
+ }
42227
+ } // 두 가지 임계값 설정
42228
+
42229
+
42230
+ var strictThreshold = avgInterval * 0.3; // 엄격한 임계값: 데이터 간격의 30%
42231
+
42232
+ var relaxedThreshold = avgInterval; // 느슨한 임계값: 데이터 간격 전체
42233
+ // 1. 먼저 엄격한 임계값으로 정확한 매치 확인
42234
+
42235
+ if (closestXDistance <= strictThreshold) {
42236
+ // 정확히 일치하거나 매우 가까운 데이터가 있음
42237
+ item.data = gdata[closestIndex];
42238
+ item.index = closestIndex;
42176
42239
  } else {
42177
- s = m + 1;
42240
+ // 2. 정확한 매치가 없을 때, 현재 X 위치 근처에 다른 유효 데이터가 있는지 확인
42241
+ var hasNearbyValidData = false;
42242
+
42243
+ for (var _i2 = 0; _i2 < validData.length; _i2++) {
42244
+ var xDist = Math.abs(xp - validData[_i2].xp);
42245
+
42246
+ if (xDist <= strictThreshold) {
42247
+ hasNearbyValidData = true;
42248
+ break;
42249
+ }
42250
+ } // 3. 근처에 다른 유효 데이터가 없을 때만 느슨한 임계값 적용
42251
+
42252
+
42253
+ if (!hasNearbyValidData && closestXDistance <= relaxedThreshold) {
42254
+ item.data = gdata[closestIndex];
42255
+ item.index = closestIndex;
42256
+ }
42257
+ } // Y축 거리를 확인하여 직접 히트 판정
42258
+
42259
+
42260
+ if (item.data) {
42261
+ var _point3 = gdata[closestIndex];
42262
+
42263
+ var _yDist = Math.abs(yp - _point3.yp);
42264
+
42265
+ var _directHitThreshold = 15; // 직접 히트 임계값
42266
+
42267
+ if (_yDist <= _directHitThreshold) {
42268
+ item.hit = true;
42269
+ }
42178
42270
  }
42179
42271
  }
42180
42272
  }
@@ -42205,6 +42297,8 @@ var element_line_Line = /*#__PURE__*/function () {
42205
42297
  }, {
42206
42298
  key: "findApproximateData",
42207
42299
  value: function findApproximateData(offset) {
42300
+ var _gdata$, _gdata$2;
42301
+
42208
42302
  var xp = offset[0];
42209
42303
  var yp = offset[1];
42210
42304
  var item = {
@@ -42215,41 +42309,87 @@ var element_line_Line = /*#__PURE__*/function () {
42215
42309
  var gdata = this.data.filter(function (data) {
42216
42310
  return !helpers_util.isNullOrUndefined(data.x);
42217
42311
  });
42312
+
42313
+ if (!gdata.length) {
42314
+ return item;
42315
+ } // 동적 감지 범위 계산
42316
+
42317
+
42318
+ var gap = gdata.length > 1 ? Math.abs(((_gdata$ = gdata[1]) === null || _gdata$ === void 0 ? void 0 : _gdata$.xp) - ((_gdata$2 = gdata[0]) === null || _gdata$2 === void 0 ? void 0 : _gdata$2.xp)) : 50;
42319
+ var xpInterval = Math.max(gap * 0.4, 10); // 데이터 간격의 40% 또는 최소 10px
42320
+
42218
42321
  var s = 0;
42219
42322
  var e = gdata.length - 1;
42323
+ var closestIndex = -1;
42324
+ var closestDistance = Infinity; // 이진 탐색으로 근처 데이터 찾기
42220
42325
 
42221
42326
  while (s <= e) {
42222
42327
  var m = Math.floor((s + e) / 2);
42223
- var x = gdata[m].xp;
42224
- var y = gdata[m].yp;
42328
+ var x = gdata[m].xp; // X 좌표가 감지 범위 내에 있는 경우
42329
+
42330
+ if (x - xpInterval <= xp && xp <= x + xpInterval) {
42331
+ // 중간점 주변 데이터들과 거리 비교
42332
+ var checkStart = Math.max(0, m - 2);
42333
+ var checkEnd = Math.min(gdata.length - 1, m + 2);
42225
42334
 
42226
- if (x - 2 <= xp && xp <= x + 2) {
42227
- item.data = gdata[m];
42228
- item.index = m;
42335
+ for (var i = checkStart; i <= checkEnd; i++) {
42336
+ if (gdata[i].xp !== null && gdata[i].yp !== null) {
42337
+ var distance = Math.sqrt(Math.pow(xp - gdata[i].xp, 2) + Math.pow(yp - gdata[i].yp, 2));
42229
42338
 
42230
- if (y - 2 <= yp && yp <= y + 2) {
42231
- item.hit = true;
42339
+ if (distance < closestDistance) {
42340
+ closestDistance = distance;
42341
+ closestIndex = i;
42342
+ }
42343
+ }
42344
+ }
42345
+
42346
+ if (closestIndex !== -1) {
42347
+ item.data = gdata[closestIndex];
42348
+ item.index = closestIndex; // 매우 가까운 경우 hit으로 표시
42349
+
42350
+ if (closestDistance < 5) {
42351
+ item.hit = true;
42352
+ }
42232
42353
  }
42233
42354
 
42234
42355
  return item;
42235
- } else if (x + 2 < xp) {
42356
+ } else if (x + xpInterval < xp) {
42357
+ // 마우스가 오른쪽에 있는 경우
42236
42358
  if (m < e && xp < gdata[m + 1].xp) {
42237
42359
  var curr = Math.abs(gdata[m].xp - xp);
42238
42360
  var next = Math.abs(gdata[m + 1].xp - xp);
42239
42361
  item.data = curr > next ? gdata[m + 1] : gdata[m];
42240
- item.index = curr > next ? m + 1 : m;
42362
+ item.index = curr > next ? m + 1 : m; // Y 거리도 확인하여 hit 판정
42363
+
42364
+ var selectedPoint = item.data;
42365
+ var yDist = Math.abs(yp - selectedPoint.yp);
42366
+
42367
+ if (yDist < 10) {
42368
+ item.hit = true;
42369
+ }
42370
+
42241
42371
  return item;
42242
42372
  }
42243
42373
 
42244
42374
  s = m + 1;
42245
42375
  } else {
42376
+ // 마우스가 왼쪽에 있는 경우
42246
42377
  if (m > 0 && xp > gdata[m - 1].xp) {
42247
42378
  var prev = Math.abs(gdata[m - 1].xp - xp);
42248
42379
 
42249
42380
  var _curr = Math.abs(gdata[m].xp - xp);
42250
42381
 
42251
42382
  item.data = prev > _curr ? gdata[m] : gdata[m - 1];
42252
- item.index = prev > _curr ? m : m - 1;
42383
+ item.index = prev > _curr ? m : m - 1; // Y 거리도 확인하여 hit 판정
42384
+
42385
+ var _selectedPoint = item.data;
42386
+
42387
+ var _yDist2 = Math.abs(yp - _selectedPoint.yp);
42388
+
42389
+ if (_yDist2 < 10) {
42390
+ item.hit = true;
42391
+ }
42392
+
42253
42393
  return item;
42254
42394
  }
42255
42395
 
@@ -42700,6 +42840,7 @@ var element_scatter_Scatter = /*#__PURE__*/function () {
42700
42840
 
42701
42841
 
42702
42842
 
42843
+
42703
42844
  var element_bar_Bar = /*#__PURE__*/function () {
42704
42845
  function Bar(sId, opt, sIdx, isHorizontal) {
42705
42846
  var _this = this;
@@ -42762,18 +42903,11 @@ var element_bar_Bar = /*#__PURE__*/function () {
42762
42903
  var minmaxX = axesSteps.x[this.xAxisIndex];
42763
42904
  var minmaxY = axesSteps.y[this.yAxisIndex];
42764
42905
  var totalCount = this.data.length;
42765
- var minIndex;
42766
- var maxIndex;
42767
42906
 
42768
- if (isHorizontal) {
42769
- var _ref = [minmaxY.minIndex, minmaxY.maxIndex];
42770
- minIndex = _ref[0];
42771
- maxIndex = _ref[1];
42772
- } else {
42773
- var _ref2 = [minmaxX.minIndex, minmaxX.maxIndex];
42774
- minIndex = _ref2[0];
42775
- maxIndex = _ref2[1];
42776
- } // minIndex, maxIndex가 유효하면 실제 그릴 데이터 개수로 보정
42907
+ var _ref = isHorizontal ? [minmaxY.minIndex, minmaxY.maxIndex] : [minmaxX.minIndex, minmaxX.maxIndex],
42908
+ _ref2 = _slicedToArray(_ref, 2),
42909
+ minIndex = _ref2[0],
42910
+ maxIndex = _ref2[1]; // minIndex, maxIndex가 유효하면 실제 그릴 데이터 개수로 보정
42777
42911
 
42778
42912
 
42779
42913
  if (truthyNumber(minIndex) && truthyNumber(maxIndex)) {
@@ -42804,20 +42938,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
42804
42938
  var h;
42805
42939
  bArea = cArea > cPad * 2 ? cArea - cPad * 2 : cArea;
42806
42940
  bArea = this.isExistGrp ? bArea : bArea / showSeriesCount;
42807
-
42808
- var getSize = function getSize() {
42809
- if (typeof thickness === 'string' && /[0-9]+px/.test(thickness)) {
42810
- return Math.min(bArea, Number(thickness.replace('px', '')));
42811
- }
42812
-
42813
- if (typeof thickness === 'number' && thickness <= 1 && thickness >= 0) {
42814
- return Math.ceil(bArea * thickness);
42815
- }
42816
-
42817
- return bArea;
42818
- };
42819
-
42820
- var size = getSize();
42941
+ var size = this.calculateBarSize(thickness, bArea);
42821
42942
  w = isHorizontal ? null : size;
42822
42943
  h = isHorizontal ? size : null;
42823
42944
  var bPad = isHorizontal ? (bArea - h) / 2 : (bArea - w) / 2;
@@ -42845,14 +42966,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
42845
42966
  var _param$selectLabel, _param$selectItem, _param$selectLabel$se, _param$selectLabel2, _param$selectLabel2$s, _param$selectItem$sel, _param$selectItem2;
42846
42967
 
42847
42968
  // 스크롤 offset(minIndex)만큼 보정해서 그리기
42848
- var categoryPoint = void 0;
42849
-
42850
- if (isHorizontal) {
42851
- categoryPoint = ysp - cArea * screenIndex - cPad;
42852
- } else {
42853
- categoryPoint = xsp + cArea * screenIndex + cPad;
42854
- } // 기본 위치 설정
42855
-
42969
+ var categoryPoint = isHorizontal ? ysp - cArea * screenIndex - cPad : xsp + cArea * screenIndex + cPad; // 기본 위치 설정
42856
42970
 
42857
42971
  if (isHorizontal) {
42858
42972
  x = xsp;
@@ -43038,13 +43152,32 @@ var element_bar_Bar = /*#__PURE__*/function () {
43038
43152
  * Find graph item
43039
43153
  * @param {array} offset mouse position
43040
43154
  * @param {boolean} isHorizontal determines if a horizontal option's value
43155
+ * @param {number} dataIndex selected label data index
43156
+ * @param {boolean} useIndicatorOnLabel
43041
43157
  *
43042
43158
  * @returns {object} graph item
43043
43159
  */
43044
43160
 
43045
43161
  }, {
43046
43162
  key: "findGraphData",
43047
- value: function findGraphData(offset, isHorizontal) {
43163
+ value: function findGraphData(offset, isHorizontal, dataIndex, useIndicatorOnLabel) {
43164
+ if (typeof dataIndex === 'number' && this.show && useIndicatorOnLabel) {
43165
+ var gdata = this.data;
43166
+ var item = {
43167
+ data: null,
43168
+ hit: false,
43169
+ color: this.color
43170
+ };
43171
+
43172
+ if (gdata[dataIndex]) {
43173
+ item.data = gdata[dataIndex];
43174
+ item.index = dataIndex;
43175
+ item.hit = this.isPointInBar(offset, gdata[dataIndex]);
43176
+ }
43177
+
43178
+ return item;
43179
+ }
43180
+
43048
43181
  return isHorizontal ? this.findGraphRangeCount(offset) : this.findGraphRange(offset);
43049
43182
  }
43050
43183
  /**
@@ -43054,13 +43187,23 @@ var element_bar_Bar = /*#__PURE__*/function () {
43054
43187
  * @returns {object} graph item
43055
43188
  */
43056
43189
 
43190
+ /**
43191
+ * Binary search for finding graph item
43192
+ * @private
43193
+ * @param {array} offset - mouse position
43194
+ * @param {boolean} isHorizontal - search orientation
43195
+ * @returns {object} graph item
43196
+ */
43197
+
43057
43198
  }, {
43058
- key: "findGraphRange",
43059
- value: function findGraphRange(offset) {
43199
+ key: "binarySearchBar",
43200
+ value: function binarySearchBar(offset, isHorizontal) {
43060
43201
  var _this$filteredCount;
43061
43202
 
43062
- var xp = offset[0];
43063
- var yp = offset[1];
43203
+ var _offset = _slicedToArray(offset, 2),
43204
+ xp = _offset[0],
43205
+ yp = _offset[1];
43206
+
43064
43207
  var item = {
43065
43208
  data: null,
43066
43209
  hit: false,
@@ -43073,21 +43216,25 @@ var element_bar_Bar = /*#__PURE__*/function () {
43073
43216
 
43074
43217
  while (s <= e) {
43075
43218
  var m = Math.floor((s + e) / 2);
43076
- var sx = gdata[m].xp;
43077
- var sy = gdata[m].yp;
43078
- var ex = sx + gdata[m].w;
43079
- var ey = sy + gdata[m].h;
43080
-
43081
- if (sx <= xp && xp <= ex) {
43082
- item.data = gdata[m];
43083
- item.index = gdata[m].index; // 원본 데이터 인덱스 사용
43219
+ var barData = gdata[m];
43220
+ var sx = barData.xp,
43221
+ sy = barData.yp,
43222
+ w = barData.w,
43223
+ h = barData.h;
43224
+ var ex = sx + w;
43225
+ var ey = sy + h;
43226
+ var inRange = isHorizontal ? ey <= yp && yp <= sy : sx <= xp && xp <= ex;
43227
+
43228
+ if (inRange) {
43229
+ item.data = barData;
43230
+ item.index = barData.index;
43231
+ item.hit = this.isPointInBar(offset, barData);
43232
+ return item;
43233
+ }
43084
43234
 
43085
- if (ey <= yp && yp <= sy) {
43086
- item.hit = true;
43087
- }
43235
+ var shouldGoRight = isHorizontal ? !(ey < yp) : sx + 4 < xp;
43088
43236
 
43089
- return item;
43090
- } else if (sx + 4 < xp) {
43237
+ if (shouldGoRight) {
43091
43238
  s = m + 1;
43092
43239
  } else {
43093
43240
  e = m - 1;
@@ -43096,6 +43243,11 @@ var element_bar_Bar = /*#__PURE__*/function () {
43096
43243
 
43097
43244
  return item;
43098
43245
  }
43246
+ }, {
43247
+ key: "findGraphRange",
43248
+ value: function findGraphRange(offset) {
43249
+ return this.binarySearchBar(offset, false);
43250
+ }
43099
43251
  /**
43100
43252
  * Find graph item (horizontal)
43101
43253
  * @param {array} offset mouse position
@@ -43106,44 +43258,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
43106
43258
  }, {
43107
43259
  key: "findGraphRangeCount",
43108
43260
  value: function findGraphRangeCount(offset) {
43109
- var _this$filteredCount2;
43110
-
43111
- var xp = offset[0];
43112
- var yp = offset[1];
43113
- var item = {
43114
- data: null,
43115
- hit: false,
43116
- color: this.color
43117
- };
43118
- var gdata = this.data;
43119
- var totalCount = (_this$filteredCount2 = this.filteredCount) !== null && _this$filteredCount2 !== void 0 ? _this$filteredCount2 : gdata.length;
43120
- var s = 0;
43121
- var e = totalCount - 1;
43122
-
43123
- while (s <= e) {
43124
- var m = Math.floor((s + e) / 2);
43125
- var sx = gdata[m].xp;
43126
- var sy = gdata[m].yp;
43127
- var ex = sx + gdata[m].w;
43128
- var ey = sy + gdata[m].h;
43129
-
43130
- if (ey <= yp && yp <= sy) {
43131
- item.data = gdata[m];
43132
- item.index = gdata[m].index; // 원본 데이터 인덱스 사용
43133
-
43134
- if (sx <= xp && xp <= ex) {
43135
- item.hit = true;
43136
- }
43137
-
43138
- return item;
43139
- } else if (ey < yp) {
43140
- e = m - 1;
43141
- } else {
43142
- s = m + 1;
43143
- }
43144
- }
43145
-
43146
- return item;
43261
+ return this.binarySearchBar(offset, true);
43147
43262
  }
43148
43263
  /**
43149
43264
  * Draw value label if series 'use' of showValue option is true
@@ -43307,14 +43422,36 @@ var element_bar_Bar = /*#__PURE__*/function () {
43307
43422
 
43308
43423
  ctx.restore();
43309
43424
  }
43425
+ /**
43426
+ * Calculate bar size based on thickness
43427
+ * @private
43428
+ * @param {string|number} thickness - thickness value
43429
+ * @param {number} bArea - available bar area
43430
+ * @returns {number} calculated size
43431
+ */
43432
+
43433
+ }, {
43434
+ key: "calculateBarSize",
43435
+ value: function calculateBarSize(thickness, bArea) {
43436
+ if (typeof thickness === 'string' && /[0-9]+px/.test(thickness)) {
43437
+ return Math.min(bArea, Number(thickness.replace('px', '')));
43438
+ }
43439
+
43440
+ if (typeof thickness === 'number' && thickness <= 1 && thickness >= 0) {
43441
+ return Math.ceil(bArea * thickness);
43442
+ }
43443
+
43444
+ return bArea;
43445
+ }
43310
43446
  }, {
43311
43447
  key: "drawBar",
43312
43448
  value: function drawBar(_ref6) {
43313
43449
  var ctx = _ref6.ctx,
43314
43450
  positions = _ref6.positions;
43315
- var isHorizontal = this.isHorizontal;
43451
+ var isHorizontal = this.isHorizontal,
43452
+ borderRadius = this.borderRadius;
43316
43453
  var isStackBar = ('stackIndex' in this);
43317
- var isBorderRadius = this.borderRadius && this.borderRadius > 0;
43454
+ var isBorderRadius = borderRadius && borderRadius > 0;
43318
43455
  var x = positions.x,
43319
43456
  y = positions.y,
43320
43457
  w = positions.w;
@@ -43338,17 +43475,40 @@ var element_bar_Bar = /*#__PURE__*/function () {
43338
43475
 
43339
43476
  ctx.restore();
43340
43477
  }
43478
+ /**
43479
+ * Check if point is within bar boundaries
43480
+ * @param {array} offset - [x, y] mouse position
43481
+ * @param {object} barData - bar data object with xp, yp, w, h properties
43482
+ * @returns {boolean} true if point is within bar
43483
+ */
43484
+
43485
+ }, {
43486
+ key: "isPointInBar",
43487
+ value: function isPointInBar(offset, barData) {
43488
+ var _offset2 = _slicedToArray(offset, 2),
43489
+ xp = _offset2[0],
43490
+ yp = _offset2[1];
43491
+
43492
+ var sx = barData.xp,
43493
+ sy = barData.yp,
43494
+ w = barData.w,
43495
+ h = barData.h;
43496
+ var ex = sx + w;
43497
+ var ey = sy + h;
43498
+ return sx <= xp && xp <= ex && ey <= yp && yp <= sy;
43499
+ }
43341
43500
  }, {
43342
43501
  key: "drawRoundedRect",
43343
43502
  value: function drawRoundedRect(ctx, positions) {
43344
- var chartRect = this.chartRect;
43345
- var labelOffset = this.labelOffset;
43346
- var isHorizontal = this.isHorizontal;
43503
+ var chartRect = this.chartRect,
43504
+ labelOffset = this.labelOffset,
43505
+ isHorizontal = this.isHorizontal,
43506
+ borderRadius = this.borderRadius;
43347
43507
  var x = positions.x,
43348
43508
  y = positions.y;
43349
43509
  var w = positions.w,
43350
43510
  h = positions.h;
43351
- var r = this.borderRadius;
43511
+ var r = borderRadius;
43352
43512
  var squarePath = new Path2D();
43353
43513
  squarePath.rect(chartRect.x1 + labelOffset.left, chartRect.y1, chartRect.chartWidth - labelOffset.right, chartRect.chartHeight - labelOffset.bottom);
43354
43514
  ctx.clip(squarePath);
@@ -44722,7 +44882,7 @@ var element_heatmap_HeatMap = /*#__PURE__*/function () {
44722
44882
  key: "findSelectionRange",
44723
44883
  value: function findSelectionRange(rangeInfo) {
44724
44884
  var xsp = rangeInfo.xsp,
44725
- ycp = rangeInfo.ycp,
44885
+ ysp = rangeInfo.ysp,
44726
44886
  width = rangeInfo.width,
44727
44887
  height = rangeInfo.height,
44728
44888
  range = rangeInfo.range;
@@ -44750,7 +44910,6 @@ var element_heatmap_HeatMap = /*#__PURE__*/function () {
44750
44910
  var gapX = (x2 - x1) / labelXCount;
44751
44911
  var gapY = (y2 - y1) / labelYCount;
44752
44912
  var xep = xsp + width;
44753
- var ysp = ycp;
44754
44913
  var yep = ysp + height;
44755
44914
  var xIndex = {
44756
44915
  min: Math.floor((xsp - x1) / gapX),
@@ -44758,8 +44917,8 @@ var element_heatmap_HeatMap = /*#__PURE__*/function () {
44758
44917
  };
44759
44918
  var lastIndexY = labelYCount - 1;
44760
44919
  var yIndex = {
44761
- min: lastIndexY - Math.floor((yep - y1 - gapY) / gapY),
44762
- max: lastIndexY - Math.floor((ysp - y1) / gapY)
44920
+ min: lastIndexY - Math.round((yep - y1 - gapY) / gapY),
44921
+ max: lastIndexY - Math.round((ysp - y1) / gapY)
44763
44922
  };
44764
44923
  var filteredLabelX = this.getFilteredLabel(labelX, labelXCount, xMin, xMax);
44765
44924
  var filteredLabelY = this.getFilteredLabel(labelY, labelYCount, yMin, yMax);
@@ -45470,10 +45629,6 @@ var scale_Scale = /*#__PURE__*/function () {
45470
45629
  var maxY = aPos.y2; // bottom
45471
45630
 
45472
45631
  (_this$plotBands2 = this.plotBands) === null || _this$plotBands2 === void 0 ? void 0 : _this$plotBands2.forEach(function (plotBand) {
45473
- if (!plotBand.from && !plotBand.to) {
45474
- return;
45475
- }
45476
-
45477
45632
  var mergedPlotBandOpt = lodash_es_defaultsDeep({}, plotBand, PLOT_BAND_OPTION);
45478
45633
  var userDefinedFrom = mergedPlotBandOpt.from,
45479
45634
  userDefinedTo = mergedPlotBandOpt.to,
@@ -50700,7 +50855,7 @@ function toFinite(value) {
50700
50855
  * _.inRange(-3, -2, -6);
50701
50856
  * // => true
50702
50857
  */
50703
- function inRange(number, start, end) {
50858
+ function inRange_inRange(number, start, end) {
50704
50859
  start = lodash_es_toFinite(start);
50705
50860
  if (end === undefined) {
50706
50861
  end = start;
@@ -50712,7 +50867,7 @@ function inRange(number, start, end) {
50712
50867
  return _baseInRange(number, start, end);
50713
50868
  }
50714
50869
 
50715
- /* harmony default export */ var lodash_es_inRange = (inRange);
50870
+ /* harmony default export */ var lodash_es_inRange = (inRange_inRange);
50716
50871
 
50717
50872
  // CONCATENATED MODULE: ./src/components/chart/plugins/plugins.interaction.js
50718
50873
 
@@ -50734,6 +50889,8 @@ function inRange(number, start, end) {
50734
50889
 
50735
50890
 
50736
50891
 
50892
+
50893
+
50737
50894
 
50738
50895
 
50739
50896
 
@@ -50819,6 +50976,29 @@ var plugins_interaction_modules = {
50819
50976
  _this.drawTooltip(hitInfo, _this.tooltipCtx);
50820
50977
  }
50821
50978
  }
50979
+ } // tooltip이 표시될 때 indicator를 해당 라벨 위치로 이동 (line 차트이거나 line series가 포함된 경우)
50980
+
50981
+
50982
+ var hasLineSeries = Object.values(_this.seriesList || {}).some(function (series) {
50983
+ return series.type === 'line';
50984
+ });
50985
+
50986
+ if (tooltip.use && (type === 'line' || hasLineSeries)) {
50987
+ // indicator를 그리고 실제 위치한 라벨 정보를 받음
50988
+ var indicatorInfo = _this.drawIndicatorForTooltip(hitInfo, indicator.color); // 실제 indicator가 위치한 라벨 값을 동기화에 사용
50989
+
50990
+
50991
+ var actualLabelValue = indicatorInfo === null || indicatorInfo === void 0 ? void 0 : indicatorInfo.labelValue;
50992
+
50993
+ var label = _this.getTimeLabel(offset);
50994
+
50995
+ args.hoveredLabel = {
50996
+ horizontal: _this.options.horizontal,
50997
+ label: label,
50998
+ mousePosition: [e.clientX, e.clientY],
50999
+ dataLabel: actualLabelValue,
51000
+ isTooltipBased: true
51001
+ };
50822
51002
  }
50823
51003
  } else if (tooltip.use && _this.isInitTooltip) {
50824
51004
  if (typeof (tooltip === null || tooltip === void 0 ? void 0 : tooltip.returnValue) === 'function') {
@@ -50830,19 +51010,28 @@ var plugins_interaction_modules = {
50830
51010
 
50831
51011
  if (_this.dragInfoBackup) {
50832
51012
  _this.drawSelectionArea(_this.dragInfoBackup);
50833
- }
51013
+ } // tooltip 기반 indicator가 아직 설정되지 않은 경우에만 일반 indicator 처리
51014
+
51015
+
51016
+ if (!args.hoveredLabel && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
51017
+ // line 차트가 아니고 line series가 없거나, tooltip이 없을 때는 일반 indicator 표시
51018
+ var _hasLineSeries = Object.values(_this.seriesList || {}).some(function (series) {
51019
+ return series.type === 'line';
51020
+ });
50834
51021
 
50835
- if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
50836
- _this.drawIndicator(offset, indicator.color);
51022
+ if (type !== 'line' && !_hasLineSeries || !tooltip.use || !Object.keys(hitInfo.items).length) {
51023
+ _this.drawIndicator(offset, indicator.color);
51024
+ }
50837
51025
 
50838
- var label = _this.getTimeLabel(offset);
51026
+ var _label = _this.getTimeLabel(offset);
50839
51027
 
50840
51028
  args.hoveredLabel = {
50841
51029
  horizontal: _this.options.horizontal,
50842
- label: label,
50843
- mousePosition: [e.clientX, e.clientY]
51030
+ label: _label,
51031
+ mousePosition: [e.clientX, e.clientY],
51032
+ isTooltipBased: false
50844
51033
  };
50845
- } else {
51034
+ } else if (!args.hoveredLabel) {
50846
51035
  args.hoveredLabel = {
50847
51036
  label: ''
50848
51037
  };
@@ -51707,6 +51896,8 @@ var plugins_interaction_modules = {
51707
51896
  * @returns {object} hit item information
51708
51897
  */
51709
51898
  findHitItem: function findHitItem(offset) {
51899
+ var _this4 = this;
51900
+
51710
51901
  var sIds = Object.keys(this.seriesList);
51711
51902
  var items = {};
51712
51903
  var isHorizontal = !!this.options.horizontal;
@@ -51716,66 +51907,153 @@ var plugins_interaction_modules = {
51716
51907
  var maxsw = 0;
51717
51908
  var maxv = '';
51718
51909
  var maxg = null;
51719
- var maxSID = null;
51910
+ var maxSID = null; // 파이 차트는 특별한 처리가 필요
51720
51911
 
51721
- for (var ix = 0; ix < sIds.length; ix++) {
51722
- var sId = sIds[ix];
51723
- var series = this.seriesList[sId];
51912
+ if (this.options.type === 'pie') {
51913
+ for (var ix = 0; ix < sIds.length; ix++) {
51914
+ var sId = sIds[ix];
51915
+ var series = this.seriesList[sId];
51916
+
51917
+ if (series.findGraphData && series.show) {
51918
+ var item = series.findGraphData(offset);
51919
+
51920
+ if (item !== null && item !== void 0 && item.data && item.hit) {
51921
+ var gdata = item.data.o;
51922
+
51923
+ if (gdata !== null && gdata !== undefined) {
51924
+ var formattedSeriesName = this.getFormattedTooltipLabel({
51925
+ dataId: series.id,
51926
+ seriesId: sId,
51927
+ seriesName: series.name,
51928
+ itemData: item.data
51929
+ });
51930
+ var sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
51931
+ item.id = series.id;
51932
+ item.name = formattedSeriesName;
51933
+ item.axis = {
51934
+ x: 0,
51935
+ y: 0
51936
+ };
51937
+ items[sId] = item;
51938
+ var formattedTxt = this.getFormattedTooltipValue({
51939
+ dataId: series.id,
51940
+ seriesId: sId,
51941
+ seriesName: formattedSeriesName,
51942
+ value: gdata,
51943
+ itemData: item.data
51944
+ });
51945
+ item.data.formatted = formattedTxt;
51946
+
51947
+ if (maxsw < sw) {
51948
+ maxs = formattedSeriesName;
51949
+ maxsw = sw;
51950
+ }
51724
51951
 
51725
- if (series.findGraphData) {
51726
- var item = series.findGraphData(offset, isHorizontal);
51952
+ if (maxv.length <= "".concat(formattedTxt).length) {
51953
+ maxv = "".concat(formattedTxt);
51954
+ }
51727
51955
 
51728
- if (item !== null && item !== void 0 && item.data) {
51729
- var gdata = void 0;
51956
+ if (maxg === null || maxg <= gdata) {
51957
+ maxg = gdata;
51958
+ maxSID = sId;
51959
+ }
51730
51960
 
51731
- if (item.data.o === null && series.interpolation !== 'zero') {
51732
- if (!series.isExistGrp) {
51733
- gdata = isHorizontal ? item.data.x : item.data.y;
51961
+ hitId = sId;
51734
51962
  }
51735
- } else if (!isNaN(item.data.o)) {
51736
- gdata = item.data.o;
51737
51963
  }
51964
+ }
51965
+ }
51966
+
51967
+ var _maxHighlight2 = maxg !== null ? [maxSID, maxg] : null;
51968
+
51969
+ return {
51970
+ items: items,
51971
+ hitId: hitId,
51972
+ maxTip: [maxs, maxv],
51973
+ maxHighlight: _maxHighlight2
51974
+ };
51975
+ } // 1. 먼저 공통으로 사용할 데이터 인덱스 결정
51976
+
51977
+
51978
+ var targetDataIndex = this.findClosestDataIndex(offset, sIds);
51979
+
51980
+ if (targetDataIndex === -1) {
51981
+ return {
51982
+ items: items,
51983
+ hitId: hitId,
51984
+ maxTip: [maxs, maxv],
51985
+ maxHighlight: null
51986
+ };
51987
+ } // 2. 모든 시리즈가 동일한 데이터 인덱스 사용
51988
+
51989
+
51990
+ var allSeriesIsBar = sIds.every(function (sId) {
51991
+ return _this4.seriesList[sId].type === 'bar';
51992
+ });
51993
+
51994
+ for (var _ix = 0; _ix < sIds.length; _ix++) {
51995
+ var _sId = sIds[_ix];
51996
+ var _series = this.seriesList[_sId];
51997
+
51998
+ if (_series.findGraphData && _series.show) {
51999
+ // 특정 데이터 인덱스로 데이터 요청
52000
+ var _item = _series.findGraphData(offset, isHorizontal, targetDataIndex, !allSeriesIsBar);
52001
+
52002
+ if (_item !== null && _item !== void 0 && _item.data) {
52003
+ var _gdata = void 0;
51738
52004
 
51739
- if (gdata !== null && gdata !== undefined) {
51740
- var formattedSeriesName = this.getFormattedTooltipLabel({
51741
- dataId: series.id,
51742
- seriesId: sId,
51743
- seriesName: series.name,
51744
- itemData: item.data
52005
+ if (_item.data.o === null && _series.interpolation !== 'zero') {
52006
+ if (!_series.isExistGrp) {
52007
+ _gdata = isHorizontal ? _item.data.x : _item.data.y;
52008
+ }
52009
+ } else if (!isNaN(_item.data.o)) {
52010
+ _gdata = _item.data.o;
52011
+ }
52012
+
52013
+ if (_gdata !== null && _gdata !== undefined) {
52014
+ var _formattedSeriesName = this.getFormattedTooltipLabel({
52015
+ dataId: _series.id,
52016
+ seriesId: _sId,
52017
+ seriesName: _series.name,
52018
+ itemData: _item.data
51745
52019
  });
51746
- var sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
51747
- item.id = series.id;
51748
- item.name = formattedSeriesName;
51749
- item.axis = {
51750
- x: series.xAxisIndex,
51751
- y: series.yAxisIndex
52020
+
52021
+ var _sw = ctx ? ctx.measureText(_formattedSeriesName).width : 1;
52022
+
52023
+ _item.id = _series.id;
52024
+ _item.name = _formattedSeriesName;
52025
+ _item.axis = {
52026
+ x: _series.xAxisIndex,
52027
+ y: _series.yAxisIndex
51752
52028
  };
51753
- items[sId] = item;
51754
- var formattedTxt = this.getFormattedTooltipValue({
51755
- dataId: series.id,
51756
- seriesId: sId,
51757
- seriesName: formattedSeriesName,
51758
- value: gdata,
51759
- itemData: item.data
52029
+ items[_sId] = _item;
52030
+
52031
+ var _formattedTxt = this.getFormattedTooltipValue({
52032
+ dataId: _series.id,
52033
+ seriesId: _sId,
52034
+ seriesName: _formattedSeriesName,
52035
+ value: _gdata,
52036
+ itemData: _item.data
51760
52037
  });
51761
- item.data.formatted = formattedTxt;
51762
52038
 
51763
- if (maxsw < sw) {
51764
- maxs = formattedSeriesName;
51765
- maxsw = sw;
52039
+ _item.data.formatted = _formattedTxt;
52040
+
52041
+ if (maxsw < _sw) {
52042
+ maxs = _formattedSeriesName;
52043
+ maxsw = _sw;
51766
52044
  }
51767
52045
 
51768
- if (maxv.length <= "".concat(formattedTxt).length) {
51769
- maxv = "".concat(formattedTxt);
52046
+ if (maxv.length <= "".concat(_formattedTxt).length) {
52047
+ maxv = "".concat(_formattedTxt);
51770
52048
  }
51771
52049
 
51772
- if (maxg === null || maxg <= gdata) {
51773
- maxg = gdata;
51774
- maxSID = sId;
52050
+ if (maxg === null || maxg <= _gdata) {
52051
+ maxg = _gdata;
52052
+ maxSID = _sId;
51775
52053
  }
51776
52054
 
51777
- if (item.hit) {
51778
- hitId = sId;
52055
+ if (_item.hit) {
52056
+ hitId = _sId;
51779
52057
  }
51780
52058
  }
51781
52059
  }
@@ -51792,6 +52070,78 @@ var plugins_interaction_modules = {
51792
52070
  };
51793
52071
  },
51794
52072
 
52073
+ /**
52074
+ * Find the closest data index (label) based on mouse position
52075
+ * @param {array} offset mouse position
52076
+ * @param {array} sIds series IDs
52077
+ * @returns {number} closest data index
52078
+ */
52079
+ findClosestDataIndex: function findClosestDataIndex(offset, sIds) {
52080
+ var _this5 = this,
52081
+ _this$seriesList$refe;
52082
+
52083
+ var _offset = _slicedToArray(offset, 2),
52084
+ xp = _offset[0],
52085
+ yp = _offset[1];
52086
+
52087
+ var isHorizontal = !!this.options.horizontal;
52088
+ var mousePos = isHorizontal ? yp : xp;
52089
+ var closestDistance = Infinity;
52090
+ var closestIndex = -1; // 첫 번째 표시 중인 시리즈를 기준으로 라벨 위치 확인
52091
+
52092
+ var referenceSeries = sIds.find(function (sId) {
52093
+ var _this5$seriesList$sId;
52094
+
52095
+ return (_this5$seriesList$sId = _this5.seriesList[sId]) === null || _this5$seriesList$sId === void 0 ? void 0 : _this5$seriesList$sId.show;
52096
+ });
52097
+
52098
+ if (!referenceSeries || !((_this$seriesList$refe = this.seriesList[referenceSeries]) !== null && _this$seriesList$refe !== void 0 && _this$seriesList$refe.data)) {
52099
+ return -1;
52100
+ }
52101
+
52102
+ var referenceData = this.seriesList[referenceSeries].data; // 각 라벨에서 가장 가까운 것 찾기
52103
+
52104
+ var _loop = function _loop(i) {
52105
+ // 이 라벨에 유효한 데이터가 있는 시리즈가 하나 이상 있는지 확인
52106
+ var hasValidData = sIds.some(function (sId) {
52107
+ var _series$data, _series$data$i, _series$data2, _series$data2$i;
52108
+
52109
+ var series = _this5.seriesList[sId];
52110
+ return (series === null || series === void 0 ? void 0 : series.show) && ((_series$data = series.data) === null || _series$data === void 0 ? void 0 : (_series$data$i = _series$data[i]) === null || _series$data$i === void 0 ? void 0 : _series$data$i.o) !== null && ((_series$data2 = series.data) === null || _series$data2 === void 0 ? void 0 : (_series$data2$i = _series$data2[i]) === null || _series$data2$i === void 0 ? void 0 : _series$data2$i.o) !== undefined;
52111
+ });
52112
+
52113
+ if (hasValidData) {
52114
+ var point = referenceData[i];
52115
+
52116
+ if (point) {
52117
+ // 라벨 위치 계산
52118
+ var labelPos;
52119
+
52120
+ if (isHorizontal) {
52121
+ labelPos = point.h ? point.yp + point.h / 2 : point.yp;
52122
+ } else {
52123
+ labelPos = point.w ? point.xp + point.w / 2 : point.xp;
52124
+ }
52125
+
52126
+ if (labelPos !== null) {
52127
+ var distance = Math.abs(mousePos - labelPos);
52128
+
52129
+ if (distance < closestDistance) {
52130
+ closestDistance = distance;
52131
+ closestIndex = i;
52132
+ }
52133
+ }
52134
+ }
52135
+ }
52136
+ };
52137
+
52138
+ for (var i = 0; i < referenceData.length; i++) {
52139
+ _loop(i);
52140
+ }
52141
+
52142
+ return closestIndex;
52143
+ },
52144
+
51795
52145
  /**
51796
52146
  * get formatted label for tooltip
51797
52147
  * @param dataId
@@ -51921,9 +52271,9 @@ var plugins_interaction_modules = {
51921
52271
  seriesName: formattedSeriesName,
51922
52272
  value: hasData === null || hasData === void 0 ? void 0 : hasData.o,
51923
52273
  itemData: hasData
51924
- });
52274
+ }); // Only add data if there's a valid value for this exact label
51925
52275
 
51926
- if (hasData && !hitInfo.items[sId]) {
52276
+ if (hasData && hasData.o !== null && hasData.o !== undefined && !hitInfo.items[sId]) {
51927
52277
  var item = {};
51928
52278
  item.color = series.color;
51929
52279
  item.hit = false;
@@ -52013,7 +52363,7 @@ var plugins_interaction_modules = {
52013
52363
  * @returns {object[]}
52014
52364
  */
52015
52365
  getSelectedLabelInfoWithLabelData: function getSelectedLabelInfoWithLabelData(labelIndexList, targetAxis) {
52016
- var _this4 = this;
52366
+ var _this6 = this;
52017
52367
 
52018
52368
  var _this$options9 = this.options,
52019
52369
  selectLabelOpt = _this$options9.selectLabel,
@@ -52029,7 +52379,7 @@ var plugins_interaction_modules = {
52029
52379
  {
52030
52380
  result.dataIndex.splice(selectLabelOpt.limit);
52031
52381
  result.label = result.dataIndex.map(function (i) {
52032
- return _this4.data.labels[i];
52382
+ return _this6.data.labels[i];
52033
52383
  });
52034
52384
  var dataEntries = Object.entries(this.data.data);
52035
52385
  result.data = result.dataIndex.map(function (labelIdx) {
@@ -52059,7 +52409,7 @@ var plugins_interaction_modules = {
52059
52409
  }
52060
52410
 
52061
52411
  result.label = result.dataIndex.map(function (i) {
52062
- return _this4.data.labels[targetAxisDirection][i];
52412
+ return _this6.data.labels[targetAxisDirection][i];
52063
52413
  });
52064
52414
  var dataValues = Object.values(this.data.data)[0];
52065
52415
  result.data = dataValues.filter(function (_ref6) {
@@ -52150,6 +52500,76 @@ var plugins_interaction_modules = {
52150
52500
  return after;
52151
52501
  },
52152
52502
 
52503
+ /**
52504
+ * Draw indicator at the label position when tooltip is displayed
52505
+ * @param {object} hitInfo hit item information from findHitItem
52506
+ * @param {string} color indicator color
52507
+ * @returns {object|null} indicator position info with actual label value
52508
+ */
52509
+ drawIndicatorForTooltip: function drawIndicatorForTooltip(hitInfo, color) {
52510
+ var _this$options$indicat;
52511
+
52512
+ if (!(hitInfo !== null && hitInfo !== void 0 && hitInfo.items) || !Object.keys(hitInfo.items).length) {
52513
+ return null;
52514
+ }
52515
+
52516
+ var ctx = this.overlayCtx;
52517
+ var horizontal = this.options.horizontal;
52518
+ var graphPos = {
52519
+ x1: this.chartRect.x1 + this.labelOffset.left,
52520
+ x2: this.chartRect.x2 - this.labelOffset.right,
52521
+ y1: this.chartRect.y1 + this.labelOffset.top,
52522
+ y2: this.chartRect.y2 - this.labelOffset.bottom
52523
+ }; // 첫 번째 시리즈의 데이터를 기준으로 라벨 위치 계산
52524
+
52525
+ var firstSeriesId = Object.keys(hitInfo.items)[0];
52526
+ var firstItem = hitInfo.items[firstSeriesId];
52527
+
52528
+ if (!(firstItem !== null && firstItem !== void 0 && firstItem.data)) {
52529
+ return null;
52530
+ } // 실제 indicator가 위치하는 라벨 값 추출
52531
+
52532
+
52533
+ var actualLabelValue = horizontal ? firstItem.data.y : firstItem.data.x;
52534
+ var indicatorPosition;
52535
+
52536
+ if (horizontal) {
52537
+ // 수평 차트에서는 Y축 라벨 위치에 수평선
52538
+ var yPosition = firstItem.data.yp + (firstItem.data.h ? firstItem.data.h / 2 : 0);
52539
+ indicatorPosition = [graphPos.x1, yPosition];
52540
+ } else {
52541
+ // 수직 차트에서는 X축 라벨 위치에 수직선
52542
+ var xPosition = firstItem.data.xp + (firstItem.data.w ? firstItem.data.w / 2 : 0);
52543
+ indicatorPosition = [xPosition, graphPos.y1];
52544
+ }
52545
+
52546
+ ctx.beginPath();
52547
+ ctx.save();
52548
+ ctx.strokeStyle = color;
52549
+ ctx.lineWidth = 1;
52550
+
52551
+ if ((_this$options$indicat = this.options.indicator) !== null && _this$options$indicat !== void 0 && _this$options$indicat.segments) {
52552
+ ctx.setLineDash(this.options.indicator.segments);
52553
+ }
52554
+
52555
+ if (horizontal) {
52556
+ ctx.moveTo(graphPos.x1, indicatorPosition[1] + 0.5);
52557
+ ctx.lineTo(graphPos.x2, indicatorPosition[1] + 0.5);
52558
+ } else {
52559
+ ctx.moveTo(indicatorPosition[0] + 0.5, graphPos.y1);
52560
+ ctx.lineTo(indicatorPosition[0] + 0.5, graphPos.y2);
52561
+ }
52562
+
52563
+ ctx.stroke();
52564
+ ctx.restore();
52565
+ ctx.closePath(); // 실제 indicator가 위치한 라벨 정보 반환
52566
+
52567
+ return {
52568
+ labelValue: actualLabelValue,
52569
+ position: indicatorPosition
52570
+ };
52571
+ },
52572
+
52153
52573
  /**
52154
52574
  * Find items by series within a range
52155
52575
  * @param {object} range object for find series items
@@ -52282,9 +52702,9 @@ var plugins_interaction_modules = {
52282
52702
  * @returns {string}
52283
52703
  */
52284
52704
  getCurMouseLocation: function getCurMouseLocation(offset) {
52285
- var _offset = _slicedToArray(offset, 2),
52286
- offsetX = _offset[0],
52287
- offsetY = _offset[1];
52705
+ var _offset2 = _slicedToArray(offset, 2),
52706
+ offsetX = _offset2[0],
52707
+ offsetY = _offset2[1];
52288
52708
 
52289
52709
  var aPos = {
52290
52710
  x1: this.chartRect.x1 + this.labelOffset.left,
@@ -52344,6 +52764,8 @@ var plugins_interaction_modules = {
52344
52764
 
52345
52765
 
52346
52766
 
52767
+
52768
+
52347
52769
 
52348
52770
  var LINE_SPACING = 8;
52349
52771
  var VALUE_MARGIN = 50;
@@ -53135,9 +53557,10 @@ var plugins_tooltip_modules = {
53135
53557
  y1: this.chartRect.y1 + this.labelOffset.top,
53136
53558
  y2: this.chartRect.y2 - this.labelOffset.bottom
53137
53559
  };
53138
- var mouseXIp = 1; // mouseInterpolation
53560
+ var mouseXIp = 15; // mouseInterpolation - 더 넓은 범위에서 감지
53561
+
53562
+ var mouseYIp = 15; // Y축도 동일하게 증가
53139
53563
 
53140
- var mouseYIp = 10;
53141
53564
  var options = this.options;
53142
53565
 
53143
53566
  if (offsetX >= graphPos.x1 - mouseXIp && offsetX <= graphPos.x2 + mouseXIp && offsetY >= graphPos.y1 - mouseYIp && offsetY <= graphPos.y2 + mouseYIp) {
@@ -53231,11 +53654,23 @@ var plugins_tooltip_modules = {
53231
53654
 
53232
53655
  var horizontal = _ref5.horizontal,
53233
53656
  label = _ref5.label,
53234
- mousePosition = _ref5.mousePosition;
53657
+ mousePosition = _ref5.mousePosition,
53658
+ dataLabel = _ref5.dataLabel,
53659
+ isTooltipBased = _ref5.isTooltipBased;
53235
53660
 
53236
53661
  if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
53237
53662
  return;
53238
- }
53663
+ } // tooltip 기반 동기화인 경우
53664
+
53665
+
53666
+ if (isTooltipBased) {
53667
+ this.drawSyncedIndicatorForTooltip({
53668
+ dataLabel: dataLabel,
53669
+ mousePosition: mousePosition
53670
+ });
53671
+ return;
53672
+ } // 기존 시간 기반 동기화
53673
+
53239
53674
 
53240
53675
  if (this.options.syncHover === false || !horizontal && !this.options.axesX.every(function (_ref6) {
53241
53676
  var type = _ref6.type;
@@ -53289,6 +53724,82 @@ var plugins_tooltip_modules = {
53289
53724
  }
53290
53725
  },
53291
53726
 
53727
+ /**
53728
+ * 제공된 dataLabel과 일치하는 Label이 있다면 indicator를 그림
53729
+ * @param {object} dataLabel data label
53730
+ * @param {object} mousePosition mouse position
53731
+ *
53732
+ * @returns {undefined}
53733
+ */
53734
+ drawSyncedIndicatorForTooltip: function drawSyncedIndicatorForTooltip(_ref8) {
53735
+ var _this$data;
53736
+
53737
+ var dataLabel = _ref8.dataLabel,
53738
+ mousePosition = _ref8.mousePosition;
53739
+
53740
+ if (!((_this$data = this.data) !== null && _this$data !== void 0 && _this$data.labels) || !dataLabel) {
53741
+ return;
53742
+ }
53743
+
53744
+ var matchingLabelIndex = this.data.labels.findIndex(function (label) {
53745
+ return (label === null || label === void 0 ? void 0 : label.valueOf()) === (dataLabel === null || dataLabel === void 0 ? void 0 : dataLabel.valueOf());
53746
+ });
53747
+
53748
+ if (matchingLabelIndex === -1) {
53749
+ this.overlayClear();
53750
+ return;
53751
+ }
53752
+
53753
+ var horizontal = this.options.horizontal;
53754
+
53755
+ var _this$chartDOM$getBou2 = this.chartDOM.getBoundingClientRect(),
53756
+ top = _this$chartDOM$getBou2.top,
53757
+ bottom = _this$chartDOM$getBou2.bottom,
53758
+ left = _this$chartDOM$getBou2.left,
53759
+ right = _this$chartDOM$getBou2.right;
53760
+
53761
+ var isHoveredChart = lodash_es_inRange(mousePosition[0], left, right) && lodash_es_inRange(mousePosition[1], bottom, top);
53762
+
53763
+ if (isHoveredChart) {
53764
+ return;
53765
+ }
53766
+
53767
+ this.overlayClear();
53768
+ var graphPos = {
53769
+ x1: this.chartRect.x1 + this.labelOffset.left,
53770
+ x2: this.chartRect.x2 - this.labelOffset.right,
53771
+ y1: this.chartRect.y1 + this.labelOffset.top,
53772
+ y2: this.chartRect.y2 - this.labelOffset.bottom
53773
+ };
53774
+ var labelsCount = this.data.labels.length;
53775
+ var indicatorPosition;
53776
+
53777
+ if (horizontal) {
53778
+ var _this$options$axesY;
53779
+
53780
+ var chartHeight = graphPos.y2 - graphPos.y1; // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
53781
+
53782
+ var isCategoryMode = (_this$options$axesY = this.options.axesY) === null || _this$options$axesY === void 0 ? void 0 : _this$options$axesY.some(function (axis) {
53783
+ return axis.categoryMode;
53784
+ });
53785
+ var positionY = isCategoryMode ? graphPos.y1 + chartHeight * (matchingLabelIndex + 0.5) / labelsCount : graphPos.y1 + chartHeight * matchingLabelIndex / (labelsCount - 1);
53786
+ indicatorPosition = [graphPos.x2, positionY];
53787
+ } else {
53788
+ var _this$options$axesX;
53789
+
53790
+ var chartWidth = graphPos.x2 - graphPos.x1; // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
53791
+
53792
+ var _isCategoryMode = (_this$options$axesX = this.options.axesX) === null || _this$options$axesX === void 0 ? void 0 : _this$options$axesX.some(function (axis) {
53793
+ return axis.categoryMode;
53794
+ });
53795
+
53796
+ var positionX = _isCategoryMode ? graphPos.x1 + chartWidth * (matchingLabelIndex + 0.5) / labelsCount : graphPos.x1 + chartWidth * matchingLabelIndex / (labelsCount - 1);
53797
+ indicatorPosition = [positionX, graphPos.y2];
53798
+ }
53799
+
53800
+ this.drawIndicator(indicatorPosition, this.options.indicator.color);
53801
+ },
53802
+
53292
53803
  /**
53293
53804
  * Clear tooltip canvas
53294
53805
  *