@mapvx/web-js 1.4.0 → 1.5.0-dev.1

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/umd/index.js CHANGED
@@ -6814,7 +6814,7 @@ var rollbar_umd_min_default = /*#__PURE__*/__webpack_require__.n(rollbar_umd_min
6814
6814
  // version placeholder is replaced with the package version by
6815
6815
  // scripts/inject-build-defines.js. The access token falls back to the MapVX
6816
6816
  // SDK-web Rollbar project token when none is injected at build time.
6817
- var SDK_VERSION = true ? "1.4.0" : 0;
6817
+ var SDK_VERSION = true ? "1.5.0-dev.1" : 0;
6818
6818
  var ACCESS_TOKEN = false ? 0 : "28279d52df43411ebd138c2bee0ab1df";
6819
6819
  var _rollbarConfig = {
6820
6820
  accessToken: ACCESS_TOKEN,
@@ -6861,7 +6861,7 @@ function logger_toPrimitive(t, r) { if ("object" != logger_typeof(t) || !t) retu
6861
6861
  // by scripts/inject-build-defines.js. The Countly key falls back to the
6862
6862
  // MapVX key when none is injected at build time.
6863
6863
  var IS_DEBUG = true ? false : 0;
6864
- var logger_SDK_VERSION = true ? "1.4.0" : 0;
6864
+ var logger_SDK_VERSION = true ? "1.5.0-dev.1" : 0;
6865
6865
  var COUNTLY_API_KEY = false ? 0 : "f0c8d3b96d336e857a8628f49dd1baf7d7add0e9";
6866
6866
  var logger_countly = {
6867
6867
  apiKey: COUNTLY_API_KEY,
@@ -9550,6 +9550,16 @@ function InternalDrawRouteConfiguration(config) {
9550
9550
  /**
9551
9551
  * Interface that represent a place with their id.
9552
9552
  * @group Routes
9553
+ * @example
9554
+ * ```typescript
9555
+ * // Resolve an internal alias that is reused across several malls by
9556
+ * // pinning the building (and, optionally, the floor) it belongs to.
9557
+ * const origin: IdLocation = {
9558
+ * id: "store-204", // integrator alias, may repeat across buildings
9559
+ * buildingId: "mall-santiago",
9560
+ * floorId: "level-2", // takes precedence over `level`
9561
+ * }
9562
+ * ```
9553
9563
  */
9554
9564
 
9555
9565
  /**
@@ -9641,208 +9651,6 @@ var InternalAnimationDrawingConfig = /*#__PURE__*/function () {
9641
9651
  }
9642
9652
  }]);
9643
9653
  }();
9644
- ;// ./src/utils/error.ts
9645
- /**
9646
- * Convert an unknown error to an Error object.
9647
- * @group Utils
9648
- * @param error - The unknown error.
9649
- * @returns An Error object.
9650
- */
9651
- function convertToError(error) {
9652
- if (error instanceof Error) {
9653
- return error;
9654
- } else {
9655
- var text = String(error);
9656
- return new Error(text);
9657
- }
9658
- }
9659
- ;// ./src/domain/models/loggeable.ts
9660
- function loggeable_typeof(o) { "@babel/helpers - typeof"; return loggeable_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; }, loggeable_typeof(o); }
9661
- function loggeable_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
9662
- function loggeable_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, loggeable_toPropertyKey(o.key), o); } }
9663
- function loggeable_createClass(e, r, t) { return r && loggeable_defineProperties(e.prototype, r), t && loggeable_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
9664
- function loggeable_toPropertyKey(t) { var i = loggeable_toPrimitive(t, "string"); return "symbol" == loggeable_typeof(i) ? i : i + ""; }
9665
- function loggeable_toPrimitive(t, r) { if ("object" != loggeable_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != loggeable_typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
9666
-
9667
-
9668
-
9669
- /**
9670
- * Represents the abstract class for the loggeable.
9671
- * @hidden
9672
- */
9673
- var Loggeable = /*#__PURE__*/function () {
9674
- /**
9675
- * The object to log the events and errors.
9676
- */
9677
-
9678
- function Loggeable() {
9679
- loggeable_classCallCheck(this, Loggeable);
9680
- this.logger = Logger.getInstance();
9681
- }
9682
-
9683
- /**
9684
- * Add values to identify the client.
9685
- * @param segmentation The pair values to use as segmentation.
9686
- * @returns The segmentation with the added values.
9687
- */
9688
- return loggeable_createClass(Loggeable, [{
9689
- key: "logEvent",
9690
- value:
9691
- /**
9692
- * To log a event in this class.
9693
- * @param eventName The event name.
9694
- * @param eventSegmentation The pair key, value to segment this event count.
9695
- */
9696
- function logEvent(eventName) {
9697
- var eventSegmentation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9698
- this.logger.logEvent(eventName, this.prepareSegmentation(eventSegmentation));
9699
- }
9700
-
9701
- /**
9702
- * To log a captured error in this class.
9703
- * @param error The captured error
9704
- * @param args The rest of the arguments.
9705
- */
9706
- }, {
9707
- key: "logError",
9708
- value: function logError(error) {
9709
- var _this$logger;
9710
- var errorTyped = convertToError(error);
9711
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
9712
- args[_key - 1] = arguments[_key];
9713
- }
9714
- (_this$logger = this.logger).logError.apply(_this$logger, [errorTyped].concat(args));
9715
- }
9716
-
9717
- /**
9718
- * To log a captured error as a warning.
9719
- * @param error The captured error
9720
- * @param args The rest of the arguments.
9721
- */
9722
- }, {
9723
- key: "logWarning",
9724
- value: function logWarning(error) {
9725
- var _this$logger2;
9726
- var errorTyped = convertToError(error);
9727
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
9728
- args[_key2 - 1] = arguments[_key2];
9729
- }
9730
- (_this$logger2 = this.logger).logWarning.apply(_this$logger2, [errorTyped].concat(args));
9731
- }
9732
- }, {
9733
- key: "logDebug",
9734
- value: function logDebug() {
9735
- var _this$logger3;
9736
- (_this$logger3 = this.logger).logDebug.apply(_this$logger3, arguments);
9737
- }
9738
-
9739
- /**
9740
- * Prints in console any number of given arguments, if and only if, app is running in debug mode.
9741
- * @param args An array of arguments to log
9742
- */
9743
- }, {
9744
- key: "debugLog",
9745
- value: function debugLog() {
9746
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
9747
- args[_key3] = arguments[_key3];
9748
- }
9749
- this.logger.debugLog(args);
9750
- }
9751
- }]);
9752
- }();
9753
- ;// ./src/domain/models/mapConfig.ts
9754
- /**
9755
- * Configuration options for map tile caching.
9756
- * Allows controlling how map tiles are cached in memory and persisted via service worker.
9757
- *
9758
- * @example
9759
- * ```typescript
9760
- * const tileCacheConfig: MapTileCacheConfig = {
9761
- * enabled: true,
9762
- * maxTiles: 500,
9763
- * ttlMs: 60 * 60 * 1000, // 1 hour
9764
- * persistToServiceWorker: true,
9765
- * preloadAdjacentZooms: false,
9766
- * maxConcurrentTileFetches: 6
9767
- * };
9768
- * ```
9769
- *
9770
- * @group Configuration
9771
- */
9772
-
9773
- /**
9774
- * Default values for tile cache configuration
9775
- * @internal
9776
- */
9777
- var DEFAULT_TILE_CACHE_CONFIG = {
9778
- enabled: true,
9779
- maxTiles: 400,
9780
- ttlMs: 30 * 60 * 1000,
9781
- // 30 minutes
9782
- persistToServiceWorker: true,
9783
- preloadAdjacentZooms: false,
9784
- maxConcurrentTileFetches: 6
9785
- };
9786
-
9787
- /**
9788
- * Hard cap for {@link MapTileCacheConfig.maxTiles}.
9789
- * Configurations above this (e.g. millions) are clamped to avoid memory pressure
9790
- * and excessive interaction with the tile CDN / service worker.
9791
- *
9792
- * @internal
9793
- */
9794
- var MAPLIBRE_MAX_TILE_CACHE_HARD_CAP = 100000;
9795
-
9796
- /**
9797
- * Basic configuration for the map.
9798
- * Provides essential settings for initializing and customizing map behavior.
9799
- *
9800
- * @example
9801
- * ```typescript
9802
- * const mapConfig: MapConfig = {
9803
- * zoom: 15,
9804
- * center: { lat: 40.7128, lng: -74.0060 },
9805
- * parentPlaceId: "building-1",
9806
- * onMapReady: () => console.log("Map is ready!"),
9807
- * enableHover: true,
9808
- * showCompass: true
9809
- * };
9810
- * ```
9811
- *
9812
- * @group Map
9813
- *
9814
- * @property zoom - The initial zoom level of the map.
9815
- * @property center - The initial center coordinates of the map.
9816
- * @property parentPlaceId - (Optional) The ID of the parent place to display.
9817
- * @property otherPotentialParentPlacesIds - (Optional) List of alternative parent place IDs.
9818
- * @property onMapReady - (Optional) Callback invoked when the map is ready.
9819
- * @property onZoomEnd - (Optional) Callback invoked when the zoom operation ends. Receives the new zoom level.
9820
- * @property onRotate - (Optional) Callback invoked when the map is rotated. Receives the rotation in degrees.
9821
- * @property onFloorChange - (Optional) Callback invoked when the floor changes. Receives the new floor ID.
9822
- * @property onParentPlaceChange - (Optional) Callback invoked when the parent place changes. Receives the new parent place ID.
9823
- * @property lang - (Optional) Language code for map labels and UI.
9824
- * @property minZoom - (Optional) Minimum allowed zoom level.
9825
- * @property maxZoom - (Optional) Maximum allowed zoom level.
9826
- * @property pitch - (Optional) The pitch (tilt) of the map in degrees.
9827
- * @property maxBounds - (Optional) Array of coordinates defining the maximum bounds of the map.
9828
- * @property enableHover - (Optional) Whether to enable hover interactions on the map.
9829
- * @property showCompass - (Optional) Whether to display the compass control.
9830
- * @property showZoom - (Optional) Whether to display the zoom control.
9831
- * @property navigationPosition - (Optional) Position of the navigation controls on the map.
9832
- * @property bearingSnap - (Optional) The bearing snap threshold in degrees.
9833
- * @property bearing - (Optional) Initial bearing (rotation) of the map in degrees, clockwise from north.
9834
- * @property interactive - (Optional) Master switch for all user interaction (pan/zoom/rotate).
9835
- * @property rotateEnabled - (Optional) Whether the user can rotate the map; keeps pinch-zoom when disabled.
9836
- * @property dragPan - (Optional) Whether the user can pan by dragging/swiping.
9837
- * @property scrollZoom - (Optional) Whether the scroll wheel/trackpad can zoom the map.
9838
- * @property doubleClickZoom - (Optional) Whether double-click/double-tap zooms the map.
9839
- * @property touchZoomRotate - (Optional) Whether pinch gestures can zoom the map on touch devices.
9840
- * @property keyboard - (Optional) Whether keyboard shortcuts can pan/zoom/rotate the map.
9841
- * @property institutionId - (Optional) The institution identifier for map context. Required for loading map related data from Portal.
9842
- * @property authToken - (Optional) Authentication token for accessing protected map resources. Required for loading map related data from Portal.
9843
- * @property apiUrl - (Optional) Injected by SDK when creating map; base API URL for map requests.
9844
- * @property mapvxRequestContext - (Optional) Injected by SDK when creating map; context sent as headers to public-api.mapvx.com.
9845
- */
9846
9654
  ;// ./src/domain/models/circle.ts
9847
9655
  function circle_typeof(o) { "@babel/helpers - typeof"; return circle_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; }, circle_typeof(o); }
9848
9656
  function circle_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; }
@@ -10027,101 +9835,303 @@ function isValidCircleConfig(config) {
10027
9835
  }
10028
9836
 
10029
9837
  /**
10030
- * Resolves a {@link CircleConfig} into a {@link CircleRecord}, applying
10031
- * default styling, generating an id when one is not provided, and validating inputs.
10032
- *
10033
- * @param config Circle configuration provided by the SDK consumer.
10034
- * @param hidden Initial hidden state, defaults to visible.
10035
- * @returns The resolved circle record ready to be stored and rendered.
10036
- * @throws {Error} If radiusMeters is ≤ 0, not finite, or coordinates are invalid.
9838
+ * Resolves a {@link CircleConfig} into a {@link CircleRecord}, applying
9839
+ * default styling, generating an id when one is not provided, and validating inputs.
9840
+ *
9841
+ * @param config Circle configuration provided by the SDK consumer.
9842
+ * @param hidden Initial hidden state, defaults to visible.
9843
+ * @returns The resolved circle record ready to be stored and rendered.
9844
+ * @throws {Error} If radiusMeters is ≤ 0, not finite, or coordinates are invalid.
9845
+ *
9846
+ * @group Circles
9847
+ */
9848
+ function resolveCircleConfig(config) {
9849
+ var _config$id, _config$fillColor, _config$strokeColor, _config$strokeWidth, _config$renderOrder;
9850
+ var hidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
9851
+ validateRadiusMeters(config.radiusMeters);
9852
+ validateCoordinate(config.coordinate);
9853
+ if (config.renderOrder !== undefined && !CIRCLE_RENDER_ORDERS.includes(config.renderOrder)) {
9854
+ throw new Error("Invalid renderOrder: ".concat(String(config.renderOrder), ". ") + "Must be one of: ".concat(CIRCLE_RENDER_ORDERS.join(", "), "."));
9855
+ }
9856
+ return {
9857
+ id: (_config$id = config.id) !== null && _config$id !== void 0 ? _config$id : generateHexadecimalKey(),
9858
+ // Copy the coordinate so later mutations of the caller's object
9859
+ // can't change internal circle state
9860
+ coordinate: {
9861
+ lat: config.coordinate.lat,
9862
+ lng: config.coordinate.lng
9863
+ },
9864
+ radiusMeters: config.radiusMeters,
9865
+ fillColor: (_config$fillColor = config.fillColor) !== null && _config$fillColor !== void 0 ? _config$fillColor : CIRCLE_DEFAULTS.fillColor,
9866
+ fillOpacity: clampOpacity(config.fillOpacity, CIRCLE_DEFAULTS.fillOpacity),
9867
+ strokeColor: (_config$strokeColor = config.strokeColor) !== null && _config$strokeColor !== void 0 ? _config$strokeColor : CIRCLE_DEFAULTS.strokeColor,
9868
+ strokeWidth: (_config$strokeWidth = config.strokeWidth) !== null && _config$strokeWidth !== void 0 ? _config$strokeWidth : CIRCLE_DEFAULTS.strokeWidth,
9869
+ strokeOpacity: clampOpacity(config.strokeOpacity, CIRCLE_DEFAULTS.strokeOpacity),
9870
+ floorId: config.floorId,
9871
+ renderOrder: (_config$renderOrder = config.renderOrder) !== null && _config$renderOrder !== void 0 ? _config$renderOrder : CIRCLE_DEFAULTS.renderOrder,
9872
+ hidden: hidden
9873
+ };
9874
+ }
9875
+
9876
+ /**
9877
+ * Builds a closed GeoJSON polygon ring approximating a geographic circle.
9878
+ *
9879
+ * The ring is computed with an equirectangular approximation: meters are
9880
+ * converted to degrees independently per axis, with the longitude scale
9881
+ * corrected by the cosine of the latitude. For the radii the SDK works with
9882
+ * (tens to hundreds of meters) the metric error is negligible (≤1%) at any latitude
9883
+ * where the projection is defined. At extreme polar latitudes, the approximation
9884
+ * breaks down, so circles near poles (|lat| > 85°) should be used with caution.
9885
+ *
9886
+ * @param lng Longitude of the circle center in degrees.
9887
+ * @param lat Latitude of the circle center in degrees.
9888
+ * @param radiusMeters Radius of the circle in meters. Must be positive and finite.
9889
+ * @param points Number of segments in the ring. Defaults to 64. Non-integer
9890
+ * values are floored and the count is clamped to a minimum of 3,
9891
+ * the smallest valid GeoJSON linear ring; non-finite values fall
9892
+ * back to the default.
9893
+ * @returns A closed ring of `[lng, lat]` positions (first equals last).
9894
+ *
9895
+ * @example
9896
+ * ```typescript
9897
+ * import { circleRing } from '@mapvx/web-js';
9898
+ *
9899
+ * // Create a 150-meter radius circle ring
9900
+ * const ring = circleRing(-74.0060, 40.7128, 150);
9901
+ * const polygon = { type: "Polygon", coordinates: [ring] };
9902
+ *
9903
+ * // Custom segments (32 instead of 64) for lower resolution
9904
+ * const coarseRing = circleRing(-74.0060, 40.7128, 150, 32);
9905
+ * ```
9906
+ *
9907
+ * @note Equirectangular approximation is accurate for radii up to ~500 km and
9908
+ * latitudes between approximately ±80°. Beyond these limits, visual
9909
+ * distortion may occur near the poles.
9910
+ * @note Generated rings do not account for geographic obstacles, walls, or
9911
+ * buildings. For complex geofencing, consider server-side validation.
9912
+ *
9913
+ * @group Circles
9914
+ */
9915
+ function circleRing(lng, lat, radiusMeters) {
9916
+ var points = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 64;
9917
+ // A linear ring needs at least 3 distinct positions to be valid GeoJSON
9918
+ var segments = Number.isFinite(points) ? Math.max(3, Math.floor(points)) : 64;
9919
+ var ring = [];
9920
+ var latRad = lat * Math.PI / 180;
9921
+ var metersPerDegLat = 110574;
9922
+ var metersPerDegLng = 111320 * Math.cos(latRad || 0.000001);
9923
+ var latR = radiusMeters / metersPerDegLat;
9924
+ var lngR = radiusMeters / (metersPerDegLng || 1);
9925
+ for (var i = 0; i < segments; i += 1) {
9926
+ var a = i / segments * Math.PI * 2;
9927
+ ring.push([lng + lngR * Math.cos(a), lat + latR * Math.sin(a)]);
9928
+ }
9929
+ // Close the ring with an exact copy of the first position, as GeoJSON requires
9930
+ ring.push([ring[0][0], ring[0][1]]);
9931
+ return ring;
9932
+ }
9933
+ ;// ./src/utils/error.ts
9934
+ /**
9935
+ * Convert an unknown error to an Error object.
9936
+ * @group Utils
9937
+ * @param error - The unknown error.
9938
+ * @returns An Error object.
9939
+ */
9940
+ function convertToError(error) {
9941
+ if (error instanceof Error) {
9942
+ return error;
9943
+ } else {
9944
+ var text = String(error);
9945
+ return new Error(text);
9946
+ }
9947
+ }
9948
+ ;// ./src/domain/models/loggeable.ts
9949
+ function loggeable_typeof(o) { "@babel/helpers - typeof"; return loggeable_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; }, loggeable_typeof(o); }
9950
+ function loggeable_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
9951
+ function loggeable_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, loggeable_toPropertyKey(o.key), o); } }
9952
+ function loggeable_createClass(e, r, t) { return r && loggeable_defineProperties(e.prototype, r), t && loggeable_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
9953
+ function loggeable_toPropertyKey(t) { var i = loggeable_toPrimitive(t, "string"); return "symbol" == loggeable_typeof(i) ? i : i + ""; }
9954
+ function loggeable_toPrimitive(t, r) { if ("object" != loggeable_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != loggeable_typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
9955
+
9956
+
9957
+
9958
+ /**
9959
+ * Represents the abstract class for the loggeable.
9960
+ * @hidden
9961
+ */
9962
+ var Loggeable = /*#__PURE__*/function () {
9963
+ /**
9964
+ * The object to log the events and errors.
9965
+ */
9966
+
9967
+ function Loggeable() {
9968
+ loggeable_classCallCheck(this, Loggeable);
9969
+ this.logger = Logger.getInstance();
9970
+ }
9971
+
9972
+ /**
9973
+ * Add values to identify the client.
9974
+ * @param segmentation The pair values to use as segmentation.
9975
+ * @returns The segmentation with the added values.
9976
+ */
9977
+ return loggeable_createClass(Loggeable, [{
9978
+ key: "logEvent",
9979
+ value:
9980
+ /**
9981
+ * To log a event in this class.
9982
+ * @param eventName The event name.
9983
+ * @param eventSegmentation The pair key, value to segment this event count.
9984
+ */
9985
+ function logEvent(eventName) {
9986
+ var eventSegmentation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9987
+ this.logger.logEvent(eventName, this.prepareSegmentation(eventSegmentation));
9988
+ }
9989
+
9990
+ /**
9991
+ * To log a captured error in this class.
9992
+ * @param error The captured error
9993
+ * @param args The rest of the arguments.
9994
+ */
9995
+ }, {
9996
+ key: "logError",
9997
+ value: function logError(error) {
9998
+ var _this$logger;
9999
+ var errorTyped = convertToError(error);
10000
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
10001
+ args[_key - 1] = arguments[_key];
10002
+ }
10003
+ (_this$logger = this.logger).logError.apply(_this$logger, [errorTyped].concat(args));
10004
+ }
10005
+
10006
+ /**
10007
+ * To log a captured error as a warning.
10008
+ * @param error The captured error
10009
+ * @param args The rest of the arguments.
10010
+ */
10011
+ }, {
10012
+ key: "logWarning",
10013
+ value: function logWarning(error) {
10014
+ var _this$logger2;
10015
+ var errorTyped = convertToError(error);
10016
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
10017
+ args[_key2 - 1] = arguments[_key2];
10018
+ }
10019
+ (_this$logger2 = this.logger).logWarning.apply(_this$logger2, [errorTyped].concat(args));
10020
+ }
10021
+ }, {
10022
+ key: "logDebug",
10023
+ value: function logDebug() {
10024
+ var _this$logger3;
10025
+ (_this$logger3 = this.logger).logDebug.apply(_this$logger3, arguments);
10026
+ }
10027
+
10028
+ /**
10029
+ * Prints in console any number of given arguments, if and only if, app is running in debug mode.
10030
+ * @param args An array of arguments to log
10031
+ */
10032
+ }, {
10033
+ key: "debugLog",
10034
+ value: function debugLog() {
10035
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
10036
+ args[_key3] = arguments[_key3];
10037
+ }
10038
+ this.logger.debugLog(args);
10039
+ }
10040
+ }]);
10041
+ }();
10042
+ ;// ./src/domain/models/mapConfig.ts
10043
+ /**
10044
+ * Configuration options for map tile caching.
10045
+ * Allows controlling how map tiles are cached in memory and persisted via service worker.
10046
+ *
10047
+ * @example
10048
+ * ```typescript
10049
+ * const tileCacheConfig: MapTileCacheConfig = {
10050
+ * enabled: true,
10051
+ * maxTiles: 500,
10052
+ * ttlMs: 60 * 60 * 1000, // 1 hour
10053
+ * persistToServiceWorker: true,
10054
+ * preloadAdjacentZooms: false,
10055
+ * maxConcurrentTileFetches: 6
10056
+ * };
10057
+ * ```
10058
+ *
10059
+ * @group Configuration
10060
+ */
10061
+
10062
+ /**
10063
+ * Default values for tile cache configuration
10064
+ * @internal
10065
+ */
10066
+ var DEFAULT_TILE_CACHE_CONFIG = {
10067
+ enabled: true,
10068
+ maxTiles: 400,
10069
+ ttlMs: 30 * 60 * 1000,
10070
+ // 30 minutes
10071
+ persistToServiceWorker: true,
10072
+ preloadAdjacentZooms: false,
10073
+ maxConcurrentTileFetches: 6
10074
+ };
10075
+
10076
+ /**
10077
+ * Hard cap for {@link MapTileCacheConfig.maxTiles}.
10078
+ * Configurations above this (e.g. millions) are clamped to avoid memory pressure
10079
+ * and excessive interaction with the tile CDN / service worker.
10037
10080
  *
10038
- * @group Circles
10081
+ * @internal
10039
10082
  */
10040
- function resolveCircleConfig(config) {
10041
- var _config$id, _config$fillColor, _config$strokeColor, _config$strokeWidth, _config$renderOrder;
10042
- var hidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
10043
- validateRadiusMeters(config.radiusMeters);
10044
- validateCoordinate(config.coordinate);
10045
- if (config.renderOrder !== undefined && !CIRCLE_RENDER_ORDERS.includes(config.renderOrder)) {
10046
- throw new Error("Invalid renderOrder: ".concat(String(config.renderOrder), ". ") + "Must be one of: ".concat(CIRCLE_RENDER_ORDERS.join(", "), "."));
10047
- }
10048
- return {
10049
- id: (_config$id = config.id) !== null && _config$id !== void 0 ? _config$id : generateHexadecimalKey(),
10050
- // Copy the coordinate so later mutations of the caller's object
10051
- // can't change internal circle state
10052
- coordinate: {
10053
- lat: config.coordinate.lat,
10054
- lng: config.coordinate.lng
10055
- },
10056
- radiusMeters: config.radiusMeters,
10057
- fillColor: (_config$fillColor = config.fillColor) !== null && _config$fillColor !== void 0 ? _config$fillColor : CIRCLE_DEFAULTS.fillColor,
10058
- fillOpacity: clampOpacity(config.fillOpacity, CIRCLE_DEFAULTS.fillOpacity),
10059
- strokeColor: (_config$strokeColor = config.strokeColor) !== null && _config$strokeColor !== void 0 ? _config$strokeColor : CIRCLE_DEFAULTS.strokeColor,
10060
- strokeWidth: (_config$strokeWidth = config.strokeWidth) !== null && _config$strokeWidth !== void 0 ? _config$strokeWidth : CIRCLE_DEFAULTS.strokeWidth,
10061
- strokeOpacity: clampOpacity(config.strokeOpacity, CIRCLE_DEFAULTS.strokeOpacity),
10062
- floorId: config.floorId,
10063
- renderOrder: (_config$renderOrder = config.renderOrder) !== null && _config$renderOrder !== void 0 ? _config$renderOrder : CIRCLE_DEFAULTS.renderOrder,
10064
- hidden: hidden
10065
- };
10066
- }
10083
+ var MAPLIBRE_MAX_TILE_CACHE_HARD_CAP = 100000;
10067
10084
 
10068
10085
  /**
10069
- * Builds a closed GeoJSON polygon ring approximating a geographic circle.
10070
- *
10071
- * The ring is computed with an equirectangular approximation: meters are
10072
- * converted to degrees independently per axis, with the longitude scale
10073
- * corrected by the cosine of the latitude. For the radii the SDK works with
10074
- * (tens to hundreds of meters) the metric error is negligible (≤1%) at any latitude
10075
- * where the projection is defined. At extreme polar latitudes, the approximation
10076
- * breaks down, so circles near poles (|lat| > 85°) should be used with caution.
10077
- *
10078
- * @param lng Longitude of the circle center in degrees.
10079
- * @param lat Latitude of the circle center in degrees.
10080
- * @param radiusMeters Radius of the circle in meters. Must be positive and finite.
10081
- * @param points Number of segments in the ring. Defaults to 64. Non-integer
10082
- * values are floored and the count is clamped to a minimum of 3,
10083
- * the smallest valid GeoJSON linear ring; non-finite values fall
10084
- * back to the default.
10085
- * @returns A closed ring of `[lng, lat]` positions (first equals last).
10086
+ * Basic configuration for the map.
10087
+ * Provides essential settings for initializing and customizing map behavior.
10086
10088
  *
10087
10089
  * @example
10088
10090
  * ```typescript
10089
- * import { circleRing } from '@mapvx/web-js';
10090
- *
10091
- * // Create a 150-meter radius circle ring
10092
- * const ring = circleRing(-74.0060, 40.7128, 150);
10093
- * const polygon = { type: "Polygon", coordinates: [ring] };
10094
- *
10095
- * // Custom segments (32 instead of 64) for lower resolution
10096
- * const coarseRing = circleRing(-74.0060, 40.7128, 150, 32);
10091
+ * const mapConfig: MapConfig = {
10092
+ * zoom: 15,
10093
+ * center: { lat: 40.7128, lng: -74.0060 },
10094
+ * parentPlaceId: "building-1",
10095
+ * onMapReady: () => console.log("Map is ready!"),
10096
+ * enableHover: true,
10097
+ * showCompass: true
10098
+ * };
10097
10099
  * ```
10098
10100
  *
10099
- * @note Equirectangular approximation is accurate for radii up to ~500 km and
10100
- * latitudes between approximately ±80°. Beyond these limits, visual
10101
- * distortion may occur near the poles.
10102
- * @note Generated rings do not account for geographic obstacles, walls, or
10103
- * buildings. For complex geofencing, consider server-side validation.
10101
+ * @group Map
10104
10102
  *
10105
- * @group Circles
10103
+ * @property zoom - The initial zoom level of the map.
10104
+ * @property center - The initial center coordinates of the map.
10105
+ * @property parentPlaceId - (Optional) The ID of the parent place to display.
10106
+ * @property otherPotentialParentPlacesIds - (Optional) List of alternative parent place IDs.
10107
+ * @property onMapReady - (Optional) Callback invoked when the map is ready.
10108
+ * @property onZoomEnd - (Optional) Callback invoked when the zoom operation ends. Receives the new zoom level.
10109
+ * @property onRotate - (Optional) Callback invoked when the map is rotated. Receives the rotation in degrees.
10110
+ * @property onFloorChange - (Optional) Callback invoked when the floor changes. Receives the new floor ID.
10111
+ * @property onParentPlaceChange - (Optional) Callback invoked when the parent place changes. Receives the new parent place ID.
10112
+ * @property lang - (Optional) Language code for map labels and UI.
10113
+ * @property minZoom - (Optional) Minimum allowed zoom level.
10114
+ * @property maxZoom - (Optional) Maximum allowed zoom level.
10115
+ * @property pitch - (Optional) The pitch (tilt) of the map in degrees.
10116
+ * @property maxBounds - (Optional) Array of coordinates defining the maximum bounds of the map.
10117
+ * @property enableHover - (Optional) Whether to enable hover interactions on the map.
10118
+ * @property showCompass - (Optional) Whether to display the compass control.
10119
+ * @property showZoom - (Optional) Whether to display the zoom control.
10120
+ * @property navigationPosition - (Optional) Position of the navigation controls on the map.
10121
+ * @property bearingSnap - (Optional) The bearing snap threshold in degrees.
10122
+ * @property bearing - (Optional) Initial bearing (rotation) of the map in degrees, clockwise from north.
10123
+ * @property interactive - (Optional) Master switch for all user interaction (pan/zoom/rotate).
10124
+ * @property rotateEnabled - (Optional) Whether the user can rotate the map; keeps pinch-zoom when disabled.
10125
+ * @property dragPan - (Optional) Whether the user can pan by dragging/swiping.
10126
+ * @property scrollZoom - (Optional) Whether the scroll wheel/trackpad can zoom the map.
10127
+ * @property doubleClickZoom - (Optional) Whether double-click/double-tap zooms the map.
10128
+ * @property touchZoomRotate - (Optional) Whether pinch gestures can zoom the map on touch devices.
10129
+ * @property keyboard - (Optional) Whether keyboard shortcuts can pan/zoom/rotate the map.
10130
+ * @property institutionId - (Optional) The institution identifier for map context. Required for loading map related data from Portal.
10131
+ * @property authToken - (Optional) Authentication token for accessing protected map resources. Required for loading map related data from Portal.
10132
+ * @property apiUrl - (Optional) Injected by SDK when creating map; base API URL for map requests.
10133
+ * @property mapvxRequestContext - (Optional) Injected by SDK when creating map; context sent as headers to public-api.mapvx.com.
10106
10134
  */
10107
- function circleRing(lng, lat, radiusMeters) {
10108
- var points = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 64;
10109
- // A linear ring needs at least 3 distinct positions to be valid GeoJSON
10110
- var segments = Number.isFinite(points) ? Math.max(3, Math.floor(points)) : 64;
10111
- var ring = [];
10112
- var latRad = lat * Math.PI / 180;
10113
- var metersPerDegLat = 110574;
10114
- var metersPerDegLng = 111320 * Math.cos(latRad || 0.000001);
10115
- var latR = radiusMeters / metersPerDegLat;
10116
- var lngR = radiusMeters / (metersPerDegLng || 1);
10117
- for (var i = 0; i < segments; i += 1) {
10118
- var a = i / segments * Math.PI * 2;
10119
- ring.push([lng + lngR * Math.cos(a), lat + latR * Math.sin(a)]);
10120
- }
10121
- // Close the ring with an exact copy of the first position, as GeoJSON requires
10122
- ring.push([ring[0][0], ring[0][1]]);
10123
- return ring;
10124
- }
10125
10135
  ;// ./node_modules/.pnpm/@googlemaps+polyline-codec@1.0.28/node_modules/@googlemaps/polyline-codec/dist/index.esm.js
10126
10136
  /**
10127
10137
  * Copyright 2020 Google LLC
@@ -11764,17 +11774,107 @@ var Requester = /*#__PURE__*/function () {
11764
11774
  }
11765
11775
  return fetchAnySubPlaces;
11766
11776
  }()
11777
+ /**
11778
+ * Build the cleaned query parameters for a route request.
11779
+ *
11780
+ * Resolves both the origin (`from*`) and destination (`to*`) sides of the route
11781
+ * from the provided configuration. For {@link IdLocation} endpoints this also
11782
+ * forwards the building (`fromBuilding`/`toBuilding`) and floor
11783
+ * (`fromFloor`/`toFloor`) so internal aliases that are reused across buildings
11784
+ * can be disambiguated. Parameters that resolve to `null`/`undefined` are dropped.
11785
+ * @param routeConfig The route configuration to translate into query params.
11786
+ * @returns The cleaned query parameters ready to be appended to the request URL.
11787
+ */
11788
+ )
11789
+ }, {
11790
+ key: "buildRouteParams",
11791
+ value: function buildRouteParams(routeConfig) {
11792
+ var params = {
11793
+ fromLatLng: undefined,
11794
+ fromBuilding: undefined,
11795
+ fromFloor: undefined,
11796
+ toLatLng: undefined,
11797
+ toBuilding: undefined,
11798
+ toFloor: undefined,
11799
+ fromPlaceId: undefined,
11800
+ toPlaceId: undefined,
11801
+ travelMode: TransportationMode.walking,
11802
+ reducedMobility: routeConfig.preferAccessibleRoute ? 1 : 0,
11803
+ announceFormat: routeConfig.announceFormat,
11804
+ userBearing: routeConfig.userBearing,
11805
+ lang: this.lang,
11806
+ unitSystem: routeConfig.unitSystem
11807
+ };
11808
+ if ("id" in routeConfig.initialLocation) {
11809
+ var _routeConfig$initialL = routeConfig.initialLocation,
11810
+ id = _routeConfig$initialL.id,
11811
+ buildingId = _routeConfig$initialL.buildingId,
11812
+ floorId = _routeConfig$initialL.floorId,
11813
+ level = _routeConfig$initialL.level;
11814
+ params.fromPlaceId = id;
11815
+ if (buildingId !== undefined) {
11816
+ params.fromBuilding = buildingId;
11817
+ }
11818
+ if (floorId !== undefined) {
11819
+ params.fromFloor = floorId;
11820
+ } else if (level !== undefined) {
11821
+ params.fromFloor = level;
11822
+ }
11823
+ } else {
11824
+ var _routeConfig$initialL2 = routeConfig.initialLocation,
11825
+ lat = _routeConfig$initialL2.lat,
11826
+ lng = _routeConfig$initialL2.lng,
11827
+ _floorId = _routeConfig$initialL2.floorId,
11828
+ placeId = _routeConfig$initialL2.placeId;
11829
+ params.fromLatLng = "".concat(lat, ",").concat(lng);
11830
+ params.fromFloor = _floorId;
11831
+ params.fromBuilding = placeId;
11832
+ }
11833
+ if ("id" in routeConfig.finalLocation) {
11834
+ var _routeConfig$finalLoc = routeConfig.finalLocation,
11835
+ _id = _routeConfig$finalLoc.id,
11836
+ _buildingId = _routeConfig$finalLoc.buildingId,
11837
+ _floorId2 = _routeConfig$finalLoc.floorId,
11838
+ _level = _routeConfig$finalLoc.level;
11839
+ params.toPlaceId = _id;
11840
+ if (_buildingId !== undefined) {
11841
+ params.toBuilding = _buildingId;
11842
+ }
11843
+ if (_floorId2 !== undefined) {
11844
+ params.toFloor = _floorId2;
11845
+ } else if (_level !== undefined) {
11846
+ params.toFloor = _level;
11847
+ }
11848
+ } else {
11849
+ var _routeConfig$finalLoc2 = routeConfig.finalLocation,
11850
+ _lat = _routeConfig$finalLoc2.lat,
11851
+ _lng = _routeConfig$finalLoc2.lng,
11852
+ _floorId3 = _routeConfig$finalLoc2.floorId,
11853
+ _placeId = _routeConfig$finalLoc2.placeId;
11854
+ params.toLatLng = "".concat(_lat, ",").concat(_lng);
11855
+ params.toFloor = _floorId3;
11856
+ params.toBuilding = _placeId;
11857
+ }
11858
+ var cleanParams = {};
11859
+ for (var key in params) {
11860
+ var value = params[key];
11861
+ if (value != null) {
11862
+ cleanParams[key] = value;
11863
+ }
11864
+ }
11865
+ return cleanParams;
11866
+ }
11867
+
11767
11868
  /**
11768
11869
  * To obtain the route
11769
11870
  * @param routeConfig
11770
11871
  * @returns
11771
11872
  */
11772
- )
11773
11873
  }, {
11774
11874
  key: "fetchRoute",
11775
11875
  value: (function () {
11776
11876
  var _fetchRoute = requester_asyncToGenerator(/*#__PURE__*/requester_regenerator().m(function _callee10(routeConfig, token) {
11777
- var options, params, _routeConfig$initialL, lat, lng, floorId, placeId, _routeConfig$finalLoc, _lat, _lng, _floorId, _placeId, cleanParams, key, value;
11877
+ var options, cleanParams;
11778
11878
  return requester_regenerator().w(function (_context10) {
11779
11879
  while (1) switch (_context10.n) {
11780
11880
  case 0:
@@ -11785,51 +11885,7 @@ var Requester = /*#__PURE__*/function () {
11785
11885
  Authorization: "Bearer ".concat(token)
11786
11886
  }
11787
11887
  };
11788
- params = {
11789
- fromLatLng: undefined,
11790
- fromBuilding: undefined,
11791
- fromFloor: undefined,
11792
- toLatLng: undefined,
11793
- toBuilding: undefined,
11794
- toFloor: undefined,
11795
- fromPlaceId: undefined,
11796
- toPlaceId: undefined,
11797
- travelMode: TransportationMode.walking,
11798
- reducedMobility: routeConfig.preferAccessibleRoute ? 1 : 0,
11799
- announceFormat: routeConfig.announceFormat,
11800
- userBearing: routeConfig.userBearing,
11801
- lang: this.lang,
11802
- unitSystem: routeConfig.unitSystem
11803
- };
11804
- if ("id" in routeConfig.initialLocation) {
11805
- params.fromPlaceId = routeConfig.initialLocation.id;
11806
- if (routeConfig.initialLocation.level !== undefined) {
11807
- params.fromFloor = routeConfig.initialLocation.level;
11808
- }
11809
- } else {
11810
- _routeConfig$initialL = routeConfig.initialLocation, lat = _routeConfig$initialL.lat, lng = _routeConfig$initialL.lng, floorId = _routeConfig$initialL.floorId, placeId = _routeConfig$initialL.placeId;
11811
- params.fromLatLng = "".concat(lat, ",").concat(lng);
11812
- params.fromFloor = floorId;
11813
- params.fromBuilding = placeId;
11814
- }
11815
- if ("id" in routeConfig.finalLocation) {
11816
- params.toPlaceId = routeConfig.finalLocation.id;
11817
- if (routeConfig.finalLocation.level !== undefined) {
11818
- params.toFloor = routeConfig.finalLocation.level;
11819
- }
11820
- } else {
11821
- _routeConfig$finalLoc = routeConfig.finalLocation, _lat = _routeConfig$finalLoc.lat, _lng = _routeConfig$finalLoc.lng, _floorId = _routeConfig$finalLoc.floorId, _placeId = _routeConfig$finalLoc.placeId;
11822
- params.toLatLng = "".concat(_lat, ",").concat(_lng);
11823
- params.toFloor = _floorId;
11824
- params.toBuilding = _placeId;
11825
- }
11826
- cleanParams = {};
11827
- for (key in params) {
11828
- value = params[key];
11829
- if (value != null) {
11830
- cleanParams[key] = value;
11831
- }
11832
- }
11888
+ cleanParams = this.buildRouteParams(routeConfig);
11833
11889
  return _context10.a(2, this.fetchFromUrl(this.routeBaseUrl + "route", cleanParams, options));
11834
11890
  }
11835
11891
  }, _callee10, this);
@@ -11849,7 +11905,7 @@ var Requester = /*#__PURE__*/function () {
11849
11905
  key: "fetchRouteV2",
11850
11906
  value: (function () {
11851
11907
  var _fetchRouteV = requester_asyncToGenerator(/*#__PURE__*/requester_regenerator().m(function _callee11(routeConfig, token) {
11852
- var options, params, _routeConfig$initialL2, lat, lng, floorId, placeId, _routeConfig$finalLoc2, _lat2, _lng2, _floorId2, _placeId2, cleanParams, key, value;
11908
+ var options, cleanParams;
11853
11909
  return requester_regenerator().w(function (_context11) {
11854
11910
  while (1) switch (_context11.n) {
11855
11911
  case 0:
@@ -11860,51 +11916,7 @@ var Requester = /*#__PURE__*/function () {
11860
11916
  Authorization: "Bearer ".concat(token)
11861
11917
  }
11862
11918
  };
11863
- params = {
11864
- fromLatLng: undefined,
11865
- fromBuilding: undefined,
11866
- fromFloor: undefined,
11867
- toLatLng: undefined,
11868
- toBuilding: undefined,
11869
- toFloor: undefined,
11870
- fromPlaceId: undefined,
11871
- toPlaceId: undefined,
11872
- travelMode: TransportationMode.walking,
11873
- reducedMobility: routeConfig.preferAccessibleRoute ? 1 : 0,
11874
- announceFormat: routeConfig.announceFormat,
11875
- userBearing: routeConfig.userBearing,
11876
- lang: this.lang,
11877
- unitSystem: routeConfig.unitSystem
11878
- };
11879
- if ("id" in routeConfig.initialLocation) {
11880
- params.fromPlaceId = routeConfig.initialLocation.id;
11881
- if (routeConfig.initialLocation.level !== undefined) {
11882
- params.fromFloor = routeConfig.initialLocation.level;
11883
- }
11884
- } else {
11885
- _routeConfig$initialL2 = routeConfig.initialLocation, lat = _routeConfig$initialL2.lat, lng = _routeConfig$initialL2.lng, floorId = _routeConfig$initialL2.floorId, placeId = _routeConfig$initialL2.placeId;
11886
- params.fromLatLng = "".concat(lat, ",").concat(lng);
11887
- params.fromFloor = floorId;
11888
- params.fromBuilding = placeId;
11889
- }
11890
- if ("id" in routeConfig.finalLocation) {
11891
- params.toPlaceId = routeConfig.finalLocation.id;
11892
- if (routeConfig.finalLocation.level !== undefined) {
11893
- params.toFloor = routeConfig.finalLocation.level;
11894
- }
11895
- } else {
11896
- _routeConfig$finalLoc2 = routeConfig.finalLocation, _lat2 = _routeConfig$finalLoc2.lat, _lng2 = _routeConfig$finalLoc2.lng, _floorId2 = _routeConfig$finalLoc2.floorId, _placeId2 = _routeConfig$finalLoc2.placeId;
11897
- params.toLatLng = "".concat(_lat2, ",").concat(_lng2);
11898
- params.toFloor = _floorId2;
11899
- params.toBuilding = _placeId2;
11900
- }
11901
- cleanParams = {};
11902
- for (key in params) {
11903
- value = params[key];
11904
- if (value != null) {
11905
- cleanParams[key] = value;
11906
- }
11907
- }
11919
+ cleanParams = this.buildRouteParams(routeConfig);
11908
11920
  return _context11.a(2, this.fetchFromUrl(this.routeBaseUrl + "v2/route", cleanParams, options));
11909
11921
  }
11910
11922
  }, _callee11, this);
@@ -13670,6 +13682,197 @@ function extractStepCoordinates(step) {
13670
13682
  }
13671
13683
  return coords;
13672
13684
  }
13685
+ ;// ./src/map/fitCamera.ts
13686
+ function fitCamera_createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = fitCamera_unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
13687
+ function fitCamera_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return fitCamera_arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? fitCamera_arrayLikeToArray(r, a) : void 0; } }
13688
+ function fitCamera_arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13689
+
13690
+
13691
+ /**
13692
+ * Padding, in pixels, already resolved from any unit-based {@link PaddingOptions}.
13693
+ */
13694
+
13695
+ /**
13696
+ * A camera target (center + zoom) that fits a set of coordinates.
13697
+ */
13698
+
13699
+ /**
13700
+ * Parameters shared by the flat and pitch-aware fit computations.
13701
+ */
13702
+
13703
+ /**
13704
+ * Minimal structural view of a maplibre transform clone (`map.transform.clone()`).
13705
+ *
13706
+ * We depend on the shape rather than the (non-exported) `ITransform` interface so
13707
+ * the coupling stays explicit and version changes surface as type errors here.
13708
+ */
13709
+
13710
+ /** maplibre world size (px) at zoom 0: tileSize (512) * 2^0. */
13711
+ var TILE_SIZE = 512;
13712
+ var clamp = function clamp(value, min, max) {
13713
+ return Math.min(Math.max(value, min), max);
13714
+ };
13715
+
13716
+ /**
13717
+ * Compute the camera (center + zoom) that tightly fits `coordinates` into the
13718
+ * padded viewport for a given bearing, using an ORIENTED bounding box.
13719
+ *
13720
+ * maplibre's `fitBounds` only fits a north-up `LngLatBounds`, which wastes
13721
+ * viewport space for diagonal geometries under a bearing. Instead we rotate the
13722
+ * mercator-projected points by the bearing, measure their axis-aligned extent in
13723
+ * that rotated frame, and derive zoom + center analytically.
13724
+ *
13725
+ * This calculation is orthographic (assumes `pitch: 0`). For a tilted camera use
13726
+ * {@link refineCameraForPitch} to correct for perspective.
13727
+ *
13728
+ * @param coordinates Points to fit (must contain at least one).
13729
+ * @param params Bearing, padding and viewport constraints.
13730
+ * @returns The fitting camera center and zoom.
13731
+ */
13732
+ function computeOrientedCamera(coordinates, params) {
13733
+ var bearing = params.bearing,
13734
+ padding = params.padding,
13735
+ containerWidth = params.containerWidth,
13736
+ containerHeight = params.containerHeight,
13737
+ maxZoom = params.maxZoom,
13738
+ minZoom = params.minZoom;
13739
+
13740
+ // Rotate the mercator plane by -bearing so the target bearing becomes axis-aligned.
13741
+ var rad = -bearing * Math.PI / 180;
13742
+ var cos = Math.cos(rad);
13743
+ var sin = Math.sin(rad);
13744
+ var minX = Infinity;
13745
+ var minY = Infinity;
13746
+ var maxX = -Infinity;
13747
+ var maxY = -Infinity;
13748
+ var _iterator = fitCamera_createForOfIteratorHelper(coordinates),
13749
+ _step;
13750
+ try {
13751
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
13752
+ var coord = _step.value;
13753
+ var m = maplibre_gl.MercatorCoordinate.fromLngLat({
13754
+ lat: coord.lat,
13755
+ lng: coord.lng
13756
+ });
13757
+ var rx = m.x * cos - m.y * sin;
13758
+ var ry = m.x * sin + m.y * cos;
13759
+ minX = Math.min(minX, rx);
13760
+ minY = Math.min(minY, ry);
13761
+ maxX = Math.max(maxX, rx);
13762
+ maxY = Math.max(maxY, ry);
13763
+ }
13764
+ } catch (err) {
13765
+ _iterator.e(err);
13766
+ } finally {
13767
+ _iterator.f();
13768
+ }
13769
+ var boxW = maxX - minX || Number.EPSILON;
13770
+ var boxH = maxY - minY || Number.EPSILON;
13771
+ var availW = Math.max(1, containerWidth - padding.left - padding.right);
13772
+ var availH = Math.max(1, containerHeight - padding.top - padding.bottom);
13773
+
13774
+ // worldSize (px) = TILE_SIZE * 2^zoom
13775
+ var worldSize = Math.min(availW / boxW, availH / boxH);
13776
+ var zoom = clamp(Math.log2(worldSize / TILE_SIZE), minZoom, maxZoom);
13777
+
13778
+ // Center of the oriented box, rotated back to geographic space.
13779
+ var cxr = (minX + maxX) / 2;
13780
+ var cyr = (minY + maxY) / 2;
13781
+ var center = new maplibre_gl.MercatorCoordinate(cxr * cos + cyr * sin, -cxr * sin + cyr * cos, 0).toLngLat();
13782
+ return {
13783
+ center: center,
13784
+ zoom: zoom
13785
+ };
13786
+ }
13787
+
13788
+ /**
13789
+ * Refine a fit camera for a non-zero pitch.
13790
+ *
13791
+ * With `pitch > 0` the ground-to-screen mapping is non-linear (perspective), so
13792
+ * the orthographic result from {@link computeOrientedCamera} either overshoots
13793
+ * (geometry spills past the padding) or leaves extra space. This iteratively
13794
+ * projects every point through maplibre's real perspective projection on a cloned
13795
+ * transform (no visible camera movement) and adjusts zoom + center until the
13796
+ * projected bounding box fits the padded viewport.
13797
+ *
13798
+ * If any point falls behind the horizon during refinement, it bails out and
13799
+ * returns the best camera computed so far (never worse than the flat input).
13800
+ *
13801
+ * @param transform A `map.transform.clone()` used purely for projection.
13802
+ * @param coordinates Points to fit.
13803
+ * @param initial The orthographic camera to refine.
13804
+ * @param params Bearing, pitch, padding and viewport constraints.
13805
+ * @returns The refined camera center and zoom.
13806
+ */
13807
+ function refineCameraForPitch(transform, coordinates, initial, params) {
13808
+ var bearing = params.bearing,
13809
+ pitch = params.pitch,
13810
+ padding = params.padding,
13811
+ containerWidth = params.containerWidth,
13812
+ containerHeight = params.containerHeight,
13813
+ maxZoom = params.maxZoom,
13814
+ minZoom = params.minZoom;
13815
+ transform.setBearing(bearing);
13816
+ transform.setPitch(pitch);
13817
+ transform.setPadding(padding);
13818
+ transform.setCenter(initial.center);
13819
+ transform.setZoom(initial.zoom);
13820
+ var availW = Math.max(1, containerWidth - padding.left - padding.right);
13821
+ var availH = Math.max(1, containerHeight - padding.top - padding.bottom);
13822
+ var MAX_ITERATIONS = 4;
13823
+ var CONVERGENCE_EPSILON = 0.01;
13824
+ var best = {
13825
+ center: initial.center,
13826
+ zoom: initial.zoom
13827
+ };
13828
+ for (var i = 0; i < MAX_ITERATIONS; i++) {
13829
+ var minX = Infinity;
13830
+ var minY = Infinity;
13831
+ var maxX = -Infinity;
13832
+ var maxY = -Infinity;
13833
+ var allOnSurface = true;
13834
+ var _iterator2 = fitCamera_createForOfIteratorHelper(coordinates),
13835
+ _step2;
13836
+ try {
13837
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
13838
+ var coord = _step2.value;
13839
+ var screen = transform.locationToScreenPoint(new maplibre_gl.LngLat(coord.lng, coord.lat));
13840
+ if (!transform.isPointOnMapSurface(screen)) {
13841
+ allOnSurface = false;
13842
+ break;
13843
+ }
13844
+ minX = Math.min(minX, screen.x);
13845
+ minY = Math.min(minY, screen.y);
13846
+ maxX = Math.max(maxX, screen.x);
13847
+ maxY = Math.max(maxY, screen.y);
13848
+ }
13849
+ // A point behind the horizon makes the projected box meaningless; keep the
13850
+ // last valid camera rather than risk an over-zoomed result.
13851
+ } catch (err) {
13852
+ _iterator2.e(err);
13853
+ } finally {
13854
+ _iterator2.f();
13855
+ }
13856
+ if (!allOnSurface) break;
13857
+
13858
+ // Recenter: move the projected box center onto the padded screen center.
13859
+ var boxCenter = new maplibre_gl.Point((minX + maxX) / 2, (minY + maxY) / 2);
13860
+ transform.setCenter(transform.screenPointToLocation(boxCenter));
13861
+
13862
+ // Rescale zoom so the projected box fills the padded viewport.
13863
+ var boxW = Math.max(maxX - minX, 1e-6);
13864
+ var boxH = Math.max(maxY - minY, 1e-6);
13865
+ var scale = Math.min(availW / boxW, availH / boxH);
13866
+ var zoomDelta = Math.log2(scale);
13867
+ transform.setZoom(clamp(transform.zoom + zoomDelta, minZoom, maxZoom));
13868
+ best = {
13869
+ center: transform.center,
13870
+ zoom: transform.zoom
13871
+ };
13872
+ if (Math.abs(zoomDelta) < CONVERGENCE_EPSILON) break;
13873
+ }
13874
+ return best;
13875
+ }
13673
13876
  ;// ./src/map/mapInteractionOptions.ts
13674
13877
  /**
13675
13878
  * Subset of MapLibre {@link MapOptions} that can be derived from the interaction
@@ -13920,6 +14123,7 @@ function convertPaddingToPixels(padding, containerWidth, containerHeight) {
13920
14123
 
13921
14124
 
13922
14125
 
14126
+
13923
14127
  /**
13924
14128
  * @group Map
13925
14129
  */
@@ -15141,6 +15345,71 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
15141
15345
  this.map.fitBounds(bounds, fitOptions);
15142
15346
  }
15143
15347
  }
15348
+ }, {
15349
+ key: "easeToCoordinates",
15350
+ value: function easeToCoordinates(coordinates, options) {
15351
+ var _options$maxZoom;
15352
+ if (coordinates.length === 0) {
15353
+ return;
15354
+ }
15355
+ var onComplete = options === null || options === void 0 ? void 0 : options.onComplete;
15356
+
15357
+ // Get container dimensions for percentage-based padding calculations
15358
+ var container = this.map.getContainer();
15359
+ var containerWidth = container.clientWidth;
15360
+ var containerHeight = container.clientHeight;
15361
+
15362
+ // Convert padding values with units to pixels
15363
+ var padding = convertPaddingToPixels(options === null || options === void 0 ? void 0 : options.padding, containerWidth, containerHeight);
15364
+ if (coordinates.length === 1) {
15365
+ var _coordinates2 = map_slicedToArray(coordinates, 1),
15366
+ coord = _coordinates2[0];
15367
+ if (onComplete) {
15368
+ void this.map.once("moveend", onComplete);
15369
+ }
15370
+ this.map.easeTo(map_objectSpread(map_objectSpread({}, options), {}, {
15371
+ center: {
15372
+ lat: coord.lat,
15373
+ lng: coord.lng
15374
+ },
15375
+ padding: padding
15376
+ }));
15377
+ return;
15378
+ }
15379
+ var bearing = (options === null || options === void 0 ? void 0 : options.bearing) !== undefined ? options.bearing : this.map.getBearing();
15380
+ var pitch = (options === null || options === void 0 ? void 0 : options.pitch) !== undefined ? options.pitch : this.map.getPitch();
15381
+ var cameraParams = {
15382
+ bearing: bearing,
15383
+ padding: padding,
15384
+ containerWidth: containerWidth,
15385
+ containerHeight: containerHeight,
15386
+ maxZoom: (_options$maxZoom = options === null || options === void 0 ? void 0 : options.maxZoom) !== null && _options$maxZoom !== void 0 ? _options$maxZoom : this.map.getMaxZoom(),
15387
+ minZoom: this.map.getMinZoom()
15388
+ };
15389
+
15390
+ // Orthographic oriented fit (exact for pitch 0). maplibre's fitBounds only
15391
+ // fits a north-up LngLatBounds, which wastes viewport space for diagonal
15392
+ // geometries under a bearing.
15393
+ var camera = computeOrientedCamera(coordinates, cameraParams);
15394
+
15395
+ // With a tilted camera the orthographic zoom is off due to perspective, so
15396
+ // refine it against maplibre's real projection on a cloned transform.
15397
+ if (pitch > 0) {
15398
+ camera = refineCameraForPitch(this.map.transform.clone(), coordinates, camera, map_objectSpread(map_objectSpread({}, cameraParams), {}, {
15399
+ pitch: pitch
15400
+ }));
15401
+ }
15402
+ if (onComplete) {
15403
+ void this.map.once("moveend", onComplete);
15404
+ }
15405
+ this.map.easeTo(map_objectSpread(map_objectSpread({}, options), {}, {
15406
+ center: camera.center,
15407
+ zoom: camera.zoom,
15408
+ bearing: bearing,
15409
+ pitch: pitch,
15410
+ padding: padding
15411
+ }));
15412
+ }
15144
15413
  }, {
15145
15414
  key: "fitRouteByPlace",
15146
15415
  value: function fitRouteByPlace(route, placeId, options) {