@mapmap/maps 0.5.1 → 0.6.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/dist/index.d.ts +119 -1
- package/dist/index.js +249 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -518,6 +518,26 @@ interface NavRouteDesign {
|
|
|
518
518
|
opacity: number;
|
|
519
519
|
/** Casing (outline) colour drawn under the line. */
|
|
520
520
|
casingColor: string;
|
|
521
|
+
/**
|
|
522
|
+
* Casing width in px. Defaults to `width + 4`.
|
|
523
|
+
*
|
|
524
|
+
* Optional because the casing was previously always `width + 4`, which
|
|
525
|
+
* cannot express a design whose casing is not exactly four wider than
|
|
526
|
+
* its line (the playground's is 9 over a 4.5 line).
|
|
527
|
+
*/
|
|
528
|
+
casingWidth?: number;
|
|
529
|
+
/**
|
|
530
|
+
* Casing opacity, 0-1. Defaults to {@link NavRouteDesign.opacity}.
|
|
531
|
+
*
|
|
532
|
+
* Optional because casing and line previously shared one opacity, which
|
|
533
|
+
* cannot express a translucent casing under a solid line.
|
|
534
|
+
*/
|
|
535
|
+
casingOpacity?: number;
|
|
536
|
+
/**
|
|
537
|
+
* Line dash pattern, in line-widths, as MapLibre's `line-dasharray`.
|
|
538
|
+
* Omitted or `null` draws a solid line.
|
|
539
|
+
*/
|
|
540
|
+
dash?: number[] | null;
|
|
521
541
|
}
|
|
522
542
|
/** Current-position puck tokens. */
|
|
523
543
|
interface NavPuckDesign {
|
|
@@ -1165,6 +1185,18 @@ declare function createMap(options: MapMapOptions): MapMapMap;
|
|
|
1165
1185
|
|
|
1166
1186
|
/** MapMap brand signal blue (see website `--signal`). */
|
|
1167
1187
|
declare const SIGNAL_BLUE = "#3a86ff";
|
|
1188
|
+
/**
|
|
1189
|
+
* Runtime overrides for the drawn line, applied over the design or the
|
|
1190
|
+
* built-in look. Every field is optional; omitted ones are left alone.
|
|
1191
|
+
*/
|
|
1192
|
+
interface RouteLineStyle {
|
|
1193
|
+
/** Line colour. */
|
|
1194
|
+
color?: string;
|
|
1195
|
+
/** Dash pattern in line-widths, or `null` for solid. */
|
|
1196
|
+
dash?: number[] | null;
|
|
1197
|
+
/** Casing opacity, 0-1. Set 0 to hide the casing entirely. */
|
|
1198
|
+
casingOpacity?: number;
|
|
1199
|
+
}
|
|
1168
1200
|
interface RouteLayerOptions {
|
|
1169
1201
|
/** Gateway base URL. Defaults to the map's `baseUrl` when given a map. */
|
|
1170
1202
|
baseUrl?: string;
|
|
@@ -1191,6 +1223,12 @@ interface RouteLayerOptions {
|
|
|
1191
1223
|
* route line"). Defaults to a dimmed grey.
|
|
1192
1224
|
*/
|
|
1193
1225
|
progressColor?: string;
|
|
1226
|
+
/** Casing colour for unselected alternative routes. */
|
|
1227
|
+
alternativeCasingColor?: string;
|
|
1228
|
+
/** Line colour for unselected alternative routes. */
|
|
1229
|
+
alternativeColor?: string;
|
|
1230
|
+
/** Colour of the ferry dashes drawn over the selected route. */
|
|
1231
|
+
ferryColor?: string;
|
|
1194
1232
|
}
|
|
1195
1233
|
/** Draws MapMap routes on a MapLibre map. */
|
|
1196
1234
|
declare class RouteLayer {
|
|
@@ -1211,7 +1249,22 @@ declare class RouteLayer {
|
|
|
1211
1249
|
private readonly design;
|
|
1212
1250
|
private alertsDesign;
|
|
1213
1251
|
private readonly progressColor;
|
|
1252
|
+
private readonly altSourceId;
|
|
1253
|
+
private readonly altCasingLayerId;
|
|
1254
|
+
private readonly altLineLayerId;
|
|
1255
|
+
private readonly ferrySourceId;
|
|
1256
|
+
private readonly ferryLayerId;
|
|
1257
|
+
private readonly altCasingColor;
|
|
1258
|
+
private readonly altColor;
|
|
1259
|
+
private readonly ferryColor;
|
|
1214
1260
|
private lastRoute;
|
|
1261
|
+
/** Unselected alternatives, drawn beneath the selected route. */
|
|
1262
|
+
private alternatives;
|
|
1263
|
+
/** Ferry legs of the selected route, drawn as dashes over its line. */
|
|
1264
|
+
private ferrySegments;
|
|
1265
|
+
private selectHandler;
|
|
1266
|
+
/** Runtime paint override, re-applied after every style reload. */
|
|
1267
|
+
private lineStyle;
|
|
1215
1268
|
private progress;
|
|
1216
1269
|
private maneuver;
|
|
1217
1270
|
private corridors;
|
|
@@ -1235,6 +1288,71 @@ declare class RouteLayer {
|
|
|
1235
1288
|
draw(route: ParsedRoute): void;
|
|
1236
1289
|
/** Add-or-update the source and layers for a route on the current style. */
|
|
1237
1290
|
private install;
|
|
1291
|
+
/**
|
|
1292
|
+
* Draw a bare line from coordinates, without a parsed OSRM route.
|
|
1293
|
+
*
|
|
1294
|
+
* {@link RouteLayer.draw} expects a {@link ParsedRoute} because it is
|
|
1295
|
+
* normally fed by {@link RouteLayer.route}. Callers that already have
|
|
1296
|
+
* geometry and nothing else — an agent tool result, a stored polyline,
|
|
1297
|
+
* a hand-built preview — had to invent a `ParsedRoute` with zeroed
|
|
1298
|
+
* distance and duration that `draw` never reads. This is that path,
|
|
1299
|
+
* named honestly.
|
|
1300
|
+
*/
|
|
1301
|
+
drawGeometry(coordinates: [number, number][]): void;
|
|
1302
|
+
/**
|
|
1303
|
+
* Draw a set of routes: one selected, the rest as dimmer alternatives
|
|
1304
|
+
* beneath it. Offering alternatives is table stakes for a navigation UI,
|
|
1305
|
+
* and the selected route keeps every feature of {@link RouteLayer.draw}
|
|
1306
|
+
* (progress, manoeuvre arrow, corridors, route effects).
|
|
1307
|
+
*
|
|
1308
|
+
* Pass the index of the route to select; out-of-range values clamp to the
|
|
1309
|
+
* first route. Calling with a single route is equivalent to `draw`, and
|
|
1310
|
+
* calling with an empty array clears everything.
|
|
1311
|
+
*/
|
|
1312
|
+
drawAlternatives(routes: ParsedRoute[], selectedIndex?: number): void;
|
|
1313
|
+
/** Which alternatives are currently drawn, in the order given. */
|
|
1314
|
+
get alternativeRoutes(): readonly ParsedRoute[];
|
|
1315
|
+
/**
|
|
1316
|
+
* Register a click handler for the alternative lines. The index is the
|
|
1317
|
+
* position within the array last passed to
|
|
1318
|
+
* {@link RouteLayer.drawAlternatives}, so a caller can re-issue that call
|
|
1319
|
+
* with the new selection. Passing `undefined` removes the handler.
|
|
1320
|
+
*/
|
|
1321
|
+
onSelectAlternative(handler: ((index: number) => void) | undefined): void;
|
|
1322
|
+
/**
|
|
1323
|
+
* Draw ferry legs of the selected route as dashes over its line, so water
|
|
1324
|
+
* crossings do not read as driving.
|
|
1325
|
+
*
|
|
1326
|
+
* Supplied as explicit geometries rather than derived from the route,
|
|
1327
|
+
* because `line-dasharray` cannot be data-driven: a ferry leg needs its
|
|
1328
|
+
* own layer, and only the caller knows which parts of their route are
|
|
1329
|
+
* ferries.
|
|
1330
|
+
*/
|
|
1331
|
+
setFerrySegments(segments: [number, number][][]): void;
|
|
1332
|
+
/** Remove the ferry dashes. */
|
|
1333
|
+
clearFerrySegments(): void;
|
|
1334
|
+
/** Add-or-update the alternative-route source and its two layers. */
|
|
1335
|
+
private installAlternatives;
|
|
1336
|
+
private readonly handleAlternativeClick;
|
|
1337
|
+
/** Original array position of each drawn alternative, by its own index. */
|
|
1338
|
+
private altOriginalIndices;
|
|
1339
|
+
private removeAlternativeLayers;
|
|
1340
|
+
/** Add-or-update the ferry-dash overlay above the selected route. */
|
|
1341
|
+
private installFerry;
|
|
1342
|
+
/**
|
|
1343
|
+
* Override the drawn line's paint at runtime, over whatever the design or
|
|
1344
|
+
* the built-in look set.
|
|
1345
|
+
*
|
|
1346
|
+
* Route styling is not always static: a route can be provisional, or a
|
|
1347
|
+
* straight-line approximation that must not be mistaken for a surveyed
|
|
1348
|
+
* one. That is a paint change on a route already drawn, so it belongs
|
|
1349
|
+
* here rather than in the constructor's design.
|
|
1350
|
+
*
|
|
1351
|
+
* Overrides survive style reloads. Pass `{}` to clear them.
|
|
1352
|
+
*/
|
|
1353
|
+
setLineStyle(style: RouteLineStyle): void;
|
|
1354
|
+
/** Apply any runtime override; a no-op when the layers are absent. */
|
|
1355
|
+
private applyLineStyle;
|
|
1238
1356
|
/**
|
|
1239
1357
|
* Sets how much of the route has been travelled, as a fraction in `[0, 1]`
|
|
1240
1358
|
* of the line's length. The travelled part dims to `progressColor` (the
|
|
@@ -2783,4 +2901,4 @@ declare class VoiceGuidance {
|
|
|
2783
2901
|
private playEarcon;
|
|
2784
2902
|
}
|
|
2785
2903
|
|
|
2786
|
-
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, 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, type MapDisplayMode, MapMapMap, type MapMapOptions, type MapMapTheme, 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, 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, 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, isNameTextField, languageTextField, lngLatToMercator, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, resetDiagnostics, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, uploadProbeBatch };
|
|
2904
|
+
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, 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, type MapDisplayMode, MapMapMap, type MapMapOptions, type MapMapTheme, 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, 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 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, isNameTextField, languageTextField, lngLatToMercator, navAlertLeadDistanceM, navAlertSoundUrl, navCameraKind, navDesignFromTheme, navDesignFromThemeUrl, parseCssColour, parseHexColor, parseNavAlertsDesign, parseNavDesign, parseOsrmRoute, parsePoiDesign, placesFromGeoJSON, poiDesignFromTheme, poiDesignFromThemeUrl, poiDesignIsDefault, poiTextColorExpression, prefersReducedMotion, registerPmtilesProtocol, relativeLuminance, resetDiagnostics, resolveTheme, runMapDiagnostics, setMapLanguage, severityProsody, shortestArcDeg, shortestArcDelta, speak, ssmlToText, sunTimes, tessellateRouteRibbon, toLngLat, toPmtilesUrl, uploadProbeBatch };
|
package/dist/index.js
CHANGED
|
@@ -2159,6 +2159,9 @@ var CASING_COLOR = "#1f438a";
|
|
|
2159
2159
|
var CORRIDOR_COLOR = "#e05c6c";
|
|
2160
2160
|
var CORRIDOR_OPACITY = 0.55;
|
|
2161
2161
|
var PROGRESS_COLOR = "#b0b0b0";
|
|
2162
|
+
var ALT_CASING_COLOR = "#5a6b84";
|
|
2163
|
+
var ALT_LINE_COLOR = "#aebdd2";
|
|
2164
|
+
var FERRY_COLOR = "#eaf1fb";
|
|
2162
2165
|
function arrowImage() {
|
|
2163
2166
|
const size = 24;
|
|
2164
2167
|
const data = new Uint8Array(size * size * 4);
|
|
@@ -2186,13 +2189,29 @@ function arrowImage() {
|
|
|
2186
2189
|
}
|
|
2187
2190
|
var RouteLayer = class {
|
|
2188
2191
|
constructor(map, options = {}) {
|
|
2192
|
+
/** Unselected alternatives, drawn beneath the selected route. */
|
|
2193
|
+
this.alternatives = [];
|
|
2194
|
+
/** Ferry legs of the selected route, drawn as dashes over its line. */
|
|
2195
|
+
this.ferrySegments = [];
|
|
2189
2196
|
this.progress = 0;
|
|
2190
2197
|
this.corridors = [];
|
|
2191
2198
|
this.handleStyleLoad = () => {
|
|
2199
|
+
this.installAlternatives();
|
|
2192
2200
|
if (this.lastRoute) this.install(this.lastRoute);
|
|
2193
2201
|
else this.installManeuver();
|
|
2194
2202
|
this.installCorridors();
|
|
2203
|
+
this.installFerry();
|
|
2195
2204
|
};
|
|
2205
|
+
this.handleAlternativeClick = (event) => {
|
|
2206
|
+
if (!this.selectHandler) return;
|
|
2207
|
+
const raw = event.features?.[0]?.properties?.["index"];
|
|
2208
|
+
const position = typeof raw === "number" ? raw : Number(raw);
|
|
2209
|
+
if (!Number.isInteger(position)) return;
|
|
2210
|
+
const original = this.altOriginalIndices[position];
|
|
2211
|
+
if (original !== void 0) this.selectHandler(original);
|
|
2212
|
+
};
|
|
2213
|
+
/** Original array position of each drawn alternative, by its own index. */
|
|
2214
|
+
this.altOriginalIndices = [];
|
|
2196
2215
|
if (map instanceof MapMapMap) {
|
|
2197
2216
|
this.map = map.map;
|
|
2198
2217
|
this.owner = map;
|
|
@@ -2219,7 +2238,15 @@ var RouteLayer = class {
|
|
|
2219
2238
|
this.arrowImageId = `${id}-arrow`;
|
|
2220
2239
|
this.corridorSourceId = `${id}-corridor-src`;
|
|
2221
2240
|
this.corridorLayerId = `${id}-corridor`;
|
|
2241
|
+
this.altSourceId = `${id}-alt-src`;
|
|
2242
|
+
this.altCasingLayerId = `${id}-alt-casing`;
|
|
2243
|
+
this.altLineLayerId = `${id}-alt-line`;
|
|
2244
|
+
this.ferrySourceId = `${id}-ferry-src`;
|
|
2245
|
+
this.ferryLayerId = `${id}-ferry`;
|
|
2222
2246
|
this.progressColor = options.progressColor ?? PROGRESS_COLOR;
|
|
2247
|
+
this.altCasingColor = options.alternativeCasingColor ?? ALT_CASING_COLOR;
|
|
2248
|
+
this.altColor = options.alternativeColor ?? ALT_LINE_COLOR;
|
|
2249
|
+
this.ferryColor = options.ferryColor ?? FERRY_COLOR;
|
|
2223
2250
|
this.map.on("style.load", this.handleStyleLoad);
|
|
2224
2251
|
}
|
|
2225
2252
|
/**
|
|
@@ -2285,6 +2312,7 @@ var RouteLayer = class {
|
|
|
2285
2312
|
}
|
|
2286
2313
|
if (this.map.getLayer(this.casingLayerId) && this.map.getLayer(this.lineLayerId)) {
|
|
2287
2314
|
this.applyProgress();
|
|
2315
|
+
this.applyLineStyle();
|
|
2288
2316
|
this.installManeuver();
|
|
2289
2317
|
return;
|
|
2290
2318
|
}
|
|
@@ -2295,8 +2323,8 @@ var RouteLayer = class {
|
|
|
2295
2323
|
layout: { "line-cap": "round", "line-join": "round" },
|
|
2296
2324
|
paint: this.design ? {
|
|
2297
2325
|
"line-color": this.design.casingColor,
|
|
2298
|
-
"line-width": this.design.width + 4,
|
|
2299
|
-
"line-opacity": this.design.opacity
|
|
2326
|
+
"line-width": this.design.casingWidth ?? this.design.width + 4,
|
|
2327
|
+
"line-opacity": this.design.casingOpacity ?? this.design.opacity
|
|
2300
2328
|
} : {
|
|
2301
2329
|
"line-color": CASING_COLOR,
|
|
2302
2330
|
"line-width": ["interpolate", ["linear"], ["zoom"], 8, 6, 16, 12]
|
|
@@ -2310,7 +2338,8 @@ var RouteLayer = class {
|
|
|
2310
2338
|
paint: this.design ? {
|
|
2311
2339
|
"line-color": this.design.color,
|
|
2312
2340
|
"line-width": this.design.width,
|
|
2313
|
-
"line-opacity": this.design.opacity
|
|
2341
|
+
"line-opacity": this.design.opacity,
|
|
2342
|
+
...this.design.dash ? { "line-dasharray": this.design.dash } : {}
|
|
2314
2343
|
} : {
|
|
2315
2344
|
"line-color": SIGNAL_BLUE,
|
|
2316
2345
|
"line-width": ["interpolate", ["linear"], ["zoom"], 8, 3, 16, 8]
|
|
@@ -2319,8 +2348,202 @@ var RouteLayer = class {
|
|
|
2319
2348
|
if (!this.map.getLayer(this.casingLayerId)) this.map.addLayer(casing);
|
|
2320
2349
|
if (!this.map.getLayer(this.lineLayerId)) this.map.addLayer(line);
|
|
2321
2350
|
this.applyProgress();
|
|
2351
|
+
this.applyLineStyle();
|
|
2322
2352
|
this.installManeuver();
|
|
2323
2353
|
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Draw a bare line from coordinates, without a parsed OSRM route.
|
|
2356
|
+
*
|
|
2357
|
+
* {@link RouteLayer.draw} expects a {@link ParsedRoute} because it is
|
|
2358
|
+
* normally fed by {@link RouteLayer.route}. Callers that already have
|
|
2359
|
+
* geometry and nothing else — an agent tool result, a stored polyline,
|
|
2360
|
+
* a hand-built preview — had to invent a `ParsedRoute` with zeroed
|
|
2361
|
+
* distance and duration that `draw` never reads. This is that path,
|
|
2362
|
+
* named honestly.
|
|
2363
|
+
*/
|
|
2364
|
+
drawGeometry(coordinates) {
|
|
2365
|
+
this.draw({
|
|
2366
|
+
distanceM: 0,
|
|
2367
|
+
durationS: 0,
|
|
2368
|
+
geometry: { type: "LineString", coordinates },
|
|
2369
|
+
raw: {}
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Draw a set of routes: one selected, the rest as dimmer alternatives
|
|
2374
|
+
* beneath it. Offering alternatives is table stakes for a navigation UI,
|
|
2375
|
+
* and the selected route keeps every feature of {@link RouteLayer.draw}
|
|
2376
|
+
* (progress, manoeuvre arrow, corridors, route effects).
|
|
2377
|
+
*
|
|
2378
|
+
* Pass the index of the route to select; out-of-range values clamp to the
|
|
2379
|
+
* first route. Calling with a single route is equivalent to `draw`, and
|
|
2380
|
+
* calling with an empty array clears everything.
|
|
2381
|
+
*/
|
|
2382
|
+
drawAlternatives(routes, selectedIndex = 0) {
|
|
2383
|
+
if (routes.length === 0) {
|
|
2384
|
+
this.clear();
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
const index = selectedIndex >= 0 && selectedIndex < routes.length ? selectedIndex : 0;
|
|
2388
|
+
this.alternatives = routes.filter((_, i) => i !== index);
|
|
2389
|
+
this.altOriginalIndices = routes.map((_, i) => i).filter((i) => i !== index);
|
|
2390
|
+
this.installAlternatives();
|
|
2391
|
+
this.draw(routes[index]);
|
|
2392
|
+
}
|
|
2393
|
+
/** Which alternatives are currently drawn, in the order given. */
|
|
2394
|
+
get alternativeRoutes() {
|
|
2395
|
+
return this.alternatives;
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Register a click handler for the alternative lines. The index is the
|
|
2399
|
+
* position within the array last passed to
|
|
2400
|
+
* {@link RouteLayer.drawAlternatives}, so a caller can re-issue that call
|
|
2401
|
+
* with the new selection. Passing `undefined` removes the handler.
|
|
2402
|
+
*/
|
|
2403
|
+
onSelectAlternative(handler) {
|
|
2404
|
+
this.selectHandler = handler;
|
|
2405
|
+
}
|
|
2406
|
+
/**
|
|
2407
|
+
* Draw ferry legs of the selected route as dashes over its line, so water
|
|
2408
|
+
* crossings do not read as driving.
|
|
2409
|
+
*
|
|
2410
|
+
* Supplied as explicit geometries rather than derived from the route,
|
|
2411
|
+
* because `line-dasharray` cannot be data-driven: a ferry leg needs its
|
|
2412
|
+
* own layer, and only the caller knows which parts of their route are
|
|
2413
|
+
* ferries.
|
|
2414
|
+
*/
|
|
2415
|
+
setFerrySegments(segments) {
|
|
2416
|
+
this.ferrySegments = segments;
|
|
2417
|
+
if (this.map.isStyleLoaded()) this.installFerry();
|
|
2418
|
+
}
|
|
2419
|
+
/** Remove the ferry dashes. */
|
|
2420
|
+
clearFerrySegments() {
|
|
2421
|
+
this.ferrySegments = [];
|
|
2422
|
+
if (this.map.getLayer(this.ferryLayerId)) this.map.removeLayer(this.ferryLayerId);
|
|
2423
|
+
if (this.map.getSource(this.ferrySourceId)) this.map.removeSource(this.ferrySourceId);
|
|
2424
|
+
}
|
|
2425
|
+
/** Add-or-update the alternative-route source and its two layers. */
|
|
2426
|
+
installAlternatives() {
|
|
2427
|
+
if (this.alternatives.length === 0) {
|
|
2428
|
+
this.removeAlternativeLayers();
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
if (!this.map.isStyleLoaded()) return;
|
|
2432
|
+
const data = {
|
|
2433
|
+
type: "FeatureCollection",
|
|
2434
|
+
features: this.alternatives.map((route, i) => ({
|
|
2435
|
+
type: "Feature",
|
|
2436
|
+
properties: { index: i },
|
|
2437
|
+
geometry: route.geometry
|
|
2438
|
+
}))
|
|
2439
|
+
};
|
|
2440
|
+
const existing = this.map.getSource(this.altSourceId);
|
|
2441
|
+
if (existing) existing.setData(data);
|
|
2442
|
+
else this.map.addSource(this.altSourceId, { type: "geojson", data });
|
|
2443
|
+
const below = this.map.getLayer(this.casingLayerId) ? this.casingLayerId : void 0;
|
|
2444
|
+
if (!this.map.getLayer(this.altCasingLayerId)) {
|
|
2445
|
+
this.map.addLayer({
|
|
2446
|
+
id: this.altCasingLayerId,
|
|
2447
|
+
type: "line",
|
|
2448
|
+
source: this.altSourceId,
|
|
2449
|
+
layout: { "line-cap": "round", "line-join": "round" },
|
|
2450
|
+
paint: {
|
|
2451
|
+
"line-color": this.altCasingColor,
|
|
2452
|
+
"line-width": 7,
|
|
2453
|
+
"line-opacity": 0.55
|
|
2454
|
+
}
|
|
2455
|
+
}, below);
|
|
2456
|
+
}
|
|
2457
|
+
if (!this.map.getLayer(this.altLineLayerId)) {
|
|
2458
|
+
this.map.addLayer({
|
|
2459
|
+
id: this.altLineLayerId,
|
|
2460
|
+
type: "line",
|
|
2461
|
+
source: this.altSourceId,
|
|
2462
|
+
layout: { "line-cap": "round", "line-join": "round" },
|
|
2463
|
+
paint: {
|
|
2464
|
+
"line-color": this.altColor,
|
|
2465
|
+
"line-width": 4,
|
|
2466
|
+
"line-opacity": 0.9
|
|
2467
|
+
}
|
|
2468
|
+
}, below);
|
|
2469
|
+
this.map.on("click", this.altLineLayerId, this.handleAlternativeClick);
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
removeAlternativeLayers() {
|
|
2473
|
+
if (this.map.getLayer(this.altLineLayerId)) {
|
|
2474
|
+
this.map.off("click", this.altLineLayerId, this.handleAlternativeClick);
|
|
2475
|
+
this.map.removeLayer(this.altLineLayerId);
|
|
2476
|
+
}
|
|
2477
|
+
if (this.map.getLayer(this.altCasingLayerId)) this.map.removeLayer(this.altCasingLayerId);
|
|
2478
|
+
if (this.map.getSource(this.altSourceId)) this.map.removeSource(this.altSourceId);
|
|
2479
|
+
}
|
|
2480
|
+
/** Add-or-update the ferry-dash overlay above the selected route. */
|
|
2481
|
+
installFerry() {
|
|
2482
|
+
if (this.ferrySegments.length === 0) {
|
|
2483
|
+
this.clearFerrySegments();
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
if (!this.map.isStyleLoaded()) return;
|
|
2487
|
+
const data = {
|
|
2488
|
+
type: "FeatureCollection",
|
|
2489
|
+
features: this.ferrySegments.map((coordinates) => ({
|
|
2490
|
+
type: "Feature",
|
|
2491
|
+
properties: {},
|
|
2492
|
+
geometry: { type: "LineString", coordinates }
|
|
2493
|
+
}))
|
|
2494
|
+
};
|
|
2495
|
+
const existing = this.map.getSource(this.ferrySourceId);
|
|
2496
|
+
if (existing) existing.setData(data);
|
|
2497
|
+
else this.map.addSource(this.ferrySourceId, { type: "geojson", data });
|
|
2498
|
+
if (!this.map.getLayer(this.ferryLayerId)) {
|
|
2499
|
+
this.map.addLayer({
|
|
2500
|
+
id: this.ferryLayerId,
|
|
2501
|
+
type: "line",
|
|
2502
|
+
source: this.ferrySourceId,
|
|
2503
|
+
layout: { "line-cap": "butt", "line-join": "round" },
|
|
2504
|
+
paint: {
|
|
2505
|
+
"line-color": this.ferryColor,
|
|
2506
|
+
"line-width": 2.5,
|
|
2507
|
+
"line-dasharray": [1.2, 1.6]
|
|
2508
|
+
}
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Override the drawn line's paint at runtime, over whatever the design or
|
|
2514
|
+
* the built-in look set.
|
|
2515
|
+
*
|
|
2516
|
+
* Route styling is not always static: a route can be provisional, or a
|
|
2517
|
+
* straight-line approximation that must not be mistaken for a surveyed
|
|
2518
|
+
* one. That is a paint change on a route already drawn, so it belongs
|
|
2519
|
+
* here rather than in the constructor's design.
|
|
2520
|
+
*
|
|
2521
|
+
* Overrides survive style reloads. Pass `{}` to clear them.
|
|
2522
|
+
*/
|
|
2523
|
+
setLineStyle(style) {
|
|
2524
|
+
this.lineStyle = Object.keys(style).length > 0 ? style : void 0;
|
|
2525
|
+
this.applyLineStyle();
|
|
2526
|
+
}
|
|
2527
|
+
/** Apply any runtime override; a no-op when the layers are absent. */
|
|
2528
|
+
applyLineStyle() {
|
|
2529
|
+
const style = this.lineStyle;
|
|
2530
|
+
if (!style) return;
|
|
2531
|
+
if (this.map.getLayer(this.lineLayerId)) {
|
|
2532
|
+
if (style.color !== void 0) {
|
|
2533
|
+
this.map.setPaintProperty(this.lineLayerId, "line-color", style.color);
|
|
2534
|
+
}
|
|
2535
|
+
if (style.dash !== void 0) {
|
|
2536
|
+
this.map.setPaintProperty(
|
|
2537
|
+
this.lineLayerId,
|
|
2538
|
+
"line-dasharray",
|
|
2539
|
+
style.dash ?? [1, 0]
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
if (style.casingOpacity !== void 0 && this.map.getLayer(this.casingLayerId)) {
|
|
2544
|
+
this.map.setPaintProperty(this.casingLayerId, "line-opacity", style.casingOpacity);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2324
2547
|
/**
|
|
2325
2548
|
* Sets how much of the route has been travelled, as a fraction in `[0, 1]`
|
|
2326
2549
|
* of the line's length. The travelled part dims to `progressColor` (the
|
|
@@ -2461,6 +2684,10 @@ var RouteLayer = class {
|
|
|
2461
2684
|
clear() {
|
|
2462
2685
|
this.clearManeuver();
|
|
2463
2686
|
this.clearAlertCorridors();
|
|
2687
|
+
this.clearFerrySegments();
|
|
2688
|
+
this.alternatives = [];
|
|
2689
|
+
this.altOriginalIndices = [];
|
|
2690
|
+
this.removeAlternativeLayers();
|
|
2464
2691
|
for (const layerId of [this.lineLayerId, this.casingLayerId]) {
|
|
2465
2692
|
if (this.map.getLayer(layerId)) this.map.removeLayer(layerId);
|
|
2466
2693
|
}
|
|
@@ -3936,6 +4163,16 @@ var AdrCheck = class {
|
|
|
3936
4163
|
};
|
|
3937
4164
|
|
|
3938
4165
|
// src/guidance.ts
|
|
4166
|
+
var CSS_COLOUR = /^(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix|var)\((?:[\w\s.,%/#-]|\([\w\s.,%/#-]*\))*\)$/i;
|
|
4167
|
+
function safeColour(value, fallback) {
|
|
4168
|
+
const v = value.trim();
|
|
4169
|
+
if (v === "" || /[;{}]|url\(|\/\*/i.test(v)) return fallback;
|
|
4170
|
+
if (v.startsWith("#")) {
|
|
4171
|
+
return /^[0-9a-fA-F]+$/.test(v.slice(1)) && [3, 4, 6, 8].includes(v.length - 1) ? v : fallback;
|
|
4172
|
+
}
|
|
4173
|
+
if (/^[a-zA-Z][a-zA-Z-]*$/.test(v)) return v;
|
|
4174
|
+
return CSS_COLOUR.test(v) ? v : fallback;
|
|
4175
|
+
}
|
|
3939
4176
|
function extractGuidance(route) {
|
|
3940
4177
|
const legs = route.raw["legs"] ?? [];
|
|
3941
4178
|
const out = [];
|
|
@@ -3986,10 +4223,11 @@ var XML_ENTITIES = {
|
|
|
3986
4223
|
"'": "'"
|
|
3987
4224
|
};
|
|
3988
4225
|
function ssmlToText(ssml) {
|
|
3989
|
-
return ssml.replace(/<[^>]+>/g, "").replace(
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
4226
|
+
return ssml.replace(/<[^>]+>/g, "").replace(/&(?:amp|lt|gt|quot|apos);|&#(\d+);/g, (entity, decimal) => {
|
|
4227
|
+
if (decimal === void 0) return XML_ENTITIES[entity] ?? entity;
|
|
4228
|
+
const n = Number(decimal);
|
|
4229
|
+
return n <= 1114111 ? String.fromCodePoint(n) : entity;
|
|
4230
|
+
}).trim();
|
|
3993
4231
|
}
|
|
3994
4232
|
function bannerLanes(banner) {
|
|
3995
4233
|
const components = banner.sub?.components ?? [];
|
|
@@ -4045,7 +4283,7 @@ var GuidanceBanner = class {
|
|
|
4045
4283
|
this.design = design;
|
|
4046
4284
|
this.element = doc.createElement("div");
|
|
4047
4285
|
this.element.className = "mapmap-banner";
|
|
4048
|
-
this.element.style.cssText = design ? `display:none;align-items:center;box-sizing:border-box;gap:${Math.round((design.padding ?? 10) * 1.2)}px;padding:${design.padding ?? 10}px ${Math.round((design.padding ?? 10) * 1.4)}px;background:${design.background};color:${design.textColor};border-radius:${design.cornerRadius ?? 10}px;max-width:${design.maxWidth ?? 340}px;` + (design.height !== void 0 ? `min-height:${design.height}px;` : "") + `font:600 ${design.fontSize}px/1.3 system-ui,sans-serif` : "display:none;gap:12px;align-items:center;padding:10px 14px;background:#101418;color:#fff;border-radius:10px;font:600 16px/1.3 system-ui,sans-serif";
|
|
4286
|
+
this.element.style.cssText = design ? `display:none;align-items:center;box-sizing:border-box;gap:${Math.round((design.padding ?? 10) * 1.2)}px;padding:${design.padding ?? 10}px ${Math.round((design.padding ?? 10) * 1.4)}px;background:${safeColour(design.background, "#101418")};color:${safeColour(design.textColor, "#ffffff")};border-radius:${design.cornerRadius ?? 10}px;max-width:${design.maxWidth ?? 340}px;` + (design.height !== void 0 ? `min-height:${design.height}px;` : "") + `font:600 ${design.fontSize}px/1.3 system-ui,sans-serif` : "display:none;gap:12px;align-items:center;padding:10px 14px;background:#101418;color:#fff;border-radius:10px;font:600 16px/1.3 system-ui,sans-serif";
|
|
4049
4287
|
container?.appendChild(this.element);
|
|
4050
4288
|
}
|
|
4051
4289
|
/**
|
|
@@ -4304,9 +4542,9 @@ var CameraAlertChip = class {
|
|
|
4304
4542
|
this.element.style.cssText = `display:${shown};gap:8px;align-items:center;padding:8px 12px;background:${this.escalated ? "#c0392b" : "#101418"};color:#fff;border-radius:10px;font:600 15px/1.3 system-ui,sans-serif`;
|
|
4305
4543
|
return;
|
|
4306
4544
|
}
|
|
4307
|
-
const background = this.escalated ? design.escalatedBackground : design.background;
|
|
4308
|
-
const color = this.escalated ? design.escalatedTextColor : design.textColor;
|
|
4309
|
-
this.element.style.cssText = `display:${shown};gap:8px;align-items:center;box-sizing:border-box;padding:8px 12px;background:${background};color:${color};border-radius:${design.cornerRadius}px;` + (design.outlineWidth > 0 ? `border:${design.outlineWidth}px solid ${design.outlineColor};` : "") + (CHIP_SLOT_CSS[design.chipPosition] ?? "") + "font:600 15px/1.3 system-ui,sans-serif";
|
|
4545
|
+
const background = this.escalated ? safeColour(design.escalatedBackground, "#c0392b") : safeColour(design.background, "#101418");
|
|
4546
|
+
const color = this.escalated ? safeColour(design.escalatedTextColor, "#ffffff") : safeColour(design.textColor, "#ffffff");
|
|
4547
|
+
this.element.style.cssText = `display:${shown};gap:8px;align-items:center;box-sizing:border-box;padding:8px 12px;background:${background};color:${color};border-radius:${design.cornerRadius}px;` + (design.outlineWidth > 0 ? `border:${design.outlineWidth}px solid ${safeColour(design.outlineColor, "#ffffff")};` : "") + (CHIP_SLOT_CSS[design.chipPosition] ?? "") + "font:600 15px/1.3 system-ui,sans-serif";
|
|
4310
4548
|
}
|
|
4311
4549
|
};
|
|
4312
4550
|
|