"use client"; import dynamic from "next/dynamic"; import Link from "next/link"; import { useEffect, useRef, useState } from "react"; import { cn } from "@/components/ui/cn"; import { Skeleton } from "@/components/ui/skeleton"; import { routes } from "@/lib/routes"; const MapCanvas = dynamic(() => import("@/components/map/map-canvas").then((m) => m.MapCanvas), { ssr: false, loading: () => }); /** * Home: live global map (clusters at zoom ~1.4), lazy-loaded when scrolled into view; the whole surface links to /map. * `interactive` lets the hero map pan/zoom while the corner button keeps the way into the full map. */ export function MapPreview({ className, interactive, children }: { className?: string; interactive?: boolean; children?: React.ReactNode }) { const ref = useRef(null); const [visible, setVisible] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; if (typeof IntersectionObserver === "undefined") { const t = setTimeout(() => setVisible(true), 0); return () => clearTimeout(t); } const io = new IntersectionObserver( (entries) => { if (entries.some((e) => e.isIntersecting)) { setVisible(true); io.disconnect(); } }, { rootMargin: "200px" }, ); io.observe(el); return () => io.disconnect(); }, []); return (
{visible ? : } {children} {interactive ? ( Open interactive map → ) : ( Open interactive map → )}
); }