feat: photography features & image optimizations
- Hero carousel: gallery.yaml hero accepts single UUID or array, crossfade component - Full-bleed single albums: subpages with 1 album skip grid, render photos directly - EXIF on hover: camera/lens/focal length overlay on grid items (toggle via exifOnHover) - Customizable grid: columns/gap/aspectRatio/layout (masonry|uniform) via gallery.yaml - Per-subpage grid overrides: each subpage can override global grid config - True masonry: per-image aspect ratios from EXIF dimensions - next/image migration: homepage hero, album covers, grid thumbnails, about portrait - ThumbHash blur placeholders and dominant color backgrounds - Custom next/image loader via image proxy with width/quality params - Lightbox fade-in transition with dominant color background - Password-protected subpages, health check, rate limiting, OG images
This commit is contained in:
@@ -44,6 +44,7 @@ export function Lightbox({
|
||||
const [showExif, setShowExif] = useState(false);
|
||||
const [exifData, setExifData] = useState<ExifData | null>(null);
|
||||
const [exifLoading, setExifLoading] = useState(false);
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
const touchStartX = useRef<number>(0);
|
||||
const touchStartY = useRef<number>(0);
|
||||
@@ -64,6 +65,7 @@ export function Lightbox({
|
||||
// Reset EXIF data when switching images; refetch if panel is open
|
||||
useEffect(() => {
|
||||
setExifData(null);
|
||||
setImageLoaded(false);
|
||||
if (showExif && current) {
|
||||
fetchExif(current.exifUrl);
|
||||
}
|
||||
@@ -149,12 +151,22 @@ export function Lightbox({
|
||||
</button>
|
||||
|
||||
{/* Image */}
|
||||
<div className="lightbox__image-container">
|
||||
<div
|
||||
className="lightbox__image-container"
|
||||
style={{
|
||||
backgroundColor: current.dominantColor || '#000',
|
||||
backgroundImage: current.blurDataURL ? `url(${current.blurDataURL})` : undefined,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
className="lightbox__image"
|
||||
className={`lightbox__image${imageLoaded ? ' lightbox__image--loaded' : ''}`}
|
||||
src={current.previewUrl}
|
||||
alt=""
|
||||
draggable={false}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user