import { useEffect, useRef } from 'react'; import { MapContainer, TileLayer, Marker, Popup, CircleMarker, useMap } from 'react-leaflet'; import L, { type LatLngTuple } from 'leaflet'; import 'leaflet/dist/leaflet.css'; const DEFAULT_ZOOM = 11; const MIN_ZOOM = 8; export interface NearbyMapPin { id: string; name: string; cityLabel: string | null; latitude: number; longitude: number; } interface NearbyBreweryMapProps { pins: NearbyMapPin[]; selectedId: string | null; onSelect: (id: string) => void; userLocation: LatLngTuple | null; userLocationLabel: string; } // Leaflet paints markers as SVG attributes, which can't reference CSS custom // properties the way class names can - resolve the current theme's colors instead. const resolveThemeColor = (variable: string, fallback: string) => { if (typeof document === 'undefined') return fallback; const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim(); return value || fallback; }; const pinIcon = (active: boolean) => L.divIcon({ className: '', html: ``, iconSize: [18, 18], iconAnchor: [9, 9], }); const FitAndFocus = ({ pins, userLocation, selectedId, }: { pins: NearbyMapPin[]; userLocation: LatLngTuple | null; selectedId: string | null; }) => { const map = useMap(); const didInitialFit = useRef(false); useEffect(() => { if (didInitialFit.current) return; const focus: LatLngTuple | null = userLocation ?? (pins[0] ? [pins[0].latitude, pins[0].longitude] : null); if (focus) { map.setView(focus, DEFAULT_ZOOM, { animate: false }); didInitialFit.current = true; } const timeout = setTimeout(() => map.invalidateSize(), 200); return () => clearTimeout(timeout); }, [map, pins, userLocation]); useEffect(() => { if (!didInitialFit.current || !selectedId) return; const pin = pins.find((p) => p.id === selectedId); if (!pin) return; map.flyTo([pin.latitude, pin.longitude], Math.max(map.getZoom(), 11), { duration: 0.8 }); }, [map, pins, selectedId]); return null; }; const RecenterButton = ({ userLocation }: { userLocation: LatLngTuple | null }) => { const map = useMap(); if (!userLocation) return null; return ( ); }; const NearbyBreweryMap = ({ pins, selectedId, onSelect, userLocation, userLocationLabel, }: NearbyBreweryMapProps) => ( {userLocation && ( You are here — {userLocationLabel} )} {pins.map((pin) => ( onSelect(pin.id) }} >

{pin.name}

{pin.cityLabel && (

{pin.cityLabel}

)} View brewery →
))}
); export default NearbyBreweryMap;