@mapmap/maps 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -3
- package/README.md +166 -4
- package/dist/index.d.ts +1167 -133
- package/dist/index.js +1756 -76
- package/dist/index.js.map +1 -1
- package/llms-sdk.txt +131 -0
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,259 @@
|
|
|
1
|
-
import maplibregl, {
|
|
1
|
+
import maplibregl, { CustomLayerInterface, Map, StyleSpecification, MapOptions, ExpressionSpecification } from 'maplibre-gl';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared public types for @mapmap/maps.
|
|
5
|
+
*
|
|
6
|
+
* These are runtime-free (type-only) so the pure logic modules that import
|
|
7
|
+
* them stay loadable in Node without a browser or maplibre-gl.
|
|
8
|
+
*/
|
|
9
|
+
/** A longitude/latitude pair, accepted in the three common shapes. */
|
|
10
|
+
type LngLatLike = [number, number] | {
|
|
11
|
+
lng: number;
|
|
12
|
+
lat: number;
|
|
13
|
+
} | {
|
|
14
|
+
lon: number;
|
|
15
|
+
lat: number;
|
|
16
|
+
};
|
|
17
|
+
/** OSRM routing profile. MapMap ships `driving`, `walking` and `truck`. */
|
|
18
|
+
type RouteProfile = "driving" | "walking" | "truck" | (string & {});
|
|
19
|
+
/**
|
|
20
|
+
* Truck / ADR vehicle parameters forwarded to the gateway's OSRM truck
|
|
21
|
+
* vendor extensions. All optional; only `truck`-profile requests honour them.
|
|
22
|
+
*/
|
|
23
|
+
interface TruckParams {
|
|
24
|
+
/** Vehicle height, metres. */
|
|
25
|
+
heightM?: number;
|
|
26
|
+
/** Vehicle width, metres. */
|
|
27
|
+
widthM?: number;
|
|
28
|
+
/** Vehicle length, metres. */
|
|
29
|
+
lengthM?: number;
|
|
30
|
+
/** Gross weight, tonnes. */
|
|
31
|
+
weightT?: number;
|
|
32
|
+
/** Carrying dangerous goods (ADR). */
|
|
33
|
+
hazmat?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* ADR 8.6.4 tunnel restriction code, e.g. `"C"` or `"B/D"`. The slash is
|
|
36
|
+
* URL-encoded automatically.
|
|
37
|
+
*/
|
|
38
|
+
tunnelCode?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Options for a single route request. */
|
|
41
|
+
interface RouteOptions {
|
|
42
|
+
/** Routing profile. Defaults to `"driving"`. */
|
|
43
|
+
profile?: RouteProfile;
|
|
44
|
+
/** Truck / ADR parameters (only meaningful with `profile: "truck"`). */
|
|
45
|
+
truck?: TruckParams;
|
|
46
|
+
/** Request spoken `voiceInstructions` on each step (see `guidance.ts`). */
|
|
47
|
+
voice?: boolean;
|
|
48
|
+
/** Request visual `bannerInstructions` (and lane data) on each step. */
|
|
49
|
+
banner?: boolean;
|
|
50
|
+
/** BCP 47 narration language, e.g. `"en-GB"`. */
|
|
51
|
+
language?: string;
|
|
52
|
+
}
|
|
53
|
+
/** A parsed GeoJSON LineString geometry (`[lng, lat]` positions). */
|
|
54
|
+
interface RouteGeometry {
|
|
55
|
+
type: "LineString";
|
|
56
|
+
coordinates: [number, number][];
|
|
57
|
+
}
|
|
58
|
+
/** A parsed OSRM route, normalised to the fields callers actually use. */
|
|
59
|
+
interface ParsedRoute {
|
|
60
|
+
/** Total distance, metres. */
|
|
61
|
+
distanceM: number;
|
|
62
|
+
/** Total duration, seconds. */
|
|
63
|
+
durationS: number;
|
|
64
|
+
/** Route line as GeoJSON, ready to hand to a MapLibre source. */
|
|
65
|
+
geometry: RouteGeometry;
|
|
66
|
+
/** The raw OSRM `routes[0]` object, for callers that need leg/step detail. */
|
|
67
|
+
raw: Record<string, unknown>;
|
|
68
|
+
}
|
|
69
|
+
/** The ADR category of a tunnel, `"A"` (least restrictive) … `"E"`. */
|
|
70
|
+
type AdrTunnelCategory = "A" | "B" | "C" | "D" | "E";
|
|
71
|
+
/**
|
|
72
|
+
* Physical truck dimensions for the ADR vehicle profile (mirrors
|
|
73
|
+
* `sn_adr::TruckDimensions`). All optional; unset fields default to the EU
|
|
74
|
+
* 96/53/EC maximum-authorised articulated vehicle (4.0 m high, 2.55 m wide,
|
|
75
|
+
* 16.5 m long, 40 t gross), matching the Rust `Default`.
|
|
76
|
+
*/
|
|
77
|
+
interface AdrDimensions {
|
|
78
|
+
/** Vehicle height, metres. Defaults to `4.0`. */
|
|
79
|
+
heightM?: number;
|
|
80
|
+
/** Vehicle width, metres. Defaults to `2.55`. */
|
|
81
|
+
widthM?: number;
|
|
82
|
+
/** Vehicle length, metres. Defaults to `16.5`. */
|
|
83
|
+
lengthM?: number;
|
|
84
|
+
/** Gross combination weight, tonnes. Defaults to `40`. */
|
|
85
|
+
grossWeightT?: number;
|
|
86
|
+
/** Heaviest single-axle load, tonnes, if known. */
|
|
87
|
+
axleLoadT?: number;
|
|
88
|
+
/** Number of axles, if known. */
|
|
89
|
+
axleCount?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Input for the gateway's `POST /adr/check` compliance endpoint: the
|
|
93
|
+
* vehicle's ADR profile plus the category of the tunnel to check. Serialised
|
|
94
|
+
* on the wire as `{"adr": <AdrVehicleProfile>, "tunnel_category": "A".."E"}`
|
|
95
|
+
* (see `sn-gateway` `routes/adr.rs`).
|
|
96
|
+
*/
|
|
97
|
+
interface AdrCheckRequest {
|
|
98
|
+
/** Carrying dangerous goods. */
|
|
99
|
+
hazmat: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The *vehicle load's* ADR 8.6.4 tunnel restriction code, e.g. `"C"` or
|
|
102
|
+
* `"C/E"`. Omit when carrying dangerous goods of unknown code (the
|
|
103
|
+
* gateway then conservatively treats the load as code `B`). This is not
|
|
104
|
+
* the tunnel's category — that goes in {@link tunnelCategory}.
|
|
105
|
+
*/
|
|
106
|
+
tunnelCode?: string;
|
|
107
|
+
/** Vehicle dimensions. Defaults to the EU standard artic maximums. */
|
|
108
|
+
dimensions?: AdrDimensions;
|
|
109
|
+
/** The ADR category of the *tunnel* to check, `"A"` … `"E"`. */
|
|
110
|
+
tunnelCategory: AdrTunnelCategory;
|
|
111
|
+
}
|
|
112
|
+
/** Parsed response from `POST /adr/check`. */
|
|
113
|
+
interface AdrCheckResult {
|
|
114
|
+
/** `"allowed"` or `"blocked"`. */
|
|
115
|
+
status: string;
|
|
116
|
+
/** Human-readable justification citing ADR 8.6.4 where blocked. */
|
|
117
|
+
reason?: string;
|
|
118
|
+
/** The raw response body. */
|
|
119
|
+
raw: Record<string, unknown>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Effects engine - named, geometry-anchored visual effects rendered through
|
|
124
|
+
* MapLibre's stable `CustomLayerInterface` (first-party GLSL, no runtime
|
|
125
|
+
* dependencies). The first effect is `"flow"`: an animated energy ribbon
|
|
126
|
+
* along the active route line, drawn as a triangle strip with a flowing
|
|
127
|
+
* pulse gradient driven by a time uniform.
|
|
128
|
+
*
|
|
129
|
+
* Deliberately NOT full-map post-processing: MapLibre has no official
|
|
130
|
+
* post-process hook, so every effect here anchors to geometry and rides the
|
|
131
|
+
* supported custom-layer API. New effects register in {@link ROUTE_EFFECTS}.
|
|
132
|
+
*
|
|
133
|
+
* Accessibility and resilience:
|
|
134
|
+
* - `prefers-reduced-motion: reduce` freezes the ribbon to a static
|
|
135
|
+
* gradient (no animation loop, no repaints).
|
|
136
|
+
* - If WebGL setup for the custom layer fails (shader compile/link, lost
|
|
137
|
+
* context), the effect silently disables itself - the ordinary route
|
|
138
|
+
* line underneath is untouched - and logs a single console warning.
|
|
139
|
+
*
|
|
140
|
+
* The tessellation and colour helpers are pure and unit-tested in Node;
|
|
141
|
+
* only the layer object itself touches WebGL.
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
/** The names the effects registry knows. Grows as effects land. */
|
|
145
|
+
type RouteEffectName = "flow";
|
|
146
|
+
/** Options for the `"flow"` route effect (all optional). */
|
|
147
|
+
interface RouteFlowOptions {
|
|
148
|
+
/** Ribbon colour (hex or rgb()/rgba()). Defaults to MapMap signal blue. */
|
|
149
|
+
color?: string;
|
|
150
|
+
/** Ribbon width in CSS pixels. Defaults to `10`. */
|
|
151
|
+
width?: number;
|
|
152
|
+
/** Flow speed in pulse cycles per second. Defaults to `0.6`. */
|
|
153
|
+
speed?: number;
|
|
154
|
+
/** MapLibre layer id. Defaults to `"mapmap-route-effect"`. */
|
|
155
|
+
id?: string;
|
|
156
|
+
}
|
|
157
|
+
/** Floats per ribbon vertex: x, y (mercator), nx, ny (unit normal), progress. */
|
|
158
|
+
declare const RIBBON_FLOATS_PER_VERTEX = 5;
|
|
159
|
+
/** A tessellated route ribbon, ready for a `TRIANGLE_STRIP` draw. */
|
|
160
|
+
interface RibbonMesh {
|
|
161
|
+
/**
|
|
162
|
+
* Interleaved vertex data, {@link RIBBON_FLOATS_PER_VERTEX} floats per
|
|
163
|
+
* vertex: mercator position, the unit extrusion normal (the shader
|
|
164
|
+
* extrudes `pos + normal * halfWidth`, so width stays zoom-correct
|
|
165
|
+
* without re-tessellating), and progress along the route (0 at the
|
|
166
|
+
* start, 1 at the end - the flowing gradient's coordinate).
|
|
167
|
+
*/
|
|
168
|
+
vertices: Float32Array;
|
|
169
|
+
/** Number of vertices (two per route point kept). */
|
|
170
|
+
vertexCount: number;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Project a `[lng, lat]` to web-mercator world coordinates in [0, 1]
|
|
174
|
+
* (MapLibre's `MercatorCoordinate` convention: x east, y south).
|
|
175
|
+
*/
|
|
176
|
+
declare function lngLatToMercator(lngLat: [number, number]): [number, number];
|
|
177
|
+
/**
|
|
178
|
+
* Tessellate a route line into a centreline triangle strip: two vertices
|
|
179
|
+
* per point, each carrying the point's mercator position, a unit extrusion
|
|
180
|
+
* normal (averaged between adjacent segments at joins - a bevel-free miter
|
|
181
|
+
* that slightly thins very sharp corners, which is invisible on a soft
|
|
182
|
+
* glow ribbon), and normalised progress along the line.
|
|
183
|
+
*
|
|
184
|
+
* Pure: no WebGL, no map. Consecutive duplicate points are dropped; fewer
|
|
185
|
+
* than two distinct points yield an empty mesh.
|
|
186
|
+
*/
|
|
187
|
+
declare function tessellateRouteRibbon(coordinates: [number, number][]): RibbonMesh;
|
|
188
|
+
/**
|
|
189
|
+
* Parse a CSS colour to premultiplication-ready `[r, g, b, a]` (0-1
|
|
190
|
+
* channels). Supports the hex forms and `rgb()`/`rgba()`; anything else
|
|
191
|
+
* (named colours, `hsl()`) returns `undefined` and the caller falls back
|
|
192
|
+
* to the default - this runs where no canvas is guaranteed, so no
|
|
193
|
+
* browser colour parser is available.
|
|
194
|
+
*/
|
|
195
|
+
declare function parseCssColour(colour: string): [number, number, number, number] | undefined;
|
|
196
|
+
/** Whether the user has asked for reduced motion. Safe without a DOM. */
|
|
197
|
+
declare function prefersReducedMotion(): boolean;
|
|
198
|
+
/** Default flow parameters (exported so docs/tests state one truth). */
|
|
199
|
+
declare const FLOW_DEFAULTS: {
|
|
200
|
+
readonly color: "#3a86ff";
|
|
201
|
+
readonly width: 10;
|
|
202
|
+
readonly speed: 0.6;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* A MapLibre custom layer (`CustomLayerInterface`) drawing the flowing
|
|
206
|
+
* route ribbon. Construct via {@link createRouteEffect} (the registry) or
|
|
207
|
+
* use `MapMapMap.setRouteEffect("flow")`, which manages the lifecycle.
|
|
208
|
+
*/
|
|
209
|
+
declare class FlowRouteEffectLayer implements CustomLayerInterface {
|
|
210
|
+
readonly id: string;
|
|
211
|
+
readonly type: "custom";
|
|
212
|
+
readonly renderingMode: "2d";
|
|
213
|
+
private geometry;
|
|
214
|
+
private readonly colour;
|
|
215
|
+
private readonly widthPx;
|
|
216
|
+
private readonly speed;
|
|
217
|
+
private readonly animate;
|
|
218
|
+
private mapRef;
|
|
219
|
+
private glRef;
|
|
220
|
+
private program;
|
|
221
|
+
private buffer;
|
|
222
|
+
private vertexCount;
|
|
223
|
+
private repeats;
|
|
224
|
+
private startedAt;
|
|
225
|
+
private failed;
|
|
226
|
+
private aPos;
|
|
227
|
+
private aNormal;
|
|
228
|
+
private aProgress;
|
|
229
|
+
private uMatrix;
|
|
230
|
+
private uHalfWidth;
|
|
231
|
+
private uColor;
|
|
232
|
+
private uPhase;
|
|
233
|
+
private uRepeats;
|
|
234
|
+
constructor(geometry: RouteGeometry, options?: RouteFlowOptions);
|
|
235
|
+
/** Swap the ribbon onto a new route line (e.g. after a reroute). */
|
|
236
|
+
setGeometry(geometry: RouteGeometry): void;
|
|
237
|
+
onAdd(map: Map, gl: WebGLRenderingContext | WebGL2RenderingContext): void;
|
|
238
|
+
onRemove(_map: Map, gl: WebGLRenderingContext | WebGL2RenderingContext): void;
|
|
239
|
+
render(gl: WebGLRenderingContext | WebGL2RenderingContext, args: unknown): void;
|
|
240
|
+
private upload;
|
|
241
|
+
}
|
|
242
|
+
/** A route effect layer: a custom layer that can retarget its geometry. */
|
|
243
|
+
interface RouteEffectLayer extends CustomLayerInterface {
|
|
244
|
+
setGeometry(geometry: RouteGeometry): void;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* The effect registry: name -> layer factory. New effects (ambient life,
|
|
248
|
+
* seasonal snow, fog-of-exploration) add an entry here and a name to
|
|
249
|
+
* {@link RouteEffectName}.
|
|
250
|
+
*/
|
|
251
|
+
declare const ROUTE_EFFECTS: Record<RouteEffectName, (geometry: RouteGeometry, options?: RouteFlowOptions) => RouteEffectLayer>;
|
|
252
|
+
/**
|
|
253
|
+
* Create a named route effect layer. Throws an agent-readable error for
|
|
254
|
+
* unknown names (the accepted list included).
|
|
255
|
+
*/
|
|
256
|
+
declare function createRouteEffect(name: RouteEffectName, geometry: RouteGeometry, options?: RouteFlowOptions): RouteEffectLayer;
|
|
2
257
|
|
|
3
258
|
/**
|
|
4
259
|
* The MapMap logo control: a small wordmark on the map, the same
|
|
@@ -104,6 +359,23 @@ interface LayerOverride {
|
|
|
104
359
|
minzoom?: number;
|
|
105
360
|
maxzoom?: number;
|
|
106
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* The optional visual-effects block, mirroring `sn_style::Effects`. Unlike
|
|
364
|
+
* `extra`, this IS carried into the compiled style — as
|
|
365
|
+
* `metadata["mapmap:effects"]` — so any consumer of a compiled `style.json`
|
|
366
|
+
* (hosted style URL, baked territory package) can honour it without the
|
|
367
|
+
* theme document. Renderers that do not know the effects engine ignore the
|
|
368
|
+
* metadata and render the style unchanged.
|
|
369
|
+
*/
|
|
370
|
+
interface ThemeEffects {
|
|
371
|
+
/** Route-line effect: `"flow"` (animated energy ribbon) or `"none"`. */
|
|
372
|
+
route?: "flow" | "none";
|
|
373
|
+
/**
|
|
374
|
+
* Effect parameters, validated per effect. For `flow`: `color` (CSS
|
|
375
|
+
* colour), `width` (px, 0.5-40), `speed` (cycles/s, 0-10).
|
|
376
|
+
*/
|
|
377
|
+
params?: Record<string, unknown>;
|
|
378
|
+
}
|
|
107
379
|
/**
|
|
108
380
|
* A MapMap Studio theme: the unit users and agents edit, store and publish.
|
|
109
381
|
* Mirrors `sn_style::Theme` (all fields carry serde defaults, so everything
|
|
@@ -146,22 +418,38 @@ interface Theme {
|
|
|
146
418
|
* source-layer.
|
|
147
419
|
*/
|
|
148
420
|
extra_layers?: JsonObject[];
|
|
421
|
+
/**
|
|
422
|
+
* Optional visual effects (route ribbon etc.). Compiled into
|
|
423
|
+
* `metadata["mapmap:effects"]` on the style — see {@link ThemeEffects}.
|
|
424
|
+
* Mirrors `Theme::effects`.
|
|
425
|
+
*/
|
|
426
|
+
effects?: ThemeEffects;
|
|
149
427
|
/**
|
|
150
428
|
* Non-style extras carried by the THEME DOCUMENT, not the compiled
|
|
151
429
|
* style. Studio stores its navigation design block here (`extra.nav`;
|
|
152
|
-
* see `nav-design.ts`)
|
|
430
|
+
* see `nav-design.ts`) and its POI category design (`extra.poi`; see
|
|
431
|
+
* `poi-design.ts`). {@link buildStyle} ignores it entirely - the
|
|
153
432
|
* compiled `style.json` is byte-identical with or without it. Mirrors
|
|
154
433
|
* `Theme::extra` in the canonical Rust crate: the hosted styles API
|
|
155
434
|
* stores the block verbatim (bounded at 256 KB serialised) and serves it
|
|
156
435
|
* back from `GET /styles/{id}/theme`, so a Studio design survives
|
|
157
436
|
* publishing - consume it via `createMap` with a theme document or
|
|
158
|
-
* `navDesignFromThemeUrl` with the hosted
|
|
437
|
+
* `navDesignFromThemeUrl` / `poiDesignFromThemeUrl` with the hosted
|
|
438
|
+
* theme URL.
|
|
159
439
|
*/
|
|
160
440
|
extra?: {
|
|
161
441
|
nav?: unknown;
|
|
442
|
+
poi?: unknown;
|
|
162
443
|
};
|
|
163
444
|
}
|
|
164
445
|
interface BuildStyleOptions {
|
|
446
|
+
/**
|
|
447
|
+
* Label language: an ISO 639 code selects `name:<code>` with a
|
|
448
|
+
* local-name fallback; the literal `"local"` selects the local name
|
|
449
|
+
* outright; omitted keeps the default (English-first). The tiles carry
|
|
450
|
+
* the OSM `name:*` set, so switching involves no tile rebuild.
|
|
451
|
+
*/
|
|
452
|
+
labelLanguage?: string;
|
|
165
453
|
/**
|
|
166
454
|
* Theme to build: a built-in name (`"light"` / `"dark"`) or a full
|
|
167
455
|
* {@link Theme} document. Defaults to `"light"`.
|
|
@@ -175,6 +463,22 @@ interface BuildStyleOptions {
|
|
|
175
463
|
}
|
|
176
464
|
/** Ensure a tiles URL carries the `pmtiles://` protocol prefix. */
|
|
177
465
|
declare function toPmtilesUrl(url: string): string;
|
|
466
|
+
/**
|
|
467
|
+
* The `metadata` key a compiled style carries its effects block under.
|
|
468
|
+
* Shared with `sn-style` (compile.rs) and read back by `MapMapMap` to
|
|
469
|
+
* auto-enable the route effect for styles that request one.
|
|
470
|
+
*/
|
|
471
|
+
declare const EFFECTS_METADATA_KEY = "mapmap:effects";
|
|
472
|
+
/**
|
|
473
|
+
* The effects block from a compiled style's `metadata`, if the style
|
|
474
|
+
* carries a valid one (`{ route: "flow", params? }`). Lenient by design —
|
|
475
|
+
* it reads FOREIGN styles (hosted URLs, baked packages), so anything
|
|
476
|
+
* malformed returns `undefined` rather than throwing.
|
|
477
|
+
*/
|
|
478
|
+
declare function effectsFromStyleMetadata(metadata: unknown): {
|
|
479
|
+
route: "flow";
|
|
480
|
+
params?: Record<string, unknown>;
|
|
481
|
+
} | undefined;
|
|
178
482
|
declare function buildStyle(options?: BuildStyleOptions): StyleSpecification;
|
|
179
483
|
|
|
180
484
|
/**
|
|
@@ -331,6 +635,128 @@ declare function navDesignFromTheme(theme: Theme | undefined | null): NavDesign
|
|
|
331
635
|
*/
|
|
332
636
|
declare function navDesignFromThemeUrl(url: string, fetchImpl?: typeof fetch): Promise<NavDesign | undefined>;
|
|
333
637
|
|
|
638
|
+
/**
|
|
639
|
+
* Studio POI category-design block (`extra.poi`) - types, defaults, parser
|
|
640
|
+
* and appliers.
|
|
641
|
+
*
|
|
642
|
+
* MapMap Studio's POIs panel colours the ~8 POI categories - the coloured
|
|
643
|
+
* category dot drawn under a POI label, and the `poi-labels` text colour -
|
|
644
|
+
* and stores the result as a small design-token block under `extra.poi` in
|
|
645
|
+
* the theme JSON it downloads/copies/publishes, exactly like the navigation
|
|
646
|
+
* design under `extra.nav` (see nav-design.ts). This module reads that
|
|
647
|
+
* block and applies the label-text part to a live MapLibre map; the dot
|
|
648
|
+
* images themselves are runtime-rasterised by their host (the MapMap
|
|
649
|
+
* website today - sprite-based icons arrive with marker packs).
|
|
650
|
+
*
|
|
651
|
+
* LOCKSTEP: this file mirrors `website/lib/studio-poi.ts` (the Studio
|
|
652
|
+
* reference parser) - identical category ids, built-in colours, leniency
|
|
653
|
+
* and expression building. The class->category mapping mirrors
|
|
654
|
+
* `website/lib/poi-icons.ts` (`POI_CLASS_CATEGORIES`). Keep them in sync so
|
|
655
|
+
* a theme previews in Studio exactly as the SDK applies it. Not imported
|
|
656
|
+
* from the website because the packages do not depend on each other.
|
|
657
|
+
*
|
|
658
|
+
* PUBLISH NOTE: the block travels with the THEME DOCUMENT, never with the
|
|
659
|
+
* compiled `style.json`. The canonical `sn_style` crate stores `extra`
|
|
660
|
+
* verbatim (bounded at 256 KB serialised) and the gateway serves it back
|
|
661
|
+
* from `GET /styles/{id}/theme`, so a design survives Studio's publish
|
|
662
|
+
* flow. Read it from a theme file you pass to `createMap` / `buildStyle`,
|
|
663
|
+
* or fetch it from a hosted style with {@link poiDesignFromThemeUrl} - a
|
|
664
|
+
* compiled style URL alone never carries it.
|
|
665
|
+
*/
|
|
666
|
+
|
|
667
|
+
/** One category's overrides. Both fields optional: absent = built-in. */
|
|
668
|
+
interface PoiCategoryDesign {
|
|
669
|
+
/** Dot fill colour (replaces the built-in category brand colour). */
|
|
670
|
+
color?: string;
|
|
671
|
+
/** Label text colour for this category (replaces `textSecondary`). */
|
|
672
|
+
textColor?: string;
|
|
673
|
+
}
|
|
674
|
+
/** The `extra.poi` block: POI category design. */
|
|
675
|
+
interface PoiDesign {
|
|
676
|
+
/** Block schema version; currently always 1. */
|
|
677
|
+
version: 1;
|
|
678
|
+
/** Overrides by category id; empty = all built-in. */
|
|
679
|
+
categories: Record<string, PoiCategoryDesign>;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* The valid category ids with their built-in dot colours, in presentation
|
|
683
|
+
* order. LOCKSTEP: mirrors `POI_CATEGORIES` in `website/lib/poi-icons.ts`.
|
|
684
|
+
*/
|
|
685
|
+
declare const POI_CATEGORY_COLORS: readonly (readonly [string, string])[];
|
|
686
|
+
/** The valid category ids, in presentation order. */
|
|
687
|
+
declare const POI_CATEGORY_IDS: readonly string[];
|
|
688
|
+
/**
|
|
689
|
+
* OpenMapTiles `poi` layer `class` values grouped into the categories
|
|
690
|
+
* above; every class not listed falls through to `services`. LOCKSTEP:
|
|
691
|
+
* mirrors `POI_CLASS_CATEGORIES` in `website/lib/poi-icons.ts`.
|
|
692
|
+
*/
|
|
693
|
+
declare const POI_CLASS_CATEGORIES: Record<string, string[]>;
|
|
694
|
+
/** The built-in dot colour for a category id. */
|
|
695
|
+
declare function builtInPoiColor(categoryId: string): string | undefined;
|
|
696
|
+
/** No overrides: every category keeps its built-in dot and label colours. */
|
|
697
|
+
declare function defaultPoiDesign(): PoiDesign;
|
|
698
|
+
/** True when the design changes nothing. */
|
|
699
|
+
declare function poiDesignIsDefault(design: PoiDesign): boolean;
|
|
700
|
+
/**
|
|
701
|
+
* Lenient parse of an `extra.poi` value: unknown category ids and invalid
|
|
702
|
+
* colours are dropped rather than failing, so an imported theme never
|
|
703
|
+
* breaks on its POI block. LOCKSTEP: identical semantics to
|
|
704
|
+
* `parsePoiDesign` in `website/lib/studio-poi.ts`.
|
|
705
|
+
*/
|
|
706
|
+
declare function parsePoiDesign(value: unknown): PoiDesign;
|
|
707
|
+
/**
|
|
708
|
+
* Reads and parses the `extra.poi` block from a Studio theme document.
|
|
709
|
+
* Returns `undefined` when the theme carries no poi block at all (so
|
|
710
|
+
* callers can tell "no design" apart from "default design"); a present but
|
|
711
|
+
* malformed block parses leniently to the defaults. Same contract as
|
|
712
|
+
* `navDesignFromTheme`.
|
|
713
|
+
*/
|
|
714
|
+
declare function poiDesignFromTheme(theme: Theme | undefined | null): PoiDesign | undefined;
|
|
715
|
+
/**
|
|
716
|
+
* Fetches a hosted theme document and reads its `extra.poi` block - point
|
|
717
|
+
* it at the gateway's public, never-cached theme endpoint, e.g.
|
|
718
|
+
* `https://api.mapmap.ai/styles/midnight-fleet-a1b2c3/theme`. Returns
|
|
719
|
+
* `undefined` when the theme carries no poi block; throws on network
|
|
720
|
+
* failure, a non-2xx response or a non-JSON body. Same contract as
|
|
721
|
+
* {@link navDesignFromThemeUrl}.
|
|
722
|
+
*
|
|
723
|
+
* @param fetchImpl Optional `fetch` replacement (tests, Node polyfills).
|
|
724
|
+
*/
|
|
725
|
+
declare function poiDesignFromThemeUrl(url: string, fetchImpl?: typeof fetch): Promise<PoiDesign | undefined>;
|
|
726
|
+
/**
|
|
727
|
+
* The `poi-labels` `text-color` value for a design: the plain fallback
|
|
728
|
+
* colour when no category overrides label text, otherwise a `match`
|
|
729
|
+
* expression keyed on the tile's `class` property. Every non-services
|
|
730
|
+
* category always gets an arm (override or fallback) so unmatched classes
|
|
731
|
+
* - the `services` fallback arm - never inherit another category's colour.
|
|
732
|
+
* LOCKSTEP: mirrors `poiTextColorExpression` in `website/lib/studio-poi.ts`.
|
|
733
|
+
*/
|
|
734
|
+
declare function poiTextColorExpression(design: PoiDesign, fallback: string): unknown;
|
|
735
|
+
/** The subset of the MapLibre map surface {@link applyPoiDesign} touches. */
|
|
736
|
+
interface PoiPaintMap {
|
|
737
|
+
getStyle(): {
|
|
738
|
+
layers?: {
|
|
739
|
+
id: string;
|
|
740
|
+
type?: string;
|
|
741
|
+
}[];
|
|
742
|
+
} | undefined;
|
|
743
|
+
setPaintProperty(layerId: string, name: string, value: unknown): unknown;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Applies a design's per-category label text colours to every `poi-labels`
|
|
747
|
+
* layer on a live map (including per-territory clones named
|
|
748
|
+
* `poi-labels@<territory>`). `fallbackTextColor` is the colour
|
|
749
|
+
* non-overridden categories keep - pass the style's `poi-labels` text
|
|
750
|
+
* colour (the theme's `textSecondary` slot; defaults to the light-base
|
|
751
|
+
* value). A default design restores the plain fallback, so this is safe to
|
|
752
|
+
* call on every design change.
|
|
753
|
+
*
|
|
754
|
+
* NOTE: runtime paint changes do not survive a later `setStyle`; re-apply
|
|
755
|
+
* after style swaps (the MapMap website bakes the expression into the
|
|
756
|
+
* style object instead for exactly this reason).
|
|
757
|
+
*/
|
|
758
|
+
declare function applyPoiDesign(map: PoiPaintMap, design: PoiDesign, fallbackTextColor?: string): void;
|
|
759
|
+
|
|
334
760
|
/**
|
|
335
761
|
* MapMapMap - the branded MapLibre GL map.
|
|
336
762
|
*
|
|
@@ -378,6 +804,15 @@ interface MapMapOptions {
|
|
|
378
804
|
*/
|
|
379
805
|
mapOptions?: Partial<Omit<MapOptions, "container" | "style">>;
|
|
380
806
|
}
|
|
807
|
+
/** Options for {@link MapMapMap.setRouteEffect}. */
|
|
808
|
+
interface SetRouteEffectOptions extends RouteFlowOptions {
|
|
809
|
+
/**
|
|
810
|
+
* The route line to attach the effect to. Optional: when omitted the
|
|
811
|
+
* effect is ARMED and applies as soon as a `RouteLayer` draws a route
|
|
812
|
+
* (RouteLayer feeds every drawn geometry to the map automatically).
|
|
813
|
+
*/
|
|
814
|
+
geometry?: RouteGeometry;
|
|
815
|
+
}
|
|
381
816
|
/** The MapMap map: a branded, tiles-and-routing-ready MapLibre map. */
|
|
382
817
|
declare class MapMapMap {
|
|
383
818
|
/** The underlying MapLibre map. Use it for any native MapLibre call. */
|
|
@@ -393,7 +828,62 @@ declare class MapMapMap {
|
|
|
393
828
|
* the theme had no nav block (or `style` was not a theme document).
|
|
394
829
|
*/
|
|
395
830
|
readonly navDesign: NavDesign | undefined;
|
|
831
|
+
/**
|
|
832
|
+
* The Studio POI category design (`extra.poi`) parsed from the theme
|
|
833
|
+
* passed as `style`, when it carried one. Apply its label-text part with
|
|
834
|
+
* `applyPoiDesign(map.map, map.poiDesign)`; `undefined` means the theme
|
|
835
|
+
* had no poi block (or `style` was not a theme document).
|
|
836
|
+
*/
|
|
837
|
+
readonly poiDesign: PoiDesign | undefined;
|
|
838
|
+
private effectName;
|
|
839
|
+
private effectOptions;
|
|
840
|
+
private effectGeometry;
|
|
841
|
+
private effectExplicit;
|
|
842
|
+
private effectLayer;
|
|
396
843
|
constructor(options: MapMapOptions);
|
|
844
|
+
private readonly handleStyleLoadForEffects;
|
|
845
|
+
/** The current style's `metadata`, if it can be read yet. */
|
|
846
|
+
private styleMetadata;
|
|
847
|
+
/**
|
|
848
|
+
* Set (or clear) the visual effect on the active route line - the
|
|
849
|
+
* effects-engine entry point (see `effects.ts`). The first effect is
|
|
850
|
+
* `"flow"`: an animated energy ribbon flowing along the route, drawn in
|
|
851
|
+
* a MapLibre custom layer with first-party GLSL.
|
|
852
|
+
*
|
|
853
|
+
* ```ts
|
|
854
|
+
* const route = await routes.route(from, to);
|
|
855
|
+
* map.setRouteEffect("flow"); // uses the drawn route
|
|
856
|
+
* map.setRouteEffect("flow", { color: "#ff7a1f" }); // options
|
|
857
|
+
* map.setRouteEffect(null); // back to the plain line
|
|
858
|
+
* ```
|
|
859
|
+
*
|
|
860
|
+
* Geometry: pass `{ geometry }` explicitly, or omit it and the effect
|
|
861
|
+
* attaches to whatever route a `RouteLayer` on this map draws (current
|
|
862
|
+
* and future - RouteLayer reports every drawn line via
|
|
863
|
+
* {@link setRouteEffectGeometry}).
|
|
864
|
+
*
|
|
865
|
+
* Styles whose theme carried an `effects` block auto-enable their effect
|
|
866
|
+
* from the compiled style's metadata; calling this method (with any
|
|
867
|
+
* value, including `null`) overrides the style's wish for the lifetime
|
|
868
|
+
* of this map.
|
|
869
|
+
*
|
|
870
|
+
* Accessibility/resilience (see effects.ts): honours
|
|
871
|
+
* `prefers-reduced-motion` (static gradient, no animation) and falls
|
|
872
|
+
* back to the plain route line with a single console warning if WebGL
|
|
873
|
+
* setup fails.
|
|
874
|
+
*/
|
|
875
|
+
setRouteEffect(effect: RouteEffectName | null, options?: SetRouteEffectOptions): void;
|
|
876
|
+
/**
|
|
877
|
+
* Attach the active route effect to a route line (or detach it with
|
|
878
|
+
* `null`). `RouteLayer` calls this on every `draw()`/`clear()`, so apps
|
|
879
|
+
* normally never do - pass `geometry` to {@link setRouteEffect} for
|
|
880
|
+
* routes drawn outside a RouteLayer.
|
|
881
|
+
*/
|
|
882
|
+
setRouteEffectGeometry(geometry: RouteGeometry | null): void;
|
|
883
|
+
private effectLayerId;
|
|
884
|
+
private removeEffectLayer;
|
|
885
|
+
/** Reconcile the effect state with the map: install, update or remove. */
|
|
886
|
+
private applyRouteEffect;
|
|
397
887
|
/**
|
|
398
888
|
* Toggle 3D building extrusions at runtime — the live equivalent of
|
|
399
889
|
* compiling the style with `buildings_3d: true` (see `Theme`): adds or
|
|
@@ -416,125 +906,6 @@ declare class MapMapMap {
|
|
|
416
906
|
/** Functional alias for {@link MapMapMap}, mirroring the Mapbox `new Map` feel. */
|
|
417
907
|
declare function createMap(options: MapMapOptions): MapMapMap;
|
|
418
908
|
|
|
419
|
-
/**
|
|
420
|
-
* Shared public types for @mapmap/maps.
|
|
421
|
-
*
|
|
422
|
-
* These are runtime-free (type-only) so the pure logic modules that import
|
|
423
|
-
* them stay loadable in Node without a browser or maplibre-gl.
|
|
424
|
-
*/
|
|
425
|
-
/** A longitude/latitude pair, accepted in the three common shapes. */
|
|
426
|
-
type LngLatLike = [number, number] | {
|
|
427
|
-
lng: number;
|
|
428
|
-
lat: number;
|
|
429
|
-
} | {
|
|
430
|
-
lon: number;
|
|
431
|
-
lat: number;
|
|
432
|
-
};
|
|
433
|
-
/** OSRM routing profile. MapMap ships `driving`, `walking` and `truck`. */
|
|
434
|
-
type RouteProfile = "driving" | "walking" | "truck" | (string & {});
|
|
435
|
-
/**
|
|
436
|
-
* Truck / ADR vehicle parameters forwarded to the gateway's OSRM truck
|
|
437
|
-
* vendor extensions. All optional; only `truck`-profile requests honour them.
|
|
438
|
-
*/
|
|
439
|
-
interface TruckParams {
|
|
440
|
-
/** Vehicle height, metres. */
|
|
441
|
-
heightM?: number;
|
|
442
|
-
/** Vehicle width, metres. */
|
|
443
|
-
widthM?: number;
|
|
444
|
-
/** Vehicle length, metres. */
|
|
445
|
-
lengthM?: number;
|
|
446
|
-
/** Gross weight, tonnes. */
|
|
447
|
-
weightT?: number;
|
|
448
|
-
/** Carrying dangerous goods (ADR). */
|
|
449
|
-
hazmat?: boolean;
|
|
450
|
-
/**
|
|
451
|
-
* ADR 8.6.4 tunnel restriction code, e.g. `"C"` or `"B/D"`. The slash is
|
|
452
|
-
* URL-encoded automatically.
|
|
453
|
-
*/
|
|
454
|
-
tunnelCode?: string;
|
|
455
|
-
}
|
|
456
|
-
/** Options for a single route request. */
|
|
457
|
-
interface RouteOptions {
|
|
458
|
-
/** Routing profile. Defaults to `"driving"`. */
|
|
459
|
-
profile?: RouteProfile;
|
|
460
|
-
/** Truck / ADR parameters (only meaningful with `profile: "truck"`). */
|
|
461
|
-
truck?: TruckParams;
|
|
462
|
-
/** Request spoken `voiceInstructions` on each step (see `guidance.ts`). */
|
|
463
|
-
voice?: boolean;
|
|
464
|
-
/** Request visual `bannerInstructions` (and lane data) on each step. */
|
|
465
|
-
banner?: boolean;
|
|
466
|
-
/** BCP 47 narration language, e.g. `"en-GB"`. */
|
|
467
|
-
language?: string;
|
|
468
|
-
}
|
|
469
|
-
/** A parsed GeoJSON LineString geometry (`[lng, lat]` positions). */
|
|
470
|
-
interface RouteGeometry {
|
|
471
|
-
type: "LineString";
|
|
472
|
-
coordinates: [number, number][];
|
|
473
|
-
}
|
|
474
|
-
/** A parsed OSRM route, normalised to the fields callers actually use. */
|
|
475
|
-
interface ParsedRoute {
|
|
476
|
-
/** Total distance, metres. */
|
|
477
|
-
distanceM: number;
|
|
478
|
-
/** Total duration, seconds. */
|
|
479
|
-
durationS: number;
|
|
480
|
-
/** Route line as GeoJSON, ready to hand to a MapLibre source. */
|
|
481
|
-
geometry: RouteGeometry;
|
|
482
|
-
/** The raw OSRM `routes[0]` object, for callers that need leg/step detail. */
|
|
483
|
-
raw: Record<string, unknown>;
|
|
484
|
-
}
|
|
485
|
-
/** The ADR category of a tunnel, `"A"` (least restrictive) … `"E"`. */
|
|
486
|
-
type AdrTunnelCategory = "A" | "B" | "C" | "D" | "E";
|
|
487
|
-
/**
|
|
488
|
-
* Physical truck dimensions for the ADR vehicle profile (mirrors
|
|
489
|
-
* `sn_adr::TruckDimensions`). All optional; unset fields default to the EU
|
|
490
|
-
* 96/53/EC maximum-authorised articulated vehicle (4.0 m high, 2.55 m wide,
|
|
491
|
-
* 16.5 m long, 40 t gross), matching the Rust `Default`.
|
|
492
|
-
*/
|
|
493
|
-
interface AdrDimensions {
|
|
494
|
-
/** Vehicle height, metres. Defaults to `4.0`. */
|
|
495
|
-
heightM?: number;
|
|
496
|
-
/** Vehicle width, metres. Defaults to `2.55`. */
|
|
497
|
-
widthM?: number;
|
|
498
|
-
/** Vehicle length, metres. Defaults to `16.5`. */
|
|
499
|
-
lengthM?: number;
|
|
500
|
-
/** Gross combination weight, tonnes. Defaults to `40`. */
|
|
501
|
-
grossWeightT?: number;
|
|
502
|
-
/** Heaviest single-axle load, tonnes, if known. */
|
|
503
|
-
axleLoadT?: number;
|
|
504
|
-
/** Number of axles, if known. */
|
|
505
|
-
axleCount?: number;
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Input for the gateway's `POST /adr/check` compliance endpoint: the
|
|
509
|
-
* vehicle's ADR profile plus the category of the tunnel to check. Serialised
|
|
510
|
-
* on the wire as `{"adr": <AdrVehicleProfile>, "tunnel_category": "A".."E"}`
|
|
511
|
-
* (see `sn-gateway` `routes/adr.rs`).
|
|
512
|
-
*/
|
|
513
|
-
interface AdrCheckRequest {
|
|
514
|
-
/** Carrying dangerous goods. */
|
|
515
|
-
hazmat: boolean;
|
|
516
|
-
/**
|
|
517
|
-
* The *vehicle load's* ADR 8.6.4 tunnel restriction code, e.g. `"C"` or
|
|
518
|
-
* `"C/E"`. Omit when carrying dangerous goods of unknown code (the
|
|
519
|
-
* gateway then conservatively treats the load as code `B`). This is not
|
|
520
|
-
* the tunnel's category — that goes in {@link tunnelCategory}.
|
|
521
|
-
*/
|
|
522
|
-
tunnelCode?: string;
|
|
523
|
-
/** Vehicle dimensions. Defaults to the EU standard artic maximums. */
|
|
524
|
-
dimensions?: AdrDimensions;
|
|
525
|
-
/** The ADR category of the *tunnel* to check, `"A"` … `"E"`. */
|
|
526
|
-
tunnelCategory: AdrTunnelCategory;
|
|
527
|
-
}
|
|
528
|
-
/** Parsed response from `POST /adr/check`. */
|
|
529
|
-
interface AdrCheckResult {
|
|
530
|
-
/** `"allowed"` or `"blocked"`. */
|
|
531
|
-
status: string;
|
|
532
|
-
/** Human-readable justification citing ADR 8.6.4 where blocked. */
|
|
533
|
-
reason?: string;
|
|
534
|
-
/** The raw response body. */
|
|
535
|
-
raw: Record<string, unknown>;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
909
|
/**
|
|
539
910
|
* RouteLayer - fetch an OSRM route from the MapMap gateway and draw it.
|
|
540
911
|
*
|
|
@@ -558,17 +929,32 @@ interface RouteLayerOptions {
|
|
|
558
929
|
* without a design the layer keeps its built-in signal-blue look.
|
|
559
930
|
*/
|
|
560
931
|
design?: NavRouteDesign;
|
|
932
|
+
/**
|
|
933
|
+
* Colour of the already-travelled part of the line once
|
|
934
|
+
* {@link RouteLayer.setProgress} is used (the Google-style "vanishing
|
|
935
|
+
* route line"). Defaults to a dimmed grey.
|
|
936
|
+
*/
|
|
937
|
+
progressColor?: string;
|
|
561
938
|
}
|
|
562
939
|
/** Draws MapMap routes on a MapLibre map. */
|
|
563
940
|
declare class RouteLayer {
|
|
564
941
|
private readonly map;
|
|
942
|
+
/** The owning MapMapMap, when built from one - fed each drawn route so
|
|
943
|
+
* an armed route effect (`setRouteEffect`) attaches automatically. */
|
|
944
|
+
private readonly owner;
|
|
565
945
|
private readonly baseUrl;
|
|
566
946
|
private readonly apiKey;
|
|
567
947
|
private readonly sourceId;
|
|
568
948
|
private readonly casingLayerId;
|
|
569
949
|
private readonly lineLayerId;
|
|
950
|
+
private readonly maneuverSourceId;
|
|
951
|
+
private readonly maneuverLayerId;
|
|
952
|
+
private readonly arrowImageId;
|
|
570
953
|
private readonly design;
|
|
954
|
+
private readonly progressColor;
|
|
571
955
|
private lastRoute;
|
|
956
|
+
private progress;
|
|
957
|
+
private maneuver;
|
|
572
958
|
constructor(map: MapMapMap | Map, options?: RouteLayerOptions);
|
|
573
959
|
private readonly handleStyleLoad;
|
|
574
960
|
/**
|
|
@@ -589,6 +975,26 @@ declare class RouteLayer {
|
|
|
589
975
|
draw(route: ParsedRoute): void;
|
|
590
976
|
/** Add-or-update the source and layers for a route on the current style. */
|
|
591
977
|
private install;
|
|
978
|
+
/**
|
|
979
|
+
* Sets how much of the route has been travelled, as a fraction in `[0, 1]`
|
|
980
|
+
* of the line's length. The travelled part dims to `progressColor` (the
|
|
981
|
+
* "vanishing route line"); `0` restores the untinted line. The value is
|
|
982
|
+
* remembered across {@link draw} calls and style swaps. Pair with the
|
|
983
|
+
* guidance module's distance-remaining to derive the fraction.
|
|
984
|
+
*/
|
|
985
|
+
setProgress(fraction: number): void;
|
|
986
|
+
/** Applies the current progress fraction to the line layer's gradient. */
|
|
987
|
+
private applyProgress;
|
|
988
|
+
/**
|
|
989
|
+
* Shows (or moves) the upcoming-manoeuvre arrow: a small map-aligned
|
|
990
|
+
* arrow at `lngLat` rotated to `bearingDeg` (clockwise from north).
|
|
991
|
+
* Survives style swaps until {@link clearManeuver}.
|
|
992
|
+
*/
|
|
993
|
+
setManeuver(lngLat: [number, number], bearingDeg: number): void;
|
|
994
|
+
/** Hides the manoeuvre arrow. */
|
|
995
|
+
clearManeuver(): void;
|
|
996
|
+
/** Add-or-update the manoeuvre arrow source/layer for the current style. */
|
|
997
|
+
private installManeuver;
|
|
592
998
|
/** Remove the route's layers and source from the map. */
|
|
593
999
|
clear(): void;
|
|
594
1000
|
/**
|
|
@@ -600,6 +1006,29 @@ declare class RouteLayer {
|
|
|
600
1006
|
|
|
601
1007
|
/** Maximum accepted `data:` puck-image payload (matches Studio's upload cap). */
|
|
602
1008
|
declare const MAX_PUCK_IMAGE_BYTES: number;
|
|
1009
|
+
/**
|
|
1010
|
+
* The signed shortest-arc rotation from `fromDeg` to `toDeg`, in degrees.
|
|
1011
|
+
* Always in `(-180, 180]`, so a heading tween never spins the long way
|
|
1012
|
+
* round the compass (350° -> 10° is +20°, not -340°).
|
|
1013
|
+
*/
|
|
1014
|
+
declare function shortestArcDeg(fromDeg: number, toDeg: number): number;
|
|
1015
|
+
/** Options for {@link PositionPuck}. */
|
|
1016
|
+
interface PositionPuckOptions {
|
|
1017
|
+
/**
|
|
1018
|
+
* Animate between fixes instead of snapping (default `true`). Position
|
|
1019
|
+
* lerps linearly and heading tweens along the shortest arc, over a
|
|
1020
|
+
* duration adapted to the observed fix interval (like the
|
|
1021
|
+
* `NavigationCamera` glide, so puck and camera arrive together). Falls
|
|
1022
|
+
* back to instant placement where `requestAnimationFrame` is missing.
|
|
1023
|
+
*/
|
|
1024
|
+
interpolate?: boolean;
|
|
1025
|
+
/** Test seam: clock override, defaults to `Date.now`. */
|
|
1026
|
+
now?: () => number;
|
|
1027
|
+
/** Test seam: frame scheduler override, defaults to rAF. */
|
|
1028
|
+
requestFrame?: (callback: () => void) => number;
|
|
1029
|
+
/** Test seam: frame canceller override, defaults to cancelAnimationFrame. */
|
|
1030
|
+
cancelFrame?: (handle: number) => void;
|
|
1031
|
+
}
|
|
603
1032
|
/** A current-position puck marker for MapMap maps. */
|
|
604
1033
|
declare class PositionPuck {
|
|
605
1034
|
/** The puck's root DOM element (the Marker element). */
|
|
@@ -608,25 +1037,200 @@ declare class PositionPuck {
|
|
|
608
1037
|
private readonly marker;
|
|
609
1038
|
private readonly design;
|
|
610
1039
|
private added;
|
|
1040
|
+
private readonly interpolate;
|
|
1041
|
+
private readonly now;
|
|
1042
|
+
private readonly requestFrame?;
|
|
1043
|
+
private readonly cancelFrame?;
|
|
1044
|
+
private frameHandle;
|
|
1045
|
+
/** The position/heading currently rendered on the marker. */
|
|
1046
|
+
private rendered;
|
|
1047
|
+
private lastFixAt;
|
|
611
1048
|
/**
|
|
612
1049
|
* Creates the puck (not yet on the map - it appears on the first
|
|
613
1050
|
* {@link setLocation}). The design defaults to the map's
|
|
614
1051
|
* `navDesign.puck` when given a `MapMapMap` whose theme carried an
|
|
615
1052
|
* `extra.nav` block, then to the built-in blue puck.
|
|
616
1053
|
*/
|
|
617
|
-
constructor(map: MapMapMap | Map, design?: NavPuckDesign);
|
|
1054
|
+
constructor(map: MapMapMap | Map, design?: NavPuckDesign, options?: PositionPuckOptions);
|
|
618
1055
|
/**
|
|
619
1056
|
* Moves the puck (adding it to the map on the first call). `headingDeg`
|
|
620
1057
|
* rotates the whole element - arrow or custom image - clockwise from
|
|
621
1058
|
* north; omit it to keep the previous heading.
|
|
1059
|
+
*
|
|
1060
|
+
* With interpolation on (the default) every call after the first glides
|
|
1061
|
+
* from the currently rendered position - a fix arriving mid-tween
|
|
1062
|
+
* retargets smoothly rather than jumping.
|
|
622
1063
|
*/
|
|
623
1064
|
setLocation(location: {
|
|
624
1065
|
lat: number;
|
|
625
1066
|
lon: number;
|
|
626
1067
|
}, headingDeg?: number): void;
|
|
627
|
-
/** Removes the puck from the map. `setLocation` re-adds it. */
|
|
1068
|
+
/** Removes the puck from the map (cancelling any tween). `setLocation` re-adds it. */
|
|
628
1069
|
remove(): void;
|
|
1070
|
+
/** Applies a position/heading to the marker immediately. */
|
|
1071
|
+
private render;
|
|
1072
|
+
/** Runs a linear position lerp + shortest-arc heading tween via rAF. */
|
|
1073
|
+
private tween;
|
|
1074
|
+
/** Cancels an in-flight tween, leaving the marker where it rendered last. */
|
|
1075
|
+
private cancelTween;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* Auto day/night theme switching from sun position.
|
|
1080
|
+
*
|
|
1081
|
+
* A dependency-free solar calculator (the standard sunrise equation, as
|
|
1082
|
+
* published at https://en.wikipedia.org/wiki/Sunrise_equation, itself a
|
|
1083
|
+
* restatement of the NOAA solar calculation details,
|
|
1084
|
+
* https://gml.noaa.gov/grad/solcalc/calcdetails.html) plus a small
|
|
1085
|
+
* scheduler that flips between light and dark at sunrise/sunset. Nothing
|
|
1086
|
+
* here touches a map: pair {@link ThemeScheduler} with
|
|
1087
|
+
* `MapMapMap.setStyle("light" | "dark")` (or any other callback) in the
|
|
1088
|
+
* app. Territory packages already ship paired light/dark styles, so the
|
|
1089
|
+
* switch works offline too.
|
|
1090
|
+
*/
|
|
1091
|
+
/** Sun-times result: either both events, or a polar day/night marker. */
|
|
1092
|
+
type SunTimes = {
|
|
1093
|
+
sunrise: Date;
|
|
1094
|
+
sunset: Date;
|
|
1095
|
+
} | "polarDay" | "polarNight";
|
|
1096
|
+
/**
|
|
1097
|
+
* Sunrise and sunset (standard -0.833° horizon: refraction + solar disc)
|
|
1098
|
+
* for the civil day containing `date` (UTC) at `lat`/`lng`, or a polar
|
|
1099
|
+
* marker when the sun never crosses the horizon that day.
|
|
1100
|
+
*/
|
|
1101
|
+
declare function sunTimes(date: Date, lat: number, lng: number): SunTimes;
|
|
1102
|
+
/** The theme the sun dictates at `date` for `lat`/`lng`. */
|
|
1103
|
+
declare function resolveTheme(date: Date, lat: number, lng: number): "light" | "dark";
|
|
1104
|
+
/** Options for {@link ThemeScheduler}. */
|
|
1105
|
+
interface ThemeSchedulerOptions {
|
|
1106
|
+
/** Latitude used for the solar calculation. */
|
|
1107
|
+
lat: number;
|
|
1108
|
+
/** Longitude used for the solar calculation. */
|
|
1109
|
+
lng: number;
|
|
1110
|
+
/** Called (immediately on construction, then at each sunrise) for light. */
|
|
1111
|
+
onLight: () => void;
|
|
1112
|
+
/** Called (immediately on construction, then at each sunset) for dark. */
|
|
1113
|
+
onDark: () => void;
|
|
1114
|
+
/** Test seam: clock override, defaults to `Date.now`. */
|
|
1115
|
+
now?: () => number;
|
|
1116
|
+
/** Test seam: timer override, defaults to `setTimeout`. */
|
|
1117
|
+
setTimeoutFn?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
1118
|
+
/** Test seam: timer canceller, defaults to `clearTimeout`. */
|
|
1119
|
+
clearTimeoutFn?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Applies the sun-appropriate theme now and at every subsequent
|
|
1123
|
+
* sunrise/sunset until {@link dispose}. No OSS map SDK ships this
|
|
1124
|
+
* out of the box; pair with the OS dark-mode signal in the app if the
|
|
1125
|
+
* user's system preference should win instead.
|
|
1126
|
+
*/
|
|
1127
|
+
declare class ThemeScheduler {
|
|
1128
|
+
private lat;
|
|
1129
|
+
private lng;
|
|
1130
|
+
private readonly onLight;
|
|
1131
|
+
private readonly onDark;
|
|
1132
|
+
private readonly now;
|
|
1133
|
+
private readonly setTimeoutFn;
|
|
1134
|
+
private readonly clearTimeoutFn;
|
|
1135
|
+
private handle;
|
|
1136
|
+
private applied;
|
|
1137
|
+
private disposed;
|
|
1138
|
+
constructor(options: ThemeSchedulerOptions);
|
|
1139
|
+
/** The theme most recently applied, if any. */
|
|
1140
|
+
get current(): "light" | "dark" | undefined;
|
|
1141
|
+
/** Moves the observer (e.g. a new GPS fix region) and re-evaluates. */
|
|
1142
|
+
setPosition(lat: number, lng: number): void;
|
|
1143
|
+
/** Stops all future flips. */
|
|
1144
|
+
dispose(): void;
|
|
1145
|
+
/** Applies the theme for now and arms the timer for the next boundary. */
|
|
1146
|
+
private evaluate;
|
|
1147
|
+
/** Milliseconds until the next sunrise/sunset (or the polar re-check). */
|
|
1148
|
+
private nextBoundaryDelay;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Runtime label-language switching.
|
|
1153
|
+
*
|
|
1154
|
+
* MapMap tiles carry OpenMapTiles multilingual `name:*` fields
|
|
1155
|
+
* (https://openmaptiles.org/schema/), so a map can switch label language
|
|
1156
|
+
* without new tiles: rewrite each symbol layer's `text-field` to prefer
|
|
1157
|
+
* `name:{language}`. `setMapLanguage(map, "de")` does exactly that for
|
|
1158
|
+
* every layer whose text-field reads name fields (other text — road refs,
|
|
1159
|
+
* house numbers — is left untouched). Pass `null` to restore the compiled
|
|
1160
|
+
* style's default (`name:en` first).
|
|
1161
|
+
*
|
|
1162
|
+
* Server-side, themes can bake a language in with `theme.language`; this
|
|
1163
|
+
* helper is the client-side equivalent for user-facing toggles. For
|
|
1164
|
+
* right-to-left scripts (Arabic, Hebrew) also install MapLibre's RTL text
|
|
1165
|
+
* plugin in the app (`maplibregl.setRTLTextPlugin(...)`) — the SDK does
|
|
1166
|
+
* not fetch remote scripts on your behalf.
|
|
1167
|
+
*/
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* The `text-field` expression for labels in `language` — the requested
|
|
1171
|
+
* language first, the Latin transliteration second, the local name last.
|
|
1172
|
+
* `null` yields the compiled default (`name:en`, then `name`).
|
|
1173
|
+
*/
|
|
1174
|
+
declare function languageTextField(language: string | null): unknown;
|
|
1175
|
+
/**
|
|
1176
|
+
* True when a layer's `text-field` reads `name`/`name:*` properties —
|
|
1177
|
+
* i.e. it is a place/POI/road-name label whose language can switch.
|
|
1178
|
+
* Fields reading other properties (`ref` shields, house numbers) are not.
|
|
1179
|
+
*/
|
|
1180
|
+
declare function isNameTextField(textField: unknown): boolean;
|
|
1181
|
+
/**
|
|
1182
|
+
* Switches every name-label layer of the map's current style to
|
|
1183
|
+
* `language` (`null` restores the style's default). Returns the ids of
|
|
1184
|
+
* the layers it rewrote. Throws on a malformed language tag. Reapply
|
|
1185
|
+
* after `setStyle` — a style swap resets label languages.
|
|
1186
|
+
*/
|
|
1187
|
+
declare function setMapLanguage(map: MapMapMap | Map, language: string | null): string[];
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* Probe batch upload - the browser side of opt-in aggregate collection.
|
|
1191
|
+
*
|
|
1192
|
+
* The wasm nav core (`@mapmap/core` `GuidanceSession`) accumulates aggregates
|
|
1193
|
+
* on-device and hands back the exact body to POST via `finishProbeJson()`;
|
|
1194
|
+
* this helper delivers it to the gateway's `POST /v1/probe`, with the same
|
|
1195
|
+
* status handling and retry policy as the mobile SDKs. Aggregates only - the
|
|
1196
|
+
* core is architecturally incapable of emitting a trajectory.
|
|
1197
|
+
*
|
|
1198
|
+
* Consent is the caller's responsibility: only upload for a key whose operator
|
|
1199
|
+
* has set `probe_opt_in`, and - in a browser - only with the user's opt-in
|
|
1200
|
+
* (ePrivacy/PECR) consent. See `docs/PROBE-SDK-INTEGRATION.md`.
|
|
1201
|
+
*
|
|
1202
|
+
* @example
|
|
1203
|
+
* ```ts
|
|
1204
|
+
* const body = session.finishProbeJson(arrived, Date.now());
|
|
1205
|
+
* if (body) void uploadProbeBatch("https://api.mapmap.ai", apiKey, body);
|
|
1206
|
+
* ```
|
|
1207
|
+
*/
|
|
1208
|
+
/** The outcome of an upload attempt. */
|
|
1209
|
+
type ProbeUploadOutcome = "accepted" | "refused" | "notEnabled" | "rejected" | "gaveUp";
|
|
1210
|
+
/** Options for {@link uploadProbeBatch}. All optional. */
|
|
1211
|
+
interface UploadProbeOptions {
|
|
1212
|
+
/** Injectable fetch (defaults to the global). */
|
|
1213
|
+
fetch?: typeof fetch;
|
|
1214
|
+
/** Total attempts including the first (default 4). */
|
|
1215
|
+
maxAttempts?: number;
|
|
1216
|
+
/** Attempt number → delay before the next try, ms (default `attempt*1000`). */
|
|
1217
|
+
backoffMs?: (attempt: number) => number;
|
|
1218
|
+
/** Injectable delay, for deterministic tests (default `setTimeout`). */
|
|
1219
|
+
sleep?: (ms: number) => Promise<void>;
|
|
1220
|
+
/** Abort signal forwarded to fetch. */
|
|
1221
|
+
signal?: AbortSignal;
|
|
629
1222
|
}
|
|
1223
|
+
/** The `/v1/probe` endpoint for a gateway origin (trailing slashes trimmed). */
|
|
1224
|
+
declare function buildProbeUrl(baseUrl: string): string;
|
|
1225
|
+
/**
|
|
1226
|
+
* POST one probe body to `{baseUrl}/v1/probe` with a bearer key. Transient
|
|
1227
|
+
* failures (network or `5xx`) are retried with bounded backoff; permanent ones
|
|
1228
|
+
* (`400`/`403`/`501`) are not. Resolves with the terminal outcome and never
|
|
1229
|
+
* rejects, so a fire-and-forget `void uploadProbeBatch(...)` is safe.
|
|
1230
|
+
*
|
|
1231
|
+
* @param body the string returned by `GuidanceSession.finishProbeJson()`.
|
|
1232
|
+
*/
|
|
1233
|
+
declare function uploadProbeBatch(baseUrl: string, apiKey: string, body: string, options?: UploadProbeOptions): Promise<ProbeUploadOutcome>;
|
|
630
1234
|
|
|
631
1235
|
/** One place to show on the map - a store, depot, branch, POI. */
|
|
632
1236
|
interface Place {
|
|
@@ -639,9 +1243,14 @@ interface Place {
|
|
|
639
1243
|
/** Longitude, degrees. */
|
|
640
1244
|
lon: number;
|
|
641
1245
|
/**
|
|
642
|
-
* Arbitrary extra data (opening hours, phone, …).
|
|
643
|
-
*
|
|
644
|
-
*
|
|
1246
|
+
* Arbitrary extra data (opening hours, phone, …). Every key is copied
|
|
1247
|
+
* verbatim onto the top level of the GeoJSON feature's `properties`,
|
|
1248
|
+
* alongside the reserved `id`, `name` and `__mapmapIndex` keys (which win
|
|
1249
|
+
* on collision) - so scalar values are directly addressable from a
|
|
1250
|
+
* data-driven `color` expression, e.g. `["get", "category"]`. MapLibre
|
|
1251
|
+
* JSON-stringifies nested objects/arrays at render time, so keep anything
|
|
1252
|
+
* you want to style on as a top-level string/number/boolean. The whole
|
|
1253
|
+
* object also comes back on the place handed to `onPlaceClick` / `popup`.
|
|
645
1254
|
*/
|
|
646
1255
|
properties?: Record<string, unknown>;
|
|
647
1256
|
}
|
|
@@ -710,8 +1319,22 @@ interface PlacesLayerOptions {
|
|
|
710
1319
|
clusterRadius?: number;
|
|
711
1320
|
/** Max zoom to cluster at. Defaults to MapLibre's `14`. */
|
|
712
1321
|
clusterMaxZoom?: number;
|
|
713
|
-
/**
|
|
714
|
-
|
|
1322
|
+
/**
|
|
1323
|
+
* Pin colour: a CSS colour string, or a MapLibre expression evaluated
|
|
1324
|
+
* against each feature's `properties` for per-category pins, e.g.
|
|
1325
|
+
* `["match", ["get", "category"], "food", "#e63946", "#3a86ff"]` (see
|
|
1326
|
+
* {@link Place.properties} for what an expression can `get`). Defaults to
|
|
1327
|
+
* MapMap signal blue (`#3a86ff`). Only styles the default circle pins -
|
|
1328
|
+
* ignored with a custom `icon`. A cluster mixes categories, so an
|
|
1329
|
+
* expression never applies to clusters: they use `clusterColor`.
|
|
1330
|
+
*/
|
|
1331
|
+
color?: string | ExpressionSpecification;
|
|
1332
|
+
/**
|
|
1333
|
+
* Cluster circle colour. Defaults to `color` when that is a plain string,
|
|
1334
|
+
* else to MapMap signal blue (a cluster mixes categories, so a
|
|
1335
|
+
* data-driven `color` expression cannot apply to it).
|
|
1336
|
+
*/
|
|
1337
|
+
clusterColor?: string;
|
|
715
1338
|
/**
|
|
716
1339
|
* Custom pin image for unclustered places (a symbol layer instead of the
|
|
717
1340
|
* default circle). If the image fails to load, the circle look is used.
|
|
@@ -740,6 +1363,26 @@ interface PlacesLayerOptions {
|
|
|
740
1363
|
*/
|
|
741
1364
|
popup?: (place: Place) => string | HTMLElement;
|
|
742
1365
|
}
|
|
1366
|
+
/** The generated MapLibre source/layer ids (see {@link PlacesLayer.ids}). */
|
|
1367
|
+
interface PlacesLayerIds {
|
|
1368
|
+
/** The GeoJSON source id. */
|
|
1369
|
+
source: string;
|
|
1370
|
+
/** The unclustered-points layer id (circle, or symbol with `icon`). */
|
|
1371
|
+
points: string;
|
|
1372
|
+
/** The cluster circles layer id (only installed with `cluster: true`). */
|
|
1373
|
+
clusters: string;
|
|
1374
|
+
/** The cluster count badge layer id (only installed with `cluster: true`). */
|
|
1375
|
+
clusterCounts: string;
|
|
1376
|
+
}
|
|
1377
|
+
/** Options for {@link PlacesLayer.select}. */
|
|
1378
|
+
interface PlacesSelectOptions {
|
|
1379
|
+
/** Open the layer's configured `popup` at the place. Defaults to `true`. */
|
|
1380
|
+
popup?: boolean;
|
|
1381
|
+
/** Ease the camera to the place. Defaults to `true`. */
|
|
1382
|
+
flyTo?: boolean;
|
|
1383
|
+
/** Zoom for the camera move (with `flyTo`). Keeps the current zoom if omitted. */
|
|
1384
|
+
zoom?: number;
|
|
1385
|
+
}
|
|
743
1386
|
/**
|
|
744
1387
|
* Normalise a GeoJSON FeatureCollection of Points to `Place[]`. The id comes
|
|
745
1388
|
* from `feature.id`, then `properties.id`, then the feature index; the name
|
|
@@ -768,6 +1411,7 @@ declare class PlacesLayer {
|
|
|
768
1411
|
private readonly clusterRadius;
|
|
769
1412
|
private readonly clusterMaxZoom;
|
|
770
1413
|
private readonly color;
|
|
1414
|
+
private readonly clusterColor;
|
|
771
1415
|
private readonly icon;
|
|
772
1416
|
private readonly wantFitBounds;
|
|
773
1417
|
private readonly onPlaceClick;
|
|
@@ -785,13 +1429,37 @@ declare class PlacesLayer {
|
|
|
785
1429
|
private readonly handleClusterClick;
|
|
786
1430
|
/**
|
|
787
1431
|
* Replace the layer's places - a `Place[]` or a GeoJSON FeatureCollection
|
|
788
|
-
* of Points.
|
|
789
|
-
*
|
|
790
|
-
* `
|
|
1432
|
+
* of Points. Never silently drops an update: once the source exists the
|
|
1433
|
+
* data is applied immediately, even while `isStyleLoaded()` is transiently
|
|
1434
|
+
* `false` mid-render (search-as-you-type just works); calls made before
|
|
1435
|
+
* the source has first been installed are stashed - the latest one wins -
|
|
1436
|
+
* and installed on the next `style.load`. With `fitBounds: true` the
|
|
1437
|
+
* first non-empty set also fits the map view.
|
|
791
1438
|
*/
|
|
792
1439
|
setPlaces(places: PlacesInput): void;
|
|
793
1440
|
/** The layer's current places (normalised to `Place[]`). */
|
|
794
1441
|
get current(): Place[];
|
|
1442
|
+
/**
|
|
1443
|
+
* The generated MapLibre source/layer ids - public API for escape-hatch
|
|
1444
|
+
* styling (`map.setPaintProperty`, `queryRenderedFeatures`, …) beyond the
|
|
1445
|
+
* layer's options. Stable for the layer's lifetime, derived from the `id`
|
|
1446
|
+
* option (default `"mapmap-places"`). The cluster ids are only installed
|
|
1447
|
+
* on the map with `cluster: true` (the default), and `points` is a circle
|
|
1448
|
+
* layer by default or a symbol layer once a custom `icon` has loaded.
|
|
1449
|
+
*/
|
|
1450
|
+
get ids(): PlacesLayerIds;
|
|
1451
|
+
/**
|
|
1452
|
+
* Programmatically select a place by id - list-to-map sync for a store
|
|
1453
|
+
* finder's results list. Opens the layer's configured `popup` at the
|
|
1454
|
+
* place (`popup: false` to skip, no-op without a `popup` option) and
|
|
1455
|
+
* eases the camera to it (`flyTo: false` to skip; `zoom` to also zoom).
|
|
1456
|
+
* Returns the selected place, or `undefined` for an unknown id (in which
|
|
1457
|
+
* case nothing happens). Does NOT invoke `onPlaceClick` - a programmatic
|
|
1458
|
+
* selection is not a user click.
|
|
1459
|
+
*/
|
|
1460
|
+
select(id: string, options?: PlacesSelectOptions): Place | undefined;
|
|
1461
|
+
/** Close the popup opened by {@link select} or a place click, if any. */
|
|
1462
|
+
deselect(): void;
|
|
795
1463
|
/**
|
|
796
1464
|
* The nearest `n` places (default `1`) to `origin` by straight-line
|
|
797
1465
|
* (haversine) distance, each with `distanceM` attached. Pure and instant -
|
|
@@ -969,6 +1637,255 @@ declare class NavigationCamera {
|
|
|
969
1637
|
private scheduleRecentre;
|
|
970
1638
|
private clearRecentreTimer;
|
|
971
1639
|
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Initial great-circle bearing from `a` to `b`, degrees clockwise from
|
|
1642
|
+
* north, normalised to `[0, 360)`.
|
|
1643
|
+
*/
|
|
1644
|
+
declare function bearingBetween(a: [number, number], b: [number, number]): number;
|
|
1645
|
+
/**
|
|
1646
|
+
* The signed shortest-arc rotation from bearing `from` to bearing `to`,
|
|
1647
|
+
* in `(-180, 180]` degrees - the slerp-style delta the flythrough eases
|
|
1648
|
+
* along so the chase cam never spins the long way round.
|
|
1649
|
+
*/
|
|
1650
|
+
declare function shortestArcDelta(from: number, to: number): number;
|
|
1651
|
+
/** A camera pose along a flythrough: where to look from, and which way. */
|
|
1652
|
+
interface FlythroughPose {
|
|
1653
|
+
/** Camera target on the route, `[lng, lat]`. */
|
|
1654
|
+
center: [number, number];
|
|
1655
|
+
/** Chase-cam bearing: towards a point `lookAheadM` up the road. */
|
|
1656
|
+
bearing: number;
|
|
1657
|
+
}
|
|
1658
|
+
/**
|
|
1659
|
+
* The camera pose at progress `t` (0-1) along a route: the interpolated
|
|
1660
|
+
* point that fraction of the total distance along the line, with a
|
|
1661
|
+
* chase-cam bearing towards the point `lookAheadM` further on. Pure -
|
|
1662
|
+
* exported for tests and for apps that drive the camera themselves.
|
|
1663
|
+
*/
|
|
1664
|
+
declare function flythroughPose(coordinates: [number, number][], t: number, lookAheadM?: number): FlythroughPose;
|
|
1665
|
+
interface FlythroughOptions {
|
|
1666
|
+
/**
|
|
1667
|
+
* Camera tilt in degrees, clamped 0-85. Default `60` (the cinematic
|
|
1668
|
+
* chase look; see {@link NavigationCameraOptions.pitch} for caveats
|
|
1669
|
+
* above 60).
|
|
1670
|
+
*/
|
|
1671
|
+
pitch?: number;
|
|
1672
|
+
/** Camera zoom held through the replay. Default `16`. */
|
|
1673
|
+
zoom?: number;
|
|
1674
|
+
/**
|
|
1675
|
+
* Total replay duration in milliseconds. Default `20000`. Ignored when
|
|
1676
|
+
* `speedMps` is given.
|
|
1677
|
+
*/
|
|
1678
|
+
durationMs?: number;
|
|
1679
|
+
/**
|
|
1680
|
+
* Replay ground speed in metres/second along the route - the duration
|
|
1681
|
+
* becomes `routeLength / speedMps`. Wins over `durationMs`.
|
|
1682
|
+
*/
|
|
1683
|
+
speedMps?: number;
|
|
1684
|
+
/**
|
|
1685
|
+
* How far up the road the chase cam looks to derive its bearing,
|
|
1686
|
+
* metres. Default `200`; larger = calmer bearing on wiggly roads.
|
|
1687
|
+
*/
|
|
1688
|
+
lookAheadM?: number;
|
|
1689
|
+
/**
|
|
1690
|
+
* Bearing smoothing rate per second (the fraction of the remaining
|
|
1691
|
+
* shortest-arc turn closed each second). Default `3`; higher = snappier.
|
|
1692
|
+
*/
|
|
1693
|
+
bearingEase?: number;
|
|
1694
|
+
}
|
|
1695
|
+
/** The handle a {@link flythrough} returns. */
|
|
1696
|
+
interface FlythroughController {
|
|
1697
|
+
/** Start (or resume) the replay. Restarts from 0 when it had finished. */
|
|
1698
|
+
play(): void;
|
|
1699
|
+
/** Freeze the replay where it is. */
|
|
1700
|
+
pause(): void;
|
|
1701
|
+
/** Pause and rewind to the start (the camera jumps to the start pose). */
|
|
1702
|
+
stop(): void;
|
|
1703
|
+
/** Scrub to progress `t` (0-1, clamped) and apply the pose immediately. */
|
|
1704
|
+
seek(t: number): void;
|
|
1705
|
+
/** Playback-rate multiplier (`1` = real duration, `2` = double). */
|
|
1706
|
+
speed: number;
|
|
1707
|
+
/** Current progress, 0-1. */
|
|
1708
|
+
readonly progress: number;
|
|
1709
|
+
/** Whether the replay is currently advancing. */
|
|
1710
|
+
readonly playing: boolean;
|
|
1711
|
+
/** Subscribe to progress updates; returns the unsubscribe function. */
|
|
1712
|
+
onProgress(listener: (t: number) => void): () => void;
|
|
1713
|
+
/** Pause and detach everything. The controller is dead afterwards. */
|
|
1714
|
+
destroy(): void;
|
|
1715
|
+
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Cinematic route replay: fly the camera along a route line with a
|
|
1718
|
+
* chase-cam bearing (eased along the shortest arc, so junctions glide
|
|
1719
|
+
* instead of spinning), at a configurable pitch/zoom/speed. Returns a
|
|
1720
|
+
* transport-style controller; nothing moves until `play()` or `seek()`.
|
|
1721
|
+
*
|
|
1722
|
+
* ```ts
|
|
1723
|
+
* const route = await routes.route(from, to);
|
|
1724
|
+
* const replay = flythrough(map, route, { pitch: 60, durationMs: 15000 });
|
|
1725
|
+
* replay.onProgress((t) => scrubber.value = String(t));
|
|
1726
|
+
* replay.play();
|
|
1727
|
+
* ```
|
|
1728
|
+
*
|
|
1729
|
+
* Drives the camera with `jumpTo` once per animation frame (the standard
|
|
1730
|
+
* MapLibre scrub pattern). Runs under any projection; on globe the ride is
|
|
1731
|
+
* unanchored but valid. Accepts a `ParsedRoute` (from `RouteLayer`) or a
|
|
1732
|
+
* bare GeoJSON LineString geometry.
|
|
1733
|
+
*/
|
|
1734
|
+
declare function flythrough(map: MapMapMap | Map, route: RouteGeometry | ParsedRoute, options?: FlythroughOptions): FlythroughController;
|
|
1735
|
+
/**
|
|
1736
|
+
* Scrollytelling: bind a flythrough to a scroll position, so scrolling a
|
|
1737
|
+
* story column scrubs the camera along the route. The binder pauses the
|
|
1738
|
+
* controller (scroll owns the timeline) and seeks it to the scrolled
|
|
1739
|
+
* fraction - immediately on bind, then on every scroll. Returns the
|
|
1740
|
+
* unbind function.
|
|
1741
|
+
*
|
|
1742
|
+
* ```ts
|
|
1743
|
+
* const replay = flythrough(map, route);
|
|
1744
|
+
* const unbind = bindFlythroughToScroll(replay, document.querySelector("#story")!);
|
|
1745
|
+
* ```
|
|
1746
|
+
*/
|
|
1747
|
+
declare function bindFlythroughToScroll(controller: FlythroughController, target?: HTMLElement | Window): () => void;
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* IsochroneLayer - walkability rings (reachability contours) on a MapMap
|
|
1751
|
+
* map, backed by the gateway's live `POST /isochrone` endpoint (Valhalla
|
|
1752
|
+
* isochrone; see docs/API.md).
|
|
1753
|
+
*
|
|
1754
|
+
* One call - `showReachability({ origin, mode: "walk", minutes: [5, 10, 15] })` -
|
|
1755
|
+
* renders concentric reachability rings: graduated-opacity fills (nearest
|
|
1756
|
+
* ring strongest), contour outlines, and "N min" labels along each
|
|
1757
|
+
* contour. The estate-agent / store-catchment / "how walkable is this
|
|
1758
|
+
* flat?" view in one line.
|
|
1759
|
+
*
|
|
1760
|
+
* Follows the RouteLayer pattern: gateway base URL/key picked up from a
|
|
1761
|
+
* `MapMapMap` automatically, layers survive `setStyle` theme swaps via
|
|
1762
|
+
* re-installation on `style.load`, and `clear()`/`destroy()` tidy up.
|
|
1763
|
+
*/
|
|
1764
|
+
|
|
1765
|
+
/**
|
|
1766
|
+
* Travel mode for the rings. The friendly names map onto gateway costings
|
|
1767
|
+
* (`walk` → `pedestrian`, `cycle` → `bicycle`, `drive` → `auto`); any
|
|
1768
|
+
* other string is passed through as a raw Valhalla costing (e.g.
|
|
1769
|
+
* `"truck"`, `"motor_scooter"`).
|
|
1770
|
+
*/
|
|
1771
|
+
type ReachabilityMode = "walk" | "cycle" | "drive" | "truck" | (string & {});
|
|
1772
|
+
interface ShowReachabilityOptions {
|
|
1773
|
+
/** Where the rings radiate from. */
|
|
1774
|
+
origin: LngLatLike;
|
|
1775
|
+
/** Travel mode. Defaults to `"walk"` - these are walkability rings. */
|
|
1776
|
+
mode?: ReachabilityMode;
|
|
1777
|
+
/** Ring contours in minutes, e.g. `[5, 10, 15]`. At least one. */
|
|
1778
|
+
minutes: number[];
|
|
1779
|
+
/** Ring colour. Defaults to MapMap signal blue. */
|
|
1780
|
+
color?: string;
|
|
1781
|
+
/**
|
|
1782
|
+
* Valhalla-style costing options forwarded verbatim, e.g.
|
|
1783
|
+
* `{ pedestrian: { use_lit: 1.0 } }`.
|
|
1784
|
+
*/
|
|
1785
|
+
costingOptions?: Record<string, unknown>;
|
|
1786
|
+
}
|
|
1787
|
+
interface IsochroneLayerOptions {
|
|
1788
|
+
/** Gateway base URL. Defaults to the map's `baseUrl` when given a map. */
|
|
1789
|
+
baseUrl?: string;
|
|
1790
|
+
/** Gateway API key. Defaults to the map's `apiKey` when given a map. */
|
|
1791
|
+
apiKey?: string;
|
|
1792
|
+
/** Unique id prefix for the source/layers. Defaults to `"mapmap-isochrone"`. */
|
|
1793
|
+
id?: string;
|
|
1794
|
+
}
|
|
1795
|
+
/** The GeoJSON FeatureCollection the gateway returns, passed through. */
|
|
1796
|
+
interface IsochroneFeatureCollection {
|
|
1797
|
+
type: "FeatureCollection";
|
|
1798
|
+
features: {
|
|
1799
|
+
type: "Feature";
|
|
1800
|
+
geometry: {
|
|
1801
|
+
type: string;
|
|
1802
|
+
coordinates: unknown;
|
|
1803
|
+
};
|
|
1804
|
+
properties?: Record<string, unknown> | null;
|
|
1805
|
+
}[];
|
|
1806
|
+
}
|
|
1807
|
+
/** Renders reachability rings from the gateway's `POST /isochrone`. */
|
|
1808
|
+
declare class IsochroneLayer {
|
|
1809
|
+
private readonly map;
|
|
1810
|
+
private readonly baseUrl;
|
|
1811
|
+
private readonly apiKey;
|
|
1812
|
+
private readonly sourceId;
|
|
1813
|
+
private readonly fillLayerId;
|
|
1814
|
+
private readonly lineLayerId;
|
|
1815
|
+
private readonly labelLayerId;
|
|
1816
|
+
private lastData;
|
|
1817
|
+
private lastMinutes;
|
|
1818
|
+
private lastColor;
|
|
1819
|
+
constructor(map: MapMapMap | Map, options?: IsochroneLayerOptions);
|
|
1820
|
+
private readonly handleStyleLoad;
|
|
1821
|
+
/**
|
|
1822
|
+
* Fetch and render reachability rings. Returns the GeoJSON
|
|
1823
|
+
* FeatureCollection the gateway produced (each feature carries a
|
|
1824
|
+
* `contour` property in minutes), for callers who also want the raw
|
|
1825
|
+
* shapes. Replaces any rings already shown by this layer.
|
|
1826
|
+
*/
|
|
1827
|
+
showReachability(options: ShowReachabilityOptions): Promise<IsochroneFeatureCollection>;
|
|
1828
|
+
/** The most recently drawn rings, if any. */
|
|
1829
|
+
get current(): IsochroneFeatureCollection | undefined;
|
|
1830
|
+
/** Draw (or update) a ring collection. Safe before the style has loaded. */
|
|
1831
|
+
private draw;
|
|
1832
|
+
/** Add-or-update the source and ring layers on the current style. */
|
|
1833
|
+
private install;
|
|
1834
|
+
/**
|
|
1835
|
+
* Graduated fill opacity: the nearest contour (fewest minutes) is the
|
|
1836
|
+
* most opaque, the farthest the faintest, interpolated on each
|
|
1837
|
+
* feature's `contour` property. With one contour it is a constant.
|
|
1838
|
+
*/
|
|
1839
|
+
private fillOpacity;
|
|
1840
|
+
/** Remove the rings' layers and source from the map. */
|
|
1841
|
+
clear(): void;
|
|
1842
|
+
/** Remove the rings and detach the layer's `style.load` listener. */
|
|
1843
|
+
destroy(): void;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
/**
|
|
1847
|
+
* Self-diagnosing map errors - the SDK tells you what went wrong and how
|
|
1848
|
+
* to fix it, instead of a silently blank map.
|
|
1849
|
+
*
|
|
1850
|
+
* `MapMapMap` runs these checks at construction (and listens for tile
|
|
1851
|
+
* auth failures); each detected issue produces ONE `console.error` per
|
|
1852
|
+
* page with an actionable message and a docs link. Everything here is
|
|
1853
|
+
* best-effort and defensive: no check may ever throw or require a DOM
|
|
1854
|
+
* (server-side rendering and Node tests just skip the DOM checks).
|
|
1855
|
+
*
|
|
1856
|
+
* Issues covered - the documented gotchas that burn real integrations:
|
|
1857
|
+
* - a container whose height resolves to 0px (MapLibre renders into a
|
|
1858
|
+
* 0-tall canvas: no error, no map)
|
|
1859
|
+
* - a container element that is not attached to the DOM
|
|
1860
|
+
* - two maplibre-gl copies on one page (duplicate dependency /
|
|
1861
|
+
* micro-frontends - breaks the shared WebGL context and styles)
|
|
1862
|
+
* - WebGL unavailable (headless browsers, blocked GPU, old devices)
|
|
1863
|
+
* - missing/invalid API key (a 401 from the tile or routing endpoints)
|
|
1864
|
+
*/
|
|
1865
|
+
/** The distinct issues the diagnostics can report. */
|
|
1866
|
+
type DiagnosticIssue = "container-zero-height" | "container-detached" | "duplicate-maplibre" | "webgl-unavailable" | "invalid-api-key";
|
|
1867
|
+
/** Reset the once-per-page dedup - for tests (and hot-reload tooling). */
|
|
1868
|
+
declare function resetDiagnostics(): void;
|
|
1869
|
+
/** What `runMapDiagnostics` needs; everything optional and structural. */
|
|
1870
|
+
interface MapDiagnosticsInput {
|
|
1871
|
+
/** The `container` option as given: an element or an element id. */
|
|
1872
|
+
container?: string | HTMLElement;
|
|
1873
|
+
/**
|
|
1874
|
+
* The constructed map (or any object with a MapLibre-style `on`). Used
|
|
1875
|
+
* to watch for tile-request auth failures.
|
|
1876
|
+
*/
|
|
1877
|
+
map?: unknown;
|
|
1878
|
+
/** The maplibre-gl module the SDK is using (duplicate detection). */
|
|
1879
|
+
maplibre?: unknown;
|
|
1880
|
+
/** The gateway API key, if one was configured. */
|
|
1881
|
+
apiKey?: string | undefined;
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Run the construction-time checks and attach the 401 watcher. Called by
|
|
1885
|
+
* `MapMapMap` automatically; exported for apps wrapping a raw
|
|
1886
|
+
* `maplibregl.Map` that still want the self-diagnosis.
|
|
1887
|
+
*/
|
|
1888
|
+
declare function runMapDiagnostics(input: MapDiagnosticsInput): void;
|
|
972
1889
|
|
|
973
1890
|
/**
|
|
974
1891
|
* AdrCheck - optional helper for the gateway's `POST /adr/check` endpoint.
|
|
@@ -1177,4 +2094,121 @@ declare class GuidanceBanner {
|
|
|
1177
2094
|
update(banner: BannerInstruction | null): void;
|
|
1178
2095
|
}
|
|
1179
2096
|
|
|
1180
|
-
|
|
2097
|
+
/**
|
|
2098
|
+
* Spoken turn-by-turn guidance over the browser's `SpeechSynthesis`.
|
|
2099
|
+
*
|
|
2100
|
+
* {@link VoiceGuidance} consumes the guidance updates emitted by the
|
|
2101
|
+
* `@mapmap/core` wasm `GuidanceSession` (`{ state: "navigating" | "arrived"
|
|
2102
|
+
* | "offRoute", spoken?, severity?, … }`). The core already schedules each
|
|
2103
|
+
* spoken prompt by its trigger distance and repeats it on every update
|
|
2104
|
+
* until it is superseded, so the speaking rule is simple: announce each
|
|
2105
|
+
* `utteranceId` exactly once, the first time it appears.
|
|
2106
|
+
*
|
|
2107
|
+
* Severity (derived in the Rust core — see `InstructionSeverity`) maps to
|
|
2108
|
+
* prosody and earcons:
|
|
2109
|
+
*
|
|
2110
|
+
* - `info` — normal manoeuvres: base rate/pitch, no earcon by default;
|
|
2111
|
+
* - `warning` — approaching a restriction (toll, ferry): slight pitch
|
|
2112
|
+
* lift, warning earcon when configured;
|
|
2113
|
+
* - `critical` — prohibitions (ADR tunnel block, gate): pitch and rate
|
|
2114
|
+
* lift, pending speech cancelled so the prompt is never queued behind
|
|
2115
|
+
* chatter, critical earcon when configured.
|
|
2116
|
+
*
|
|
2117
|
+
* Off-route updates carry no instruction; they play the warning earcon
|
|
2118
|
+
* once per off-route episode (the app recalculates and speech resumes on
|
|
2119
|
+
* the new session).
|
|
2120
|
+
*
|
|
2121
|
+
* Earcons are lazy URLs (see `map-assets/earcons/`, generated by
|
|
2122
|
+
* `scripts/generate-earcons.py`) — nothing is bundled with the SDK.
|
|
2123
|
+
* Everything no-ops safely where `speechSynthesis` is unavailable
|
|
2124
|
+
* (non-browser contexts, some webviews).
|
|
2125
|
+
*/
|
|
2126
|
+
/** Instruction urgency, as emitted by the core (`InstructionSeverity`). */
|
|
2127
|
+
type GuidanceSeverity = "info" | "warning" | "critical";
|
|
2128
|
+
/** The spoken prompt of a core guidance update. */
|
|
2129
|
+
interface GuidanceSpokenPrompt {
|
|
2130
|
+
/** Plain text for speech synthesis. */
|
|
2131
|
+
text: string;
|
|
2132
|
+
/** SSML form; browsers reject raw SSML, so it is stripped to text. */
|
|
2133
|
+
ssml?: string | null;
|
|
2134
|
+
/** Metres before the manoeuvre at which the core released the prompt. */
|
|
2135
|
+
triggerDistanceM: number;
|
|
2136
|
+
/** Unique utterance id — the de-duplication key. */
|
|
2137
|
+
utteranceId: string;
|
|
2138
|
+
}
|
|
2139
|
+
/** The subset of a core guidance update that {@link VoiceGuidance} reads. */
|
|
2140
|
+
interface VoiceGuidanceUpdate {
|
|
2141
|
+
/** Guidance state, as emitted by the wasm `GuidanceSession`. */
|
|
2142
|
+
state: "navigating" | "arrived" | "offRoute";
|
|
2143
|
+
/** Spoken prompt currently due (repeated until superseded). */
|
|
2144
|
+
spoken?: GuidanceSpokenPrompt | null;
|
|
2145
|
+
/** Urgency of the current step's instruction (default `info`). */
|
|
2146
|
+
severity?: GuidanceSeverity;
|
|
2147
|
+
/** BCP 47 locale of the instruction text, when the payload carries one. */
|
|
2148
|
+
voiceLocale?: string;
|
|
2149
|
+
}
|
|
2150
|
+
/** Options for {@link VoiceGuidance}. */
|
|
2151
|
+
interface VoiceGuidanceOptions {
|
|
2152
|
+
/** BCP 47 language for utterances, e.g. `en-GB`. An update's
|
|
2153
|
+
* `voiceLocale` takes precedence when present. */
|
|
2154
|
+
lang?: string;
|
|
2155
|
+
/** Base speech rate (0.1–10, default 1). Critical prompts speak
|
|
2156
|
+
* slightly faster than this base. */
|
|
2157
|
+
rate?: number;
|
|
2158
|
+
/** Volume for speech and earcons, 0–1 (default 1). */
|
|
2159
|
+
volume?: number;
|
|
2160
|
+
/** Start muted. */
|
|
2161
|
+
muted?: boolean;
|
|
2162
|
+
/** Severity → earcon audio URL. Absent entries play nothing. */
|
|
2163
|
+
earcons?: Partial<Record<GuidanceSeverity, string>>;
|
|
2164
|
+
}
|
|
2165
|
+
/** Speech parameters for one severity level. */
|
|
2166
|
+
interface SeverityProsody {
|
|
2167
|
+
/** Utterance rate. */
|
|
2168
|
+
rate: number;
|
|
2169
|
+
/** Utterance pitch (0–2, 1 = neutral). */
|
|
2170
|
+
pitch: number;
|
|
2171
|
+
/** Whether pending speech is cancelled before this prompt. */
|
|
2172
|
+
interrupt: boolean;
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* Prosody for a severity level at a base rate. Pure — exported for tests
|
|
2176
|
+
* and for custom voice layers that want the same house style.
|
|
2177
|
+
*/
|
|
2178
|
+
declare function severityProsody(severity: GuidanceSeverity, baseRate?: number): SeverityProsody;
|
|
2179
|
+
/**
|
|
2180
|
+
* Speaks core guidance updates through the browser's `SpeechSynthesis`,
|
|
2181
|
+
* with severity-aware prosody, optional earcons, and mute/volume
|
|
2182
|
+
* controls. Feed every update from the wasm `GuidanceSession` to
|
|
2183
|
+
* {@link VoiceGuidance.update}.
|
|
2184
|
+
*/
|
|
2185
|
+
declare class VoiceGuidance {
|
|
2186
|
+
private readonly options;
|
|
2187
|
+
private volume;
|
|
2188
|
+
private mutedState;
|
|
2189
|
+
private lastUtteranceId;
|
|
2190
|
+
private offRouteAnnounced;
|
|
2191
|
+
constructor(options?: VoiceGuidanceOptions);
|
|
2192
|
+
/** Whether this environment can speak at all. */
|
|
2193
|
+
get available(): boolean;
|
|
2194
|
+
/** Whether announcements are currently muted. */
|
|
2195
|
+
get muted(): boolean;
|
|
2196
|
+
/** Mute announcements (also cancels anything mid-utterance). */
|
|
2197
|
+
mute(): void;
|
|
2198
|
+
/** Unmute announcements. Prompts seen while muted are not replayed. */
|
|
2199
|
+
unmute(): void;
|
|
2200
|
+
/** Set the volume for speech and earcons (clamped to 0–1). */
|
|
2201
|
+
setVolume(volume: number): void;
|
|
2202
|
+
/**
|
|
2203
|
+
* Consume one guidance update. Speaks the update's prompt the first
|
|
2204
|
+
* time its `utteranceId` appears; plays the warning earcon once per
|
|
2205
|
+
* off-route episode. Safe to call in any environment.
|
|
2206
|
+
*/
|
|
2207
|
+
update(update: VoiceGuidanceUpdate): void;
|
|
2208
|
+
/** Cancel any speech in progress and forget the de-duplication state. */
|
|
2209
|
+
dispose(): void;
|
|
2210
|
+
private speak;
|
|
2211
|
+
private playEarcon;
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
export { AdrCheck, type AdrCheckOptions, type AdrCheckRequest, type AdrCheckResult, type AdrDimensions, type AdrTunnelCategory, type BannerComponent, type BannerContent, type BannerInstruction, type BuildStyleOptions, type CameraFix, DEFAULT_GLYPHS_URL, DEFAULT_TERRITORY_TILES_URL, type DiagnosticIssue, EFFECTS_METADATA_KEY, FLOW_DEFAULTS, FULL_ATTRIBUTION, FlowRouteEffectLayer, type FlythroughController, type FlythroughOptions, type FlythroughPose, GuidanceBanner, type GuidanceSeverity, type GuidanceSpokenPrompt, type IsochroneFeatureCollection, IsochroneLayer, type IsochroneLayerOptions, LOGO_SVG, type LaneIndication, type LayerOverride, type LngLatLike, LogoControl, type LogoOptions, type LogoPosition, MAX_PUCK_IMAGE_BYTES, type MapDiagnosticsInput, MapMapMap, type MapMapOptions, type MapMapTheme, NAV_CAMERA_DEFAULTS, type NavBannerDesign, type NavCameraDesign, type NavDesign, type NavPuckDesign, type NavRouteDesign, NavigationCamera, type NavigationCameraMode, type NavigationCameraOptions, type NearestByDriveTimeOptions, OPENMAPTILES_ATTRIBUTION, OSM_ATTRIBUTION, PALETTE_SLOTS, POI_CATEGORY_COLORS, POI_CATEGORY_IDS, POI_CLASS_CATEGORIES, type ParsedRoute, type Place, type PlacePointFeature, type PlaceWithDistance, type PlaceWithDriveTime, type PlacesFeatureCollection, type PlacesIcon, type PlacesInput, PlacesLayer, type PlacesLayerIds, type PlacesLayerOptions, type PlacesSelectOptions, type PoiCategoryDesign, type PoiDesign, PositionPuck, type PositionPuckOptions, type ProbeUploadOutcome, RIBBON_FLOATS_PER_VERTEX, ROUTE_EFFECTS, type ReachabilityMode, type RibbonMesh, type RouteEffectLayer, type RouteEffectName, type RouteFlowOptions, type RouteGeometry, RouteLayer, type RouteLayerOptions, type RouteOptions, type RouteProfile, SIGNAL_BLUE, SOURCE_LAYERS, type SetRouteEffectOptions, type SeverityProsody, type ShowReachabilityOptions, type SpeakOptions, type StepGuidance, type SunTimes, type Theme, type ThemeEffects, ThemeScheduler, type ThemeSchedulerOptions, type TruckParams, type UploadProbeOptions, VoiceGuidance, type VoiceGuidanceOptions, type VoiceGuidanceUpdate, type VoiceInstruction, applyPoiDesign, bannerLanes, bearingBetween, bindFlythroughToScroll, buildAdrCheckBody, buildProbeUrl, buildRouteQuery, buildRouteUrl, buildStyle, builtInPoiColor, createMap, createRouteEffect, defaultNavDesign, defaultPoiDesign, directionArrow, effectsFromStyleMetadata, extractGuidance, flythrough, flythroughPose, formatCoord, formatCoords, haversineDistanceM, isNameTextField, languageTextField, lngLatToMercator, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, resetDiagnostics, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, uploadProbeBatch };
|