mapcn-react-native
Location

Location puck

The location puck shown on the map. Capability-gated props are documented, not faked.

Renderer support: MapLibre ✓ (⚠ pulsing/scale/images are Mapbox-only)  ·  Mapbox ✓ (⚠ onPress/custom children are MapLibre-only)

npx mapcn-rn add location-puck
import { MapLocationPuck, MAP_LOCATION_PUCK_CAPABILITIES } from "@/components/ui/mapcn";

Overview

MapLocationPuck is one of the four renderer-specific files. MapLibre renders its own JS <UserLocation> component (which can host custom children and an onPress handler); Mapbox renders its native <LocationPuck> (which supports pulsing, a custom scale, and custom top/bearing/shadow images). Neither renderer's feature set is faked on the other -- unsupported props are accepted (so the prop type stays uniform) but produce a __DEV__ console warning and have no effect, and MAP_LOCATION_PUCK_CAPABILITIES (a per-renderer RendererCapabilities object) lets you branch on what's actually supported at runtime.

follow is implemented as camera recentering on every location update (via useMap().flyTo) rather than wiring into Camera's native trackUserLocation/followUserLocation prop, which is declarative and owned by Map's own <Camera> element and not reachable from a sibling component. This is a documented simplification: visually equivalent to native follow for "keep the puck centered," at the cost of one extra location subscription while follow is active.

Props

PropTypeDefaultDescription
visiblebooleantrue
bearing"none" | "heading" | "course""none"Bearing source for the puck's directional indicator.
accuracyRingbooleantrueShows an accuracy ring around the puck.
minDisplacementnumber—Meters between position updates.
followfalse | "position" | "heading" | "course"falseRecenters the camera on every location update while set.
onFollowChange(follow) => void—Fires whenever the camera is recentered due to follow.
requestPermissionbooleantrueRequests foreground location permission on mount.
onPermissionDenied() => void—
pulsingboolean | { color?, radius?: number | "accuracy" }—Mapbox only.
scalenumber—Mapbox only.
images{ top?, bearing?, shadow? }—Mapbox only. Custom puck images.
onPress() => void—MapLibre only.
childrenReactNode—MapLibre only. Fully custom JS-rendered puck.
classNamestring—

Example

import { Map } from "@/components/ui/mapcn";
import { MapLocationPuck } from "@/components/ui/mapcn";

export function LiveLocation() {
  return (
    <Map defaultViewport={{ center: [-122.4194, 37.7749], zoom: 14 }} className="flex-1">
      <MapLocationPuck bearing="heading" follow="position" pulsing={{ color: "#4285F4" }} />
    </Map>
  );
}

Renderer support

interface RendererCapabilities {
  clusterMinPoints: boolean;
  locationPuckPulsing: boolean;   // Mapbox: true, MapLibre: false
  locationPuckScale: boolean;     // Mapbox: true, MapLibre: false
  locationPuckImages: boolean;    // Mapbox: true, MapLibre: false
  locationPuckPress: boolean;     // Mapbox: false, MapLibre: true
  locationPuckCustomChildren: boolean; // Mapbox: false, MapLibre: true
}

Location tracking · Permissions · Controls

On this page