| import { type ClassValue, clsx } from "clsx"; | |
| import { twMerge } from "tailwind-merge"; | |
| export function cn(...inputs: ClassValue[]) { | |
| return twMerge(clsx(inputs)); | |
| } | |
| export function formatDuration(ms: number): string { | |
| if (ms < 1000) return `${ms}ms`; | |
| if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`; | |
| if (ms < 3600000) return `${(ms / 60000).toFixed(1)}m`; | |
| return `${(ms / 3600000).toFixed(1)}h`; | |
| } | |
| export function truncate(str: string, length: number): string { | |
| if (str.length <= length) return str; | |
| return `${str.slice(0, length)}...`; | |
| } | |
| export function formatRelativeTime(timestamp: number): string { | |
| const now = Date.now(); | |
| const diff = now - timestamp; | |
| if (diff < 60000) return `${Math.floor(diff / 1000)}s ago`; | |
| if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`; | |
| if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`; | |
| return `${Math.floor(diff / 86400000)}d ago`; | |
| } | |
| export function formatAbsoluteTime(timestamp: number): string { | |
| const date = new Date(timestamp); | |
| return date.toLocaleString(undefined, { | |
| month: "short", | |
| day: "numeric", | |
| hour: "2-digit", | |
| minute: "2-digit", | |
| second: "2-digit", | |
| }); | |
| } | |