'use client' import { Layers, LocateFixed, MapPin, Maximize2, Mountain, RotateCcw, Search, X } from 'lucide-react' import { cn } from '@djangocfg/ui-core/lib' import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, Tooltip, TooltipContent, TooltipTrigger, } from '@djangocfg/ui-core/components' import { MAP_STYLE_LABELS } from '../../styles' import type { MapStyleKey } from '../../types' import { CompassChip } from '../CompassChip' import { MAP_CONTROL_CLASS } from './constants' import type { GeolocateState } from './GeolocateHandle' /** * Map controls — one icon-only toolbar, top-right (Google-Maps style). All * chips are a uniform 36×36 square; labels live in tooltips (shown on the LEFT * so they never spill off the map's right edge). Sits above the scroll-lock * overlay so it stays clickable. * * The `data-map-control` attribute is load-bearing: the scroll-protection * re-lock skips clicks inside it. */ export function MapToolbar({ onClose, fullscreenButton, fullscreenLabel, onFullscreenOpen, basemapSwitcher, basemapOptions, basemapLabel, activeKey, onBasemapPick, terrainButton, terrainLabel, terrainOn, onTerrainToggle, compassButton, isOriented, compassLabel, bearing, onResetNorth, geolocate, geolocateLabel, geolocateState, onGeolocateTrigger, geocoder, geocoderOpen, onGeocoderToggle, externalMapsUrl, externalMapsLabel, showResetButton, hasViewportChanged, onResetToInitial, }: { onClose: (() => void) | undefined fullscreenButton: boolean fullscreenLabel: string onFullscreenOpen: () => void basemapSwitcher: boolean basemapOptions: MapStyleKey[] basemapLabel: string activeKey: MapStyleKey | undefined onBasemapPick: (key: string) => void terrainButton: boolean terrainLabel: string terrainOn: boolean onTerrainToggle: () => void compassButton: boolean isOriented: boolean compassLabel: string bearing: number onResetNorth: () => void geolocate: boolean geolocateLabel: string geolocateState: GeolocateState onGeolocateTrigger: () => void geocoder: boolean geocoderOpen: boolean onGeocoderToggle: () => void externalMapsUrl: string | undefined externalMapsLabel: string showResetButton: boolean hasViewportChanged: boolean onResetToInitial: () => void }) { return (
{onClose && ( Close )} {fullscreenButton && ( {fullscreenLabel} )} {/* Search (geocoder) — Google-Maps-style magnifier that toggles an on-map autocomplete (rendered top-left by MapInner). Tinted text-primary while open; aria-pressed mirrors the open state. */} {geocoder && ( {geocoderOpen ? 'Close search' : 'Search'} )} {/* Basemap switcher (Google-Maps "Layers") — pick the map style at runtime. Hidden if disabled or there's nothing to switch to. */} {basemapSwitcher && basemapOptions.length > 1 && ( {basemapLabel} {basemapOptions.map((key) => ( {MAP_STYLE_LABELS[key]} ))} )} {/* 3D terrain toggle (Mountain) — adds the free DEM terrain + hillshade and pitches the camera in so it reads as 3D. */} {terrainButton && ( {terrainLabel} )} {/* Compass — shows only when rotated/tilted (gated here); the chip's needle reflects the bearing and tints accent as an off-north cue, click eases back to north-up + top-down (Google style). */} {compassButton && isOriented && ( )} {/* Locate me (GPS) — drives maplibre's hidden GeolocateControl via trigger(). Tinted text-primary while actively following (like the terrain chip); muted/disabled look on permission-denied or unavailable, with a tooltip explaining it. Opt-in only. */} {geolocate && ( {geolocateState === 'error' ? 'Location unavailable — check permission' : geolocateLabel} )} {externalMapsUrl && ( {externalMapsLabel} )} {showResetButton && hasViewportChanged && ( Reset to the initial view )}
) }