Map
MapLibre GL primitives. Ships on the `@aeontel/ui/map` subpath — heavy, lazy by design. Pair with `@aeontel/ui/styles/map` for popup overrides.
Usage
TSX
import {
Map,
MapControls,
MapMarker,
MarkerContent,
MarkerPopup,
} from "@aeontel/ui/map";
export default function Sites() {
return (
<div className="h-96 w-full">
{/* The viewport prop is `viewport`, not `initialViewState`. */}
{/* Shape: { center: [lng, lat], zoom } — center is a tuple. */}
<Map viewport={{ center: [-122.4, 37.78], zoom: 11 }}>
<MapControls position="top-right" />
{/* Default blue dot + click popup */}
<MapMarker longitude={-122.4} latitude={37.78}>
<MarkerPopup>San Francisco HQ</MarkerPopup>
</MapMarker>
{/* Custom marker visual — wrap in MarkerContent. Raw children */}
{/* of MapMarker are not portaled into the marker DOM and stay */}
{/* invisible. */}
<MapMarker longitude={2.3522} latitude={48.8566}>
<MarkerContent>
<div className="bg-primary text-primary-foreground rounded-full px-2 py-1 text-xs font-semibold shadow">
Paris
</div>
</MarkerContent>
</MapMarker>
</Map>
</div>
);
}
// The container needs an explicit height — MapLibre measures its parent.
// Pair every map with `@import "@aeontel/ui/styles/map"` in your root CSS
// (only affects popup chrome — does NOT gate marker visibility).Exports
Map
TypeScript
Map(props: ComponentProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
children? | ReactNode | — | |
className? | string | undefined | — | Additional CSS classes for the map container |
theme? | Theme | undefined | — | Theme for the map. If not provided, automatically detects system preference. Pass your theme value here. |
styles? | { light?: MapStyleOption; dark?: MapStyleOption; } | undefined | — | Custom map styles for light and dark themes. Overrides the default Carto styles. |
projection? | MapLibreGL.ProjectionSpecification | undefined | — | Map projection type. Use { type: "globe" } for 3D globe view. |
viewport? | Partial<MapViewport> | undefined | — | Controlled viewport. When provided with onViewportChange, the map becomes controlled and viewport is driven by this prop. |
onViewportChange? | ((viewport: MapViewport) => void) | undefined | — | Callback fired continuously as the viewport changes (pan, zoom, rotate, pitch). Can be used standalone to observe changes, or with viewport prop to enable controlled mode where the map viewport is driven by your state. |
loading? | boolean | undefined | false | Show a loading indicator on the map |
MapMarker
TypeScript
MapMarker(props: MapMarkerProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
longitude | number | — | Longitude coordinate for marker position |
latitude | number | — | Latitude coordinate for marker position |
children | ReactNode | — | Marker subcomponents (MarkerContent, MarkerPopup, MarkerTooltip, MarkerLabel) |
onClick? | ((e: MouseEvent) => void) | undefined | — | Callback when marker is clicked |
onMouseEnter? | ((e: MouseEvent) => void) | undefined | — | Callback when mouse enters marker |
onMouseLeave? | ((e: MouseEvent) => void) | undefined | — | Callback when mouse leaves marker |
onDragStart? | ((lngLat: { lng: number; lat: number; }) => void) | undefined | — | Callback when marker drag starts (requires draggable: true) |
onDrag? | ((lngLat: { lng: number; lat: number; }) => void) | undefined | — | Callback during marker drag (requires draggable: true) |
onDragEnd? | ((lngLat: { lng: number; lat: number; }) => void) | undefined | — | Callback when marker drag ends (requires draggable: true) |
MarkerContent
TypeScript
MarkerContent(props: MarkerContentProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
children? | ReactNode | — | Custom marker content. Defaults to a blue dot if not provided |
className? | string | undefined | — | Additional CSS classes for the marker container |
MarkerLabel
TypeScript
MarkerLabel(props: MarkerLabelProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Label text content |
className? | string | undefined | — | Additional CSS classes for the label |
position? | "top" | "bottom" | undefined | "top" | Position of the label relative to the marker (default: "top") |
MarkerPopup
TypeScript
MarkerPopup(props: MarkerPopupProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Popup content |
className? | string | undefined | — | Additional CSS classes for the popup container |
closeButton? | boolean | undefined | false | Show a close button in the popup (default: false) |
MarkerTooltip
TypeScript
MarkerTooltip(props: MarkerTooltipProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Tooltip content |
className? | string | undefined | — | Additional CSS classes for the tooltip container |
MapPopup
TypeScript
MapPopup(props: MapPopupProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
longitude | number | — | Longitude coordinate for popup position |
latitude | number | — | Latitude coordinate for popup position |
onClose? | (() => void) | undefined | — | Callback when popup is closed |
children | ReactNode | — | Popup content |
className? | string | undefined | — | Additional CSS classes for the popup container |
closeButton? | boolean | undefined | false | Show a close button in the popup (default: false) |
MapControls
TypeScript
MapControls(props: MapControlsProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
position? | "top-left" | "top-right" | "bottom-left" | "bottom-right" | undefined | "bottom-right" | Position of the controls on the map (default: "bottom-right") |
showZoom? | boolean | undefined | true | Show zoom in/out buttons (default: true) |
showCompass? | boolean | undefined | false | Show compass button to reset bearing (default: false) |
showLocate? | boolean | undefined | false | Show locate button to find user's location (default: false) |
showFullscreen? | boolean | undefined | false | Show fullscreen toggle button (default: false) |
className? | string | undefined | — | Additional CSS classes for the controls container |
onLocate? | ((coords: { longitude: number; latitude: number; }) => void) | undefined | — | Callback with user coordinates when located |
MapRoute
TypeScript
MapRoute(props: MapRouteProps): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
id? | string | undefined | — | Optional unique identifier for the route layer |
coordinates | [number, number][] | — | Array of [longitude, latitude] coordinate pairs defining the route |
color? | string | undefined | "#4285F4" | Line color as CSS color value (default: "#4285F4") |
width? | number | undefined | 3 | Line width in pixels (default: 3) |
opacity? | number | undefined | 0.8 | Line opacity from 0 to 1 (default: 0.8) |
dashArray? | [number, number] | undefined | — | Dash pattern [dash length, gap length] for dashed lines |
onClick? | (() => void) | undefined | — | Callback when the route line is clicked |
onMouseEnter? | (() => void) | undefined | — | Callback when mouse enters the route line |
onMouseLeave? | (() => void) | undefined | — | Callback when mouse leaves the route line |
interactive? | boolean | undefined | true | Whether the route is interactive - shows pointer cursor on hover (default: true) |
MapArc
TypeScript
MapArc(props: MapArcProps<T>): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
data | T[] | — | Array of arcs to render. Each arc must have a unique id. |
id? | string | undefined | — | Optional unique identifier prefix for the arc source/layers. Auto-generated if not provided. |
curvature? | number | undefined | DEFAULT_ARC_CURVATURE | How far each arc bows away from a straight line. 0 renders straight lines; higher values bend further. Negative values bend to the opposite side. Arcs are computed as a quadratic Bézier in lng/lat space and do not account for the antimeridian. (default: 0.2) |
samples? | number | undefined | DEFAULT_ARC_SAMPLES | Number of samples used to render each curve. Higher = smoother. (default: 64) |
paint? | { "line-opacity"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-opacity-transition"?: MapLibreGL.TransitionSpecification; "line-color"?: MapLibreGL.DataDrivenPropertyValueSpecification<MapLibreGL.ColorSpecification>; "line-color-transition"?: MapLibreGL.TransitionSpecification; "line-translate"?: MapLibreGL.PropertyValueSpecification<[number, number]>; "line-translate-transition"?: MapLibreGL.TransitionSpecification; "line-translate-anchor"?: MapLibreGL.PropertyValueSpecification<"map" | "viewport">; "line-width"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-width-transition"?: MapLibreGL.TransitionSpecification; "line-gap-width"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-gap-width-transition"?: MapLibreGL.TransitionSpecification; "line-offset"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-offset-transition"?: MapLibreGL.TransitionSpecification; "line-blur"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-blur-transition"?: MapLibreGL.TransitionSpecification; "line-dasharray"?: MapLibreGL.DataDrivenPropertyValueSpecification<Array<number>>; "line-dasharray-transition"?: MapLibreGL.TransitionSpecification; "line-pattern"?: MapLibreGL.DataDrivenPropertyValueSpecification<MapLibreGL.ResolvedImageSpecification>; "line-pattern-transition"?: MapLibreGL.TransitionSpecification; "line-gradient"?: MapLibreGL.ExpressionSpecification; } | undefined | — | MapLibre paint properties for the arc layer. Merged on top of sensible defaults (line-color: #4285F4, line-width: 2, line-opacity: 0.85). Any value can be a MapLibre expression for per-feature styling, every field on each arc datum (besides from/to) is exposed via ["get", ...]. |
layout? | { "line-cap"?: MapLibreGL.DataDrivenPropertyValueSpecification<"butt" | "round" | "square">; "line-join"?: MapLibreGL.DataDrivenPropertyValueSpecification<"bevel" | "round" | "miter">; "line-miter-limit"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-round-limit"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-sort-key"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; visibility?: MapLibreGL.VisibilitySpecification; } | undefined | — | MapLibre layout properties for the arc layer. Defaults to rounded joins/caps. |
hoverPaint? | { "line-opacity"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-opacity-transition"?: MapLibreGL.TransitionSpecification; "line-color"?: MapLibreGL.DataDrivenPropertyValueSpecification<MapLibreGL.ColorSpecification>; "line-color-transition"?: MapLibreGL.TransitionSpecification; "line-translate"?: MapLibreGL.PropertyValueSpecification<[number, number]>; "line-translate-transition"?: MapLibreGL.TransitionSpecification; "line-translate-anchor"?: MapLibreGL.PropertyValueSpecification<"map" | "viewport">; "line-width"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-width-transition"?: MapLibreGL.TransitionSpecification; "line-gap-width"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-gap-width-transition"?: MapLibreGL.TransitionSpecification; "line-offset"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-offset-transition"?: MapLibreGL.TransitionSpecification; "line-blur"?: MapLibreGL.DataDrivenPropertyValueSpecification<number>; "line-blur-transition"?: MapLibreGL.TransitionSpecification; "line-dasharray"?: MapLibreGL.DataDrivenPropertyValueSpecification<Array<number>>; "line-dasharray-transition"?: MapLibreGL.TransitionSpecification; "line-pattern"?: MapLibreGL.DataDrivenPropertyValueSpecification<MapLibreGL.ResolvedImageSpecification>; "line-pattern-transition"?: MapLibreGL.TransitionSpecification; "line-gradient"?: MapLibreGL.ExpressionSpecification; } | undefined | — | Paint properties applied to the arc currently under the cursor. Each key is merged into paint as a case expression keyed on per-feature hover state, so only the hovered arc changes appearance. |
onClick? | ((e: MapArcEvent<T>) => void) | undefined | — | Callback when an arc is clicked. |
onHover? | ((e: MapArcEvent<T> | null) => void) | undefined | — | Callback fired when the hovered arc changes. Receives the cursor's lng/lat at the moment of entry, and null when the cursor leaves the last hovered arc. |
interactive? | boolean | undefined | true | Whether arcs respond to mouse events (default: true). |
beforeId? | string | undefined | — | Optional MapLibre layer id to insert the arc layers before (z-order control). |
MapClusterLayer
TypeScript
MapClusterLayer(props: MapClusterLayerProps<P>): JSX.ElementProps
| Prop | Type | Default | Description |
|---|---|---|---|
data | string | import("/home/runner/work/aeontel/aeontel/node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index").FeatureCollection<import("/home/runner/work/aeontel/aeontel/node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index").Point, P> | — | GeoJSON FeatureCollection data or URL to fetch GeoJSON from |
clusterMaxZoom? | number | undefined | 14 | Maximum zoom level to cluster points on (default: 14) |
clusterRadius? | number | undefined | 50 | Radius of each cluster when clustering points in pixels (default: 50) |
clusterColors? | [string, string, string] | undefined | ["#22c55e", "#eab308", "#ef4444"] | Colors for cluster circles: [small, medium, large] based on point count (default: ["#22c55e", "#eab308", "#ef4444"]) |
clusterThresholds? | [number, number] | undefined | [100, 750] | Point count thresholds for color/size steps: [medium, large] (default: [100, 750]) |
pointColor? | string | undefined | "#3b82f6" | Color for unclustered individual points (default: "#3b82f6") |
onPointClick? | ((feature: import("/home/runner/work/aeontel/aeontel/node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index").Feature<import("/home/runner/work/aeontel/aeontel/node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index").Point, P>, coordinates: [number, number]) => void) | undefined | — | Callback when an unclustered point is clicked |
onClusterClick? | ((clusterId: number, coordinates: [number, number], pointCount: number) => void) | undefined | — | Callback when a cluster is clicked. If not provided, zooms into the cluster |
useMap
TypeScript
useMap(props: ComponentProps): JSX.Element