import { useEffect, type MutableRefObject } from 'react'; import type maplibregl from 'maplibre-gl'; import { onMapStyleReady } from '../lib/mapCore'; import type { MapProjectionId } from '../types'; export function useFlyTo( mapRef: MutableRefObject, projectionRef: MutableRefObject, opts: { selectedMmsi: number | null; shipData: { mmsi: number; lon: number; lat: number }[]; fleetFocusId: string | number | undefined; fleetFocusLon: number | undefined; fleetFocusLat: number | undefined; fleetFocusZoom: number | undefined; }, ) { const { selectedMmsi, shipData, fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom } = opts; useEffect(() => { const map = mapRef.current; if (!map) return; if (!selectedMmsi) return; const t = shipData.find((x) => x.mmsi === selectedMmsi); if (!t) return; const flyOpts = { center: [t.lon, t.lat] as [number, number], zoom: Math.max(map.getZoom(), 10), duration: 600 }; if (projectionRef.current === 'globe') { map.flyTo(flyOpts); } else { map.easeTo(flyOpts); } }, [selectedMmsi, shipData]); useEffect(() => { const map = mapRef.current; if (!map || fleetFocusLon == null || fleetFocusLat == null || !Number.isFinite(fleetFocusLon) || !Number.isFinite(fleetFocusLat)) return; const lon = fleetFocusLon; const lat = fleetFocusLat; const zoom = fleetFocusZoom ?? 10; const apply = () => { const flyOpts = { center: [lon, lat] as [number, number], zoom, duration: 700 }; if (projectionRef.current === 'globe') { map.flyTo(flyOpts); } else { map.easeTo(flyOpts); } }; if (map.isStyleLoaded()) { apply(); return; } const stop = onMapStyleReady(map, apply); return () => { stop(); }; }, [fleetFocusId, fleetFocusLon, fleetFocusLat, fleetFocusZoom]); }