import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function formatNumber(num: number, decimals = 2): string { if (num === 0) return "0" if (Math.abs(num) < 0.01) return num.toExponential(2) return num.toFixed(decimals) } export function formatTime(ms: number): string { if (ms < 1000) return `${ms.toFixed(0)}ms` if (ms < 60000) return `${(ms / 1000).toFixed(1)}s` return `${Math.floor(ms / 60000)}m ${((ms % 60000) / 1000).toFixed(0)}s` } export function clamp(value: number, min: number, max: number): number { return Math.min(Math.max(value, min), max) } export function lerp(a: number, b: number, t: number): number { return a + (b - a) * t } export function generateId(): string { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}` } export function debounce unknown>( fn: T, delay: number ): (...args: Parameters) => void { let timeoutId: ReturnType return (...args: Parameters) => { clearTimeout(timeoutId) timeoutId = setTimeout(() => fn(...args), delay) } } export function throttle unknown>( fn: T, limit: number ): (...args: Parameters) => void { let inThrottle = false return (...args: Parameters) => { if (!inThrottle) { fn(...args) inThrottle = true setTimeout(() => (inThrottle = false), limit) } } }