Files

58 lines
1.6 KiB
JavaScript

// Generic grid + lightbox behavior shared across photoflow apps.
// Apps spread this into their own Alpine component: { ...photoGrid(), ...appLogic }
function photoGrid() {
return {
focused: null,
lightboxOpen: false,
cards() {
return [...document.querySelectorAll('.photo-card')]
.filter(c => c.style.display !== 'none');
},
select(el) {
if (this.focused) this.focused.classList.remove('ring-4', 'ring-white', 'z-10');
this.focused = el;
if (el) {
el.classList.add('ring-4', 'ring-white', 'z-10');
el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
if (this.lightboxOpen) this.updateLightbox();
}
},
selectFirst() {
const cards = this.cards();
if (cards.length) this.select(cards[0]);
},
navigate(dir) {
const cards = this.cards();
if (!cards.length) return;
const idx = this.focused ? cards.indexOf(this.focused) : -1;
const next = cards[Math.max(0, Math.min(cards.length - 1, idx + dir))];
if (next) this.select(next);
},
openLightbox(el) {
this.select(el);
this.lightboxOpen = true;
document.getElementById('lb').style.display = '';
this.updateLightbox();
},
closeLightbox() {
this.lightboxOpen = false;
const lb = document.getElementById('lb');
if (lb) lb.style.display = 'none';
},
updateLightbox() {
const el = this.focused;
if (!el) return;
const img = el.querySelector('img');
const lbImg = document.getElementById('lb-img');
if (img && lbImg) lbImg.src = img.src;
},
};
}