# @mapmap/react-native reference

> Generated from the published **@mapmap/react-native 0.4.0** type declarations by `website/scripts/sdk-reference.mjs`. Do not edit by hand: change the JSDoc in the package, or the examples in `website/content/sdk-reference/react-native.examples.md`, and regenerate.

Every public export of the React Native and Expo module: the navigation bridge, its pure-TypeScript mock, events and custom regions. The guide, with native setup for each platform, is [React Native in SDKs & installation](/docs/sdks#react-native-mapmapreact-native).

```bash
npm install @mapmap/react-native@0.4.0
```

Other SDK references: [@mapmap/maps](/docs/maps-reference), [@mapmap/points](/docs/points-reference), [@mapmap/core](/docs/core-reference), [@mapmap/tile](/docs/tile-reference), [@mapmap/voice](/docs/voice-reference), [MapMapKit](/docs/ios-reference), [ai.mapmap:core](/docs/android-reference).

59 exports across 1 entry point: 2 classes, 11 functions, 2 interfaces, 42 types, 2 constants.

## How to read this page

Each entry gives the declaration as published, the JSDoc description, and a table of parameters or properties with their types. The **Default** column quotes the default the source states (an `@default` tag or a "Default ..." sentence in the JSDoc). "required" means the property must be given; "not stated" means the source gives no default, so none is claimed here. Classes, factories and the main entry functions each carry a minimal example; examples marked *from the source* are the package's own `@example`.

## Contents

- [`@mapmap/react-native`](#mapmapreact-native): 59 exports

## `@mapmap/react-native`

```ts
import { /* … */ } from "@mapmap/react-native";
```

### Classes (@mapmap/react-native)

[`CustomRegionError`](#customregionerror), [`MapmapNavMock`](#mapmapnavmock)

#### `CustomRegionError`

*Class*

```ts
class CustomRegionError extends Error { … }
```

A rejected custom-region call.

Extends `Error`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `readonly code` | [`CustomRegionErrorCode`](#customregionerrorcode) |  |  |
| `readonly status?` | `number` |  | HTTP status, when the gateway answered. |
| `readonly problem?` | `string` |  | Problem type slug, e.g. `region-area-too-large` or `region-crosses-territories`. |
| `readonly limit?` | `number` |  | The limit exceeded, for limit refusals. |
| `readonly value?` | `number` |  | The request's value against `limit`. |

**Constructor and methods**

- `constructor(code: CustomRegionErrorCode, message: string, extra?: { status?: number; problem?: string; limit?: number; value?: number; })`

**Example**

```ts
import { CustomRegionError, createCustomRegionClient } from "@mapmap/react-native";

const regions = createCustomRegionClient({ apiKey: "snk_…" });
try {
  await regions.requestAndWait({ bbox: [-5, 50, 2, 55] });
} catch (err) {
  if (err instanceof CustomRegionError && err.code === "E_REGION_REFUSED") {
    console.log(err.problem, err.limit, err.value); // e.g. region-area-too-large
  } else {
    throw err;
  }
}
```

#### `MapmapNavMock`

*Class*

```ts
class MapmapNavMock extends SimpleEventEmitter<MapmapNavEvents> implements MapmapNavModule { … }
```

Extends `SimpleEventEmitter<MapmapNavEvents>`.

Implements [`MapmapNavModule`](#mapmapnavmodule).

**Constructor and methods**

- `constructor(options?: MapmapNavMockOptions)`
- `init(_apiKey: string, _gatewayBaseUrl?: string): Promise<void>`
- `listAvailableTerritories(): Promise<TerritorySummary[]>`
- `listInstalledTerritories(): Promise<TerritoryInfo[]>`
- `installTerritory(territoryId: string): Promise<void>`
- `installCustomRegion(region: CustomRegionInstall): Promise<void>`: Simulates installing a custom region: the same phased progress as installTerritory, and the region appears as an installed, active territory. Validates the id shape the gateway issues (`region-` + 16 hex) so UI code is exercised against real ids.
- `cancelTerritoryInstall(territoryId: string): Promise<void>`
- `removeTerritory(territoryId: string): Promise<void>`
- `getTerritoryStyle(territoryId: string, theme: "light" | "dark"): Promise<string>`
- `search(query: string, near?: LatLng, limit?: number): Promise<SearchResult[]>`
- `computeRoute(request: RouteRequest): Promise<RouteResult>`
- `startGuidance(options: GuidanceOptions): Promise<void>`
- `stopGuidance(): Promise<void>`
- `setVoiceMuted(muted: boolean): Promise<void>`
- `setVoiceVolume(volume: number): Promise<void>`

**Example**

```ts
import { MapmapNavMock } from "@mapmap/react-native";

// The pure-TS stand-in for the native module, with the same API and events.
const nav = new MapmapNavMock({ territoryInstallDurationMs: 1000 });
await nav.init("snk_…");
nav.addListener("territoryProgress", (event) => console.log(event));
await nav.installTerritory("gb");
```

### Functions (@mapmap/react-native)

[`addBridgeErrorListener`](#addbridgeerrorlistener), [`addGuidanceListener`](#addguidancelistener), [`addTerritoryProgressListener`](#addterritoryprogresslistener), [`addVoiceStateListener`](#addvoicestatelistener), [`createCustomRegionClient`](#createcustomregionclient), [`createMapmapNavMock`](#createmapmapnavmock), [`getMapmapNav`](#getmapmapnav), [`installCustomRegion`](#installcustomregion), [`parseBoundaryCandidate`](#parseboundarycandidate), [`parseBoundaryFeature`](#parseboundaryfeature), [`parseCustomRegion`](#parsecustomregion)

#### `addBridgeErrorListener`

*Function*

```ts
function addBridgeErrorListener(handle: MapmapNavEmitterLike<MapmapNavEvents>, listener: (event: BridgeError) => void): EventSubscription;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `MapmapNavEmitterLike<MapmapNavEvents>` | required |  |
| `listener` | `(event: BridgeError) => void` | required |  |

Options and types: [`MapmapNavEmitterLike`](#mapmapnavemitterlike), [`MapmapNavEvents`](#mapmapnavevents), [`BridgeError`](#bridgeerror).

#### `addGuidanceListener`

*Function*

```ts
function addGuidanceListener(handle: MapmapNavEmitterLike<MapmapNavEvents>, listener: (event: GuidanceEvent) => void): EventSubscription;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `MapmapNavEmitterLike<MapmapNavEvents>` | required |  |
| `listener` | `(event: GuidanceEvent) => void` | required |  |

Options and types: [`MapmapNavEmitterLike`](#mapmapnavemitterlike), [`MapmapNavEvents`](#mapmapnavevents), [`GuidanceEvent`](#guidanceevent).

#### `addTerritoryProgressListener`

*Function*

```ts
function addTerritoryProgressListener(handle: MapmapNavEmitterLike<MapmapNavEvents>, listener: (event: TerritoryProgressEvent) => void): EventSubscription;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `MapmapNavEmitterLike<MapmapNavEvents>` | required |  |
| `listener` | `(event: TerritoryProgressEvent) => void` | required |  |

Options and types: [`MapmapNavEmitterLike`](#mapmapnavemitterlike), [`MapmapNavEvents`](#mapmapnavevents), [`TerritoryProgressEvent`](#territoryprogressevent).

#### `addVoiceStateListener`

*Function*

```ts
function addVoiceStateListener(handle: MapmapNavEmitterLike<MapmapNavEvents>, listener: (event: VoiceStateEvent) => void): EventSubscription;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `MapmapNavEmitterLike<MapmapNavEvents>` | required |  |
| `listener` | `(event: VoiceStateEvent) => void` | required |  |

Options and types: [`MapmapNavEmitterLike`](#mapmapnavemitterlike), [`MapmapNavEvents`](#mapmapnavevents), [`VoiceStateEvent`](#voicestateevent).

#### `createCustomRegionClient`

*Function*

```ts
function createCustomRegionClient(options: CustomRegionClientOptions): CustomRegionClient;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `options` | [`CustomRegionClientOptions`](#customregionclientoptions) | required |  |

Options and types: [`CustomRegionClientOptions`](#customregionclientoptions).

**Example**

```ts
import { createCustomRegionClient, getMapmapNav, installCustomRegion } from "@mapmap/react-native";

const regions = createCustomRegionClient({ apiKey: "snk_…" });
const region = await regions.requestAndWait({ bbox: [-2.65, 51.42, -2.53, 51.49] });
const nav = getMapmapNav(false);
await nav.init("snk_…");
await installCustomRegion(nav, region); // a CustomRegion carries what the install needs
```

#### `createMapmapNavMock`

*Function*

```ts
function createMapmapNavMock(options?: MapmapNavMockOptions): MapmapNavMock;
```

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `options?` | [`MapmapNavMockOptions`](#mapmapnavmockoptions) | not stated |  |

Options and types: [`MapmapNavMockOptions`](#mapmapnavmockoptions).

**Example**

```ts
import { createMapmapNavMock } from "@mapmap/react-native";

const nav = createMapmapNavMock({ tickIntervalMs: 500, simulateReroute: false });
await nav.init("snk_…");
console.log(await nav.listAvailableTerritories());
```

#### `getMapmapNav`

*Function*

```ts
function getMapmapNav(useMock: boolean, mockOptions?: MapmapNavMockOptions): MapmapNavHandle;
```

Resolves either the real native-backed module or the pure-TS mock.
Pass `useMock: true` in Expo Go, unit tests, and any UI work happening
ahead of a native build.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `useMock` | `boolean` | required |  |
| `mockOptions?` | [`MapmapNavMockOptions`](#mapmapnavmockoptions) | not stated |  |

Options and types: [`MapmapNavMockOptions`](#mapmapnavmockoptions).

**Example**

```ts
import { getMapmapNav } from "@mapmap/react-native";

// useMock: true in Expo Go, unit tests and UI work ahead of a native build.
const nav = getMapmapNav(false);
await nav.init("snk_…");
const sub = nav.addListener("guidance", (event) => console.log(event));
const { routes } = await nav.computeRoute({
  profile: "car",
  origin: { latitude: 51.5072, longitude: -0.1276 },
  destination: { latitude: 51.4545, longitude: -2.5879 },
});
console.log(routes.length);
await nav.startGuidance({ routeIndex: 0, source: { kind: "live" } });
sub.remove();
```

#### `installCustomRegion`

*Function*

```ts
function installCustomRegion(nav: MapmapNavModule, region: CustomRegionInstall): Promise<void>;
```

Install (or update) a custom region through the native core, which
verifies the region index, manifest and every layer against the pinned
REGION key, then activates it. Same `territoryProgress` events and
`cancelTerritoryInstall` as `installTerritory`. Call it again after a
re-cut (same `territoryId`, newer `version`) to update.

Rejects `E_TERRITORY_NOT_FOUND` for an id that is not a custom region, and
`E_INTERNAL` naming the gap on a native build that predates custom regions
(README, "Custom regions"), rather than throwing an opaque
"is not a function".

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `nav` | [`MapmapNavModule`](#mapmapnavmodule) | required |  |
| `region` | [`CustomRegionInstall`](#customregioninstall) | required |  |

Options and types: [`MapmapNavModule`](#mapmapnavmodule), [`CustomRegionInstall`](#customregioninstall).

**Example**

```ts
import { createCustomRegionClient, getMapmapNav, installCustomRegion } from "@mapmap/react-native";

const nav = getMapmapNav(false);
await nav.init("snk_…");
const regions = createCustomRegionClient({ apiKey: "snk_…" });
const [county] = await regions.searchBoundaries({ q: "Rutland" });
if (county) {
  const region = await regions.requestAndWait({ boundaryId: county.boundaryId });
  await installCustomRegion(nav, region); // verified against the pinned key, then activated
}
```

#### `parseBoundaryCandidate`

*Function*

```ts
function parseBoundaryCandidate(raw: Json): BoundaryCandidate;
```

Maps one gateway boundary (snake_case) onto `BoundaryCandidate`.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `raw` | `Json` | required |  |

#### `parseBoundaryFeature`

*Function*

```ts
function parseBoundaryFeature(raw: Json): BoundaryFeature;
```

Maps a gateway boundary Feature onto `BoundaryFeature`.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `raw` | `Json` | required |  |

#### `parseCustomRegion`

*Function*

```ts
function parseCustomRegion(raw: Json): CustomRegion;
```

Maps the gateway's snake_case result onto `CustomRegion`.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `raw` | `Json` | required |  |

### Interfaces (@mapmap/react-native)

[`MapmapNavEmitterLike`](#mapmapnavemitterlike), [`MapmapNavModule`](#mapmapnavmodule)

#### `MapmapNavEmitterLike`

*Interface*

```ts
interface MapmapNavEmitterLike<Events extends EventsMap>
```

Structural shape both the real native module and `MapmapNavMock` satisfy.

**Methods**

- `addListener<K extends keyof Events>(eventName: K, listener: Events[K]): EventSubscription`
- `removeAllListeners?(eventName: keyof Events): void`

#### `MapmapNavModule`

*Interface*

```ts
interface MapmapNavModule
```

**Methods**

- `init(apiKey: string, gatewayBaseUrl?: string): Promise<void>`: Load the native core and remember the API key + gateway base. Idempotent. Everything else rejects E_NOT_INITIALISED before this.
- `listAvailableTerritories(): Promise<TerritorySummary[]>`
- `listInstalledTerritories(): Promise<TerritoryInfo[]>`
- `installTerritory(territoryId: string): Promise<void>`: Resolves when active; emits territoryProgress throughout. Rejects E_CANCELLED after a "cancelled" progress event when cancelTerritoryInstall(territoryId) is called while it is in flight.
- `cancelTerritoryInstall(territoryId: string): Promise<void>`: Stop an in-flight installTerritory(territoryId). The pending install emits a "cancelled" territoryProgress event and rejects E_CANCELLED; nothing partial is kept on disk and any previously installed version of the territory is untouched. Resolves immediately, and is a no-op when no install of that territory is running.
- `removeTerritory(territoryId: string): Promise<void>`
- `getTerritoryStyle(territoryId: string, theme: "light" | "dark"): Promise<string>`: Complete MapLibre style JSON (string) for the installed territory, every source pointing at LOCAL data, renders with radios off.
- `installCustomRegion?(region: CustomRegionInstall): Promise<void>`: Install (or update) a custom region from its own signed channel. Same progress events, cancellation and verify-then-promote as installTerritory; the core verifies against the pinned REGION key, which it accepts for `region-` ids only. Implemented by both native bridges from 0.4.0 and by the mock. Optional in the type so that the `installCustomRegion(nav, region)` helper can name the gap (E_INTERNAL) on an older native build instead of failing with "is not a function".
- `search(query: string, near?: LatLng, limit?: number): Promise<SearchResult[]>`
- `computeRoute(request: RouteRequest): Promise<RouteResult>`
- `startGuidance(options: GuidanceOptions): Promise<void>`
- `stopGuidance(): Promise<void>`
- `setVoiceMuted(muted: boolean): Promise<void>`
- `setVoiceVolume(volume: number): Promise<void>`

### Types (@mapmap/react-native)

[`AbortSignalLike`](#abortsignallike), [`BannerInstruction`](#bannerinstruction), [`BoundaryCandidate`](#boundarycandidate), [`BoundaryFeature`](#boundaryfeature), [`BoundarySearch`](#boundarysearch), [`BridgeError`](#bridgeerror), [`BridgeErrorCode`](#bridgeerrorcode), [`CustomRegion`](#customregion), [`CustomRegionBoundary`](#customregionboundary), [`CustomRegionClient`](#customregionclient), [`CustomRegionClientOptions`](#customregionclientoptions), [`CustomRegionErrorCode`](#customregionerrorcode), [`CustomRegionInstall`](#customregioninstall), [`CustomRegionJob`](#customregionjob), [`CustomRegionJobStatus`](#customregionjobstatus), [`CustomRegionLayer`](#customregionlayer), [`CustomRegionLayerInfo`](#customregionlayerinfo), [`CustomRegionRequest`](#customregionrequest), [`FetchLike`](#fetchlike), [`GuidanceEvent`](#guidanceevent), [`GuidanceOptions`](#guidanceoptions), [`LatLng`](#latlng), [`LocationSource`](#locationsource), [`Maneuver`](#maneuver), [`ManeuverType`](#maneuvertype), [`MapmapNavEvents`](#mapmapnavevents), [`MapmapNavHandle`](#mapmapnavhandle), [`MapmapNavMockOptions`](#mapmapnavmockoptions), [`NativeMapmapNavModule`](#nativemapmapnavmodule), [`Position`](#position), [`RegionPolygon`](#regionpolygon), [`Route`](#route), [`RouteProfile`](#routeprofile), [`RouteRequest`](#routerequest), [`RouteResult`](#routeresult), [`SearchResult`](#searchresult), [`TerritoryInfo`](#territoryinfo), [`TerritoryPhase`](#territoryphase), [`TerritoryProgressEvent`](#territoryprogressevent), [`TerritorySummary`](#territorysummary), [`VoiceStateEvent`](#voicestateevent), [`WaitOptions`](#waitoptions)

#### `AbortSignalLike`

*Type*

```ts
type AbortSignalLike = {
    readonly aborted: boolean;
    addEventListener(type: "abort", listener: () => void): void;
    removeEventListener(type: "abort", listener: () => void): void;
};
```

The minimum of `AbortSignal` this client needs.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `readonly aborted` | `boolean` | required |  |

**Methods**

- `addEventListener(type: "abort", listener: () => void): void`
- `removeEventListener(type: "abort", listener: () => void): void`

#### `BannerInstruction`

*Type*

```ts
type BannerInstruction = {
    primary: string;
    secondary?: string;
    maneuverType: ManeuverType;
    roundaboutExit?: number;
    thenPrimary?: string;
    thenManeuverType?: ManeuverType;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `primary` | `string` | required |  |
| `secondary?` | `string` | not stated |  |
| `maneuverType` | [`ManeuverType`](#maneuvertype) | required |  |
| `roundaboutExit?` | `number` | not stated |  |
| `thenPrimary?` | `string` | not stated | The instruction after this one, when imminent; for the "Then ↰" chip. |
| `thenManeuverType?` | [`ManeuverType`](#maneuvertype) | not stated |  |

#### `BoundaryCandidate`

*Type*

```ts
type BoundaryCandidate = {
    boundaryId: string;
    name: string;
    nameEn?: string;
    adminLevel: number;
    country?: string;
    isoCode?: string;
    areaKm2: number;
    bbox: [number, number, number, number];
    territory: string;
    containsNear?: boolean;
    distanceKm?: number;
};
```

One administrative boundary from `searchBoundaries`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `boundaryId` | `string` | required | Stable id: pass it as a custom region's `boundaryId`. |
| `name` | `string` | required |  |
| `nameEn?` | `string` | not stated |  |
| `adminLevel` | `number` | required |  |
| `country?` | `string` | not stated |  |
| `isoCode?` | `string` | not stated |  |
| `areaKm2` | `number` | required | Area of the stored polygon: the figure the custom-region area limit applies to. |
| `bbox` | `[number, number, number, number]` | required |  |
| `territory` | `string` | required | The territory dataset it came from (e.g. `"uk"`). |
| `containsNear?` | `boolean` | not stated | Only when searched `near` a point. |
| `distanceKm?` | `number` | not stated | Only when searched `near` a point: km to its bounding box, 0 inside it. |

#### `BoundaryFeature`

*Type*

```ts
type BoundaryFeature = BoundaryCandidate & {
    geometry: RegionPolygon;
    simplification: {
        method: string;
        toleranceDeg: number;
        toleranceM: number;
        vertices: number;
        sourceVertices: number;
    };
    dataUpdated: string;
    licence: string;
    attribution: string;
};
```

One boundary with its polygon, from `getBoundary`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `geometry` | [`RegionPolygon`](#regionpolygon) | required | The stored polygon (accepted as is as a custom region's `polygon`). |
| `simplification` | `{ method: string; toleranceDeg: number; toleranceM: number; vertices: number; sourceVertices: number; }` | required |  |
| `dataUpdated` | `string` | required |  |
| `licence` | `string` | required |  |
| `attribution` | `string` | required |  |

#### `BoundarySearch`

*Type*

```ts
type BoundarySearch = {
    q?: string;
    near?: {
        lat: number;
        lon: number;
    };
    level?: number | number[];
    country?: string;
    limit?: number;
};
```

What to look for in `searchBoundaries`. At least one of `q` and `near`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `q?` | `string` | not stated | A name, matched from the start of each word, case and accents folded ("camden", "mosc"). |
| `near?` | `{ lat: number; lon: number; }` | not stated | With `q`: nearest first. Without `q`: exactly the boundaries whose polygon contains the point, coarsest level first. |
| `level?` | `number \| number[]` | not stated | OSM admin_level(s), 2 to 10 (2 country, 4 region, 5 to 8 county/district/borough, 9-10 parish). |
| `country?` | `string` | not stated | ISO 3166-1 alpha-2 country, e.g. `"GB"`. |
| `limit?` | `number` | not stated | 1 to 50; default 10. |

#### `BridgeError`

*Type*

```ts
type BridgeError = {
    code: BridgeErrorCode;
    message: string;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `code` | [`BridgeErrorCode`](#bridgeerrorcode) | required |  |
| `message` | `string` | required |  |

#### `BridgeErrorCode`

*Type*

```ts
type BridgeErrorCode = "E_NOT_INITIALISED" | "E_INIT_FAILED" | "E_NETWORK" | "E_AUTH" | "E_TERRITORY_ALLOWANCE" | "E_TERRITORY_VERIFY" | "E_TERRITORY_NOT_FOUND" | "E_NO_TERRITORY" | "E_NO_ROUTE" | "E_GUIDANCE_ACTIVE" | "E_NO_GUIDANCE" | "E_REPLAY_CORPUS" | "E_CANCELLED" | "E_INTERNAL";
```

Stable machine-readable codes carried on every rejected promise.

#### `CustomRegion`

*Type*

```ts
type CustomRegion = CustomRegionInstall & {
    version: string;
    displayName: string;
    bbox: [number, number, number, number];
    areaKm2: number;
    sourceTerritory: string;
    sourceVersion: string;
    dataUpdated: string;
    layers: CustomRegionLayerInfo[];
    installedBytes: number;
    downloadBytes: number;
    overlappingTerritories: string[];
    cached: boolean;
    boundary?: CustomRegionBoundary;
};
```

A published custom region, ready to install.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `version` | `string` | required |  |
| `displayName` | `string` | required |  |
| `bbox` | `[number, number, number, number]` | required |  |
| `areaKm2` | `number` | required |  |
| `sourceTerritory` | `string` | required |  |
| `sourceVersion` | `string` | required |  |
| `dataUpdated` | `string` | required | ISO date of the OpenStreetMap data. |
| `layers` | [`CustomRegionLayerInfo[]`](#customregionlayerinfo) | required |  |
| `installedBytes` | `number` | required |  |
| `downloadBytes` | `number` | required |  |
| `overlappingTerritories` | `string[]` | required | Territories whose bounding boxes also overlap the area; their data is NOT in the cut. |
| `cached` | `boolean` | required | True when the gateway answered from an earlier cut (free). |
| `boundary?` | [`CustomRegionBoundary`](#customregionboundary) | not stated | Set when the region was requested by `boundaryId`. |

#### `CustomRegionBoundary`

*Type*

```ts
type CustomRegionBoundary = {
    boundaryId: string;
    name: string;
    nameEn?: string;
    adminLevel: number;
    country?: string;
    simplificationToleranceDeg: number;
    dataUpdated: string;
};
```

The boundary a region was cut by, when it was requested by `boundaryId`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `boundaryId` | `string` | required |  |
| `name` | `string` | required |  |
| `nameEn?` | `string` | not stated |  |
| `adminLevel` | `number` | required |  |
| `country?` | `string` | not stated |  |
| `simplificationToleranceDeg` | `number` | required | Douglas-Peucker tolerance of the polygon that was cut, degrees. |
| `dataUpdated` | `string` | required | ISO date of the OpenStreetMap boundary data. |

#### `CustomRegionClient`

*Type*

```ts
type CustomRegionClient = {
    requestCustomRegion(request: CustomRegionRequest, signal?: AbortSignalLike): Promise<CustomRegionJob>;
    getCustomRegionJob(jobId: string, signal?: AbortSignalLike): Promise<CustomRegionJob>;
    waitForCustomRegion(jobId: string, options?: WaitOptions): Promise<CustomRegion>;
    requestAndWait(request: CustomRegionRequest, options?: WaitOptions): Promise<CustomRegion>;
    searchBoundaries(search: BoundarySearch, signal?: AbortSignalLike): Promise<BoundaryCandidate[]>;
    getBoundary(boundaryId: string, signal?: AbortSignalLike): Promise<BoundaryFeature>;
};
```

A client for the custom-region job lane.

**Methods**

- `requestCustomRegion(request: CustomRegionRequest, signal?: AbortSignalLike): Promise<CustomRegionJob>`: Submit a cut. Resolves with the queued job (or an already-finished one for a cached area).
- `getCustomRegionJob(jobId: string, signal?: AbortSignalLike): Promise<CustomRegionJob>`: Read a job once (free: polling costs no units).
- `waitForCustomRegion(jobId: string, options?: WaitOptions): Promise<CustomRegion>`: Poll a job until it finishes; resolves with the region or rejects `E_REGION_FAILED`.
- `requestAndWait(request: CustomRegionRequest, options?: WaitOptions): Promise<CustomRegion>`: `requestCustomRegion` then `waitForCustomRegion`.
- `searchBoundaries(search: BoundarySearch, signal?: AbortSignalLike): Promise<BoundaryCandidate[]>`: Find administrative boundaries (countries to parishes) by name and/or point, to request a region by `boundaryId`. One unit per call.
- `getBoundary(boundaryId: string, signal?: AbortSignalLike): Promise<BoundaryFeature>`: One boundary with its simplified polygon and the tolerance it was simplified at. One unit.

#### `CustomRegionClientOptions`

*Type*

```ts
type CustomRegionClientOptions = {
    apiKey: string;
    gatewayBaseUrl?: string;
    fetch?: FetchLike;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `apiKey` | `string` | required |  |
| `gatewayBaseUrl?` | `string` | `https://api.mapmap.ai` | Gateway base, no trailing slash. Default `https://api.mapmap.ai`. |
| `fetch?` | [`FetchLike`](#fetchlike) | Transport; defaults to the global `fetch` | Transport; defaults to the global `fetch`. |

#### `CustomRegionErrorCode`

*Type*

```ts
type CustomRegionErrorCode = "E_REGION_REFUSED" | "E_REGION_INVALID" | "E_REGION_FAILED" | "E_REGION_TIMEOUT" | "E_REGIONS_NOT_ENABLED" | "E_BOUNDARIES_NOT_ENABLED" | "E_NOT_FOUND" | "E_AUTH" | "E_QUOTA" | "E_CANCELLED" | "E_NETWORK";
```

Stable codes on a rejected custom-region call.

#### `CustomRegionInstall`

*Type*

```ts
type CustomRegionInstall = {
    territoryId: string;
    indexUrl: string;
    indexSigUrl: string;
};
```

What the bridge needs to install a custom region: the `region-…` id and
where its signed one-territory channel index lives. The job result of
`POST /v1/jobs/territory` carries all three (see `customRegions.ts`).

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `territoryId` | `string` | required |  |
| `indexUrl` | `string` | required |  |
| `indexSigUrl` | `string` | required |  |

#### `CustomRegionJob`

*Type*

```ts
type CustomRegionJob = {
    id: string;
    status: CustomRegionJobStatus;
    resultUrl: string;
    unitsCharged: number;
    refunded: boolean;
    error?: string;
    region?: CustomRegion;
};
```

The job as `GET /v1/jobs/{id}` reports it.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | required |  |
| `status` | [`CustomRegionJobStatus`](#customregionjobstatus) | required |  |
| `resultUrl` | `string` | required |  |
| `unitsCharged` | `number` | required |  |
| `refunded` | `boolean` | required |  |
| `error?` | `string` | not stated | Set once `status === "failed"`. |
| `region?` | [`CustomRegion`](#customregion) | not stated | Set once `status === "succeeded"`. |

#### `CustomRegionJobStatus`

*Type*

```ts
type CustomRegionJobStatus = "queued" | "running" | "succeeded" | "failed";
```

#### `CustomRegionLayer`

*Type*

```ts
type CustomRegionLayer = "valhalla-tiles" | "pmtiles" | "geocode-index" | "style";
```

Layer kinds a custom region can carry. Default: all four.

#### `CustomRegionLayerInfo`

*Type*

```ts
type CustomRegionLayerInfo = {
    kind: string;
    installedBytes: number;
    downloadBytes: number;
};
```

One layer of a cut region.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `kind` | `string` | required |  |
| `installedBytes` | `number` | required |  |
| `downloadBytes` | `number` | required | Bytes on the wire: what the download allowance meters. |

#### `CustomRegionRequest`

*Type*

```ts
type CustomRegionRequest = ({
    bbox: [west: number, south: number, east: number, north: number];
    polygon?: never;
    boundaryId?: never;
} | {
    polygon: RegionPolygon;
    bbox?: never;
    boundaryId?: never;
} | {
    boundaryId: string;
    bbox?: never;
    polygon?: never;
}) & {
    layers?: CustomRegionLayer[];
    source?: string;
    webhookUrl?: string;
};
```

What to cut. Exactly one of `bbox`, `polygon` and `boundaryId`.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `layers?` | [`CustomRegionLayer[]`](#customregionlayer) | not stated | Layers to carry; `style` needs `pmtiles`. Omit for all four. |
| `source?` | `string` | not stated | Territory to cut from (e.g. `"uk"`). Omit to let the gateway choose. |
| `webhookUrl?` | `string` | not stated | HTTPS target for the job lane's signed completion webhook. |

#### `FetchLike`

*Type*

```ts
type FetchLike = (url: string, init: {
    method: string;
    headers: Record<string, string>;
    body?: string;
    signal?: AbortSignalLike;
}) => Promise<{
    status: number;
    text(): Promise<string>;
}>;
```

The minimum of `fetch` this client needs (React Native's global fetch fits).

#### `GuidanceEvent`

*Type*

```ts
type GuidanceEvent = {
    state: "navigating" | "rerouting" | "arrived";
    location: LatLng & {
        bearingDegrees: number;
        speedMps: number;
    };
    banner?: BannerInstruction;
    distanceToManeuverMeters: number;
    remainingDistanceMeters: number;
    remainingDurationSeconds: number;
    etaEpochMs: number;
    isOffRoute: boolean;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `state` | `"navigating" \| "rerouting" \| "arrived"` | required |  |
| `location` | `LatLng & { bearingDegrees: number; speedMps: number; }` | required | Snapped position for the puck + chase camera. |
| `banner?` | [`BannerInstruction`](#bannerinstruction) | not stated |  |
| `distanceToManeuverMeters` | `number` | required |  |
| `remainingDistanceMeters` | `number` | required |  |
| `remainingDurationSeconds` | `number` | required |  |
| `etaEpochMs` | `number` | required | Unix ms arrival estimate, recomputed continuously. |
| `isOffRoute` | `boolean` | required |  |

#### `GuidanceOptions`

*Type*

```ts
type GuidanceOptions = {
    routeIndex: number;
    source: LocationSource;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `routeIndex` | `number` | required | Which route from the last computeRoute() to follow. |
| `source` | [`LocationSource`](#locationsource) | required |  |

#### `LatLng`

*Type*

```ts
type LatLng = {
    latitude: number;
    longitude: number;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `latitude` | `number` | required |  |
| `longitude` | `number` | required |  |

#### `LocationSource`

*Type*

```ts
type LocationSource = {
    kind: "live";
} | {
    kind: "replay";
    corpusPath: string;
    speedMultiplier?: number;
};
```

#### `Maneuver`

*Type*

```ts
type Maneuver = {
    type: ManeuverType;
    instruction: string;
    distanceMeters: number;
    position: LatLng;
    roundaboutExit?: number;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | [`ManeuverType`](#maneuvertype) | required |  |
| `instruction` | `string` | required |  |
| `distanceMeters` | `number` | required |  |
| `position` | [`LatLng`](#latlng) | required |  |
| `roundaboutExit?` | `number` | not stated |  |

#### `ManeuverType`

*Type*

```ts
type ManeuverType = "depart" | "turn-left" | "turn-right" | "slight-left" | "slight-right" | "sharp-left" | "sharp-right" | "uturn" | "straight" | "merge" | "on-ramp" | "off-ramp" | "fork-left" | "fork-right" | "roundabout" | "arrive";
```

#### `MapmapNavEvents`

*Type*

```ts
type MapmapNavEvents = {
    territoryProgress: (event: TerritoryProgressEvent) => void;
    guidance: (event: GuidanceEvent) => void;
    voiceState: (event: VoiceStateEvent) => void;
    bridgeError: (event: BridgeError) => void;
};
```

Event name → payload map (Expo Modules event emitter).

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `territoryProgress` | `(event: TerritoryProgressEvent) => void` | required |  |
| `guidance` | `(event: GuidanceEvent) => void` | required |  |
| `voiceState` | `(event: VoiceStateEvent) => void` | required |  |
| `bridgeError` | `(event: BridgeError) => void` | required |  |

#### `MapmapNavHandle`

*Type*

```ts
type MapmapNavHandle = MapmapNavModule & MapmapNavEmitterLike<MapmapNavEvents>;
```

Combined shape returned by `getMapmapNav`: the promise-based API plus the typed event emitter.

#### `MapmapNavMockOptions`

*Type*

```ts
type MapmapNavMockOptions = {
    tickIntervalMs?: number;
    territoryInstallDurationMs?: number;
    simulateReroute?: boolean;
    routeProvider?: (request: RouteRequest) => Promise<RouteResult | null>;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `tickIntervalMs?` | `number` | 1000 (1Hz) | Interval between simulated `guidance` ticks, ms. Default 1000 (1Hz). |
| `territoryInstallDurationMs?` | `number` | 3000 | Total wall-clock time to simulate a territory install. Default 3000. |
| `simulateReroute?` | `boolean` | true | Whether to emit one illustrative `rerouting` blip per guidance session. Default true. |
| `routeProvider?` | `(request: RouteRequest) => Promise<RouteResult \| null>` | not stated | Optional real-route source (e.g. the hosted MapMap engine). When set, computeRoute tries it first and only falls back to the synthetic dogleg when it returns null, so demo guidance follows real roads. |

#### `NativeMapmapNavModule`

*Type*

```ts
type NativeMapmapNavModule = MapmapNavModule & MapmapNavEmitterLike<MapmapNavEvents>;
```

#### `Position`

*Type*

```ts
type Position = [number, number];
```

A WGS84 position, `[longitude, latitude]` (GeoJSON order).

#### `RegionPolygon`

*Type*

```ts
type RegionPolygon = {
    type: "Polygon";
    coordinates: Position[][];
} | {
    type: "MultiPolygon";
    coordinates: Position[][][];
};
```

GeoJSON polygon geometry accepted as a region area.

#### `Route`

*Type*

```ts
type Route = {
    index: number;
    geometry: LatLng[];
    distanceMeters: number;
    durationSeconds: number;
    maneuvers: Maneuver[];
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `index` | `number` | required | Index into the RouteResult.routes array; stable for the session. |
| `geometry` | [`LatLng[]`](#latlng) | required | Full geometry, ordered, ready for a MapLibre LineString. |
| `distanceMeters` | `number` | required |  |
| `durationSeconds` | `number` | required |  |
| `maneuvers` | [`Maneuver[]`](#maneuver) | required |  |

#### `RouteProfile`

*Type*

```ts
type RouteProfile = "car" | "bicycle" | "walking";
```

#### `RouteRequest`

*Type*

```ts
type RouteRequest = {
    profile: RouteProfile;
    origin: LatLng;
    destination: LatLng;
    alternatives?: number;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `profile` | [`RouteProfile`](#routeprofile) | required |  |
| `origin` | [`LatLng`](#latlng) | required |  |
| `destination` | [`LatLng`](#latlng) | required |  |
| `alternatives?` | `number` | 2 | Extra full routes wanted beyond the primary (0–3). Default 2. |

#### `RouteResult`

*Type*

```ts
type RouteResult = {
    routes: Route[];
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `routes` | [`Route[]`](#route) | required |  |

#### `SearchResult`

*Type*

```ts
type SearchResult = {
    name: string;
    address: string;
    position: LatLng;
    distanceMeters?: number;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | required |  |
| `address` | `string` | required | Secondary line: locality / address; empty string when unknown. |
| `position` | [`LatLng`](#latlng) | required |  |
| `distanceMeters?` | `number` | not stated | Straight-line metres from `near` when it was provided. |

#### `TerritoryInfo`

*Type*

```ts
type TerritoryInfo = {
    id: string;
    name: string;
    version: string;
    sizeOnDiskBytes: number;
    active: boolean;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | required |  |
| `name` | `string` | required |  |
| `version` | `string` | required |  |
| `sizeOnDiskBytes` | `number` | required |  |
| `active` | `boolean` | required |  |

#### `TerritoryPhase`

*Type*

```ts
type TerritoryPhase = "downloading" | "verifying" | "activating" | "done" | "failed" | "cancelled";
```

#### `TerritoryProgressEvent`

*Type*

```ts
type TerritoryProgressEvent = {
    territoryId: string;
    phase: TerritoryPhase;
    bytesDone: number;
    bytesTotal: number;
    error?: BridgeError;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `territoryId` | `string` | required |  |
| `phase` | [`TerritoryPhase`](#territoryphase) | required |  |
| `bytesDone` | `number` | required | Bytes fetched so far; only meaningful while downloading. |
| `bytesTotal` | `number` | required | Total bytes to fetch; 0 until known. |
| `error?` | [`BridgeError`](#bridgeerror) | not stated | Set only when phase === "failed". A "cancelled" phase carries none. |

#### `TerritorySummary`

*Type*

```ts
type TerritorySummary = {
    id: string;
    name: string;
    sizeBytes: number;
    version: string;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | required |  |
| `name` | `string` | required |  |
| `sizeBytes` | `number` | required |  |
| `version` | `string` | required |  |

#### `VoiceStateEvent`

*Type*

```ts
type VoiceStateEvent = {
    muted: boolean;
    volume: number;
    speaking: boolean;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `muted` | `boolean` | required |  |
| `volume` | `number` | required |  |
| `speaking` | `boolean` | required |  |

#### `WaitOptions`

*Type*

```ts
type WaitOptions = {
    intervalMs?: number;
    maxIntervalMs?: number;
    timeoutMs?: number;
    signal?: AbortSignalLike;
    onUpdate?: (job: CustomRegionJob) => void;
};
```

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `intervalMs?` | `number` | 1000 | First poll delay, ms. Doubles to `maxIntervalMs`. Default 1000. |
| `maxIntervalMs?` | `number` | 10000 | Poll delay ceiling, ms. Default 10000. |
| `timeoutMs?` | `number` | 15 minutes | Give up after this long, ms. Default 15 minutes. |
| `signal?` | [`AbortSignalLike`](#abortsignallike) | not stated |  |
| `onUpdate?` | `(job: CustomRegionJob) => void` | not stated | Called with every poll's answer (progress UI). |

### Constants (@mapmap/react-native)

[`HOSTED_REGION_KEY_HEX`](#hosted_region_key_hex), [`MapmapNav`](#mapmapnav)

#### `HOSTED_REGION_KEY_HEX`

*Constant*

```ts
const HOSTED_REGION_KEY_HEX = "6f60f17bc31be2f7696cb957b2188416741e09cb3e7bdec2719fe553213be107";
```

The public half of the hosted gateway's custom-region signing key (ed25519,
64 hex), the default the Android and iOS bridges pin (the same value as
`ai.mapmap.territory.TerritoryKeys.HOSTED_REGION_KEY_HEX` and MapMapKit's
`TerritoryKeys.hostedRegionKeyHex`). Informational on the JS side: the
native core does the verifying, and a self-hosted gateway's key is set at
build time (`mapmap.regionPubkeyHex` on Android, the Info.plist key
`MAPMAP_REGION_VERIFYING_KEY` on iOS), never at runtime.

#### `MapmapNav`

*Constant*

```ts
const MapmapNav: NativeMapmapNavModule;
```

The native-backed handle. A lazy stand-in: every property read, call and
write is forwarded to the real native module, resolved on first touch.
