@mapvx/web-kit 0.0.0-stage → 1.2.0-develop.10

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.
Files changed (50) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +187 -2
  3. package/dist/cjs/chunks/DRACOLoader-BatVMFjv.cjs +2 -0
  4. package/dist/cjs/chunks/GLTFLoader-DPzCuhq_.cjs +2 -0
  5. package/dist/cjs/chunks/KTX2Loader-D3UkVYrQ.cjs +2 -0
  6. package/dist/cjs/chunks/accessibility-DSrJvXsP.cjs +2 -0
  7. package/dist/cjs/chunks/back_arrow-DDucL2vy.cjs +2 -0
  8. package/dist/cjs/chunks/debug-hooks-6E-6XyZt.cjs +2 -0
  9. package/dist/cjs/chunks/dist-Bn3kS9il.cjs +2 -0
  10. package/dist/cjs/chunks/dist-C7Xq932f.cjs +2 -0
  11. package/dist/cjs/chunks/dist-CyU0uhT_.cjs +2 -0
  12. package/dist/cjs/chunks/expression-YhbojQDk.cjs +2 -0
  13. package/dist/cjs/chunks/globe-viewport-L8jhK17I.cjs +2 -0
  14. package/dist/cjs/chunks/icon-origin-point-Fx1ItO6l.cjs +2 -0
  15. package/dist/cjs/chunks/meshopt_decoder.module-CfZgR5oC.cjs +2 -0
  16. package/dist/cjs/chunks/repeat_icon-DTL5IJer.cjs +2 -0
  17. package/dist/cjs/chunks/rolldown-runtime-X-Z9OGZI.cjs +2 -0
  18. package/dist/cjs/chunks/shader-type-decoder-CM9es9dC.cjs +2 -0
  19. package/dist/cjs/chunks/styles-DSsNALyl.cjs +2 -0
  20. package/dist/cjs/chunks/three.module-DrkjviT-.cjs +2 -0
  21. package/dist/cjs/chunks/walking-DH57xlEw.cjs +2 -0
  22. package/dist/cjs/chunks/webgl-CmQcn-HM.cjs +2 -0
  23. package/dist/cjs/chunks/webgl-device-Bjj2DuDc.cjs +2 -0
  24. package/dist/cjs/web-kit.cjs +425 -0
  25. package/dist/es/chunks/DRACOLoader-Coaeymvd.js +2 -0
  26. package/dist/es/chunks/GLTFLoader-Cg9W7uGp.js +2 -0
  27. package/dist/es/chunks/KTX2Loader-CW7QOwqk.js +2 -0
  28. package/dist/es/chunks/accessibility-CY2Znzrd.js +2 -0
  29. package/dist/es/chunks/back_arrow-DXxWd53C.js +2 -0
  30. package/dist/es/chunks/debug-hooks-CttUbwx0.js +2 -0
  31. package/dist/es/chunks/dist-DrDbx8fV.js +2 -0
  32. package/dist/es/chunks/dist-Dzp0YWIR.js +4 -0
  33. package/dist/es/chunks/dist-TkIGGp-O.js +2 -0
  34. package/dist/es/chunks/expression-DK4fcsrz.js +2 -0
  35. package/dist/es/chunks/globe-viewport-CmXSxt1e.js +2 -0
  36. package/dist/es/chunks/icon-origin-point-CsdwEebb.js +2 -0
  37. package/dist/es/chunks/meshopt_decoder.module-CymL9NxH.js +2 -0
  38. package/dist/es/chunks/repeat_icon-VI8TF8gY.js +2 -0
  39. package/dist/es/chunks/rolldown-runtime-DD4WNi4o.js +2 -0
  40. package/dist/es/chunks/shader-type-decoder-aS2S_0ef.js +2 -0
  41. package/dist/es/chunks/styles-CT7CDFlr.js +2 -0
  42. package/dist/es/chunks/three.module-BeGwQoXi.js +22 -0
  43. package/dist/es/chunks/walking-DJUq61cT.js +2 -0
  44. package/dist/es/chunks/webgl-Cm54xPsy.js +2 -0
  45. package/dist/es/chunks/webgl-device-Cmfm4mkc.js +2 -0
  46. package/dist/es/web-kit.mjs +428 -0
  47. package/dist/iife/web-kit.iife.js +425 -0
  48. package/dist/sw/mvx-tiles-sw.js +582 -0
  49. package/dist/types/index.d.ts +1765 -0
  50. package/package.json +87 -4
@@ -0,0 +1,1765 @@
1
+ import { Configuration } from '@mapvx/web-js';
2
+ import { CSSResult } from 'lit';
3
+ import { InnerFloor } from '@mapvx/web-js';
4
+ import { LatLng } from '@mapvx/web-js';
5
+ import { LitElement } from 'lit';
6
+ import { MapVXSDK } from '@mapvx/web-js';
7
+ import { MVXPlace } from '@mapvx/web-js';
8
+ import { MVXRoute } from '@mapvx/web-js';
9
+ import { PropertyValues } from 'lit';
10
+ import { ReactiveController } from 'lit';
11
+ import { ReactiveControllerHost } from 'lit';
12
+ import { ReactiveElement } from '@lit/reactive-element';
13
+ import { TemplateResult } from 'lit-html';
14
+
15
+ /**
16
+ * LocalStorage keys used by the SDK for caching.
17
+ *
18
+ * @description These keys are used internally by the SDK to persist cached data, one per cache
19
+ * type (web-js 4.3.1 `DEFAULT_CACHE_CONFIGS`). Exposed for advanced use cases like manual cache
20
+ * inspection or cleanup. A unit test writes every type with the SDK's own `CacheManager` and
21
+ * checks that this list clears them all, so a renamed key fails it.
22
+ *
23
+ * @example Checking cache size
24
+ * ```typescript
25
+ * import { CACHE_STORAGE_KEYS } from '@mapvx/web-kit';
26
+ *
27
+ * let totalSize = 0;
28
+ * CACHE_STORAGE_KEYS.forEach(key => {
29
+ * const data = localStorage.getItem(key);
30
+ * if (data) totalSize += data.length;
31
+ * });
32
+ * console.log(`Cache size: ${(totalSize / 1024).toFixed(2)} KB`);
33
+ * ```
34
+ */
35
+ export declare const CACHE_STORAGE_KEYS: readonly ["mvx_places", "mvx_routes", "mvx_accessible_routes", "mvx_configurations", "mvx_categories", "mvx_vehicles", "mvx_stops", "mvx_subplaces", "mvx_available_places", "mvx_styles"];
36
+
37
+ /**
38
+ * Complete cache configuration for the SDK.
39
+ *
40
+ * @description Provides comprehensive control over SDK caching behavior.
41
+ * Use the provided presets ({@link TOTEM_CACHE_CONFIG}, {@link WEB_CACHE_CONFIG})
42
+ * or create custom configurations with {@link mergeCacheConfig}.
43
+ *
44
+ * @example Using a preset directly
45
+ * ```typescript
46
+ * import { TOTEM_CACHE_CONFIG } from '@mapvx/web-kit';
47
+ *
48
+ * // Pass to component
49
+ * element.cacheConfig = TOTEM_CACHE_CONFIG;
50
+ * ```
51
+ *
52
+ * @example Creating a custom configuration
53
+ * ```typescript
54
+ * const myConfig: CacheConfig = {
55
+ * persistent: true,
56
+ * maxStorageBytes: 10 * 1024 * 1024, // 10MB
57
+ * configs: {
58
+ * places: { maxItems: 500, ttlMs: 2 * 60 * 60 * 1000 },
59
+ * subPlaces: { maxItems: 200, ttlMs: 60 * 60 * 1000 },
60
+ * routes: { maxItems: 100, ttlMs: 15 * 60 * 1000 },
61
+ * accessibleRoutes: { maxItems: 100, ttlMs: 15 * 60 * 1000 },
62
+ * configurations: { maxItems: 10, ttlMs: 4 * 60 * 60 * 1000 },
63
+ * categories: { maxItems: 50, ttlMs: 2 * 60 * 60 * 1000 },
64
+ * vehicles: { maxItems: 20, ttlMs: 30 * 60 * 1000 },
65
+ * stops: { maxItems: 50, ttlMs: 30 * 60 * 1000 },
66
+ * },
67
+ * };
68
+ * ```
69
+ */
70
+ export declare interface CacheConfig {
71
+ /**
72
+ * Enables localStorage persistence across browser sessions.
73
+ * When true, cached data survives page reloads and browser restarts, except for the types
74
+ * whose {@link CacheTypeConfig.persist} is `false`.
75
+ * @defaultValue true (in presets)
76
+ */
77
+ persistent: boolean;
78
+ /**
79
+ * Largest localStorage entry each cache type may write, in UTF-16 code units despite the name:
80
+ * the SDK compares it with the length of the serialized string, the unit Chrome counts its quota
81
+ * in (an origin gets about 5.2 M of them). The SDK applies it to every type on its own, not to
82
+ * their sum, so it does not bound the total the components store. A type that outgrows it stops
83
+ * being written and keeps its last stored copy.
84
+ */
85
+ maxStorageBytes: number;
86
+ /**
87
+ * Per-type cache customization.
88
+ * Each key represents a different data category with independent limits. `availablePlaces` and
89
+ * `styles` are optional: left out, the SDK's own defaults apply (persisted, 5 and 20 items).
90
+ */
91
+ configs: {
92
+ /** Location/venue information (parent places, POIs) */
93
+ places: CacheTypeConfig;
94
+ /** The places inside each venue (stores, services), one list per venue and language */
95
+ subPlaces: CacheTypeConfig;
96
+ /** Standard walking route calculations */
97
+ routes: CacheTypeConfig;
98
+ /** Accessibility-optimized routes (wheelchair, reduced mobility) */
99
+ accessibleRoutes: CacheTypeConfig;
100
+ /** Map styling and system configurations */
101
+ configurations: CacheTypeConfig;
102
+ /** Place categorization and taxonomy data */
103
+ categories: CacheTypeConfig;
104
+ /** Transport mode information */
105
+ vehicles: CacheTypeConfig;
106
+ /** Transit station/stop data */
107
+ stops: CacheTypeConfig;
108
+ /** The api key's place list, which the components no longer prefetch */
109
+ availablePlaces?: CacheTypeConfig;
110
+ /** Map styles, one per venue, theme and language (about 50 KB each) */
111
+ styles?: CacheTypeConfig;
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Configuration for a specific cache type.
117
+ *
118
+ * @description Defines storage limits and expiration for a single data category.
119
+ * Each cache type (places, routes, etc.) can have independent configuration.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const routeCacheConfig: CacheTypeConfig = {
124
+ * maxItems: 100, // Store up to 100 routes
125
+ * ttlMs: 15 * 60000 // Expire after 15 minutes
126
+ * };
127
+ * ```
128
+ *
129
+ * @example Keeping a type out of localStorage
130
+ * ```typescript
131
+ * const subPlacesCacheConfig: CacheTypeConfig = {
132
+ * maxItems: 100,
133
+ * ttlMs: 15 * 60000,
134
+ * persist: false // In memory only, even when `persistent` is on
135
+ * };
136
+ * ```
137
+ */
138
+ export declare interface CacheTypeConfig {
139
+ /**
140
+ * Maximum number of entries to store in this cache.
141
+ * When exceeded, oldest entries are evicted (LRU policy).
142
+ */
143
+ maxItems: number;
144
+ /**
145
+ * Time-to-live in milliseconds before expiration.
146
+ * After this time, cached entries are considered stale and will be refetched.
147
+ */
148
+ ttlMs: number;
149
+ /**
150
+ * Whether this type is written to localStorage when {@link CacheConfig.persistent} is on.
151
+ * `false` keeps it in memory only: it is fetched again after a reload, but takes none of the
152
+ * localStorage the host page shares with the components.
153
+ * @defaultValue true
154
+ */
155
+ persist?: boolean;
156
+ }
157
+
158
+ /**
159
+ * Clears all SDK cache entries from localStorage.
160
+ *
161
+ * @description Removes all cached data stored by the SDK. This forces the SDK
162
+ * to fetch fresh data on the next request. Safe to call even if localStorage
163
+ * is unavailable (fails silently).
164
+ *
165
+ * @example Clear cache on user logout
166
+ * ```typescript
167
+ * import { clearAllCacheStorage } from '@mapvx/web-kit';
168
+ *
169
+ * function handleLogout() {
170
+ * clearAllCacheStorage();
171
+ * // ... other cleanup
172
+ * }
173
+ * ```
174
+ *
175
+ * @example Add a "clear cache" button for debugging
176
+ * ```typescript
177
+ * document.getElementById('clearCache')?.addEventListener('click', () => {
178
+ * clearAllCacheStorage();
179
+ * alert('Cache cleared. Refresh the page to see fresh data.');
180
+ * });
181
+ * ```
182
+ */
183
+ export declare function clearAllCacheStorage(): void;
184
+
185
+ /**
186
+ * Manages all application contexts and provides typed update methods.
187
+ * Acts as a single source of truth for state management across components.
188
+ */
189
+ declare class ContextManager {
190
+ private sdkProvider;
191
+ private placeProvider;
192
+ private routeProvider;
193
+ private uiProvider;
194
+ /**
195
+ * Creates a new ContextManager attached to the given host element.
196
+ * Sets up all context providers with their initial values.
197
+ *
198
+ * @param host - The host element that will provide the contexts
199
+ */
200
+ constructor(host: ReactiveElement);
201
+ /**
202
+ * Updates the SDK context with partial values.
203
+ * @param updates - Partial SDK context to merge
204
+ */
205
+ updateSDK(updates: Partial<SDKContextType>): void;
206
+ /**
207
+ * Gets the current SDK context (read-only).
208
+ */
209
+ get sdk(): SDKContextType;
210
+ /**
211
+ * Updates the place context with partial values.
212
+ * @param updates - Partial place context to merge
213
+ */
214
+ updatePlace(updates: Partial<PlaceContextType>): void;
215
+ /**
216
+ * Gets the current place context (read-only).
217
+ */
218
+ get place(): PlaceContextType;
219
+ /**
220
+ * Updates the route context with partial values.
221
+ * @param updates - Partial route context to merge
222
+ */
223
+ updateRoute(updates: Partial<RouteContextType>): void;
224
+ /**
225
+ * Gets the current route context (read-only).
226
+ */
227
+ get route(): RouteContextType;
228
+ /**
229
+ * Updates the UI context with partial values.
230
+ * @param updates - Partial UI context to merge
231
+ */
232
+ updateUI(updates: Partial<UIContextType>): void;
233
+ /**
234
+ * Gets the current UI context (read-only).
235
+ */
236
+ get ui(): UIContextType;
237
+ /**
238
+ * Resets all contexts to their initial states.
239
+ * Useful when navigating away or clearing the current session.
240
+ */
241
+ reset(): void;
242
+ /**
243
+ * Resets navigation-related state while preserving SDK and parent place.
244
+ * Useful when selecting a new destination.
245
+ */
246
+ resetNavigation(): void;
247
+ /**
248
+ * Gets a snapshot of all current context values.
249
+ * Useful for debugging or logging.
250
+ */
251
+ getSnapshot(): {
252
+ sdk: SDKContextType;
253
+ place: PlaceContextType;
254
+ route: RouteContextType;
255
+ ui: UIContextType;
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Default cache configuration (uses WEB preset).
261
+ *
262
+ * @description The default configuration applied when no `cacheConfig` is specified.
263
+ * Uses {@link WEB_CACHE_CONFIG} for broad compatibility with web deployments.
264
+ *
265
+ * @see {@link WEB_CACHE_CONFIG} for detailed settings
266
+ * @see {@link TOTEM_CACHE_CONFIG} for kiosk deployments
267
+ */
268
+ export declare const DEFAULT_CACHE_CONFIG: CacheConfig;
269
+
270
+ export declare const DEFAULT_VECTOR_TILES_BASE_URL = "https://tiles.mapvx.com/tiles";
271
+
272
+ /**
273
+ * The floor a route endpoint is on, for a place that exists on several floors (an elevator, a
274
+ * staircase, an entrance shared by two levels).
275
+ *
276
+ * Without it the route starts, or ends, on the first floor the place is listed on: an elevator
277
+ * picked as the origin of someone standing on level 3 would send them from the basement. Both
278
+ * fields are optional; `floorId` wins over `level` when both are set, as in the SDK's `IdLocation`.
279
+ */
280
+ declare interface EndpointFloor {
281
+ /** Id of the floor (`InnerFloor.key`) the endpoint is on. Takes precedence over {@link level}. */
282
+ floorId?: string;
283
+ /**
284
+ * Level number of that floor (`InnerFloor.level`). A level is not the floor's name: a venue can
285
+ * call level `-2` "Nivel -1", so prefer {@link floorId} when it is known.
286
+ */
287
+ level?: number;
288
+ }
289
+
290
+ /**
291
+ * Where a floor selector is anchored inside its component: an edge, and where along that edge.
292
+ * `map-view-with-modal` and `route-view-totems` take the same values through
293
+ * `floor-selector-position`.
294
+ */
295
+ declare const FLOOR_SELECTOR_POSITIONS: readonly ["top-left", "top-center", "top-right", "center-left", "center-right", "bottom-left", "bottom-center", "bottom-right"];
296
+
297
+ /**
298
+ * Controller for managing floor-related operations.
299
+ */
300
+ declare class FloorController implements ReactiveController {
301
+ private host;
302
+ private contextManager;
303
+ constructor(host: ReactiveControllerHost, contextManager: ContextManager);
304
+ hostConnected(): void;
305
+ hostDisconnected(): void;
306
+ /**
307
+ * Sets the current floor by ID.
308
+ * Does nothing if the floor is already selected or doesn't exist.
309
+ *
310
+ * @param floorId - The floor key to select
311
+ * @returns true if floor was changed, false otherwise
312
+ */
313
+ setFloor(floorId: string): boolean;
314
+ /**
315
+ * Sets the current floor directly.
316
+ *
317
+ * @param floor - The floor object to set as current
318
+ */
319
+ setFloorDirect(floor: InnerFloor): void;
320
+ /**
321
+ * Gets the currently selected floor.
322
+ */
323
+ getCurrentFloor(): InnerFloor | undefined;
324
+ /**
325
+ * Gets all available floors in the parent place.
326
+ */
327
+ getAllFloors(): InnerFloor[];
328
+ /**
329
+ * Gets floors that are part of the current route.
330
+ * Returns all floors if no route is active.
331
+ */
332
+ getEnabledFloors(): InnerFloor[];
333
+ /**
334
+ * Checks if a floor is enabled (part of the current route or no route active).
335
+ *
336
+ * @param floorId - The floor key to check
337
+ */
338
+ isFloorEnabled(floorId: string): boolean;
339
+ /**
340
+ * Gets the index of the current floor in the floors list.
341
+ * Returns -1 if no floor is selected.
342
+ */
343
+ getCurrentFloorIndex(): number;
344
+ /**
345
+ * Moves to the next floor in the list.
346
+ * Returns false if already on the last floor.
347
+ */
348
+ nextFloor(): boolean;
349
+ /**
350
+ * Moves to the previous floor in the list.
351
+ * Returns false if already on the first floor.
352
+ */
353
+ previousFloor(): boolean;
354
+ /**
355
+ * Gets the floor count.
356
+ */
357
+ getFloorCount(): number;
358
+ /**
359
+ * Checks if the current floor is the first floor.
360
+ */
361
+ isFirstFloor(): boolean;
362
+ /**
363
+ * Checks if the current floor is the last floor.
364
+ */
365
+ isLastFloor(): boolean;
366
+ }
367
+
368
+ /** One of {@link FLOOR_SELECTOR_POSITIONS}. */
369
+ export declare type FloorSelectorPosition = (typeof FLOOR_SELECTOR_POSITIONS)[number];
370
+
371
+ /**
372
+ * @description Publishes the rendered width and height of `<floor-selector>` on its container as
373
+ * {@link FLOOR_SELECTOR_INLINE_SIZE_PROPERTY} and {@link FLOOR_SELECTOR_BLOCK_SIZE_PROPERTY}, so the
374
+ * siblings laid out around the bar can keep clear of it.
375
+ *
376
+ * The bar is as wide as the venue's longest floor name, not its CSS `min-width`: the demo venue's
377
+ * vertical bar is 115px against a min-width of 87px. `route-options` reserves this width for the
378
+ * compact card, so the card never slides under the bar in a narrow embed (MFE-492). Custom
379
+ * properties inherit across shadow roots, so setting it on the shared container is enough.
380
+ *
381
+ * Both are the selector's border box, which includes the transparent margin it keeps around the
382
+ * bar for its shadow. Only the one across the bar's edge is published: the width of a vertical bar,
383
+ * the height of a horizontal one. The other is removed, since it measures the layout rather than
384
+ * the bar (a vertical bar's host spans the full height): left in place, a bar moved to another edge
385
+ * would be laid out against it until the next report, rather than against the stylesheets'
386
+ * fallbacks. `floor-selector.css` lays a vertical bar's host out as a column, which is how the
387
+ * orientation is told apart. Tracked with a `ResizeObserver`, so they follow floor names, the layout
388
+ * switch at the container breakpoint, a new `floor-selector-position` and the late definition of
389
+ * the lazily loaded element. A report of 0px (the element before it is defined and laid out) is not
390
+ * published: the stylesheets' fallbacks stand in until the first real size. Neither is a report
391
+ * from a bar without floors, which is a placeholder rather than a bar
392
+ * ({@link FLOOR_SELECTOR_HAS_FLOORS_ATTRIBUTE}).
393
+ *
394
+ * @example
395
+ * ```ts
396
+ * // A class field next to the host's other controllers. It is never read, so `protected` rather
397
+ * // than `private`: `noUnusedLocals` rejects a private field that is only held (TS6133).
398
+ * protected readonly floorSelectorSize = new FloorSelectorSizeController(this, '.route-container')
399
+ * ```
400
+ */
401
+ declare class FloorSelectorSizeController implements ReactiveController {
402
+ private observer;
403
+ private readonly host;
404
+ private readonly containerSelector;
405
+ /**
406
+ * @param host Component that renders `<floor-selector>` in its shadow root.
407
+ * @param containerSelector Selector, in the same shadow root, of the element that receives the
408
+ * custom property: the common ancestor of the bar and the elements that keep clear of it.
409
+ */
410
+ constructor(host: ReactiveControllerHost & HTMLElement, containerSelector: string);
411
+ /** Resumes observing when an already rendered host is attached again. */
412
+ hostConnected(): void;
413
+ /** Starts observing once the first render has put the selector in the shadow root. */
414
+ hostUpdated(): void;
415
+ hostDisconnected(): void;
416
+ private observe;
417
+ }
418
+
419
+ export declare class MapViewWithModal extends LitElement {
420
+ static styles: CSSResult[];
421
+ apiKey: string;
422
+ parentPlaceId: string;
423
+ locale: string;
424
+ /**
425
+ * Enables the experimental 3D scene on the underlying map (forwarded to `<custom-map>`).
426
+ *
427
+ * **Off by default**, unlike `<route-view-totems>`. This view is the one embedded in public web
428
+ * and mobile pages, where the extra WebGL cost is rarely wanted and the 3D overlay has no label
429
+ * collision detection, so 3D is something the page opts into rather than inherits.
430
+ *
431
+ * Turning it on is still not sufficient: the parent place must also be in `scene-3d-place-ids`, and
432
+ * the API key's style must publish `fill-extrusion` layers.
433
+ */
434
+ enable3D: boolean;
435
+ /**
436
+ * Parent places the 3D scene is allowed on, as a comma-separated list of ids (forwarded to
437
+ * `<custom-map>`). Empty (the default) keeps `<custom-map>`'s own validated default set.
438
+ */
439
+ scene3dPlaceIds: string[];
440
+ /**
441
+ * Destination popup style (forwarded to `<custom-map>`): `full` shows logo + name + category,
442
+ * `compact` shows a small icon-only bubble. Defaults to `compact`; pass `full` to opt back in.
443
+ */
444
+ markerVariant: string;
445
+ /** The one place shown on the map, as a destination marker (no route, no origin). */
446
+ placeId: string;
447
+ /** Institution identifier forwarded to MapVX API as the `X-MapVx-Institution-Id` request header. */
448
+ institutionId: string;
449
+ /** Human-readable institution name forwarded to MapVX API as the `X-MapVx-Institution-Name` request header. */
450
+ institutionName: string;
451
+ /** Forwarded to `<custom-map>` and reflected on this host too, for its own compact-mode CSS. */
452
+ compactMode: boolean;
453
+ /** `'small' | 'normal' | 'large'`. Forwarded to `<custom-map>` and reflected on this host too. */
454
+ zoomButtonSize: string;
455
+ /** Maximum zoom cap used when fitting markers in the map-with-modal view. */
456
+ fitMaxZoom: number;
457
+ /** Maximum zoom cap used when focusing a single point in the map-with-modal view. */
458
+ singlePointMaxZoom: number;
459
+ /** Maximum zoom cap used when fitting route geometry in the map-with-modal view. */
460
+ routeFitMaxZoom: number;
461
+ /** Base camera padding for the top edge in the map-with-modal view. */
462
+ cameraPaddingTop: number;
463
+ /** Base camera padding for the right edge in the map-with-modal view. */
464
+ cameraPaddingRight: number;
465
+ /** Base camera padding for the bottom edge in the map-with-modal view. */
466
+ cameraPaddingBottom: number;
467
+ /** Base camera padding for the left edge in the map-with-modal view. */
468
+ cameraPaddingLeft: number;
469
+ /**
470
+ * Overlay padding strategy used by the map-with-modal view: `none`, `auto` or `left-panel-stack`.
471
+ * `free-space` (MFE-523) is for `<route-view-totems>` only: this view does not measure the compact
472
+ * floor selector it renders.
473
+ */
474
+ overlayPaddingMode: string;
475
+ /**
476
+ * Cache configuration for SDK data. Defaults to {@link WEB_CACHE_CONFIG}, the preset built for this
477
+ * component's web/mobile deployment. What is set here is merged **over that preset**, so a partial
478
+ * override changes only the entries it names.
479
+ */
480
+ cacheConfig: CacheConfig | undefined;
481
+ /** {@link cacheConfig} resolved against the web preset it defaults to. */
482
+ private get _effectiveCacheConfig();
483
+ /**
484
+ * Whether the compact floor selector is rendered. **On by default**, so the attribute value is
485
+ * what turns it off: `show-floor-selector="false"` (see {@link defaultTrueBooleanConverter}). The
486
+ * lowercase spelling `showfloorselector` is still accepted as a legacy alias.
487
+ */
488
+ showFloorSelector: boolean;
489
+ /**
490
+ * Corner or edge the floor selector is anchored to, trimmed and lowercased first. The lowercase
491
+ * `floorselectorposition` is still accepted as a legacy alias.
492
+ */
493
+ floorSelectorPosition: string;
494
+ /**
495
+ * Renders the floor selector but blocks floor changes. Off by default; present disables, absent or
496
+ * `floor-selector-disabled="false"` enables (see {@link defaultFalseBooleanConverter}). The
497
+ * lowercase `floorselectordisabled` is still accepted as a legacy alias.
498
+ */
499
+ floorSelectorDisabled: boolean;
500
+ /**
501
+ * Hides the built-in loading indicator so the host can show its own. Reads the attribute's value
502
+ * rather than its presence (see {@link defaultFalseBooleanConverter}), so `hide-loading="false"`
503
+ * keeps the indicator.
504
+ */
505
+ hideLoading: boolean;
506
+ static get observedAttributes(): string[];
507
+ attributeChangedCallback(name: string, oldValue: string | null, value: string | null): void;
508
+ /* Excluded from this release type: contextManager */
509
+ /* Excluded from this release type: placeController */
510
+ /* Excluded from this release type: routeController */
511
+ /* Excluded from this release type: floorController */
512
+ constructor();
513
+ /** The inner `custom-map`. Always rendered (no lazy loading yet; see Task 11's own scope). */
514
+ private _customMap;
515
+ /** The inner `compact-floor-selector`, or `null` while {@link showFloorSelector} is off. */
516
+ private _compactFloorSelector;
517
+ /** Context forwarded to MapVX API as `X-MapVx-*` and `mvx-product` request headers. */
518
+ private mapVxRequestContext;
519
+ private readonly analyticsController;
520
+ /**
521
+ * The tiles service worker, run exactly as the reference's own `_initTileServiceWorker()`/
522
+ * `_syncTilePrefetch()` do: registered and asked for the initial tile prefetch from
523
+ * `firstUpdated()`, asked again when `apiKey`/`parentPlaceId` change, the periodic refresh
524
+ * (production builds only) stopped on disconnect. See {@link TileServiceWorkerController}.
525
+ */
526
+ private readonly tileServiceWorker;
527
+ firstUpdated(): void;
528
+ /** Same shape as the reference's own `baseParams()`: no route, so no destination/origin fields. */
529
+ private baseParams;
530
+ private _mapReadyHandler;
531
+ private _cameraInitializedHandler;
532
+ /**
533
+ * The floor id this handler last reported `floor_change` analytics for — this element's own
534
+ * dedupe, independent of `FloorController.setFloor()`'s return value (review round 1, finding 1).
535
+ *
536
+ * An earlier version gated the analytics call on `setFloor()`'s own return (`true` only when it
537
+ * actually changed `uiContext.currentFloor`), reasoning that was a more reliable dedupe than a
538
+ * locally-tracked field. That reasoning held for `<custom-map>`'s own `floorChange` (it never
539
+ * touches `FloorController` itself before dispatching), but broke for
540
+ * `<compact-floor-selector>`'s: `BaseFloorSelector.selectFloor()` (Task 3) already calls
541
+ * `floorController.setFloor(floorKey)` ITSELF before dispatching the event, so by the time this
542
+ * handler ran, the change had already been applied and `setFloor()` correctly (but unhelpfully,
543
+ * for that gate) returned `false` for every single selector click — analytics never fired at all.
544
+ * Verified with a real click on `.floor-option` (not a mocked `setFloor`) in this file's own test
545
+ * suite. Tracking the last-notified id here, instead of trusting the controller's own return value,
546
+ * works the same for both event sources regardless of which of them already consumed the change.
547
+ */
548
+ private _lastNotifiedFloorId;
549
+ /**
550
+ * Turns `<custom-map>`'s/`<compact-floor-selector>`'s `floorChange` event into
551
+ * `FloorController.setFloor()`, closing the loop for a floor change that originated on the map SDK
552
+ * side rather than through the controller (see Task 9's identical wiring and its own doc comment).
553
+ * Safe to call for either source: idempotent on an already-applied floor.
554
+ */
555
+ private _floorChangeHandler;
556
+ updated(changedProperties: PropertyValues): void;
557
+ /** The `placeId` last passed to {@link PlaceController.setOriginAndDestination}, or `undefined`. */
558
+ private _placeIdRequestedFor;
559
+ /**
560
+ * Loads {@link placeId} through `PlaceController` once an SDK is actually available for it. No
561
+ * origin and no route: the single place is loaded as the "destination" so `PlaceController`
562
+ * marks and frames it the same way it would a route's destination.
563
+ *
564
+ * Dedupes on the value it last actually requested, independent of whether `placeId` happened to
565
+ * be in `changedProperties` for the update pass this runs in — see `updated()`'s own call site for
566
+ * why that matters (review round 1, finding 2). Checking the SDK's own readiness itself, rather
567
+ * than only relying on `PlaceController.setOriginAndDestination()`'s internal no-op when the SDK
568
+ * isn't ready yet, matters here specifically: without it, a call made before the SDK exists would
569
+ * still mark `placeId` as "already requested" and this method would never retry it once the SDK
570
+ * actually becomes available.
571
+ */
572
+ private maybeLoadPlace;
573
+ private getFloorSelectorPositionStyles;
574
+ render(): TemplateResult<1>;
575
+ /**
576
+ * Destroys the map and builds a fresh one, keeping venue, place and markers. Not needed on
577
+ * unmount: the map (and its WebGL context) is released automatically when the element leaves the
578
+ * page. A no-op until `<custom-map>` has built one.
579
+ * @example
580
+ * ```ts
581
+ * document.querySelector('map-view-with-modal')?.reloadMap();
582
+ * ```
583
+ */
584
+ reloadMap(): void;
585
+ }
586
+
587
+ declare interface MarkerContext {
588
+ style: MarkerStyle;
589
+ id: string;
590
+ data: MVXPlace | PlacePopupData;
591
+ /**
592
+ * Floor the marker is drawn on, when it is not the place's first floor: a route endpoint on a
593
+ * place that spans several floors (an elevator) is drawn on the floor the route starts or ends.
594
+ */
595
+ floorId?: string;
596
+ }
597
+
598
+ /**
599
+ * Marker visual style.
600
+ *
601
+ * Written as a frozen object + derived union rather than a TS `enum`: this project's tsconfig sets
602
+ * `erasableSyntaxOnly`, which disallows `enum` declarations because they emit non-erasable runtime
603
+ * code. Call sites are unchanged from the reference — `MarkerStyle.youAreHere` still works, and the
604
+ * type `MarkerStyle` still names the union of valid values.
605
+ */
606
+ declare const MarkerStyle: {
607
+ readonly youAreHere: "youAreHere";
608
+ readonly placePopup: "placePopup";
609
+ readonly pin: "pin";
610
+ readonly default: "default";
611
+ };
612
+
613
+ declare type MarkerStyle = (typeof MarkerStyle)[keyof typeof MarkerStyle];
614
+
615
+ /**
616
+ * Merges a partial cache configuration with a base configuration.
617
+ *
618
+ * @description Merges per cache type: the types an override names replace the base's entries
619
+ * whole, and the rest keep the base's. This is the recommended way to customize cache behavior.
620
+ *
621
+ * Because an entry is replaced whole, `persist` included, overriding `subPlaces` over
622
+ * {@link WEB_CACHE_CONFIG} without `persist: false` persists them. The SDK controller relies on
623
+ * it: it merges the totem preset over the web default, and the totem's `subPlaces` must not pick
624
+ * up the web's `persist: false`.
625
+ *
626
+ * @param base - The base configuration to start from (e.g., TOTEM_CACHE_CONFIG)
627
+ * @param overrides - Partial configuration with values to override
628
+ * @returns Complete cache configuration with overrides applied
629
+ *
630
+ * @example Override storage limit only
631
+ * ```typescript
632
+ * const config = mergeCacheConfig(WEB_CACHE_CONFIG, {
633
+ * maxStorageBytes: 8 * 1024 * 1024, // 8MB instead of 5MB
634
+ * });
635
+ * ```
636
+ *
637
+ * @example Override specific cache type
638
+ * ```typescript
639
+ * const config = mergeCacheConfig(TOTEM_CACHE_CONFIG, {
640
+ * configs: {
641
+ * routes: { maxItems: 200, ttlMs: 30 * 60 * 1000 } // Longer route cache
642
+ * }
643
+ * });
644
+ * ```
645
+ *
646
+ * @example Multiple overrides
647
+ * ```typescript
648
+ * const config = mergeCacheConfig(WEB_CACHE_CONFIG, {
649
+ * persistent: false, // Disable persistence
650
+ * maxStorageBytes: 2 * 1024 * 1024, // Reduce to 2MB
651
+ * configs: {
652
+ * places: { maxItems: 50, ttlMs: 10 * 60 * 1000 }, // Smaller, shorter
653
+ * routes: { maxItems: 25, ttlMs: 2 * 60 * 1000 }, // Very short TTL
654
+ * }
655
+ * });
656
+ * ```
657
+ */
658
+ export declare function mergeCacheConfig(base: CacheConfig, overrides?: Partial<CacheConfig>): CacheConfig;
659
+
660
+ /** Name of the event this component dispatches on a map failure. */
661
+ export declare const MVX_ERROR_EVENT = "mvxError";
662
+
663
+ /**
664
+ * Helpers for the MapVX tiles service worker shipped at `/mvx-tiles-sw.js`.
665
+ * Host apps must serve that file at the site root (HTTPS).
666
+ *
667
+ * The worker script itself lives at `src/sw/mvx-tiles-sw.js` and ships at
668
+ * `dist/sw/mvx-tiles-sw.js` via `vite.config.ts`'s `viteStaticCopy` plugin.
669
+ */
670
+ export declare const MVX_TILES_SW_PATH = "/mvx-tiles-sw.js";
671
+
672
+ export declare const MVX_TILES_SW_SCOPE = "/";
673
+
674
+ /** Reasons `<custom-map>` dispatches its `mvxError` event for. Narrower than the reference's
675
+ * `MvxErrorCode`: only the map-rebuild case is reported. web-kit's `PlaceController`/
676
+ * `RouteController` do not produce the reference's place/route loading-failure codes (see
677
+ * `docs/parity-checklist.md`'s "Known gaps"). */
678
+ export declare type MvxErrorCode = 'MAP_CONTEXT_LOST';
679
+
680
+ /** Payload of the `mvxError` event, ported (narrowed) from the reference's `models/mvx-error.ts`. */
681
+ export declare interface MvxErrorDetail {
682
+ code: MvxErrorCode;
683
+ message: string;
684
+ parentPlaceId?: string;
685
+ }
686
+
687
+ /**
688
+ * Detail of the `mvxLoadingChange` event, ported verbatim from the reference's
689
+ * `models/loading-events.ts`.
690
+ */
691
+ export declare interface MvxLoadingChangeDetail {
692
+ /** Whether a loading indicator should be on screen right now. */
693
+ loading: boolean;
694
+ /**
695
+ * What is being waited on:
696
+ * - `places` — resolving the origin and destination.
697
+ * - `route` — generating the route between them.
698
+ * - `camera` — the map is settling on what it has to show: framing the pair or the route it just
699
+ * received, building itself on a cold start, or clearing itself for the next destination. The
700
+ * catch-all for "the data is in, the map is not ready to be looked at yet".
701
+ * - `idle` — nothing; emitted with `loading: false` when the load ends.
702
+ */
703
+ phase: 'places' | 'route' | 'camera' | 'idle';
704
+ }
705
+
706
+ export declare interface MvxTilePrefetchOptions {
707
+ apiKey: string;
708
+ placeId: string;
709
+ tilesBaseUrl?: string;
710
+ }
711
+
712
+ /**
713
+ * The floors asked for the two ends of a route. Same shape as the reference's `PairFloors`
714
+ * (`sdk-controller.ts`): `undefined` means "not given", `{}` means "given as no floor".
715
+ */
716
+ declare interface PairFloors {
717
+ originFloor?: EndpointFloor;
718
+ destinationFloor?: EndpointFloor;
719
+ }
720
+
721
+ /**
722
+ * Context type for place-related state.
723
+ */
724
+ declare interface PlaceContextType {
725
+ /** Parent place containing floors and configuration */
726
+ parentPlace?: MVXPlace;
727
+ /** Origin place for navigation */
728
+ origin?: MVXPlace;
729
+ /** Destination place for navigation */
730
+ destination?: MVXPlace;
731
+ /** Origin place ID */
732
+ originId?: string;
733
+ /** Destination place ID */
734
+ destinationId?: string;
735
+ /** General configuration for the parent place */
736
+ generalConfig?: Configuration;
737
+ /**
738
+ * Floor of the origin, for an origin on several floors (an elevator). See {@link EndpointFloor}.
739
+ * Matches the reference's (legacy, flat) `sdkContext` field of the same name. Written by
740
+ * `PlaceController.setOriginAndDestination` with the pair it loads; read by `route-options` (the
741
+ * floor shown next to the origin row) and by `RouteController` (the floor the route starts on).
742
+ */
743
+ originFloor?: EndpointFloor;
744
+ /** Floor of the destination, for a destination on several floors. Same notes as {@link originFloor}. */
745
+ destinationFloor?: EndpointFloor;
746
+ /**
747
+ * Whether the origin/destination places are currently being fetched — the `places` phase of
748
+ * `<custom-map>`'s loading overlay and `mvxLoadingChange`. Matches the reference's (legacy, flat)
749
+ * `sdkContext.isLoading`. Raised by `PlaceController.setOriginAndDestination` before the fetch and
750
+ * cleared once it settles (success or failure); not raised by the parent-place load, as in the
751
+ * reference.
752
+ */
753
+ isLoading?: boolean;
754
+ }
755
+
756
+ /**
757
+ * Controller for managing place-related operations.
758
+ */
759
+ declare class PlaceController implements ReactiveController {
760
+ private host;
761
+ private contextManager;
762
+ private connected;
763
+ /**
764
+ * Request counter, the reference's `placesRequest`. Every pair load bumps it and keeps the value it
765
+ * started with; its answer is written only if the counter has not moved since. Comparing ids is not
766
+ * enough: the same pair can be requested twice, and an older request for another pair can land
767
+ * after a newer one. {@link reset} bumps it too, so a load still in flight when the kiosk is reset
768
+ * for the next visitor never writes its places back.
769
+ */
770
+ private placesRequest;
771
+ /**
772
+ * The venue load in flight, if any. A pair whose floor is asked for by level waits for it before
773
+ * publishing: only the venue's floors say which floor a level is (the reference's `venueLoad`).
774
+ */
775
+ private venueLoad;
776
+ constructor(host: ReactiveControllerHost, contextManager: ContextManager);
777
+ hostConnected(): void;
778
+ hostDisconnected(): void;
779
+ /**
780
+ * Loads the parent place and its configuration.
781
+ *
782
+ * Does not raise `placeContext.isLoading`: the reference's venue load (`prewarm`/`initializeSDK`)
783
+ * does not either — that flag is the `places` loading phase of an origin/destination load only.
784
+ *
785
+ * The venue can land after the pair on screen (both start in the same update on a cold start).
786
+ * When it does, the pair's floor is shown rather than the venue's first floor, and its markers and
787
+ * enabled floors are rebuilt — only the venue's floors can resolve a floor asked for by level. The
788
+ * reference's `publishVenue`.
789
+ *
790
+ * @param parentPlaceId - The ID of the parent place to load
791
+ * @returns The loaded parent place or undefined on error
792
+ */
793
+ loadParentPlace(parentPlaceId: string): Promise<MVXPlace | undefined>;
794
+ /** The body of {@link loadParentPlace}, split out so a pair load can wait on it. */
795
+ private fetchParentPlace;
796
+ /**
797
+ * Sets the origin and destination places.
798
+ * Fetches place details and updates markers.
799
+ *
800
+ * Raises `placeContext.isLoading` before the fetch and clears it once the fetch settles, on
801
+ * success and on failure alike — the `places` phase of `<custom-map>`'s loading overlay and
802
+ * `mvxLoadingChange`. A load superseded by a newer one (or by {@link reset}) writes nothing and
803
+ * leaves the flag to the load that superseded it.
804
+ *
805
+ * @param originId - The ID of the origin place
806
+ * @param destinationId - The ID of the destination place
807
+ * @param floors - Floors asked for each end (`origin-floor-id`/`origin-level` and their destination
808
+ * twins). An end left `undefined` keeps the floor already set when it is the same place, and
809
+ * drops it otherwise — the reference's `floorsFor`; `{}` says "no floor".
810
+ * @returns `true` once this load's places are in context and every requested place resolved;
811
+ * `false` when it was superseded, could not run (disconnected, no SDK), or a place failed to
812
+ * load. A route asked for alongside this load uses it as its gate (see
813
+ * `RouteController.generateRoute`'s `after` option).
814
+ */
815
+ setOriginAndDestination(originId: string, destinationId: string, floors?: PairFloors): Promise<boolean>;
816
+ /**
817
+ * Writes the places a load resolved, with their markers, the floor to show and the floors the
818
+ * selector offers, and ends the `places` phase. The reference's `publishPlaces`.
819
+ */
820
+ private publishPlaces;
821
+ /**
822
+ * The floors of a pair about to load: the ones given, else the ones already set. A floor belongs
823
+ * to the place it was given for: kept for a reload of the same place, never carried over to
824
+ * another place, where it would name a floor that place may not even be on. The reference's
825
+ * `floorsFor`.
826
+ */
827
+ private floorsFor;
828
+ /** The venue's floors: the parent place's, else whatever the floor selector was given. */
829
+ private venueFloors;
830
+ /**
831
+ * Creates markers for origin and destination, each on the floor its end of the route is on
832
+ * ({@link endpointFloorId}: the floor asked for when the place is on it, else its first floor).
833
+ */
834
+ private updateMarkers;
835
+ /**
836
+ * Opens the floor the map shows for the pair: the destination's (the floor asked for it, when the
837
+ * place is on it), else the origin's — {@link shownFloorId}, the same rule the reference's
838
+ * `publishPlaces` selects with. A pair with no resolvable floor keeps the floor already shown.
839
+ */
840
+ private updateCurrentFloor;
841
+ /**
842
+ * Updates enabled floors to the floor each end of the route is on. Left alone while a route is on
843
+ * screen: the route enables every floor it passes through, the richer set (the reference's
844
+ * `routeOwnsFloors`). An empty list means "no endpoint floor", which the floor selector reads as
845
+ * "every floor".
846
+ */
847
+ private updateEnabledFloors;
848
+ /**
849
+ * Gets the current destination place.
850
+ */
851
+ getDestination(): MVXPlace | undefined;
852
+ /**
853
+ * Gets the current origin place.
854
+ */
855
+ getOrigin(): MVXPlace | undefined;
856
+ /**
857
+ * Resets the pair for the next visitor: origin, destination, their ids and floors, the markers,
858
+ * the `places` phase, and the view the last pair left — the camera (so `<qr-modal>`, which shows
859
+ * only once the camera is initialized, hides again) and the floor (back to the venue's first). The
860
+ * place half of the reference's `resetData()`; also drops any load still in flight.
861
+ */
862
+ reset(): void;
863
+ }
864
+
865
+ /**
866
+ * Plain-object marker payload, used when the caller renders a popup marker without a full
867
+ * {@link MVXPlace} (e.g. a destination reconstructed from host attributes). Every field is optional
868
+ * because callers outside this package build these objects by hand.
869
+ */
870
+ declare interface PlacePopupData {
871
+ name?: string;
872
+ category?: string;
873
+ logo?: string;
874
+ position?: LatLng;
875
+ floorId?: string;
876
+ }
877
+
878
+ /**
879
+ * Visual variant of the place popup marker.
880
+ *
881
+ * - `compact`: icon only, in a small bubble anchored above the point. Default, since the place name
882
+ * is usually already visible elsewhere in the UI (e.g. the modal) and the big bubble covers the map.
883
+ * - `full`: logo + name + category, the historical look. Opt-in via `marker-variant="full"`.
884
+ */
885
+ export declare type PopupVariant = 'full' | 'compact';
886
+
887
+ /**
888
+ * Registers the tiles service worker and starts bounded prefetch in one call.
889
+ *
890
+ * @description Pairs registration with the wait and the initial load, so a caller does not have to
891
+ * know that messaging a worker before it is active is dropped silently. Everything is best-effort:
892
+ * a worker that cannot be registered yields a `null` registration, and the prefetch calls then do
893
+ * nothing rather than throwing.
894
+ *
895
+ * The periodic refresh re-reads `options` on every tick, so later changes to `apiKey` and
896
+ * `placeId` are picked up. `import.meta.env.PROD` is resolved when this package is built, not when
897
+ * the host is, so in the published bundles the refresh is scheduled whenever
898
+ * `enablePeriodicRefresh` is set — a development build of the host does not turn it off.
899
+ * @param options - Prefetch credentials, plus the worker's path and scope and whether to keep
900
+ * refreshing
901
+ * @returns The registration, and a function that stops the periodic refresh (a no-op when none was
902
+ * scheduled)
903
+ * @example
904
+ * const { registration, stopPeriodicRefresh } = await registerAndTriggerTilePrefetch({
905
+ * apiKey: 'key',
906
+ * placeId: 'place',
907
+ * enablePeriodicRefresh: true,
908
+ * });
909
+ * // call stopPeriodicRefresh() when tearing the view down
910
+ */
911
+ export declare function registerAndTriggerTilePrefetch(options: MvxTilePrefetchOptions & {
912
+ swPath?: string;
913
+ swScope?: string;
914
+ enablePeriodicRefresh?: boolean;
915
+ }): Promise<{
916
+ registration: ServiceWorkerRegistration | null;
917
+ stopPeriodicRefresh: () => void;
918
+ }>;
919
+
920
+ /**
921
+ * Registers the MapVX tiles service worker.
922
+ *
923
+ * @description Best-effort: returns `null` instead of throwing when the browser has no service
924
+ * worker support, when there is no `navigator` at all (SSR), or when `register` rejects because
925
+ * the host does not serve the file, serves it with the wrong MIME type, or blocks it by CSP.
926
+ * @param swPath - Path the worker is served from
927
+ * @param scope - Scope the worker controls
928
+ * @returns The registration, or `null` when the worker could not be registered
929
+ * @example
930
+ * const registration = await registerMvxTileServiceWorker();
931
+ * if (registration) {
932
+ * await waitForServiceWorkerReady(registration);
933
+ * }
934
+ */
935
+ export declare function registerMvxTileServiceWorker(swPath?: string, scope?: string): Promise<ServiceWorkerRegistration | null>;
936
+
937
+ /**
938
+ * Context type for route-related state.
939
+ */
940
+ declare interface RouteContextType {
941
+ /** Current route being displayed/animated */
942
+ route?: MVXRoute;
943
+ /** Whether to prefer accessible routes */
944
+ accessibleRoute: boolean;
945
+ /** Whether route animation is currently playing */
946
+ isAnimating: boolean;
947
+ /** Whether a route is currently being loaded. `RouteController` keeps it in step with {@link loadingRoute}. */
948
+ isLoading: boolean;
949
+ /** Floors that are part of the current route */
950
+ enabledFloors: InnerFloor[];
951
+ /**
952
+ * Whether a route is currently being generated — the `route` phase of `<custom-map>`'s loading
953
+ * overlay and `mvxLoadingChange`, and what `route-options` reads to keep its panel busy. Matches
954
+ * the reference's (legacy, flat) `sdkContext` field of the same name (the places' own loading flag
955
+ * is `placeContext.isLoading`). Raised by `RouteController` for the whole time a route is being
956
+ * asked for — from the moment it is requested alongside a pair's places — and cleared once the
957
+ * request settles, or is dropped by `clearRoute()`.
958
+ */
959
+ loadingRoute?: boolean;
960
+ /**
961
+ * Error message from the last failed route generation attempt, surfaced by `route-options`'s
962
+ * error modal. Matches the reference's (legacy, flat) `sdkContext` field of the same name. No
963
+ * web-kit controller produces it from a real failure yet (see `docs/parity-checklist.md`'s "Known
964
+ * gaps"); `RouteController.reset()` and the `dismissRouteError` handler clear it.
965
+ */
966
+ routeError?: string;
967
+ /** Whether {@link routeError} was caused by a network failure (a different icon is shown for it). */
968
+ isNetworkError?: boolean;
969
+ /** Set when the last route request failed; stays set after the error modal is dismissed. */
970
+ routeFailed?: boolean;
971
+ /** Set when origin or destination failed to load; stays set after the error modal is dismissed. */
972
+ placesFailed?: boolean;
973
+ }
974
+
975
+ /**
976
+ * Controller for managing route-related operations.
977
+ */
978
+ declare class RouteController implements ReactiveController {
979
+ private host;
980
+ private contextManager;
981
+ private connected;
982
+ /**
983
+ * Request counter, the reference's `routeRequest`. Every route request bumps it and keeps the value
984
+ * it started with; its answer is written only if the counter has not moved since — last request
985
+ * wins (a second switch toggle, a new pair). {@link clearRoute} bumps it too: a route dropped
986
+ * because the pair was replaced or the kiosk was reset must not come back when its answer lands.
987
+ */
988
+ private routeRequest;
989
+ constructor(host: ReactiveControllerHost, contextManager: ContextManager);
990
+ hostConnected(): void;
991
+ hostDisconnected(): void;
992
+ /**
993
+ * Loads a route between two places.
994
+ *
995
+ * Raises `routeContext.loadingRoute` (and `isLoading`, kept in step with it) before the request
996
+ * and clears it once the request settles, on every path this request still owns. A request
997
+ * superseded by a newer one, or by {@link clearRoute}, writes nothing.
998
+ *
999
+ * @param originId - The origin place ID
1000
+ * @param destinationId - The destination place ID
1001
+ * @param preferAccessible - Whether to prefer accessible routes
1002
+ * @param floors - Floors of each end; defaults to the ones set for the pair on screen
1003
+ * (`placeContext.originFloor`/`destinationFloor`)
1004
+ * @returns The loaded route or undefined on error
1005
+ */
1006
+ loadRoute(originId: string, destinationId: string, preferAccessible?: boolean, floors?: PairFloors): Promise<MVXRoute | undefined>;
1007
+ /** The body of a route request once its token is taken and the `route` phase is raised. */
1008
+ private requestRoute;
1009
+ /** Raises or ends the `route` phase. `isLoading` is kept in step with `loadingRoute`. */
1010
+ private setLoading;
1011
+ /** The floors set for the pair on screen. */
1012
+ private pairFloors;
1013
+ /** The location of one end of the route, with its floor resolved against what is loaded. */
1014
+ private endpointLocation;
1015
+ /**
1016
+ * Whether the pair a route was asked for is still the one on screen. A context with no pair at
1017
+ * all (a route asked for directly, outside any pair load) accepts any route.
1018
+ */
1019
+ private isPairOnScreen;
1020
+ /**
1021
+ * Extracts unique floors from a route's steps.
1022
+ */
1023
+ private extractFloorsFromRoute;
1024
+ /**
1025
+ * Generates a route using current origin and destination.
1026
+ *
1027
+ * @param options.after - The pair load this route follows (`PlaceController
1028
+ * .setOriginAndDestination`'s promise). The `route` phase is raised at once, so the loading
1029
+ * overlay goes straight from `places` to `route` without ever reading as idle in between; the
1030
+ * request itself goes out only once that load resolves `true`, reading the pair, its floors and
1031
+ * the route type from context then — so a level is sent against the loaded place, and a switch
1032
+ * toggled while the places load is honoured. Resolving `false` (the places failed, or a newer
1033
+ * load superseded it) asks for nothing, the reference's `publishAfter` gate.
1034
+ */
1035
+ generateRoute(options?: {
1036
+ after?: Promise<boolean>;
1037
+ }): Promise<MVXRoute | undefined>;
1038
+ /**
1039
+ * Sets the accessible route preference and reloads route if one exists.
1040
+ *
1041
+ * @param accessible - Whether to prefer accessible routes
1042
+ */
1043
+ setAccessibleRoute(accessible: boolean): Promise<void>;
1044
+ /**
1045
+ * Starts the route animation.
1046
+ */
1047
+ startAnimation(): void;
1048
+ /**
1049
+ * Stops the route animation.
1050
+ */
1051
+ stopAnimation(): void;
1052
+ /**
1053
+ * Repeats the route animation from the beginning.
1054
+ */
1055
+ repeatAnimation(): void;
1056
+ /**
1057
+ * Clears the current route.
1058
+ *
1059
+ * By default also drops any request still in flight (its answer would otherwise land on whatever
1060
+ * pair replaced it) and ends the `route` phase — what the reference's `SDKController` does on every
1061
+ * pair replacement and on `resetData()`.
1062
+ *
1063
+ * @param options.keepInFlight - Only take the route off the screen, leaving a request in flight
1064
+ * (and its `route` phase) alone. For `<custom-map>`'s passive destination-change detection: by
1065
+ * the time it notices the new destination, whatever replaced the pair has already superseded any
1066
+ * stale request, and the one in flight is the new pair's own.
1067
+ */
1068
+ clearRoute(options?: {
1069
+ keepInFlight?: boolean;
1070
+ }): void;
1071
+ /**
1072
+ * Resets everything route-related for the next visitor: the route and any request in flight
1073
+ * ({@link clearRoute}), the floors the route enabled, the last request's error state, and the route
1074
+ * type — back to `defaultAccessibleRoute`, what the host configured (`accessible-route`), not to
1075
+ * whatever the last visitor's switch left. The route half of the reference's `resetData()`.
1076
+ *
1077
+ * @param defaultAccessibleRoute - The host's configured route type
1078
+ */
1079
+ reset(defaultAccessibleRoute: boolean): void;
1080
+ /**
1081
+ * Gets the current route.
1082
+ */
1083
+ getRoute(): MVXRoute | undefined;
1084
+ /**
1085
+ * Checks if a route is currently loaded.
1086
+ */
1087
+ hasRoute(): boolean;
1088
+ /**
1089
+ * Checks if a route is currently being loaded.
1090
+ */
1091
+ isLoading(): boolean;
1092
+ /**
1093
+ * Checks if a route animation is currently playing.
1094
+ */
1095
+ isAnimating(): boolean;
1096
+ /**
1097
+ * Clears the SDK routes cache.
1098
+ */
1099
+ clearCache(): void;
1100
+ }
1101
+
1102
+ /**
1103
+ * Layout of the route panel rendered by `<route-options>`.
1104
+ *
1105
+ * - `full`: back bar, destination name, floor and distance, origin/destination rows, accessible
1106
+ * route switch, "Repetir ruta" and "Generar ruta". Default.
1107
+ * - `compact`: a single card with the destination name, floor and distance, and the accessible
1108
+ * route switch beside them. No back bar, no origin/destination rows, no "Repetir ruta".
1109
+ */
1110
+ export declare type RoutePanelVariant = 'full' | 'compact';
1111
+
1112
+ export declare class RouteViewTotems extends LitElement {
1113
+ static styles: CSSResult[];
1114
+ apiKey: string;
1115
+ parentPlaceId: string;
1116
+ /**
1117
+ * Enables the experimental 3D scene on the underlying map (forwarded to `<custom-map>`).
1118
+ *
1119
+ * **On by default**, because it is not the only condition: the scene also requires the parent
1120
+ * place to be in `scene-3d-place-ids`, so an integration that says nothing gets 3D on the venues
1121
+ * the scene was built for and plain 2D everywhere else.
1122
+ *
1123
+ * Set `enable-3d="false"` to force 2D on a venue that is in the list.
1124
+ */
1125
+ enable3D: boolean;
1126
+ /**
1127
+ * Parent places the 3D scene is allowed on, as a comma-separated list of ids (forwarded to
1128
+ * `<custom-map>`). Empty (the default) keeps `<custom-map>`'s own validated default set.
1129
+ */
1130
+ scene3dPlaceIds: string[];
1131
+ /**
1132
+ * Destination popup style (forwarded to `<custom-map>`): `full` shows logo + name + category,
1133
+ * `compact` shows a small icon-only bubble. Defaults to `compact`; pass `full` to opt back in.
1134
+ */
1135
+ markerVariant: string;
1136
+ locale: string;
1137
+ originId: string;
1138
+ /** Institution identifier forwarded to MapVX API as the `X-MapVx-Institution-Id` request header. */
1139
+ institutionId: string;
1140
+ /** Human-readable institution name forwarded to MapVX API as the `X-MapVx-Institution-Name` request header. */
1141
+ institutionName: string;
1142
+ /** Maximum zoom cap used when fitting origin and destination in the totem view. */
1143
+ fitMaxZoom: number;
1144
+ /** Maximum zoom cap used when focusing a single point in the totem view. */
1145
+ singlePointMaxZoom: number;
1146
+ /** Maximum zoom cap used when fitting route geometry in the totem view. */
1147
+ routeFitMaxZoom: number;
1148
+ /** Base camera padding for the top edge in the totem view. */
1149
+ cameraPaddingTop: number;
1150
+ /** Base camera padding for the right edge in the totem view. */
1151
+ cameraPaddingRight: number;
1152
+ /** Base camera padding for the bottom edge in the totem view. */
1153
+ cameraPaddingBottom: number;
1154
+ /**
1155
+ * Base camera padding for the left edge in the totem view. The overlays (route panel, QR card,
1156
+ * floor bar, zoom buttons) are measured on top of it inside `<custom-map>`, as `overlay-padding-mode` says.
1157
+ */
1158
+ cameraPaddingLeft: number;
1159
+ /**
1160
+ * How the camera keeps the route clear of what is drawn over the map: `free-space` (default)
1161
+ * measures every overlay at each fit and frames the route in the free rect where it is drawn
1162
+ * largest; `left-panel-stack` reserves the panel's width over the full height; `auto` adds top
1163
+ * padding under the panel; `none` uses only `camera-padding-*`. Forwarded to `<custom-map>`.
1164
+ */
1165
+ overlayPaddingMode: string;
1166
+ /** Hides the "Volver" bar rendered on top of the route panel. */
1167
+ hideBack: boolean;
1168
+ /**
1169
+ * Hides the built-in loading indicator so the host can show its own. Reads the attribute's value
1170
+ * rather than its presence (see {@link defaultFalseBooleanConverter}), so `hide-loading="false"`
1171
+ * keeps the indicator.
1172
+ */
1173
+ hideLoading: boolean;
1174
+ /** Hides the "Repetir ruta" button shown next to the destination name once a route has been generated. */
1175
+ hideRepeatRoute: boolean;
1176
+ /** Hides the origin/destination rows of the route panel. Destination name, floor, distance and the accessible-route switch stay visible. */
1177
+ hideRouteInputs: boolean;
1178
+ /** Hides the walking / accessible route switch. Routes are then always walking routes. */
1179
+ hideAccessibilitySwitch: boolean;
1180
+ /**
1181
+ * Asks for the accessible route from the start. The visitor can still turn it off, and "Volver"
1182
+ * goes back to it for the next visitor. Reads the attribute's value (see
1183
+ * {@link defaultFalseBooleanConverter}), so `accessible-route="false"` is the walking route.
1184
+ */
1185
+ accessibleRoute: boolean;
1186
+ /**
1187
+ * Floor the route starts on, for an origin that exists on several floors (an elevator). Takes the
1188
+ * floor's id (`InnerFloor.key`) and takes precedence over `origin-level`.
1189
+ */
1190
+ originFloorId: string;
1191
+ /** Same as `origin-floor-id`, by the floor's level number instead of its id. */
1192
+ originLevel: number | undefined;
1193
+ /**
1194
+ * Floor the route ends on, for a destination on several floors. Unlike `origin-floor-id`, "Volver"
1195
+ * clears this one: it belongs to the last visitor's destination, not to the kiosk.
1196
+ */
1197
+ destinationFloorId: string;
1198
+ /** Same as `destination-floor-id`, by level number. */
1199
+ destinationLevel: number | undefined;
1200
+ /** Hides the "Generar ruta" button, and turns on {@link autoGenerateRoute} with it. */
1201
+ hideGenerateRoute: boolean;
1202
+ /**
1203
+ * Hides the QR card. Reads the attribute's value (see {@link defaultFalseBooleanConverter}), so
1204
+ * `hide-qr="false"` keeps the card.
1205
+ */
1206
+ hideQr: boolean;
1207
+ /** Requests and animates the route as soon as origin and destination are loaded, without waiting for "Generar ruta". */
1208
+ autoGenerateRoute: boolean;
1209
+ /** Whether routes are requested automatically: asked for, or implied by hiding the button. */
1210
+ private get _routesAutomatically();
1211
+ /** Route panel layout: `full` (default) or `compact`. The `hide-*` flags still apply on top. */
1212
+ panelVariant: string;
1213
+ /** Where the floor bar goes; see `<floor-selector>`'s `position` values. */
1214
+ floorSelectorPosition: string | undefined;
1215
+ /**
1216
+ * Cache configuration for SDK data (places, routes, configurations, etc.). Defaults to
1217
+ * {@link TOTEM_CACHE_CONFIG}, the preset built for this component's kiosk deployment. What is set
1218
+ * here is merged **over that preset**, so a partial override changes only the entries it names.
1219
+ */
1220
+ cacheConfig: CacheConfig | undefined;
1221
+ /** {@link cacheConfig} resolved against the kiosk preset it defaults to. */
1222
+ private get _effectiveCacheConfig();
1223
+ /**
1224
+ * The destination place ID. Setting this property (even to the same value) clears the previous
1225
+ * route and reloads the destination — handles a totem screen that re-selects the same destination
1226
+ * (e.g. after being locked).
1227
+ */
1228
+ get destinationId(): string;
1229
+ set destinationId(value: string);
1230
+ private _destinationId;
1231
+ /**
1232
+ * Assigns `destinationId` without the same-value reload above. Used by {@link updateComponent},
1233
+ * whose delegation to `<custom-map>`'s own `updateComponent()` already performed the load — a
1234
+ * second one here would be a pointless, redundant `PlaceController.setOriginAndDestination` call.
1235
+ */
1236
+ private _setDestinationIdSilently;
1237
+ /** Whether `firstUpdated` has run, enabling the destination-reload-on-same-value behavior above. */
1238
+ private _hasInitialized;
1239
+ /**
1240
+ * Set while {@link updateComponent} syncs its own reflected properties after delegating the real
1241
+ * work to `<custom-map>`'s own `updateComponent()`. Without it, those property assignments would
1242
+ * also trigger this element's OWN reactive `willUpdate`/`updated` pair-load and
1243
+ * accessible-route-reload paths below — redundantly reloading the very pair, and redundantly
1244
+ * re-applying the very accessible-route preference, `<custom-map>` just finished applying.
1245
+ *
1246
+ * Invariant (Task 14 integration-pass note): {@link _maybeLoadPair}'s suppressed branch assumes
1247
+ * nothing else can legitimately change the pair's identity while this flag is active — true today
1248
+ * only because `updateComponent()` is this flag's one and only write site; re-verify that branch
1249
+ * before ever flipping this flag from a second call site.
1250
+ */
1251
+ private _suppressPairLoad;
1252
+ /**
1253
+ * The pair's identity as last ACTUALLY requested through {@link _loadPair}, or `undefined` once
1254
+ * the pair is incomplete or has never been requested. Compared against a fresh {@link _pairKey} by
1255
+ * {@link _maybeLoadPair} to decide whether a load is due — independent of whether the id fields
1256
+ * themselves changed in the CURRENT render pass (review round 2, see `_maybeLoadPair`'s own doc
1257
+ * comment for why that independence is the fix).
1258
+ */
1259
+ private _pairRequestedFor;
1260
+ /**
1261
+ * A stable identity for the whole pair, not just `destinationId`: changing any one of these six
1262
+ * fields is a different pair that needs its own load. `undefined` when there is no complete pair
1263
+ * to load yet (no `originId` or no `destinationId`).
1264
+ */
1265
+ private _pairKey;
1266
+ /**
1267
+ * Whether {@link _maybeLoadPair} would start a fresh load for the pair as it stands right now: a
1268
+ * complete pair, not already requested, with an SDK actually available for it. Read-only (no side
1269
+ * effects, unlike `_maybeLoadPair` itself) — used by `willUpdate()` to decide whether an
1270
+ * `accessibleRoute` change should apply straight to context (a load is about to replace the route
1271
+ * anyway) or go through `RouteController.setAccessibleRoute()` (nothing else is about to touch the
1272
+ * route this pass).
1273
+ */
1274
+ private _pairLoadPending;
1275
+ /**
1276
+ * Loads the pair through {@link _loadPair} once it is complete and an SDK is actually available for
1277
+ * it. Checked on EVERY `updated()` pass — NOT gated on `changedProperties` naming the id fields,
1278
+ * unlike the version this replaced (review round 2, the same load-ordering gap Task 10's own review
1279
+ * found in `map-view-with-modal.ts`'s `maybeLoadPlace()`, ported here adapted to a full pair instead
1280
+ * of a single id):
1281
+ *
1282
+ * A pair set in an EARLIER render pass than `apiKey`/`locale`/`parentPlaceId` would otherwise never
1283
+ * load at all. `PlaceController.setOriginAndDestination()` silently no-ops with no SDK yet; by the
1284
+ * time credentials finally arrive in their OWN, later pass, the id fields are no longer "changed"
1285
+ * in THAT pass, so a `changedProperties`-gated check would never fire for them again — the pair
1286
+ * would be stuck forever. Deduping on {@link _pairKey} (the identity actually last requested)
1287
+ * instead of on Lit's own per-pass dirty-checking is what fixes this: a pair set before the SDK
1288
+ * exists is simply never marked "handled" until a pass where the SDK really is ready picks it up.
1289
+ * The same dedupe also means calling this unconditionally never causes a redundant re-fetch of an
1290
+ * already-loaded pair.
1291
+ *
1292
+ * Respects {@link _suppressPairLoad} (set by {@link updateComponent} while it syncs its own
1293
+ * reflected properties after `<custom-map>`'s own `updateComponent()` already did the real load):
1294
+ * while suppressed, this still records the CURRENT key as `_pairRequestedFor` — without that, once
1295
+ * suppression lifts, this method would see the pair `<custom-map>` just loaded as still "pending"
1296
+ * (its key was never recorded) and fire a redundant reload for it, reopening the exact bug the
1297
+ * first review round's `_suppressPairLoad` fix closed. This suppressed branch relies on nothing
1298
+ * else legitimately changing the pair's identity while `_suppressPairLoad` is active — safe only
1299
+ * because that flag has exactly one write site (`updateComponent()`); a second write site would
1300
+ * need this branch re-checked, or it could silently drop a pair load it should have started.
1301
+ *
1302
+ * @returns `true` once it actually started a load this call, so `updated()`'s own
1303
+ * auto-route-toggle branch does not duplicate the request `_loadPair()` already makes for a fresh pair.
1304
+ */
1305
+ private _maybeLoadPair;
1306
+ /**
1307
+ * Loads the current origin/destination pair, and the route too when routes are automatic.
1308
+ *
1309
+ * Clears the previous route first (review round 1, Important finding 2): without this, a route
1310
+ * loaded for the pair being left stays in context — `RouteController` has no other call site that
1311
+ * drops it on a plain property-driven pair change (unlike `<custom-map>`'s own `updateComponent()`,
1312
+ * whose `replacePair()` clears it before loading). Left uncleared, three things went wrong: a
1313
+ * same-value `destinationId` reload (the kiosk "re-select after screen lock" case) kept the stale
1314
+ * route id; an origin-only change in auto mode never asked for a new route because
1315
+ * `_requestRouteIfIdle()` saw the stale one and thought one already existed; and an origin-only
1316
+ * change outside auto mode left the old, now-wrong route drawn on the map. `clearRoute()` also
1317
+ * drops a route request still in flight for the pair being left, so its answer cannot land on this one.
1318
+ *
1319
+ * In auto mode the route is requested together with the places (`generateRoute({ after })`, the
1320
+ * reference's route-alongside-places load): its `route` loading phase is raised before the
1321
+ * `places` one ends, so `mvxLoadingChange` never reports the load as over between the two, and the
1322
+ * request itself goes out once the places are in — with the floors the host asked for resolved
1323
+ * against the loaded places — or not at all if they failed or a newer load superseded them.
1324
+ */
1325
+ private _loadPair;
1326
+ /** Generates the route for the current pair, unless one is already loaded or loading. */
1327
+ private _requestRouteIfIdle;
1328
+ /** Context forwarded to MapVX API as `X-MapVx-*` and `mvx-product` request headers. */
1329
+ private mapVxRequestContext;
1330
+ /* Excluded from this release type: contextManager */
1331
+ /* Excluded from this release type: placeController */
1332
+ /* Excluded from this release type: routeController */
1333
+ /* Excluded from this release type: floorController */
1334
+ private readonly analyticsController;
1335
+ /** The tiles service worker (see this class's doc comment), started in `firstUpdated()`. */
1336
+ private readonly tileServiceWorker;
1337
+ /**
1338
+ * Keeps the compact route card clear of the vertical floor bar, however wide the floor names make
1339
+ * it. Held only so it lives as long as the host: `protected` rather than `private` because
1340
+ * `noUnusedLocals` rejects a private field that is never read (TS6133).
1341
+ */
1342
+ protected readonly floorSelectorSize: FloorSelectorSizeController;
1343
+ constructor();
1344
+ /**
1345
+ * The inner `custom-map`. Always present (this element renders it unconditionally, unlike the
1346
+ * lazily-loaded reference), so a plain cast is enough — no `Partial<>`/optional-chaining dance.
1347
+ */
1348
+ private _customMap;
1349
+ firstUpdated(): void;
1350
+ private sendEvent;
1351
+ private _mapReadyHandler;
1352
+ private _cameraInitializedHandler;
1353
+ willUpdate(changedProperties: PropertyValues): void;
1354
+ updated(changedProperties: PropertyValues): void;
1355
+ render(): TemplateResult<1>;
1356
+ private _floorChangeHandler;
1357
+ private _accessibilityChangeHandler;
1358
+ private _repeatRouteHandler;
1359
+ private _generateRouteHandler;
1360
+ private _backHandler;
1361
+ /**
1362
+ * Turns `<custom-map>`'s `startRouteAnimation`/`routeAnimationFinished` events, and
1363
+ * `<route-options>`'s `repeatRoute` event, into the matching `RouteController` call. This is the
1364
+ * wiring Task 8b's review found missing (its M2): without it, `routeData.isAnimating` stays `true`
1365
+ * forever once a route finishes naturally, which `<custom-map>`'s stall-recovery branch
1366
+ * (`restartStalledRoute`) reads as "stalled" and restarts — an endless replay loop. See
1367
+ * `route-view-totems.test.ts`'s "route animation wiring" suite for the regression test proving a
1368
+ * natural finish does not trigger a restart.
1369
+ */
1370
+ private _startRouteAnimationHandler;
1371
+ private _routeAnimationFinishedHandler;
1372
+ private _dismissRouteErrorHandler;
1373
+ /**
1374
+ * Updates the component's origin/destination/floor/route-type without requiring a "back" event.
1375
+ * Delegates to the inner `<custom-map>`'s own `updateComponent()` (see this class's doc comment for
1376
+ * why the real work lives there), then keeps this element's own reflected properties in step with
1377
+ * what was actually requested.
1378
+ *
1379
+ * @param params - Parameters for the update
1380
+ * @returns Promise resolving to the result of the update operation
1381
+ * @example
1382
+ * ```typescript
1383
+ * const result = await totemView.updateComponent({ destinationId: 'PDP_N1_1036' });
1384
+ * if (result.success) {
1385
+ * console.log('Updated from', result.previousDestinationId, 'to', result.newDestinationId);
1386
+ * }
1387
+ * ```
1388
+ */
1389
+ updateComponent(params: UpdateComponentParams): Promise<UpdateComponentResult>;
1390
+ /**
1391
+ * Clears the map of routes and destination markers, keeping the origin.
1392
+ * @param preserveOrigin - Whether to preserve the origin marker (default: true)
1393
+ */
1394
+ clearMap(preserveOrigin?: boolean): Promise<void>;
1395
+ /**
1396
+ * Destroys the map and builds a fresh one, keeping venue, origin, destination and route.
1397
+ * @example
1398
+ * ```ts
1399
+ * document.querySelector('route-view-totems')?.reloadMap();
1400
+ * ```
1401
+ */
1402
+ reloadMap(): void;
1403
+ /**
1404
+ * Whether a load is in progress: places, route or camera. Independent of whether anything is
1405
+ * painted, so `hide-loading` does not make it `false`.
1406
+ */
1407
+ isLoading(): boolean;
1408
+ connectedCallback(): void;
1409
+ disconnectedCallback(): void;
1410
+ }
1411
+
1412
+ /**
1413
+ * Schedules periodic tile warmup (same message as initial load). Returns a cleanup function.
1414
+ */
1415
+ export declare function schedulePeriodicTileRefresh(registration: ServiceWorkerRegistration | null | undefined, options: MvxTilePrefetchOptions, intervalMs?: number): () => void;
1416
+
1417
+ /**
1418
+ * Context type for SDK core state.
1419
+ */
1420
+ declare interface SDKContextType {
1421
+ /** The initialized SDK instance */
1422
+ sdk?: MapVXSDK;
1423
+ /** Current locale for SDK operations */
1424
+ locale?: string;
1425
+ /** Parent place ID for SDK scope */
1426
+ parentPlaceId?: string;
1427
+ }
1428
+
1429
+ /**
1430
+ * Storage size constants in bytes.
1431
+ *
1432
+ * @description Helper constants for defining storage limits in cache configurations. Used as
1433
+ * {@link CacheConfig.maxStorageBytes}, the SDK reads them as UTF-16 code units, not bytes.
1434
+ *
1435
+ * @example
1436
+ * ```typescript
1437
+ * import { STORAGE_BYTES } from '@mapvx/web-kit';
1438
+ *
1439
+ * const config = {
1440
+ * maxStorageBytes: STORAGE_BYTES.MB_10, // 10MB limit
1441
+ * };
1442
+ * ```
1443
+ */
1444
+ export declare const STORAGE_BYTES: {
1445
+ /** 2 megabytes in bytes (2,097,152) */
1446
+ readonly MB_2: number;
1447
+ /** 5 megabytes in bytes (5,242,880) */
1448
+ readonly MB_5: number;
1449
+ /** 10 megabytes in bytes (10,485,760) */
1450
+ readonly MB_10: number;
1451
+ };
1452
+
1453
+ /**
1454
+ * Time constants in milliseconds for readability.
1455
+ *
1456
+ * @description Helper constants for defining TTL values in cache configurations.
1457
+ *
1458
+ * @example
1459
+ * ```typescript
1460
+ * import { TIME_MS } from '@mapvx/web-kit';
1461
+ *
1462
+ * const ttl = 15 * TIME_MS.MINUTE; // 15 minutes in ms
1463
+ * const longTtl = 2 * TIME_MS.HOUR; // 2 hours in ms
1464
+ * ```
1465
+ */
1466
+ export declare const TIME_MS: {
1467
+ /** One minute in milliseconds (60,000) */
1468
+ readonly MINUTE: number;
1469
+ /** One hour in milliseconds (3,600,000) */
1470
+ readonly HOUR: number;
1471
+ };
1472
+
1473
+ /**
1474
+ * Cache configuration optimized for totem/kiosk deployments.
1475
+ *
1476
+ * @description Designed for dedicated hardware running continuously:
1477
+ * - 2MB storage limit per cache type: a large mall's store lists in two languages fit (1.8 M
1478
+ * measured for Costanera), and no single type can fill the 5 M an origin gets on its own. A
1479
+ * third language would not fit: the SDK then stops writing that type and keeps the copy it has
1480
+ * - Longer TTLs (1-4 hours) to reduce API calls
1481
+ * - Persistent storage enabled for fast cold starts
1482
+ *
1483
+ * Unlike {@link WEB_CACHE_CONFIG}, store lists (`subPlaces`) are persisted too. A kiosk shows one
1484
+ * venue on a page no host shares, so they take a bounded share of storage nothing else competes
1485
+ * for, and a reload does not download the largest response again. The SDK also seeds every store
1486
+ * it downloads into `places`, so on a large venue the stores fill that cache as well: about 1.5 of
1487
+ * the 1.6 MB a Costanera totem stores is store data, kept twice.
1488
+ *
1489
+ * Recommended for: Digital signage, wayfinding kiosks, information totems.
1490
+ *
1491
+ * @example
1492
+ * ```typescript
1493
+ * import { TOTEM_CACHE_CONFIG } from '@mapvx/web-kit';
1494
+ *
1495
+ * // Use directly
1496
+ * <route-view-totems
1497
+ * apiKey="your-api-key"
1498
+ * parentPlaceId="venue-id"
1499
+ * .cacheConfig=${TOTEM_CACHE_CONFIG}
1500
+ * />
1501
+ * ```
1502
+ *
1503
+ * | Cache Type | Max Items | TTL | Persisted |
1504
+ * |------------------|-----------|------------|-----------|
1505
+ * | places | 500 | 2 hours | yes |
1506
+ * | subPlaces | 200 | 1 hour | yes |
1507
+ * | routes | 100 | 15 minutes | yes |
1508
+ * | accessibleRoutes | 100 | 15 minutes | yes |
1509
+ * | configurations | 10 | 4 hours | yes |
1510
+ * | categories | 50 | 2 hours | yes |
1511
+ * | vehicles | 20 | 30 minutes | yes |
1512
+ * | stops | 50 | 30 minutes | yes |
1513
+ * | styles | 20 | 24 hours | yes (SDK default) |
1514
+ */
1515
+ export declare const TOTEM_CACHE_CONFIG: CacheConfig;
1516
+
1517
+ /**
1518
+ * Asks the active service worker to run bounded progressive tile prefetch.
1519
+ */
1520
+ export declare function triggerInitialTileLoad(registration: ServiceWorkerRegistration | null | undefined, options: MvxTilePrefetchOptions): void;
1521
+
1522
+ /**
1523
+ * Context type for UI-related state.
1524
+ */
1525
+ declare interface UIContextType {
1526
+ /** Currently selected floor */
1527
+ currentFloor?: InnerFloor;
1528
+ /** All available floors in the parent place */
1529
+ allFloors: InnerFloor[];
1530
+ /** Markers to display on the map */
1531
+ markers: MarkerContext[];
1532
+ /** Whether the map is fully loaded and ready */
1533
+ mapReady: boolean;
1534
+ /** Whether the camera has been initialized with proper view */
1535
+ cameraInitialized: boolean;
1536
+ }
1537
+
1538
+ /**
1539
+ * Parameters for updating the map component programmatically. Same shape as the reference's
1540
+ * `custom-map.ts` (there, just a type; the reference's actual `updateComponent()` lives on
1541
+ * `route-view-totems.ts` — see the class doc for why it lives here instead in web-kit).
1542
+ */
1543
+ export declare interface UpdateComponentParams {
1544
+ /** New destination ID to navigate to */
1545
+ destinationId?: string;
1546
+ /** New origin ID (optional, defaults to current origin) */
1547
+ originId?: string;
1548
+ /**
1549
+ * Floor the route starts on, for an origin on several floors (an elevator). Takes precedence over
1550
+ * `originLevel`. A new `originId` given without a floor clears the previous one.
1551
+ */
1552
+ originFloorId?: string;
1553
+ /** Level of the floor the route starts on. Prefer `originFloorId`; see `origin-level`. */
1554
+ originLevel?: number;
1555
+ /** Same as `originFloorId`, for the destination. A new `destinationId` without a floor clears it. */
1556
+ destinationFloorId?: string;
1557
+ /** Same as `originLevel`, for the destination. */
1558
+ destinationLevel?: number;
1559
+ /** Asks for the accessible route (elevators over stairs and escalators). */
1560
+ accessibleRoute?: boolean;
1561
+ /** Floor shown in the floor selector (optional). Not where the route starts. */
1562
+ floor?: string;
1563
+ }
1564
+
1565
+ /** Result of an {@link CustomMap.updateComponent} call. Ported from the reference's `route-view-totems.ts`. */
1566
+ export declare interface UpdateComponentResult {
1567
+ success: boolean;
1568
+ error?: string;
1569
+ previousDestinationId?: string;
1570
+ newDestinationId?: string;
1571
+ }
1572
+
1573
+ /**
1574
+ * Waits for whichever service worker registration's scope covers this page.
1575
+ *
1576
+ * @description Kept because it is the behaviour published up to v0.13.0, and dropping it would
1577
+ * break every existing caller — silently for plain-JS importers, where there is no compiler to
1578
+ * complain. It waits for the registration whose scope covers the page, which need not be the tiles
1579
+ * one: with a host worker at a narrower scope it returns while the tiles worker is still
1580
+ * installing, and `triggerInitialTileLoad` then drops the prefetch. Per spec it never rejects, and
1581
+ * it never resolves at all while no registration covers the page.
1582
+ *
1583
+ * This signature comes first on purpose: TypeScript reads the **last** overload for
1584
+ * `Parameters<>` and for inference into generic functions, so putting it last would type the
1585
+ * function as `() => Promise<void>` and push callers towards the form being deprecated.
1586
+ * @deprecated Pass the registration {@link registerMvxTileServiceWorker} returned.
1587
+ * @returns A promise that resolves once some registration covering the page has an active worker
1588
+ * @example
1589
+ * // Prefer this instead:
1590
+ * const registration = await registerMvxTileServiceWorker();
1591
+ * await waitForServiceWorkerReady(registration);
1592
+ */
1593
+ export declare function waitForServiceWorkerReady(): Promise<void>;
1594
+
1595
+ /**
1596
+ * Waits until a tiles service worker registration can receive messages.
1597
+ *
1598
+ * @description Resolves as soon as `registration` has a messageable worker, and immediately when
1599
+ * there is nothing to wait for. `null` and `undefined` both mean that: `registerMvxTileServiceWorker`
1600
+ * returns `null` when it could not register, and `ServiceWorkerContainer.getRegistration` resolves
1601
+ * to `undefined` when nothing matches. Treating either as "wait for the page instead" is how this
1602
+ * used to hang for the life of the page.
1603
+ * @param registration - The registration {@link registerMvxTileServiceWorker} returned, or
1604
+ * `null`/`undefined` when there is none
1605
+ * @returns A promise that resolves once the worker can be messaged, or immediately when there is
1606
+ * nothing to wait for
1607
+ * @example
1608
+ * const registration = await registerMvxTileServiceWorker();
1609
+ * await waitForServiceWorkerReady(registration);
1610
+ * if (registration) {
1611
+ * triggerInitialTileLoad(registration, { apiKey: 'key', placeId: 'place' });
1612
+ * }
1613
+ */
1614
+ export declare function waitForServiceWorkerReady(registration: ServiceWorkerRegistration | null | undefined): Promise<void>;
1615
+
1616
+ /**
1617
+ * Cache configuration optimized for web browser usage.
1618
+ *
1619
+ * @description Designed for standard website visitors:
1620
+ * - 5MB storage limit per cache type
1621
+ * - Shorter TTLs (5-60 minutes) for fresher data
1622
+ * - Persistent storage enabled for return visitors, except for store lists and map styles
1623
+ *
1624
+ * Store lists (`subPlaces`) stay in memory only. They are the largest entry, 0.85 MB for one
1625
+ * language of a large mall, and they pile up with every venue a visitor opens, in the localStorage
1626
+ * the host page shares with the components: twelve venues took 3.3 MB of the 5 MB that Chrome
1627
+ * gives an origin (MFE-272). The stores themselves still reach localStorage one by one, because the
1628
+ * SDK seeds every store it downloads into `places`, which is persisted; `places.maxItems` bounds
1629
+ * them (about 280 KB here).
1630
+ *
1631
+ * Map styles (`styles`) stay in memory too, at about 50 KB per venue: twelve venues stored 561 KB
1632
+ * of them. SDK 4.0.1 kept both lists and styles in memory, in a cache of the map's own.
1633
+ *
1634
+ * Recommended for: Website embeds, mobile web apps, standard deployments.
1635
+ *
1636
+ * @example
1637
+ * ```typescript
1638
+ * import { WEB_CACHE_CONFIG } from '@mapvx/web-kit';
1639
+ *
1640
+ * // Use directly
1641
+ * <map-view-with-modal
1642
+ * apiKey="your-api-key"
1643
+ * parentPlaceId="venue-id"
1644
+ * .cacheConfig=${WEB_CACHE_CONFIG}
1645
+ * />
1646
+ * ```
1647
+ *
1648
+ * | Cache Type | Max Items | TTL | Persisted |
1649
+ * |------------------|-----------|------------|-----------|
1650
+ * | places | 200 | 30 minutes | yes |
1651
+ * | subPlaces | 100 | 15 minutes | no |
1652
+ * | routes | 50 | 5 minutes | yes |
1653
+ * | accessibleRoutes | 50 | 5 minutes | yes |
1654
+ * | configurations | 10 | 1 hour | yes |
1655
+ * | categories | 30 | 1 hour | yes |
1656
+ * | vehicles | 10 | 5 minutes | yes |
1657
+ * | stops | 20 | 5 minutes | yes |
1658
+ * | styles | 20 | 24 hours | no |
1659
+ */
1660
+ export declare const WEB_CACHE_CONFIG: CacheConfig;
1661
+
1662
+ export { }
1663
+
1664
+
1665
+ declare global {
1666
+ interface HTMLElementTagNameMap {
1667
+ 'route-view-totems': RouteViewTotems;
1668
+ }
1669
+ }
1670
+
1671
+
1672
+ declare global {
1673
+ interface HTMLElementTagNameMap {
1674
+ 'map-view-with-modal': MapViewWithModal;
1675
+ }
1676
+ }
1677
+
1678
+
1679
+ declare global {
1680
+ interface HTMLElementEventMap {
1681
+ mvxError: CustomEvent<MvxErrorDetail>;
1682
+ /**
1683
+ * The route started animating onto the map.
1684
+ *
1685
+ * **Also fires on every route repeat**, not only the first one, so treat it as "a route is
1686
+ * being drawn now" rather than "the first load finished". For the end of a load use
1687
+ * {@link HTMLElementEventMap.mvxLoadingChange}.
1688
+ */
1689
+ startRouteAnimation: CustomEvent<void>;
1690
+ /**
1691
+ * The camera finished framing its target.
1692
+ *
1693
+ * **Not the end of the load.** With `auto-generate-route` the route is requested alongside the
1694
+ * two places, so the camera frames them and fires this while the route is still being
1695
+ * generated — seconds before it appears. A host indicator taken down here leaves the visitor
1696
+ * on an empty map waiting for a route with nothing to say so.
1697
+ *
1698
+ * For the end of a load use {@link HTMLElementEventMap.mvxLoadingChange} with
1699
+ * `detail.loading === false`, which is the one signal the built-in overlay itself goes down on.
1700
+ */
1701
+ cameraInitialized: CustomEvent<Record<string, never>>;
1702
+ }
1703
+ }
1704
+
1705
+
1706
+ declare global {
1707
+ interface HTMLElementTagNameMap {
1708
+ 'custom-map': CustomMap;
1709
+ }
1710
+ }
1711
+
1712
+
1713
+ declare global {
1714
+ interface HTMLElementTagNameMap {
1715
+ 'compact-floor-selector': CompactFloorSelector;
1716
+ }
1717
+ }
1718
+
1719
+
1720
+ declare global {
1721
+ interface HTMLElementTagNameMap {
1722
+ 'floor-selector': FloorSelector;
1723
+ }
1724
+ }
1725
+
1726
+
1727
+ declare global {
1728
+ interface HTMLElementTagNameMap {
1729
+ 'route-options': RouteOptions;
1730
+ }
1731
+ }
1732
+
1733
+
1734
+ declare global {
1735
+ interface HTMLElementTagNameMap {
1736
+ 'qr-modal': QRModal;
1737
+ }
1738
+ }
1739
+
1740
+
1741
+ declare global {
1742
+ interface HTMLElementEventMap {
1743
+ /**
1744
+ * The loading state changed, with the phase that caused it. One event per transition, and
1745
+ * `detail.loading === false` is the end of the load — the same moment the built-in indicator
1746
+ * goes down.
1747
+ */
1748
+ mvxLoadingChange: CustomEvent<MvxLoadingChangeDetail>;
1749
+ }
1750
+ }
1751
+
1752
+
1753
+ declare global {
1754
+ interface HTMLElementTagNameMap {
1755
+ 'map-loading-overlay': MapLoadingOverlay;
1756
+ }
1757
+ }
1758
+
1759
+
1760
+ declare global {
1761
+ interface Window {
1762
+ dataLayer: unknown[];
1763
+ gtag: (...args: unknown[]) => void;
1764
+ }
1765
+ }