// Time-of-day heatmap strip rendered above the time axis. Aggregates the // currently displayed (filter-passing) meows across all loaded rows into // fixed-width bins; cell brightness encodes count. const { useMemo: useMemoH } = React; const HEATMAP_BINS = 96; // 15-minute resolution function Heatmap({ rows, scoreThreshold, enabledLabels, zoom, pan }) { const bins = useMemoH(() => { const counts = new Array(HEATMAP_BINS).fill(0); for (const row of rows) { for (const m of row.meows) { if (m.score < scoreThreshold) continue; if (!enabledLabels.has(m.label)) continue; let idx = Math.floor(m.start * HEATMAP_BINS); if (idx < 0) idx = 0; if (idx >= HEATMAP_BINS) idx = HEATMAP_BINS - 1; counts[idx] += 1; } } let max = 0; for (const c of counts) if (c > max) max = c; return { counts, max }; }, [rows, scoreThreshold, enabledLabels]); const widthPct = 100 / HEATMAP_BINS; return (
{bins.counts.map((c, i) => { const intensity = bins.max > 0 ? c / bins.max : 0; return (
); })}
); } window.Heatmap = Heatmap;