import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function formatDate(date: Date | string): string { const d = new Date(date) const now = new Date() const diff = now.getTime() - d.getTime() // Less than 1 minute if (diff < 60000) { return 'Just now' } // Less than 1 hour if (diff < 3600000) { const minutes = Math.floor(diff / 60000) return `${minutes}m ago` } // Less than 24 hours if (diff < 86400000) { const hours = Math.floor(diff / 3600000) return `${hours}h ago` } // Less than 7 days if (diff < 604800000) { const days = Math.floor(diff / 86400000) return `${days}d ago` } // More than 7 days return d.toLocaleDateString() } export function formatTime(date: Date | string): string { const d = new Date(date) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) } export function formatFileSize(bytes: number): string { if (bytes === 0) return '0 Bytes' const k = 1024 const sizes = ['Bytes', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] } export function getFileIcon(mimeType: string): string { if (mimeType.startsWith('image/')) return '🖼️' if (mimeType.startsWith('video/')) return '🎥' if (mimeType.startsWith('audio/')) return '🎵' if (mimeType.includes('pdf')) return '📄' if (mimeType.includes('word')) return '📝' if (mimeType.includes('excel') || mimeType.includes('spreadsheet')) return '📊' if (mimeType.includes('powerpoint') || mimeType.includes('presentation')) return '📽️' if (mimeType.includes('zip') || mimeType.includes('rar') || mimeType.includes('archive')) return '📦' return '📎' } export function generateAvatar(name: string): string { const colors = [ '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9' ] const initials = name .split(' ') .map(word => word[0]) .join('') .toUpperCase() .slice(0, 2) const colorIndex = name.charCodeAt(0) % colors.length const color = colors[colorIndex] return `data:image/svg+xml,${encodeURIComponent(` ${initials} `)}` } export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout | null = null return (...args: Parameters) => { if (timeout) { clearTimeout(timeout) } timeout = setTimeout(() => { func(...args) }, wait) } } export function throttle any>( func: T, limit: number ): (...args: Parameters) => void { let inThrottle: boolean return (...args: Parameters) => { if (!inThrottle) { func(...args) inThrottle = true setTimeout(() => inThrottle = false, limit) } } } export function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ return emailRegex.test(email) } export function isValidUsername(username: string): boolean { const usernameRegex = /^[a-zA-Z0-9_]{3,20}$/ return usernameRegex.test(username) } export function truncateText(text: string, maxLength: number): string { if (text.length <= maxLength) return text return text.slice(0, maxLength) + '...' } export function copyToClipboard(text: string): Promise { if (navigator.clipboard) { return navigator.clipboard.writeText(text) } else { // Fallback for older browsers const textArea = document.createElement('textarea') textArea.value = text document.body.appendChild(textArea) textArea.focus() textArea.select() try { document.execCommand('copy') return Promise.resolve() } catch (err) { return Promise.reject(err) } finally { document.body.removeChild(textArea) } } } export function downloadFile(url: string, filename: string): void { const link = document.createElement('a') link.href = url link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) } export function isImageFile(file: File): boolean { return file.type.startsWith('image/') } export function isVideoFile(file: File): boolean { return file.type.startsWith('video/') } export function isAudioFile(file: File): boolean { return file.type.startsWith('audio/') } export function getInitials(name: string): string { return name .split(' ') .map(word => word[0]) .join('') .toUpperCase() .slice(0, 2) }