edbnedbn/ui
ComponentsMapsPDF
GitHub stars
Explorer
Maps
Components

API Reference

Props, hooks, and shared types for all map components. Built on MapLibre GL JS.

Jump to

AnatomyMapuseMapMapControlsMapMarkerMarkerContentMarkerPopupMarkerTooltipMarkerLabelMapPopupMapRouteMapClusterLayerMapLayerControlMapHeatmapLayerMapSearchMapDirectionsHooksShared Types

Component anatomy

example.tsx
18 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Map>
  <MapMarker longitude={...} latitude={...}>
    <MarkerContent>
      <MarkerLabel />
    </MarkerContent>
    <MarkerPopup />
    <MarkerTooltip />
  </MapMarker>

  <MapPopup longitude={...} latitude={...} />
  <MapControls />
  <MapLayerControl />
  <MapRoute coordinates={...} />
  <MapClusterLayer data={...} />
  <MapHeatmapLayer data={...} />
  <MapSearch />
  <MapDirections />
</Map>

Map

Root container that initializes MapLibre GL and provides context to child components. Handles theme switching between light and dark modes automatically.

Extends MapOptions from MapLibre GL (excluding container, style).

Propchildren
TypeReactNode
Default—
DescriptionChild components (markers, popups, controls, routes).
Proptheme
Type"light" | "dark"
Defaultauto
DescriptionMap theme. Auto-detects from document class or system preference if not set.
Propstyles
Type{ light?: string | StyleSpecification; dark?: string | StyleSpecification }
DefaultCARTO
DescriptionCustom map styles for light and dark themes. Overrides the default CARTO base tiles.
Propprojection
TypeProjectionSpecification
Defaultmercator
DescriptionMap projection. Use { type: "globe" } for 3D globe view (MapLibre v5+).
Propattribution
Typeboolean | "compact" | "full"
Default"compact"
DescriptionControls the attribution display. Compact shows a small closeable attribution.
ProponClick
Type(e: MapMouseEvent) => void
Default—
DescriptionCallback when the map is clicked.
ProponMoveEnd
Type(e: MapLibreEvent) => void
Default—
DescriptionCallback when the camera finishes moving (pan, zoom, rotate, pitch).
ProponZoomEnd
Type(e: MapLibreEvent) => void
Default—
DescriptionCallback when the zoom level finishes changing.
ProponLoad
Type(map: MapLibreGL.Map) => void
Default—
DescriptionCallback when the map finishes loading. Receives the map instance.
PropTypeDefaultDescription
childrenReactNode—Child components (markers, popups, controls, routes).
theme"light" | "dark"autoMap theme. Auto-detects from document class or system preference if not set.
styles{ light?: string | StyleSpecification; dark?: string | StyleSpecification }CARTOCustom map styles for light and dark themes. Overrides the default CARTO base tiles.
projectionProjectionSpecificationmercatorMap projection. Use { type: "globe" } for 3D globe view (MapLibre v5+).
attributionboolean | "compact" | "full""compact"Controls the attribution display. Compact shows a small closeable attribution.
onClick(e: MapMouseEvent) => void—Callback when the map is clicked.
onMoveEnd(e: MapLibreEvent) => void—Callback when the camera finishes moving (pan, zoom, rotate, pitch).
onZoomEnd(e: MapLibreEvent) => void—Callback when the zoom level finishes changing.
onLoad(map: MapLibreGL.Map) => void—Callback when the map finishes loading. Receives the map instance.

useMap

Hook that provides access to the MapLibre map instance and loading state. Must be used within a Map component.

example.tsx
1 lines
1
const { map, isLoaded } = useMap();

Returns map (MapLibre.Map | null) and isLoaded (boolean).

MapControls

Renders map control buttons (zoom, compass, locate, fullscreen). Must be inside Map.

Propposition
Type"top-left" | "top-right" | "bottom-left" | "bottom-right"
Default"bottom-right"
DescriptionPosition of the controls on the map.
PropshowZoom
Typeboolean
Defaulttrue
DescriptionShow zoom in/out buttons.
PropshowCompass
Typeboolean
Defaultfalse
DescriptionShow compass button to reset bearing.
PropshowLocate
Typeboolean
Defaultfalse
DescriptionShow locate button to find user's location.
PropshowFullscreen
Typeboolean
Defaultfalse
DescriptionShow fullscreen toggle button.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes.
ProponLocate
Type(coords: { longitude: number; latitude: number; accuracy: number }) => void
Default—
DescriptionCallback with user coordinates and GPS accuracy when located.
ProponLocateError
Type(error: GeolocationPositionError | null) => void
Default—
DescriptionCallback when geolocation fails or is unavailable.
PropshowAccuracy
Typeboolean
Defaultfalse
DescriptionShow an accuracy radius circle around the user's location.
PropaccuracyStyles
TypeAccuracyCircleStyles
Default—
DescriptionCustom styles: { fillColor?, strokeColor?, fillOpacity?, strokeWidth? }.
PropaccuracyTimeout
Typenumber
Default10000
DescriptionDuration in ms to show accuracy circle before auto-hiding (0 = never).
PropTypeDefaultDescription
position"top-left" | "top-right" | "bottom-left" | "bottom-right""bottom-right"Position of the controls on the map.
showZoombooleantrueShow zoom in/out buttons.
showCompassbooleanfalseShow compass button to reset bearing.
showLocatebooleanfalseShow locate button to find user's location.
showFullscreenbooleanfalseShow fullscreen toggle button.
classNamestring—Additional CSS classes.
onLocate(coords: { longitude: number; latitude: number; accuracy: number }) => void—Callback with user coordinates and GPS accuracy when located.
onLocateError(error: GeolocationPositionError | null) => void—Callback when geolocation fails or is unavailable.
showAccuracybooleanfalseShow an accuracy radius circle around the user's location.
accuracyStylesAccuracyCircleStyles—Custom styles: { fillColor?, strokeColor?, fillOpacity?, strokeWidth? }.
accuracyTimeoutnumber10000Duration in ms to show accuracy circle before auto-hiding (0 = never).

MapMarker

Container for marker-related components. Provides context for children and handles positioning.

Extends MarkerOptions from MapLibre GL (excluding element).

Proplongitude
Typenumber
Default—
DescriptionLongitude coordinate for marker position.
Proplatitude
Typenumber
Default—
DescriptionLatitude coordinate for marker position.
Propchildren
TypeReactNode
Default—
DescriptionMarker subcomponents (MarkerContent, MarkerPopup, etc).
ProponClick
Type(e: MouseEvent) => void
Default—
DescriptionCallback when marker is clicked.
ProponMouseEnter
Type(e: MouseEvent) => void
Default—
DescriptionCallback when mouse enters marker.
ProponMouseLeave
Type(e: MouseEvent) => void
Default—
DescriptionCallback when mouse leaves marker.
ProponDragStart
Type(lngLat: {lng, lat}) => void
Default—
DescriptionCallback when marker drag starts (requires draggable: true).
ProponDrag
Type(lngLat: {lng, lat}) => void
Default—
DescriptionCallback during marker drag.
ProponDragEnd
Type(lngLat: {lng, lat}) => void
Default—
DescriptionCallback when marker drag ends.
PropariaLabel
Typestring
Default—
DescriptionAccessible label for the marker element.
PropTypeDefaultDescription
longitudenumber—Longitude coordinate for marker position.
latitudenumber—Latitude coordinate for marker position.
childrenReactNode—Marker subcomponents (MarkerContent, MarkerPopup, etc).
onClick(e: MouseEvent) => void—Callback when marker is clicked.
onMouseEnter(e: MouseEvent) => void—Callback when mouse enters marker.
onMouseLeave(e: MouseEvent) => void—Callback when mouse leaves marker.
onDragStart(lngLat: {lng, lat}) => void—Callback when marker drag starts (requires draggable: true).
onDrag(lngLat: {lng, lat}) => void—Callback during marker drag.
onDragEnd(lngLat: {lng, lat}) => void—Callback when marker drag ends.
ariaLabelstring—Accessible label for the marker element.

MarkerContent

Renders the visual content of a marker. Must be inside MapMarker. Defaults to a blue dot if no children.

Propchildren
TypeReactNode
Default—
DescriptionCustom marker content. Uses the variant default (pin) if omitted.
Propvariant
Type"pin" | "dot" | "pulse" | "numbered" | "custom"
Default"pin"
DescriptionVisual style variant for the marker.
Propsize
Type"sm" | "md" | "lg"
Default"md"
DescriptionSize of the marker.
Propcolor
Type"primary" | "destructive" | "success" | "warning" | "muted"
Default"primary"
DescriptionColor theme for the marker.
Propanimate
Typeboolean
Defaultfalse
DescriptionEnable entrance animation on the marker.
Propnumber
Typenumber
Default—
DescriptionNumber to display inside the marker (requires variant: "numbered").
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes for the marker container.
PropTypeDefaultDescription
childrenReactNode—Custom marker content. Uses the variant default (pin) if omitted.
variant"pin" | "dot" | "pulse" | "numbered" | "custom""pin"Visual style variant for the marker.
size"sm" | "md" | "lg""md"Size of the marker.
color"primary" | "destructive" | "success" | "warning" | "muted""primary"Color theme for the marker.
animatebooleanfalseEnable entrance animation on the marker.
numbernumber—Number to display inside the marker (requires variant: "numbered").
classNamestring—Additional CSS classes for the marker container.

MarkerPopup

Popup attached to the marker, opens on click. Must be inside MapMarker.

Extends PopupOptions from MapLibre GL (excluding className, closeButton).

Propchildren
TypeReactNode
Default—
DescriptionPopup content.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes for the popup container.
PropcloseButton
Typeboolean
Defaultfalse
DescriptionShow a close button in the popup.
Propvariant
Type"default" | "glass"
Default"default"
DescriptionVisual style variant for the popup.
PropTypeDefaultDescription
childrenReactNode—Popup content.
classNamestring—Additional CSS classes for the popup container.
closeButtonbooleanfalseShow a close button in the popup.
variant"default" | "glass""default"Visual style variant for the popup.

MarkerTooltip

Tooltip that appears on hover. Must be inside MapMarker.

Extends PopupOptions from MapLibre GL (excluding className, closeButton, closeOnClick).

Propchildren
TypeReactNode
Default—
DescriptionTooltip content.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes for the tooltip container.
Propvariant
Type"default" | "glass"
Default"default"
DescriptionVisual style variant for the tooltip.
PropTypeDefaultDescription
childrenReactNode—Tooltip content.
classNamestring—Additional CSS classes for the tooltip container.
variant"default" | "glass""default"Visual style variant for the tooltip.

MarkerLabel

Text label above or below the marker. Must be inside MarkerContent.

Propchildren
TypeReactNode
Default—
DescriptionLabel text content.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes for the label.
Propposition
Type"top" | "bottom"
Default"top"
DescriptionPosition of the label relative to the marker.
PropTypeDefaultDescription
childrenReactNode—Label text content.
classNamestring—Additional CSS classes for the label.
position"top" | "bottom""top"Position of the label relative to the marker.

MapPopup

Standalone popup placed anywhere on the map without a marker. Must be inside Map.

Extends PopupOptions from MapLibre GL (excluding className, closeButton).

Proplongitude
Typenumber
Default—
DescriptionLongitude coordinate for popup position.
Proplatitude
Typenumber
Default—
DescriptionLatitude coordinate for popup position.
ProponClose
Type() => void
Default—
DescriptionCallback when popup is closed.
Propchildren
TypeReactNode
Default—
DescriptionPopup content.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes for the popup.
PropcloseButton
Typeboolean
Defaultfalse
DescriptionShow a close button in the popup.
Propvariant
Type"default" | "glass"
Default"default"
DescriptionVisual style variant for the popup.
PropTypeDefaultDescription
longitudenumber—Longitude coordinate for popup position.
latitudenumber—Latitude coordinate for popup position.
onClose() => void—Callback when popup is closed.
childrenReactNode—Popup content.
classNamestring—Additional CSS classes for the popup.
closeButtonbooleanfalseShow a close button in the popup.
variant"default" | "glass""default"Visual style variant for the popup.

MapRoute

Renders a line/route connecting coordinate points. Must be inside Map. Supports click and hover interactions.

Propid
Typestring
Defaultauto
DescriptionUnique identifier for the route layer. Auto-generated if not provided.
Propcoordinates
Type[number, number][]
Default—
DescriptionArray of [longitude, latitude] coordinate pairs.
Propcolor
Typestring
Default#2563eb
DescriptionLine color (CSS color value).
Propwidth
Typenumber
Default3
DescriptionLine width in pixels.
Propopacity
Typenumber
Default0.8
DescriptionLine opacity (0 to 1).
PropdashArray
Type[number, number]
Default—
DescriptionDash pattern [dash length, gap length] for dashed lines.
ProponClick
Type() => void
Default—
DescriptionCallback when the route line is clicked.
ProponMouseEnter
Type() => void
Default—
DescriptionCallback when mouse enters the route line.
ProponMouseLeave
Type() => void
Default—
DescriptionCallback when mouse leaves the route line.
Propinteractive
Typeboolean
Defaulttrue
DescriptionWhether the route is interactive (pointer cursor on hover).
PropTypeDefaultDescription
idstringautoUnique identifier for the route layer. Auto-generated if not provided.
coordinates[number, number][]—Array of [longitude, latitude] coordinate pairs.
colorstring#2563ebLine color (CSS color value).
widthnumber3Line width in pixels.
opacitynumber0.8Line opacity (0 to 1).
dashArray[number, number]—Dash pattern [dash length, gap length] for dashed lines.
onClick() => void—Callback when the route line is clicked.
onMouseEnter() => void—Callback when mouse enters the route line.
onMouseLeave() => void—Callback when mouse leaves the route line.
interactivebooleantrueWhether the route is interactive (pointer cursor on hover).

MapClusterLayer

Clustered point data using MapLibre GL's native clustering. Groups nearby points into clusters that expand on click. Must be inside Map.

Propdata
Typestring | GeoJSON.FeatureCollection
Default—
DescriptionGeoJSON FeatureCollection data or URL to fetch GeoJSON from.
PropclusterMaxZoom
Typenumber
Default14
DescriptionMaximum zoom level to cluster points on.
PropclusterRadius
Typenumber
Default50
DescriptionRadius of each cluster when clustering (in pixels).
PropclusterColors
Type[string, string, string]
Default["#51bbd6", "#f1f075", "#f28cb1"]
DescriptionCluster circle colors: [small, medium, large] by point count.
PropclusterThresholds
Type[number, number]
Default[100, 750]
DescriptionPoint count thresholds for color/size steps: [medium, large].
ProppointColor
Typestring
Default"#3b82f6"
DescriptionColor for unclustered individual points.
ProponPointClick
Type(feature, coordinates) => void
Default—
DescriptionCallback when an unclustered point is clicked.
ProponClusterClick
Type(clusterId, coordinates, pointCount) => void
Defaultzoom in
DescriptionCallback when a cluster is clicked. Zooms in by default.
PropTypeDefaultDescription
datastring | GeoJSON.FeatureCollection—GeoJSON FeatureCollection data or URL to fetch GeoJSON from.
clusterMaxZoomnumber14Maximum zoom level to cluster points on.
clusterRadiusnumber50Radius of each cluster when clustering (in pixels).
clusterColors[string, string, string]["#51bbd6", "#f1f075", "#f28cb1"]Cluster circle colors: [small, medium, large] by point count.
clusterThresholds[number, number][100, 750]Point count thresholds for color/size steps: [medium, large].
pointColorstring"#3b82f6"Color for unclustered individual points.
onPointClick(feature, coordinates) => void—Callback when an unclustered point is clicked.
onClusterClick(clusterId, coordinates, pointCount) => voidzoom inCallback when a cluster is clicked. Zooms in by default.

MapLayerControl

Dropdown to switch between Standard (vector), Satellite (raster), and Terrain (3D) base map layers. Controlled and uncontrolled modes. Must be inside Map.

Propposition
TypeControlPosition
Default"top-right"
DescriptionPosition of the control on the map.
PropdefaultLayer
TypeMapLayerType
Default"standard"
DescriptionInitial layer for uncontrolled mode.
PropactiveLayer
TypeMapLayerType
Default—
DescriptionControlled active layer.
ProponLayerChange
Type(layer: MapLayerType) => void
Default—
DescriptionCallback when the active layer changes.
PropsatelliteTiles
Typestring[]
DefaultEsri
DescriptionCustom satellite tile URLs.
PropterrainSource
Typestring
Default—
DescriptionCustom terrain tiles.json URL.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes.
PropTypeDefaultDescription
positionControlPosition"top-right"Position of the control on the map.
defaultLayerMapLayerType"standard"Initial layer for uncontrolled mode.
activeLayerMapLayerType—Controlled active layer.
onLayerChange(layer: MapLayerType) => void—Callback when the active layer changes.
satelliteTilesstring[]EsriCustom satellite tile URLs.
terrainSourcestring—Custom terrain tiles.json URL.
classNamestring—Additional CSS classes.

Extended Components

MapHeatmapLayer

Native MapLibre heatmap layer for point density visualization. Accepts HeatmapPoint[] or GeoJSON FeatureCollection. Must be inside Map.

Import from @/components/ui/map-heatmap. For GPU-accelerated heatmaps with larger datasets, see .
Propid
Typestring
Default"map-heatmap"
DescriptionUnique layer identifier.
Proppoints
TypeHeatmapPoint[]
Default—
DescriptionArray of HeatmapPoint objects ({ latitude, longitude, weight? }).
Propdata
TypeHeatmapPoint[]
Default—
DescriptionAlias for points. Array of HeatmapPoint objects.
PropweightProperty
Typestring
Default"weight"
DescriptionGeoJSON property name to use as the heatmap weight.
Propradius
Typenumber
Default25
DescriptionRadius of each heatmap point in pixels.
Propintensity
Typenumber | number[]
Default1
DescriptionIntensity multiplier. Array form interpolates by zoom level.
Propopacity
Typenumber
Default0.8
DescriptionLayer opacity (0–1).
PropcolorStops
TypeHeatmapColorStop[]
Default—
DescriptionCustom color gradient. Use heatmapColorPresets for built-in palettes.
Propgradient
TypeRecord<number, string>
DefaultheatmapColorPresets.default
DescriptionColor gradient as stop-to-color mapping. Alternative to colorStops.
PropmaxZoom
Typenumber
Default18
DescriptionMaximum zoom level for the heatmap.
PropbeforeId
Typestring
Default—
DescriptionID of an existing layer to insert below.
Propvisible
Typeboolean
Defaulttrue
DescriptionWhether the layer is visible.
PropTypeDefaultDescription
idstring"map-heatmap"Unique layer identifier.
pointsHeatmapPoint[]—Array of HeatmapPoint objects ({ latitude, longitude, weight? }).
dataHeatmapPoint[]—Alias for points. Array of HeatmapPoint objects.
weightPropertystring"weight"GeoJSON property name to use as the heatmap weight.
radiusnumber25Radius of each heatmap point in pixels.
intensitynumber | number[]1Intensity multiplier. Array form interpolates by zoom level.
opacitynumber0.8Layer opacity (0–1).
colorStopsHeatmapColorStop[]—Custom color gradient. Use heatmapColorPresets for built-in palettes.
gradientRecord<number, string>heatmapColorPresets.defaultColor gradient as stop-to-color mapping. Alternative to colorStops.
maxZoomnumber18Maximum zoom level for the heatmap.
beforeIdstring—ID of an existing layer to insert below.
visiblebooleantrueWhether the layer is visible.

MapSearch

Geocoding search with Nominatim integration, debounced input, keyboard navigation, and auto-fly. Also exports MapSearchInput and MapSearchResults for custom layouts.

Import from @/components/ui/map-search. Uses free Nominatim API — no API key required.
Propplaceholder
Typestring
Default"Search location..."
DescriptionInput placeholder text.
ProponResultSelect
Type(result: SearchResult) => void
Default—
DescriptionCallback when a result is selected. SearchResult has lat, lng, name, type?, bbox?.
PropmaxResults
Typenumber
Default5
DescriptionMaximum number of results to display.
PropminQueryLength
Typenumber
Default3
DescriptionMinimum characters required before searching.
Propgeocoder
Type(query: string) => Promise<SearchResult[]>
DefaultNominatim
DescriptionCustom geocoding function. Defaults to OpenStreetMap Nominatim.
PropdebounceMs
Typenumber
Default350
DescriptionDebounce delay in milliseconds.
Propposition
TypeControlPosition
Default"top-left"
DescriptionPosition of the search on the map.
PropflyToZoom
Typenumber
Default14
DescriptionZoom level when flying to selected location.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes.
PropdefaultExpanded
Typeboolean
Defaultfalse (mobile) / true (desktop)
DescriptionInitial expanded state for uncontrolled mode.
Propexpanded
Typeboolean
Default—
DescriptionControlled expanded state.
ProponExpandedChange
Type(expanded: boolean) => void
Default—
DescriptionCallback when expanded state changes.
PropTypeDefaultDescription
placeholderstring"Search location..."Input placeholder text.
onResultSelect(result: SearchResult) => void—Callback when a result is selected. SearchResult has lat, lng, name, type?, bbox?.
maxResultsnumber5Maximum number of results to display.
minQueryLengthnumber3Minimum characters required before searching.
geocoder(query: string) => Promise<SearchResult[]>NominatimCustom geocoding function. Defaults to OpenStreetMap Nominatim.
debounceMsnumber350Debounce delay in milliseconds.
positionControlPosition"top-left"Position of the search on the map.
flyToZoomnumber14Zoom level when flying to selected location.
classNamestring—Additional CSS classes.
defaultExpandedbooleanfalse (mobile) / true (desktop)Initial expanded state for uncontrolled mode.
expandedboolean—Controlled expanded state.
onExpandedChange(expanded: boolean) => void—Callback when expanded state changes.

MapDirections

Routing and turn-by-turn directions powered by OSRM. Supports driving, walking, and cycling profiles with multi-waypoint routes.

Import from @/components/ui/map-directions. Default router uses the free OSRM demo server. Provide a custom router prop for production.
Propposition
TypeControlPosition
Default"top-right"
DescriptionPosition of the directions panel.
Proporigin
Type[number, number]
Default—
DescriptionControlled origin coordinates [lng, lat].
Propdestination
Type[number, number]
Default—
DescriptionControlled destination coordinates [lng, lat].
Propwaypoints
Type[number, number][]
Default—
DescriptionArray of waypoint coordinates [lng, lat] for multi-stop routes.
PropdefaultOrigin
Type[number, number]
Default—
DescriptionDefault starting coordinates [lng, lat] for uncontrolled mode.
PropdefaultDestination
Type[number, number]
Default—
DescriptionDefault destination coordinates [lng, lat] for uncontrolled mode.
PropdefaultProfile
Type"driving" | "walking" | "cycling"
Default"driving"
DescriptionDefault routing profile.
ProponRouteCalculated
Type(route: RouteResult) => void
Default—
DescriptionCallback when route is calculated.
ProponError
Type(error: Error) => void
Default—
DescriptionCallback when routing fails.
ProprouteColor
Typestring
Defaultprofile-dependent
DescriptionColor of the route line. Defaults vary by routing profile.
ProprouteWidth
Typenumber
Default4
DescriptionWidth of the route line in pixels.
PropshowControls
Typeboolean
Defaulttrue
DescriptionShow the directions control UI panel.
PropfitBounds
Typeboolean
Defaulttrue
DescriptionAutomatically fit map bounds to show the full route.
PropfitBoundsPadding
Typenumber
Default50
DescriptionPadding in pixels when fitting route bounds.
PropclassName
Typestring
Default—
DescriptionAdditional CSS classes.
Proprouter
Type(origin, destination, profile, waypoints?) => Promise<RouteResult>
DefaultOSRM
DescriptionCustom routing function. Provide yours for Mapbox, Google, etc.
Propgeocoder
Type(query: string) => Promise<GeocodingResult[]>
DefaultNominatim
DescriptionCustom geocoding function for address search inputs.
PropTypeDefaultDescription
positionControlPosition"top-right"Position of the directions panel.
origin[number, number]—Controlled origin coordinates [lng, lat].
destination[number, number]—Controlled destination coordinates [lng, lat].
waypoints[number, number][]—Array of waypoint coordinates [lng, lat] for multi-stop routes.
defaultOrigin[number, number]—Default starting coordinates [lng, lat] for uncontrolled mode.
defaultDestination[number, number]—Default destination coordinates [lng, lat] for uncontrolled mode.
defaultProfile"driving" | "walking" | "cycling""driving"Default routing profile.
onRouteCalculated(route: RouteResult) => void—Callback when route is calculated.
onError(error: Error) => void—Callback when routing fails.
routeColorstringprofile-dependentColor of the route line. Defaults vary by routing profile.
routeWidthnumber4Width of the route line in pixels.
showControlsbooleantrueShow the directions control UI panel.
fitBoundsbooleantrueAutomatically fit map bounds to show the full route.
fitBoundsPaddingnumber50Padding in pixels when fitting route bounds.
classNamestring—Additional CSS classes.
router(origin, destination, profile, waypoints?) => Promise<RouteResult>OSRMCustom routing function. Provide yours for Mapbox, Google, etc.
geocoder(query: string) => Promise<GeocodingResult[]>NominatimCustom geocoding function for address search inputs.

Hooks

Import from @/features/maps/lib/hooks.

useMapEvent

Subscribe to MapLibre map events with automatic cleanup. Handlers stay fresh via useCallbackRef — no stale closures.

example.tsx
11 lines
1
2
3
4
5
6
7
8
9
10
11
import { useMapEvent } from "@/features/maps/lib/hooks";

// Subscribe to map camera events
useMapEvent(map, isLoaded, "moveend", () => {
  console.log("Camera stopped moving");
});

// Subscribe to layer-specific events
useMapEvent(map, isLoaded, "click", (e) => {
  console.log("Clicked feature:", e.features?.[0]);
}, "my-layer-id");
Parammap
TypeMapLibreGL.Map | null
DescriptionThe map instance from useMap().
ParamisLoaded
Typeboolean
DescriptionWhether the map is loaded.
Paramevent
Typekeyof MapEventType
DescriptionMapLibre event name (e.g. "click", "moveend", "mouseenter").
Paramhandler
Type(ev: MapEventType[K]) => void
DescriptionEvent handler. Kept fresh via useCallbackRef — no stale closures.
ParamlayerId
Typestring
DescriptionOptional layer ID to scope the event to a specific layer.
ParamTypeDescription
mapMapLibreGL.Map | nullThe map instance from useMap().
isLoadedbooleanWhether the map is loaded.
eventkeyof MapEventTypeMapLibre event name (e.g. "click", "moveend", "mouseenter").
handler(ev: MapEventType[K]) => voidEvent handler. Kept fresh via useCallbackRef — no stale closures.
layerIdstringOptional layer ID to scope the event to a specific layer.

useMapLayer

Declaratively manage a GeoJSON source + layer pair. Full lifecycle: add on mount, update reactively, remove on unmount. Re-creates after basemap style switches.

Returns { sourceId: string, layerId: string }

example.tsx
17 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { useMapLayer } from "@/features/maps/lib/hooks";

const geojson = useMemo(() => ({
  type: "FeatureCollection" as const,
  features: points.map((p) => ({
    type: "Feature" as const,
    geometry: { type: "Point" as const, coordinates: [p.lng, p.lat] },
    properties: p,
  })),
}), [points]);

const { sourceId, layerId } = useMapLayer(map, isLoaded, {
  id: "my-points",
  type: "circle",
  data: geojson,
  paint: { "circle-radius": 6, "circle-color": "#3b82f6" },
});
Parammap
TypeMapLibreGL.Map | null
DescriptionThe map instance from useMap().
ParamisLoaded
Typeboolean
DescriptionWhether the map is loaded.
Paramoptions.id
Typestring
DescriptionBase ID for source and layer ("{id}-source" and "{id}-layer").
Paramoptions.type
TypeLayerSpecification['type']
DescriptionMapLibre layer type ("circle", "line", "fill", "symbol", etc.).
Paramoptions.data
TypeGeoJSON.GeoJSON
DescriptionGeoJSON data for the source. Updates reactively.
Paramoptions.paint
TypeRecord<string, unknown>
DescriptionPaint properties. Updates reactively via setPaintProperty.
Paramoptions.layout
TypeRecord<string, unknown>
DescriptionLayout properties for the layer.
Paramoptions.filter
Typeunknown[]
DescriptionMapLibre filter expression.
Paramoptions.beforeId
Typestring
DescriptionInsert the layer before this layer ID.
Paramoptions.sourceOptions
TypeRecord<string, unknown>
DescriptionAdditional source options (cluster, clusterMaxZoom, clusterRadius).
ParamTypeDescription
mapMapLibreGL.Map | nullThe map instance from useMap().
isLoadedbooleanWhether the map is loaded.
options.idstringBase ID for source and layer ("{id}-source" and "{id}-layer").
options.typeLayerSpecification['type']MapLibre layer type ("circle", "line", "fill", "symbol", etc.).
options.dataGeoJSON.GeoJSONGeoJSON data for the source. Updates reactively.
options.paintRecord<string, unknown>Paint properties. Updates reactively via setPaintProperty.
options.layoutRecord<string, unknown>Layout properties for the layer.
options.filterunknown[]MapLibre filter expression.
options.beforeIdstringInsert the layer before this layer ID.
options.sourceOptionsRecord<string, unknown>Additional source options (cluster, clusterMaxZoom, clusterRadius).

useMapViewport

Tracks current viewport state. Updates after camera moves, zooms, rotations, and pitch changes.

Returns { center: [lng, lat], zoom: number, bearing: number, pitch: number }

example.tsx
4 lines
1
2
3
4
import { useMapViewport } from "@/features/maps/lib/hooks";

const { center, zoom, bearing, pitch } = useMapViewport(map, isLoaded);
// center: [lng, lat], zoom: number, bearing: degrees, pitch: degrees
Parammap
TypeMapLibreGL.Map | null
DescriptionThe map instance.
ParamisLoaded
Typeboolean
DescriptionWhether the map is loaded.
ParamTypeDescription
mapMapLibreGL.Map | nullThe map instance.
isLoadedbooleanWhether the map is loaded.

useMapBounds

Returns visible map bounds. Updates after every camera move.

Returns [[sw_lng, sw_lat], [ne_lng, ne_lat]] | null

example.tsx
4 lines
1
2
3
4
import { useMapBounds } from "@/features/maps/lib/hooks";

const bounds = useMapBounds(map, isLoaded);
// bounds: [[sw_lng, sw_lat], [ne_lng, ne_lat]] | null
Parammap
TypeMapLibreGL.Map | null
DescriptionThe map instance.
ParamisLoaded
Typeboolean
DescriptionWhether the map is loaded.
ParamTypeDescription
mapMapLibreGL.Map | nullThe map instance.
isLoadedbooleanWhether the map is loaded.

useCallbackRef

Keeps a stable ref in sync with the latest callback. Essential for MapLibre event handlers that attach on mount and must avoid stale closures.

Returns RefObject<T | undefined>

example.tsx
11 lines
1
2
3
4
5
6
7
8
9
10
11
import { useCallbackRef } from "@/features/maps/lib/hooks";

// Prevents stale closures in MapLibre event handlers
const onClickRef = useCallbackRef(onClick);

useEffect(() => {
  if (!map || !isLoaded) return;
  const handler = (e: MapMouseEvent) => onClickRef.current?.(e);
  map.on("click", "my-layer", handler);
  return () => { map.off("click", "my-layer", handler); };
}, [map, isLoaded]);
Paramcallback
TypeT | undefined
DescriptionCallback to keep a stable ref to. Updates without re-subscriptions.
ParamTypeDescription
callbackT | undefinedCallback to keep a stable ref to. Updates without re-subscriptions.

useReducedMotion

Detects whether the user prefers reduced motion. Returns true if prefers-reduced-motion: reduce is active. Used by map camera transitions.

Returns boolean

example.tsx
4 lines
1
2
3
4
import { useReducedMotion } from "@/features/maps/lib/hooks";

const reduceMotion = useReducedMotion();
// true if prefers-reduced-motion: reduce is active

useDebouncedValue

Returns a debounced version of a value. Useful for search inputs and viewport-dependent queries.

Returns T

example.tsx
5 lines
1
2
3
4
5
import { useDebouncedValue } from "@/features/maps/lib/hooks";

const [search, setSearch] = useState("");
const debouncedSearch = useDebouncedValue(search, 300);
// debouncedSearch updates 300ms after last search change
Paramvalue
TypeT
DescriptionThe value to debounce.
Paramdelay
Typenumber
DescriptionDebounce delay in milliseconds.
ParamTypeDescription
valueTThe value to debounce.
delaynumberDebounce delay in milliseconds.

useDebouncedCallback

Debounces a callback function. Unlike useDebouncedValue, debounces the call itself. Cancels pending calls on unmount.

Returns T

example.tsx
5 lines
1
2
3
4
5
import { useDebouncedCallback } from "@/features/maps/lib/hooks";

const debouncedFetch = useDebouncedCallback((query: string) => {
  fetch(`/api/search?q=${query}`);
}, 300);
Paramcallback
TypeT
DescriptionThe callback function to debounce.
Paramdelay
Typenumber
DescriptionDebounce delay in milliseconds.
ParamTypeDescription
callbackTThe callback function to debounce.
delaynumberDebounce delay in milliseconds.

Shared types

From @/lib/map-theme and @/lib/map-hooks.

example.tsx
24 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// map-theme.ts
type ControlPosition = "top-left" | "top-right" | "bottom-left" | "bottom-right";

const mapColors = {
  marker: { default, origin, destination, waypoint, selected, location },
  cluster: { low, mid, high, text, stroke },
  route: { primary: "#2563eb", outline, walking, cycling },
  accuracy: { fill, stroke },
  terrain: { hillshadeShadow, hillshadeAccent },
};

const mapTransitions = {
  flyTo: 1200, easeTo: 400, zoomStep: 300,
  pitchReset: 600, layerFade: 180, clusterExpand: 400,
};

const mapZoomLevels = { locate: 14, search: 14, clusterExpand: 14, maxRoute: 15 };

// map-hooks.ts
function useDebouncedValue<T>(value: T, delay: number): T;
function useClickOutside(ref: RefObject, handler: () => void): void;
function useMobile(breakpoint?: number): boolean;
function useCallbackRef<T>(callback: T | undefined): RefObject<T | undefined>;
function useResolvedTheme(themeProp?: "light" | "dark"): "light" | "dark";