@mapvx/web-js 3.5.0-dev.1 → 3.5.0-dev.2

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 (31) hide show
  1. package/dist/cjs/controllers/routeController.js +221 -47
  2. package/dist/cjs/controllers/routeController.js.map +1 -1
  3. package/dist/cjs/domain/models/animation.js.map +1 -1
  4. package/dist/cjs/domain/models/marker.js +31 -0
  5. package/dist/cjs/domain/models/marker.js.map +1 -1
  6. package/dist/cjs/domain/models/routeInstance.js.map +1 -1
  7. package/dist/cjs/logger/sentry.js +1 -1
  8. package/dist/cjs/map/map.js +18 -10
  9. package/dist/cjs/map/map.js.map +1 -1
  10. package/dist/es/controllers/routeController.d.ts +14 -0
  11. package/dist/es/controllers/routeController.d.ts.map +1 -1
  12. package/dist/es/controllers/routeController.js +221 -47
  13. package/dist/es/controllers/routeController.js.map +1 -1
  14. package/dist/es/domain/models/animation.d.ts +19 -0
  15. package/dist/es/domain/models/animation.d.ts.map +1 -1
  16. package/dist/es/domain/models/animation.js.map +1 -1
  17. package/dist/es/domain/models/marker.d.ts +27 -0
  18. package/dist/es/domain/models/marker.d.ts.map +1 -1
  19. package/dist/es/domain/models/marker.js +31 -0
  20. package/dist/es/domain/models/marker.js.map +1 -1
  21. package/dist/es/domain/models/routeInstance.d.ts +11 -0
  22. package/dist/es/domain/models/routeInstance.d.ts.map +1 -1
  23. package/dist/es/domain/models/routeInstance.js.map +1 -1
  24. package/dist/es/logger/sentry.js +1 -1
  25. package/dist/es/map/map.d.ts +9 -0
  26. package/dist/es/map/map.d.ts.map +1 -1
  27. package/dist/es/map/map.js +18 -10
  28. package/dist/es/map/map.js.map +1 -1
  29. package/dist/umd/index.js +380 -156
  30. package/dist/umd/index.js.map +1 -1
  31. package/package.json +1 -1
package/dist/umd/index.js CHANGED
@@ -11249,7 +11249,7 @@ const extractSafariExtensionDetails = (func, filename) => {
11249
11249
  // exists only for the type-checker, so in the ES/CJS builds the identifier is
11250
11250
  // genuinely absent and a direct comparison throws ReferenceError at module load.
11251
11251
  // `typeof` is the only safe way to probe a possibly-undeclared global.
11252
- var sentry_SDK_VERSION = false ? 0 : "3.5.0-dev.1";
11252
+ var sentry_SDK_VERSION = false ? 0 : "3.5.0-dev.2";
11253
11253
  var DSN = false ? 0 : "https://872f598f020e3cd73a0933b562d24c81@sentry.mapvx.app/5";
11254
11254
 
11255
11255
  /**
@@ -11888,14 +11888,17 @@ function getBoundingBox(points) {
11888
11888
  function marker_typeof(o) { "@babel/helpers - typeof"; return marker_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, marker_typeof(o); }
11889
11889
  function marker_ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11890
11890
  function marker_objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? marker_ownKeys(Object(t), !0).forEach(function (r) { marker_defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : marker_ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11891
- function marker_defineProperty(e, r, t) { return (r = marker_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
11892
11891
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
11893
11892
  function _possibleConstructorReturn(t, e) { if (e && ("object" == marker_typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
11894
11893
  function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
11895
11894
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11895
+ function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
11896
+ function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }
11897
+ function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }
11896
11898
  function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
11897
11899
  function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
11898
11900
  function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
11901
+ function marker_defineProperty(e, r, t) { return (r = marker_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
11899
11902
  function marker_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
11900
11903
  function marker_defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, marker_toPropertyKey(o.key), o); } }
11901
11904
  function marker_createClass(e, r, t) { return r && marker_defineProperties(e.prototype, r), t && marker_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -12248,21 +12251,6 @@ var MarkerUtils = /*#__PURE__*/function () {
12248
12251
  * ```
12249
12252
  */
12250
12253
  var MarkerAttribute = /*#__PURE__*/function (_Marker) {
12251
- /**
12252
- * Unique identifier for the marker attribute.
12253
- * Used for marker management and identification.
12254
- */
12255
-
12256
- /**
12257
- * Geographic coordinates of the marker attribute.
12258
- * @see {@link LatLng} for coordinate structure
12259
- */
12260
-
12261
- /**
12262
- * Identifier of the floor where the marker attribute is located.
12263
- * Used for indoor navigation and floor-specific marker management.
12264
- */
12265
-
12266
12254
  /**
12267
12255
  * Resolved icon dimensions (defaults to {@link DEFAULT_ICON_SIZE_PX} square
12268
12256
  * when unspecified), matching whatever `MarkerUtils.createMarkerElement`
@@ -12338,6 +12326,33 @@ var MarkerAttribute = /*#__PURE__*/function (_Marker) {
12338
12326
  anchor: (_markerConfig$anchor = markerConfig.anchor) !== null && _markerConfig$anchor !== void 0 ? _markerConfig$anchor : "center",
12339
12327
  offset: [0, 0]
12340
12328
  }]);
12329
+ /**
12330
+ * Unique identifier for the marker attribute.
12331
+ * Used for marker management and identification.
12332
+ */
12333
+ /**
12334
+ * Geographic coordinates of the marker attribute.
12335
+ * @see {@link LatLng} for coordinate structure
12336
+ */
12337
+ /**
12338
+ * Identifier of the floor where the marker attribute is located.
12339
+ * Used for indoor navigation and floor-specific marker management.
12340
+ */
12341
+ /**
12342
+ * True while this marker is hidden on purpose, via {@link hide} (or {@link changeFloor}
12343
+ * resolving to a floor this marker is not on).
12344
+ *
12345
+ * DOM connectivity cannot answer this: {@link hide} works by calling maplibre's
12346
+ * `Marker.remove()`, which detaches the element, so a hidden marker and one that never got
12347
+ * attached look identical from `getElement().isConnected`. Anything that re-attaches a marker
12348
+ * it does not own — the route animation re-attaches its arrow when a step transition drops it —
12349
+ * has to consult this flag, or it silently un-hides the marker on its next frame.
12350
+ *
12351
+ * Any attach clears it — see the {@link addTo} override — so "attached" and "not hidden"
12352
+ * never disagree, whichever entry point put the marker back on the map.
12353
+ * @internal
12354
+ */
12355
+ marker_defineProperty(_this, "hiddenOnPurpose", false);
12341
12356
  _this.setLngLat([markerConfig.coordinate.lng, markerConfig.coordinate.lat]);
12342
12357
  _this.setRotationAlignment((_markerConfig$rotatio = markerConfig.rotationAlignment) !== null && _markerConfig$rotatio !== void 0 ? _markerConfig$rotatio : "viewport");
12343
12358
  _this.setPitchAlignment("viewport");
@@ -12499,6 +12514,7 @@ var MarkerAttribute = /*#__PURE__*/function (_Marker) {
12499
12514
  }, {
12500
12515
  key: "hide",
12501
12516
  value: function hide() {
12517
+ this.hiddenOnPurpose = true;
12502
12518
  this.remove();
12503
12519
  }
12504
12520
 
@@ -12519,6 +12535,24 @@ var MarkerAttribute = /*#__PURE__*/function (_Marker) {
12519
12535
  this.addTo(map);
12520
12536
  }
12521
12537
 
12538
+ /**
12539
+ * Attaches the marker, clearing {@link hiddenOnPurpose}.
12540
+ *
12541
+ * Overridden so every attach path agrees on visibility: {@link show}, {@link addToMap} and a
12542
+ * direct `addTo` all funnel through here, so a marker cannot end up on the map while still
12543
+ * flagged as deliberately hidden — which would make the route animation refuse to restore an
12544
+ * arrow that is in fact visible.
12545
+ *
12546
+ * @param map - The map instance to attach the marker to.
12547
+ * @returns This marker, for chaining, as maplibre's `Marker.addTo` does.
12548
+ */
12549
+ }, {
12550
+ key: "addTo",
12551
+ value: function addTo(map) {
12552
+ this.hiddenOnPurpose = false;
12553
+ return _superPropGet(MarkerAttribute, "addTo", this, 3)([map]);
12554
+ }
12555
+
12522
12556
  /**
12523
12557
  * Hides marker if currentFloor is different from the marker floor.
12524
12558
  * Used for floor-based marker visibility management.
@@ -13280,6 +13314,32 @@ var DEFAULT_AUTO_FIT_PADDING = {
13280
13314
  left: 150
13281
13315
  };
13282
13316
 
13317
+ /**
13318
+ * Longest gap between two frames, in milliseconds, that still counts as
13319
+ * animation time.
13320
+ *
13321
+ * The frame loop charges the marker for however much wall clock has elapsed,
13322
+ * which is what makes a step take `stepTime` at any frame rate. A gap larger
13323
+ * than any frame rate can explain is not slow rendering, though — it is time
13324
+ * the animation did not run at all. `requestAnimationFrame` does not fire in a
13325
+ * backgrounded tab, so the first frame after the page comes back carries the
13326
+ * entire absence, and charging it advanced the draw by the whole gap: one
13327
+ * frame 10 s late at 50 m/s consumed exactly a hundred vertices in a single
13328
+ * `setData`, with the camera following the line as it jumped.
13329
+ *
13330
+ * Such a gap is therefore not charged (see `animateStep`). This is deliberately
13331
+ * NOT a clamp on how far one frame may advance: clamping would cap the catch-up
13332
+ * and hand back the frame-rate independence this loop exists to provide, and it
13333
+ * would still be wrong — the marker would sprint to catch up through time
13334
+ * nobody watched. Skipping the gap instead is what a pause does, which is what
13335
+ * an absence is.
13336
+ *
13337
+ * 500 ms is two frames per second. Real rendering does not sustain anything
13338
+ * near that low, so the threshold only ever separates absence from rendering,
13339
+ * and never shortens the catch-up of a genuinely slow frame.
13340
+ */
13341
+ var MAX_FRAME_GAP_MS = 500;
13342
+
13283
13343
  /**
13284
13344
  * Represents the controller for routes on the map.
13285
13345
  * Supports multiple simultaneous routes with independent customizations,
@@ -13310,12 +13370,18 @@ var RouteController = /*#__PURE__*/function () {
13310
13370
 
13311
13371
  /**
13312
13372
  * Add MapLibre sources and layers for a single route instance.
13373
+ *
13374
+ * All three sources set `lineMetrics`: maplibre computes `line-progress` only
13375
+ * when a source asks it to, and `preparePaintForLayer` emits a
13376
+ * `line-progress` gradient for a GradientStyle. Without it, a consumer
13377
+ * setting a gradient route style silently got no gradient at all.
13313
13378
  */
13314
13379
  }, {
13315
13380
  key: "addSourcesAndLayersForRoute",
13316
13381
  value: function addSourcesAndLayersForRoute(instance) {
13317
13382
  this.map.addSource(instance.aheadId, {
13318
13383
  type: "geojson",
13384
+ lineMetrics: true,
13319
13385
  data: instance.aheadSourceData
13320
13386
  });
13321
13387
  this.map.addLayer({
@@ -13329,6 +13395,7 @@ var RouteController = /*#__PURE__*/function () {
13329
13395
  });
13330
13396
  this.map.addSource(instance.behindId, {
13331
13397
  type: "geojson",
13398
+ lineMetrics: true,
13332
13399
  data: instance.behindSourceData
13333
13400
  });
13334
13401
  this.map.addLayer({
@@ -13342,6 +13409,7 @@ var RouteController = /*#__PURE__*/function () {
13342
13409
  });
13343
13410
  this.map.addSource(instance.currentId, {
13344
13411
  type: "geojson",
13412
+ lineMetrics: true,
13345
13413
  data: instance.currentSourceData
13346
13414
  });
13347
13415
  this.map.addLayer({
@@ -13701,9 +13769,12 @@ var RouteController = /*#__PURE__*/function () {
13701
13769
  value: function updateLayerFilter(layerId, floorId) {
13702
13770
  var newFloorId = floorId !== null && floorId !== void 0 ? floorId : this.mapvxMap.getCurrentFloor();
13703
13771
  if (newFloorId === undefined) return;
13704
- if (this.map.getStyle().layers.some(function (layer) {
13705
- return layer.id === layerId;
13706
- })) {
13772
+ // `getLayer` is a map lookup; `getStyle()` serialises every source and
13773
+ // layer in the style just to answer the same question. This runs three
13774
+ // times per route per floor change, and each preceding `setFilter`
13775
+ // invalidates maplibre's serialised-layer cache, so the later calls used to
13776
+ // re-serialise from scratch.
13777
+ if (this.map.getLayer(layerId) != null) {
13707
13778
  this.map.setFilter(layerId, ["==", ["get", "floor_key"], newFloorId]);
13708
13779
  }
13709
13780
  }
@@ -13822,13 +13893,20 @@ var RouteController = /*#__PURE__*/function () {
13822
13893
  }, {
13823
13894
  key: "updateRouteMarkerVisibility",
13824
13895
  value: function updateRouteMarkerVisibility(floorId) {
13896
+ // An outdoor step gives its marker an empty floorId, which never equals a
13897
+ // real floor key — so on a venue with buildings the route arrow used to be
13898
+ // hidden the moment the map filtered by one, and only reappeared because
13899
+ // the animation re-attached the marker on its next frame. Outdoors is an
13900
+ // allowance markers and circles already make; the route arrow makes it too.
13901
+ var isOutdoor = this.mapvxMap.isOutdoorFloor(floorId);
13825
13902
  var _iterator7 = routeController_createForOfIteratorHelper(this.routes.values()),
13826
13903
  _step7;
13827
13904
  try {
13828
13905
  for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
13829
- var _instance$routeMarker, _instance$routeMarker2, _instance$routeMarker3;
13906
+ var _instance$routeMarker, _instance$routeMarker2, _instance$routeMarker3, _instance$routeMarker4;
13830
13907
  var instance = _step7.value;
13831
- ((_instance$routeMarker = instance.routeMarker) === null || _instance$routeMarker === void 0 ? void 0 : _instance$routeMarker.floorId) === floorId ? (_instance$routeMarker2 = instance.routeMarker) === null || _instance$routeMarker2 === void 0 ? void 0 : _instance$routeMarker2.show(this.map) : (_instance$routeMarker3 = instance.routeMarker) === null || _instance$routeMarker3 === void 0 ? void 0 : _instance$routeMarker3.hide();
13908
+ var markerFloorId = (_instance$routeMarker = (_instance$routeMarker2 = instance.routeMarker) === null || _instance$routeMarker2 === void 0 ? void 0 : _instance$routeMarker2.floorId) !== null && _instance$routeMarker !== void 0 ? _instance$routeMarker : "";
13909
+ markerFloorId === floorId || isOutdoor && markerFloorId === "" ? (_instance$routeMarker3 = instance.routeMarker) === null || _instance$routeMarker3 === void 0 ? void 0 : _instance$routeMarker3.show(this.map) : (_instance$routeMarker4 = instance.routeMarker) === null || _instance$routeMarker4 === void 0 ? void 0 : _instance$routeMarker4.hide();
13832
13910
  }
13833
13911
  } catch (err) {
13834
13912
  _iterator7.e(err);
@@ -13840,10 +13918,10 @@ var RouteController = /*#__PURE__*/function () {
13840
13918
  key: "updatePlaceFloorForRouting",
13841
13919
  value: function updatePlaceFloorForRouting(instance, placeId, floorKey) {
13842
13920
  if (placeId && floorKey) {
13843
- var _instance$routeMarker4;
13921
+ var _instance$routeMarker5;
13844
13922
  this.mapvxMap.updatePlaceAndFloorForRouting(placeId, floorKey);
13845
13923
  this.updateRouteLayers(floorKey);
13846
- (_instance$routeMarker4 = instance.routeMarker) === null || _instance$routeMarker4 === void 0 || _instance$routeMarker4.setFloor(floorKey);
13924
+ (_instance$routeMarker5 = instance.routeMarker) === null || _instance$routeMarker5 === void 0 || _instance$routeMarker5.setFloor(floorKey);
13847
13925
  this.updateRouteMarkerVisibility(floorKey);
13848
13926
  }
13849
13927
  }
@@ -13858,8 +13936,8 @@ var RouteController = /*#__PURE__*/function () {
13858
13936
  key: "startAnimating",
13859
13937
  value: function startAnimating(route, drawConfig, animationConfig) {
13860
13938
  var _animationConfig$auto,
13861
- _animationConfig$call,
13862
- _this2 = this;
13939
+ _this2 = this,
13940
+ _animationConfig$call;
13863
13941
  var instance = createRouteInstance(route);
13864
13942
  this.routes.set(instance.id, instance);
13865
13943
  this.lastAddedRouteId = instance.id;
@@ -13897,10 +13975,13 @@ var RouteController = /*#__PURE__*/function () {
13897
13975
  this.mapvxMap.fitRouteByPlace(route, firstStep.startInsidePlace, fitOptions);
13898
13976
  }
13899
13977
  }
13900
- (_animationConfig$call = animationConfig.callBack) === null || _animationConfig$call === void 0 || _animationConfig$call.call(animationConfig, {
13901
- isFinished: false,
13902
- step: firstStep
13903
- });
13978
+
13979
+ // The conditions go in before the consumer hears about the start, for the same reason
13980
+ // `restartAnimation` orders it that way. `animationStatus` is already "STARTED" here, so a
13981
+ // consumer that pauses from inside this callback — showing a modal per step, say — passed
13982
+ // `internalPause`'s status guard and then died on its `instance.conditions == null` check:
13983
+ // the pause was dropped in silence, the loop kept running, and because the status stayed
13984
+ // "STARTED" the matching `resumeAnimation()` bailed out too.
13904
13985
  instance.conditions = {
13905
13986
  index: 0,
13906
13987
  coordinatesIndex: 0,
@@ -13917,13 +13998,17 @@ var RouteController = /*#__PURE__*/function () {
13917
13998
  return _this2.prepareForNextStep(time, instance);
13918
13999
  }
13919
14000
  };
14001
+ (_animationConfig$call = animationConfig.callBack) === null || _animationConfig$call === void 0 || _animationConfig$call.call(animationConfig, {
14002
+ isFinished: false,
14003
+ step: firstStep
14004
+ });
13920
14005
  this.syncRouteCollision();
13921
14006
  }
13922
14007
  }, {
13923
14008
  key: "clearRouteInstance",
13924
14009
  value: function clearRouteInstance(instance) {
13925
- var _instance$routeMarker5;
13926
- (_instance$routeMarker5 = instance.routeMarker) === null || _instance$routeMarker5 === void 0 || _instance$routeMarker5.remove();
14010
+ var _instance$routeMarker6;
14011
+ (_instance$routeMarker6 = instance.routeMarker) === null || _instance$routeMarker6 === void 0 || _instance$routeMarker6.remove();
13927
14012
  instance.routeMarker = undefined;
13928
14013
  this.setSourceData(instance, instance.aheadId, []);
13929
14014
  this.setSourceData(instance, instance.behindId, []);
@@ -14046,9 +14131,9 @@ var RouteController = /*#__PURE__*/function () {
14046
14131
  value: function restartAnimation(routeId) {
14047
14132
  var _this$setMarkerRotati,
14048
14133
  _instance$animationCo,
14134
+ _this4 = this,
14049
14135
  _instance$animationCo3,
14050
- _instance$animationCo4,
14051
- _this4 = this;
14136
+ _instance$animationCo4;
14052
14137
  var instance = this.resolveInstance(routeId);
14053
14138
  if (!instance) {
14054
14139
  throw new Error("Does not exist animated route to restart");
@@ -14086,10 +14171,15 @@ var RouteController = /*#__PURE__*/function () {
14086
14171
  this.mapvxMap.fitRouteByPlace(instance.route, firstStep.startInsidePlace, fitOptions);
14087
14172
  }
14088
14173
  }
14089
- (_instance$animationCo3 = (_instance$animationCo4 = instance.animationConfig).callBack) === null || _instance$animationCo3 === void 0 || _instance$animationCo3.call(_instance$animationCo4, {
14090
- isFinished: false,
14091
- step: firstStep
14092
- });
14174
+
14175
+ // The new conditions go in before the consumer hears about the restart.
14176
+ // Invoking the callback first left `instance.conditions` pointing at the
14177
+ // previous run, so a consumer that pauses from inside it — showing a modal
14178
+ // per step, say — cancelled a frame id that had already fired, marked the
14179
+ // instance PAUSED, and then had a live loop installed underneath it. The
14180
+ // next resume passed the "not paused" guard and started a second loop on
14181
+ // the same instance; each schedules its own successor, so the doubling was
14182
+ // permanent.
14093
14183
  instance.conditions = {
14094
14184
  index: 0,
14095
14185
  coordinatesIndex: 0,
@@ -14106,6 +14196,10 @@ var RouteController = /*#__PURE__*/function () {
14106
14196
  return _this4.prepareForNextStep(time, instance);
14107
14197
  }
14108
14198
  };
14199
+ (_instance$animationCo3 = (_instance$animationCo4 = instance.animationConfig).callBack) === null || _instance$animationCo3 === void 0 || _instance$animationCo3.call(_instance$animationCo4, {
14200
+ isFinished: false,
14201
+ step: firstStep
14202
+ });
14109
14203
  }
14110
14204
 
14111
14205
  /**
@@ -14134,8 +14228,8 @@ var RouteController = /*#__PURE__*/function () {
14134
14228
  key: "addStepAnimation",
14135
14229
  value: function addStepAnimation(route, drawConfig, animationConfig) {
14136
14230
  var _animationConfig$auto3,
14137
- _animationConfig$call2,
14138
- _this5 = this;
14231
+ _this5 = this,
14232
+ _animationConfig$call4;
14139
14233
  var instance = createRouteInstance(route);
14140
14234
  this.routes.set(instance.id, instance);
14141
14235
  this.lastAddedRouteId = instance.id;
@@ -14171,10 +14265,12 @@ var RouteController = /*#__PURE__*/function () {
14171
14265
  this.mapvxMap.fitRouteByPlace(route, firstStep.startInsidePlace, fitOptions);
14172
14266
  }
14173
14267
  }
14174
- (_animationConfig$call2 = animationConfig.callBack) === null || _animationConfig$call2 === void 0 || _animationConfig$call2.call(animationConfig, {
14175
- isFinished: false,
14176
- step: firstStep
14177
- });
14268
+
14269
+ // The conditions go in before the consumer hears about the route, as they
14270
+ // do in `startAnimating`. Invoking the callback first left `conditions`
14271
+ // undefined, so a consumer advancing the route from it — the step-by-step
14272
+ // integration draws its first step this way — hit `nextStepAnimation`'s
14273
+ // null check and got an exception instead of a step.
14178
14274
  instance.conditions = {
14179
14275
  index: 0,
14180
14276
  coordinatesIndex: 0,
@@ -14199,8 +14295,16 @@ var RouteController = /*#__PURE__*/function () {
14199
14295
  _this5.setSourceData(instance, instance.aheadId, aheadSteps);
14200
14296
  _this5.setCurrentSourceData(instance, step);
14201
14297
  instance.conditions.index = index;
14298
+
14299
+ // The status settles before either callback, as everywhere else: no frame
14300
+ // is live once `animateStep` hands over to `onFinish`, so "WAITING" is
14301
+ // already true here. Writing it afterwards overwrote the "ANIMATING" of a
14302
+ // consumer that chained the next step from this callback, and the
14303
+ // following `nextStepAnimation` then skipped its cancel and installed a
14304
+ // second self-sustaining loop on the same instance.
14305
+ instance.stepAnimationStatus = "WAITING";
14202
14306
  if (index < route.steps.length) {
14203
- var _animationConfig$auto5, _animationConfig$call3;
14307
+ var _animationConfig$auto5, _animationConfig$call2;
14204
14308
  var nextStep = route.steps[index];
14205
14309
 
14206
14310
  // Auto-fit by place if enabled and place changed
@@ -14215,20 +14319,23 @@ var RouteController = /*#__PURE__*/function () {
14215
14319
  _this5.mapvxMap.fitRouteByPlace(instance.route, stepPlaceId, _fitOptions);
14216
14320
  }
14217
14321
  }
14218
- (_animationConfig$call3 = animationConfig.callBack) === null || _animationConfig$call3 === void 0 || _animationConfig$call3.call(animationConfig, {
14322
+ (_animationConfig$call2 = animationConfig.callBack) === null || _animationConfig$call2 === void 0 || _animationConfig$call2.call(animationConfig, {
14219
14323
  isFinished: false,
14220
14324
  step: nextStep
14221
14325
  });
14222
14326
  } else {
14223
- var _animationConfig$call4;
14224
- (_animationConfig$call4 = animationConfig.callBack) === null || _animationConfig$call4 === void 0 || _animationConfig$call4.call(animationConfig, {
14327
+ var _animationConfig$call3;
14328
+ (_animationConfig$call3 = animationConfig.callBack) === null || _animationConfig$call3 === void 0 || _animationConfig$call3.call(animationConfig, {
14225
14329
  isFinished: true,
14226
14330
  step: null
14227
14331
  });
14228
14332
  }
14229
- instance.stepAnimationStatus = "WAITING";
14230
14333
  }
14231
14334
  };
14335
+ (_animationConfig$call4 = animationConfig.callBack) === null || _animationConfig$call4 === void 0 || _animationConfig$call4.call(animationConfig, {
14336
+ isFinished: false,
14337
+ step: firstStep
14338
+ });
14232
14339
  this.syncRouteCollision();
14233
14340
  }
14234
14341
 
@@ -14347,7 +14454,7 @@ var RouteController = /*#__PURE__*/function () {
14347
14454
  }, {
14348
14455
  key: "centerOnCurrentStep",
14349
14456
  value: function centerOnCurrentStep(routeId) {
14350
- var _instance$routeMarker6;
14457
+ var _instance$routeMarker7;
14351
14458
  var instance = this.resolveInstance(routeId);
14352
14459
  if (!instance) {
14353
14460
  throw new Error("Error: Does not exist step animation");
@@ -14358,7 +14465,7 @@ var RouteController = /*#__PURE__*/function () {
14358
14465
  if (instance.conditions == null || instance.animationConfig == null || instance.route == null) {
14359
14466
  throw new Error("Error: conditions, animationConfig or route should not be null at this point");
14360
14467
  }
14361
- var currentMarkerPosition = (_instance$routeMarker6 = instance.routeMarker) === null || _instance$routeMarker6 === void 0 ? void 0 : _instance$routeMarker6.getLngLat();
14468
+ var currentMarkerPosition = (_instance$routeMarker7 = instance.routeMarker) === null || _instance$routeMarker7 === void 0 ? void 0 : _instance$routeMarker7.getLngLat();
14362
14469
  if (currentMarkerPosition) {
14363
14470
  this.map.panTo(currentMarkerPosition);
14364
14471
  } else {
@@ -14413,12 +14520,19 @@ var RouteController = /*#__PURE__*/function () {
14413
14520
  });
14414
14521
  } else {
14415
14522
  var _instance$animationCo11, _instance$animationCo12;
14416
- // finishes animation
14523
+ // The status settles before the consumer hears that the route finished,
14524
+ // for the same reason `startAnimating` and `restartAnimation` order it
14525
+ // that way. A consumer that relaunches from this callback — looping a
14526
+ // kiosk demo is the ordinary case — got its fresh "STARTED" overwritten
14527
+ // by the "FINISHED" written afterwards, and was left with a live loop the
14528
+ // controller believed was over: `pauseAnimation` and `stopAnimation` both
14529
+ // bailed on the status guard, and the next `restartAnimation` skipped its
14530
+ // cancel and installed a second self-sustaining loop.
14531
+ instance.animationStatus = "FINISHED";
14417
14532
  (_instance$animationCo11 = (_instance$animationCo12 = instance.animationConfig).callBack) === null || _instance$animationCo11 === void 0 || _instance$animationCo11.call(_instance$animationCo12, {
14418
14533
  isFinished: true,
14419
14534
  step: null
14420
14535
  });
14421
- instance.animationStatus = "FINISHED";
14422
14536
  }
14423
14537
  }
14424
14538
  }, {
@@ -14431,19 +14545,25 @@ var RouteController = /*#__PURE__*/function () {
14431
14545
  var _instance$conditions = instance.conditions,
14432
14546
  startTime = _instance$conditions.startTime,
14433
14547
  resetTime = _instance$conditions.resetTime,
14434
- progress = _instance$conditions.progress;
14548
+ progress = _instance$conditions.progress,
14549
+ waitStartTime = _instance$conditions.waitStartTime;
14435
14550
  var _instance$conditions2 = instance.conditions,
14436
14551
  coordinatesIndex = _instance$conditions2.coordinatesIndex,
14437
14552
  iconRotation = _instance$conditions2.iconRotation,
14438
14553
  index = _instance$conditions2.index,
14439
14554
  onFinish = _instance$conditions2.onFinish,
14440
- rotatingIcon = _instance$conditions2.rotatingIcon,
14441
- waitStartTime = _instance$conditions2.waitStartTime;
14555
+ rotatingIcon = _instance$conditions2.rotatingIcon;
14442
14556
  var _instance$animationCo13 = instance.animationConfig,
14443
14557
  stepTime = _instance$animationCo13.stepTime,
14444
14558
  minimumSpeed = _instance$animationCo13.minimumSpeed,
14445
14559
  iconRotationTime = _instance$animationCo13.iconRotationTime,
14446
14560
  changeFloorTime = _instance$animationCo13.changeFloorTime;
14561
+
14562
+ // How long this frame took to arrive. Recorded before any early return, so
14563
+ // the next frame measures from the last one delivered rather than from the
14564
+ // last one that drew.
14565
+ var previousFrameTime = instance.conditions.lastFrameTime;
14566
+ instance.conditions.lastFrameTime = timestamp;
14447
14567
  if (startTime == null) {
14448
14568
  instance.conditions.startTime = timestamp;
14449
14569
  instance.conditions.animationId = requestAnimationFrame(function (time) {
@@ -14456,10 +14576,35 @@ var RouteController = /*#__PURE__*/function () {
14456
14576
  instance.conditions.startTime = startTime;
14457
14577
  resetTime = false;
14458
14578
  instance.conditions.resetTime = resetTime;
14579
+ } else if (previousFrameTime != null && timestamp - previousFrameTime > MAX_FRAME_GAP_MS) {
14580
+ // Absence, not slow rendering: see MAX_FRAME_GAP_MS. Shift the clock
14581
+ // forward by the gap instead of charging it, exactly as resuming from a
14582
+ // pause does above, so this frame redraws where the last one left off
14583
+ // and the next resumes from there.
14584
+ var gap = timestamp - previousFrameTime;
14585
+ // What the previous frame had charged. Equal to `progress` whenever the
14586
+ // two are in step, but the rotation branches above set `startTime` to
14587
+ // the frame timestamp without resetting `progress`, so reading the
14588
+ // stored value would carry a whole rotation's worth of time into the
14589
+ // first frame back. Recomputed instead, which is 0 in exactly that case.
14590
+ progress = previousFrameTime - startTime;
14591
+ instance.conditions.progress = progress;
14592
+ startTime = timestamp - progress;
14593
+ instance.conditions.startTime = startTime;
14594
+ // The floor-change wait runs on the raw timestamp rather than on
14595
+ // `progress`, so it needs the same shift or an absence would satisfy it
14596
+ // outright.
14597
+ if (waitStartTime != null) {
14598
+ waitStartTime += gap;
14599
+ instance.conditions.waitStartTime = waitStartTime;
14600
+ }
14459
14601
  } else {
14460
14602
  progress = timestamp - startTime;
14461
14603
  instance.conditions.progress = progress;
14462
14604
  }
14605
+
14606
+ // Not const: the segment loop below rewinds it as it charges the clock for
14607
+ // each segment it consumes within the frame.
14463
14608
  var progressInSeconds = progress / 1000;
14464
14609
  var step = instance.route.steps[index];
14465
14610
  if (step.coordinates.length <= 0) {
@@ -14469,7 +14614,6 @@ var RouteController = /*#__PURE__*/function () {
14469
14614
  var start = step.coordinates[coordinatesIndex];
14470
14615
  var end = step.coordinates[coordinatesIndex + 1];
14471
14616
  if (start != null && end != null) {
14472
- var _instance$routeMarker8;
14473
14617
  if (rotatingIcon) {
14474
14618
  var angle = NavFunctions.bearingInDegBetween(start, end);
14475
14619
  if (iconRotationTime === 0 || instance.conditions.nextFloorFirstStepIndex === index || Math.abs(angle - instance.conditions.iconRotation) < 15) {
@@ -14521,43 +14665,101 @@ var RouteController = /*#__PURE__*/function () {
14521
14665
  return;
14522
14666
  }
14523
14667
  }
14524
- var distance = NavFunctions.distance(start, end);
14525
14668
  var speed = Math.max(step.distance / stepTime, minimumSpeed !== null && minimumSpeed !== void 0 ? minimumSpeed : 0);
14526
- if (speed * progressInSeconds > distance) {
14527
- instance.currentSourceData.geometry.coordinates.push([end.lng, end.lat]);
14528
- var _source = this.map.getSource(instance.currentId);
14529
- _source === null || _source === void 0 || _source.setData(instance.currentSourceData);
14530
- if (coordinatesIndex + 2 < step.coordinates.length) {
14531
- var next = step.coordinates[coordinatesIndex + 2];
14532
- if (!compareLatLng(end, next)) {
14533
- if (instance.conditions.isStepByStep) {
14534
- instance.conditions.rotatingIcon = true;
14535
- } else {
14536
- var _instance$routeMarker7;
14537
- var nextAngle = NavFunctions.bearingInDegBetween(end, next);
14538
- instance.conditions.iconRotation = nextAngle;
14539
- (_instance$routeMarker7 = instance.routeMarker) === null || _instance$routeMarker7 === void 0 || _instance$routeMarker7.setRotation(nextAngle);
14540
- }
14541
- }
14542
- instance.conditions.startTime = timestamp;
14543
- instance.conditions.progress = 0;
14544
- instance.conditions.coordinatesIndex++;
14545
- instance.conditions.animationId = requestAnimationFrame(function (time) {
14546
- return _this8.animateStep(time, instance);
14547
- });
14548
- return;
14549
- } else {
14669
+
14670
+ // Consume every whole segment the elapsed time pays for inside this one
14671
+ // frame, carrying the sub-segment remainder into the next.
14672
+ //
14673
+ // Advancing a single vertex per frame — and restarting the clock at each
14674
+ // one, which threw the overshoot away — made a step's duration depend on
14675
+ // the frame rate: it cost `stepTime` plus up to one frame per vertex,
14676
+ // and once `speed * frameInterval` exceeded a segment's length it
14677
+ // ignored `stepTime` altogether and collapsed to `vertexCount / fps`.
14678
+ // Encoded polylines quantise near 1.1 m, so that regime was the common
14679
+ // one, not the corner case.
14680
+ var segmentStart = start;
14681
+ var segmentEnd = end;
14682
+ var segmentDistance = NavFunctions.distance(segmentStart, segmentEnd);
14683
+
14684
+ // Drop the previous frame's interpolated tip before committing anything.
14685
+ // Coordinates up to and including the current vertex are settled geometry
14686
+ // — exactly `coordinatesIndex + 1` of them — and the tip is a single
14687
+ // moving point after them, re-placed at the end of this frame. Appending
14688
+ // one per frame instead grew the drawn line with elapsed frames, well
14689
+ // past the polyline's own vertex count, and `setData` re-indexed every
14690
+ // one of those points on the next frame.
14691
+ var coordinates = instance.currentSourceData.geometry.coordinates;
14692
+ coordinates.length = Math.min(coordinates.length, instance.conditions.coordinatesIndex + 1);
14693
+ while (speed * progressInSeconds > segmentDistance) {
14694
+ coordinates.push([segmentEnd.lng, segmentEnd.lat]);
14695
+ if (instance.conditions.coordinatesIndex + 2 >= step.coordinates.length) {
14696
+ this.flushCurrentSourceData(instance);
14550
14697
  onFinish === null || onFinish === void 0 || onFinish(timestamp);
14551
14698
  return;
14552
14699
  }
14700
+
14701
+ // Charge the clock exactly what this segment cost instead of
14702
+ // restarting it, so no time is lost at a vertex.
14703
+ var segmentMs = segmentDistance / speed * 1000;
14704
+ startTime += segmentMs;
14705
+ progress -= segmentMs;
14706
+ instance.conditions.startTime = startTime;
14707
+ instance.conditions.progress = progress;
14708
+ progressInSeconds = progress / 1000;
14709
+ instance.conditions.coordinatesIndex++;
14710
+ var next = step.coordinates[instance.conditions.coordinatesIndex + 1];
14711
+ if (!compareLatLng(segmentEnd, next)) {
14712
+ var _instance$routeMarker8;
14713
+ if (instance.conditions.isStepByStep) {
14714
+ // Step-by-step mode animates the turn itself, on the rotation
14715
+ // branch of the next frame. Stop consuming segments and let it.
14716
+ //
14717
+ // The clock restarts here because the rotation branch measures its
14718
+ // own progress from `startTime`, and every other transition into it
14719
+ // resets too (see `prepareForNextStep` and the floor-change hand-off).
14720
+ // Carrying this frame's leftover sub-segment time over instead
14721
+ // started the turn already part-way through — or skipped it outright
14722
+ // once the remainder exceeded `iconRotationTime`. Before the segment
14723
+ // loop existed the per-vertex path reset it as well.
14724
+ instance.conditions.rotatingIcon = true;
14725
+ instance.conditions.startTime = timestamp;
14726
+ instance.conditions.progress = 0;
14727
+ this.flushCurrentSourceData(instance);
14728
+ instance.conditions.animationId = requestAnimationFrame(function (time) {
14729
+ return _this8.animateStep(time, instance);
14730
+ });
14731
+ return;
14732
+ }
14733
+ var nextAngle = NavFunctions.bearingInDegBetween(segmentEnd, next);
14734
+ instance.conditions.iconRotation = nextAngle;
14735
+ (_instance$routeMarker8 = instance.routeMarker) === null || _instance$routeMarker8 === void 0 || _instance$routeMarker8.setRotation(nextAngle);
14736
+ }
14737
+ segmentStart = segmentEnd;
14738
+ segmentEnd = next;
14739
+ segmentDistance = NavFunctions.distance(segmentStart, segmentEnd);
14553
14740
  }
14554
- var fraction = speed * progressInSeconds / distance;
14555
- var point = distance === 0 ? end : NavFunctions.intermediatePointBetween(start, end, Math.min(fraction, 1));
14556
- instance.currentSourceData.geometry.coordinates.push([point.lng, point.lat]);
14557
- var source = this.map.getSource(instance.currentId);
14558
- source === null || source === void 0 || source.setData(instance.currentSourceData);
14741
+ var fraction = speed * progressInSeconds / segmentDistance;
14742
+ var point = segmentDistance === 0 ? segmentEnd : NavFunctions.intermediatePointBetween(segmentStart, segmentEnd, Math.min(fraction, 1));
14743
+ coordinates.push([point.lng, point.lat]);
14744
+ this.flushCurrentSourceData(instance);
14559
14745
  this.setMarkerLngLat(instance, point);
14560
- (_instance$routeMarker8 = instance.routeMarker) === null || _instance$routeMarker8 === void 0 || _instance$routeMarker8.addTo(this.map);
14746
+ // Only when it has genuinely left the DOM. maplibre's `Marker.addTo`
14747
+ // opens with `remove()`, so re-attaching an attached marker tears down
14748
+ // and rebuilds 13 map listeners and detaches and re-appends the element.
14749
+ // Unconditionally, that ran every frame — and quietly undid
14750
+ // `updateRouteMarkerVisibility` hiding the arrow, which is the bug it was
14751
+ // really covering for.
14752
+ //
14753
+ // `isConnected` alone cannot express that: `hide()` detaches the element
14754
+ // through maplibre's `Marker.remove()`, so a marker hidden by a floor
14755
+ // change reads as disconnected and was re-attached on the very next
14756
+ // frame — the arrow reappeared on the wrong floor. Hidden-ness is an
14757
+ // intent, so it is read from the flag `hide()`/`show()` maintain, and
14758
+ // `isConnected` is left to answer only what it can: whether a marker
14759
+ // nobody hid has fallen out of the DOM (a step transition removing it).
14760
+ if (instance.routeMarker != null && !instance.routeMarker.hiddenOnPurpose && !instance.routeMarker.getElement().isConnected) {
14761
+ instance.routeMarker.addTo(this.map);
14762
+ }
14561
14763
  instance.conditions.animationId = requestAnimationFrame(function (time) {
14562
14764
  return _this8.animateStep(time, instance);
14563
14765
  });
@@ -14567,6 +14769,21 @@ var RouteController = /*#__PURE__*/function () {
14567
14769
  return;
14568
14770
  }
14569
14771
  }
14772
+
14773
+ /**
14774
+ * Pushes the in-progress segment's geometry to its map source.
14775
+ *
14776
+ * Called once per frame rather than once per vertex crossed: `setData`
14777
+ * rebuilds the whole geojson-vt index and reloads every in-view tile, so its
14778
+ * cost is a large fixed one per call and is worth paying only once, with the
14779
+ * frame's final geometry.
14780
+ */
14781
+ }, {
14782
+ key: "flushCurrentSourceData",
14783
+ value: function flushCurrentSourceData(instance) {
14784
+ var source = this.map.getSource(instance.currentId);
14785
+ source === null || source === void 0 || source.setData(instance.currentSourceData);
14786
+ }
14570
14787
  }, {
14571
14788
  key: "setMarkerLngLat",
14572
14789
  value: function setMarkerLngLat(instance, point) {
@@ -22574,9 +22791,8 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
22574
22791
  }, {
22575
22792
  key: "addMarker",
22576
22793
  value: function addMarker(marker) {
22577
- var _this11 = this;
22578
22794
  try {
22579
- var _marker$maxLabelWidth, _this$innerFloors$fin4, _this$innerFloors$fin5;
22795
+ var _marker$maxLabelWidth;
22580
22796
  // Check if a marker with the same ID already exists and remove it
22581
22797
  if (marker.id) {
22582
22798
  var existingMarkerIndex = this.markers.findIndex(function (m) {
@@ -22595,10 +22811,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
22595
22811
  var markerCreated = new MarkerAttribute(map_objectSpread(map_objectSpread({}, marker), {}, {
22596
22812
  maxLabelWidthPx: (_marker$maxLabelWidth = marker.maxLabelWidthPx) !== null && _marker$maxLabelWidth !== void 0 ? _marker$maxLabelWidth : this.markerLayoutConfig.maxLabelWidthPx
22597
22813
  }));
22598
- var isOutdoor = !this.parentPlace || ((_this$innerFloors$fin4 = (_this$innerFloors$fin5 = this.innerFloors.find(function (floor) {
22599
- return floor.key === _this11.currentFloor;
22600
- })) === null || _this$innerFloors$fin5 === void 0 ? void 0 : _this$innerFloors$fin5.reachableFromGPS) !== null && _this$innerFloors$fin4 !== void 0 ? _this$innerFloors$fin4 : false);
22601
- markerCreated.changeFloor(this.currentFloor, this.map, isOutdoor);
22814
+ markerCreated.changeFloor(this.currentFloor, this.map, this.isOutdoorFloor(this.currentFloor));
22602
22815
  this.markers.push(markerCreated);
22603
22816
  this.markerLayoutController.scheduleRelayout();
22604
22817
  this.logEvent("addMarker");
@@ -22913,11 +23126,9 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
22913
23126
  }, {
22914
23127
  key: "circleFeatureCollection",
22915
23128
  value: function circleFeatureCollection() {
22916
- var _this$currentFloor3, _this$innerFloors$fin6, _this$innerFloors$fin7;
23129
+ var _this$currentFloor3;
22917
23130
  var floorId = (_this$currentFloor3 = this.currentFloor) !== null && _this$currentFloor3 !== void 0 ? _this$currentFloor3 : "";
22918
- var isOutdoor = !this.parentPlace || ((_this$innerFloors$fin6 = (_this$innerFloors$fin7 = this.innerFloors.find(function (floor) {
22919
- return floor.key === floorId;
22920
- })) === null || _this$innerFloors$fin7 === void 0 ? void 0 : _this$innerFloors$fin7.reachableFromGPS) !== null && _this$innerFloors$fin6 !== void 0 ? _this$innerFloors$fin6 : false);
23131
+ var isOutdoor = this.isOutdoorFloor(floorId);
22921
23132
  var features = this.circles.filter(function (circle) {
22922
23133
  var _circle$floorId;
22923
23134
  if (circle.hidden) return false;
@@ -23134,14 +23345,10 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23134
23345
  }, {
23135
23346
  key: "updateMarkersTo",
23136
23347
  value: function updateMarkersTo(floorId) {
23137
- var _this$innerFloors$fin8,
23138
- _this$innerFloors$fin9,
23139
- _this12 = this;
23140
- var isOutdoor = !this.parentPlace || ((_this$innerFloors$fin8 = (_this$innerFloors$fin9 = this.innerFloors.find(function (floor) {
23141
- return floor.key === floorId;
23142
- })) === null || _this$innerFloors$fin9 === void 0 ? void 0 : _this$innerFloors$fin9.reachableFromGPS) !== null && _this$innerFloors$fin8 !== void 0 ? _this$innerFloors$fin8 : false);
23348
+ var _this11 = this;
23349
+ var isOutdoor = this.isOutdoorFloor(floorId);
23143
23350
  this.markers.forEach(function (e) {
23144
- e.changeFloor(floorId, _this12.map, isOutdoor);
23351
+ e.changeFloor(floorId, _this11.map, isOutdoor);
23145
23352
  });
23146
23353
  this.markerLayoutController.scheduleRelayout();
23147
23354
  }
@@ -23150,18 +23357,18 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23150
23357
  value: function updateFiltersTo(floorId) {
23151
23358
  var _this$map$getStyle$la3,
23152
23359
  _this$map$getStyle3,
23153
- _this13 = this,
23154
- _this$innerFloors$fin0;
23360
+ _this12 = this,
23361
+ _this$innerFloors$fin4;
23155
23362
  if (!this.map) return;
23156
23363
  var layers = (_this$map$getStyle$la3 = (_this$map$getStyle3 = this.map.getStyle()) === null || _this$map$getStyle3 === void 0 ? void 0 : _this$map$getStyle3.layers) !== null && _this$map$getStyle$la3 !== void 0 ? _this$map$getStyle$la3 : [];
23157
23364
  layers.filter(function (l) {
23158
23365
  return l.id.startsWith("base-indoor-");
23159
23366
  }).forEach(function (l) {
23160
- _this13.map.removeLayer(l.id);
23367
+ _this12.map.removeLayer(l.id);
23161
23368
  });
23162
- var baseFloorId = (_this$innerFloors$fin0 = this.innerFloors.find(function (floor) {
23369
+ var baseFloorId = (_this$innerFloors$fin4 = this.innerFloors.find(function (floor) {
23163
23370
  return floor.key === floorId;
23164
- })) === null || _this$innerFloors$fin0 === void 0 ? void 0 : _this$innerFloors$fin0.baseFloor;
23371
+ })) === null || _this$innerFloors$fin4 === void 0 ? void 0 : _this$innerFloors$fin4.baseFloor;
23165
23372
  var indoorLayers = layers.filter(function (layer) {
23166
23373
  return layer.id.startsWith("indoor-");
23167
23374
  });
@@ -23175,7 +23382,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23175
23382
  // resolved are skipped, so a filter this class wrote is never mistaken for a
23176
23383
  // declared one.
23177
23384
  indoorLayers.forEach(function (layer) {
23178
- return _this13.captureDeclaredBaseFilter(layer.id);
23385
+ return _this12.captureDeclaredBaseFilter(layer.id);
23179
23386
  });
23180
23387
  if (baseFloorId != undefined) {
23181
23388
  var _indoorLayers$;
@@ -23185,13 +23392,13 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23185
23392
  }).forEach(function (layer) {
23186
23393
  var baseLayer = deepClone(layer);
23187
23394
  baseLayer.id = "base-" + layer.id;
23188
- _this13.baseFilters[baseLayer.id] = _this13.baseFilters[layer.id];
23189
- _this13.map.addLayer(baseLayer, firstLayerId);
23190
- _this13.applyLayerFilters(baseLayer, baseFloorId);
23395
+ _this12.baseFilters[baseLayer.id] = _this12.baseFilters[layer.id];
23396
+ _this12.map.addLayer(baseLayer, firstLayerId);
23397
+ _this12.applyLayerFilters(baseLayer, baseFloorId);
23191
23398
  });
23192
23399
  }
23193
23400
  indoorLayers.forEach(function (layer) {
23194
- _this13.applyLayerFilters(layer, floorId);
23401
+ _this12.applyLayerFilters(layer, floorId);
23195
23402
  });
23196
23403
  }
23197
23404
 
@@ -23263,6 +23470,23 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23263
23470
  value: function getInnerFloors() {
23264
23471
  return this.innerFloors;
23265
23472
  }
23473
+
23474
+ /**
23475
+ * Whether `floorId` shows the venue's outdoors, and so whether entities that
23476
+ * carry no floor of their own belong on screen with it.
23477
+ *
23478
+ * A map without a parent place is outdoors throughout; inside one, only a
23479
+ * floor reachable from GPS is. Markers, circles and the route marker all hang
23480
+ * their visibility on this, so they answer it the same way.
23481
+ */
23482
+ }, {
23483
+ key: "isOutdoorFloor",
23484
+ value: function isOutdoorFloor(floorId) {
23485
+ var _this$innerFloors$fin5, _this$innerFloors$fin6;
23486
+ return !this.parentPlace || ((_this$innerFloors$fin5 = (_this$innerFloors$fin6 = this.innerFloors.find(function (floor) {
23487
+ return floor.key === floorId;
23488
+ })) === null || _this$innerFloors$fin6 === void 0 ? void 0 : _this$innerFloors$fin6.reachableFromGPS) !== null && _this$innerFloors$fin5 !== void 0 ? _this$innerFloors$fin5 : false);
23489
+ }
23266
23490
  }, {
23267
23491
  key: "updateCamera",
23268
23492
  value: function updateCamera(newCamera, callback) {
@@ -23744,17 +23968,17 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23744
23968
  }, {
23745
23969
  key: "defaultClickListener",
23746
23970
  value: function defaultClickListener() {
23747
- var _this14 = this;
23971
+ var _this13 = this;
23748
23972
  this.map.on("click", /*#__PURE__*/function () {
23749
23973
  var _ref4 = map_asyncToGenerator(/*#__PURE__*/map_regenerator().m(function _callee3(e) {
23750
23974
  var features, roomFeatures, touchedFeature, ref, _clickedPlace, _ref5, _clickedPlace$mapvxId, _clickedPlace2, _clickedPlace3, clickedPlace, _iterator3, _step3, potentialParentPlace, cachedSubPlaces, cachedPlaces, clickedPlaceId, _t3;
23751
23975
  return map_regenerator().w(function (_context3) {
23752
23976
  while (1) switch (_context3.p = _context3.n) {
23753
23977
  case 0:
23754
- features = _this14.map.queryRenderedFeatures(e.point); // Filter room features by current floor
23978
+ features = _this13.map.queryRenderedFeatures(e.point); // Filter room features by current floor
23755
23979
  roomFeatures = features.filter(function (feature) {
23756
23980
  var _feature$properties;
23757
- return feature.properties["class"] === "room" && ((_feature$properties = feature.properties) === null || _feature$properties === void 0 ? void 0 : _feature$properties.floor_key) === _this14.currentFloor;
23981
+ return feature.properties["class"] === "room" && ((_feature$properties = feature.properties) === null || _feature$properties === void 0 ? void 0 : _feature$properties.floor_key) === _this13.currentFloor;
23758
23982
  });
23759
23983
  touchedFeature = roomFeatures[0];
23760
23984
  ref = touchedFeature === null || touchedFeature === void 0 ? void 0 : touchedFeature.properties.ref;
@@ -23765,14 +23989,14 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23765
23989
  console.log("touchedFeature", ref);
23766
23990
 
23767
23991
  // First, search in current subPlaces
23768
- clickedPlace = _this14.subPlaces.find(function (subPlace) {
23992
+ clickedPlace = _this13.subPlaces.find(function (subPlace) {
23769
23993
  return subPlace.mapvxId === ref;
23770
23994
  }); // If not found, search in subplaces of potential parent places
23771
23995
  if (!(clickedPlace === undefined)) {
23772
23996
  _context3.n = 7;
23773
23997
  break;
23774
23998
  }
23775
- _iterator3 = map_createForOfIteratorHelper(_this14.potentialParentPlaces);
23999
+ _iterator3 = map_createForOfIteratorHelper(_this13.potentialParentPlaces);
23776
24000
  _context3.p = 1;
23777
24001
  _iterator3.s();
23778
24002
  case 2:
@@ -23781,7 +24005,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23781
24005
  break;
23782
24006
  }
23783
24007
  potentialParentPlace = _step3.value;
23784
- cachedSubPlaces = _this14.repository.getCachedSubPlaces(potentialParentPlace.mapvxId);
24008
+ cachedSubPlaces = _this13.repository.getCachedSubPlaces(potentialParentPlace.mapvxId);
23785
24009
  if (!cachedSubPlaces) {
23786
24010
  _context3.n = 3;
23787
24011
  break;
@@ -23813,14 +24037,14 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23813
24037
  _context3.n = 10;
23814
24038
  break;
23815
24039
  }
23816
- cachedPlaces = _this14.repository.getCachedPlaces([ref]);
24040
+ cachedPlaces = _this13.repository.getCachedPlaces([ref]);
23817
24041
  if (!(cachedPlaces.length === 0)) {
23818
24042
  _context3.n = 9;
23819
24043
  break;
23820
24044
  }
23821
24045
  console.log("fetching place detail from server", ref);
23822
24046
  _context3.n = 8;
23823
- return _this14.repository.fetchAndParsePlaceDetail({
24047
+ return _this13.repository.fetchAndParsePlaceDetail({
23824
24048
  id: ref
23825
24049
  });
23826
24050
  case 8:
@@ -23833,8 +24057,8 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23833
24057
  case 10:
23834
24058
  console.log("clickedPlace", (_clickedPlace = clickedPlace) === null || _clickedPlace === void 0 ? void 0 : _clickedPlace.title);
23835
24059
  clickedPlaceId = (_ref5 = (_clickedPlace$mapvxId = (_clickedPlace2 = clickedPlace) === null || _clickedPlace2 === void 0 ? void 0 : _clickedPlace2.mapvxId) !== null && _clickedPlace$mapvxId !== void 0 ? _clickedPlace$mapvxId : (_clickedPlace3 = clickedPlace) === null || _clickedPlace3 === void 0 ? void 0 : _clickedPlace3.clientId) !== null && _ref5 !== void 0 ? _ref5 : "";
23836
- if (clickedPlace !== undefined && _this14.clickCallback) {
23837
- _this14.clickCallback(clickedPlaceId);
24060
+ if (clickedPlace !== undefined && _this13.clickCallback) {
24061
+ _this13.clickCallback(clickedPlaceId);
23838
24062
  }
23839
24063
  case 11:
23840
24064
  return _context3.a(2);
@@ -23849,29 +24073,29 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
23849
24073
  }, {
23850
24074
  key: "onHover",
23851
24075
  value: function onHover() {
23852
- var _this15 = this;
24076
+ var _this14 = this;
23853
24077
  if (!this.enableHover) return;
23854
24078
  this.map.on("mousemove", "hoverable", function (e) {
23855
24079
  var _e$features;
23856
24080
  var feature = (_e$features = e.features) === null || _e$features === void 0 ? void 0 : _e$features.find(function (feature) {
23857
24081
  var _feature$properties$r, _feature$properties2;
23858
- return ((_feature$properties$r = feature.properties.ref) === null || _feature$properties$r === void 0 ? void 0 : _feature$properties$r.length) > 0 && ((_feature$properties2 = feature.properties) === null || _feature$properties2 === void 0 ? void 0 : _feature$properties2.floor_key) === _this15.currentFloor;
24082
+ return ((_feature$properties$r = feature.properties.ref) === null || _feature$properties$r === void 0 ? void 0 : _feature$properties$r.length) > 0 && ((_feature$properties2 = feature.properties) === null || _feature$properties2 === void 0 ? void 0 : _feature$properties2.floor_key) === _this14.currentFloor;
23859
24083
  });
23860
24084
  var ref = feature === null || feature === void 0 ? void 0 : feature.properties.ref;
23861
24085
  if (ref != null && typeof ref === "string" && ref.length > 0) {
23862
- _this15.hoveredId = ref;
23863
- _this15.updateFiltersTo(_this15.currentFloor);
23864
- } else if (ref === undefined && _this15.hoveredId !== "unselected") {
23865
- _this15.hoveredId = "unselected";
23866
- _this15.updateFiltersTo(_this15.currentFloor);
24086
+ _this14.hoveredId = ref;
24087
+ _this14.updateFiltersTo(_this14.currentFloor);
24088
+ } else if (ref === undefined && _this14.hoveredId !== "unselected") {
24089
+ _this14.hoveredId = "unselected";
24090
+ _this14.updateFiltersTo(_this14.currentFloor);
23867
24091
  }
23868
24092
  });
23869
24093
 
23870
24094
  // When the mouse leaves the state-fill layer, update the feature state of the
23871
24095
  // previously hovered feature.
23872
24096
  this.map.on("mouseleave", "hoverable", function () {
23873
- _this15.hoveredId = "unselected";
23874
- _this15.updateFiltersTo(_this15.currentFloor);
24097
+ _this14.hoveredId = "unselected";
24098
+ _this14.updateFiltersTo(_this14.currentFloor);
23875
24099
  });
23876
24100
  }
23877
24101
  }, {
@@ -24272,7 +24496,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24272
24496
  }, {
24273
24497
  key: "addUserLocationTracking",
24274
24498
  value: function addUserLocationTracking(enableHighAccuracy, geoLocation, icon) {
24275
- var _this16 = this;
24499
+ var _this15 = this;
24276
24500
  var initialCoordinate = {
24277
24501
  lat: 0.0,
24278
24502
  lng: 0.0
@@ -24296,7 +24520,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24296
24520
  this.markerLayoutController.scheduleRelayout();
24297
24521
  var updateMarker = function updateMarker(position) {
24298
24522
  marker.setLngLat([position.coords.longitude, position.coords.latitude]);
24299
- _this16.markerLayoutController.scheduleRelayout();
24523
+ _this15.markerLayoutController.scheduleRelayout();
24300
24524
  };
24301
24525
  this.geoLocation = geoLocation !== null && geoLocation !== void 0 ? geoLocation : navigator.geolocation;
24302
24526
  this.watchPositionID = this.geoLocation.watchPosition(updateMarker, function (error) {
@@ -24392,7 +24616,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24392
24616
  key: "onWebGLContextLost",
24393
24617
  value: function onWebGLContextLost(e) {
24394
24618
  var _this$map2,
24395
- _this17 = this;
24619
+ _this16 = this;
24396
24620
  e.originalEvent.preventDefault();
24397
24621
  console.warn("Contexto WebGL perdido 😢");
24398
24622
 
@@ -24403,8 +24627,8 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24403
24627
  var _ext$restoreContext;
24404
24628
  canvas.addEventListener("webglcontextrestored", function () {
24405
24629
  console.debug("Contexto WebGL restaurado, forzando re-render");
24406
- _this17.map.triggerRepaint(); // forzar repaint
24407
- _this17.failedTiles.clear();
24630
+ _this16.map.triggerRepaint(); // forzar repaint
24631
+ _this16.failedTiles.clear();
24408
24632
  }, {
24409
24633
  once: true
24410
24634
  });
@@ -24480,7 +24704,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24480
24704
  }, {
24481
24705
  key: "subscribeToFailedTiles",
24482
24706
  value: function subscribeToFailedTiles() {
24483
- var _this18 = this;
24707
+ var _this17 = this;
24484
24708
  if (this.retryTimer) return;
24485
24709
 
24486
24710
  // Store bound functions for proper cleanup
@@ -24497,23 +24721,23 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24497
24721
  // exactly when tiles fail — gating on it would skip every tick during a
24498
24722
  // bad-network burst. The queue is left untouched so the tiles queued
24499
24723
  // mid-swap are still retried on the next tick.
24500
- if (!_this18.hasStyle()) {
24724
+ if (!_this17.hasStyle()) {
24501
24725
  return;
24502
24726
  }
24503
- if (!_this18.map.getSource("indoorequal")) {
24504
- _this18.failedTiles.clear();
24727
+ if (!_this17.map.getSource("indoorequal")) {
24728
+ _this17.failedTiles.clear();
24505
24729
  return;
24506
24730
  }
24507
- var source = _this18.map.getSource("indoorequal");
24731
+ var source = _this17.map.getSource("indoorequal");
24508
24732
  if (!source || source.type !== "vector") {
24509
- _this18.failedTiles.clear();
24733
+ _this17.failedTiles.clear();
24510
24734
  return;
24511
24735
  }
24512
24736
 
24513
24737
  // Process tiles and remove invalid ones
24514
24738
  var tilesToRetry = [];
24515
24739
  var tilesToRemove = [];
24516
- _this18.failedTiles.forEach(function (tile) {
24740
+ _this17.failedTiles.forEach(function (tile) {
24517
24741
  // Check if tile is still valid before attempting reload
24518
24742
  if (!tile || tile.state === "unloaded" || tile.state === "loading") {
24519
24743
  tilesToRemove.push(tile);
@@ -24531,14 +24755,14 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24531
24755
 
24532
24756
  // Remove invalid tiles from the set
24533
24757
  tilesToRemove.forEach(function (tile) {
24534
- return _this18.failedTiles["delete"](tile);
24758
+ return _this17.failedTiles["delete"](tile);
24535
24759
  });
24536
24760
 
24537
24761
  // Attempt to reload valid failed tiles
24538
24762
  var now = Date.now();
24539
24763
  tilesToRetry.forEach(function (tile) {
24540
- var _this18$tileRetryStat;
24541
- var retry = (_this18$tileRetryStat = _this18.tileRetryState.get(tile)) !== null && _this18$tileRetryStat !== void 0 ? _this18$tileRetryStat : {
24764
+ var _this17$tileRetryStat;
24765
+ var retry = (_this17$tileRetryStat = _this17.tileRetryState.get(tile)) !== null && _this17$tileRetryStat !== void 0 ? _this17$tileRetryStat : {
24542
24766
  attempts: 0,
24543
24767
  nextAttemptAt: 0,
24544
24768
  pending: false
@@ -24549,16 +24773,16 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24549
24773
  var onFailure = function onFailure(error) {
24550
24774
  var attempts = retry.attempts + 1;
24551
24775
  if (attempts >= MAX_TILE_RETRIES) {
24552
- _this18.debugLog("Tile reload failed ".concat(attempts, " times, dropping it from the retry queue"), error);
24553
- _this18.failedTiles["delete"](tile);
24554
- _this18.tileRetryState["delete"](tile);
24776
+ _this17.debugLog("Tile reload failed ".concat(attempts, " times, dropping it from the retry queue"), error);
24777
+ _this17.failedTiles["delete"](tile);
24778
+ _this17.tileRetryState["delete"](tile);
24555
24779
  return;
24556
24780
  }
24557
24781
 
24558
24782
  // Stay in the queue and try again once the backoff has elapsed.
24559
24783
  var backoffMs = TILE_RETRY_BASE_DELAY_MS * Math.pow(2, attempts - 1);
24560
- _this18.debugLog("Tile reload failed (attempt ".concat(attempts, "/").concat(MAX_TILE_RETRIES, "), retrying in ").concat(backoffMs, "ms"), error);
24561
- _this18.tileRetryState.set(tile, {
24784
+ _this17.debugLog("Tile reload failed (attempt ".concat(attempts, "/").concat(MAX_TILE_RETRIES, "), retrying in ").concat(backoffMs, "ms"), error);
24785
+ _this17.tileRetryState.set(tile, {
24562
24786
  attempts: attempts,
24563
24787
  nextAttemptAt: Date.now() + backoffMs,
24564
24788
  pending: false
@@ -24567,7 +24791,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24567
24791
  try {
24568
24792
  // Verify tile still exists and is in a retryable state
24569
24793
  if (tile && (tile.state === "errored" || tile.state === "expired")) {
24570
- _this18.tileRetryState.set(tile, map_objectSpread(map_objectSpread({}, retry), {}, {
24794
+ _this17.tileRetryState.set(tile, map_objectSpread(map_objectSpread({}, retry), {}, {
24571
24795
  pending: true
24572
24796
  }));
24573
24797
  // loadTile is async, so a rejection escapes this try/catch and has to be handled
@@ -24577,7 +24801,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
24577
24801
  // Loaded: forget the attempt history so a later failure starts from zero. The
24578
24802
  // tile leaves the queue through the tilesToRemove branch on the next tick,
24579
24803
  // once its state is no longer errored/expired.
24580
- _this18.tileRetryState["delete"](tile);
24804
+ _this17.tileRetryState["delete"](tile);
24581
24805
  })["catch"](onFailure);
24582
24806
  }
24583
24807
  } catch (error) {