@mapmap/maps 0.8.0 → 0.10.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/README.md CHANGED
@@ -333,6 +333,24 @@ small custom images, each with an optional label. They are placed in
333
333
  Studio's Markers tab, so a designer can ship "here are our depots" with the
334
334
  style itself - no places data, no code change:
335
335
 
336
+ > **Glyph markers now render without this SDK.** A published theme's glyph
337
+ > pins and dots are compiled INTO its `style.json` - an inline
338
+ > `mm-user-markers` GeoJSON source plus two symbol layers over MapMap's SDF
339
+ > marker sprite - so they draw in **any** MapLibre client that loads the
340
+ > style URL: `new maplibregl.Map({ style })`, MapLibre Native on iOS and
341
+ > Android, static/server-side renderers. No `MapMapMap`, no `MarkersLayer`,
342
+ > no code at all.
343
+ >
344
+ > The one exception is a marker with a custom **`image`** (`data:` URI):
345
+ > a static sprite cannot carry per-theme artwork, so the compiler skips
346
+ > those items rather than drawing the wrong glyph in their place. They
347
+ > render only through `MarkersLayer`, below.
348
+ >
349
+ > You still want `MarkersLayer` to **change** markers at runtime, to draw
350
+ > custom-image markers, or for short-text numbered pins. Use
351
+ > `hasBakedMarkers(map)` to find out whether the current style is already
352
+ > drawing its own.
353
+
336
354
  ```ts
337
355
  import { MarkersLayer, markersFromThemeUrl } from "@mapmap/maps";
338
356
 
@@ -392,6 +410,16 @@ layer.destroy(); // clear() + detach the style.load listener
392
410
  style that INCLUDES runtime sources/layers, so a diffed `setStyle`
393
411
  removes `mm-user-markers` and the `style.load` that `setState` fires
394
412
  afterwards is what puts it back.
413
+ - **Against a baked style it takes over, it does not double-draw.** A style
414
+ compiled from a theme with markers already carries `mm-user-markers` plus
415
+ a second layer, `mm-user-markers-glyph`, that this SDK never creates.
416
+ When you give a `MarkersLayer` markers on such a style, it removes both
417
+ baked layers and installs its own - so the markers appear exactly once,
418
+ and custom-image and short-text pins (which the baked layers cannot
419
+ carry) work as they always have. A `MarkersLayer` you construct and never
420
+ hand markers to leaves the baked layers completely alone, so the style
421
+ keeps drawing them. `hasBakedMarkers(map)` reports whether the current
422
+ style is baked; `BAKED_MARKERS_GLYPH_ID` is the layer id it looks for.
395
423
 
396
424
  ### `class NavigationCamera`
397
425
 
@@ -474,9 +502,15 @@ const map = new MapMapMap({
474
502
  below.
475
503
  - **`extra.markers`** (Studio's custom markers & labels, schema v1) rides
476
504
  the same way: `{ "version": 1, "items": [ { "id", "lng", "lat", "icon",
477
- "colour", "size", "label", "image" } ] }`, up to 200 items, never part of
478
- the compiled `style.json`. Read it with `markersFromTheme(theme)` /
479
- `markersFromThemeUrl(url)` and draw it with `MarkersLayer` (above).
505
+ "colour", "size", "label", "image" } ] }`, up to 200 items. The raw block
506
+ is never copied into `style.json`, but it IS compiled into it: every
507
+ glyph marker becomes an `mm-user-markers` GeoJSON source plus the
508
+ `mm-user-markers` / `mm-user-markers-glyph` symbol layers over the SDF
509
+ marker sprite (the style's `sprite` is set to it unless the theme names
510
+ its own), so the markers render from the style URL alone in any MapLibre
511
+ client. Markers with a custom `image` are the exception - they are left
512
+ out of the bake and drawn only by `MarkersLayer`. Read the block with
513
+ `markersFromTheme(theme)` / `markersFromThemeUrl(url)`.
480
514
  `extra` as a whole is bounded at 256 KB serialised, and each marker
481
515
  `image` at 64 KB decoded - the per-image caps multiply, so a few
482
516
  full-size marker images will hit the block cap first.
@@ -772,8 +806,16 @@ Neither the mark nor the attribution can be switched off:
772
806
  `attributionControl: { customAttribution: "© Your Co" }` adds your own
773
807
  credit alongside the OSM one.
774
808
 
775
- In a bottom corner the mark sits above the attribution: MapLibre prepends
776
- controls in the bottom corners, so the control added last is the highest.
809
+ The default layout is the canonical one: OpenStreetMap attribution in
810
+ small print bottom-left, the MapMap mark bottom-right. Pass
811
+ `attributionPosition: "bottom-right" | "bottom-left" | "top-left" |
812
+ "top-right"` to `createMap` to mount the credit in another corner; there
813
+ is no need to dig the control out of the map's internals to move it. The
814
+ two are never in the same corner, because stacking the mark on the credit
815
+ makes a line the ODbL requires unreadable. The SDK enforces that: if the
816
+ attribution's corner and the mark's corner collide (via
817
+ `attributionPosition`, `logo.position` or both), the mark moves to the
818
+ opposite bottom corner and one `console.warn` is logged for that map.
777
819
 
778
820
  ## Turn-by-turn guidance
779
821
 
@@ -922,3 +964,18 @@ npm test # vitest (pure-logic unit tests, no browser)
922
964
 
923
965
  Proprietary - © 2026 Mapmap AI Ltd, distributed under a commercial licence.
924
966
  See [`LICENSE`](./LICENSE).
967
+
968
+ ## 3D terrain
969
+
970
+ ```ts
971
+ createMap({ container: "map", terrain: true });
972
+ createMap({ container: "map", terrain: { exaggeration: 1.4, hillshade: true } });
973
+ map.setTerrain(false);
974
+ ```
975
+
976
+ The default DEM is the same dataset the gateway samples for `POST
977
+ /elevation`, so rendered terrain and elevation queries agree. The SDK
978
+ re-applies terrain across style swaps, gives hillshade its own DEM source
979
+ (sharing one causes artefacts) and carries the DEM attribution. Note that
980
+ terrain displaces by ABSOLUTE elevation: custom layers drawing in a local
981
+ frame must add `map.queryTerrainElevation(...)` at their anchor.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,77 @@
1
- import maplibregl, { CustomLayerInterface, Map, StyleSpecification, MapOptions, ExpressionSpecification } from 'maplibre-gl';
1
+ import maplibregl, { Map, CustomLayerInterface, StyleSpecification, MapOptions, ExpressionSpecification } from 'maplibre-gl';
2
2
  export { DirectionIconName, DirectionIconStep, directionIconSvg, directionIcons, iconNameForManeuver, iconNameForStep, iconNamesForSteps } from './direction-icons.js';
3
3
 
4
+ /**
5
+ * 3D terrain and hillshading for MapMap maps.
6
+ *
7
+ * MapLibre can displace the ground by a DEM and shade it, but only if a
8
+ * `raster-dem` source is present and re-applied after every style load.
9
+ * This module owns that lifecycle so `new MapMapMap({ terrain: true })` is
10
+ * all a caller needs.
11
+ *
12
+ * Six things this encodes, each of which cost real debugging time building
13
+ * the survey viewer:
14
+ *
15
+ * 1. Terrain displaces by ABSOLUTE elevation. `queryTerrainElevation`
16
+ * returns absolute metres, so custom layers drawing in a local frame
17
+ * must add the terrain height at the map centre — otherwise every
18
+ * distance-derived effect is computed from a camera underground.
19
+ * 2. Terrain does not survive `setStyle`. The source and the `setTerrain`
20
+ * call must both be re-applied on every `style.load`.
21
+ * 3. A `hillshade` layer must NOT share the source used by `setTerrain` —
22
+ * sharing one produces artefacts. Two sources, same tiles.
23
+ * 4. The DEM needs its own attribution; it is not covered by the OSM
24
+ * credit the vector tiles carry.
25
+ * 5. Sky needs an explicit `atmosphere-blend`: MapLibre's default ramps to
26
+ * zero at low zoom, so the sky silently stops drawing and the container
27
+ * background shows through as a band across the horizon.
28
+ * 6. `fog-ground-blend` is where fog STARTS (0 = at the camera), not where
29
+ * it ends. A low value paints a fog slab over the ground the moment the
30
+ * camera looks toward the horizon.
31
+ */
32
+
33
+ /** Terrain configuration. `true` means "on, with sensible defaults". */
34
+ interface TerrainOptions {
35
+ /**
36
+ * Vertical exaggeration. 1 is true-to-life; 1.2–1.5 reads better on
37
+ * gentle terrain. Clamped to 0–8.
38
+ */
39
+ exaggeration?: number;
40
+ /**
41
+ * DEM tile template. Defaults to the Mapzen terrarium set on AWS Open
42
+ * Data — the same dataset the MapMap gateway reports as
43
+ * `mapzen-terrain-tiles` from `POST /elevation`, so a map and an
44
+ * elevation query agree with each other.
45
+ *
46
+ * Self-hosters: point this at your own terrarium tiles.
47
+ */
48
+ url?: string;
49
+ /** Encoding of the DEM tiles. Defaults to `"terrarium"`. */
50
+ encoding?: "terrarium" | "mapbox";
51
+ /** Max zoom of the DEM tile set. Defaults to 15. */
52
+ maxzoom?: number;
53
+ /** Tile size in px. Defaults to 256. */
54
+ tileSize?: number;
55
+ /** Attribution for the DEM. Defaults to the Mapzen/AWS credit. */
56
+ attribution?: string;
57
+ /**
58
+ * Add a `hillshade` layer as well, for relief shading that reads even
59
+ * with the camera pointing straight down. Uses its own source (see 3).
60
+ */
61
+ hillshade?: boolean;
62
+ }
63
+ declare const DEFAULT_TERRAIN_URL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
64
+ declare const DEFAULT_TERRAIN_ATTRIBUTION: string;
65
+ /** Normalise `true | TerrainOptions` into a full, clamped config. */
66
+ declare function resolveTerrain(input: boolean | TerrainOptions | undefined): Required<Omit<TerrainOptions, "hillshade">> & {
67
+ hillshade: boolean;
68
+ } | null;
69
+ type ResolvedTerrain = NonNullable<ReturnType<typeof resolveTerrain>>;
70
+ /** Add the sources/layers and switch terrain on. Safe to call repeatedly. */
71
+ declare function applyTerrain(map: Map, cfg: ResolvedTerrain): void;
72
+ /** Turn terrain off and remove what {@link applyTerrain} added. */
73
+ declare function removeTerrain(map: Map): void;
74
+
4
75
  /**
5
76
  * Shared public types for @mapmap/maps.
6
77
  *
@@ -273,13 +344,14 @@ type LogoPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
273
344
  /** Options for {@link LogoControl}. */
274
345
  interface LogoOptions {
275
346
  /**
276
- * Corner to render in. Default `bottom-right`.
277
- *
278
- * In a bottom corner the mark sits ABOVE the attribution, despite being
279
- * added after it: MapLibre prepends controls in the bottom corners
280
- * (`insertBefore(container.firstChild)`) and the corner is anchored to
281
- * the bottom edge, so the control added last is the one that ends up
282
- * highest. Verified against maplibre-gl 5's `addControl`.
347
+ * Corner to render in. Default `bottom-right` — the opposite corner
348
+ * from the attribution, which the SDK mounts bottom-left (movable with
349
+ * `attributionPosition`). That is the canonical MapMap layout:
350
+ * attribution small bottom-left, mark bottom-right, never both in one
351
+ * corner (stacking the mark on the OSM credit makes a licence-required
352
+ * line unreadable). {@link MapMapMap} enforces that: if this corner is
353
+ * the attribution's corner, the mark is mounted in the opposite bottom
354
+ * corner instead, with one `console.warn` for that map.
283
355
  */
284
356
  position?: LogoPosition;
285
357
  /** Link target when clicked. Default the MapMap site. */
@@ -1052,10 +1124,12 @@ declare function applyPoiDesign(map: PoiPaintMap, design: PoiDesign, fallbackTex
1052
1124
  * their own bundled maplibre-gl copy) but still want to read MapMap PMTiles.
1053
1125
  */
1054
1126
  declare function registerPmtilesProtocol(gl?: typeof maplibregl): void;
1127
+ /** Map corners an enforced control (attribution, mark) can be mounted in. */
1128
+ type AttributionPosition = "bottom-left" | "bottom-right" | "top-left" | "top-right";
1055
1129
  interface MapMapOptions {
1056
1130
  /**
1057
1131
  * The MapMap wordmark on the map (like the Google Maps / Mapbox marks).
1058
- * Always on, at bottom-right above the attribution by default; pass
1132
+ * Always on, at bottom-right (the attribution's opposite corner); pass
1059
1133
  * `{ position, href }` to move or relink it.
1060
1134
  *
1061
1135
  * The mark cannot be taken off. Every displayed MapMap map carries it,
@@ -1087,6 +1161,15 @@ interface MapMapOptions {
1087
1161
  center?: [number, number];
1088
1162
  /** Initial zoom. Defaults to `5`. */
1089
1163
  zoom?: number;
1164
+ /**
1165
+ * 3D terrain from a DEM. `true` uses sensible defaults; pass
1166
+ * {@link TerrainOptions} to set exaggeration, point at your own DEM
1167
+ * tiles, or add relief shading.
1168
+ *
1169
+ * The default DEM is the same dataset the gateway reports from
1170
+ * `POST /elevation`, so a map and an elevation query agree.
1171
+ */
1172
+ terrain?: boolean | TerrainOptions;
1090
1173
  /**
1091
1174
  * Extra MapLibre `MapOptions` merged last (escape hatch for hash, bearing,
1092
1175
  * maxBounds, etc.). `container` and `style` here are ignored.
@@ -1099,6 +1182,22 @@ interface MapMapOptions {
1099
1182
  * served under, for MapMap and for you.
1100
1183
  */
1101
1184
  mapOptions?: Partial<Omit<MapOptions, "container" | "style">>;
1185
+ /**
1186
+ * Corner for the OpenStreetMap attribution. Default `"bottom-left"`,
1187
+ * which is the canonical MapMap layout: attribution small bottom-left,
1188
+ * MapMap mark bottom-right. This chooses the credit's corner and nothing
1189
+ * else; the credit itself stays on regardless (see
1190
+ * `mapOptions.attributionControl` above), so there is no longer any
1191
+ * reason to reach into `map._controls` to relocate it.
1192
+ *
1193
+ * The attribution and the mark never share a corner: stacking the mark
1194
+ * on the credit makes a line the ODbL requires unreadable. If the corner
1195
+ * requested here is the mark's corner (whether the mark's default
1196
+ * bottom-right or an explicit `logo.position`), the mark moves to the
1197
+ * opposite bottom corner and the SDK logs one `console.warn` for that
1198
+ * map.
1199
+ */
1200
+ attributionPosition?: AttributionPosition;
1102
1201
  }
1103
1202
  /** Options for {@link MapMapMap.setRouteEffect}. */
1104
1203
  interface SetRouteEffectOptions extends RouteFlowOptions {
@@ -1138,6 +1237,8 @@ declare class MapMapMap {
1138
1237
  private effectLayer;
1139
1238
  /** True while an effect re-apply is already queued behind the style. */
1140
1239
  private effectWaiting;
1240
+ /** Resolved terrain config, or null when terrain is off. */
1241
+ private terrainConfig;
1141
1242
  private destroyed;
1142
1243
  private readonly pendingWaits;
1143
1244
  private readonly notices;
@@ -1162,6 +1263,12 @@ declare class MapMapMap {
1162
1263
  * and the listeners detach as soon as one fires (or on `destroy()`).
1163
1264
  */
1164
1265
  private whenStyleReady;
1266
+ private readonly handleStyleLoadForTerrain;
1267
+ /**
1268
+ * Turn terrain on or off after construction. `false` removes the DEM
1269
+ * sources and any hillshade layer this SDK added.
1270
+ */
1271
+ setTerrain(terrain: boolean | TerrainOptions): void;
1165
1272
  private readonly handleStyleLoadForEffects;
1166
1273
  /** The current style's `metadata`, if it can be read yet. */
1167
1274
  private styleMetadata;
@@ -1292,6 +1399,18 @@ declare const MARKER_GLYPH_VIEWBOX = 24;
1292
1399
  * gateway's Rust validator. Do not change ids, defaults or key formats
1293
1400
  * here without coordinating all three.
1294
1401
  *
1402
+ * BAKED STYLES. Since the SDF marker sprite shipped, the theme compiler
1403
+ * TRANSLATES a theme's `extra.markers` block into the same `mm-user-markers`
1404
+ * source plus two sprite-driven symbol layers, so a published style URL
1405
+ * draws its glyph markers in ANY MapLibre client — native SDKs and static
1406
+ * renderers included — with no SDK code running at all. This layer is still
1407
+ * a strict superset (runtime changes, custom `data:` images, short-text
1408
+ * numbered pins), so when it is given markers on a style that is already
1409
+ * baked it TAKES OVER: it removes the two baked layers and installs its
1410
+ * own, rather than drawing a second copy. Constructing one and never
1411
+ * setting markers leaves a baked style untouched. See
1412
+ * {@link hasBakedMarkers}.
1413
+ *
1295
1414
  * Like PlacesLayer, the layer survives `setStyle` (theme swaps) — but NOT
1296
1415
  * because a diffed `setStyle` leaves it alone. `Style.serialize()` includes
1297
1416
  * runtime-added sources and layers, so MapLibre's diff sees
@@ -1330,6 +1449,25 @@ declare const MAX_MARKER_LABEL_LENGTH = 120;
1330
1449
  declare const MAX_MARKER_TEXT_LENGTH = 3;
1331
1450
  /** The shared GeoJSON source id AND symbol layer id (contract). */
1332
1451
  declare const MARKERS_ID = "mm-user-markers";
1452
+ /**
1453
+ * The SECOND symbol layer a BAKED style carries — the glyph-and-label layer
1454
+ * the theme compiler appends next to `mm-user-markers` when it translates
1455
+ * `extra.markers` into style constructs (`sn_style::MARKERS_GLYPH_LAYER_ID`).
1456
+ *
1457
+ * This layer is the reliable "already baked" signal: {@link MarkersLayer}
1458
+ * never creates it, so finding it means the style itself is drawing the
1459
+ * markers and a naive install would draw them TWICE.
1460
+ */
1461
+ declare const BAKED_MARKERS_GLYPH_ID = "mm-user-markers-glyph";
1462
+ /**
1463
+ * Whether the map's current style carries compiler-baked marker layers —
1464
+ * i.e. its markers already render in any MapLibre client, with no SDK code.
1465
+ *
1466
+ * Useful for deciding whether to construct a {@link MarkersLayer} at all:
1467
+ * you only need one to CHANGE the markers at runtime, or to render the
1468
+ * custom `data:` image markers a static sprite cannot carry.
1469
+ */
1470
+ declare function hasBakedMarkers(map: MapMapMap | Map): boolean;
1333
1471
  /** One parsed marker of an `extra.markers` v1 block. */
1334
1472
  interface MarkerItem {
1335
1473
  /** Stable unique id, non-empty, at most 64 characters. */
@@ -1581,6 +1719,24 @@ declare class MarkersLayer {
1581
1719
  * install as well as every data rebuild.
1582
1720
  */
1583
1721
  private registerImages;
1722
+ /**
1723
+ * TAKE OVER from a baked style. A style compiled from a theme with an
1724
+ * `extra.markers` block already draws those markers itself, from an
1725
+ * inline GeoJSON source plus two sprite-driven symbol layers — so
1726
+ * installing on top would draw every marker twice, and pointing the SDK's
1727
+ * feature shape at the baked layers would draw nothing sensible (they
1728
+ * read `bodySize`/`anchor`, this layer writes `iconImage`/`iconSize`).
1729
+ *
1730
+ * Take-over rather than no-op, because this layer is a strict superset:
1731
+ * it also renders the custom `data:` image markers and the short-text
1732
+ * numbered pins that a static sprite cannot carry. The baked SOURCE is
1733
+ * kept and its data replaced in place; only the two baked LAYERS go.
1734
+ *
1735
+ * Only ever runs once markers have been set on this layer, so a
1736
+ * `new MarkersLayer(map)` that is never given any leaves a baked style
1737
+ * completely alone. Idempotent; returns whether anything was taken over.
1738
+ */
1739
+ private takeOverBakedLayers;
1584
1740
  /** Add-or-update the images, source and layer on the current style. */
1585
1741
  private install;
1586
1742
  /**
@@ -3598,4 +3754,4 @@ declare class VoiceGuidance {
3598
3754
  private playEarcon;
3599
3755
  }
3600
3756
 
3601
- export { ALERT_CONTRAST_MIN, AdrCheck, type AdrCheckOptions, type AdrCheckRequest, type AdrCheckResult, type AdrDimensions, type AdrTunnelCategory, type AlertChipContent, type AlertContrastIssue, type AlertPresentation, type BannerComponent, type BannerContent, type BannerInstruction, type BuildStyleOptions, type CameraAlert, CameraAlertChip, type CameraFix, DEFAULT_GLYPHS_URL, DEFAULT_TERRITORY_TILES_URL, type DiagnosticIssue, EFFECTS_METADATA_KEY, type EndpointMarker, type EndpointsDesign, 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, MARKERS_ID, MARKER_DEFAULT_COLOUR, MARKER_GLYPH_IDS, MARKER_GLYPH_VIEWBOX, MARKER_LABEL_TEXT_SIZES, MARKER_PIN_BODY_PATH, MARKER_SIZES, MARKER_SIZES_PX, MAX_MARKER_ID_LENGTH, MAX_MARKER_IMAGE_BYTES, MAX_MARKER_ITEMS, MAX_MARKER_LABEL_LENGTH, MAX_MARKER_TEXT_LENGTH, MAX_PUCK_IMAGE_BYTES, type MapDiagnosticsInput, type MapDisplayMode, MapMapMap, type MapMapOptions, type MapMapTheme, type MarkerGlyphId, type MarkerItem, type MarkerSize, type MarkersBlock, MarkersLayer, type MarkersLayerIds, type MarkersLayerOptions, NAV_ALERT_AUDIO_MODES, NAV_ALERT_CHIP_POSITIONS, NAV_ALERT_ICON_SETS, NAV_ALERT_LEAD_DISTANCES, NAV_ALERT_LEAD_DISTANCE_M, NAV_ALERT_MODES, NAV_ALERT_SOUNDS, NAV_ALERT_SOUND_BASE_URL, NAV_ALERT_SOUND_FILES, NAV_CAMERA_DEFAULTS, NAV_CAMERA_KINDS, type NavAlertAudioMode, type NavAlertChipPosition, type NavAlertIconSet, type NavAlertKindDesign, type NavAlertLeadDistance, type NavAlertMode, type NavAlertSound, type NavAlertsDesign, type NavBannerDesign, type NavCameraDesign, type NavCameraKind, 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, type PlacesLabelOptions, 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 RenderMarkerImageOptions, type RenderedMarkerImage, type RibbonMesh, type RouteEffectLayer, type RouteEffectName, type RouteFlowOptions, type RouteGeometry, RouteLayer, type RouteLayerIds, type RouteLayerOptions, type RouteLineStyle, 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, alertChipContent, alertContrastIssues, alertIconSvg, alertIconUrl, alertPresentation, alertSoundUrl, alertSpeedReadoutColor, applyPoiDesign, bannerLanes, bearingBetween, bindFlythroughToScroll, buildAdrCheckBody, buildProbeUrl, buildRouteQuery, buildRouteUrl, buildStyle, builtInPoiColor, cameraKindLabel, cameraKindsShownOnMap, cameraShownOnMap, cameraSpriteName, cameraSymbolLayer, contrastRatio, createMap, createRouteEffect, defaultNavAlertsDesign, defaultNavDesign, defaultPoiDesign, directionArrow, effectsFromStyleMetadata, extractGuidance, flythrough, flythroughPose, formatCoord, formatCoords, haversineDistanceM, isMarkerGlyphId, isNameTextField, laneArrowDirection, languageTextField, lngLatToMercator, markerGlyphPaths, markerImage, markerImageDataKey, markerImageKey, markerText, markerTextImageKey, markersFromTheme, markersFromThemeUrl, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseMarkers, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, renderMarkerImage, resetDiagnostics, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, truncateChars, uploadProbeBatch };
3757
+ export { ALERT_CONTRAST_MIN, AdrCheck, type AdrCheckOptions, type AdrCheckRequest, type AdrCheckResult, type AdrDimensions, type AdrTunnelCategory, type AlertChipContent, type AlertContrastIssue, type AlertPresentation, type AttributionPosition, BAKED_MARKERS_GLYPH_ID, type BannerComponent, type BannerContent, type BannerInstruction, type BuildStyleOptions, type CameraAlert, CameraAlertChip, type CameraFix, DEFAULT_GLYPHS_URL, DEFAULT_TERRAIN_ATTRIBUTION, DEFAULT_TERRAIN_URL, DEFAULT_TERRITORY_TILES_URL, type DiagnosticIssue, EFFECTS_METADATA_KEY, type EndpointMarker, type EndpointsDesign, 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, MARKERS_ID, MARKER_DEFAULT_COLOUR, MARKER_GLYPH_IDS, MARKER_GLYPH_VIEWBOX, MARKER_LABEL_TEXT_SIZES, MARKER_PIN_BODY_PATH, MARKER_SIZES, MARKER_SIZES_PX, MAX_MARKER_ID_LENGTH, MAX_MARKER_IMAGE_BYTES, MAX_MARKER_ITEMS, MAX_MARKER_LABEL_LENGTH, MAX_MARKER_TEXT_LENGTH, MAX_PUCK_IMAGE_BYTES, type MapDiagnosticsInput, type MapDisplayMode, MapMapMap, type MapMapOptions, type MapMapTheme, type MarkerGlyphId, type MarkerItem, type MarkerSize, type MarkersBlock, MarkersLayer, type MarkersLayerIds, type MarkersLayerOptions, NAV_ALERT_AUDIO_MODES, NAV_ALERT_CHIP_POSITIONS, NAV_ALERT_ICON_SETS, NAV_ALERT_LEAD_DISTANCES, NAV_ALERT_LEAD_DISTANCE_M, NAV_ALERT_MODES, NAV_ALERT_SOUNDS, NAV_ALERT_SOUND_BASE_URL, NAV_ALERT_SOUND_FILES, NAV_CAMERA_DEFAULTS, NAV_CAMERA_KINDS, type NavAlertAudioMode, type NavAlertChipPosition, type NavAlertIconSet, type NavAlertKindDesign, type NavAlertLeadDistance, type NavAlertMode, type NavAlertSound, type NavAlertsDesign, type NavBannerDesign, type NavCameraDesign, type NavCameraKind, 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, type PlacesLabelOptions, 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 RenderMarkerImageOptions, type RenderedMarkerImage, type RibbonMesh, type RouteEffectLayer, type RouteEffectName, type RouteFlowOptions, type RouteGeometry, RouteLayer, type RouteLayerIds, type RouteLayerOptions, type RouteLineStyle, type RouteOptions, type RouteProfile, SIGNAL_BLUE, SOURCE_LAYERS, type SetRouteEffectOptions, type SeverityProsody, type ShowReachabilityOptions, type SpeakOptions, type StepGuidance, type SunTimes, type TerrainOptions, type Theme, type ThemeEffects, ThemeScheduler, type ThemeSchedulerOptions, type TruckParams, type UploadProbeOptions, VoiceGuidance, type VoiceGuidanceOptions, type VoiceGuidanceUpdate, type VoiceInstruction, alertChipContent, alertContrastIssues, alertIconSvg, alertIconUrl, alertPresentation, alertSoundUrl, alertSpeedReadoutColor, applyPoiDesign, applyTerrain, bannerLanes, bearingBetween, bindFlythroughToScroll, buildAdrCheckBody, buildProbeUrl, buildRouteQuery, buildRouteUrl, buildStyle, builtInPoiColor, cameraKindLabel, cameraKindsShownOnMap, cameraShownOnMap, cameraSpriteName, cameraSymbolLayer, contrastRatio, createMap, createRouteEffect, defaultNavAlertsDesign, defaultNavDesign, defaultPoiDesign, directionArrow, effectsFromStyleMetadata, extractGuidance, flythrough, flythroughPose, formatCoord, formatCoords, hasBakedMarkers, haversineDistanceM, isMarkerGlyphId, isNameTextField, laneArrowDirection, languageTextField, lngLatToMercator, markerGlyphPaths, markerImage, markerImageDataKey, markerImageKey, markerText, markerTextImageKey, markersFromTheme, markersFromThemeUrl, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseMarkers, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, removeTerrain, renderMarkerImage, resetDiagnostics, resolveTerrain, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, truncateChars, uploadProbeBatch };
package/dist/index.js CHANGED
@@ -104,6 +104,72 @@ function watchForAuthFailures(map, apiKey) {
104
104
  }
105
105
  }
106
106
 
107
+ // src/terrain.ts
108
+ var DEFAULT_TERRAIN_URL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
109
+ var DEFAULT_TERRAIN_ATTRIBUTION = '<a href="https://registry.opendata.aws/terrain-tiles/">Terrain data</a> Mapzen, AWS Open Data';
110
+ var TERRAIN_SOURCE_ID = "mapmap-terrain-dem";
111
+ var HILLSHADE_SOURCE_ID = "mapmap-hillshade-dem";
112
+ var HILLSHADE_LAYER_ID = "mapmap-hillshade";
113
+ var MAX_EXAGGERATION = 8;
114
+ function resolveTerrain(input) {
115
+ if (!input) return null;
116
+ const o = input === true ? {} : input;
117
+ const raw = o.exaggeration ?? 1;
118
+ return {
119
+ // NaN must not reach MapLibre: it silently flattens the whole terrain.
120
+ exaggeration: Number.isFinite(raw) ? Math.min(MAX_EXAGGERATION, Math.max(0, raw)) : 1,
121
+ url: o.url ?? DEFAULT_TERRAIN_URL,
122
+ encoding: o.encoding ?? "terrarium",
123
+ maxzoom: o.maxzoom ?? 15,
124
+ tileSize: o.tileSize ?? 256,
125
+ attribution: o.attribution ?? DEFAULT_TERRAIN_ATTRIBUTION,
126
+ hillshade: o.hillshade ?? false
127
+ };
128
+ }
129
+ function applyTerrain(map, cfg) {
130
+ const demSpec = {
131
+ type: "raster-dem",
132
+ tiles: [cfg.url],
133
+ encoding: cfg.encoding,
134
+ tileSize: cfg.tileSize,
135
+ maxzoom: cfg.maxzoom,
136
+ attribution: cfg.attribution
137
+ };
138
+ if (!map.getSource(TERRAIN_SOURCE_ID)) {
139
+ map.addSource(TERRAIN_SOURCE_ID, demSpec);
140
+ }
141
+ map.setTerrain({ source: TERRAIN_SOURCE_ID, exaggeration: cfg.exaggeration });
142
+ if (!cfg.hillshade) {
143
+ if (map.getLayer(HILLSHADE_LAYER_ID)) map.removeLayer(HILLSHADE_LAYER_ID);
144
+ return;
145
+ }
146
+ if (!map.getSource(HILLSHADE_SOURCE_ID)) {
147
+ map.addSource(HILLSHADE_SOURCE_ID, demSpec);
148
+ }
149
+ if (!map.getLayer(HILLSHADE_LAYER_ID)) {
150
+ const layers = map.getStyle()?.layers ?? [];
151
+ const firstLineOrSymbol = layers.find(
152
+ (l) => l.type === "line" || l.type === "symbol"
153
+ );
154
+ map.addLayer(
155
+ {
156
+ id: HILLSHADE_LAYER_ID,
157
+ type: "hillshade",
158
+ source: HILLSHADE_SOURCE_ID,
159
+ paint: { "hillshade-exaggeration": 0.5 }
160
+ },
161
+ firstLineOrSymbol?.id
162
+ );
163
+ }
164
+ }
165
+ function removeTerrain(map) {
166
+ map.setTerrain(null);
167
+ if (map.getLayer(HILLSHADE_LAYER_ID)) map.removeLayer(HILLSHADE_LAYER_ID);
168
+ for (const id of [TERRAIN_SOURCE_ID, HILLSHADE_SOURCE_ID]) {
169
+ if (map.getSource(id)) map.removeSource(id);
170
+ }
171
+ }
172
+
107
173
  // src/coords.ts
108
174
  function toLngLat(point) {
109
175
  if (Array.isArray(point)) {
@@ -1887,6 +1953,8 @@ var MapMapMap = class {
1887
1953
  this.effectExplicit = false;
1888
1954
  /** True while an effect re-apply is already queued behind the style. */
1889
1955
  this.effectWaiting = false;
1956
+ /** Resolved terrain config, or null when terrain is off. */
1957
+ this.terrainConfig = null;
1890
1958
  // Lifecycle: `destroy()` must silence anything still queued behind a
1891
1959
  // style load, and the cleanups let it detach those listeners.
1892
1960
  this.destroyed = false;
@@ -1897,6 +1965,10 @@ var MapMapMap = class {
1897
1965
  // removal is its own licence problem and deserves its own line, but a
1898
1966
  // theme swap or re-render must never repeat one.
1899
1967
  this.notices = /* @__PURE__ */ new Set();
1968
+ this.handleStyleLoadForTerrain = () => {
1969
+ if (this.destroyed || !this.terrainConfig) return;
1970
+ applyTerrain(this.map, this.terrainConfig);
1971
+ };
1900
1972
  this.handleStyleLoadForEffects = () => {
1901
1973
  if (this.destroyed) return;
1902
1974
  if (!this.effectExplicit) {
@@ -1931,8 +2003,21 @@ var MapMapMap = class {
1931
2003
  center: options.center ?? DEFAULT_CENTER,
1932
2004
  zoom: options.zoom ?? DEFAULT_ZOOM,
1933
2005
  ...options.mapOptions,
1934
- attributionControl
2006
+ // Never let the constructor mount the attribution: it would land in
2007
+ // MapLibre's default corner, bottom-RIGHT, which is the mark's
2008
+ // corner. The canonical MapMap layout (Matt, 4 Aug 2026) is
2009
+ // attribution small bottom-LEFT, mark bottom-RIGHT, never stacked —
2010
+ // an SDK map must produce that with zero configuration, because
2011
+ // every embed that got the old both-bottom-right default shipped
2012
+ // the mark sitting on top of the OSM credit, and one demo "fixed"
2013
+ // that by display:none-ing the credit, which is an ODbL breach.
2014
+ attributionControl: false
1935
2015
  });
2016
+ const attributionPosition = options.attributionPosition ?? "bottom-left";
2017
+ this.map.addControl(
2018
+ new maplibregl.AttributionControl(attributionControl),
2019
+ attributionPosition
2020
+ );
1936
2021
  if (options.logo === false) {
1937
2022
  this.notice(
1938
2023
  "logo-removal",
@@ -1940,11 +2025,23 @@ var MapMapMap = class {
1940
2025
  );
1941
2026
  }
1942
2027
  const logoOptions = typeof options.logo === "object" && options.logo !== null ? options.logo : {};
1943
- this.map.addControl(
1944
- new LogoControl(logoOptions),
1945
- logoOptions.position ?? "bottom-right"
1946
- );
2028
+ let logoPosition = logoOptions.position ?? "bottom-right";
2029
+ if (logoPosition === attributionPosition) {
2030
+ logoPosition = attributionPosition.endsWith("left") ? "bottom-right" : "bottom-left";
2031
+ this.notice(
2032
+ "logo-collision",
2033
+ `the MapMap mark and the attribution cannot share the ${attributionPosition} corner (the mark would cover the OpenStreetMap credit, which the ODbL requires readable). The mark has moved to ${logoPosition}.`
2034
+ );
2035
+ }
2036
+ this.map.addControl(new LogoControl(logoOptions), logoPosition);
1947
2037
  this.map.on("style.load", this.handleStyleLoadForEffects);
2038
+ this.terrainConfig = resolveTerrain(options.terrain);
2039
+ this.map.on("style.load", this.handleStyleLoadForTerrain);
2040
+ if (this.terrainConfig) {
2041
+ this.whenStyleReady(() => {
2042
+ if (this.terrainConfig) applyTerrain(this.map, this.terrainConfig);
2043
+ });
2044
+ }
1948
2045
  runMapDiagnostics({
1949
2046
  container: options.container,
1950
2047
  map: this.map,
@@ -1994,6 +2091,19 @@ var MapMapMap = class {
1994
2091
  this.pendingWaits.add(cleanup);
1995
2092
  for (const event of events) this.map.on(event, run);
1996
2093
  }
2094
+ /**
2095
+ * Turn terrain on or off after construction. `false` removes the DEM
2096
+ * sources and any hillshade layer this SDK added.
2097
+ */
2098
+ setTerrain(terrain) {
2099
+ if (this.destroyed) return;
2100
+ this.terrainConfig = resolveTerrain(terrain);
2101
+ const cfg = this.terrainConfig;
2102
+ this.whenStyleReady(() => {
2103
+ if (cfg) applyTerrain(this.map, cfg);
2104
+ else removeTerrain(this.map);
2105
+ });
2106
+ }
1997
2107
  /** The current style's `metadata`, if it can be read yet. */
1998
2108
  styleMetadata() {
1999
2109
  try {
@@ -2342,6 +2452,11 @@ var MAX_MARKER_ID_LENGTH = 64;
2342
2452
  var MAX_MARKER_LABEL_LENGTH = 120;
2343
2453
  var MAX_MARKER_TEXT_LENGTH = 3;
2344
2454
  var MARKERS_ID = "mm-user-markers";
2455
+ var BAKED_MARKERS_GLYPH_ID = "mm-user-markers-glyph";
2456
+ function hasBakedMarkers(map) {
2457
+ const ml = map instanceof MapMapMap ? map.map : map;
2458
+ return ml.getLayer(BAKED_MARKERS_GLYPH_ID) !== void 0;
2459
+ }
2345
2460
  var MARKER_IMAGE_MIME = /^data:image\/(png|jpeg|webp|svg\+xml);base64,/;
2346
2461
  function isRecord3(v) {
2347
2462
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -2596,11 +2711,12 @@ var MarkersLayer = class {
2596
2711
  type: "FeatureCollection",
2597
2712
  features: this.items.map((item) => this.featureFor(item))
2598
2713
  };
2714
+ const tookOver = this.takeOverBakedLayers();
2599
2715
  const source = this.map.getSource(MARKERS_ID);
2600
- if (source) {
2716
+ if (source && !tookOver) {
2601
2717
  this.registerImages();
2602
2718
  source.setData(this.data);
2603
- } else if (this.map.isStyleLoaded()) {
2719
+ } else if (tookOver || this.map.isStyleLoaded()) {
2604
2720
  this.install();
2605
2721
  }
2606
2722
  }
@@ -2703,9 +2819,33 @@ var MarkersLayer = class {
2703
2819
  }
2704
2820
  for (const key of needed) this.registeredImageKeys.add(key);
2705
2821
  }
2822
+ /**
2823
+ * TAKE OVER from a baked style. A style compiled from a theme with an
2824
+ * `extra.markers` block already draws those markers itself, from an
2825
+ * inline GeoJSON source plus two sprite-driven symbol layers — so
2826
+ * installing on top would draw every marker twice, and pointing the SDK's
2827
+ * feature shape at the baked layers would draw nothing sensible (they
2828
+ * read `bodySize`/`anchor`, this layer writes `iconImage`/`iconSize`).
2829
+ *
2830
+ * Take-over rather than no-op, because this layer is a strict superset:
2831
+ * it also renders the custom `data:` image markers and the short-text
2832
+ * numbered pins that a static sprite cannot carry. The baked SOURCE is
2833
+ * kept and its data replaced in place; only the two baked LAYERS go.
2834
+ *
2835
+ * Only ever runs once markers have been set on this layer, so a
2836
+ * `new MarkersLayer(map)` that is never given any leaves a baked style
2837
+ * completely alone. Idempotent; returns whether anything was taken over.
2838
+ */
2839
+ takeOverBakedLayers() {
2840
+ if (this.map.getLayer(BAKED_MARKERS_GLYPH_ID) === void 0) return false;
2841
+ this.map.removeLayer(BAKED_MARKERS_GLYPH_ID);
2842
+ if (this.map.getLayer(MARKERS_ID)) this.map.removeLayer(MARKERS_ID);
2843
+ return true;
2844
+ }
2706
2845
  /** Add-or-update the images, source and layer on the current style. */
2707
2846
  install() {
2708
2847
  if (!this.data) return;
2848
+ this.takeOverBakedLayers();
2709
2849
  this.registerImages();
2710
2850
  const existing = this.map.getSource(MARKERS_ID);
2711
2851
  if (existing) {
@@ -5719,6 +5859,6 @@ function clampVolume(volume) {
5719
5859
  return Math.min(1, Math.max(0, volume));
5720
5860
  }
5721
5861
 
5722
- export { ALERT_CONTRAST_MIN, AdrCheck, CameraAlertChip, DEFAULT_GLYPHS_URL, DEFAULT_TERRITORY_TILES_URL, EFFECTS_METADATA_KEY, FLOW_DEFAULTS, FULL_ATTRIBUTION, FlowRouteEffectLayer, GuidanceBanner, IsochroneLayer, LOGO_SVG, LogoControl, MARKERS_ID, MARKER_DEFAULT_COLOUR, MARKER_GLYPH_IDS, MARKER_GLYPH_VIEWBOX, MARKER_LABEL_TEXT_SIZES, MARKER_PIN_BODY_PATH, MARKER_SIZES, MARKER_SIZES_PX, MAX_MARKER_ID_LENGTH, MAX_MARKER_IMAGE_BYTES, MAX_MARKER_ITEMS, MAX_MARKER_LABEL_LENGTH, MAX_MARKER_TEXT_LENGTH, MAX_PUCK_IMAGE_BYTES, MapMapMap, MarkersLayer, NAV_ALERT_AUDIO_MODES, NAV_ALERT_CHIP_POSITIONS, NAV_ALERT_ICON_SETS, NAV_ALERT_LEAD_DISTANCES, NAV_ALERT_LEAD_DISTANCE_M, NAV_ALERT_MODES, NAV_ALERT_SOUNDS, NAV_ALERT_SOUND_BASE_URL, NAV_ALERT_SOUND_FILES, NAV_CAMERA_DEFAULTS, NAV_CAMERA_KINDS, NavigationCamera, OPENMAPTILES_ATTRIBUTION, OSM_ATTRIBUTION, PALETTE_SLOTS, POI_CATEGORY_COLORS, POI_CATEGORY_IDS, POI_CLASS_CATEGORIES, PlacesLayer, PositionPuck, RIBBON_FLOATS_PER_VERTEX, ROUTE_EFFECTS, RouteLayer, SIGNAL_BLUE, SOURCE_LAYERS, ThemeScheduler, VoiceGuidance, alertChipContent, alertContrastIssues, alertIconSvg, alertIconUrl, alertPresentation, alertSoundUrl, alertSpeedReadoutColor, applyPoiDesign, bannerLanes, bearingBetween, bindFlythroughToScroll, buildAdrCheckBody, buildProbeUrl, buildRouteQuery, buildRouteUrl, buildStyle, builtInPoiColor, cameraKindLabel, cameraKindsShownOnMap, cameraShownOnMap, cameraSpriteName, cameraSymbolLayer, contrastRatio, createMap, createRouteEffect, defaultNavAlertsDesign, defaultNavDesign, defaultPoiDesign, directionArrow, effectsFromStyleMetadata, extractGuidance, flythrough, flythroughPose, formatCoord, formatCoords, haversineDistanceM, isMarkerGlyphId, isNameTextField, laneArrowDirection, languageTextField, lngLatToMercator, markerGlyphPaths, markerImage, markerImageDataKey, markerImageKey, markerText, markerTextImageKey, markersFromTheme, markersFromThemeUrl, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseMarkers, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, renderMarkerImage, resetDiagnostics, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, truncateChars, uploadProbeBatch };
5862
+ export { ALERT_CONTRAST_MIN, AdrCheck, BAKED_MARKERS_GLYPH_ID, CameraAlertChip, DEFAULT_GLYPHS_URL, DEFAULT_TERRAIN_ATTRIBUTION, DEFAULT_TERRAIN_URL, DEFAULT_TERRITORY_TILES_URL, EFFECTS_METADATA_KEY, FLOW_DEFAULTS, FULL_ATTRIBUTION, FlowRouteEffectLayer, GuidanceBanner, IsochroneLayer, LOGO_SVG, LogoControl, MARKERS_ID, MARKER_DEFAULT_COLOUR, MARKER_GLYPH_IDS, MARKER_GLYPH_VIEWBOX, MARKER_LABEL_TEXT_SIZES, MARKER_PIN_BODY_PATH, MARKER_SIZES, MARKER_SIZES_PX, MAX_MARKER_ID_LENGTH, MAX_MARKER_IMAGE_BYTES, MAX_MARKER_ITEMS, MAX_MARKER_LABEL_LENGTH, MAX_MARKER_TEXT_LENGTH, MAX_PUCK_IMAGE_BYTES, MapMapMap, MarkersLayer, NAV_ALERT_AUDIO_MODES, NAV_ALERT_CHIP_POSITIONS, NAV_ALERT_ICON_SETS, NAV_ALERT_LEAD_DISTANCES, NAV_ALERT_LEAD_DISTANCE_M, NAV_ALERT_MODES, NAV_ALERT_SOUNDS, NAV_ALERT_SOUND_BASE_URL, NAV_ALERT_SOUND_FILES, NAV_CAMERA_DEFAULTS, NAV_CAMERA_KINDS, NavigationCamera, OPENMAPTILES_ATTRIBUTION, OSM_ATTRIBUTION, PALETTE_SLOTS, POI_CATEGORY_COLORS, POI_CATEGORY_IDS, POI_CLASS_CATEGORIES, PlacesLayer, PositionPuck, RIBBON_FLOATS_PER_VERTEX, ROUTE_EFFECTS, RouteLayer, SIGNAL_BLUE, SOURCE_LAYERS, ThemeScheduler, VoiceGuidance, alertChipContent, alertContrastIssues, alertIconSvg, alertIconUrl, alertPresentation, alertSoundUrl, alertSpeedReadoutColor, applyPoiDesign, applyTerrain, bannerLanes, bearingBetween, bindFlythroughToScroll, buildAdrCheckBody, buildProbeUrl, buildRouteQuery, buildRouteUrl, buildStyle, builtInPoiColor, cameraKindLabel, cameraKindsShownOnMap, cameraShownOnMap, cameraSpriteName, cameraSymbolLayer, contrastRatio, createMap, createRouteEffect, defaultNavAlertsDesign, defaultNavDesign, defaultPoiDesign, directionArrow, effectsFromStyleMetadata, extractGuidance, flythrough, flythroughPose, formatCoord, formatCoords, hasBakedMarkers, haversineDistanceM, isMarkerGlyphId, isNameTextField, laneArrowDirection, languageTextField, lngLatToMercator, markerGlyphPaths, markerImage, markerImageDataKey, markerImageKey, markerText, markerTextImageKey, markersFromTheme, markersFromThemeUrl, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseMarkers, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, removeTerrain, renderMarkerImage, resetDiagnostics, resolveTerrain, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, truncateChars, uploadProbeBatch };
5723
5863
  //# sourceMappingURL=index.js.map
5724
5864
  //# sourceMappingURL=index.js.map