@minmaps-dev/mm-web-sdk 1.0.0-rc.33 → 1.0.0-rc.34

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { IControl, ControlPosition, StyleSpecification, Map } from 'maplibre-gl';
1
+ import { Map, IControl, ControlPosition, StyleSpecification } from 'maplibre-gl';
2
2
 
3
3
  /**
4
4
  * Represents a floor in a building
@@ -51,6 +51,12 @@ interface POI {
51
51
  floorId: string | number;
52
52
  /** Category/type of amenity (e.g., 'restroom', 'elevator') */
53
53
  amenityType?: string;
54
+ /** Which amenity icon layer this POI renders in — `'connector'`,
55
+ * `'entrance'`, `'parking'`, `'bus'` or `'other'`. Derived from the
56
+ * amenity's connector flag, name, type and keywords; emitted as the
57
+ * `amenityCategory` feature property the theme filters on. Amenities
58
+ * only. See `amenityCategoryFor`. */
59
+ amenityCategory?: 'connector' | 'entrance' | 'parking' | 'bus' | 'other';
54
60
  /** Search keywords */
55
61
  keywords?: string[];
56
62
  /** Additional properties */
@@ -115,20 +121,26 @@ interface Destination {
115
121
  category?: string;
116
122
  /** Additional properties */
117
123
  properties?: Record<string, unknown>;
118
- /** Uploaded image (e.g. brand/store logo). JACS `/all` fullcall serves this
119
- * as `{ items: [{ resourceType, mimeType, path }] }`; the legacy/basic shape
120
- * is `[{ locales: [{ uriPath }] }]`. `DestinationIcons.register` handles both. */
124
+ /** The CMS "Location Image" — a photo or logo for the popover, not a map
125
+ * marker. JACS `/all` fullcall serves this as
126
+ * `{ items: [{ resourceType, mimeType, path }] }`; the legacy/basic shape is
127
+ * `[{ locales: [{ uriPath }] }]`. `destinationImageSrc` handles both, and
128
+ * surfaces the result on `sdk.getPOIDetails(poi).imageUrl`. */
121
129
  uris?: unknown;
122
- /** Free-form CMS metadata (reserved for future destination icon options). */
130
+ /** Inline SVG for the uploaded image, embedded by JACS `/all`. Preferred over
131
+ * fetching `uris[].path` — no network round-trip. */
132
+ svg?: string;
133
+ /** Free-form CMS metadata. */
123
134
  extensors?: Record<string, unknown>;
124
- /** Map-manager "Label Display" mode (JACS `displayMode`):
125
- * `0` Hidden (dot only) · `1` Label (dot + text) · `2` Image (uploaded logo).
126
- * Undefined treated as Label (backwards-compatible default). */
135
+ /** @deprecated Read by nothing in the SDK as of rc.34.
136
+ *
137
+ * JACS still serves the old map-manager "Label Display" mode
138
+ * (`0` Hidden · `1` Label · `2` Image), but the CMS removed the picker and
139
+ * pins every write to `1`. Rows authored before that keep a stale `0`/`2`
140
+ * the author can no longer change, so honouring the field would hide labels
141
+ * with no way to bring them back. Destinations always render dot + text
142
+ * label; the uploaded image goes to the popover instead. */
127
143
  displayMode?: number;
128
- /** Runtime-assigned map-image id, decorated in place by
129
- * `DestinationIcons.register` (only for `displayMode === 2`).
130
- * Read by the POI builder + theme layer. */
131
- iconId?: string;
132
144
  }
133
145
  /**
134
146
  * Waypoint - a specific point location
@@ -339,16 +351,16 @@ type AmenityBadgeStyle = {
339
351
  /** Ring width in logical px. Default `2`. */
340
352
  ringWidth?: number;
341
353
  };
342
- type DestinationChipStyle = {
343
- /** Chip fill colour. Default `'#FFFFFF'`. */
344
- color?: string;
345
- /** Chip border colour. Default navy `'#162e51'`. */
346
- borderColor?: string;
347
- /** Chip border width in logical px. Default `2`. */
348
- borderWidth?: number;
349
- };
350
354
  interface SDKOptions {
351
355
  debug?: boolean;
356
+ /**
357
+ * `window` key the SDK instance is published under while `debug` is on, so
358
+ * a running kiosk can be driven from devtools (`mm.debug.hide('labels')`,
359
+ * `mm.getMap()`). Defaults to `'mm'`. Pass another name to avoid a clash,
360
+ * or `false` to publish nothing even in debug mode. Ignored entirely when
361
+ * `debug` is off.
362
+ */
363
+ debugGlobal?: string | false;
352
364
  /**
353
365
  * Initial theme. `'default'` uses the bundled hybrid 3D theme.
354
366
  * `'high-contrast'` uses the WCAG-AA tuned theme. Pass a
@@ -437,14 +449,6 @@ interface SDKOptions {
437
449
  * unless this is set explicitly.
438
450
  */
439
451
  connectorBadge?: AmenityBadgeStyle | false;
440
- /**
441
- * Chip composited behind each destination's uploaded logo. Destinations are
442
- * full-colour brand images (not recoloured), so they get a neutral white
443
- * rounded chip for legibility instead of the amenity gold badge. Pass `false`
444
- * to render the logo bare, or an object to tune the chip fill / border.
445
- * Defaults to a white chip with a 2px navy border.
446
- */
447
- destinationChip?: DestinationChipStyle | false;
448
452
  styleMode?: 'venueStyleUrl' | 'sdkTemplate';
449
453
  templateOverrideMode?: 'colorsOnly' | 'colorsAndConstants' | 'all';
450
454
  }
@@ -497,6 +501,230 @@ type SDKConfig = {
497
501
  options?: SDKOptions;
498
502
  };
499
503
 
504
+ type Visibility = 'visible' | 'none';
505
+ type DebugLayersDeps = {
506
+ getMap: () => Map | null;
507
+ /**
508
+ * Re-assert the visibility the SDK itself owns — floor layers, the POI
509
+ * category filter, the 2D/3D view mode. Called at the end of `reset()`,
510
+ * because restoring a captured `visibility` can't distinguish "the theme
511
+ * ships this visible" from "the SDK hid it because it belongs to another
512
+ * floor", and the naive restore would reveal every floor at once.
513
+ */
514
+ reapplySdkState?: () => void;
515
+ log?: (...args: unknown[]) => void;
516
+ };
517
+ type LayerRow = {
518
+ id: string;
519
+ type: string;
520
+ visibility: Visibility;
521
+ /**
522
+ * What this layer's visibility was before we touched it — i.e. what the
523
+ * theme and the SDK want it to be. Equal to `visibility` for any layer we
524
+ * hold no override on. A UI wanting to show "is this group on" should judge
525
+ * only the layers whose `base` is `'visible'`: the rest (the 3D extrusions
526
+ * in flat mode, the 2D outlines outside it) aren't rendering by design, so
527
+ * counting them makes a healthy group look half-off.
528
+ */
529
+ base: Visibility;
530
+ };
531
+ /**
532
+ * Console-facing layer inspector for demos, screenshots and debugging.
533
+ *
534
+ * Reachable as `sdk.debug`, and as `window.mm.debug` when
535
+ * `options.debug` is on (see `options.debugGlobal`).
536
+ *
537
+ * Two things make it more than a wrapper around `setLayoutProperty`:
538
+ *
539
+ * 1. **Selectors.** `hide('amenities')`, `hide('route-')`, `hide('/^poi-/')`
540
+ * and `hide('type:fill-extrusion')` all work, so you don't have to know
541
+ * the theme's layer ids to start poking at it.
542
+ * 2. **Overrides are sticky.** The SDK re-asserts layer visibility on floor
543
+ * changes, `setPOIFilter`, flat-mode toggles and theme swaps — all of which
544
+ * would otherwise wipe a manual toggle mid-demo. Every override is re-applied
545
+ * on `styledata`, so what you hid stays hidden until `reset()`.
546
+ */
547
+ declare class DebugLayers {
548
+ private deps;
549
+ /** layer id → visibility this API is asserting. */
550
+ private overrides;
551
+ /** layer id → visibility before we first touched it. */
552
+ private originals;
553
+ /** `${layer}|${prop}` → paint value before we first touched it. */
554
+ private paintOriginals;
555
+ private sticky;
556
+ private attachedTo;
557
+ /** Re-entrancy guard: our own `setLayoutProperty` fires `styledata`. */
558
+ private applying;
559
+ private readonly onStyleData;
560
+ constructor(deps: DebugLayersDeps);
561
+ /** Begin re-asserting overrides across style/floor changes. */
562
+ attach(map: Map): void;
563
+ detach(): void;
564
+ /**
565
+ * Every layer in the active style, newest-on-top last, with its current
566
+ * visibility. Pass a selector to narrow it (same grammar as `hide`).
567
+ */
568
+ list(selector?: string): LayerRow[];
569
+ /** Just the ids currently rendering — the quickest "what am I looking at". */
570
+ visible(): string[];
571
+ /** Group name → the ids it resolves to *in the active style*. */
572
+ groups(): Record<string, string[]>;
573
+ /** Hide every layer the selectors resolve to. Returns the ids affected. */
574
+ hide(...selectors: string[]): string[];
575
+ /**
576
+ * **Force** every resolved layer visible — including ones the SDK
577
+ * deliberately keeps off: the 3D extrusions while flat mode is on, the 2D
578
+ * outlines while it isn't, every floor but the active one. Forcing those
579
+ * renders two representations of the same geometry at once, or every floor
580
+ * stacked, and the map looks wrong.
581
+ *
582
+ * So this is *not* the way to undo a `hide()` — use `restore()`, which puts
583
+ * each layer back to what it was rather than blanket-revealing the group.
584
+ * Reach for `show()` only when you actually mean "reveal this regardless".
585
+ */
586
+ show(...selectors: string[]): string[];
587
+ /**
588
+ * Undo our overrides on these layers: each goes back to the visibility it
589
+ * had before we first touched it, and control returns to the SDK (floor
590
+ * layers, POI filter, view mode re-assert afterwards).
591
+ *
592
+ * This is the correct inverse of `hide()`. A group is rarely uniformly
593
+ * visible to begin with — `rooms` hides either the 2D outline or the 3D
594
+ * extrusion depending on view mode, and every floor layer but the active
595
+ * one is off — so `hide()` then `show()` does not round-trip, but `hide()`
596
+ * then `restore()` does.
597
+ *
598
+ * Returns the ids that actually had an override; layers we never touched
599
+ * are left alone.
600
+ */
601
+ restore(...selectors: string[]): string[];
602
+ /** Flip each resolved layer independently. Returns the ids affected. */
603
+ toggle(...selectors: string[]): string[];
604
+ /**
605
+ * Show only what the selectors resolve to — everything else is hidden
606
+ * (except `background`, which is just the canvas colour). The one-liner for
607
+ * "which layer is drawing that thing".
608
+ *
609
+ * The kept set is *restored*, not forced: anything we'd previously hidden
610
+ * comes back, but a layer the theme ships hidden stays hidden. Soloing must
611
+ * not invent geometry that never renders normally — see `show()`.
612
+ */
613
+ solo(...selectors: string[]): string[];
614
+ /**
615
+ * Set a paint property — `paint('units-fill', 'fill-color', '#f00')`. The
616
+ * original value is captured so `reset()` puts it back. Not sticky: unlike
617
+ * visibility, a theme swap rebuilds paint from the new style and re-applying
618
+ * a captured expression across themes is exactly the bug `setTheme` had to
619
+ * fix. Re-run it after a swap if you need it back.
620
+ */
621
+ paint(selector: string, prop: string, value: unknown): string[];
622
+ /**
623
+ * Drop every override and paint change, then let the SDK re-assert the
624
+ * visibility it owns (floor layers, POI filter, view mode). Back to the map
625
+ * you'd have had without touching anything.
626
+ */
627
+ reset(): void;
628
+ /**
629
+ * Hand the layers we just released back to the SDK, then re-assert whatever
630
+ * overrides are still standing.
631
+ *
632
+ * The second half is not belt-and-braces. The SDK's re-assert passes are
633
+ * all-or-nothing: with no POI filter active, `applyPOIFilter` writes
634
+ * `visible` to *every* POI category layer, and the floor / view-mode passes
635
+ * sweep their whole layer sets the same way. So releasing one group would
636
+ * un-hide every other group you'd hidden — hide labels, destinations and
637
+ * amenities, re-check one, and all three came back.
638
+ *
639
+ * Doing it here rather than waiting for the `styledata` the SDK's writes
640
+ * trigger also keeps it synchronous: MapLibre fires that on a later frame,
641
+ * so a UI reading visibility straight after this call would otherwise see —
642
+ * and render — the clobbered state.
643
+ */
644
+ private handBackToSdk;
645
+ /**
646
+ * The current override set as a plain object — save it, paste it back with
647
+ * `apply()` to reproduce the exact same framing for a screenshot later.
648
+ */
649
+ snapshot(): Record<string, Visibility>;
650
+ /** Apply a `snapshot()` (or any layer-id → visibility map). */
651
+ apply(snapshot: Record<string, Visibility>): string[];
652
+ /**
653
+ * Stop (or resume) re-asserting overrides when the style changes. Turn it
654
+ * off if you want a floor switch or `setPOIFilter` to win over what you
655
+ * toggled by hand.
656
+ */
657
+ setSticky(enabled: boolean): boolean;
658
+ /** Console cheat sheet. */
659
+ help(): Array<{
660
+ call: string;
661
+ does: string;
662
+ }>;
663
+ /**
664
+ * Resolve one selector to layer ids present in the active style, tried in
665
+ * order: group name → exact layer id → `type:<layer type>` → `/regex/` →
666
+ * case-insensitive substring on the id.
667
+ */
668
+ resolve(selector: string): string[];
669
+ private resolveAll;
670
+ private set;
671
+ /**
672
+ * Put these layers back to their pre-override visibility and forget them.
673
+ * Callers decide whether to follow up with `reapplySdkState` — `restore()`
674
+ * and `reset()` do, `solo()` deliberately doesn't.
675
+ */
676
+ private restoreVisibility;
677
+ /** Write one layer's visibility and remember it as an override. */
678
+ private write;
679
+ /**
680
+ * Re-assert overrides after something else rewrote layer visibility. Only
681
+ * writes when the current value actually differs, so this doesn't feed
682
+ * itself through the `styledata` it triggers.
683
+ */
684
+ private reapply;
685
+ private styleLayers;
686
+ private visibilityOf;
687
+ /**
688
+ * MapLibre throws from these getters/setters while a style is mid-swap (the
689
+ * layer exists in `getStyle()` but its owner is being replaced). A debug tool
690
+ * that can break the map it's inspecting is worse than useless.
691
+ */
692
+ private safe;
693
+ }
694
+
695
+ type LayerAudit = {
696
+ /** `featureType` values the CMS permits for this customer. */
697
+ allowed: string[];
698
+ /** `featureType` values actually present in the loaded floors. */
699
+ inData: string[];
700
+ /** `featureType` values some theme layer filters on. */
701
+ inStyle: string[];
702
+ /**
703
+ * Drawn on a map but not in the customer's allowed list — a mis-authored
704
+ * or renamed layer. These render only by accident (if the theme happens to
705
+ * match the string) and are invisible otherwise.
706
+ */
707
+ unauthorized: string[];
708
+ /**
709
+ * Present in the data and allowed, but no theme layer filters on it. The
710
+ * author drew something the map will never show.
711
+ */
712
+ unstyled: string[];
713
+ /**
714
+ * The theme filters on it, but no loaded floor contains it. Dead weight in
715
+ * the style *for this venue* — another venue may well use it, so this is a
716
+ * prompt to check, not a delete list. Cross-reference `allowed`: a value
717
+ * that isn't in there either is dead everywhere for this customer.
718
+ */
719
+ unused: string[];
720
+ /**
721
+ * Allowed by the CMS but no theme rule matches it, whether or not this
722
+ * venue happens to draw it. The SDK's total blind spot — an author can
723
+ * legitimately draw any of these and get nothing.
724
+ */
725
+ allowedNotStyled: string[];
726
+ };
727
+
500
728
  type LoggerFn = (...args: unknown[]) => void;
501
729
  type AmenityManagerDeps = {
502
730
  getVenue: () => any;
@@ -559,8 +787,17 @@ declare class MinuteMaps {
559
787
  private floorsApi;
560
788
  private venue;
561
789
  private spriteKeys;
562
- private readonly debug;
790
+ private readonly debugEnabled;
563
791
  private readonly logger;
792
+ /**
793
+ * Console-facing layer inspector — `sdk.debug.hide('labels')`,
794
+ * `sdk.debug.solo('route')`, `sdk.debug.reset()`. Always present so demo
795
+ * code can drive it; additionally reachable as `window.mm.debug` when
796
+ * `options.debug` is on. See `DebugLayers`.
797
+ */
798
+ readonly debug: DebugLayers;
799
+ /** The `window` key `debug` mode installed this instance under, if any. */
800
+ private debugGlobalKey;
564
801
  private defaultCamera;
565
802
  private viewModes;
566
803
  /** Mirror of `config.options.reducedMotion`, mutable via `setReducedMotion`. */
@@ -616,10 +853,9 @@ declare class MinuteMaps {
616
853
  * visible as wayfinding reference. Restored on `clearHighlight`. */
617
854
  private static readonly DESTINATION_FOCUS_LAYERS;
618
855
  /** Categorical POI layers in the bundled theme that `setPOIFilter`
619
- * toggles. Layers absent from this list — `poi-you-are-here-*`, the
620
- * `poi-accessibility-icons` badge, and the `poi-highlight-*` layers
621
- * are intentionally unaffected; they're either anchors, status
622
- * indicators, or transient focus state, not categorical content. */
856
+ * toggles. Layers absent from this list — `poi-you-are-here-*` and the
857
+ * `poi-highlight-*` layers are intentionally unaffected; they're
858
+ * anchors or transient focus state, not categorical content. */
623
859
  private static readonly POI_CATEGORY_LAYERS;
624
860
  private poiVisibleTypes;
625
861
  constructor(config: SDKConfig);
@@ -676,6 +912,21 @@ declare class MinuteMaps {
676
912
  set3dEnabled(enabled: boolean): void;
677
913
  toggle3d(): void;
678
914
  getIs3dEnabled(): boolean;
915
+ /**
916
+ * (Re-)register per-amenity icons, per-destination logos, and the kiosk
917
+ * "you are here" icon. Needed both at init and after every `setTheme()`
918
+ * call — `map.setStyle(..., { diff: false })` tears down and recreates
919
+ * the whole `Style` object, which drops every image added at runtime via
920
+ * `map.addImage`. Only `route-arrow` re-registers itself lazily via
921
+ * `styleimagemissing`; everything else must be re-run explicitly here or
922
+ * it silently goes blank after a theme swap.
923
+ *
924
+ * `themeName === 'high-contrast'` recolors the amenity badge disc to
925
+ * `HIGH_CONTRAST_AMENITY_BADGE_COLOR`, leaving ring/glyph colors and
926
+ * connector (elevator/stairs/escalator) badges untouched. Failures per
927
+ * icon set are logged and skipped so one bad icon doesn't block the rest.
928
+ */
929
+ private registerRuntimeIcons;
679
930
  /**
680
931
  * Set the active map theme by name (`'default'` / `'high-contrast'`) or by
681
932
  * passing a custom `StyleSpecification`. The current floor, route, POIs
@@ -733,9 +984,9 @@ declare class MinuteMaps {
733
984
  getZoneForPOI(poi: POI): Zone | null;
734
985
  /** Human-readable detail fields for a POI info popover. Only surfaces
735
986
  * fields that exist on the current data — `category`, `floorName`,
736
- * `zoneName`, `keywords`, and `description` are each omitted when absent.
737
- * Keeps the display-field derivation (incl. the zone lookup) in the SDK
738
- * so consumers stay thin. */
987
+ * `zoneName`, `keywords`, `description`, and `imageUrl` are each omitted
988
+ * when absent. Keeps the display-field derivation (incl. the zone lookup)
989
+ * in the SDK so consumers stay thin. */
739
990
  getPOIDetails(poi: POI): {
740
991
  name: string;
741
992
  type: 'amenity' | 'destination' | 'kiosk';
@@ -745,12 +996,36 @@ declare class MinuteMaps {
745
996
  zoneDescription?: string;
746
997
  keywords?: string[];
747
998
  description?: string;
999
+ /** The destination's uploaded location image, ready for an `<img src>`.
1000
+ * Destinations only — amenities use sprite glyphs, not photos. Inline SVG
1001
+ * from `/all` comes back as a data URI; otherwise it's the uploaded uri
1002
+ * path. Absent when nothing was uploaded in the CMS. */
1003
+ imageUrl?: string;
748
1004
  };
749
1005
  /** Resolve the source Destination/Amenity record backing a rendered POI,
750
1006
  * for detail fields (category, localized description) that don't live on
751
1007
  * the built POI object. */
752
1008
  private getSourceEntity;
753
1009
  getPolygonLayers(): any[];
1010
+ /**
1011
+ * Cross-reference the venue's drawn layers against the customer's allowed
1012
+ * layer list (JACS `GET /customer/{id}/polygon-layer`) and against what the
1013
+ * active theme can actually render.
1014
+ *
1015
+ * Three failure modes, none of which is visible by looking at the map:
1016
+ * a layer drawn under a name the CMS doesn't list (`unauthorized`), a layer
1017
+ * legitimately drawn that no theme rule matches (`unstyled`), and a theme
1018
+ * rule with nothing to draw at this venue (`unused`). Runs automatically
1019
+ * once after `ready` when `options.debug` is on; call it directly —
1020
+ * `mm.validateMapLayers()` — any time.
1021
+ *
1022
+ * Only counts floors whose geojson has loaded. Init preloads the rest in
1023
+ * the background, so a call in the first moments after `ready` may report
1024
+ * fewer `inData` types than a call a second later.
1025
+ */
1026
+ validateMapLayers(): Promise<LayerAudit>;
1027
+ /** Debug-mode auto-run: log findings once, stay silent when clean. */
1028
+ private reportLayerAudit;
754
1029
  getFloorMapTemplate3d(floorId: string | number): any[];
755
1030
  getAllPOIs(floor?: Floor): POI[];
756
1031
  getYouAreHerePOI(floor?: Floor): POI | null;
@@ -993,6 +1268,19 @@ declare class MinuteMaps {
993
1268
  private findFloorForWaypoint;
994
1269
  getCameraPosition(): CameraState | null;
995
1270
  getMap(): Map | null;
1271
+ /**
1272
+ * Put this instance on `window` so a kiosk running in a browser can be
1273
+ * driven from devtools — `mm.debug.help()`, `mm.getMap()`, `mm.setTheme(…)`.
1274
+ * Debug builds only: nothing is exposed unless `options.debug` is on, and
1275
+ * `options.debugGlobal` renames the key (or `false` opts out entirely).
1276
+ *
1277
+ * Refuses to clobber a key that already holds something that isn't a
1278
+ * MinuteMaps — a kiosk shell with its own `window.mm` shouldn't lose it to
1279
+ * a dev-mode convenience.
1280
+ */
1281
+ private exposeDebugGlobal;
1282
+ /** Drop the `window` handle, but only if it still points at this instance. */
1283
+ private releaseDebugGlobal;
996
1284
  destroy(): void;
997
1285
  setCurrentFloor(floor: Floor): Promise<void>;
998
1286
  /**
@@ -1077,4 +1365,4 @@ declare function groupStepsIntoFloorSections(steps: WayfindStep[]): RouteFloorSe
1077
1365
  declare function activeSectionIndex(sections: RouteFloorSection[], activeStepIndex: number): number;
1078
1366
 
1079
1367
  export { MinuteMaps, activeSectionIndex, createMinuteMapsSDK, groupStepsIntoFloorSections };
1080
- export type { Amenity, AmenityBadgeStyle, AmenityWithFloor, Bounds, BoundsPadding, CameraState, Destination, DestinationChipStyle, EventCallback, Floor, FloorMetadata, JMapAuth, JMapConfig, JacsAuth, JacsConfig, MapEvent, POI, POISearchResult, RouteFloorSection, RoutePoint, RoutingOptions, SDKConfig, SDKOptions, ThemeName, TransitionStep, ViewOptions, WayfindCenterMode, WayfindStep, Waypoint, Zone };
1368
+ export type { Amenity, AmenityBadgeStyle, AmenityWithFloor, Bounds, BoundsPadding, CameraState, Destination, EventCallback, Floor, FloorMetadata, JMapAuth, JMapConfig, JacsAuth, JacsConfig, MapEvent, POI, POISearchResult, RouteFloorSection, RoutePoint, RoutingOptions, SDKConfig, SDKOptions, ThemeName, TransitionStep, ViewOptions, WayfindCenterMode, WayfindStep, Waypoint, Zone };