export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: number | undefined; return function executedFunction(...args: Parameters) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = window.setTimeout(later, wait); }; } export function throttle any>( func: T, limit: number ): (...args: Parameters) => void { let inThrottle: boolean; return function executedFunction(...args: Parameters) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } 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 Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; } export function isInViewport(element: Element, margin = 0): boolean { const rect = element.getBoundingClientRect(); return ( rect.top >= -margin && rect.left >= -margin && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) + margin && rect.right <= (window.innerWidth || document.documentElement.clientWidth) + margin ); } export class PerformanceMonitor { private static marks = new Map(); private static measures: Array<{ name: string; duration: number }> = []; public static mark(name: string) { this.marks.set(name, performance.now()); } public static measure(name: string, startMark: string) { const start = this.marks.get(startMark); if (start) { const duration = performance.now() - start; this.measures.push({ name, duration }); this.marks.delete(startMark); return duration; } return 0; } public static getReport() { const report = { measures: [...this.measures], averages: {} as Record, }; // Calculate averages for repeated measures const grouped = new Map(); for (const measure of this.measures) { if (!grouped.has(measure.name)) { grouped.set(measure.name, []); } grouped.get(measure.name)!.push(measure.duration); } for (const [name, durations] of grouped) { report.averages[name] = durations.reduce((a, b) => a + b, 0) / durations.length; } return report; } public static clear() { this.marks.clear(); this.measures = []; } }