import React, { useMemo } from 'react'; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'; import { LatencyHistogramData } from '../../hooks/useAudioEvents'; interface LatencyHistogramProps { data?: LatencyHistogramData; title: string; height?: number; className?: string; } interface ChartDataPoint { bucket: string; count: number; bucketValue: number; } const LatencyHistogram: React.FC = ({ data, title, height = 200, className = '' }) => { // Memoize chart data transformation to avoid recalculation on every render const chartData = useMemo((): ChartDataPoint[] => { if (!data || !data.buckets || !data.counts || data.buckets.length === 0) { return []; } const transformedData: ChartDataPoint[] = []; // Process each bucket with its count for (let i = 0; i < data.buckets.length; i++) { const bucketValue = data.buckets[i]; const count = data.counts[i] || 0; // Skip empty buckets to reduce chart clutter if (count === 0) continue; // Format bucket label based on value let bucketLabel: string; if (bucketValue < 1) { bucketLabel = `${(bucketValue * 1000).toFixed(0)}μs`; } else if (bucketValue < 1000) { bucketLabel = `${bucketValue.toFixed(1)}ms`; } else { bucketLabel = `${(bucketValue / 1000).toFixed(1)}s`; } transformedData.push({ bucket: bucketLabel, count, bucketValue }); } // Handle overflow bucket (last count if it exists) if (data.counts.length > data.buckets.length) { const overflowCount = data.counts[data.counts.length - 1]; if (overflowCount > 0) { transformedData.push({ bucket: '>2s', count: overflowCount, bucketValue: 2000 // 2 seconds in ms }); } } return transformedData; }, [data]); // Custom tooltip for better UX const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?: { payload: ChartDataPoint }[]; label?: string; }) => { if (active && payload && payload.length) { const data = payload[0].payload; return (

{`Latency: ${label}`}

{`Count: ${data.count}`}

); } return null; }; if (!data || chartData.length === 0) { return (

{title}

No latency data available
); } return (

{title}

} />
); }; export default LatencyHistogram;