import { useCallback, useEffect, useMemo, useRef } from "react"; import { DEFAULT_MAP_SIZE, clampMapZoom } from "../lib/locationMapUtils"; const COMPACT_MAP_LAYOUT_QUERY = "(max-width: 839px)"; function getAutoFitKey(mapState, mapSize) { return [ mapState?.location?.id || "", mapState?.draft_map?.id || "", mapState?.published_map?.id || "", mapSize.width, mapSize.height, ].join(":"); } function getFitZoom(mapSize, scrollElement) { const fallbackWidth = typeof window === "undefined" ? DEFAULT_MAP_SIZE.width : window.innerWidth; const fallbackHeight = typeof window === "undefined" ? DEFAULT_MAP_SIZE.height : window.innerHeight; const isCompactLayout = typeof window !== "undefined" && window.matchMedia(COMPACT_MAP_LAYOUT_QUERY).matches; const minimumWidth = isCompactLayout ? 160 : 280; const minimumHeight = isCompactLayout ? 120 : 220; const availableWidth = Math.max(minimumWidth, (scrollElement?.clientWidth || fallbackWidth) - 24); const availableHeight = Math.max(minimumHeight, (scrollElement?.clientHeight || fallbackHeight) - 24); return Number(clampMapZoom( Math.min(availableWidth / mapSize.width, availableHeight / mapSize.height) ).toFixed(2)); } export default function useMobileMapAutoFit({ mapSize, mapState, mode, setZoom, svgRef, }) { const lastAutoFitKeyRef = useRef(null); const autoFitKey = useMemo( () => getAutoFitKey(mapState, mapSize), [mapSize, mapState] ); const fitMapToCanvas = useCallback(() => { const scrollElement = svgRef.current?.closest(".location-map-scroll"); setZoom(getFitZoom(mapSize, scrollElement)); scrollElement?.scrollTo({ left: 0, top: 0 }); }, [mapSize, setZoom, svgRef]); useEffect(() => { if (typeof window === "undefined") return undefined; if (!mapState || mode === "setup") return undefined; if (!window.matchMedia(COMPACT_MAP_LAYOUT_QUERY).matches) return undefined; if (lastAutoFitKeyRef.current === autoFitKey) return undefined; const frameId = window.requestAnimationFrame(() => { if (!svgRef.current) return; lastAutoFitKeyRef.current = autoFitKey; fitMapToCanvas(); }); return () => window.cancelAnimationFrame(frameId); }, [autoFitKey, fitMapToCanvas, mapState, mode, svgRef]); return fitMapToCanvas; }