@perses-dev/components 0.54.0-beta.9 → 0.54.0-rc.1
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.
- package/dist/EChart/index.d.ts +1 -0
- package/dist/EChart/index.d.ts.map +1 -1
- package/dist/EChart/index.js +1 -0
- package/dist/EChart/index.js.map +1 -1
- package/dist/EChart/timezone-formatter.d.ts +5 -0
- package/dist/EChart/timezone-formatter.d.ts.map +1 -0
- package/dist/EChart/timezone-formatter.js +43 -0
- package/dist/EChart/timezone-formatter.js.map +1 -0
- package/dist/LinksEditor/index.d.ts +0 -1
- package/dist/LinksEditor/index.d.ts.map +1 -1
- package/dist/LinksEditor/index.js +0 -1
- package/dist/LinksEditor/index.js.map +1 -1
- package/dist/TimeSeriesTooltip/TimeChartTooltip.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/TimeChartTooltip.js +25 -6
- package/dist/TimeSeriesTooltip/TimeChartTooltip.js.map +1 -1
- package/dist/TimeSeriesTooltip/TooltipContent.d.ts +1 -1
- package/dist/TimeSeriesTooltip/TooltipContent.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/TooltipContent.js.map +1 -1
- package/dist/TimeSeriesTooltip/TooltipHeader.d.ts +1 -1
- package/dist/TimeSeriesTooltip/TooltipHeader.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/TooltipHeader.js.map +1 -1
- package/dist/TimeSeriesTooltip/index.d.ts +1 -0
- package/dist/TimeSeriesTooltip/index.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/index.js +1 -0
- package/dist/TimeSeriesTooltip/index.js.map +1 -1
- package/dist/TimeSeriesTooltip/nearby-series.d.ts +5 -23
- package/dist/TimeSeriesTooltip/nearby-series.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/nearby-series.js +218 -153
- package/dist/TimeSeriesTooltip/nearby-series.js.map +1 -1
- package/dist/TimeSeriesTooltip/tooltip-model.d.ts +1 -1
- package/dist/TimeSeriesTooltip/tooltip-model.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/tooltip-model.js.map +1 -1
- package/dist/TimeSeriesTooltip/types.d.ts +30 -0
- package/dist/TimeSeriesTooltip/types.d.ts.map +1 -0
- package/dist/TimeSeriesTooltip/types.js +15 -0
- package/dist/TimeSeriesTooltip/types.js.map +1 -0
- package/dist/TimeSeriesTooltip/utils.d.ts +26 -1
- package/dist/TimeSeriesTooltip/utils.d.ts.map +1 -1
- package/dist/TimeSeriesTooltip/utils.js +105 -9
- package/dist/TimeSeriesTooltip/utils.js.map +1 -1
- package/dist/cjs/EChart/index.js +1 -0
- package/dist/cjs/EChart/timezone-formatter.js +49 -0
- package/dist/cjs/LinksEditor/index.js +0 -1
- package/dist/cjs/TimeSeriesTooltip/TimeChartTooltip.js +24 -5
- package/dist/cjs/TimeSeriesTooltip/index.js +1 -0
- package/dist/cjs/TimeSeriesTooltip/nearby-series.js +216 -151
- package/dist/cjs/TimeSeriesTooltip/types.js +16 -0
- package/dist/cjs/TimeSeriesTooltip/utils.js +109 -8
- package/dist/cjs/utils/chart-actions.js +12 -4
- package/dist/cjs/utils/request-interpolation.js +20 -2
- package/dist/cjs/utils/variable-interpolation.js +6 -0
- package/dist/utils/chart-actions.d.ts.map +1 -1
- package/dist/utils/chart-actions.js +12 -4
- package/dist/utils/chart-actions.js.map +1 -1
- package/dist/utils/request-interpolation.d.ts.map +1 -1
- package/dist/utils/request-interpolation.js +20 -2
- package/dist/utils/request-interpolation.js.map +1 -1
- package/dist/utils/variable-interpolation.d.ts +3 -1
- package/dist/utils/variable-interpolation.d.ts.map +1 -1
- package/dist/utils/variable-interpolation.js +6 -0
- package/dist/utils/variable-interpolation.js.map +1 -1
- package/package.json +3 -4
- package/dist/LinksEditor/LinksEditor.d.ts +0 -8
- package/dist/LinksEditor/LinksEditor.d.ts.map +0 -1
- package/dist/LinksEditor/LinksEditor.js +0 -149
- package/dist/LinksEditor/LinksEditor.js.map +0 -1
- package/dist/cjs/LinksEditor/LinksEditor.js +0 -162
|
@@ -13,39 +13,224 @@
|
|
|
13
13
|
import { OPTIMIZED_MODE_SERIES_LIMIT, formatValue } from '../model';
|
|
14
14
|
import { batchDispatchNearbySeriesActions, getPointInGrid, getClosestTimestamp } from '../utils';
|
|
15
15
|
import { EMPTY_TOOLTIP_DATA } from './tooltip-model';
|
|
16
|
+
import { calculateBarBandwidth, calculateBarSegmentBounds, calculateBarYBounds, calculateVisualYForSeries, getPixelXFromGrid } from './utils';
|
|
16
17
|
// increase multipliers to show more series in tooltip
|
|
17
18
|
export const INCREASE_NEARBY_SERIES_MULTIPLIER = 5.5; // adjusts how many series show in tooltip (higher == more series shown)
|
|
18
19
|
export const DYNAMIC_NEARBY_SERIES_MULTIPLIER = 30; // used for adjustment after series number divisor
|
|
19
20
|
export const SHOW_FEWER_SERIES_LIMIT = 5;
|
|
21
|
+
function gatherCandidates(data, seriesMapping, closestTimestamp, cursorX, cursorY, cursorXPixel, cursorPixelY, yBuffer, yBufferPixels, chart) {
|
|
22
|
+
const candidates = [];
|
|
23
|
+
const totalSeries = data.length;
|
|
24
|
+
const stackTotals = new Map();
|
|
25
|
+
let sortedTimestamps = [];
|
|
26
|
+
const firstValues = data[0]?.values;
|
|
27
|
+
if (firstValues && firstValues.length > 0) {
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
for (const [ts] of firstValues){
|
|
30
|
+
if (!seen.has(ts)) {
|
|
31
|
+
seen.add(ts);
|
|
32
|
+
sortedTimestamps.push(ts);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
sortedTimestamps = sortedTimestamps.sort((a, b)=>a - b);
|
|
36
|
+
}
|
|
37
|
+
// Bar-only indexes: ECharts groups bars independently of lines, so bar-relative index and count must exclude line series.
|
|
38
|
+
const barSeriesIndexes = [];
|
|
39
|
+
for(let i = 0; i < totalSeries; i++){
|
|
40
|
+
if ((seriesMapping[i]?.type ?? 'line') === 'bar') barSeriesIndexes.push(i);
|
|
41
|
+
}
|
|
42
|
+
// Computed once outside the loop — both depend only on the timestamp, not the series index.
|
|
43
|
+
let barBandwidth = null;
|
|
44
|
+
let barCenterPixelX = null;
|
|
45
|
+
if (barSeriesIndexes.length > 0 && cursorXPixel !== null) {
|
|
46
|
+
barBandwidth = calculateBarBandwidth(closestTimestamp, sortedTimestamps, chart);
|
|
47
|
+
barCenterPixelX = getPixelXFromGrid(closestTimestamp, chart);
|
|
48
|
+
}
|
|
49
|
+
for(let seriesIdx = 0; seriesIdx < totalSeries; seriesIdx++){
|
|
50
|
+
const currentSeries = seriesMapping[seriesIdx];
|
|
51
|
+
if (!currentSeries) continue;
|
|
52
|
+
const currentDataset = data[seriesIdx];
|
|
53
|
+
if (!currentDataset) continue;
|
|
54
|
+
const currentDatasetValues = currentDataset.values;
|
|
55
|
+
if (!currentDatasetValues || !Array.isArray(currentDatasetValues)) continue;
|
|
56
|
+
const seriesType = currentSeries.type ?? 'line';
|
|
57
|
+
const currentSeriesName = currentSeries.name ? currentSeries.name.toString() : '';
|
|
58
|
+
const seriesId = currentSeries.id ? currentSeries.id.toString() : '';
|
|
59
|
+
const markerColor = (currentSeries.color ?? '#000').toString();
|
|
60
|
+
let datumIdx = -1;
|
|
61
|
+
let xValue = 0;
|
|
62
|
+
let yValue;
|
|
63
|
+
for(let i = 0; i < currentDatasetValues.length; i++){
|
|
64
|
+
const tuple = currentDatasetValues[i];
|
|
65
|
+
if (!tuple) continue;
|
|
66
|
+
if (tuple[0] === closestTimestamp) {
|
|
67
|
+
datumIdx = i;
|
|
68
|
+
xValue = tuple[0];
|
|
69
|
+
yValue = tuple[1];
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (datumIdx === -1) continue;
|
|
74
|
+
if (yValue === null || yValue === undefined) continue;
|
|
75
|
+
let isCandidate = false;
|
|
76
|
+
let visualY = yValue;
|
|
77
|
+
let distance = Infinity;
|
|
78
|
+
if (seriesType === 'line') {
|
|
79
|
+
visualY = calculateVisualYForSeries(seriesIdx, yValue, seriesMapping, stackTotals);
|
|
80
|
+
if (cursorPixelY !== undefined && yBufferPixels !== null) {
|
|
81
|
+
try {
|
|
82
|
+
const dataPointPixel = chart.convertToPixel({
|
|
83
|
+
seriesIndex: seriesIdx
|
|
84
|
+
}, [
|
|
85
|
+
datumIdx,
|
|
86
|
+
visualY
|
|
87
|
+
]);
|
|
88
|
+
if (dataPointPixel && dataPointPixel[1] !== undefined) {
|
|
89
|
+
const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);
|
|
90
|
+
isCandidate = pixelDistance <= yBufferPixels;
|
|
91
|
+
distance = pixelDistance;
|
|
92
|
+
} else {
|
|
93
|
+
const verticalDistance = Math.abs(visualY - cursorY);
|
|
94
|
+
isCandidate = verticalDistance <= yBuffer;
|
|
95
|
+
distance = verticalDistance;
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
const verticalDistance = Math.abs(visualY - cursorY);
|
|
99
|
+
isCandidate = verticalDistance <= yBuffer;
|
|
100
|
+
distance = verticalDistance;
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
const verticalDistance = Math.abs(visualY - cursorY);
|
|
104
|
+
isCandidate = verticalDistance <= yBuffer;
|
|
105
|
+
distance = verticalDistance;
|
|
106
|
+
}
|
|
107
|
+
} else if (seriesType === 'bar') {
|
|
108
|
+
if (cursorXPixel === null || barBandwidth === null || barCenterPixelX === null) continue;
|
|
109
|
+
const barRelativeIdx = barSeriesIndexes.indexOf(seriesIdx);
|
|
110
|
+
if (barRelativeIdx === -1) continue;
|
|
111
|
+
const segmentBounds = calculateBarSegmentBounds(barRelativeIdx, barBandwidth, barCenterPixelX, barSeriesIndexes.length);
|
|
112
|
+
const isWithinXBounds = cursorXPixel >= segmentBounds.left && cursorXPixel <= segmentBounds.right;
|
|
113
|
+
if (!isWithinXBounds) continue;
|
|
114
|
+
const stackId = currentSeries.stack;
|
|
115
|
+
let isHoveringYBounds = true;
|
|
116
|
+
if (stackId) {
|
|
117
|
+
const stackIdStr = stackId.toString();
|
|
118
|
+
const visualYBottom = stackTotals.get(stackIdStr) ?? 0;
|
|
119
|
+
visualY = calculateVisualYForSeries(seriesIdx, yValue, seriesMapping, stackTotals);
|
|
120
|
+
const yBounds = calculateBarYBounds(visualYBottom, visualY, chart);
|
|
121
|
+
if (yBounds) {
|
|
122
|
+
const cursorYPixel = chart.convertToPixel('grid', [
|
|
123
|
+
0,
|
|
124
|
+
cursorY
|
|
125
|
+
]);
|
|
126
|
+
if (cursorYPixel && cursorYPixel[1] !== undefined) {
|
|
127
|
+
isHoveringYBounds = cursorYPixel[1] >= yBounds.top && cursorYPixel[1] <= yBounds.bottom;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
visualY = yValue;
|
|
132
|
+
}
|
|
133
|
+
if (!isHoveringYBounds) continue;
|
|
134
|
+
const segmentCenter = (segmentBounds.left + segmentBounds.right) / 2;
|
|
135
|
+
distance = Math.abs(cursorXPixel - segmentCenter);
|
|
136
|
+
isCandidate = true;
|
|
137
|
+
}
|
|
138
|
+
if (isCandidate) {
|
|
139
|
+
candidates.push({
|
|
140
|
+
seriesIdx,
|
|
141
|
+
datumIdx,
|
|
142
|
+
seriesId,
|
|
143
|
+
seriesName: currentSeriesName,
|
|
144
|
+
date: closestTimestamp,
|
|
145
|
+
markerColor,
|
|
146
|
+
x: xValue,
|
|
147
|
+
y: yValue,
|
|
148
|
+
visualY,
|
|
149
|
+
distance
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return candidates;
|
|
154
|
+
}
|
|
155
|
+
function findClosestCandidate(candidates) {
|
|
156
|
+
if (candidates.length === 0) return null;
|
|
157
|
+
let winner = null;
|
|
158
|
+
for (const candidate of candidates){
|
|
159
|
+
if (winner === null || candidate.distance < winner.distance) {
|
|
160
|
+
winner = candidate;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return winner;
|
|
164
|
+
}
|
|
165
|
+
function processCandidates(candidates, winner, format, seriesFormatMap, chart, nonCandidateSeriesIndexes) {
|
|
166
|
+
const nearbySeriesIndexes = [];
|
|
167
|
+
const emphasizedSeriesIndexes = [];
|
|
168
|
+
const nonEmphasizedSeriesIndexes = [
|
|
169
|
+
...nonCandidateSeriesIndexes
|
|
170
|
+
];
|
|
171
|
+
const emphasizedDatapoints = [];
|
|
172
|
+
const duplicateDatapoints = [];
|
|
173
|
+
const yValueCounts = new Map();
|
|
174
|
+
const result = [];
|
|
175
|
+
for (const candidate of candidates){
|
|
176
|
+
const seriesFormat = seriesFormatMap?.get(candidate.seriesId) ?? format;
|
|
177
|
+
// Use raw y, not visualY — visualY is for proximity detection only.
|
|
178
|
+
const displayY = candidate.y;
|
|
179
|
+
const formattedY = formatValue(displayY, seriesFormat);
|
|
180
|
+
const isClosestToCursor = winner !== null && candidate.seriesIdx === winner.seriesIdx;
|
|
181
|
+
if (isClosestToCursor) {
|
|
182
|
+
emphasizedSeriesIndexes.push(candidate.seriesIdx);
|
|
183
|
+
const duplicateValuesCount = yValueCounts.get(displayY) ?? 0;
|
|
184
|
+
yValueCounts.set(displayY, duplicateValuesCount + 1);
|
|
185
|
+
if (duplicateValuesCount > 0) {
|
|
186
|
+
duplicateDatapoints.push({
|
|
187
|
+
seriesIndex: candidate.seriesIdx,
|
|
188
|
+
dataIndex: candidate.datumIdx,
|
|
189
|
+
seriesName: candidate.seriesName,
|
|
190
|
+
yValue: displayY
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
emphasizedDatapoints.push({
|
|
194
|
+
seriesIndex: candidate.seriesIdx,
|
|
195
|
+
dataIndex: candidate.datumIdx,
|
|
196
|
+
seriesName: candidate.seriesName,
|
|
197
|
+
yValue: displayY
|
|
198
|
+
});
|
|
199
|
+
} else {
|
|
200
|
+
nonEmphasizedSeriesIndexes.push(candidate.seriesIdx);
|
|
201
|
+
}
|
|
202
|
+
result.push({
|
|
203
|
+
seriesIdx: candidate.seriesIdx,
|
|
204
|
+
datumIdx: candidate.datumIdx,
|
|
205
|
+
seriesName: candidate.seriesName,
|
|
206
|
+
date: candidate.date,
|
|
207
|
+
x: candidate.x,
|
|
208
|
+
y: displayY,
|
|
209
|
+
formattedY,
|
|
210
|
+
markerColor: candidate.markerColor,
|
|
211
|
+
isClosestToCursor
|
|
212
|
+
});
|
|
213
|
+
nearbySeriesIndexes.push(candidate.seriesIdx);
|
|
214
|
+
}
|
|
215
|
+
batchDispatchNearbySeriesActions(chart, nearbySeriesIndexes, emphasizedSeriesIndexes, nonEmphasizedSeriesIndexes, emphasizedDatapoints, duplicateDatapoints);
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
20
218
|
/**
|
|
21
219
|
* Returns formatted series data for the points that are close to the user's cursor.
|
|
22
220
|
* Adjust xBuffer and yBuffer to increase or decrease number of series shown.
|
|
23
221
|
*/ export function checkforNearbyTimeSeries(data, seriesMapping, pointInGrid, yBuffer, chart, format, seriesFormatMap, // in the case of multi-axis, we need the cursor Y position in pixel space
|
|
24
|
-
cursorPixelY) {
|
|
25
|
-
const currentNearbySeriesData = [];
|
|
222
|
+
cursorPixelY, cursorXPixel) {
|
|
26
223
|
const cursorX = pointInGrid[0] ?? null;
|
|
27
224
|
const cursorY = pointInGrid[1] ?? null;
|
|
28
|
-
if (cursorX === null || cursorY === null) return
|
|
29
|
-
if (chart.dispatchAction === undefined) return
|
|
30
|
-
if (!Array.isArray(data)) return
|
|
31
|
-
|
|
32
|
-
const emphasizedSeriesIndexes = [];
|
|
33
|
-
const nonEmphasizedSeriesIndexes = [];
|
|
34
|
-
const emphasizedDatapoints = [];
|
|
35
|
-
const duplicateDatapoints = [];
|
|
36
|
-
const totalSeries = data.length;
|
|
37
|
-
const yValueCounts = new Map();
|
|
38
|
-
// Only need to loop through first dataset source since getCommonTimeScale ensures xAxis timestamps are consistent
|
|
225
|
+
if (cursorX === null || cursorY === null) return EMPTY_TOOLTIP_DATA;
|
|
226
|
+
if (chart.dispatchAction === undefined) return EMPTY_TOOLTIP_DATA;
|
|
227
|
+
if (!Array.isArray(data)) return EMPTY_TOOLTIP_DATA;
|
|
228
|
+
// All series share the same x-axis timestamps (enforced by getCommonTimeScale).
|
|
39
229
|
const firstTimeSeriesValues = data[0]?.values;
|
|
40
230
|
const closestTimestamp = getClosestTimestamp(firstTimeSeriesValues, cursorX);
|
|
41
|
-
if (closestTimestamp === null)
|
|
42
|
-
return EMPTY_TOOLTIP_DATA;
|
|
43
|
-
}
|
|
44
|
-
// For multi-axis support: convert yBuffer to pixel space for consistent comparison
|
|
45
|
-
// This allows us to compare series on different Y axes fairly
|
|
231
|
+
if (closestTimestamp === null) return EMPTY_TOOLTIP_DATA;
|
|
46
232
|
let yBufferPixels = null;
|
|
47
233
|
if (cursorPixelY !== undefined) {
|
|
48
|
-
// Convert a point at cursorY and cursorY + yBuffer to pixels to get the buffer in pixel space
|
|
49
234
|
const cursorPoint = chart.convertToPixel('grid', [
|
|
50
235
|
0,
|
|
51
236
|
cursorY
|
|
@@ -58,133 +243,16 @@ cursorPixelY) {
|
|
|
58
243
|
yBufferPixels = Math.abs(bufferPoint[1] - cursorPoint[1]);
|
|
59
244
|
}
|
|
60
245
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
const lineSeries = currentSeries;
|
|
70
|
-
const currentSeriesName = lineSeries.name ? lineSeries.name.toString() : '';
|
|
71
|
-
const seriesId = lineSeries.id ? lineSeries.id.toString() : '';
|
|
72
|
-
const markerColor = lineSeries.color ?? '#000';
|
|
73
|
-
// Get the format for this series (from seriesFormatMap or fallback to default format)
|
|
74
|
-
const seriesFormat = seriesFormatMap?.get(seriesId) ?? format;
|
|
75
|
-
if (Array.isArray(data)) {
|
|
76
|
-
for(let datumIdx = 0; datumIdx < currentDatasetValues.length; datumIdx++){
|
|
77
|
-
const nearbyTimeSeries = currentDatasetValues[datumIdx];
|
|
78
|
-
if (nearbyTimeSeries === undefined || !Array.isArray(nearbyTimeSeries)) break;
|
|
79
|
-
const xValue = nearbyTimeSeries[0];
|
|
80
|
-
const yValue = nearbyTimeSeries[1];
|
|
81
|
-
// TODO: ensure null values not displayed in tooltip
|
|
82
|
-
if (yValue !== undefined && yValue !== null) {
|
|
83
|
-
if (closestTimestamp === xValue) {
|
|
84
|
-
// Check if this series is nearby the cursor
|
|
85
|
-
let isNearby = false;
|
|
86
|
-
// For multi-axis: compare in pixel space
|
|
87
|
-
if (cursorPixelY !== undefined && yBufferPixels !== null) {
|
|
88
|
-
const dataPointPixel = chart.convertToPixel({
|
|
89
|
-
seriesIndex: seriesIdx
|
|
90
|
-
}, [
|
|
91
|
-
datumIdx,
|
|
92
|
-
yValue
|
|
93
|
-
]);
|
|
94
|
-
if (dataPointPixel && dataPointPixel[1] !== undefined) {
|
|
95
|
-
const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);
|
|
96
|
-
isNearby = pixelDistance <= yBufferPixels;
|
|
97
|
-
} else {
|
|
98
|
-
// Fallback to data-space comparison for primary axis
|
|
99
|
-
isNearby = cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer;
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
// Fallback to original data-space comparison
|
|
103
|
-
isNearby = cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer;
|
|
104
|
-
}
|
|
105
|
-
if (isNearby) {
|
|
106
|
-
// show fewer bold series in tooltip when many total series
|
|
107
|
-
const minPercentRange = totalSeries > SHOW_FEWER_SERIES_LIMIT ? 2 : 5;
|
|
108
|
-
const percentRangeToCheck = Math.max(minPercentRange, 100 / totalSeries);
|
|
109
|
-
// For isClosestToCursor, also use pixel space for multi-axis
|
|
110
|
-
let isClosestToCursor = false;
|
|
111
|
-
if (cursorPixelY !== undefined) {
|
|
112
|
-
const dataPointPixel = chart.convertToPixel({
|
|
113
|
-
seriesIndex: seriesIdx
|
|
114
|
-
}, [
|
|
115
|
-
datumIdx,
|
|
116
|
-
yValue
|
|
117
|
-
]);
|
|
118
|
-
if (dataPointPixel && dataPointPixel[1] !== undefined) {
|
|
119
|
-
const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);
|
|
120
|
-
// Use percentage of buffer for "closest" determination
|
|
121
|
-
const tightBufferPixels = (yBufferPixels ?? 50) * (percentRangeToCheck / 100);
|
|
122
|
-
isClosestToCursor = pixelDistance <= Math.max(tightBufferPixels, 5);
|
|
123
|
-
} else {
|
|
124
|
-
isClosestToCursor = isWithinPercentageRange({
|
|
125
|
-
valueToCheck: cursorY,
|
|
126
|
-
baseValue: yValue,
|
|
127
|
-
percentage: percentRangeToCheck
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
isClosestToCursor = isWithinPercentageRange({
|
|
132
|
-
valueToCheck: cursorY,
|
|
133
|
-
baseValue: yValue,
|
|
134
|
-
percentage: percentRangeToCheck
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
if (isClosestToCursor) {
|
|
138
|
-
// shows as bold in tooltip, customize 'emphasis' options in getTimeSeries util
|
|
139
|
-
emphasizedSeriesIndexes.push(seriesIdx);
|
|
140
|
-
// Used to determine which datapoint to apply select styles to.
|
|
141
|
-
// Accounts for cases where lines may be rendered directly on top of eachother.
|
|
142
|
-
const duplicateValuesCount = yValueCounts.get(yValue) ?? 0;
|
|
143
|
-
yValueCounts.set(yValue, duplicateValuesCount + 1);
|
|
144
|
-
if (duplicateValuesCount > 0) {
|
|
145
|
-
duplicateDatapoints.push({
|
|
146
|
-
seriesIndex: seriesIdx,
|
|
147
|
-
dataIndex: datumIdx,
|
|
148
|
-
seriesName: currentSeriesName,
|
|
149
|
-
yValue: yValue
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
// keep track of all bold datapoints in tooltip so that 'select' state only applied to topmost
|
|
153
|
-
emphasizedDatapoints.push({
|
|
154
|
-
seriesIndex: seriesIdx,
|
|
155
|
-
dataIndex: datumIdx,
|
|
156
|
-
seriesName: currentSeriesName,
|
|
157
|
-
yValue: yValue
|
|
158
|
-
});
|
|
159
|
-
} else {
|
|
160
|
-
nonEmphasizedSeriesIndexes.push(seriesIdx);
|
|
161
|
-
// ensure series far away from cursor are not highlighted
|
|
162
|
-
chart.dispatchAction({
|
|
163
|
-
type: 'downplay',
|
|
164
|
-
seriesIndex: seriesIdx
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
const formattedY = formatValue(yValue, seriesFormat);
|
|
168
|
-
currentNearbySeriesData.push({
|
|
169
|
-
seriesIdx: seriesIdx,
|
|
170
|
-
datumIdx: datumIdx,
|
|
171
|
-
seriesName: currentSeriesName,
|
|
172
|
-
date: closestTimestamp,
|
|
173
|
-
x: xValue,
|
|
174
|
-
y: yValue,
|
|
175
|
-
formattedY: formattedY,
|
|
176
|
-
markerColor: markerColor.toString(),
|
|
177
|
-
isClosestToCursor
|
|
178
|
-
});
|
|
179
|
-
nearbySeriesIndexes.push(seriesIdx);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
246
|
+
const resolvedCursorXPixel = cursorXPixel ?? getPixelXFromGrid(closestTimestamp, chart);
|
|
247
|
+
const candidates = gatherCandidates(data, seriesMapping, closestTimestamp, cursorX, cursorY, resolvedCursorXPixel, cursorPixelY, yBuffer, yBufferPixels, chart);
|
|
248
|
+
const winner = findClosestCandidate(candidates);
|
|
249
|
+
const candidateIndexes = new Set();
|
|
250
|
+
for (const candidate of candidates)candidateIndexes.add(candidate.seriesIdx);
|
|
251
|
+
const nonCandidateSeriesIndexes = [];
|
|
252
|
+
for(let idx = 0; idx < data.length; idx++){
|
|
253
|
+
if (!candidateIndexes.has(idx)) nonCandidateSeriesIndexes.push(idx);
|
|
185
254
|
}
|
|
186
|
-
|
|
187
|
-
return currentNearbySeriesData;
|
|
255
|
+
return processCandidates(candidates, winner, format, seriesFormatMap, chart, nonCandidateSeriesIndexes);
|
|
188
256
|
}
|
|
189
257
|
/**
|
|
190
258
|
* [DEPRECATED] Returns formatted series data for the points that are close to the user's cursor
|
|
@@ -308,24 +376,22 @@ cursorPixelY) {
|
|
|
308
376
|
cursorTargetMatchesChart = true;
|
|
309
377
|
}
|
|
310
378
|
if (cursorTargetMatchesChart === false || data === null || chart['_model'] === undefined) return EMPTY_TOOLTIP_DATA;
|
|
311
|
-
// mousemove position undefined when not hovering over chart canvas
|
|
312
379
|
if (mousePos.plotCanvas.x === undefined || mousePos.plotCanvas.y === undefined) return EMPTY_TOOLTIP_DATA;
|
|
313
380
|
const cursorPixelY = mousePos.plotCanvas.y;
|
|
314
|
-
const
|
|
381
|
+
const cursorXPixel = mousePos.plotCanvas.x;
|
|
382
|
+
const pointInGrid = getPointInGrid(cursorXPixel, cursorPixelY, chart);
|
|
315
383
|
if (pointInGrid !== null) {
|
|
316
384
|
const chartModel = chart['_model'];
|
|
317
385
|
const yAxisScale = chartModel.getComponent('yAxis').axis.scale;
|
|
318
386
|
const isLogScale = yAxisScale.type === 'log';
|
|
319
387
|
let yInterval = yAxisScale._interval;
|
|
320
|
-
// For
|
|
388
|
+
// For log scales, convert from log-space extent to actual data range and use 1% as the interval.
|
|
321
389
|
if (isLogScale && yAxisScale.base) {
|
|
322
390
|
const logBase = yAxisScale.base;
|
|
323
391
|
const extent = yAxisScale._extent;
|
|
324
|
-
//
|
|
325
|
-
// extent is in log space (e.g., [0, 2] for 10^0 to 10^2)
|
|
392
|
+
// e.g. extent [0, 2] → 10^0..10^2
|
|
326
393
|
const actualMin = logBase ** extent[0];
|
|
327
394
|
const actualMax = logBase ** extent[1];
|
|
328
|
-
// Use a fraction of the actual range as the interval
|
|
329
395
|
yInterval = (actualMax - actualMin) / 100;
|
|
330
396
|
}
|
|
331
397
|
const totalSeries = data.length;
|
|
@@ -334,9 +400,8 @@ cursorPixelY) {
|
|
|
334
400
|
totalSeries,
|
|
335
401
|
showAllSeries
|
|
336
402
|
});
|
|
337
|
-
// Detect if chart has multiple Y-axes by checking if any series uses yAxisIndex > 0
|
|
338
403
|
const hasMultipleYAxes = seriesMapping.some((series)=>series.yAxisIndex !== undefined && series.yAxisIndex > 0);
|
|
339
|
-
return checkforNearbyTimeSeries(data, seriesMapping, pointInGrid, yBuffer, chart, format, seriesFormatMap, hasMultipleYAxes ? cursorPixelY : undefined);
|
|
404
|
+
return checkforNearbyTimeSeries(data, seriesMapping, pointInGrid, yBuffer, chart, format, seriesFormatMap, hasMultipleYAxes ? cursorPixelY : undefined, cursorXPixel);
|
|
340
405
|
}
|
|
341
406
|
// no nearby series found
|
|
342
407
|
return EMPTY_TOOLTIP_DATA;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/TimeSeriesTooltip/nearby-series.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { LineSeriesOption } from 'echarts/charts';\nimport { TimeSeries, TimeSeriesValueTuple } from '@perses-dev/spec';\nimport {\n EChartsDataFormat,\n OPTIMIZED_MODE_SERIES_LIMIT,\n TimeChartSeriesMapping,\n DatapointInfo,\n FormatOptions,\n formatValue,\n} from '../model';\nimport { batchDispatchNearbySeriesActions, getPointInGrid, getClosestTimestamp } from '../utils';\nimport { CursorCoordinates, CursorData, EMPTY_TOOLTIP_DATA } from './tooltip-model';\n\n// increase multipliers to show more series in tooltip\nexport const INCREASE_NEARBY_SERIES_MULTIPLIER = 5.5; // adjusts how many series show in tooltip (higher == more series shown)\nexport const DYNAMIC_NEARBY_SERIES_MULTIPLIER = 30; // used for adjustment after series number divisor\nexport const SHOW_FEWER_SERIES_LIMIT = 5;\n\nexport interface NearbySeriesInfo {\n seriesIdx: number | null;\n datumIdx: number | null;\n seriesName: string;\n date: number;\n markerColor: string;\n x: number;\n y: number;\n formattedY: string;\n isClosestToCursor: boolean;\n}\n\nexport type NearbySeriesArray = NearbySeriesInfo[];\n\n/**\n * Returns formatted series data for the points that are close to the user's cursor.\n * Adjust xBuffer and yBuffer to increase or decrease number of series shown.\n */\nexport function checkforNearbyTimeSeries(\n data: TimeSeries[],\n seriesMapping: TimeChartSeriesMapping,\n pointInGrid: number[],\n yBuffer: number,\n chart: EChartsInstance,\n format?: FormatOptions,\n seriesFormatMap?: Map<string, FormatOptions>,\n // in the case of multi-axis, we need the cursor Y position in pixel space\n cursorPixelY?: number\n): NearbySeriesArray {\n const currentNearbySeriesData: NearbySeriesArray = [];\n const cursorX: number | null = pointInGrid[0] ?? null;\n const cursorY: number | null = pointInGrid[1] ?? null;\n\n if (cursorX === null || cursorY === null) return currentNearbySeriesData;\n\n if (chart.dispatchAction === undefined) return currentNearbySeriesData;\n\n if (!Array.isArray(data)) return currentNearbySeriesData;\n const nearbySeriesIndexes: number[] = [];\n const emphasizedSeriesIndexes: number[] = [];\n const nonEmphasizedSeriesIndexes: number[] = [];\n const emphasizedDatapoints: DatapointInfo[] = [];\n const duplicateDatapoints: DatapointInfo[] = [];\n\n const totalSeries = data.length;\n\n const yValueCounts: Map<number, number> = new Map();\n\n // Only need to loop through first dataset source since getCommonTimeScale ensures xAxis timestamps are consistent\n const firstTimeSeriesValues = data[0]?.values;\n const closestTimestamp = getClosestTimestamp(firstTimeSeriesValues, cursorX);\n\n if (closestTimestamp === null) {\n return EMPTY_TOOLTIP_DATA;\n }\n\n // For multi-axis support: convert yBuffer to pixel space for consistent comparison\n // This allows us to compare series on different Y axes fairly\n let yBufferPixels: number | null = null;\n if (cursorPixelY !== undefined) {\n // Convert a point at cursorY and cursorY + yBuffer to pixels to get the buffer in pixel space\n const cursorPoint = chart.convertToPixel('grid', [0, cursorY]);\n const bufferPoint = chart.convertToPixel('grid', [0, cursorY + yBuffer]);\n if (cursorPoint && bufferPoint && cursorPoint[1] !== undefined && bufferPoint[1] !== undefined) {\n yBufferPixels = Math.abs(bufferPoint[1] - cursorPoint[1]);\n }\n }\n\n // find the timestamp with data that is closest to cursorX\n for (let seriesIdx = 0; seriesIdx < totalSeries; seriesIdx++) {\n const currentSeries = seriesMapping[seriesIdx];\n if (!currentSeries) break;\n\n const currentDataset = totalSeries > 0 ? data[seriesIdx] : null;\n if (!currentDataset) break;\n\n const currentDatasetValues: TimeSeriesValueTuple[] = currentDataset.values;\n if (currentDatasetValues === undefined || !Array.isArray(currentDatasetValues)) break;\n const lineSeries = currentSeries as LineSeriesOption;\n const currentSeriesName = lineSeries.name ? lineSeries.name.toString() : '';\n const seriesId = lineSeries.id ? lineSeries.id.toString() : '';\n const markerColor = lineSeries.color ?? '#000';\n\n // Get the format for this series (from seriesFormatMap or fallback to default format)\n const seriesFormat = seriesFormatMap?.get(seriesId) ?? format;\n\n if (Array.isArray(data)) {\n for (let datumIdx = 0; datumIdx < currentDatasetValues.length; datumIdx++) {\n const nearbyTimeSeries = currentDatasetValues[datumIdx];\n if (nearbyTimeSeries === undefined || !Array.isArray(nearbyTimeSeries)) break;\n\n const xValue = nearbyTimeSeries[0];\n const yValue = nearbyTimeSeries[1];\n // TODO: ensure null values not displayed in tooltip\n if (yValue !== undefined && yValue !== null) {\n if (closestTimestamp === xValue) {\n // Check if this series is nearby the cursor\n let isNearby = false;\n\n // For multi-axis: compare in pixel space\n if (cursorPixelY !== undefined && yBufferPixels !== null) {\n const dataPointPixel = chart.convertToPixel({ seriesIndex: seriesIdx }, [datumIdx, yValue]);\n if (dataPointPixel && dataPointPixel[1] !== undefined) {\n const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);\n isNearby = pixelDistance <= yBufferPixels;\n } else {\n // Fallback to data-space comparison for primary axis\n isNearby = cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer;\n }\n } else {\n // Fallback to original data-space comparison\n isNearby = cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer;\n }\n\n if (isNearby) {\n // show fewer bold series in tooltip when many total series\n const minPercentRange = totalSeries > SHOW_FEWER_SERIES_LIMIT ? 2 : 5;\n const percentRangeToCheck = Math.max(minPercentRange, 100 / totalSeries);\n\n // For isClosestToCursor, also use pixel space for multi-axis\n let isClosestToCursor = false;\n if (cursorPixelY !== undefined) {\n const dataPointPixel = chart.convertToPixel({ seriesIndex: seriesIdx }, [datumIdx, yValue]);\n if (dataPointPixel && dataPointPixel[1] !== undefined) {\n const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);\n // Use percentage of buffer for \"closest\" determination\n const tightBufferPixels = (yBufferPixels ?? 50) * (percentRangeToCheck / 100);\n isClosestToCursor = pixelDistance <= Math.max(tightBufferPixels, 5);\n } else {\n isClosestToCursor = isWithinPercentageRange({\n valueToCheck: cursorY,\n baseValue: yValue,\n percentage: percentRangeToCheck,\n });\n }\n } else {\n isClosestToCursor = isWithinPercentageRange({\n valueToCheck: cursorY,\n baseValue: yValue,\n percentage: percentRangeToCheck,\n });\n }\n\n if (isClosestToCursor) {\n // shows as bold in tooltip, customize 'emphasis' options in getTimeSeries util\n emphasizedSeriesIndexes.push(seriesIdx);\n\n // Used to determine which datapoint to apply select styles to.\n // Accounts for cases where lines may be rendered directly on top of eachother.\n const duplicateValuesCount = yValueCounts.get(yValue) ?? 0;\n yValueCounts.set(yValue, duplicateValuesCount + 1);\n if (duplicateValuesCount > 0) {\n duplicateDatapoints.push({\n seriesIndex: seriesIdx,\n dataIndex: datumIdx,\n seriesName: currentSeriesName,\n yValue: yValue,\n });\n }\n\n // keep track of all bold datapoints in tooltip so that 'select' state only applied to topmost\n emphasizedDatapoints.push({\n seriesIndex: seriesIdx,\n dataIndex: datumIdx,\n seriesName: currentSeriesName,\n yValue: yValue,\n });\n } else {\n nonEmphasizedSeriesIndexes.push(seriesIdx);\n // ensure series far away from cursor are not highlighted\n chart.dispatchAction({\n type: 'downplay',\n seriesIndex: seriesIdx,\n });\n }\n const formattedY = formatValue(yValue, seriesFormat);\n currentNearbySeriesData.push({\n seriesIdx: seriesIdx,\n datumIdx: datumIdx,\n seriesName: currentSeriesName,\n date: closestTimestamp,\n x: xValue,\n y: yValue,\n formattedY: formattedY,\n markerColor: markerColor.toString(),\n isClosestToCursor,\n });\n nearbySeriesIndexes.push(seriesIdx);\n }\n }\n }\n }\n }\n }\n\n batchDispatchNearbySeriesActions(\n chart,\n nearbySeriesIndexes,\n emphasizedSeriesIndexes,\n nonEmphasizedSeriesIndexes,\n emphasizedDatapoints,\n duplicateDatapoints\n );\n\n return currentNearbySeriesData;\n}\n\n/**\n * [DEPRECATED] Returns formatted series data for the points that are close to the user's cursor\n * Adjust yBuffer to increase or decrease number of series shown\n */\nexport function legacyCheckforNearbySeries(\n data: EChartsDataFormat,\n pointInGrid: number[],\n yBuffer: number,\n chart?: EChartsInstance,\n format?: FormatOptions\n): NearbySeriesArray {\n const currentNearbySeriesData: NearbySeriesArray = [];\n const cursorX: number | null = pointInGrid[0] ?? null;\n const cursorY: number | null = pointInGrid[1] ?? null;\n\n if (cursorX === null || cursorY === null) {\n return currentNearbySeriesData;\n }\n\n const nearbySeriesIndexes: number[] = [];\n const emphasizedSeriesIndexes: number[] = [];\n const nonEmphasizedSeriesIndexes: number[] = [];\n const totalSeries = data.timeSeries.length;\n if (Array.isArray(data.xAxis) && Array.isArray(data.timeSeries)) {\n for (let seriesIdx = 0; seriesIdx < totalSeries; seriesIdx++) {\n const currentSeries = data.timeSeries[seriesIdx];\n if (currentSeries === undefined) break;\n if (currentNearbySeriesData.length >= OPTIMIZED_MODE_SERIES_LIMIT) break;\n\n const currentSeriesName = currentSeries.name ? currentSeries.name.toString() : '';\n const markerColor = currentSeries.color ?? '#000';\n if (Array.isArray(currentSeries.data)) {\n for (let datumIdx = 0; datumIdx < currentSeries.data.length; datumIdx++) {\n const xValue = data.xAxis[datumIdx] ?? 0;\n const yValue = currentSeries.data[datumIdx];\n // ensure null values not displayed in tooltip\n if (yValue !== undefined && yValue !== null && cursorX === datumIdx) {\n if (yValue !== '-' && cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer) {\n // show fewer bold series in tooltip when many total series\n const minPercentRange = totalSeries > SHOW_FEWER_SERIES_LIMIT ? 2 : 5;\n const percentRangeToCheck = Math.max(minPercentRange, 100 / totalSeries);\n const isClosestToCursor = isWithinPercentageRange({\n valueToCheck: cursorY,\n baseValue: yValue,\n percentage: percentRangeToCheck,\n });\n if (isClosestToCursor) {\n emphasizedSeriesIndexes.push(seriesIdx);\n } else {\n nonEmphasizedSeriesIndexes.push(seriesIdx);\n // ensure series not close to cursor are not highlighted\n if (chart?.dispatchAction !== undefined) {\n chart.dispatchAction({\n type: 'downplay',\n seriesIndex: seriesIdx,\n });\n }\n }\n\n // determine whether to convert timestamp to ms, see: https://stackoverflow.com/a/23982005/17575201\n const xValueMilliSeconds = xValue > 99999999999 ? xValue : xValue * 1000;\n const formattedY = formatValue(yValue, format);\n currentNearbySeriesData.push({\n seriesIdx: seriesIdx,\n datumIdx: datumIdx,\n seriesName: currentSeriesName,\n date: xValueMilliSeconds,\n x: xValue,\n y: yValue,\n formattedY: formattedY,\n markerColor: markerColor.toString(),\n isClosestToCursor,\n });\n nearbySeriesIndexes.push(seriesIdx);\n }\n }\n }\n }\n }\n }\n if (chart?.dispatchAction !== undefined) {\n // Clears emphasis state of all lines that are not emphasized.\n // Emphasized is a subset of just the nearby series that are closest to cursor.\n chart.dispatchAction({\n type: 'downplay',\n seriesIndex: nonEmphasizedSeriesIndexes,\n });\n\n // https://echarts.apache.org/en/api.html#action.highlight\n if (emphasizedSeriesIndexes.length > 0) {\n // Fadeout opacity of all series not closest to cursor.\n chart.dispatchAction({\n type: 'highlight',\n seriesIndex: emphasizedSeriesIndexes,\n notBlur: false, // ensure blur IS triggered, this is default but setting so it is explicit\n escapeConnect: true, // shared crosshair should not emphasize series on adjacent charts\n });\n } else {\n // When no emphasized series with bold text, notBlur allows opacity fadeout to not trigger.\n chart.dispatchAction({\n type: 'highlight',\n seriesIndex: nearbySeriesIndexes,\n notBlur: true, // do not trigger blur state when cursor is not immediately close to any series\n escapeConnect: true, // shared crosshair should not emphasize series on adjacent charts\n });\n }\n }\n\n return currentNearbySeriesData;\n}\n\n/**\n * Uses mouse position to determine whether user is hovering over a chart canvas\n * If yes, convert from pixel values to logical cartesian coordinates and return all nearby series\n */\nexport function getNearbySeriesData({\n mousePos,\n pinnedPos,\n data,\n seriesMapping,\n chart,\n format,\n seriesFormatMap,\n showAllSeries = false,\n}: {\n mousePos: CursorData['coords'];\n pinnedPos: CursorCoordinates | null;\n data: TimeSeries[];\n seriesMapping: TimeChartSeriesMapping;\n chart?: EChartsInstance;\n format?: FormatOptions;\n seriesFormatMap?: Map<string, FormatOptions>;\n showAllSeries?: boolean;\n}): NearbySeriesArray {\n if (chart === undefined || mousePos === null) return EMPTY_TOOLTIP_DATA;\n\n // prevents multiple tooltips showing from adjacent charts unless tooltip is pinned\n let cursorTargetMatchesChart = false;\n if (mousePos.target !== null) {\n const currentParent = (<HTMLElement>mousePos.target).parentElement;\n if (currentParent !== null) {\n const currentGrandparent = currentParent.parentElement;\n if (currentGrandparent !== null) {\n const chartDom = chart.getDom();\n if (chartDom === currentGrandparent) {\n cursorTargetMatchesChart = true;\n }\n }\n }\n }\n\n // allows moving cursor inside tooltip without it fading away\n if (pinnedPos !== null) {\n mousePos = pinnedPos;\n cursorTargetMatchesChart = true;\n }\n\n if (cursorTargetMatchesChart === false || data === null || chart['_model'] === undefined) return EMPTY_TOOLTIP_DATA;\n\n // mousemove position undefined when not hovering over chart canvas\n if (mousePos.plotCanvas.x === undefined || mousePos.plotCanvas.y === undefined) return EMPTY_TOOLTIP_DATA;\n\n const cursorPixelY = mousePos.plotCanvas.y;\n const pointInGrid = getPointInGrid(mousePos.plotCanvas.x, cursorPixelY, chart);\n if (pointInGrid !== null) {\n const chartModel = chart['_model'];\n const yAxisScale = chartModel.getComponent('yAxis').axis.scale;\n const isLogScale = yAxisScale.type === 'log';\n let yInterval = yAxisScale._interval;\n // For logarithmic scales, convert the log interval to actual data range\n if (isLogScale && yAxisScale.base) {\n const logBase = yAxisScale.base;\n const extent = yAxisScale._extent;\n // Calculate actual data range from log extent\n // extent is in log space (e.g., [0, 2] for 10^0 to 10^2)\n const actualMin = logBase ** extent[0];\n const actualMax = logBase ** extent[1];\n // Use a fraction of the actual range as the interval\n yInterval = (actualMax - actualMin) / 100;\n }\n const totalSeries = data.length;\n const yBuffer = getYBuffer({ yInterval, totalSeries, showAllSeries });\n\n // Detect if chart has multiple Y-axes by checking if any series uses yAxisIndex > 0\n const hasMultipleYAxes = seriesMapping.some((series) => series.yAxisIndex !== undefined && series.yAxisIndex > 0);\n\n return checkforNearbyTimeSeries(\n data,\n seriesMapping,\n pointInGrid,\n yBuffer,\n chart,\n format,\n seriesFormatMap,\n hasMultipleYAxes ? cursorPixelY : undefined\n );\n }\n\n // no nearby series found\n return EMPTY_TOOLTIP_DATA;\n}\n\n/*\n * Check if two numbers are within a specified percentage range\n */\nexport function isWithinPercentageRange({\n valueToCheck,\n baseValue,\n percentage,\n}: {\n valueToCheck: number;\n baseValue: number;\n percentage: number;\n}): boolean {\n const range = (percentage / 100) * baseValue;\n const lowerBound = baseValue - range;\n const upperBound = baseValue + range;\n return valueToCheck >= lowerBound && valueToCheck <= upperBound;\n}\n\n/*\n * Get range to check within for nearby series to show in tooltip.\n */\nexport function getYBuffer({\n yInterval,\n totalSeries,\n showAllSeries = false,\n}: {\n yInterval: number;\n totalSeries: number;\n showAllSeries?: boolean;\n}): number {\n if (showAllSeries) {\n return yInterval * 10; // roughly correlates with grid so entire canvas is searched\n }\n // never let nearby series range be less than roughly the size of a single tick\n const yBufferMin = yInterval * 0.3;\n\n // tooltip trigger area gets smaller with more series\n if (totalSeries > SHOW_FEWER_SERIES_LIMIT) {\n const adjustedBuffer = (yInterval * DYNAMIC_NEARBY_SERIES_MULTIPLIER) / totalSeries;\n return Math.max(yBufferMin, adjustedBuffer);\n }\n // increase multiplier to expand nearby series range\n return Math.max(yBufferMin, yInterval * INCREASE_NEARBY_SERIES_MULTIPLIER);\n}\n"],"names":["OPTIMIZED_MODE_SERIES_LIMIT","formatValue","batchDispatchNearbySeriesActions","getPointInGrid","getClosestTimestamp","EMPTY_TOOLTIP_DATA","INCREASE_NEARBY_SERIES_MULTIPLIER","DYNAMIC_NEARBY_SERIES_MULTIPLIER","SHOW_FEWER_SERIES_LIMIT","checkforNearbyTimeSeries","data","seriesMapping","pointInGrid","yBuffer","chart","format","seriesFormatMap","cursorPixelY","currentNearbySeriesData","cursorX","cursorY","dispatchAction","undefined","Array","isArray","nearbySeriesIndexes","emphasizedSeriesIndexes","nonEmphasizedSeriesIndexes","emphasizedDatapoints","duplicateDatapoints","totalSeries","length","yValueCounts","Map","firstTimeSeriesValues","values","closestTimestamp","yBufferPixels","cursorPoint","convertToPixel","bufferPoint","Math","abs","seriesIdx","currentSeries","currentDataset","currentDatasetValues","lineSeries","currentSeriesName","name","toString","seriesId","id","markerColor","color","seriesFormat","get","datumIdx","nearbyTimeSeries","xValue","yValue","isNearby","dataPointPixel","seriesIndex","pixelDistance","minPercentRange","percentRangeToCheck","max","isClosestToCursor","tightBufferPixels","isWithinPercentageRange","valueToCheck","baseValue","percentage","push","duplicateValuesCount","set","dataIndex","seriesName","type","formattedY","date","x","y","legacyCheckforNearbySeries","timeSeries","xAxis","xValueMilliSeconds","notBlur","escapeConnect","getNearbySeriesData","mousePos","pinnedPos","showAllSeries","cursorTargetMatchesChart","target","currentParent","parentElement","currentGrandparent","chartDom","getDom","plotCanvas","chartModel","yAxisScale","getComponent","axis","scale","isLogScale","yInterval","_interval","base","logBase","extent","_extent","actualMin","actualMax","getYBuffer","hasMultipleYAxes","some","series","yAxisIndex","range","lowerBound","upperBound","yBufferMin","adjustedBuffer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/TimeSeriesTooltip/nearby-series.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { BarSeriesOption } from 'echarts/charts';\nimport { TimeSeries, TimeSeriesValueTuple } from '@perses-dev/spec';\nimport {\n EChartsDataFormat,\n OPTIMIZED_MODE_SERIES_LIMIT,\n TimeChartSeriesMapping,\n DatapointInfo,\n FormatOptions,\n formatValue,\n} from '../model';\nimport { batchDispatchNearbySeriesActions, getPointInGrid, getClosestTimestamp } from '../utils';\nimport { CursorCoordinates, CursorData, EMPTY_TOOLTIP_DATA } from './tooltip-model';\nimport {\n calculateBarBandwidth,\n calculateBarSegmentBounds,\n calculateBarYBounds,\n calculateVisualYForSeries,\n getPixelXFromGrid,\n} from './utils';\nimport { Candidate, GetYBufferParams, IsWithinPercentageRangeParams, NearbySeriesArray } from './types';\n\nexport type { NearbySeriesArray, NearbySeriesInfo } from './types';\n\n// increase multipliers to show more series in tooltip\nexport const INCREASE_NEARBY_SERIES_MULTIPLIER = 5.5; // adjusts how many series show in tooltip (higher == more series shown)\nexport const DYNAMIC_NEARBY_SERIES_MULTIPLIER = 30; // used for adjustment after series number divisor\nexport const SHOW_FEWER_SERIES_LIMIT = 5;\n\nfunction gatherCandidates(\n data: TimeSeries[],\n seriesMapping: TimeChartSeriesMapping,\n closestTimestamp: number,\n cursorX: number,\n cursorY: number,\n cursorXPixel: number | null,\n cursorPixelY: number | undefined,\n yBuffer: number,\n yBufferPixels: number | null,\n chart: EChartsInstance\n): Candidate[] {\n const candidates: Candidate[] = [];\n const totalSeries = data.length;\n\n const stackTotals = new Map<string, number>();\n\n let sortedTimestamps: number[] = [];\n const firstValues = data[0]?.values;\n if (firstValues && firstValues.length > 0) {\n const seen = new Set<number>();\n for (const [ts] of firstValues) {\n if (!seen.has(ts)) {\n seen.add(ts);\n sortedTimestamps.push(ts);\n }\n }\n sortedTimestamps = sortedTimestamps.sort((a, b) => a - b);\n }\n\n // Bar-only indexes: ECharts groups bars independently of lines, so bar-relative index and count must exclude line series.\n const barSeriesIndexes: number[] = [];\n for (let i = 0; i < totalSeries; i++) {\n if ((seriesMapping[i]?.type ?? 'line') === 'bar') barSeriesIndexes.push(i);\n }\n\n // Computed once outside the loop — both depend only on the timestamp, not the series index.\n let barBandwidth: number | null = null;\n let barCenterPixelX: number | null = null;\n if (barSeriesIndexes.length > 0 && cursorXPixel !== null) {\n barBandwidth = calculateBarBandwidth(closestTimestamp, sortedTimestamps, chart);\n barCenterPixelX = getPixelXFromGrid(closestTimestamp, chart);\n }\n\n for (let seriesIdx = 0; seriesIdx < totalSeries; seriesIdx++) {\n const currentSeries = seriesMapping[seriesIdx];\n if (!currentSeries) continue;\n\n const currentDataset = data[seriesIdx];\n if (!currentDataset) continue;\n\n const currentDatasetValues: TimeSeriesValueTuple[] | undefined = currentDataset.values;\n if (!currentDatasetValues || !Array.isArray(currentDatasetValues)) continue;\n\n const seriesType = currentSeries.type ?? 'line';\n const currentSeriesName = currentSeries.name ? currentSeries.name.toString() : '';\n const seriesId = currentSeries.id ? currentSeries.id.toString() : '';\n const markerColor = (currentSeries.color ?? '#000').toString();\n\n let datumIdx = -1;\n let xValue = 0;\n let yValue: number | null | undefined;\n for (let i = 0; i < currentDatasetValues.length; i++) {\n const tuple = currentDatasetValues[i];\n if (!tuple) continue;\n if (tuple[0] === closestTimestamp) {\n datumIdx = i;\n xValue = tuple[0];\n yValue = tuple[1];\n break;\n }\n }\n if (datumIdx === -1) continue;\n\n if (yValue === null || yValue === undefined) continue;\n\n let isCandidate = false;\n let visualY = yValue;\n let distance = Infinity;\n\n if (seriesType === 'line') {\n visualY = calculateVisualYForSeries(seriesIdx, yValue, seriesMapping, stackTotals);\n\n if (cursorPixelY !== undefined && yBufferPixels !== null) {\n try {\n const dataPointPixel = chart.convertToPixel({ seriesIndex: seriesIdx }, [datumIdx, visualY]);\n if (dataPointPixel && dataPointPixel[1] !== undefined) {\n const pixelDistance = Math.abs(cursorPixelY - dataPointPixel[1]);\n isCandidate = pixelDistance <= yBufferPixels;\n distance = pixelDistance;\n } else {\n const verticalDistance = Math.abs(visualY - cursorY);\n isCandidate = verticalDistance <= yBuffer;\n distance = verticalDistance;\n }\n } catch {\n const verticalDistance = Math.abs(visualY - cursorY);\n isCandidate = verticalDistance <= yBuffer;\n distance = verticalDistance;\n }\n } else {\n const verticalDistance = Math.abs(visualY - cursorY);\n isCandidate = verticalDistance <= yBuffer;\n distance = verticalDistance;\n }\n } else if (seriesType === 'bar') {\n if (cursorXPixel === null || barBandwidth === null || barCenterPixelX === null) continue;\n\n const barRelativeIdx = barSeriesIndexes.indexOf(seriesIdx);\n if (barRelativeIdx === -1) continue;\n\n const segmentBounds = calculateBarSegmentBounds(\n barRelativeIdx,\n barBandwidth,\n barCenterPixelX,\n barSeriesIndexes.length\n );\n\n const isWithinXBounds = cursorXPixel >= segmentBounds.left && cursorXPixel <= segmentBounds.right;\n if (!isWithinXBounds) continue;\n\n const stackId = (currentSeries as BarSeriesOption).stack;\n let isHoveringYBounds = true;\n\n if (stackId) {\n const stackIdStr = stackId.toString();\n const visualYBottom = stackTotals.get(stackIdStr) ?? 0;\n visualY = calculateVisualYForSeries(seriesIdx, yValue, seriesMapping, stackTotals);\n const yBounds = calculateBarYBounds(visualYBottom, visualY, chart);\n\n if (yBounds) {\n const cursorYPixel = chart.convertToPixel('grid', [0, cursorY]);\n if (cursorYPixel && cursorYPixel[1] !== undefined) {\n isHoveringYBounds = cursorYPixel[1] >= yBounds.top && cursorYPixel[1] <= yBounds.bottom;\n }\n }\n } else {\n visualY = yValue;\n }\n\n if (!isHoveringYBounds) continue;\n\n const segmentCenter = (segmentBounds.left + segmentBounds.right) / 2;\n distance = Math.abs(cursorXPixel - segmentCenter);\n isCandidate = true;\n }\n\n if (isCandidate) {\n candidates.push({\n seriesIdx,\n datumIdx,\n seriesId,\n seriesName: currentSeriesName,\n date: closestTimestamp,\n markerColor,\n x: xValue,\n y: yValue,\n visualY,\n distance,\n });\n }\n }\n\n return candidates;\n}\n\nfunction findClosestCandidate(candidates: Candidate[]): Candidate | null {\n if (candidates.length === 0) return null;\n let winner: Candidate | null = null;\n for (const candidate of candidates) {\n if (winner === null || candidate.distance < winner.distance) {\n winner = candidate;\n }\n }\n return winner;\n}\n\nfunction processCandidates(\n candidates: Candidate[],\n winner: Candidate | null,\n format: FormatOptions | undefined,\n seriesFormatMap: Map<string, FormatOptions> | undefined,\n chart: EChartsInstance,\n nonCandidateSeriesIndexes: number[]\n): NearbySeriesArray {\n const nearbySeriesIndexes: number[] = [];\n const emphasizedSeriesIndexes: number[] = [];\n const nonEmphasizedSeriesIndexes: number[] = [...nonCandidateSeriesIndexes];\n const emphasizedDatapoints: DatapointInfo[] = [];\n const duplicateDatapoints: DatapointInfo[] = [];\n const yValueCounts: Map<number, number> = new Map();\n\n const result: NearbySeriesArray = [];\n\n for (const candidate of candidates) {\n const seriesFormat = seriesFormatMap?.get(candidate.seriesId) ?? format;\n // Use raw y, not visualY — visualY is for proximity detection only.\n const displayY = candidate.y;\n const formattedY = formatValue(displayY, seriesFormat);\n const isClosestToCursor = winner !== null && candidate.seriesIdx === winner.seriesIdx;\n\n if (isClosestToCursor) {\n emphasizedSeriesIndexes.push(candidate.seriesIdx);\n\n const duplicateValuesCount = yValueCounts.get(displayY) ?? 0;\n yValueCounts.set(displayY, duplicateValuesCount + 1);\n if (duplicateValuesCount > 0) {\n duplicateDatapoints.push({\n seriesIndex: candidate.seriesIdx,\n dataIndex: candidate.datumIdx,\n seriesName: candidate.seriesName,\n yValue: displayY,\n });\n }\n\n emphasizedDatapoints.push({\n seriesIndex: candidate.seriesIdx,\n dataIndex: candidate.datumIdx,\n seriesName: candidate.seriesName,\n yValue: displayY,\n });\n } else {\n nonEmphasizedSeriesIndexes.push(candidate.seriesIdx);\n }\n\n result.push({\n seriesIdx: candidate.seriesIdx,\n datumIdx: candidate.datumIdx,\n seriesName: candidate.seriesName,\n date: candidate.date,\n x: candidate.x,\n y: displayY,\n formattedY,\n markerColor: candidate.markerColor,\n isClosestToCursor,\n });\n\n nearbySeriesIndexes.push(candidate.seriesIdx);\n }\n\n batchDispatchNearbySeriesActions(\n chart,\n nearbySeriesIndexes,\n emphasizedSeriesIndexes,\n nonEmphasizedSeriesIndexes,\n emphasizedDatapoints,\n duplicateDatapoints\n );\n\n return result;\n}\n\n/**\n * Returns formatted series data for the points that are close to the user's cursor.\n * Adjust xBuffer and yBuffer to increase or decrease number of series shown.\n */\nexport function checkforNearbyTimeSeries(\n data: TimeSeries[],\n seriesMapping: TimeChartSeriesMapping,\n pointInGrid: number[],\n yBuffer: number,\n chart: EChartsInstance,\n format?: FormatOptions,\n seriesFormatMap?: Map<string, FormatOptions>,\n // in the case of multi-axis, we need the cursor Y position in pixel space\n cursorPixelY?: number,\n cursorXPixel?: number | null\n): NearbySeriesArray {\n const cursorX: number | null = pointInGrid[0] ?? null;\n const cursorY: number | null = pointInGrid[1] ?? null;\n\n if (cursorX === null || cursorY === null) return EMPTY_TOOLTIP_DATA;\n if (chart.dispatchAction === undefined) return EMPTY_TOOLTIP_DATA;\n if (!Array.isArray(data)) return EMPTY_TOOLTIP_DATA;\n\n // All series share the same x-axis timestamps (enforced by getCommonTimeScale).\n const firstTimeSeriesValues = data[0]?.values;\n const closestTimestamp = getClosestTimestamp(firstTimeSeriesValues, cursorX);\n if (closestTimestamp === null) return EMPTY_TOOLTIP_DATA;\n\n let yBufferPixels: number | null = null;\n if (cursorPixelY !== undefined) {\n const cursorPoint = chart.convertToPixel('grid', [0, cursorY]);\n const bufferPoint = chart.convertToPixel('grid', [0, cursorY + yBuffer]);\n if (cursorPoint && bufferPoint && cursorPoint[1] !== undefined && bufferPoint[1] !== undefined) {\n yBufferPixels = Math.abs(bufferPoint[1] - cursorPoint[1]);\n }\n }\n\n const resolvedCursorXPixel = cursorXPixel ?? getPixelXFromGrid(closestTimestamp, chart);\n\n const candidates = gatherCandidates(\n data,\n seriesMapping,\n closestTimestamp,\n cursorX,\n cursorY,\n resolvedCursorXPixel,\n cursorPixelY,\n yBuffer,\n yBufferPixels,\n chart\n );\n\n const winner = findClosestCandidate(candidates);\n\n const candidateIndexes = new Set<number>();\n for (const candidate of candidates) candidateIndexes.add(candidate.seriesIdx);\n const nonCandidateSeriesIndexes: number[] = [];\n for (let idx = 0; idx < data.length; idx++) {\n if (!candidateIndexes.has(idx)) nonCandidateSeriesIndexes.push(idx);\n }\n\n return processCandidates(candidates, winner, format, seriesFormatMap, chart, nonCandidateSeriesIndexes);\n}\n\n/**\n * [DEPRECATED] Returns formatted series data for the points that are close to the user's cursor\n * Adjust yBuffer to increase or decrease number of series shown\n */\nexport function legacyCheckforNearbySeries(\n data: EChartsDataFormat,\n pointInGrid: number[],\n yBuffer: number,\n chart?: EChartsInstance,\n format?: FormatOptions\n): NearbySeriesArray {\n const currentNearbySeriesData: NearbySeriesArray = [];\n const cursorX: number | null = pointInGrid[0] ?? null;\n const cursorY: number | null = pointInGrid[1] ?? null;\n\n if (cursorX === null || cursorY === null) {\n return currentNearbySeriesData;\n }\n\n const nearbySeriesIndexes: number[] = [];\n const emphasizedSeriesIndexes: number[] = [];\n const nonEmphasizedSeriesIndexes: number[] = [];\n const totalSeries = data.timeSeries.length;\n if (Array.isArray(data.xAxis) && Array.isArray(data.timeSeries)) {\n for (let seriesIdx = 0; seriesIdx < totalSeries; seriesIdx++) {\n const currentSeries = data.timeSeries[seriesIdx];\n if (currentSeries === undefined) break;\n if (currentNearbySeriesData.length >= OPTIMIZED_MODE_SERIES_LIMIT) break;\n\n const currentSeriesName = currentSeries.name ? currentSeries.name.toString() : '';\n const markerColor = currentSeries.color ?? '#000';\n if (Array.isArray(currentSeries.data)) {\n for (let datumIdx = 0; datumIdx < currentSeries.data.length; datumIdx++) {\n const xValue = data.xAxis[datumIdx] ?? 0;\n const yValue = currentSeries.data[datumIdx];\n // ensure null values not displayed in tooltip\n if (yValue !== undefined && yValue !== null && cursorX === datumIdx) {\n if (yValue !== '-' && cursorY <= yValue + yBuffer && cursorY >= yValue - yBuffer) {\n // show fewer bold series in tooltip when many total series\n const minPercentRange = totalSeries > SHOW_FEWER_SERIES_LIMIT ? 2 : 5;\n const percentRangeToCheck = Math.max(minPercentRange, 100 / totalSeries);\n const isClosestToCursor = isWithinPercentageRange({\n valueToCheck: cursorY,\n baseValue: yValue,\n percentage: percentRangeToCheck,\n });\n if (isClosestToCursor) {\n emphasizedSeriesIndexes.push(seriesIdx);\n } else {\n nonEmphasizedSeriesIndexes.push(seriesIdx);\n // ensure series not close to cursor are not highlighted\n if (chart?.dispatchAction !== undefined) {\n chart.dispatchAction({\n type: 'downplay',\n seriesIndex: seriesIdx,\n });\n }\n }\n\n // determine whether to convert timestamp to ms, see: https://stackoverflow.com/a/23982005/17575201\n const xValueMilliSeconds = xValue > 99999999999 ? xValue : xValue * 1000;\n const formattedY = formatValue(yValue, format);\n currentNearbySeriesData.push({\n seriesIdx: seriesIdx,\n datumIdx: datumIdx,\n seriesName: currentSeriesName,\n date: xValueMilliSeconds,\n x: xValue,\n y: yValue,\n formattedY: formattedY,\n markerColor: markerColor.toString(),\n isClosestToCursor,\n });\n nearbySeriesIndexes.push(seriesIdx);\n }\n }\n }\n }\n }\n }\n if (chart?.dispatchAction !== undefined) {\n // Clears emphasis state of all lines that are not emphasized.\n // Emphasized is a subset of just the nearby series that are closest to cursor.\n chart.dispatchAction({\n type: 'downplay',\n seriesIndex: nonEmphasizedSeriesIndexes,\n });\n\n // https://echarts.apache.org/en/api.html#action.highlight\n if (emphasizedSeriesIndexes.length > 0) {\n // Fadeout opacity of all series not closest to cursor.\n chart.dispatchAction({\n type: 'highlight',\n seriesIndex: emphasizedSeriesIndexes,\n notBlur: false, // ensure blur IS triggered, this is default but setting so it is explicit\n escapeConnect: true, // shared crosshair should not emphasize series on adjacent charts\n });\n } else {\n // When no emphasized series with bold text, notBlur allows opacity fadeout to not trigger.\n chart.dispatchAction({\n type: 'highlight',\n seriesIndex: nearbySeriesIndexes,\n notBlur: true, // do not trigger blur state when cursor is not immediately close to any series\n escapeConnect: true, // shared crosshair should not emphasize series on adjacent charts\n });\n }\n }\n\n return currentNearbySeriesData;\n}\n\n/**\n * Uses mouse position to determine whether user is hovering over a chart canvas\n * If yes, convert from pixel values to logical cartesian coordinates and return all nearby series\n */\nexport function getNearbySeriesData({\n mousePos,\n pinnedPos,\n data,\n seriesMapping,\n chart,\n format,\n seriesFormatMap,\n showAllSeries = false,\n}: {\n mousePos: CursorData['coords'];\n pinnedPos: CursorCoordinates | null;\n data: TimeSeries[];\n seriesMapping: TimeChartSeriesMapping;\n chart?: EChartsInstance;\n format?: FormatOptions;\n seriesFormatMap?: Map<string, FormatOptions>;\n showAllSeries?: boolean;\n}): NearbySeriesArray {\n if (chart === undefined || mousePos === null) return EMPTY_TOOLTIP_DATA;\n\n // prevents multiple tooltips showing from adjacent charts unless tooltip is pinned\n let cursorTargetMatchesChart = false;\n if (mousePos.target !== null) {\n const currentParent = (<HTMLElement>mousePos.target).parentElement;\n if (currentParent !== null) {\n const currentGrandparent = currentParent.parentElement;\n if (currentGrandparent !== null) {\n const chartDom = chart.getDom();\n if (chartDom === currentGrandparent) {\n cursorTargetMatchesChart = true;\n }\n }\n }\n }\n\n // allows moving cursor inside tooltip without it fading away\n if (pinnedPos !== null) {\n mousePos = pinnedPos;\n cursorTargetMatchesChart = true;\n }\n\n if (cursorTargetMatchesChart === false || data === null || chart['_model'] === undefined) return EMPTY_TOOLTIP_DATA;\n\n if (mousePos.plotCanvas.x === undefined || mousePos.plotCanvas.y === undefined) return EMPTY_TOOLTIP_DATA;\n\n const cursorPixelY = mousePos.plotCanvas.y;\n const cursorXPixel = mousePos.plotCanvas.x;\n const pointInGrid = getPointInGrid(cursorXPixel, cursorPixelY, chart);\n if (pointInGrid !== null) {\n const chartModel = chart['_model'];\n const yAxisScale = chartModel.getComponent('yAxis').axis.scale;\n const isLogScale = yAxisScale.type === 'log';\n let yInterval = yAxisScale._interval;\n // For log scales, convert from log-space extent to actual data range and use 1% as the interval.\n if (isLogScale && yAxisScale.base) {\n const logBase = yAxisScale.base;\n const extent = yAxisScale._extent;\n // e.g. extent [0, 2] → 10^0..10^2\n const actualMin = logBase ** extent[0];\n const actualMax = logBase ** extent[1];\n yInterval = (actualMax - actualMin) / 100;\n }\n const totalSeries = data.length;\n const yBuffer = getYBuffer({ yInterval, totalSeries, showAllSeries });\n\n const hasMultipleYAxes = seriesMapping.some((series) => series.yAxisIndex !== undefined && series.yAxisIndex > 0);\n\n return checkforNearbyTimeSeries(\n data,\n seriesMapping,\n pointInGrid,\n yBuffer,\n chart,\n format,\n seriesFormatMap,\n hasMultipleYAxes ? cursorPixelY : undefined,\n cursorXPixel\n );\n }\n\n // no nearby series found\n return EMPTY_TOOLTIP_DATA;\n}\n\n/*\n * Check if two numbers are within a specified percentage range\n */\nexport function isWithinPercentageRange({\n valueToCheck,\n baseValue,\n percentage,\n}: IsWithinPercentageRangeParams): boolean {\n const range = (percentage / 100) * baseValue;\n const lowerBound = baseValue - range;\n const upperBound = baseValue + range;\n return valueToCheck >= lowerBound && valueToCheck <= upperBound;\n}\n\n/*\n * Get range to check within for nearby series to show in tooltip.\n */\nexport function getYBuffer({ yInterval, totalSeries, showAllSeries = false }: GetYBufferParams): number {\n if (showAllSeries) {\n return yInterval * 10; // roughly correlates with grid so entire canvas is searched\n }\n // never let nearby series range be less than roughly the size of a single tick\n const yBufferMin = yInterval * 0.3;\n\n // tooltip trigger area gets smaller with more series\n if (totalSeries > SHOW_FEWER_SERIES_LIMIT) {\n const adjustedBuffer = (yInterval * DYNAMIC_NEARBY_SERIES_MULTIPLIER) / totalSeries;\n return Math.max(yBufferMin, adjustedBuffer);\n }\n // increase multiplier to expand nearby series range\n return Math.max(yBufferMin, yInterval * INCREASE_NEARBY_SERIES_MULTIPLIER);\n}\n"],"names":["OPTIMIZED_MODE_SERIES_LIMIT","formatValue","batchDispatchNearbySeriesActions","getPointInGrid","getClosestTimestamp","EMPTY_TOOLTIP_DATA","calculateBarBandwidth","calculateBarSegmentBounds","calculateBarYBounds","calculateVisualYForSeries","getPixelXFromGrid","INCREASE_NEARBY_SERIES_MULTIPLIER","DYNAMIC_NEARBY_SERIES_MULTIPLIER","SHOW_FEWER_SERIES_LIMIT","gatherCandidates","data","seriesMapping","closestTimestamp","cursorX","cursorY","cursorXPixel","cursorPixelY","yBuffer","yBufferPixels","chart","candidates","totalSeries","length","stackTotals","Map","sortedTimestamps","firstValues","values","seen","Set","ts","has","add","push","sort","a","b","barSeriesIndexes","i","type","barBandwidth","barCenterPixelX","seriesIdx","currentSeries","currentDataset","currentDatasetValues","Array","isArray","seriesType","currentSeriesName","name","toString","seriesId","id","markerColor","color","datumIdx","xValue","yValue","tuple","undefined","isCandidate","visualY","distance","Infinity","dataPointPixel","convertToPixel","seriesIndex","pixelDistance","Math","abs","verticalDistance","barRelativeIdx","indexOf","segmentBounds","isWithinXBounds","left","right","stackId","stack","isHoveringYBounds","stackIdStr","visualYBottom","get","yBounds","cursorYPixel","top","bottom","segmentCenter","seriesName","date","x","y","findClosestCandidate","winner","candidate","processCandidates","format","seriesFormatMap","nonCandidateSeriesIndexes","nearbySeriesIndexes","emphasizedSeriesIndexes","nonEmphasizedSeriesIndexes","emphasizedDatapoints","duplicateDatapoints","yValueCounts","result","seriesFormat","displayY","formattedY","isClosestToCursor","duplicateValuesCount","set","dataIndex","checkforNearbyTimeSeries","pointInGrid","dispatchAction","firstTimeSeriesValues","cursorPoint","bufferPoint","resolvedCursorXPixel","candidateIndexes","idx","legacyCheckforNearbySeries","currentNearbySeriesData","timeSeries","xAxis","minPercentRange","percentRangeToCheck","max","isWithinPercentageRange","valueToCheck","baseValue","percentage","xValueMilliSeconds","notBlur","escapeConnect","getNearbySeriesData","mousePos","pinnedPos","showAllSeries","cursorTargetMatchesChart","target","currentParent","parentElement","currentGrandparent","chartDom","getDom","plotCanvas","chartModel","yAxisScale","getComponent","axis","scale","isLogScale","yInterval","_interval","base","logBase","extent","_extent","actualMin","actualMax","getYBuffer","hasMultipleYAxes","some","series","yAxisIndex","range","lowerBound","upperBound","yBufferMin","adjustedBuffer"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip-model.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"tooltip-model.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,wBAAwB,QAA0B,CAAC;AAChE,eAAO,MAAM,+BAA+B,OAAO,CAAC;AACpD,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAC5E,eAAO,MAAM,6BAA6B,iDAAiD,CAAC;AAE5F,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,eAAO,MAAM,mBAAmB,qBAQ9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAa7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,iBAAsB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAAC;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAE7D,eAAO,MAAM,gBAAgB,QAAO,UAAU,CAAC,QAAQ,CAkCtD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D,eAAO,MAAM,uBAAuB,yBAAyB,CAAC"}
|