Files
Juergen Kunz a61f57db13 feat: Add PDF viewer and preview components with styling and functionality
- Implemented DeesPdfViewer for full-featured PDF viewing with toolbar and sidebar navigation.
- Created DeesPdfPreview for lightweight PDF previews.
- Introduced PdfManager for managing PDF document loading and caching.
- Added CanvasPool for efficient canvas management.
- Developed utility functions for performance monitoring and file size formatting.
- Established styles for viewer and preview components to enhance UI/UX.
- Included demo examples for showcasing PDF viewer capabilities.
2025-09-20 11:42:22 +00:00

98 lines
2.6 KiB
TypeScript

export function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: number | undefined;
return function executedFunction(...args: Parameters<T>) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = window.setTimeout(later, wait);
};
}
export function throttle<T extends (...args: any[]) => any>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return function executedFunction(...args: Parameters<T>) {
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<string, number>();
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<string, number>,
};
// Calculate averages for repeated measures
const grouped = new Map<string, number[]>();
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 = [];
}
}