1 Commits

Author SHA1 Message Date
Sebastian Seedorf
c754316935 fix: replace addEventListener with onmouseleave to prevent listener leak 2026-06-05 12:54:37 +02:00
3 changed files with 6 additions and 5 deletions

View File

@@ -50,7 +50,7 @@ export default function SignalsChart({
const { containerRef, legendRef } = usePlot( const { containerRef, legendRef } = usePlot(
(el, w, h, lRef) => { (el, w, h, lRef) => {
const data = buildSeriesData(rows, config.signal_type, timeMode, config.series_limit); const data = buildSeriesData(rows, config.signal_type, timeMode);
if (!data) return null; if (!data) return null;
const { keys, allXs, data: seriesData } = data; const { keys, allXs, data: seriesData } = data;

View File

@@ -1,5 +1,7 @@
import type { SignalRow, ChartConfig, TimeMode } from '@/lib/types'; import type { SignalRow, ChartConfig, TimeMode } from '@/lib/types';
const MAX_SERIES = 80;
export interface SeriesData { export interface SeriesData {
keys: string[]; keys: string[];
allXs: number[]; allXs: number[];
@@ -10,7 +12,6 @@ export function buildSeriesData(
rows: SignalRow[], rows: SignalRow[],
signalType: ChartConfig['signal_type'], signalType: ChartConfig['signal_type'],
timeMode: TimeMode, timeMode: TimeMode,
seriesLimit: number = 80,
): SeriesData | null { ): SeriesData | null {
const seriesMap = new Map<string, Map<number, number>>(); const seriesMap = new Map<string, Map<number, number>>();
@@ -33,7 +34,7 @@ export function buildSeriesData(
if (seriesMap.size === 0) return null; if (seriesMap.size === 0) return null;
const keys = [...seriesMap.keys()].slice(0, seriesLimit); const keys = [...seriesMap.keys()].slice(0, MAX_SERIES);
const allXs = [ const allXs = [
...new Set( ...new Set(
keys.flatMap((k) => { keys.flatMap((k) => {

View File

@@ -57,11 +57,11 @@ export function usePlot(
// Defer mouseleave — prevents React hydration events firing before lastIdxRef set // Defer mouseleave — prevents React hydration events firing before lastIdxRef set
requestAnimationFrame(() => { requestAnimationFrame(() => {
plot.over.addEventListener('mouseleave', () => { plot.over.onmouseleave = () => {
const p = plotRef.current; const p = plotRef.current;
if (!p) return; if (!p) return;
p.setCursor({ left: idxToPixel(p, lastIdxRef.current), top: -10 }); p.setCursor({ left: idxToPixel(p, lastIdxRef.current), top: -10 });
}); };
}); });
} }
// deps is intentionally dynamic — passed by parent to allow external rebuild triggers // deps is intentionally dynamic — passed by parent to allow external rebuild triggers