File size: 1,530 Bytes
80bcac8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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<T extends (...args: unknown[]) => unknown>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timeoutId: ReturnType<typeof setTimeout>
return (...args: Parameters<T>) => {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn(...args), delay)
}
}
export function throttle<T extends (...args: unknown[]) => unknown>(
fn: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle = false
return (...args: Parameters<T>) => {
if (!inThrottle) {
fn(...args)
inThrottle = true
setTimeout(() => (inThrottle = false), limit)
}
}
} |