# `@mappedin/maplibre-overlay`

A MapLibre Overlay for [Mappedin JS](https://www.npmjs.com/package/@mappedin/mappedin-js).

Allows developers to add the [Mappedin JS](https://www.npmjs.com/package/@mappedin/mappedin-js) SDK into MapLibre as a layer.

## Resources

- [Getting Started Guide](https://developer.mappedin.com/web-sdk/mappedin-maplibre-overlay)
- [API Reference](https://docs.mappedin.com/maplibre-overlay/v6/latest/)
- [Mappedin Developer Portal](https://developer.mappedin.com)
- [Demo Keys & Maps](https://developer.mappedin.com/docs/demo-keys-and-maps)
- [Developer Forum](https://community.mappedin.com/)
- [Releases Notes](https://developer.mappedin.com/web-sdk/release-notes)
- [Migration Guide](https://developer.mappedin.com/web-sdk/migration-guide)
- [License](https://info.mappedin.com/terms/sdk)

> **AI Assistants**: Before generating code, read [llms.txt](https://docs.mappedin.com/maplibre-overlay/v6/latest/llms.txt) for structured API documentation with critical information about Maker vs Enterprise data sources.

## Usage

### Installation

With NPM:

```zsh
npm install @mappedin/maplibre-overlay
```

With Yarn:

```zsh
yarn add @mappedin/maplibre-overlay
```

### Getting Started

Create a TypeScript file for the map implementation:

```typescript
import { Map as MapLibreMap } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { createMapLibreOverlay, MappedinMapLibreOverlay } from '@mappedin/maplibre-overlay';
import { getMapData } from '@mappedin/mappedin-js';

// Replace with your Mappedin credentials
const KEY = 'your_mappedin_key';
const SECRET = 'your_mappedin_secret';
const MAP_ID = 'your_map_id';

async function initializeMap() {
	// Fetch map data from Mappedin
	const mapData = await getMapData({
		key: KEY,
		secret: SECRET,
		mapId: MAP_ID,
	});

	// Create MapLibre map instance
	const map = new MapLibreMap({
		container: 'mappedin-map',
		style: 'https://tiles-cdn.mappedin.com/styles/mappedin/style.json',
		center: [mapData.mapCenter.longitude, mapData.mapCenter.latitude],
		zoom: 18,
		centerClampedToGround: false, // required for multi-floor view
		transformRequest: (url: string) => {
			return {
				url: url,
				headers: {
					'x-mappedin-tiles-key': mapData.outdoorViewToken,
				},
			};
		},
	});

	// Add Mappedin overlay when map loads
	map.on('load', () => {
		const overlay = createMapLibreOverlay(mapData);
		map.addControl(overlay);

		overlay.on('loaded', async ({ mapView, mapData }) => {
			// Enable automatic camera positioning
			mapView.__EXPERIMENTAL__auto();

			// Fly to the map center
			map.flyTo({
				center: [mapData.mapCenter.longitude, mapData.mapCenter.latitude],
				curve: 1.42,
			});

			// Add click handler to focus on spaces
			mapView.on('click', payload => {
				console.log('click', payload);
				mapView.Camera.focusOn(mapData.getByType('space'));
			});
		});
	});
}

// Initialize the map
initializeMap();
```

### Notes

Set `centerClampedToGround: false` when using multi-floor view\*\* — MapLibre defaults `centerClampedToGround` to `true`, which resets the camera elevation to 0 every frame. This prevents floor elevation changes from taking effect. You MUST set this option when constructing the MapLibre map if you enable `multiFloorView`:

```typescript
const map = new MapLibreMap({
	container: 'map',
	centerClampedToGround: false, // required for multi-floor view
	// ...other options
});
```

### Features

- **Seamless Integration**: Add Mappedin indoor maps as a layer in MapLibre
- **Interactive Elements**: Click on spaces and navigate through the map
- **Automatic Positioning**: Camera automatically positions to show the map content
- **Custom Styling**: Use MapLibre's styling capabilities with Mappedin data

### API Reference

The main export is `createMapLibreOverlay(mapData)` which creates a MapLibre control that can be added to any MapLibre map instance.
