/**
* SchoolHeroMap
* The location map that sits atop the school-detail hero. Shows a static
* preview (pin + tiles) that blends down into the title; the whole band — or
* the parent's "View on map" link, via the imperative `open()` handle — expands
* it to a fullscreen, interactive map.
*/
'use client';
import dynamic from 'next/dynamic';
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
import styles from './SchoolHeroMap.module.css';
const LeafletHeroMap = dynamic(() => import('./LeafletHeroMapInner'), {
ssr: false,
loading: () =>
,
});
export interface SchoolHeroMapHandle {
open: () => void;
}
interface SchoolHeroMapProps {
lat: number;
lng: number;
}
export const SchoolHeroMap = forwardRef(
function SchoolHeroMap({ lat, lng }, ref) {
const wrapperRef = useRef(null);
const [nativeFullscreen, setNativeFullscreen] = useState(false);
// iOS Safari has no Element.requestFullscreen — fall back to a
// fixed-position overlay driven by state instead of the Fullscreen API.
const [fallbackFullscreen, setFallbackFullscreen] = useState(false);
const isFullscreen = nativeFullscreen || fallbackFullscreen;
const open = useCallback(() => {
const el = wrapperRef.current;
if (!el) return;
if (el.requestFullscreen) {
el.requestFullscreen().catch(() => setFallbackFullscreen(true));
} else {
setFallbackFullscreen(true);
}
}, []);
const close = useCallback(() => {
if (document.fullscreenElement) document.exitFullscreen().catch(() => {});
setFallbackFullscreen(false);
}, []);
useImperativeHandle(ref, () => ({ open }), [open]);
useEffect(() => {
const onChange = () => setNativeFullscreen(!!document.fullscreenElement);
document.addEventListener('fullscreenchange', onChange);
return () => document.removeEventListener('fullscreenchange', onChange);
}, []);
// The fallback overlay sits on top of the page rather than replacing it,
// so lock body scroll while it is up.
useEffect(() => {
if (!fallbackFullscreen) return;
const prev = document.body.style.overflow;
document.body.style.overflow = 'hidden';
return () => { document.body.style.overflow = prev; };
}, [fallbackFullscreen]);
return (
{isFullscreen ? (
) : (
<>
{/* Whole-band click target that opens the full map. */}
{/* Diffuse blend into the hero body below. */}
>
)}