/** * Map — a themed vector map. * * Everything visible is built from theme tokens rather than shipped as a * finished style, so the map belongs to whatever theme is active instead of * being the one rectangle on the screen that stayed grey. See `basemap.ts` for * how the style is assembled; the short version is that the tiles are bought * and the colours are ours. * * ```tsx * * * * Charing Cross * * * * * ``` * * The renderer is native and optional, so `Map` has a state no other component * here does: it may be unable to draw at all. It says so in place rather than * throwing, because the usual way to reach that state is running in a client * that cannot load native modules, and a screen explaining the build you need * is more use than a stack trace. * * `Map.Popup` reads its position from the marker it sits inside, the way a * frame's title reads its weight from its slot. Given a `lngLat` of its own it * anchors to that coordinate instead, so the same name covers both the popup * attached to a pin and the one floating over a place with no pin at all. */ import { type ReactNode } from 'react'; import { type PressableProps, type ViewProps } from 'react-native'; import { CARTO_SOURCE, type BasemapSource, type BasemapTokens } from './basemap.js'; import { hasMapLibre, type CameraRef, type LngLat, type LngLatBounds, type MapRef, type PixelPoint, type StyleSpecification, type ViewState } from './maplibre.js'; import { type MapFeatureAccessibility } from './map-accessibility.js'; export { hasMapLibre, CARTO_SOURCE }; export type { BasemapSource, BasemapTokens, LngLat, LngLatBounds, PixelPoint, ViewState }; export type { MapFeatureAccessibility } from './map-accessibility.js'; export type MapControlsPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; interface MapContextValue { mapRef: React.RefObject; cameraRef: React.RefObject; /** The style has loaded and the map is drawing. */ ready: boolean; } /** * The map's camera and view state, from inside it. * * For a control, an overlay, or anything that has to move the map in response * to something that is not a gesture on it. */ export declare function useMap(): MapContextValue; export interface MapHandle { /** Move the camera, animating unless `duration` is 0. */ flyTo(options: { center: LngLat; zoom?: number; duration?: number; }): void; /** Frame a bounding box, leaving `padding` points around it. */ fitBounds(bounds: LngLatBounds, padding?: number): void; /** Where the map is looking right now. */ getViewState(): Promise; } export interface MapProps extends Omit { children?: ReactNode; /** Initial centre, `[longitude, latitude]`. */ center?: LngLat; /** Initial zoom. 0 is the whole world; 18 is a building. */ zoom?: number; /** Initial bearing in degrees, clockwise from north. */ bearing?: number; /** Initial tilt in degrees. 0 looks straight down. */ pitch?: number; /** * Frame these bounds instead of centring — `[west, south, east, north]`. * Wins over `center` and `zoom` when both are given. */ bounds?: LngLatBounds; /** * Drop the basemap and keep only the ground colour. For data that carries * its own geography — a choropleth, an arc diagram — where streets * underneath are noise rather than context. */ blank?: boolean; /** * Where the vector tiles come from. Defaults to CARTO, which is free for * non-commercial use and licensed for everything else. */ source?: BasemapSource; /** * Use this style wholesale instead of building one from tokens. The escape * hatch for a map that has to match something outside the app. */ mapStyle?: string | StyleSpecification; /** Let the map rotate and tilt. Off by default — most maps only pan and zoom. */ rotatable?: boolean; /** Turn off panning and zooming, for a map that is an illustration. */ interactive?: boolean; /** Fires continuously while the map moves. */ onViewStateChange?: (state: ViewState) => void; /** * Fires when the map is pressed somewhere that is not a feature. The second * argument is the same press in screen coordinates, for anchoring something * of your own to where the finger landed. */ onPress?: (lngLat: LngLat, point: PixelPoint) => void; /** Fires once the style has loaded and the first frame is drawn. */ onReady?: () => void; } export interface MapMarkerProps extends Omit { /** Where the marker sits, `[longitude, latitude]`. */ lngLat: LngLat; /** * Which part of the marker sits on the coordinate. A pin drawn above its * point wants `bottom`; a dot centred on it wants the default. */ anchor?: 'center' | 'top' | 'bottom' | 'left' | 'right'; /** Pressing the marker. Adds a button role when given. */ onPress?: () => void; /** Explicit spoken name. Other React Native accessibility props pass through too. */ accessibilityLabel?: string; className?: string; /** Defaults to a dot. Anything else replaces it. */ children?: ReactNode; } /** * A point on the map, drawn as React views rather than as a style layer — so * it can be anything the rest of the library can draw. For hundreds of points * use `Map.Cluster` instead: a view per marker stops being affordable long * before the map stops being readable. */ declare function MapMarker({ lngLat, anchor, onPress, className, children, accessibilityState, ...props }: MapMarkerProps): import("react").JSX.Element | null; declare namespace MapMarker { var displayName: string; } export interface MapLabelProps { children?: ReactNode; className?: string; /** Which side of the marker the label sits on. */ side?: 'top' | 'bottom'; /** `sm` for a map carrying a lot of them, where the pills start to collide. */ size?: 'sm' | 'md'; /** * How loud the label is. `muted` for codes and counts that support the map * without being its subject; `primary` for the one place being pointed at. */ tone?: 'default' | 'muted' | 'primary'; } /** * A caption pinned to a marker. Always visible, unlike a popup — for the * handful of places whose names are the point of the map. * * It is taken out of the marker's layout flow, which matters more than it * sounds: a marker sits on its coordinate by the centre of its box, so a label * in flow underneath the pin would pull that centre down and lift every pin * off the place it marks. Absolute keeps the box the size of the pin. * * The overhang on each side is what lets a long name stay centred on the pin * without widening the marker — a name is usually far wider than the dot it * belongs to, and a box sized to the name would be anchored by the name. */ declare function MapLabel({ children, className, side, size, tone, }: MapLabelProps): import("react").JSX.Element; declare namespace MapLabel { var displayName: string; } export interface MapPopupProps { children?: ReactNode; className?: string; /** Heading above the content. Strings are wrapped for you. */ title?: string; /** * Anchor to this coordinate instead of to an enclosing marker. Required when * the popup is not inside one. */ lngLat?: LngLat; } /** * A card anchored to a point. * * Inside a `Map.Marker` it takes that marker's coordinate and opens when the * marker is pressed. Given a `lngLat` it stands alone at that coordinate — the * same component either way, because the difference is where it is anchored * rather than what it is. * * Either way it is its own annotation rather than something drawn inside the * marker, which is what keeps a card from dragging the pin off its coordinate. * Anchored by its bottom edge, so it floats above the point it describes * instead of covering it. */ declare function MapPopup({ children, className, title, lngLat }: MapPopupProps): import("react").JSX.Element | null; declare namespace MapPopup { var displayName: string; } export interface MapControlsProps { /** Which corner the stack sits in. */ position?: MapControlsPosition; /** Zoom in and out. On by default — it is the one control a map always needs. */ zoom?: boolean; /** Recentre on the device's location. Needs a location permission. */ locate?: boolean; /** Reset bearing and pitch to north and flat. */ compass?: boolean; className?: string; /** Called with the located coordinate, so a caller can react to it. */ onLocate?: (lngLat: LngLat) => void; } /** * The map's own chrome, as themed views. * * The renderer draws its own zoom and compass ornaments, but in its style * rather than the app's, and they cannot be recoloured — so they are turned * off in `Map` and replaced here by buttons built from the same tokens as * every other control in the library. */ declare function MapControls({ position, zoom, locate, compass, className, onLocate, }: MapControlsProps): import("react").JSX.Element; declare namespace MapControls { var displayName: string; } export interface MapRouteProps { /** The path, in order. */ coordinates: LngLat[]; /** Defaults to the primary token. */ color?: string; /** Line thickness in points. */ width?: number; /** Draw it dashed — for a leg that is planned rather than travelled. */ dashed?: boolean; /** 0 is invisible, 1 is solid. */ opacity?: number; id?: string; } /** * A path across the map, drawn as a style layer rather than as views — so its * cost does not grow with the number of points in it. */ declare function MapRoute({ coordinates, color, width, dashed, opacity, id, }: MapRouteProps): import("react").JSX.Element | null; declare namespace MapRoute { var displayName: string; } export interface MapArcProps { /** Where the arc starts. */ from: LngLat; /** Where it ends. */ to: LngLat; /** How far it bows. 0 is a straight line; 0.2 is the default lift. */ curvature?: number; color?: string; width?: number; opacity?: number; id?: string; } /** * A curved connection between two points. * * The curve is not geography — a great circle between two cities is not bowed * on a flat projection. It is there so that two arcs sharing an endpoint stay * tellable apart, which a bundle of straight lines through one city does not. */ declare function MapArc({ from, to, curvature, color, width, opacity, id, }: MapArcProps): import("react").JSX.Element | null; declare namespace MapArc { var displayName: string; } export interface MapGeoJSONProps { /** A Feature, FeatureCollection, or the URL of one. */ data: unknown; /** Fill colour for polygons. A style expression works here too. */ fill?: string | unknown[]; /** Outline colour. Defaults to the border token. */ stroke?: string | unknown[]; /** Outline thickness. */ strokeWidth?: number; /** 0 is invisible, 1 is solid. */ fillOpacity?: number; /** Fires with the pressed feature. */ onPress?: (feature: unknown) => void; /** Describes each inline GeoJSON feature for the synchronized nonvisual list. */ accessibility?: (feature: unknown, index: number) => MapFeatureAccessibility; id?: string; } /** * Arbitrary geography as a themed layer — the component behind a choropleth, * a coverage area, or any other shape that comes from data rather than from * the basemap. * * `fill` takes a style expression as well as a colour, which is what makes a * choropleth one layer instead of one layer per bucket. */ declare function MapGeoJSON({ data, fill, stroke, strokeWidth, fillOpacity, onPress, accessibility, id, }: MapGeoJSONProps): import("react").JSX.Element | null; declare namespace MapGeoJSON { var displayName: string; } export interface MapClusterProps { /** Point features to cluster. */ data: unknown; /** Defaults to the primary token. */ color?: string; /** Text colour inside a cluster bubble. */ textColor?: string; /** How close two points have to be, in points, to merge. */ radius?: number; /** Above this zoom every point stands alone. */ maxZoom?: number; /** Fires with the pressed cluster or point. */ onPress?: (feature: unknown) => void; /** Describes each source point for the synchronized nonvisual list. */ accessibility?: (feature: unknown, index: number) => MapFeatureAccessibility; id?: string; } /** * Dense points, merged as they get too close to tell apart. * * This is the layer to reach for past a few dozen points: `Map.Marker` mounts * a React view each, which a thousand points cannot afford, and a thousand * overlapping pins would be unreadable even if it could. */ declare function MapCluster({ data, color, textColor, radius, maxZoom, onPress, accessibility, id, }: MapClusterProps): import("react").JSX.Element | null; declare namespace MapCluster { var displayName: string; } export interface MapHeatmapProps { /** Point features to spread. */ data: unknown; /** Feature property to weight each point by. Unweighted when omitted. */ weight?: string; /** * Base colour of the field — a theme token by name, or a literal. The ramp * is this colour at rising opacity, so density reads as *more of the same * thing* rather than as a change of subject. * * Defaults to `--color-chart-2`, which is a saturated accent in every theme. * It is deliberately not `--color-chart-1`: that is the series colour a chart * is about, and every theme starts it on something close to the foreground — * near-black in a light theme, near-white in a dark one — which over a * basemap is a smudge rather than a measurement. */ color?: string; /** * Replace the derived ramp outright, coolest first. For the conventional * heat ramp, where the hue carries the reading as well as the opacity — * worth it when the field sits over varied terrain and one hue at five * opacities stops being separable from what is underneath it. * * The first stop is drawn at the lowest density, the last at the highest. * Density zero stays fully transparent either way. */ colors?: string[]; /** * Spread of a single point, in points, at street zoom. Larger blurs more. * The drawn radius shrinks as the map zooms out, so a point keeps covering * roughly the same ground rather than the same screen area. */ radius?: number; /** Overall strength. Raise it when the data is sparse. */ intensity?: number; /** 0 is invisible, 1 is solid. */ opacity?: number; /** Above this zoom the layer fades out — see the note on the component. */ maxZoom?: number; /** * Draw the points themselves as the field fades out, coloured from the same * ramp by weight. Without them, zooming past `maxZoom` leaves an empty map: * the layer gets out of the way, and nothing takes its place. */ points?: boolean; id?: string; } /** * Point density as a continuous field. * * The opposite trade to `Map.Cluster`: a cluster keeps every point countable * and tells you nothing about the space between them, while a heatmap shows * the shape of the distribution and no longer lets you count anything. Reach * for it when the question is *where* rather than *how many*. * * It fades out past `maxZoom` on purpose. Zoomed far enough in, every point is * its own island and the blur says less than the points would — so the layer * gets out of the way rather than smearing five records across a street. Set * `points` and the records themselves fade in as it goes, which is the whole * handover: a field while the question is where, marks once it is which. * * The radius is tied to zoom for the mirror-image reason. Left as a fixed * number of screen points it would mean a different distance at every zoom: * a blur that reads as a city at street level covers half a continent once * the map is pulled out, and a field measured over land ends up sitting in * the sea. Scaling it with the projection keeps the claim the same one. * * Intensity is tied to zoom too, and in the other direction. The same points * are packed into fewer pixels the further out the map goes, so a constant * intensity saturates the whole field at world zoom and shows nothing but its * own ceiling. */ declare function MapHeatmap({ data, weight, color, colors, radius, intensity, opacity, maxZoom, points, id, }: MapHeatmapProps): import("react").JSX.Element | null; declare namespace MapHeatmap { var displayName: string; } export interface MapUserLocationProps { /** Show which way the device is facing, not just where it is. */ heading?: boolean; /** Draw the ring showing how confident the fix is. */ accuracy?: boolean; } /** The device's own position, drawn by the renderer. */ declare function MapUserLocation({ heading, accuracy, }: MapUserLocationProps): import("react").JSX.Element | null; declare namespace MapUserLocation { var displayName: string; } export declare const Map: import("react").ForwardRefExoticComponent> & { Marker: typeof MapMarker; Label: typeof MapLabel; Popup: typeof MapPopup; Controls: typeof MapControls; Route: typeof MapRoute; Arc: typeof MapArc; GeoJSON: typeof MapGeoJSON; Cluster: typeof MapCluster; Heatmap: typeof MapHeatmap; UserLocation: typeof MapUserLocation; }; //# sourceMappingURL=index.d.ts.map