feat(web): add saved searches, image lightbox, and web vitals tracking
New features: - Saved searches dashboard page with CRUD hooks and API client - Image lightbox component for property gallery full-screen viewing - Web vitals provider and reporting utilities for performance monitoring - Image blur placeholder generation utility Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
53
apps/web/lib/image-blur.ts
Normal file
53
apps/web/lib/image-blur.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Tiny SVG-based blur placeholder for next/image.
|
||||
*
|
||||
* Generates a small, inline base64-encoded SVG that next/image displays while
|
||||
* the real image loads. This eliminates layout shift (CLS) and provides a smooth
|
||||
* visual transition without needing to pre-compute per-image blur hashes.
|
||||
*
|
||||
* Usage:
|
||||
* <Image placeholder="blur" blurDataURL={shimmerBlurDataURL()} ... />
|
||||
*/
|
||||
|
||||
const SHIMMER_SVG = `
|
||||
<svg width="400" height="300" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#e5e7eb"/>
|
||||
<stop offset="50%" stop-color="#f3f4f6"/>
|
||||
<stop offset="100%" stop-color="#e5e7eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="400" height="300" fill="#e5e7eb"/>
|
||||
<rect width="400" height="300" fill="url(#g)">
|
||||
<animate attributeName="x" from="-400" to="400" dur="1.5s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
</svg>`.trim();
|
||||
|
||||
const STATIC_BLUR_SVG = `
|
||||
<svg width="8" height="6" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="8" height="6" fill="#d1d5db"/>
|
||||
</svg>`.trim();
|
||||
|
||||
function toBase64(str: string): string {
|
||||
if (typeof window === 'undefined') {
|
||||
return Buffer.from(str).toString('base64');
|
||||
}
|
||||
return btoa(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animated shimmer blur placeholder (for listing thumbnails).
|
||||
* Shows a shimmer animation while the image loads.
|
||||
*/
|
||||
export function shimmerBlurDataURL(): string {
|
||||
return `data:image/svg+xml;base64,${toBase64(SHIMMER_SVG)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static grey blur placeholder (for small thumbnails like table rows).
|
||||
* Lightweight, no animation.
|
||||
*/
|
||||
export function staticBlurDataURL(): string {
|
||||
return `data:image/svg+xml;base64,${toBase64(STATIC_BLUR_SVG)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user