# ng-mapcn — full reference > Angular port of [mapcn](https://www.mapcn.dev) — composable MapLibre GL v6 map components in the spirit of shadcn/ui. Standalone, signals-first, OnPush, SSR-safe, theme-aware. Carto basemaps by default, so no API key is required. Distributed both as an npm package and as copy-paste sources via `ng add` (you own the code). Version: 22.0.0-beta.7 · License: MIT · Docs: https://ng-mapcn.vercel.app · Repository: https://github.com/juanvieiraprado99/ng-mapcn ## Installation ### Copy-paste (recommended, shadcn-style) ```bash ng add ng-mapcn ``` Adds `maplibre-gl`, registers its CSS, appends the required `.maplibregl-popup-*` overrides and copies the component sources into `src/app/components/ui/map` (customize with `--path`). ### npm package ```bash npm install ng-mapcn maplibre-gl ``` ```scss // global styles.scss @use 'ng-mapcn/src/lib/styles/index' as *; // tokens + utilities @use 'ng-mapcn/styles.scss' as *; // required popup overrides @import 'maplibre-gl/dist/maplibre-gl.css'; // MapLibre base CSS ``` The `.maplibregl-popup-*` overrides are **required** — MapLibre injects its own popup chrome, which must be neutralized for popups and tooltips to render correctly. ### Agent skill ```bash npx skills add juanvieiraprado99/ng-mapcn ``` Installs the ng-mapcn agent skill (https://github.com/juanvieiraprado99/ng-mapcn/tree/main/skills/ng-mapcn) with the [skills.sh](https://skills.sh) CLI, so coding agents use the real API: selectors, inputs, outputs, setup, recipes and troubleshooting. ## Quick start ```html São Paulo Olá! ``` ## Component anatomy Every part of the component set, and how they nest: ```html
New York
Hover content Click content
Standalone popup
``` ## Components ### Map `ng-map` The root container component that initializes MapLibre GL and provides context to child components. Automatically handles theme switching between light and dark modes. **Inputs** | Name | Type | Default | Description | |---|---|---|---| | `center` | `[number, number]` | `[0, 0]` | Initial center coordinates as [longitude, latitude]. | | `zoom` | `number` | `2` | Initial zoom level of the map. | | `styles` | `MapStylesConfig` | `CARTO` | Custom style URLs or style objects for light and dark themes. | | `blank` | `boolean` | `false` | Swaps the basemap for a transparent, tile-less canvas. Add your own layers on top. | | `projection` | `ProjectionSpecification` | — | Map projection, e.g. { type: 'globe' }. | | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Force a theme, or 'auto' to follow the dark/light class on . | | `loading` | `boolean` | `false` | Shows the loading overlay. | | `labels` | `Partial` | — | Label overrides (loading), merged over provideMapLabels() and the English defaults. | | `viewport` | `Partial` | — | Controlled viewport ({ center, zoom, bearing, pitch }). Pair with viewportChange. | | `fitBounds` | `MapFitBoundsOptions` | — | Fits the camera to bounds ({ bounds?, padding?, maxZoom?, duration?, animate? }). Without bounds it fits the union of the children's data (markers, GeoJSON, routes, arcs, clusters, heatmaps). Runs after load and refits only when the bounds change; the first fit never animates; maxZoom defaults to 16. A draggable marker bound to signals refits while dragged: pass explicit bounds for that case. Imperative form: MapContextService.fitBounds(). | | `options` | `Omit` | — | Extra MapLibre MapOptions (scrollZoom, dragRotate, …) passed to the map constructor. | **Outputs** | Name | Type | Default | Description | |---|---|---|---| | `viewportChange` | `MapViewport` | — | Emits on every viewport change (move, zoom, rotate, pitch). | | `mapReady` | `Map` | — | Emits the raw maplibre-gl Map instance once loaded. | | `mapClick` | `MapMouseEvent` | — | Emits when the map is clicked. | | `mapError` | `Error` | — | Emits when the map fails to initialize or load. | ### MapControls `ng-map-controls` Renders map control buttons: zoom, compass, locate, and fullscreen. Must be used inside ng-map. **Inputs** | Name | Type | Default | Description | |---|---|---|---| | `position` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `'bottom-right'` | Corner of the map to place the controls in. | | `showZoom` | `boolean` | `true` | Show zoom in/out buttons. | | `showCompass` | `boolean` | `false` | Show compass button (resets bearing). | | `showLocate` | `boolean` | `false` | Show geolocate button. | | `showFullscreen` | `boolean` | `false` | Show fullscreen toggle button. | | `labels` | `Partial` | — | Label overrides (zoomIn, zoomOut, resetNorth, locate, fullscreen), merged over provideMapLabels() and the English defaults. | | `className` | `string` | — | Extra space-separated classes added to the rendered .ng-controls element. Reactive; the built-in class is always kept. | **Outputs** | Name | Type | Default | Description | |---|---|---|---| | `locateChange` | `{ longitude: number; latitude: number }` | — | Emits the user position after a successful locate. | | `locateError` | `GeolocationPositionError \| Error` | — | Emits when locating fails (denied, timeout) or when the browser has no geolocation. | ### MapMarker `ng-map-marker` A container for marker-related components. Provides context for its children and handles marker positioning. **Inputs** | Name | Type | Default | Description | |---|---|---|---| | `longitude` | `number` | `required` | Longitude coordinate of the marker. | | `latitude` | `number` | `required` | Latitude coordinate of the marker. | | `draggable` | `boolean` | `false` | Allows the marker to be dragged. | | `offset` | `PointLike` | — | Pixel offset applied to the marker element. | | `rotation` | `number` | `0` | Rotation of the marker in degrees. | | `anchor` | `PositionAnchor` | — | Part of the marker element positioned at the coordinates. | | `rotationAlignment` | `'map' \| 'viewport' \| 'auto'` | `'auto'` | How the marker rotates with the map. | | `pitchAlignment` | `'map' \| 'viewport' \| 'auto'` | `'auto'` | How the marker tilts with the map pitch. | | `ariaLabel` | `string` | — | Accessible name of the marker (aria-label). Interactive markers whose content has no text fall back to labels.marker ('Map marker'); a static labelled marker gets role="img". | | `labels` | `Partial` | — | Label overrides (marker), merged over provideMapLabels() and the English defaults. | | `keyboardStep` | `number` | `10` | Pixels a draggable marker moves per arrow key press. | | `keyboardStepLarge` | `number` | `50` | Pixels per arrow key press while Shift is held. | **Outputs** | Name | Type | Default | Description | |---|---|---|---| | `markerClick` | `MouseEvent` | — | Emits when the marker is clicked, or when Enter or Space (on keyup) is pressed on the focused marker, also with ng-marker-popup. Give icon-only clickable markers their own ariaLabel. A marker with this handler becomes a role=button tab stop. | | `markerMouseEnter` | `MouseEvent` | — | Emits when the pointer enters the marker. | | `markerMouseLeave` | `MouseEvent` | — | Emits when the pointer leaves the marker. | | `dragStart` | `{ lng: number; lat: number }` | — | Emits when dragging starts. | | `drag` | `{ lng: number; lat: number }` | — | Emits continuously while dragging. | | `dragEnd` | `{ lng: number; lat: number }` | — | Emits the final position after dragging. | ### MarkerContent `ng-marker-content` Renders the visual content of a marker via content projection. If left empty, a default blue dot is rendered; it follows conditional content (shown while nothing is projected). Must be used inside ng-map-marker. **Inputs** | Name | Type | Default | Description | |---|---|---|---| | `className` | `string` | — | Extra space-separated classes added to the rendered .ng-marker-content element. Reactive; the built-in class is always kept. | ### MarkerLabel `ng-marker-label` An always-visible text label above or below the marker. Must be used inside ng-marker-content. **Inputs** | Name | Type | Default | Description | |---|---|---|---| | `position` | `'top' \| 'bottom'` | `'top'` | Side of the marker the label appears on. | ### MarkerPopup `ng-marker-popup` A popup attached to the marker that opens on click. Must be used inside ng-map-marker. Keyboard: the marker becomes a focusable role=button with aria-haspopup=dialog (unless you set them), Enter/Space opens it, focus moves into the popup, and Escape closes it, stops propagation and returns focus to the marker. Avoid your own