// Shared UI primitives
const { useState, useEffect, useRef, useMemo, useCallback } = React;
function useMobile(bp = 768) {
const [m, setM] = useState(() => window.innerWidth < bp);
useEffect(() => {
const fn = () => setM(window.innerWidth < bp);
window.addEventListener("resize", fn, { passive: true });
return () => window.removeEventListener("resize", fn);
}, [bp]);
return m;
}
window.useMobile = useMobile;
function Placeholder({ label, src, className = "", style = {}, children }) {
if (src) {
return (

{ e.currentTarget.parentElement.className += " ph"; e.currentTarget.remove(); }}
style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
{label && (
{label}
)}
{children}
);
}
return (
{children}
);
}
function Eyebrow({ children, style = {} }) {
return {children}
;
}
function IconStar({ filled }) {
return (
);
}
function IconSearch() {
return (
);
}
function IconSun() {
return (
);
}
function IconMoon() {
return (
);
}
function IconArrow({ rotate = 0 }) {
return (
);
}
function IconChevron({ rotate = 0 }) {
return (
);
}
function IconClose() {
return (
);
}
function IconHeart({ filled }) {
return (
);
}
function FavoriteButton({ id }) {
const [fav, setFav] = useState(() => {
try {
const list = JSON.parse(localStorage.getItem("cal:favs") || "[]");
return list.includes(id);
} catch { return false; }
});
const toggle = (e) => {
e.preventDefault(); e.stopPropagation();
setFav(v => {
const next = !v;
try {
const list = JSON.parse(localStorage.getItem("cal:favs") || "[]");
const upd = next ? [...new Set([...list, id])] : list.filter(x => x !== id);
localStorage.setItem("cal:favs", JSON.stringify(upd));
window.dispatchEvent(new CustomEvent("favsChanged", { detail: upd }));
} catch {}
window.showToast && window.showToast(next ? "Aggiunto ai preferiti" : "Rimosso dai preferiti");
return next;
});
};
return (
);
}
function SectionHeader({ kicker, title, link, linkLabel = "Vedi tutti" }) {
return (
);
}
function showToast(msg) {
const t = document.getElementById("toast");
if (!t) return;
t.textContent = msg;
t.classList.add("on");
clearTimeout(window.__toastTO);
window.__toastTO = setTimeout(() => t.classList.remove("on"), 1800);
}
window.showToast = showToast;
Object.assign(window, {
Placeholder, Eyebrow, SectionHeader, FavoriteButton,
IconStar, IconSearch, IconSun, IconMoon, IconArrow, IconChevron, IconClose, IconHeart
});