npm package: @plotimap/sdk
Description: A TypeScript SDK that wraps [MapLibre GL JS](https://maplibre.org/) with a high-level API for building interactive map editors and viewers.
Latest version: 0.1.1

# @plotimap/sdk

A TypeScript SDK that wraps [MapLibre GL JS](https://maplibre.org/) with a high-level API for building interactive map editors and viewers.

## Installation

```bash
npm install @plotimap/sdk maplibre-gl
```

> `maplibre-gl` is a peer dependency — install it alongside the SDK.

## Quick Start

```ts
import { PlotiMap, PlotiMapMode } from '@plotimap/sdk';

const map = new PlotiMap({
  container: 'map',                          // DOM element id or HTMLElement
  styleUrl: 'https://your-style-url.json'   // MapLibre style URL
});

map.onStyleLoaded(() => {
  console.log('Map ready');
});
```

## Constructor Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `container` | `string \| HTMLElement` | — | DOM container id or element |
| `mode` | `PlotiMapMode` | `VIEWER` | `EDITOR` or `VIEWER` |
| `styleUrl` | `string` | — | URL to a MapLibre style JSON |
| `initialStyle` | `unknown` | — | Pre-loaded style object (alternative to `styleUrl`) |

## Enums

### `PlotiMapMode`

```ts
enum PlotiMapMode {
  EDITOR = 'EDITOR',
  VIEWER = 'VIEWER',
}
```

## API Reference

### Lifecycle

```ts
// Run callback once the style is fully loaded (or immediately if already loaded)
map.onStyleLoaded(callback: () => void): void

// Get the raw MapLibre Map instance for advanced use
map.getNativeMap(): maplibregl.Map
```

---

### Layers

```ts
// List all layers in the current style
map.getLayers(): MapLayer[]

// Get all feature properties for a layer (deduped)
map.getLayerData(layerId: string): Record<string, unknown>[]

// Add a custom layer
map.addCustomLayer(config: CustomLayerConfig): void

// Remove a layer (and its source)
map.removeLayer(layerId: string): void

// Remove a layer plus all companion layers, icons, interactions, animations
map.removeLayerFull(layerId: string): void

// Reorder a layer (move before another layer)
map.moveLayer(layerId: string, beforeId?: string): void

// Set a human-readable display name stored in layer metadata
map.setLayerDisplayName(layerId: string, name: string): void

// Ensure a stroke/outline companion layer exists for a fill layer
map.ensureOutlineLayer(layerId: string): string

// Generate a unique layer/source id from a base name
map.generateUniqueId(baseName: string): string
```

#### `MapLayer`

```ts
interface MapLayer {
  id: string;
  type: string;
  sourceLayer?: string;
  visible: boolean;
  displayName: string;
}
```

#### `CustomLayerConfig`

```ts
interface CustomLayerConfig {
  id: string;
  type: 'fill' | 'line' | 'circle' | 'symbol' | 'raster' | 'heatmap';
  source: string | { type: 'geojson'; data: GeoJSON.GeoJSON };
  sourceLayer?: string;
  paint?: Record<string, unknown>;
  layout?: Record<string, unknown>;
  filter?: unknown[];
  displayName?: string;
}
```

---

### Visibility

```ts
map.setLayerVisibility(layerId: string, visible: boolean): void
map.setLayersVisibility(layerIds: string[], visible: boolean): void
```

Visibility changes automatically sync to companion `-outline` and `-labels` layers.

---

### Paint & Layout Properties

```ts
// Set a single paint property (e.g. 'fill-color', 'line-width')
map.setPaintProperty(layerId: string, property: string, value: unknown): void

// Set multiple paint properties at once
map.updateLayerPaint(layerId: string, properties: Record<string, unknown>): void

// Set a layout property (e.g. 'icon-image', 'text-field')
map.setLayoutProperty(layerId: string, property: string, value: unknown): void

// Read a style property (paint or layout)
map.getStyleProperty(layerId: string, property: string, type?: 'paint' | 'layout'): unknown
```

---

### Filters

```ts
// Apply a raw MapLibre filter expression
map.setFilter(layerId: string, filter: unknown[] | null): void

// Build and apply a filter from simple rule objects
map.applyFilterRules(
  layerId: string,
  rules: { field: string; operator: string; value: string }[]
): void
```

**Supported operators:** `==`, `!=`, `>`, `>=`, `<`, `<=`, `contains`, `not-contains`

---

### Labels

```ts
// Add or update a text label layer for a data layer
map.updateLabels(
  layerId: string,
  field: string,
  options?: {
    fontSize?: number;
    color?: string;
    haloColor?: string;
    haloWidth?: number;
    placement?: 'center' | 'line';
    offset?: [number, number];
  }
): void

// Remove the label layer for a data layer
map.removeLabels(layerId: string): void

// Style base-map label groups (road labels, place labels, water labels)
map.setGroupLabelStyle(
  groupId: 'roadLabels' | 'placeLabels' | 'globalNames',
  color: string,
  haloColor: string,
  haloWidth: number
): void
```

---

### Sources & Assets

```ts
// Add a GeoJSON or CSV asset as a map source; returns the source id
map.addSourceFromAsset(asset: Asset): string

// Check if a source for the given asset id already exists
map.hasAssetSource(assetId: string): boolean
```

---

### Icon Maps

```ts
// Upload an SVG string as a named icon sprite; returns the sprite id
map.uploadIcon(
  layerId: string,
  ruleId: string,
  svgString: string,
  color: string,
  size?: number
): Promise<string>

// Apply a data-driven icon expression (MapLibre `case` expression)
map.setIconMapExpression(
  layerId: string,
  rules: Array<{ field: string; value: string; spriteId: string; size: number }>,
  defaultSpriteId: string,
  defaultSize: number
): void

// Remove all icon sprites registered for a layer
map.removeLayerIcons(layerId: string): void
```

---

### Interactions (Popups & Tooltips)

```ts
// Enable/disable click popups and hover tooltips for a layer
map.updateInteraction(layerId: string, config: InteractionConfig): void

// Remove all interactions from a layer
map.removeInteraction(layerId: string): void

// Rebind all stored interactions (call after style reload)
map.rebindInteractions(): void
```

#### `InteractionConfig`

```ts
interface InteractionConfig {
  popup: { enabled: boolean; fields: string[] };
  tooltip: { enabled: boolean; fields: string[] };
}
```

---

### Timeline Animation

```ts
// Apply a snapshot filter for a specific time value
map.applyTimelineFilter(
  layerId: string,
  timeField: string,
  value: number | string
): void

// Start a looping animation over time values
map.startAnimation(
  layerId: string,
  timeField: string,
  values: (number | string)[],
  intervalMs: number,
  onTick: (value: number | string, index: number) => void
): void

// Stop animation for a single layer
map.stopAnimation(layerId: string): void

// Stop all running animations
map.stopAllAnimations(): void
```

---

### 3D & Terrain

```ts
// Add 3D building extrusion layer
map.add3DBuildings(): void
map.remove3DBuildings(): void
map.has3DBuildings(): boolean

// Enable/disable terrain (requires a terrain source in the style)
map.enableTerrain(exaggeration?: number): void  // default exaggeration: 1.5
map.disableTerrain(): void

// Enable height extrusion on a fill layer
map.enableExtrusion(
  layerId: string,
  heightField: string,
  heightScale?: number,
  color?: string,
  opacity?: number
): void
map.disableExtrusion(layerId: string, opacity?: number): void
```

---

### Visual Adjustments

```ts
map.setSaturation(value: number): void    // 0–200, default 100
map.setBrightness(value: number): void    // 0–200, default 100
map.setLightIntensity(intensity: number): void
map.setLightDirection(azimuth: number): void
map.resetVisualFilters(): void
map.getLightProperties(): { intensity: number; position: number[] }
map.getSaturation(): number
map.getBrightness(): number
```

---

### Camera

```ts
// Fly to a location
map.goTo(lng: number, lat: number, zoom?: number): void

// Jump instantly to a camera position (no animation)
map.jumpToCamera(lng: number, lat: number, zoom: number, pitch?: number): void

// Set map pitch (tilt)
map.setPitch(pitch: number): void

// Add a marker at a location
map.addMarker(lng: number, lat: number, element?: HTMLElement): void

// Get current viewport corners as coordinates
map.getViewBoundsAsCoordinates(): number[][]
```

---

### Style Management

```ts
// Replace the entire map style
map.setStyle(style: unknown): void

// Export the current style as a plain object
map.exportStyle(): unknown

// Export the current style as a JSON string (with layer configs embedded in metadata)
map.getStyleDefinition(): string

// Embed layer configs to be included on next getStyleDefinition call
map.setLayerConfigs(configs: Record<string, LayerConfigEntry>): void
```

---

### Image / Raster Layers

```ts
// Enable drag-to-reposition for a raster image layer
map.enableImageMove(
  sourceId: string,
  layerId: string,
  onChange?: (coords: number[][]) => void
): void
map.disableImageMove(): void
map.isImageMoveActive(): boolean

// Enable georeferencing (4-corner drag handles)
map.enableGeoreferencing(
  sourceId: string,
  layerId: string,
  initialCoords?: number[][],
  onChange?: (coords: number[][]) => void
): void
map.disableGeoreferencing(): void
map.isGeoreferencingActive(): boolean

// Update image source coordinates directly
map.updateImageCoordinates(sourceId: string, coordinates: number[][]): void
map.getImageCoordinates(sourceId: string): number[][] | null
```

---

### Corner Radius (Polygon Smoothing)

```ts
// Apply Chaikin curve smoothing to a polygon fill layer
map.setCornerRadius(layerId: string, enabled: boolean, factor: number): Promise<void>

// Rebind corner radius on all configured layers (call after style reload)
map.rebindCornerRadius(): Promise<void>
```

---

### Export

```ts
// Export the current map view as a PNG File
map.exportImage(options: {
  width?: number;
  height?: number;
  fileName?: string;
}): Promise<File>

// Export a low-resolution thumbnail as a File
map.exportThumbnail(): File | null
```

---

### Rebind Helpers

Call these after reloading the map style to restore all dynamic state:

```ts
map.rebindInteractions(): void
map.rebindFiltersAndLabels(): void
map.rebindIconMaps(): Promise<void>
map.rebindCornerRadius(): Promise<void>
```

---

## Exported Types

```ts
export { PlotiMap, PlotiMapMode }
export type { MapLayer, CustomLayerConfig, InteractionConfig }

// Asset types
export { AssetType }
export type { Asset, AssetListResponse }

// Base layer group utilities
export { LAYER_GROUPS, deriveBaseLayerGroups }
export type { BaseLayerGroup }
```

## License

MIT