"use client"; import { useId, useMemo } from "react"; import { cn } from "@/lib/utils"; interface PriceSparklinePoint { timestamp: string; priceUsd: number; } interface PriceSparklineProps { points: PriceSparklinePoint[]; isLoading?: boolean; className?: string; } export function PriceSparkline({ points, isLoading = false, className, }: PriceSparklineProps) { const gradientId = useId(); const chart = useMemo(() => { const sorted = [...points] .filter((point) => Number.isFinite(point.priceUsd) && point.priceUsd > 0) .sort( (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(), ); if (sorted.length < 2) { return null; } const width = 320; const height = 84; const padding = 6; const prices = sorted.map((point) => point.priceUsd); const minPrice = Math.min(...prices); const maxPrice = Math.max(...prices); const range = Math.max(maxPrice - minPrice, maxPrice * 0.001, 0.00000001); const coordinates = sorted.map((point, index) => { const x = padding + (index / (sorted.length - 1)) * (width - padding * 2); const y = padding + (1 - (point.priceUsd - minPrice) / range) * (height - padding * 2); return { x, y }; }); const linePath = coordinates .map((point, index) => `${index === 0 ? "M" : "L"} ${point.x.toFixed(2)} ${point.y.toFixed(2)}`, ) .join(" "); const firstPoint = coordinates[0]; const lastPoint = coordinates[coordinates.length - 1]; const areaPath = `${linePath} L ${lastPoint.x.toFixed(2)} ${(height - padding).toFixed(2)} L ${firstPoint.x.toFixed(2)} ${(height - padding).toFixed(2)} Z`; const isUptrend = prices[prices.length - 1] >= prices[0]; return { width, height, linePath, areaPath, isUptrend, }; }, [points]); return (

Price (24h)

{chart ? (
) : (
{isLoading ? "Loading 24h price history..." : "24h price history unavailable"}
)}
); }