evui 3.4.130 → 3.4.131

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.130\"}");
11177
+ module.exports = JSON.parse("{\"a\":\"3.4.131\"}");
11178
11178
 
11179
11179
  /***/ }),
11180
11180
 
@@ -41698,6 +41698,9 @@ var TIME_INTERVALS = {
41698
41698
 
41699
41699
 
41700
41700
 
41701
+
41702
+
41703
+
41701
41704
 
41702
41705
  var element_line_Line = /*#__PURE__*/function () {
41703
41706
  function Line(sId, opt, sIdx) {
@@ -42082,77 +42085,166 @@ var element_line_Line = /*#__PURE__*/function () {
42082
42085
  var gdata = this.data.filter(function (data) {
42083
42086
  return !helpers_util.isNullOrUndefined(data.x);
42084
42087
  });
42085
- var SPARE_XP = 0.5;
42086
42088
  var isLinearInterpolation = this.useLinearInterpolation();
42087
42089
 
42088
42090
  if (gdata !== null && gdata !== void 0 && gdata.length) {
42089
42091
  if (typeof dataIndex === 'number' && this.show) {
42090
42092
  item.data = gdata[dataIndex];
42091
42093
  item.index = dataIndex;
42094
+
42095
+ if (item.data) {
42096
+ var point = gdata[dataIndex];
42097
+ var yDist = Math.abs(yp - point.yp);
42098
+ var directHitThreshold = 15; // 직접 히트 임계값
42099
+
42100
+ if (yDist <= directHitThreshold) {
42101
+ item.hit = true;
42102
+ }
42103
+ }
42092
42104
  } else if (typeof this.beforeFindItemIndex === 'number' && this.show && useSelectLabelOrItem) {
42093
42105
  item.data = gdata[this.beforeFindItemIndex];
42094
42106
  item.index = this.beforeFindItemIndex;
42095
42107
  } else {
42096
- var _gdata$;
42097
-
42098
- var s = 0;
42099
- var e = gdata.length - 1;
42100
- var xpInterval = ((_gdata$ = gdata[1]) === null || _gdata$ === void 0 ? void 0 : _gdata$.xp) - gdata[0].xp < 6 ? 1.5 : 6;
42101
-
42102
- while (s <= e) {
42103
- var m = Math.floor((s + e) / 2);
42104
- var x = gdata[m].xp;
42105
- var y = gdata[m].yp;
42106
-
42107
- if (x - xpInterval < xp && xp < x + xpInterval) {
42108
- var _gdata$m, _gdata$xp, _gdata, _gdata2, _gdata3;
42109
-
42110
- 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);
42111
-
42112
- if ((_gdata2 = gdata[m - 1]) !== null && _gdata2 !== void 0 && _gdata2.xp && (_gdata3 = gdata[m + 1]) !== null && _gdata3 !== void 0 && _gdata3.xp && curXpInterval > 0) {
42113
- var leftXp = xp - gdata[m - 1].xp;
42114
- var midXp = Math.abs(xp - gdata[m].xp);
42115
- var rightXp = gdata[m + 1].xp - xp;
42116
-
42117
- if (Math.abs(this.beforeMouseXp - xp) >= curXpInterval - SPARE_XP && (this.beforeFindItemIndex === m || midXp === rightXp || midXp === leftXp)) {
42118
- if (this.beforeMouseXp - xp > 0) {
42119
- item.data = gdata[this.beforeFindItemIndex - 1];
42120
- item.index = this.beforeFindItemIndex - 1;
42121
- } else if (this.beforeMouseXp - xp < 0) {
42122
- item.data = gdata[this.beforeFindItemIndex + 1];
42123
- item.index = this.beforeFindItemIndex + 1;
42124
- } else if (this.beforeMouseYp !== yp) {
42125
- item.data = gdata[this.beforeFindItemIndex];
42126
- item.index = this.beforeFindItemIndex;
42127
- }
42128
- } else {
42129
- var closeXp = Math.min(leftXp, midXp, rightXp);
42130
-
42131
- if (closeXp === leftXp) {
42132
- item.data = gdata[m - 1];
42133
- item.index = m - 1;
42134
- } else if (closeXp === rightXp) {
42135
- item.data = gdata[m + 1];
42136
- item.index = m + 1;
42137
- } else {
42138
- item.data = gdata[m];
42139
- item.index = m;
42140
- }
42108
+ // Axis 트리거 방식: X축 위치에서 가장 가까운 데이터 포인트 찾기
42109
+ var closestXDistance = Infinity;
42110
+ var closestIndex = -1; // null이 아닌 유효한 데이터만 필터링
42111
+
42112
+ var validData = [];
42113
+ gdata.forEach(function (point, idx) {
42114
+ if (point.xp !== null && point.yp !== null && point.o !== null) {
42115
+ validData.push(_objectSpread2(_objectSpread2({}, point), {}, {
42116
+ originalIndex: idx
42117
+ }));
42118
+ }
42119
+ });
42120
+
42121
+ if (validData.length === 0) {
42122
+ return item;
42123
+ } // 이진 탐색으로 가장 가까운 포인트 찾기
42124
+
42125
+
42126
+ var left = 0;
42127
+ var right = validData.length - 1;
42128
+
42129
+ while (left <= right) {
42130
+ var mid = Math.floor((left + right) / 2);
42131
+ var _point = validData[mid];
42132
+ var xDistance = Math.abs(xp - _point.xp);
42133
+
42134
+ if (xDistance < closestXDistance) {
42135
+ closestXDistance = xDistance;
42136
+ closestIndex = _point.originalIndex;
42137
+ }
42138
+
42139
+ if (_point.xp < xp) {
42140
+ left = mid + 1; // 다음 포인트도 확인
42141
+
42142
+ if (left < validData.length) {
42143
+ var nextDistance = Math.abs(xp - validData[left].xp);
42144
+
42145
+ if (nextDistance < closestXDistance) {
42146
+ closestXDistance = nextDistance;
42147
+ closestIndex = validData[left].originalIndex;
42141
42148
  }
42142
- } else {
42143
- item.data = gdata[m];
42144
- item.index = m;
42145
42149
  }
42150
+ } else if (_point.xp > xp) {
42151
+ right = mid - 1; // 이전 포인트도 확인
42146
42152
 
42147
- if (y - 6 <= yp && yp <= y + 6) {
42148
- item.hit = true;
42149
- }
42153
+ if (right >= 0) {
42154
+ var prevDistance = Math.abs(xp - validData[right].xp);
42150
42155
 
42156
+ if (prevDistance < closestXDistance) {
42157
+ closestXDistance = prevDistance;
42158
+ closestIndex = validData[right].originalIndex;
42159
+ }
42160
+ }
42161
+ } else {
42162
+ // 정확히 일치하는 경우
42151
42163
  break;
42152
- } else if (x + xpInterval > xp) {
42153
- e = m - 1;
42164
+ }
42165
+ } // 이진 탐색 후 주변 포인트 추가 확인 (정확도 향상)
42166
+
42167
+
42168
+ var foundIdx = validData.findIndex(function (p) {
42169
+ return p.originalIndex === closestIndex;
42170
+ });
42171
+
42172
+ if (foundIdx !== -1) {
42173
+ // 앞뒤 2개씩 추가 확인
42174
+ for (var i = Math.max(0, foundIdx - 2); i <= Math.min(validData.length - 1, foundIdx + 2); i++) {
42175
+ var _point2 = validData[i];
42176
+
42177
+ var _xDistance = Math.abs(xp - _point2.xp);
42178
+
42179
+ if (_xDistance < closestXDistance) {
42180
+ closestXDistance = _xDistance;
42181
+ closestIndex = _point2.originalIndex;
42182
+ }
42183
+ }
42184
+ } // 가장 가까운 포인트 설정
42185
+
42186
+
42187
+ if (closestIndex !== -1) {
42188
+ // 데이터 간격 계산 - 모든 데이터(null 포함)의 평균 간격 사용
42189
+ var avgInterval = 50;
42190
+
42191
+ if (gdata.length > 1) {
42192
+ var intervals = [];
42193
+
42194
+ for (var _i = 1; _i < gdata.length; _i++) {
42195
+ if (gdata[_i].xp !== null && gdata[_i - 1].xp !== null) {
42196
+ intervals.push(Math.abs(gdata[_i].xp - gdata[_i - 1].xp));
42197
+ }
42198
+ }
42199
+
42200
+ if (intervals.length > 0) {
42201
+ avgInterval = intervals.reduce(function (a, b) {
42202
+ return a + b;
42203
+ }, 0) / intervals.length;
42204
+ }
42205
+ } // 두 가지 임계값 설정
42206
+
42207
+
42208
+ var strictThreshold = avgInterval * 0.3; // 엄격한 임계값: 데이터 간격의 30%
42209
+
42210
+ var relaxedThreshold = avgInterval; // 느슨한 임계값: 데이터 간격 전체
42211
+ // 1. 먼저 엄격한 임계값으로 정확한 매치 확인
42212
+
42213
+ if (closestXDistance <= strictThreshold) {
42214
+ // 정확히 일치하거나 매우 가까운 데이터가 있음
42215
+ item.data = gdata[closestIndex];
42216
+ item.index = closestIndex;
42154
42217
  } else {
42155
- s = m + 1;
42218
+ // 2. 정확한 매치가 없을 때, 현재 X 위치 근처에 다른 유효 데이터가 있는지 확인
42219
+ var hasNearbyValidData = false;
42220
+
42221
+ for (var _i2 = 0; _i2 < validData.length; _i2++) {
42222
+ var xDist = Math.abs(xp - validData[_i2].xp);
42223
+
42224
+ if (xDist <= strictThreshold) {
42225
+ hasNearbyValidData = true;
42226
+ break;
42227
+ }
42228
+ } // 3. 근처에 다른 유효 데이터가 없을 때만 느슨한 임계값 적용
42229
+
42230
+
42231
+ if (!hasNearbyValidData && closestXDistance <= relaxedThreshold) {
42232
+ item.data = gdata[closestIndex];
42233
+ item.index = closestIndex;
42234
+ }
42235
+ } // Y축 거리를 확인하여 직접 히트 판정
42236
+
42237
+
42238
+ if (item.data) {
42239
+ var _point3 = gdata[closestIndex];
42240
+
42241
+ var _yDist = Math.abs(yp - _point3.yp);
42242
+
42243
+ var _directHitThreshold = 15; // 직접 히트 임계값
42244
+
42245
+ if (_yDist <= _directHitThreshold) {
42246
+ item.hit = true;
42247
+ }
42156
42248
  }
42157
42249
  }
42158
42250
  }
@@ -42183,6 +42275,8 @@ var element_line_Line = /*#__PURE__*/function () {
42183
42275
  }, {
42184
42276
  key: "findApproximateData",
42185
42277
  value: function findApproximateData(offset) {
42278
+ var _gdata$, _gdata$2;
42279
+
42186
42280
  var xp = offset[0];
42187
42281
  var yp = offset[1];
42188
42282
  var item = {
@@ -42193,41 +42287,87 @@ var element_line_Line = /*#__PURE__*/function () {
42193
42287
  var gdata = this.data.filter(function (data) {
42194
42288
  return !helpers_util.isNullOrUndefined(data.x);
42195
42289
  });
42290
+
42291
+ if (!gdata.length) {
42292
+ return item;
42293
+ } // 동적 감지 범위 계산
42294
+
42295
+
42296
+ 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;
42297
+ var xpInterval = Math.max(gap * 0.4, 10); // 데이터 간격의 40% 또는 최소 10px
42298
+
42196
42299
  var s = 0;
42197
42300
  var e = gdata.length - 1;
42301
+ var closestIndex = -1;
42302
+ var closestDistance = Infinity; // 이진 탐색으로 근처 데이터 찾기
42198
42303
 
42199
42304
  while (s <= e) {
42200
42305
  var m = Math.floor((s + e) / 2);
42201
- var x = gdata[m].xp;
42202
- var y = gdata[m].yp;
42306
+ var x = gdata[m].xp; // X 좌표가 감지 범위 내에 있는 경우
42307
+
42308
+ if (x - xpInterval <= xp && xp <= x + xpInterval) {
42309
+ // 중간점 주변 데이터들과 거리 비교
42310
+ var checkStart = Math.max(0, m - 2);
42311
+ var checkEnd = Math.min(gdata.length - 1, m + 2);
42203
42312
 
42204
- if (x - 2 <= xp && xp <= x + 2) {
42205
- item.data = gdata[m];
42206
- item.index = m;
42313
+ for (var i = checkStart; i <= checkEnd; i++) {
42314
+ if (gdata[i].xp !== null && gdata[i].yp !== null) {
42315
+ var distance = Math.sqrt(Math.pow(xp - gdata[i].xp, 2) + Math.pow(yp - gdata[i].yp, 2));
42207
42316
 
42208
- if (y - 2 <= yp && yp <= y + 2) {
42209
- item.hit = true;
42317
+ if (distance < closestDistance) {
42318
+ closestDistance = distance;
42319
+ closestIndex = i;
42320
+ }
42321
+ }
42322
+ }
42323
+
42324
+ if (closestIndex !== -1) {
42325
+ item.data = gdata[closestIndex];
42326
+ item.index = closestIndex; // 매우 가까운 경우 hit으로 표시
42327
+
42328
+ if (closestDistance < 5) {
42329
+ item.hit = true;
42330
+ }
42210
42331
  }
42211
42332
 
42212
42333
  return item;
42213
- } else if (x + 2 < xp) {
42334
+ } else if (x + xpInterval < xp) {
42335
+ // 마우스가 오른쪽에 있는 경우
42214
42336
  if (m < e && xp < gdata[m + 1].xp) {
42215
42337
  var curr = Math.abs(gdata[m].xp - xp);
42216
42338
  var next = Math.abs(gdata[m + 1].xp - xp);
42217
42339
  item.data = curr > next ? gdata[m + 1] : gdata[m];
42218
- item.index = curr > next ? m + 1 : m;
42340
+ item.index = curr > next ? m + 1 : m; // Y 거리도 확인하여 hit 판정
42341
+
42342
+ var selectedPoint = item.data;
42343
+ var yDist = Math.abs(yp - selectedPoint.yp);
42344
+
42345
+ if (yDist < 10) {
42346
+ item.hit = true;
42347
+ }
42348
+
42219
42349
  return item;
42220
42350
  }
42221
42351
 
42222
42352
  s = m + 1;
42223
42353
  } else {
42354
+ // 마우스가 왼쪽에 있는 경우
42224
42355
  if (m > 0 && xp > gdata[m - 1].xp) {
42225
42356
  var prev = Math.abs(gdata[m - 1].xp - xp);
42226
42357
 
42227
42358
  var _curr = Math.abs(gdata[m].xp - xp);
42228
42359
 
42229
42360
  item.data = prev > _curr ? gdata[m] : gdata[m - 1];
42230
- item.index = prev > _curr ? m : m - 1;
42361
+ item.index = prev > _curr ? m : m - 1; // Y 거리도 확인하여 hit 판정
42362
+
42363
+ var _selectedPoint = item.data;
42364
+
42365
+ var _yDist2 = Math.abs(yp - _selectedPoint.yp);
42366
+
42367
+ if (_yDist2 < 10) {
42368
+ item.hit = true;
42369
+ }
42370
+
42231
42371
  return item;
42232
42372
  }
42233
42373
 
@@ -42678,6 +42818,7 @@ var element_scatter_Scatter = /*#__PURE__*/function () {
42678
42818
 
42679
42819
 
42680
42820
 
42821
+
42681
42822
  var element_bar_Bar = /*#__PURE__*/function () {
42682
42823
  function Bar(sId, opt, sIdx, isHorizontal) {
42683
42824
  var _this = this;
@@ -42740,18 +42881,11 @@ var element_bar_Bar = /*#__PURE__*/function () {
42740
42881
  var minmaxX = axesSteps.x[this.xAxisIndex];
42741
42882
  var minmaxY = axesSteps.y[this.yAxisIndex];
42742
42883
  var totalCount = this.data.length;
42743
- var minIndex;
42744
- var maxIndex;
42745
42884
 
42746
- if (isHorizontal) {
42747
- var _ref = [minmaxY.minIndex, minmaxY.maxIndex];
42748
- minIndex = _ref[0];
42749
- maxIndex = _ref[1];
42750
- } else {
42751
- var _ref2 = [minmaxX.minIndex, minmaxX.maxIndex];
42752
- minIndex = _ref2[0];
42753
- maxIndex = _ref2[1];
42754
- } // minIndex, maxIndex가 유효하면 실제 그릴 데이터 개수로 보정
42885
+ var _ref = isHorizontal ? [minmaxY.minIndex, minmaxY.maxIndex] : [minmaxX.minIndex, minmaxX.maxIndex],
42886
+ _ref2 = _slicedToArray(_ref, 2),
42887
+ minIndex = _ref2[0],
42888
+ maxIndex = _ref2[1]; // minIndex, maxIndex가 유효하면 실제 그릴 데이터 개수로 보정
42755
42889
 
42756
42890
 
42757
42891
  if (truthyNumber(minIndex) && truthyNumber(maxIndex)) {
@@ -42778,20 +42912,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
42778
42912
  var h;
42779
42913
  bArea = cArea > cPad * 2 ? cArea - cPad * 2 : cArea;
42780
42914
  bArea = this.isExistGrp ? bArea : bArea / showSeriesCount;
42781
-
42782
- var getSize = function getSize() {
42783
- if (typeof thickness === 'string' && /[0-9]+px/.test(thickness)) {
42784
- return Math.min(bArea, Number(thickness.replace('px', '')));
42785
- }
42786
-
42787
- if (typeof thickness === 'number' && thickness <= 1 && thickness >= 0) {
42788
- return Math.ceil(bArea * thickness);
42789
- }
42790
-
42791
- return bArea;
42792
- };
42793
-
42794
- var size = getSize();
42915
+ var size = this.calculateBarSize(thickness, bArea);
42795
42916
  w = isHorizontal ? null : size;
42796
42917
  h = isHorizontal ? size : null;
42797
42918
  var bPad = isHorizontal ? (bArea - h) / 2 : (bArea - w) / 2;
@@ -42819,13 +42940,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
42819
42940
  var _param$selectLabel, _param$selectItem, _param$selectLabel$se, _param$selectLabel2, _param$selectLabel2$s, _param$selectItem$sel, _param$selectItem2;
42820
42941
 
42821
42942
  // 스크롤 offset(minIndex)만큼 보정해서 그리기
42822
- var categoryPoint = void 0;
42823
-
42824
- if (isHorizontal) {
42825
- categoryPoint = ysp - cArea * screenIndex - cPad;
42826
- } else {
42827
- categoryPoint = xsp + cArea * screenIndex + cPad;
42828
- }
42943
+ var categoryPoint = isHorizontal ? ysp - cArea * screenIndex - cPad : xsp + cArea * screenIndex + cPad;
42829
42944
 
42830
42945
  if (isHorizontal) {
42831
42946
  x = xsp;
@@ -43003,13 +43118,32 @@ var element_bar_Bar = /*#__PURE__*/function () {
43003
43118
  * Find graph item
43004
43119
  * @param {array} offset mouse position
43005
43120
  * @param {boolean} isHorizontal determines if a horizontal option's value
43121
+ * @param {number} dataIndex selected label data index
43122
+ * @param {boolean} useIndicatorOnLabel
43006
43123
  *
43007
43124
  * @returns {object} graph item
43008
43125
  */
43009
43126
 
43010
43127
  }, {
43011
43128
  key: "findGraphData",
43012
- value: function findGraphData(offset, isHorizontal) {
43129
+ value: function findGraphData(offset, isHorizontal, dataIndex, useIndicatorOnLabel) {
43130
+ if (typeof dataIndex === 'number' && this.show && useIndicatorOnLabel) {
43131
+ var gdata = this.data;
43132
+ var item = {
43133
+ data: null,
43134
+ hit: false,
43135
+ color: this.color
43136
+ };
43137
+
43138
+ if (gdata[dataIndex]) {
43139
+ item.data = gdata[dataIndex];
43140
+ item.index = dataIndex;
43141
+ item.hit = this.isPointInBar(offset, gdata[dataIndex]);
43142
+ }
43143
+
43144
+ return item;
43145
+ }
43146
+
43013
43147
  return isHorizontal ? this.findGraphRangeCount(offset) : this.findGraphRange(offset);
43014
43148
  }
43015
43149
  /**
@@ -43019,13 +43153,23 @@ var element_bar_Bar = /*#__PURE__*/function () {
43019
43153
  * @returns {object} graph item
43020
43154
  */
43021
43155
 
43156
+ /**
43157
+ * Binary search for finding graph item
43158
+ * @private
43159
+ * @param {array} offset - mouse position
43160
+ * @param {boolean} isHorizontal - search orientation
43161
+ * @returns {object} graph item
43162
+ */
43163
+
43022
43164
  }, {
43023
- key: "findGraphRange",
43024
- value: function findGraphRange(offset) {
43165
+ key: "binarySearchBar",
43166
+ value: function binarySearchBar(offset, isHorizontal) {
43025
43167
  var _this$filteredCount;
43026
43168
 
43027
- var xp = offset[0];
43028
- var yp = offset[1];
43169
+ var _offset = _slicedToArray(offset, 2),
43170
+ xp = _offset[0],
43171
+ yp = _offset[1];
43172
+
43029
43173
  var item = {
43030
43174
  data: null,
43031
43175
  hit: false,
@@ -43038,21 +43182,25 @@ var element_bar_Bar = /*#__PURE__*/function () {
43038
43182
 
43039
43183
  while (s <= e) {
43040
43184
  var m = Math.floor((s + e) / 2);
43041
- var sx = gdata[m].xp;
43042
- var sy = gdata[m].yp;
43043
- var ex = sx + gdata[m].w;
43044
- var ey = sy + gdata[m].h;
43045
-
43046
- if (sx <= xp && xp <= ex) {
43047
- item.data = gdata[m];
43048
- item.index = gdata[m].index; // 원본 데이터 인덱스 사용
43185
+ var barData = gdata[m];
43186
+ var sx = barData.xp,
43187
+ sy = barData.yp,
43188
+ w = barData.w,
43189
+ h = barData.h;
43190
+ var ex = sx + w;
43191
+ var ey = sy + h;
43192
+ var inRange = isHorizontal ? ey <= yp && yp <= sy : sx <= xp && xp <= ex;
43193
+
43194
+ if (inRange) {
43195
+ item.data = barData;
43196
+ item.index = barData.index;
43197
+ item.hit = this.isPointInBar(offset, barData);
43198
+ return item;
43199
+ }
43049
43200
 
43050
- if (ey <= yp && yp <= sy) {
43051
- item.hit = true;
43052
- }
43201
+ var shouldGoRight = isHorizontal ? !(ey < yp) : sx + 4 < xp;
43053
43202
 
43054
- return item;
43055
- } else if (sx + 4 < xp) {
43203
+ if (shouldGoRight) {
43056
43204
  s = m + 1;
43057
43205
  } else {
43058
43206
  e = m - 1;
@@ -43061,6 +43209,11 @@ var element_bar_Bar = /*#__PURE__*/function () {
43061
43209
 
43062
43210
  return item;
43063
43211
  }
43212
+ }, {
43213
+ key: "findGraphRange",
43214
+ value: function findGraphRange(offset) {
43215
+ return this.binarySearchBar(offset, false);
43216
+ }
43064
43217
  /**
43065
43218
  * Find graph item (horizontal)
43066
43219
  * @param {array} offset mouse position
@@ -43071,44 +43224,7 @@ var element_bar_Bar = /*#__PURE__*/function () {
43071
43224
  }, {
43072
43225
  key: "findGraphRangeCount",
43073
43226
  value: function findGraphRangeCount(offset) {
43074
- var _this$filteredCount2;
43075
-
43076
- var xp = offset[0];
43077
- var yp = offset[1];
43078
- var item = {
43079
- data: null,
43080
- hit: false,
43081
- color: this.color
43082
- };
43083
- var gdata = this.data;
43084
- var totalCount = (_this$filteredCount2 = this.filteredCount) !== null && _this$filteredCount2 !== void 0 ? _this$filteredCount2 : gdata.length;
43085
- var s = 0;
43086
- var e = totalCount - 1;
43087
-
43088
- while (s <= e) {
43089
- var m = Math.floor((s + e) / 2);
43090
- var sx = gdata[m].xp;
43091
- var sy = gdata[m].yp;
43092
- var ex = sx + gdata[m].w;
43093
- var ey = sy + gdata[m].h;
43094
-
43095
- if (ey <= yp && yp <= sy) {
43096
- item.data = gdata[m];
43097
- item.index = gdata[m].index; // 원본 데이터 인덱스 사용
43098
-
43099
- if (sx <= xp && xp <= ex) {
43100
- item.hit = true;
43101
- }
43102
-
43103
- return item;
43104
- } else if (ey < yp) {
43105
- e = m - 1;
43106
- } else {
43107
- s = m + 1;
43108
- }
43109
- }
43110
-
43111
- return item;
43227
+ return this.binarySearchBar(offset, true);
43112
43228
  }
43113
43229
  /**
43114
43230
  * Draw value label if series 'use' of showValue option is true
@@ -43247,14 +43363,36 @@ var element_bar_Bar = /*#__PURE__*/function () {
43247
43363
 
43248
43364
  ctx.restore();
43249
43365
  }
43366
+ /**
43367
+ * Calculate bar size based on thickness
43368
+ * @private
43369
+ * @param {string|number} thickness - thickness value
43370
+ * @param {number} bArea - available bar area
43371
+ * @returns {number} calculated size
43372
+ */
43373
+
43374
+ }, {
43375
+ key: "calculateBarSize",
43376
+ value: function calculateBarSize(thickness, bArea) {
43377
+ if (typeof thickness === 'string' && /[0-9]+px/.test(thickness)) {
43378
+ return Math.min(bArea, Number(thickness.replace('px', '')));
43379
+ }
43380
+
43381
+ if (typeof thickness === 'number' && thickness <= 1 && thickness >= 0) {
43382
+ return Math.ceil(bArea * thickness);
43383
+ }
43384
+
43385
+ return bArea;
43386
+ }
43250
43387
  }, {
43251
43388
  key: "drawBar",
43252
43389
  value: function drawBar(_ref6) {
43253
43390
  var ctx = _ref6.ctx,
43254
43391
  positions = _ref6.positions;
43255
- var isHorizontal = this.isHorizontal;
43392
+ var isHorizontal = this.isHorizontal,
43393
+ borderRadius = this.borderRadius;
43256
43394
  var isStackBar = ('stackIndex' in this);
43257
- var isBorderRadius = this.borderRadius && this.borderRadius > 0;
43395
+ var isBorderRadius = borderRadius && borderRadius > 0;
43258
43396
  var x = positions.x,
43259
43397
  y = positions.y,
43260
43398
  w = positions.w;
@@ -43278,17 +43416,40 @@ var element_bar_Bar = /*#__PURE__*/function () {
43278
43416
 
43279
43417
  ctx.restore();
43280
43418
  }
43419
+ /**
43420
+ * Check if point is within bar boundaries
43421
+ * @param {array} offset - [x, y] mouse position
43422
+ * @param {object} barData - bar data object with xp, yp, w, h properties
43423
+ * @returns {boolean} true if point is within bar
43424
+ */
43425
+
43426
+ }, {
43427
+ key: "isPointInBar",
43428
+ value: function isPointInBar(offset, barData) {
43429
+ var _offset2 = _slicedToArray(offset, 2),
43430
+ xp = _offset2[0],
43431
+ yp = _offset2[1];
43432
+
43433
+ var sx = barData.xp,
43434
+ sy = barData.yp,
43435
+ w = barData.w,
43436
+ h = barData.h;
43437
+ var ex = sx + w;
43438
+ var ey = sy + h;
43439
+ return sx <= xp && xp <= ex && ey <= yp && yp <= sy;
43440
+ }
43281
43441
  }, {
43282
43442
  key: "drawRoundedRect",
43283
43443
  value: function drawRoundedRect(ctx, positions) {
43284
- var chartRect = this.chartRect;
43285
- var labelOffset = this.labelOffset;
43286
- var isHorizontal = this.isHorizontal;
43444
+ var chartRect = this.chartRect,
43445
+ labelOffset = this.labelOffset,
43446
+ isHorizontal = this.isHorizontal,
43447
+ borderRadius = this.borderRadius;
43287
43448
  var x = positions.x,
43288
43449
  y = positions.y;
43289
43450
  var w = positions.w,
43290
43451
  h = positions.h;
43291
- var r = this.borderRadius;
43452
+ var r = borderRadius;
43292
43453
  var squarePath = new Path2D();
43293
43454
  squarePath.rect(chartRect.x1 + labelOffset.left, chartRect.y1, chartRect.chartWidth - labelOffset.right, chartRect.chartHeight - labelOffset.bottom);
43294
43455
  ctx.clip(squarePath);
@@ -50430,7 +50591,7 @@ function toFinite(value) {
50430
50591
  * _.inRange(-3, -2, -6);
50431
50592
  * // => true
50432
50593
  */
50433
- function inRange(number, start, end) {
50594
+ function inRange_inRange(number, start, end) {
50434
50595
  start = lodash_es_toFinite(start);
50435
50596
  if (end === undefined) {
50436
50597
  end = start;
@@ -50442,7 +50603,7 @@ function inRange(number, start, end) {
50442
50603
  return _baseInRange(number, start, end);
50443
50604
  }
50444
50605
 
50445
- /* harmony default export */ var lodash_es_inRange = (inRange);
50606
+ /* harmony default export */ var lodash_es_inRange = (inRange_inRange);
50446
50607
 
50447
50608
  // CONCATENATED MODULE: ./src/components/chart/plugins/plugins.interaction.js
50448
50609
 
@@ -50464,6 +50625,8 @@ function inRange(number, start, end) {
50464
50625
 
50465
50626
 
50466
50627
 
50628
+
50629
+
50467
50630
 
50468
50631
 
50469
50632
 
@@ -50549,6 +50712,29 @@ var plugins_interaction_modules = {
50549
50712
  _this.drawTooltip(hitInfo, _this.tooltipCtx);
50550
50713
  }
50551
50714
  }
50715
+ } // tooltip이 표시될 때 indicator를 해당 라벨 위치로 이동 (line 차트이거나 line series가 포함된 경우)
50716
+
50717
+
50718
+ var hasLineSeries = Object.values(_this.seriesList || {}).some(function (series) {
50719
+ return series.type === 'line';
50720
+ });
50721
+
50722
+ if (tooltip.use && (type === 'line' || hasLineSeries)) {
50723
+ // indicator를 그리고 실제 위치한 라벨 정보를 받음
50724
+ var indicatorInfo = _this.drawIndicatorForTooltip(hitInfo, indicator.color); // 실제 indicator가 위치한 라벨 값을 동기화에 사용
50725
+
50726
+
50727
+ var actualLabelValue = indicatorInfo === null || indicatorInfo === void 0 ? void 0 : indicatorInfo.labelValue;
50728
+
50729
+ var label = _this.getTimeLabel(offset);
50730
+
50731
+ args.hoveredLabel = {
50732
+ horizontal: _this.options.horizontal,
50733
+ label: label,
50734
+ mousePosition: [e.clientX, e.clientY],
50735
+ dataLabel: actualLabelValue,
50736
+ isTooltipBased: true
50737
+ };
50552
50738
  }
50553
50739
  } else if (tooltip.use && _this.isInitTooltip) {
50554
50740
  if (typeof (tooltip === null || tooltip === void 0 ? void 0 : tooltip.returnValue) === 'function') {
@@ -50560,19 +50746,28 @@ var plugins_interaction_modules = {
50560
50746
 
50561
50747
  if (_this.dragInfoBackup) {
50562
50748
  _this.drawSelectionArea(_this.dragInfoBackup);
50563
- }
50749
+ } // tooltip 기반 indicator가 아직 설정되지 않은 경우에만 일반 indicator 처리
50750
+
50564
50751
 
50565
- if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
50566
- _this.drawIndicator(offset, indicator.color);
50752
+ if (!args.hoveredLabel && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
50753
+ // line 차트가 아니고 line series가 없거나, tooltip이 없을 때는 일반 indicator 표시
50754
+ var _hasLineSeries = Object.values(_this.seriesList || {}).some(function (series) {
50755
+ return series.type === 'line';
50756
+ });
50757
+
50758
+ if (type !== 'line' && !_hasLineSeries || !tooltip.use || !Object.keys(hitInfo.items).length) {
50759
+ _this.drawIndicator(offset, indicator.color);
50760
+ }
50567
50761
 
50568
- var label = _this.getTimeLabel(offset);
50762
+ var _label = _this.getTimeLabel(offset);
50569
50763
 
50570
50764
  args.hoveredLabel = {
50571
50765
  horizontal: _this.options.horizontal,
50572
- label: label,
50573
- mousePosition: [e.clientX, e.clientY]
50766
+ label: _label,
50767
+ mousePosition: [e.clientX, e.clientY],
50768
+ isTooltipBased: false
50574
50769
  };
50575
- } else {
50770
+ } else if (!args.hoveredLabel) {
50576
50771
  args.hoveredLabel = {
50577
50772
  label: ''
50578
50773
  };
@@ -51437,6 +51632,8 @@ var plugins_interaction_modules = {
51437
51632
  * @returns {object} hit item information
51438
51633
  */
51439
51634
  findHitItem: function findHitItem(offset) {
51635
+ var _this4 = this;
51636
+
51440
51637
  var sIds = Object.keys(this.seriesList);
51441
51638
  var items = {};
51442
51639
  var isHorizontal = !!this.options.horizontal;
@@ -51446,66 +51643,153 @@ var plugins_interaction_modules = {
51446
51643
  var maxsw = 0;
51447
51644
  var maxv = '';
51448
51645
  var maxg = null;
51449
- var maxSID = null;
51646
+ var maxSID = null; // 파이 차트는 특별한 처리가 필요
51450
51647
 
51451
- for (var ix = 0; ix < sIds.length; ix++) {
51452
- var sId = sIds[ix];
51453
- var series = this.seriesList[sId];
51648
+ if (this.options.type === 'pie') {
51649
+ for (var ix = 0; ix < sIds.length; ix++) {
51650
+ var sId = sIds[ix];
51651
+ var series = this.seriesList[sId];
51652
+
51653
+ if (series.findGraphData && series.show) {
51654
+ var item = series.findGraphData(offset);
51655
+
51656
+ if (item !== null && item !== void 0 && item.data && item.hit) {
51657
+ var gdata = item.data.o;
51658
+
51659
+ if (gdata !== null && gdata !== undefined) {
51660
+ var formattedSeriesName = this.getFormattedTooltipLabel({
51661
+ dataId: series.id,
51662
+ seriesId: sId,
51663
+ seriesName: series.name,
51664
+ itemData: item.data
51665
+ });
51666
+ var sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
51667
+ item.id = series.id;
51668
+ item.name = formattedSeriesName;
51669
+ item.axis = {
51670
+ x: 0,
51671
+ y: 0
51672
+ };
51673
+ items[sId] = item;
51674
+ var formattedTxt = this.getFormattedTooltipValue({
51675
+ dataId: series.id,
51676
+ seriesId: sId,
51677
+ seriesName: formattedSeriesName,
51678
+ value: gdata,
51679
+ itemData: item.data
51680
+ });
51681
+ item.data.formatted = formattedTxt;
51682
+
51683
+ if (maxsw < sw) {
51684
+ maxs = formattedSeriesName;
51685
+ maxsw = sw;
51686
+ }
51687
+
51688
+ if (maxv.length <= "".concat(formattedTxt).length) {
51689
+ maxv = "".concat(formattedTxt);
51690
+ }
51691
+
51692
+ if (maxg === null || maxg <= gdata) {
51693
+ maxg = gdata;
51694
+ maxSID = sId;
51695
+ }
51696
+
51697
+ hitId = sId;
51698
+ }
51699
+ }
51700
+ }
51701
+ }
51702
+
51703
+ var _maxHighlight2 = maxg !== null ? [maxSID, maxg] : null;
51704
+
51705
+ return {
51706
+ items: items,
51707
+ hitId: hitId,
51708
+ maxTip: [maxs, maxv],
51709
+ maxHighlight: _maxHighlight2
51710
+ };
51711
+ } // 1. 먼저 공통으로 사용할 데이터 인덱스 결정
51712
+
51713
+
51714
+ var targetDataIndex = this.findClosestDataIndex(offset, sIds);
51715
+
51716
+ if (targetDataIndex === -1) {
51717
+ return {
51718
+ items: items,
51719
+ hitId: hitId,
51720
+ maxTip: [maxs, maxv],
51721
+ maxHighlight: null
51722
+ };
51723
+ } // 2. 모든 시리즈가 동일한 데이터 인덱스 사용
51724
+
51725
+
51726
+ var allSeriesIsBar = sIds.every(function (sId) {
51727
+ return _this4.seriesList[sId].type === 'bar';
51728
+ });
51729
+
51730
+ for (var _ix = 0; _ix < sIds.length; _ix++) {
51731
+ var _sId = sIds[_ix];
51732
+ var _series = this.seriesList[_sId];
51454
51733
 
51455
- if (series.findGraphData) {
51456
- var item = series.findGraphData(offset, isHorizontal);
51734
+ if (_series.findGraphData && _series.show) {
51735
+ // 특정 데이터 인덱스로 데이터 요청
51736
+ var _item = _series.findGraphData(offset, isHorizontal, targetDataIndex, !allSeriesIsBar);
51457
51737
 
51458
- if (item !== null && item !== void 0 && item.data) {
51459
- var gdata = void 0;
51738
+ if (_item !== null && _item !== void 0 && _item.data) {
51739
+ var _gdata = void 0;
51460
51740
 
51461
- if (item.data.o === null && series.interpolation !== 'zero') {
51462
- if (!series.isExistGrp) {
51463
- gdata = isHorizontal ? item.data.x : item.data.y;
51741
+ if (_item.data.o === null && _series.interpolation !== 'zero') {
51742
+ if (!_series.isExistGrp) {
51743
+ _gdata = isHorizontal ? _item.data.x : _item.data.y;
51464
51744
  }
51465
- } else if (!isNaN(item.data.o)) {
51466
- gdata = item.data.o;
51745
+ } else if (!isNaN(_item.data.o)) {
51746
+ _gdata = _item.data.o;
51467
51747
  }
51468
51748
 
51469
- if (gdata !== null && gdata !== undefined) {
51470
- var formattedSeriesName = this.getFormattedTooltipLabel({
51471
- dataId: series.id,
51472
- seriesId: sId,
51473
- seriesName: series.name,
51474
- itemData: item.data
51749
+ if (_gdata !== null && _gdata !== undefined) {
51750
+ var _formattedSeriesName = this.getFormattedTooltipLabel({
51751
+ dataId: _series.id,
51752
+ seriesId: _sId,
51753
+ seriesName: _series.name,
51754
+ itemData: _item.data
51475
51755
  });
51476
- var sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
51477
- item.id = series.id;
51478
- item.name = formattedSeriesName;
51479
- item.axis = {
51480
- x: series.xAxisIndex,
51481
- y: series.yAxisIndex
51756
+
51757
+ var _sw = ctx ? ctx.measureText(_formattedSeriesName).width : 1;
51758
+
51759
+ _item.id = _series.id;
51760
+ _item.name = _formattedSeriesName;
51761
+ _item.axis = {
51762
+ x: _series.xAxisIndex,
51763
+ y: _series.yAxisIndex
51482
51764
  };
51483
- items[sId] = item;
51484
- var formattedTxt = this.getFormattedTooltipValue({
51485
- dataId: series.id,
51486
- seriesId: sId,
51487
- seriesName: formattedSeriesName,
51488
- value: gdata,
51489
- itemData: item.data
51765
+ items[_sId] = _item;
51766
+
51767
+ var _formattedTxt = this.getFormattedTooltipValue({
51768
+ dataId: _series.id,
51769
+ seriesId: _sId,
51770
+ seriesName: _formattedSeriesName,
51771
+ value: _gdata,
51772
+ itemData: _item.data
51490
51773
  });
51491
- item.data.formatted = formattedTxt;
51492
51774
 
51493
- if (maxsw < sw) {
51494
- maxs = formattedSeriesName;
51495
- maxsw = sw;
51775
+ _item.data.formatted = _formattedTxt;
51776
+
51777
+ if (maxsw < _sw) {
51778
+ maxs = _formattedSeriesName;
51779
+ maxsw = _sw;
51496
51780
  }
51497
51781
 
51498
- if (maxv.length <= "".concat(formattedTxt).length) {
51499
- maxv = "".concat(formattedTxt);
51782
+ if (maxv.length <= "".concat(_formattedTxt).length) {
51783
+ maxv = "".concat(_formattedTxt);
51500
51784
  }
51501
51785
 
51502
- if (maxg === null || maxg <= gdata) {
51503
- maxg = gdata;
51504
- maxSID = sId;
51786
+ if (maxg === null || maxg <= _gdata) {
51787
+ maxg = _gdata;
51788
+ maxSID = _sId;
51505
51789
  }
51506
51790
 
51507
- if (item.hit) {
51508
- hitId = sId;
51791
+ if (_item.hit) {
51792
+ hitId = _sId;
51509
51793
  }
51510
51794
  }
51511
51795
  }
@@ -51522,6 +51806,78 @@ var plugins_interaction_modules = {
51522
51806
  };
51523
51807
  },
51524
51808
 
51809
+ /**
51810
+ * Find the closest data index (label) based on mouse position
51811
+ * @param {array} offset mouse position
51812
+ * @param {array} sIds series IDs
51813
+ * @returns {number} closest data index
51814
+ */
51815
+ findClosestDataIndex: function findClosestDataIndex(offset, sIds) {
51816
+ var _this5 = this,
51817
+ _this$seriesList$refe;
51818
+
51819
+ var _offset = _slicedToArray(offset, 2),
51820
+ xp = _offset[0],
51821
+ yp = _offset[1];
51822
+
51823
+ var isHorizontal = !!this.options.horizontal;
51824
+ var mousePos = isHorizontal ? yp : xp;
51825
+ var closestDistance = Infinity;
51826
+ var closestIndex = -1; // 첫 번째 표시 중인 시리즈를 기준으로 라벨 위치 확인
51827
+
51828
+ var referenceSeries = sIds.find(function (sId) {
51829
+ var _this5$seriesList$sId;
51830
+
51831
+ return (_this5$seriesList$sId = _this5.seriesList[sId]) === null || _this5$seriesList$sId === void 0 ? void 0 : _this5$seriesList$sId.show;
51832
+ });
51833
+
51834
+ if (!referenceSeries || !((_this$seriesList$refe = this.seriesList[referenceSeries]) !== null && _this$seriesList$refe !== void 0 && _this$seriesList$refe.data)) {
51835
+ return -1;
51836
+ }
51837
+
51838
+ var referenceData = this.seriesList[referenceSeries].data; // 각 라벨에서 가장 가까운 것 찾기
51839
+
51840
+ var _loop = function _loop(i) {
51841
+ // 이 라벨에 유효한 데이터가 있는 시리즈가 하나 이상 있는지 확인
51842
+ var hasValidData = sIds.some(function (sId) {
51843
+ var _series$data, _series$data$i, _series$data2, _series$data2$i;
51844
+
51845
+ var series = _this5.seriesList[sId];
51846
+ 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;
51847
+ });
51848
+
51849
+ if (hasValidData) {
51850
+ var point = referenceData[i];
51851
+
51852
+ if (point) {
51853
+ // 라벨 위치 계산
51854
+ var labelPos;
51855
+
51856
+ if (isHorizontal) {
51857
+ labelPos = point.h ? point.yp + point.h / 2 : point.yp;
51858
+ } else {
51859
+ labelPos = point.w ? point.xp + point.w / 2 : point.xp;
51860
+ }
51861
+
51862
+ if (labelPos !== null) {
51863
+ var distance = Math.abs(mousePos - labelPos);
51864
+
51865
+ if (distance < closestDistance) {
51866
+ closestDistance = distance;
51867
+ closestIndex = i;
51868
+ }
51869
+ }
51870
+ }
51871
+ }
51872
+ };
51873
+
51874
+ for (var i = 0; i < referenceData.length; i++) {
51875
+ _loop(i);
51876
+ }
51877
+
51878
+ return closestIndex;
51879
+ },
51880
+
51525
51881
  /**
51526
51882
  * get formatted label for tooltip
51527
51883
  * @param dataId
@@ -51651,9 +52007,9 @@ var plugins_interaction_modules = {
51651
52007
  seriesName: formattedSeriesName,
51652
52008
  value: hasData === null || hasData === void 0 ? void 0 : hasData.o,
51653
52009
  itemData: hasData
51654
- });
52010
+ }); // Only add data if there's a valid value for this exact label
51655
52011
 
51656
- if (hasData && !hitInfo.items[sId]) {
52012
+ if (hasData && hasData.o !== null && hasData.o !== undefined && !hitInfo.items[sId]) {
51657
52013
  var item = {};
51658
52014
  item.color = series.color;
51659
52015
  item.hit = false;
@@ -51743,7 +52099,7 @@ var plugins_interaction_modules = {
51743
52099
  * @returns {object[]}
51744
52100
  */
51745
52101
  getSelectedLabelInfoWithLabelData: function getSelectedLabelInfoWithLabelData(labelIndexList, targetAxis) {
51746
- var _this4 = this;
52102
+ var _this6 = this;
51747
52103
 
51748
52104
  var _this$options9 = this.options,
51749
52105
  selectLabelOpt = _this$options9.selectLabel,
@@ -51759,7 +52115,7 @@ var plugins_interaction_modules = {
51759
52115
  {
51760
52116
  result.dataIndex.splice(selectLabelOpt.limit);
51761
52117
  result.label = result.dataIndex.map(function (i) {
51762
- return _this4.data.labels[i];
52118
+ return _this6.data.labels[i];
51763
52119
  });
51764
52120
  var dataEntries = Object.entries(this.data.data);
51765
52121
  result.data = result.dataIndex.map(function (labelIdx) {
@@ -51789,7 +52145,7 @@ var plugins_interaction_modules = {
51789
52145
  }
51790
52146
 
51791
52147
  result.label = result.dataIndex.map(function (i) {
51792
- return _this4.data.labels[targetAxisDirection][i];
52148
+ return _this6.data.labels[targetAxisDirection][i];
51793
52149
  });
51794
52150
  var dataValues = Object.values(this.data.data)[0];
51795
52151
  result.data = dataValues.filter(function (_ref6) {
@@ -51880,6 +52236,76 @@ var plugins_interaction_modules = {
51880
52236
  return after;
51881
52237
  },
51882
52238
 
52239
+ /**
52240
+ * Draw indicator at the label position when tooltip is displayed
52241
+ * @param {object} hitInfo hit item information from findHitItem
52242
+ * @param {string} color indicator color
52243
+ * @returns {object|null} indicator position info with actual label value
52244
+ */
52245
+ drawIndicatorForTooltip: function drawIndicatorForTooltip(hitInfo, color) {
52246
+ var _this$options$indicat;
52247
+
52248
+ if (!(hitInfo !== null && hitInfo !== void 0 && hitInfo.items) || !Object.keys(hitInfo.items).length) {
52249
+ return null;
52250
+ }
52251
+
52252
+ var ctx = this.overlayCtx;
52253
+ var horizontal = this.options.horizontal;
52254
+ var graphPos = {
52255
+ x1: this.chartRect.x1 + this.labelOffset.left,
52256
+ x2: this.chartRect.x2 - this.labelOffset.right,
52257
+ y1: this.chartRect.y1 + this.labelOffset.top,
52258
+ y2: this.chartRect.y2 - this.labelOffset.bottom
52259
+ }; // 첫 번째 시리즈의 데이터를 기준으로 라벨 위치 계산
52260
+
52261
+ var firstSeriesId = Object.keys(hitInfo.items)[0];
52262
+ var firstItem = hitInfo.items[firstSeriesId];
52263
+
52264
+ if (!(firstItem !== null && firstItem !== void 0 && firstItem.data)) {
52265
+ return null;
52266
+ } // 실제 indicator가 위치하는 라벨 값 추출
52267
+
52268
+
52269
+ var actualLabelValue = horizontal ? firstItem.data.y : firstItem.data.x;
52270
+ var indicatorPosition;
52271
+
52272
+ if (horizontal) {
52273
+ // 수평 차트에서는 Y축 라벨 위치에 수평선
52274
+ var yPosition = firstItem.data.yp + (firstItem.data.h ? firstItem.data.h / 2 : 0);
52275
+ indicatorPosition = [graphPos.x1, yPosition];
52276
+ } else {
52277
+ // 수직 차트에서는 X축 라벨 위치에 수직선
52278
+ var xPosition = firstItem.data.xp + (firstItem.data.w ? firstItem.data.w / 2 : 0);
52279
+ indicatorPosition = [xPosition, graphPos.y1];
52280
+ }
52281
+
52282
+ ctx.beginPath();
52283
+ ctx.save();
52284
+ ctx.strokeStyle = color;
52285
+ ctx.lineWidth = 1;
52286
+
52287
+ if ((_this$options$indicat = this.options.indicator) !== null && _this$options$indicat !== void 0 && _this$options$indicat.segments) {
52288
+ ctx.setLineDash(this.options.indicator.segments);
52289
+ }
52290
+
52291
+ if (horizontal) {
52292
+ ctx.moveTo(graphPos.x1, indicatorPosition[1] + 0.5);
52293
+ ctx.lineTo(graphPos.x2, indicatorPosition[1] + 0.5);
52294
+ } else {
52295
+ ctx.moveTo(indicatorPosition[0] + 0.5, graphPos.y1);
52296
+ ctx.lineTo(indicatorPosition[0] + 0.5, graphPos.y2);
52297
+ }
52298
+
52299
+ ctx.stroke();
52300
+ ctx.restore();
52301
+ ctx.closePath(); // 실제 indicator가 위치한 라벨 정보 반환
52302
+
52303
+ return {
52304
+ labelValue: actualLabelValue,
52305
+ position: indicatorPosition
52306
+ };
52307
+ },
52308
+
51883
52309
  /**
51884
52310
  * Find items by series within a range
51885
52311
  * @param {object} range object for find series items
@@ -52012,9 +52438,9 @@ var plugins_interaction_modules = {
52012
52438
  * @returns {string}
52013
52439
  */
52014
52440
  getCurMouseLocation: function getCurMouseLocation(offset) {
52015
- var _offset = _slicedToArray(offset, 2),
52016
- offsetX = _offset[0],
52017
- offsetY = _offset[1];
52441
+ var _offset2 = _slicedToArray(offset, 2),
52442
+ offsetX = _offset2[0],
52443
+ offsetY = _offset2[1];
52018
52444
 
52019
52445
  var aPos = {
52020
52446
  x1: this.chartRect.x1 + this.labelOffset.left,
@@ -52074,6 +52500,8 @@ var plugins_interaction_modules = {
52074
52500
 
52075
52501
 
52076
52502
 
52503
+
52504
+
52077
52505
 
52078
52506
  var LINE_SPACING = 8;
52079
52507
  var VALUE_MARGIN = 50;
@@ -52865,9 +53293,10 @@ var plugins_tooltip_modules = {
52865
53293
  y1: this.chartRect.y1 + this.labelOffset.top,
52866
53294
  y2: this.chartRect.y2 - this.labelOffset.bottom
52867
53295
  };
52868
- var mouseXIp = 1; // mouseInterpolation
53296
+ var mouseXIp = 15; // mouseInterpolation - 더 넓은 범위에서 감지
53297
+
53298
+ var mouseYIp = 15; // Y축도 동일하게 증가
52869
53299
 
52870
- var mouseYIp = 10;
52871
53300
  var options = this.options;
52872
53301
 
52873
53302
  if (offsetX >= graphPos.x1 - mouseXIp && offsetX <= graphPos.x2 + mouseXIp && offsetY >= graphPos.y1 - mouseYIp && offsetY <= graphPos.y2 + mouseYIp) {
@@ -52961,11 +53390,23 @@ var plugins_tooltip_modules = {
52961
53390
 
52962
53391
  var horizontal = _ref5.horizontal,
52963
53392
  label = _ref5.label,
52964
- mousePosition = _ref5.mousePosition;
53393
+ mousePosition = _ref5.mousePosition,
53394
+ dataLabel = _ref5.dataLabel,
53395
+ isTooltipBased = _ref5.isTooltipBased;
52965
53396
 
52966
53397
  if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
52967
53398
  return;
52968
- }
53399
+ } // tooltip 기반 동기화인 경우
53400
+
53401
+
53402
+ if (isTooltipBased) {
53403
+ this.drawSyncedIndicatorForTooltip({
53404
+ dataLabel: dataLabel,
53405
+ mousePosition: mousePosition
53406
+ });
53407
+ return;
53408
+ } // 기존 시간 기반 동기화
53409
+
52969
53410
 
52970
53411
  if (this.options.syncHover === false || !horizontal && !this.options.axesX.every(function (_ref6) {
52971
53412
  var type = _ref6.type;
@@ -53019,6 +53460,82 @@ var plugins_tooltip_modules = {
53019
53460
  }
53020
53461
  },
53021
53462
 
53463
+ /**
53464
+ * 제공된 dataLabel과 일치하는 Label이 있다면 indicator를 그림
53465
+ * @param {object} dataLabel data label
53466
+ * @param {object} mousePosition mouse position
53467
+ *
53468
+ * @returns {undefined}
53469
+ */
53470
+ drawSyncedIndicatorForTooltip: function drawSyncedIndicatorForTooltip(_ref8) {
53471
+ var _this$data;
53472
+
53473
+ var dataLabel = _ref8.dataLabel,
53474
+ mousePosition = _ref8.mousePosition;
53475
+
53476
+ if (!((_this$data = this.data) !== null && _this$data !== void 0 && _this$data.labels) || !dataLabel) {
53477
+ return;
53478
+ }
53479
+
53480
+ var matchingLabelIndex = this.data.labels.findIndex(function (label) {
53481
+ return (label === null || label === void 0 ? void 0 : label.valueOf()) === (dataLabel === null || dataLabel === void 0 ? void 0 : dataLabel.valueOf());
53482
+ });
53483
+
53484
+ if (matchingLabelIndex === -1) {
53485
+ this.overlayClear();
53486
+ return;
53487
+ }
53488
+
53489
+ var horizontal = this.options.horizontal;
53490
+
53491
+ var _this$chartDOM$getBou2 = this.chartDOM.getBoundingClientRect(),
53492
+ top = _this$chartDOM$getBou2.top,
53493
+ bottom = _this$chartDOM$getBou2.bottom,
53494
+ left = _this$chartDOM$getBou2.left,
53495
+ right = _this$chartDOM$getBou2.right;
53496
+
53497
+ var isHoveredChart = lodash_es_inRange(mousePosition[0], left, right) && lodash_es_inRange(mousePosition[1], bottom, top);
53498
+
53499
+ if (isHoveredChart) {
53500
+ return;
53501
+ }
53502
+
53503
+ this.overlayClear();
53504
+ var graphPos = {
53505
+ x1: this.chartRect.x1 + this.labelOffset.left,
53506
+ x2: this.chartRect.x2 - this.labelOffset.right,
53507
+ y1: this.chartRect.y1 + this.labelOffset.top,
53508
+ y2: this.chartRect.y2 - this.labelOffset.bottom
53509
+ };
53510
+ var labelsCount = this.data.labels.length;
53511
+ var indicatorPosition;
53512
+
53513
+ if (horizontal) {
53514
+ var _this$options$axesY;
53515
+
53516
+ var chartHeight = graphPos.y2 - graphPos.y1; // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
53517
+
53518
+ var isCategoryMode = (_this$options$axesY = this.options.axesY) === null || _this$options$axesY === void 0 ? void 0 : _this$options$axesY.some(function (axis) {
53519
+ return axis.categoryMode;
53520
+ });
53521
+ var positionY = isCategoryMode ? graphPos.y1 + chartHeight * (matchingLabelIndex + 0.5) / labelsCount : graphPos.y1 + chartHeight * matchingLabelIndex / (labelsCount - 1);
53522
+ indicatorPosition = [graphPos.x2, positionY];
53523
+ } else {
53524
+ var _this$options$axesX;
53525
+
53526
+ var chartWidth = graphPos.x2 - graphPos.x1; // CategoryMode인 경우 라벨들이 균등 간격으로 배치됨
53527
+
53528
+ var _isCategoryMode = (_this$options$axesX = this.options.axesX) === null || _this$options$axesX === void 0 ? void 0 : _this$options$axesX.some(function (axis) {
53529
+ return axis.categoryMode;
53530
+ });
53531
+
53532
+ var positionX = _isCategoryMode ? graphPos.x1 + chartWidth * (matchingLabelIndex + 0.5) / labelsCount : graphPos.x1 + chartWidth * matchingLabelIndex / (labelsCount - 1);
53533
+ indicatorPosition = [positionX, graphPos.y2];
53534
+ }
53535
+
53536
+ this.drawIndicator(indicatorPosition, this.options.indicator.color);
53537
+ },
53538
+
53022
53539
  /**
53023
53540
  * Clear tooltip canvas
53024
53541
  *