import { useEffect, useRef, useState } from 'react' import { imgUrl } from '../api' // True justified layout: pack photos greedily into rows at their real aspect // ratios, then scale each row's height so it fills the container width // exactly. No cropping, no stretch, and the last row simply renders at the // target height instead of being padded by a spacer. function layoutRows(photos, containerWidth, targetHeight, gap) { const rows = [] let row = [] let arSum = 0 let index = 0 for (const photo of photos) { const ar = photo.width && photo.height ? photo.width / photo.height : 1.5 row.push({ photo, ar, index: index++ }) arSum += ar const gaps = (row.length - 1) * gap if (arSum * targetHeight + gaps >= containerWidth) { rows.push({ items: row, height: (containerWidth - gaps) / arSum }) row = [] arSum = 0 } } if (row.length > 0) { const gaps = (row.length - 1) * gap rows.push({ items: row, height: Math.min(targetHeight, (containerWidth - gaps) / arSum), }) } return rows } export default function Gallery({ photos, onOpen, overlay, selected, onToggleSelect }) { const containerRef = useRef(null) const [width, setWidth] = useState(0) useEffect(() => { const el = containerRef.current if (!el) return const observer = new ResizeObserver((entries) => setWidth(entries[0].contentRect.width)) observer.observe(el) return () => observer.disconnect() }, []) if (photos.length === 0) return null const gap = 6 const targetHeight = width < 700 ? 170 : 240 const rows = width > 0 ? layoutRows(photos, width, targetHeight, gap) : [] const selecting = selected && selected.size > 0 return (