/* Hash router + slug helper + embeddable Media component */ const { useState: uSr, useEffect: uEr } = React; function slugify(str) { return String(str).toLowerCase() .replace(/[^\w\s-]/g, "") .trim().replace(/\s+/g, "-").slice(0, 60); } function parseHash() { const h = window.location.hash || ""; const m = h.match(/^#!\/(kegiatan|artikel)\/(.+)$/); if (m) return { type: m[1], slug: decodeURIComponent(m[2]) }; return { type: "home" }; } /* navigate("kegiatan/" + slug) ; navigate("") -> home */ function navigate(path) { const target = path ? "#!/" + path : "#"; if (window.location.hash !== target) window.location.hash = target; else window.dispatchEvent(new HashChangeEvent("hashchange")); window.scrollTo({ top: 0, behavior: "instant" in window ? "instant" : "auto" }); } const useRoute = () => { const [route, setRoute] = uSr(parseHash()); uEr(() => { const on = () => { setRoute(parseHash()); window.scrollTo(0, 0); }; window.addEventListener("hashchange", on); return () => window.removeEventListener("hashchange", on); }, []); return route; }; /* ----- Media: renders image OR video; placeholder when src empty ----- */ const isYouTube = (u) => /youtube\.com|youtu\.be/.test(u); const Media = ({ media, label = "Media", radius, poster, dark }) => { const m = media || {}; const style = radius ? { borderRadius: radius } : undefined; if (m.src && m.kind === "image") { return {label}; } if (m.src && m.kind === "video") { if (isYouTube(m.src)) { return ; } return ; } // placeholder const isVideo = m.kind === "video"; return (
{isVideo ? "Slot video" : "Slot gambar"}
); }; window.slugify = slugify; window.navigate = navigate; window.useRoute = useRoute; window.Media = Media;