/* global React, PAOLA_DATA */
// Shared components: Nav, Footer, Hero, Reveal, Marquee, helpers
const { useState, useEffect, useRef, useMemo, useCallback } = React;
/* --- Reveal on scroll --- */
function Reveal({ children, delay = 0, className = '', as = 'div' }) {
const ref = useRef(null);
const [shown, setShown] = useState(false);
useEffect(() => {
const el = ref.current; if (!el) return;
const io = new IntersectionObserver(([e]) => {
if (e.isIntersecting) { setShown(true); io.disconnect(); }
}, { threshold: 0.12 });
io.observe(el);
return () => io.disconnect();
}, []);
const Tag = as;
return {children};
}
/* --- Nav --- */
function Nav({ route, go, dark, onOpenMenu }) {
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 60);
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
return () => window.removeEventListener('scroll', onScroll);
}, []);
const navClass = `nav ${scrolled ? 'scrolled' : ''} ${(!scrolled && !dark) ? 'light' : ''}`;
const link = (id, label) => (
{e.preventDefault(); go(id);}} className={route===id?'active':''}>{label}
);
return (
);
}
/* --- Fullscreen menu (mobile + accessory) --- */
function FullMenu({ open, onClose, go }) {
return (
SABANETA · ANTIOQUIA
@{PAOLA_DATA.contact.instagram}
{PAOLA_DATA.contact.whatsappPretty}
);
}
/* --- Marquee --- */
function Marquee({ items }) {
const all = [...items, ...items];
return (
);
}
/* --- Footer --- */
function Footer({ go }) {
const c = PAOLA_DATA.contact;
return (
);
}
/* --- Floating WhatsApp --- */
function WhatsAppFloat() {
const c = PAOLA_DATA.contact;
const phone = String(c.whatsappPretty || c.whatsapp || '').replace(/\D/g, '');
if (!phone) return null;
const message = c.whatsappMessage || 'Hola Paola, quiero recibir información sobre una sesión fotográfica.';
const href = `https://wa.me/${phone}?text=${encodeURIComponent(message)}`;
return (
✆
WhatsApp
);
}
/* --- Hero --- */
function Hero({ go, heroCopy }) {
const ref = useRef(null);
const [loaded, setLoaded] = useState(false);
const slides = Array.isArray(PAOLA_DATA.hero.slides)
? PAOLA_DATA.hero.slides.filter(Boolean)
: (PAOLA_DATA.hero.main ? [PAOLA_DATA.hero.main] : []);
const hasSlides = slides.length > 0;
const [idx, setIdx] = useState(0);
useEffect(() => {
const t = setTimeout(() => setLoaded(true), 80);
return () => clearTimeout(t);
}, []);
// Auto-advance slides
useEffect(() => {
if (slides.length <= 1) return;
const t = setInterval(() => setIdx(i => (i + 1) % slides.length), 5500);
return () => clearInterval(t);
}, [slides.length]);
// Parallax
useEffect(() => {
const onScroll = () => {
if (!ref.current) return;
const y = window.scrollY;
ref.current.querySelectorAll('.h-bg').forEach(bg => {
bg.style.setProperty('--py', `${y * 0.25}px`);
});
};
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
return (
{slides.map((src, i) => (
))}
{hasSlides && N° 0{idx+1} · COLECCIÓN 2026
}
FOTÓGRAFA PROFESIONAL — MEDELLÍN
{heroCopy.line1}
{heroCopy.line2}
{heroCopy.sub}
{hasSlides && (
{slides.map((_, i) => (
))}
)}
SCROLL
);
}
/* --- Lightbox --- */
function Lightbox({ items, index, onClose, onPrev, onNext }) {
const touchStart = useRef(null);
useEffect(() => {
const onKey = (e) => {
if (e.key === 'Escape') onClose();
if (e.key === 'ArrowLeft') onPrev();
if (e.key === 'ArrowRight') onNext();
};
window.addEventListener('keydown', onKey);
document.body.style.overflow = 'hidden';
return () => {
window.removeEventListener('keydown', onKey);
document.body.style.overflow = '';
};
}, [onClose, onPrev, onNext]);
const handleTouchStart = (e) => {
touchStart.current = e.touches[0].clientX;
};
const handleTouchEnd = (e) => {
if (touchStart.current === null) return;
const dx = e.changedTouches[0].clientX - touchStart.current;
if (Math.abs(dx) > 50) {
dx < 0 ? onNext() : onPrev();
}
touchStart.current = null;
};
const item = items[index];
return (
})
e.stopPropagation()} />
{item.label} — {index+1} / {items.length}
);
}
Object.assign(window, { Reveal, Nav, FullMenu, Marquee, Footer, WhatsAppFloat, Hero, Lightbox });