evui 3.4.203 → 3.4.205

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.203\"}");
11177
+ module.exports = JSON.parse("{\"a\":\"3.4.205\"}");
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);
@@ -50695,7 +50855,7 @@ function toFinite(value) {
50695
50855
  * _.inRange(-3, -2, -6);
50696
50856
  * // => true
50697
50857
  */
50698
- function inRange(number, start, end) {
50858
+ function inRange_inRange(number, start, end) {
50699
50859
  start = lodash_es_toFinite(start);
50700
50860
  if (end === undefined) {
50701
50861
  end = start;
@@ -50707,7 +50867,7 @@ function inRange(number, start, end) {
50707
50867
  return _baseInRange(number, start, end);
50708
50868
  }
50709
50869
 
50710
- /* harmony default export */ var lodash_es_inRange = (inRange);
50870
+ /* harmony default export */ var lodash_es_inRange = (inRange_inRange);
50711
50871
 
50712
50872
  // CONCATENATED MODULE: ./src/components/chart/plugins/plugins.interaction.js
50713
50873
 
@@ -50729,6 +50889,8 @@ function inRange(number, start, end) {
50729
50889
 
50730
50890
 
50731
50891
 
50892
+
50893
+
50732
50894
 
50733
50895
 
50734
50896
 
@@ -50814,6 +50976,29 @@ var plugins_interaction_modules = {
50814
50976
  _this.drawTooltip(hitInfo, _this.tooltipCtx);
50815
50977
  }
50816
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
+ };
50817
51002
  }
50818
51003
  } else if (tooltip.use && _this.isInitTooltip) {
50819
51004
  if (typeof (tooltip === null || tooltip === void 0 ? void 0 : tooltip.returnValue) === 'function') {
@@ -50825,19 +51010,28 @@ var plugins_interaction_modules = {
50825
51010
 
50826
51011
  if (_this.dragInfoBackup) {
50827
51012
  _this.drawSelectionArea(_this.dragInfoBackup);
50828
- }
51013
+ } // tooltip 기반 indicator가 아직 설정되지 않은 경우에만 일반 indicator 처리
51014
+
50829
51015
 
50830
- if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
50831
- _this.drawIndicator(offset, indicator.color);
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
+ });
51021
+
51022
+ if (type !== 'line' && !_hasLineSeries || !tooltip.use || !Object.keys(hitInfo.items).length) {
51023
+ _this.drawIndicator(offset, indicator.color);
51024
+ }
50832
51025
 
50833
- var label = _this.getTimeLabel(offset);
51026
+ var _label = _this.getTimeLabel(offset);
50834
51027
 
50835
51028
  args.hoveredLabel = {
50836
51029
  horizontal: _this.options.horizontal,
50837
- label: label,
50838
- mousePosition: [e.clientX, e.clientY]
51030
+ label: _label,
51031
+ mousePosition: [e.clientX, e.clientY],
51032
+ isTooltipBased: false
50839
51033
  };
50840
- } else {
51034
+ } else if (!args.hoveredLabel) {
50841
51035
  args.hoveredLabel = {
50842
51036
  label: ''
50843
51037
  };
@@ -51702,6 +51896,8 @@ var plugins_interaction_modules = {
51702
51896
  * @returns {object} hit item information
51703
51897
  */
51704
51898
  findHitItem: function findHitItem(offset) {
51899
+ var _this4 = this;
51900
+
51705
51901
  var sIds = Object.keys(this.seriesList);
51706
51902
  var items = {};
51707
51903
  var isHorizontal = !!this.options.horizontal;
@@ -51711,66 +51907,153 @@ var plugins_interaction_modules = {
51711
51907
  var maxsw = 0;
51712
51908
  var maxv = '';
51713
51909
  var maxg = null;
51714
- var maxSID = null;
51910
+ var maxSID = null; // 파이 차트는 특별한 처리가 필요
51715
51911
 
51716
- for (var ix = 0; ix < sIds.length; ix++) {
51717
- var sId = sIds[ix];
51718
- 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
+ }
51951
+
51952
+ if (maxv.length <= "".concat(formattedTxt).length) {
51953
+ maxv = "".concat(formattedTxt);
51954
+ }
51955
+
51956
+ if (maxg === null || maxg <= gdata) {
51957
+ maxg = gdata;
51958
+ maxSID = sId;
51959
+ }
51960
+
51961
+ hitId = sId;
51962
+ }
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];
51719
51997
 
51720
- if (series.findGraphData) {
51721
- var item = series.findGraphData(offset, isHorizontal);
51998
+ if (_series.findGraphData && _series.show) {
51999
+ // 특정 데이터 인덱스로 데이터 요청
52000
+ var _item = _series.findGraphData(offset, isHorizontal, targetDataIndex, !allSeriesIsBar);
51722
52001
 
51723
- if (item !== null && item !== void 0 && item.data) {
51724
- var gdata = void 0;
52002
+ if (_item !== null && _item !== void 0 && _item.data) {
52003
+ var _gdata = void 0;
51725
52004
 
51726
- if (item.data.o === null && series.interpolation !== 'zero') {
51727
- if (!series.isExistGrp) {
51728
- gdata = isHorizontal ? item.data.x : item.data.y;
52005
+ if (_item.data.o === null && _series.interpolation !== 'zero') {
52006
+ if (!_series.isExistGrp) {
52007
+ _gdata = isHorizontal ? _item.data.x : _item.data.y;
51729
52008
  }
51730
- } else if (!isNaN(item.data.o)) {
51731
- gdata = item.data.o;
52009
+ } else if (!isNaN(_item.data.o)) {
52010
+ _gdata = _item.data.o;
51732
52011
  }
51733
52012
 
51734
- if (gdata !== null && gdata !== undefined) {
51735
- var formattedSeriesName = this.getFormattedTooltipLabel({
51736
- dataId: series.id,
51737
- seriesId: sId,
51738
- seriesName: series.name,
51739
- itemData: item.data
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
51740
52019
  });
51741
- var sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
51742
- item.id = series.id;
51743
- item.name = formattedSeriesName;
51744
- item.axis = {
51745
- x: series.xAxisIndex,
51746
- 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
51747
52028
  };
51748
- items[sId] = item;
51749
- var formattedTxt = this.getFormattedTooltipValue({
51750
- dataId: series.id,
51751
- seriesId: sId,
51752
- seriesName: formattedSeriesName,
51753
- value: gdata,
51754
- 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
51755
52037
  });
51756
- item.data.formatted = formattedTxt;
51757
52038
 
51758
- if (maxsw < sw) {
51759
- maxs = formattedSeriesName;
51760
- maxsw = sw;
52039
+ _item.data.formatted = _formattedTxt;
52040
+
52041
+ if (maxsw < _sw) {
52042
+ maxs = _formattedSeriesName;
52043
+ maxsw = _sw;
51761
52044
  }
51762
52045
 
51763
- if (maxv.length <= "".concat(formattedTxt).length) {
51764
- maxv = "".concat(formattedTxt);
52046
+ if (maxv.length <= "".concat(_formattedTxt).length) {
52047
+ maxv = "".concat(_formattedTxt);
51765
52048
  }
51766
52049
 
51767
- if (maxg === null || maxg <= gdata) {
51768
- maxg = gdata;
51769
- maxSID = sId;
52050
+ if (maxg === null || maxg <= _gdata) {
52051
+ maxg = _gdata;
52052
+ maxSID = _sId;
51770
52053
  }
51771
52054
 
51772
- if (item.hit) {
51773
- hitId = sId;
52055
+ if (_item.hit) {
52056
+ hitId = _sId;
51774
52057
  }
51775
52058
  }
51776
52059
  }
@@ -51787,6 +52070,78 @@ var plugins_interaction_modules = {
51787
52070
  };
51788
52071
  },
51789
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
+
51790
52145
  /**
51791
52146
  * get formatted label for tooltip
51792
52147
  * @param dataId
@@ -51916,9 +52271,9 @@ var plugins_interaction_modules = {
51916
52271
  seriesName: formattedSeriesName,
51917
52272
  value: hasData === null || hasData === void 0 ? void 0 : hasData.o,
51918
52273
  itemData: hasData
51919
- });
52274
+ }); // Only add data if there's a valid value for this exact label
51920
52275
 
51921
- if (hasData && !hitInfo.items[sId]) {
52276
+ if (hasData && hasData.o !== null && hasData.o !== undefined && !hitInfo.items[sId]) {
51922
52277
  var item = {};
51923
52278
  item.color = series.color;
51924
52279
  item.hit = false;
@@ -52008,7 +52363,7 @@ var plugins_interaction_modules = {
52008
52363
  * @returns {object[]}
52009
52364
  */
52010
52365
  getSelectedLabelInfoWithLabelData: function getSelectedLabelInfoWithLabelData(labelIndexList, targetAxis) {
52011
- var _this4 = this;
52366
+ var _this6 = this;
52012
52367
 
52013
52368
  var _this$options9 = this.options,
52014
52369
  selectLabelOpt = _this$options9.selectLabel,
@@ -52024,7 +52379,7 @@ var plugins_interaction_modules = {
52024
52379
  {
52025
52380
  result.dataIndex.splice(selectLabelOpt.limit);
52026
52381
  result.label = result.dataIndex.map(function (i) {
52027
- return _this4.data.labels[i];
52382
+ return _this6.data.labels[i];
52028
52383
  });
52029
52384
  var dataEntries = Object.entries(this.data.data);
52030
52385
  result.data = result.dataIndex.map(function (labelIdx) {
@@ -52054,7 +52409,7 @@ var plugins_interaction_modules = {
52054
52409
  }
52055
52410
 
52056
52411
  result.label = result.dataIndex.map(function (i) {
52057
- return _this4.data.labels[targetAxisDirection][i];
52412
+ return _this6.data.labels[targetAxisDirection][i];
52058
52413
  });
52059
52414
  var dataValues = Object.values(this.data.data)[0];
52060
52415
  result.data = dataValues.filter(function (_ref6) {
@@ -52145,6 +52500,76 @@ var plugins_interaction_modules = {
52145
52500
  return after;
52146
52501
  },
52147
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
+
52148
52573
  /**
52149
52574
  * Find items by series within a range
52150
52575
  * @param {object} range object for find series items
@@ -52277,9 +52702,9 @@ var plugins_interaction_modules = {
52277
52702
  * @returns {string}
52278
52703
  */
52279
52704
  getCurMouseLocation: function getCurMouseLocation(offset) {
52280
- var _offset = _slicedToArray(offset, 2),
52281
- offsetX = _offset[0],
52282
- offsetY = _offset[1];
52705
+ var _offset2 = _slicedToArray(offset, 2),
52706
+ offsetX = _offset2[0],
52707
+ offsetY = _offset2[1];
52283
52708
 
52284
52709
  var aPos = {
52285
52710
  x1: this.chartRect.x1 + this.labelOffset.left,
@@ -52339,6 +52764,8 @@ var plugins_interaction_modules = {
52339
52764
 
52340
52765
 
52341
52766
 
52767
+
52768
+
52342
52769
 
52343
52770
  var LINE_SPACING = 8;
52344
52771
  var VALUE_MARGIN = 50;
@@ -53130,9 +53557,10 @@ var plugins_tooltip_modules = {
53130
53557
  y1: this.chartRect.y1 + this.labelOffset.top,
53131
53558
  y2: this.chartRect.y2 - this.labelOffset.bottom
53132
53559
  };
53133
- var mouseXIp = 1; // mouseInterpolation
53560
+ var mouseXIp = 15; // mouseInterpolation - 더 넓은 범위에서 감지
53561
+
53562
+ var mouseYIp = 15; // Y축도 동일하게 증가
53134
53563
 
53135
- var mouseYIp = 10;
53136
53564
  var options = this.options;
53137
53565
 
53138
53566
  if (offsetX >= graphPos.x1 - mouseXIp && offsetX <= graphPos.x2 + mouseXIp && offsetY >= graphPos.y1 - mouseYIp && offsetY <= graphPos.y2 + mouseYIp) {
@@ -53226,11 +53654,23 @@ var plugins_tooltip_modules = {
53226
53654
 
53227
53655
  var horizontal = _ref5.horizontal,
53228
53656
  label = _ref5.label,
53229
- mousePosition = _ref5.mousePosition;
53657
+ mousePosition = _ref5.mousePosition,
53658
+ dataLabel = _ref5.dataLabel,
53659
+ isTooltipBased = _ref5.isTooltipBased;
53230
53660
 
53231
53661
  if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
53232
53662
  return;
53233
- }
53663
+ } // tooltip 기반 동기화인 경우
53664
+
53665
+
53666
+ if (isTooltipBased) {
53667
+ this.drawSyncedIndicatorForTooltip({
53668
+ dataLabel: dataLabel,
53669
+ mousePosition: mousePosition
53670
+ });
53671
+ return;
53672
+ } // 기존 시간 기반 동기화
53673
+
53234
53674
 
53235
53675
  if (this.options.syncHover === false || !horizontal && !this.options.axesX.every(function (_ref6) {
53236
53676
  var type = _ref6.type;
@@ -53284,6 +53724,82 @@ var plugins_tooltip_modules = {
53284
53724
  }
53285
53725
  },
53286
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
+
53287
53803
  /**
53288
53804
  * Clear tooltip canvas
53289
53805
  *