Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 56 57 58 59 60 | import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]): string { return twMerge(clsx(inputs)); } export const capitalize = (s?: string | null): string => { if (!s) return ''; if (s.length === 0) return s; if (s.length === 1) return s.toUpperCase(); return s.charAt(0).toUpperCase() + s.slice(1); }; export function formatBytes( bytes: number, opts: { decimals?: number; sizeType?: 'accurate' | 'normal'; } = {} ): string { const { decimals = 0, sizeType = 'normal' } = opts; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; const accurateSizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB']; if (bytes === 0) return '0 Byte'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return `${(bytes / Math.pow(1024, i)).toFixed(decimals)} ${ sizeType === 'accurate' ? (accurateSizes[i] ?? 'Bytest') : (sizes[i] ?? 'Bytes') }`; } export function formatDuration(seconds: number): string { if (seconds < 60) { return `${seconds} seconds`; } const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; const parts = []; if (hours > 0) { parts.push(`${hours} ${hours === 1 ? 'hour' : 'hours'}`); } if (minutes > 0) { parts.push(`${minutes} ${minutes === 1 ? 'minute' : 'minutes'}`); } if (remainingSeconds > 0 && hours === 0) { // Only show seconds if less than 1 hour parts.push( `${remainingSeconds} ${remainingSeconds === 1 ? 'second' : 'seconds'}` ); } return parts.join(' '); } |