import { useEffect, useRef } from 'react'; import * as echarts from 'echarts/core'; import { GaugeChart } from 'echarts/charts'; import { CanvasRenderer } from 'echarts/renderers'; import type { EChartsType } from 'echarts/core'; import { buildEChartsTheme } from './buildEChartsTheme'; echarts.use([GaugeChart, CanvasRenderer]); interface VramGaugeProps { used: number; // MB total: number; // MB size?: number; } export function VramGauge({ used, total, size = 120 }: VramGaugeProps) { const containerRef = useRef(null); const chartRef = useRef(null); useEffect(() => { if (!containerRef.current) return; if (!chartRef.current) { const theme = buildEChartsTheme(); chartRef.current = echarts.init(containerRef.current, theme); } const chart = chartRef.current; const root = getComputedStyle(document.documentElement); const get = (prop: string) => root.getPropertyValue(prop).trim(); const pct = total > 0 ? Math.round((used / total) * 100) : 0; // Derive gauge progress color from CSS custom properties // Green -> Amber -> Red as utilization increases let color = get('--glow-green'); if (pct > 80) color = get('--glow-red'); else if (pct > 60) color = get('--glow-amber'); chart.setOption({ backgroundColor: 'transparent', series: [ { type: 'gauge', startAngle: 220, endAngle: -40, min: 0, max: total, radius: '90%', center: ['50%', '55%'], pointer: { show: false }, progress: { show: true, overlap: false, roundCap: true, clip: false, itemStyle: { color }, width: 8, }, axisLine: { lineStyle: { width: 8, color: [[1, get('--border')]], }, }, axisTick: { show: false }, splitLine: { show: false }, axisLabel: { show: false }, title: { show: true, offsetCenter: ['0%', '-10%'], fontSize: 11, color: get('--muted-foreground'), fontFamily: 'Inter', }, detail: { show: true, offsetCenter: ['0%', '10%'], fontSize: 18, fontWeight: 'bold', color: get('--foreground'), fontFamily: 'Orbitron', formatter: () => `${used} / ${total} MB`, }, data: [{ value: used, name: 'VRAM' }], }, ], }); const observer = new ResizeObserver(() => chart.resize()); observer.observe(containerRef.current); return () => { observer.disconnect(); chart.dispose(); chartRef.current = null; }; }, [used, total]); return (
); }