@mapvx/web-js 1.2.2 → 1.3.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/domain/models/categories.js +23 -10
  2. package/dist/cjs/domain/models/categories.js.map +1 -1
  3. package/dist/cjs/domain/models/marker.js +86 -80
  4. package/dist/cjs/domain/models/marker.js.map +1 -1
  5. package/dist/cjs/domain/models/routeConfiguration.js +3 -1
  6. package/dist/cjs/domain/models/routeConfiguration.js.map +1 -1
  7. package/dist/cjs/index.js +13 -12
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/logger/logger.js +1 -1
  10. package/dist/cjs/logger/rollbar.js +1 -1
  11. package/dist/cjs/map/map.js +448 -4
  12. package/dist/cjs/map/map.js.map +1 -1
  13. package/dist/cjs/repository/requester.js +48 -65
  14. package/dist/cjs/repository/requester.js.map +1 -1
  15. package/dist/cjs/utils/3d.js +12 -0
  16. package/dist/cjs/utils/3d.js.map +1 -0
  17. package/dist/es/domain/models/categories.d.ts +34 -10
  18. package/dist/es/domain/models/categories.d.ts.map +1 -1
  19. package/dist/es/domain/models/categories.js +21 -9
  20. package/dist/es/domain/models/categories.js.map +1 -1
  21. package/dist/es/domain/models/mapConfig.d.ts +11 -0
  22. package/dist/es/domain/models/mapConfig.d.ts.map +1 -1
  23. package/dist/es/domain/models/marker.d.ts +8 -0
  24. package/dist/es/domain/models/marker.d.ts.map +1 -1
  25. package/dist/es/domain/models/marker.js +86 -80
  26. package/dist/es/domain/models/marker.js.map +1 -1
  27. package/dist/es/domain/models/routeConfiguration.d.ts +47 -0
  28. package/dist/es/domain/models/routeConfiguration.d.ts.map +1 -1
  29. package/dist/es/domain/models/routeConfiguration.js +3 -1
  30. package/dist/es/domain/models/routeConfiguration.js.map +1 -1
  31. package/dist/es/index.d.ts +12 -12
  32. package/dist/es/index.d.ts.map +1 -1
  33. package/dist/es/index.js +6 -6
  34. package/dist/es/index.js.map +1 -1
  35. package/dist/es/logger/logger.js +1 -1
  36. package/dist/es/logger/rollbar.js +1 -1
  37. package/dist/es/map/map.d.ts +27 -1
  38. package/dist/es/map/map.d.ts.map +1 -1
  39. package/dist/es/map/map.js +449 -5
  40. package/dist/es/map/map.js.map +1 -1
  41. package/dist/es/repository/requester.d.ts +12 -0
  42. package/dist/es/repository/requester.d.ts.map +1 -1
  43. package/dist/es/repository/requester.js +48 -65
  44. package/dist/es/repository/requester.js.map +1 -1
  45. package/dist/es/utils/3d.d.ts +2 -0
  46. package/dist/es/utils/3d.d.ts.map +1 -0
  47. package/dist/es/utils/3d.js +8 -0
  48. package/dist/es/utils/3d.js.map +1 -0
  49. package/dist/umd/index.js +154088 -2173
  50. package/dist/umd/index.js.map +1 -1
  51. package/dist/umd/styles.css +32 -14
  52. package/dist/umd/styles.css.map +1 -1
  53. package/package.json +19 -5
@@ -24,7 +24,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.InternalMapVXMap = void 0;
27
+ const geo_layers_1 = require("@deck.gl/geo-layers");
28
+ const layers_1 = require("@deck.gl/layers");
27
29
  const maplibre_gl_1 = __importStar(require("maplibre-gl"));
30
+ const THREE = __importStar(require("three"));
31
+ const GLTFLoader_js_1 = require("three/examples/jsm/loaders/GLTFLoader.js");
28
32
  const semaphore_1 = require("../utils/semaphore");
29
33
  /** Shared GeoJSON source holding every circle drawn through the circle API. */
30
34
  const CIRCLE_SOURCE_ID = "mapvx-circles";
@@ -153,19 +157,20 @@ function convertPaddingToPixels(padding, containerWidth, containerHeight) {
153
157
  right: parsePaddingValue(padding.right, containerWidth),
154
158
  };
155
159
  }
160
+ const mapbox_1 = require("@deck.gl/mapbox");
156
161
  const icons_1 = require("../assets/icons");
157
162
  const routeController_1 = require("../controllers/routeController");
158
163
  const _rtl_1 = require("../domain/models/_rtl");
159
164
  const animation_1 = require("../domain/models/animation");
165
+ const circle_1 = require("../domain/models/circle");
160
166
  const loggeable_1 = require("../domain/models/loggeable");
161
167
  const mapConfig_1 = require("../domain/models/mapConfig");
162
- const circle_1 = require("../domain/models/circle");
163
168
  const marker_1 = require("../domain/models/marker");
164
169
  const route_1 = require("../domain/models/route");
165
170
  const routeConfiguration_1 = require("../domain/models/routeConfiguration");
166
171
  const repository_1 = require("../repository/repository");
167
- const utils_1 = require("../utils/utils");
168
172
  const route_utils_1 = require("../utils/route-utils");
173
+ const utils_1 = require("../utils/utils");
169
174
  const mapInteractionOptions_1 = require("./mapInteractionOptions");
170
175
  /**
171
176
  * Class to interact with the map.
@@ -182,7 +187,7 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
182
187
  * @returns A new instance of MapVXMap.
183
188
  */
184
189
  constructor(mapConfig, container, token) {
185
- var _a, _b;
190
+ var _a, _b, _c;
186
191
  super();
187
192
  this.potentialParentPlaces = [];
188
193
  this.innerFloors = [];
@@ -195,6 +200,22 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
195
200
  this.hoveredId = "unselected";
196
201
  this.failedTiles = new Set();
197
202
  this.geoLocation = navigator.geolocation;
203
+ // 3d related variables
204
+ this.mode = "2D";
205
+ this.deckOverlay = undefined;
206
+ this.escalatorScene = undefined;
207
+ this.escalatorModelTemplate = undefined;
208
+ this.escalatorCenter = undefined;
209
+ this.escalatorCache = {};
210
+ this.ESCALATOR_MODEL_URL = "https://mapvx-glb-assets.s3.us-east-1.amazonaws.com/shared/escalator.glb";
211
+ /**
212
+ * Number of lights to use for the escalators
213
+ *
214
+ */
215
+ this.ESCALATOR_LIGHTS = 3;
216
+ this.SPRITE_URL = "https://lazarillo.app/internal/maps/vector-style/cenco-cl-pe-co-ar-3D/sprites_cencosud";
217
+ this.spriteIconMapping = {};
218
+ this.spriteAtlasImage = new Image();
198
219
  if (_rtl_1.rtlLanguages.includes((_a = mapConfig.lang) !== null && _a !== void 0 ? _a : "")) {
199
220
  this.setRTLSupport();
200
221
  }
@@ -206,11 +227,16 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
206
227
  this.watchPositionID = undefined;
207
228
  this.onFloorChange = mapConfig.onFloorChange;
208
229
  this.onParentPlaceChange = mapConfig.onParentPlaceChange;
230
+ this.mode = (_c = mapConfig.mode) !== null && _c !== void 0 ? _c : "2D";
231
+ this.initialCenter = mapConfig.center;
209
232
  this.tileCacheConfig = (() => {
210
233
  const merged = Object.assign(Object.assign({}, mapConfig_1.DEFAULT_TILE_CACHE_CONFIG), mapConfig.tileCache);
211
234
  merged.maxTiles = Math.min(merged.maxTiles, mapConfig_1.MAPLIBRE_MAX_TILE_CACHE_HARD_CAP);
212
235
  return merged;
213
236
  })();
237
+ if (this.mode === "3D") {
238
+ this.loadSpriteAtlas().catch(console.error);
239
+ }
214
240
  if (mapConfig.parentPlaceId != null) {
215
241
  this.initialPlaceDetailSetUp(mapConfig.parentPlaceId, mapConfig.authToken);
216
242
  }
@@ -338,6 +364,30 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
338
364
  }), (_e = mapConfig.navigationPosition) !== null && _e !== void 0 ? _e : "top-right");
339
365
  this.map.on("load", () => {
340
366
  var _a;
367
+ if (this.mode === "3D") {
368
+ this.deckOverlay = new mapbox_1.MapboxOverlay({ layers: [] });
369
+ this.map.addControl(this.deckOverlay);
370
+ this.hideIndoorSymbolLayers();
371
+ // Hide MapLibre icon layers — replaced by deck.gl IconLayer
372
+ this.map.setLayoutProperty("indoor-poi-logo", "visibility", "none");
373
+ const style = this.map.getStyle();
374
+ for (const layer of style.layers) {
375
+ if (layer.id.startsWith("indoor-logo-tiendas-ancla")) {
376
+ this.map.setLayoutProperty(layer.id, "visibility", "none");
377
+ }
378
+ }
379
+ // Add 3D escalator layer and hide 2D transportation line
380
+ this.map.addLayer(this.createEscalatorLayer());
381
+ this.map.setPaintProperty("indoor-transportation", "line-opacity", 0);
382
+ // Capture escalator positions when new tiles arrive (stops once cached)
383
+ this.map.on("sourcedata", (e) => {
384
+ if (e.sourceId === "indoorequal" &&
385
+ this.currentFloor &&
386
+ !this.escalatorCache[this.currentFloor]) {
387
+ this.placeEscalators();
388
+ }
389
+ });
390
+ }
341
391
  this.whenStyleUpdates(style);
342
392
  if (mapConfig.lang)
343
393
  this.setLayersForLanguage(mapConfig.lang);
@@ -360,7 +410,6 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
360
410
  (_a = mapConfig.onRotate) === null || _a === void 0 ? void 0 : _a.call(mapConfig, this.map.getBearing());
361
411
  });
362
412
  this.defaultClickListener();
363
- return this.map;
364
413
  }
365
414
  setBaseFilters(style) {
366
415
  if (!style)
@@ -489,6 +538,386 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
489
538
  // Tile cache clear may fail if cache doesn't exist
490
539
  }
491
540
  }
541
+ // Start 3D related methods ------------------------------------------------------------
542
+ hideIndoorSymbolLayers() {
543
+ var _a, _b;
544
+ const style = this.map.getStyle();
545
+ for (const layer of style.layers) {
546
+ if (layer.type === "symbol" && layer.id.startsWith("indoor-")) {
547
+ const hasText = !!((_a = layer.layout) === null || _a === void 0 ? void 0 : _a["text-field"]);
548
+ const hasIcon = !!((_b = layer.layout) === null || _b === void 0 ? void 0 : _b["icon-image"]);
549
+ // Hide text-only layers (replaced by deck.gl)
550
+ if (hasText && !hasIcon) {
551
+ this.map.setLayoutProperty(layer.id, "visibility", "none");
552
+ }
553
+ }
554
+ }
555
+ }
556
+ createEscalatorLayer() {
557
+ const refMercator = maplibre_gl_1.MercatorCoordinate.fromLngLat(this.initialCenter, 0);
558
+ const meterScale = refMercator.meterInMercatorCoordinateUnits();
559
+ const modelTransform = new THREE.Matrix4()
560
+ .makeTranslation(refMercator.x, refMercator.y, refMercator.z)
561
+ .scale(new THREE.Vector3(meterScale, -meterScale, meterScale))
562
+ .multiply(new THREE.Matrix4().makeRotationX(Math.PI / 2));
563
+ this.escalatorScene = new THREE.Scene();
564
+ const dirLight = new THREE.DirectionalLight(0xffffff, 2.0);
565
+ dirLight.position.set(50, 100, 80);
566
+ this.escalatorScene.add(dirLight);
567
+ const dirLight2 = new THREE.DirectionalLight(0xffffff, 1.5);
568
+ dirLight2.position.set(-50, 80, -60);
569
+ this.escalatorScene.add(dirLight2);
570
+ this.escalatorScene.add(new THREE.AmbientLight(0xffffff, 1.5));
571
+ new GLTFLoader_js_1.GLTFLoader().load(this.ESCALATOR_MODEL_URL, (gltf) => {
572
+ this.escalatorModelTemplate = gltf.scene;
573
+ const box = new THREE.Box3().setFromObject(this.escalatorModelTemplate);
574
+ this.escalatorCenter = box.getCenter(new THREE.Vector3());
575
+ this.escalatorCenter.y = box.min.y; // align bottom to ground
576
+ this.placeEscalators();
577
+ });
578
+ let renderer = undefined;
579
+ let camera = undefined;
580
+ const tmpMatrix = new THREE.Matrix4();
581
+ return {
582
+ id: "3d-escalators",
583
+ type: "custom",
584
+ renderingMode: "3d",
585
+ onAdd(_map, gl) {
586
+ camera = new THREE.Camera();
587
+ renderer = new THREE.WebGLRenderer({
588
+ canvas: _map.getCanvas(),
589
+ context: gl,
590
+ antialias: true,
591
+ });
592
+ renderer.autoClear = false;
593
+ },
594
+ render: (gl, args) => {
595
+ var _a, _b;
596
+ if (!camera ||
597
+ !renderer ||
598
+ !this.escalatorModelTemplate ||
599
+ !this.escalatorScene ||
600
+ this.escalatorScene.children.length <= this.ESCALATOR_LIGHTS)
601
+ return;
602
+ const matrixData = (_b = (_a = args === null || args === void 0 ? void 0 : args.defaultProjectionData) === null || _a === void 0 ? void 0 : _a.mainMatrix) !== null && _b !== void 0 ? _b : args;
603
+ tmpMatrix.fromArray(matrixData).multiply(modelTransform);
604
+ camera.projectionMatrix.copy(tmpMatrix);
605
+ renderer.resetState();
606
+ renderer.render(this.escalatorScene, camera);
607
+ },
608
+ };
609
+ }
610
+ placeEscalators() {
611
+ if (!this.escalatorModelTemplate ||
612
+ !this.escalatorScene ||
613
+ !this.currentFloor ||
614
+ !this.escalatorCenter)
615
+ return;
616
+ // Try to capture positions if not cached yet
617
+ this.captureEscalatorPositions();
618
+ const positions = this.escalatorCache[this.currentFloor];
619
+ if (!positions)
620
+ return;
621
+ // Clear scene models (keep lights)
622
+ while (this.escalatorScene.children.length > this.ESCALATOR_LIGHTS) {
623
+ const lastChild = this.escalatorScene.children.at(-1);
624
+ if (lastChild) {
625
+ this.escalatorScene.remove(lastChild);
626
+ }
627
+ }
628
+ const refMercator = maplibre_gl_1.MercatorCoordinate.fromLngLat(this.initialCenter, 0);
629
+ const meterScale = refMercator.meterInMercatorCoordinateUnits();
630
+ for (const pos of positions) {
631
+ const target = maplibre_gl_1.default.MercatorCoordinate.fromLngLat([pos.lng, pos.lat], 0);
632
+ const sx = (target.x - refMercator.x) / meterScale;
633
+ const sz = (target.y - refMercator.y) / meterScale;
634
+ const pivot = new THREE.Group();
635
+ pivot.position.set(sx, 0, sz);
636
+ pivot.rotation.y = Math.PI / 2 - pos.bearing;
637
+ pivot.scale.set(0.3, 0.3, 0.3);
638
+ const model = this.escalatorModelTemplate.clone();
639
+ model.position.set(-this.escalatorCenter.x, -this.escalatorCenter.y - 3, -this.escalatorCenter.z);
640
+ pivot.add(model);
641
+ this.escalatorScene.add(pivot);
642
+ }
643
+ this.map.triggerRepaint();
644
+ }
645
+ captureEscalatorPositions() {
646
+ if (this.currentFloor && this.escalatorCache[this.currentFloor])
647
+ return;
648
+ // queryRenderedFeatures uses exact rendered coordinates (not tile-approximated)
649
+ const features = this.map
650
+ .queryRenderedFeatures(undefined, {
651
+ layers: ["indoor-transportation"],
652
+ })
653
+ .filter((f) => { var _a; return ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.floor_key) === this.currentFloor; });
654
+ if (!features.length)
655
+ return;
656
+ // Collect all midpoints first
657
+ const allMids = [];
658
+ for (const f of features) {
659
+ const coords = f.geometry.coordinates;
660
+ if (!coords || coords.length < 2)
661
+ continue;
662
+ const start = coords[0];
663
+ const end = coords[coords.length - 1];
664
+ const midLng = (start[0] + end[0]) / 2;
665
+ const midLat = (start[1] + end[1]) / 2;
666
+ const bearing = Math.atan2(end[0] - start[0], end[1] - start[1]);
667
+ allMids.push({ lng: midLng, lat: midLat, bearing });
668
+ }
669
+ // Merge points within ~15m of each other into one
670
+ const MERGE_DEG = 0.00015; // ~15m
671
+ const positions = [];
672
+ const used = new Set();
673
+ for (let i = 0; i < allMids.length; i++) {
674
+ if (used.has(i))
675
+ continue;
676
+ used.add(i);
677
+ const group = [allMids[i]];
678
+ for (let j = i + 1; j < allMids.length; j++) {
679
+ if (used.has(j))
680
+ continue;
681
+ const dLng = allMids[i].lng - allMids[j].lng;
682
+ const dLat = allMids[i].lat - allMids[j].lat;
683
+ if (Math.abs(dLng) < MERGE_DEG && Math.abs(dLat) < MERGE_DEG) {
684
+ used.add(j);
685
+ group.push(allMids[j]);
686
+ }
687
+ }
688
+ // Use average position and first bearing
689
+ const avgLng = group.reduce((s, p) => s + p.lng, 0) / group.length;
690
+ const avgLat = group.reduce((s, p) => s + p.lat, 0) / group.length;
691
+ positions.push({ lng: avgLng, lat: avgLat, bearing: group[0].bearing });
692
+ }
693
+ if (positions.length && this.currentFloor) {
694
+ this.escalatorCache[this.currentFloor] = positions;
695
+ }
696
+ }
697
+ async loadSpriteAtlas() {
698
+ const [json, img] = await Promise.all([
699
+ fetch(`${this.SPRITE_URL}.json`).then((r) => r.json()),
700
+ new Promise((resolve, reject) => {
701
+ const image = new Image();
702
+ image.crossOrigin = "anonymous";
703
+ image.onload = () => resolve(image);
704
+ image.onerror = reject;
705
+ image.src = `${this.SPRITE_URL}.png`;
706
+ }),
707
+ ]);
708
+ this.spriteIconMapping = json;
709
+ this.spriteAtlasImage = img;
710
+ }
711
+ makeMVTLayer(floorKey) {
712
+ return new geo_layers_1.MVTLayer({
713
+ id: "indoor-lines-elevated",
714
+ data: "https://tiles.mapvx.com/",
715
+ binary: false,
716
+ renderSubLayers: (props) => {
717
+ var _a;
718
+ const roomData = (props.data || []);
719
+ const roomFeatures = roomData.filter((f) => {
720
+ var _a, _b, _c;
721
+ return ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.class) === "room" &&
722
+ ((_b = f.properties) === null || _b === void 0 ? void 0 : _b.subclass) !== "empty" &&
723
+ ((_c = f.properties) === null || _c === void 0 ? void 0 : _c.floor_key) === floorKey;
724
+ });
725
+ if (!roomFeatures.length)
726
+ return null;
727
+ const paths = [];
728
+ for (const f of roomFeatures) {
729
+ const z = ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height) ? Number(f.properties.height) : 5;
730
+ const geom = f.geometry;
731
+ const polygons = geom.type === "Polygon"
732
+ ? [geom.coordinates]
733
+ : geom.type === "MultiPolygon"
734
+ ? geom.coordinates
735
+ : [];
736
+ for (const rings of polygons) {
737
+ for (const ring of rings) {
738
+ paths.push({ path: ring.map(([lon, lat]) => [lon, lat, z]) });
739
+ }
740
+ }
741
+ }
742
+ return new layers_1.PathLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-paths`, data: paths, getPath: (d) => d.path, getColor: [203, 203, 203], getWidth: 1.5, widthUnits: "pixels", pickable: false }));
743
+ },
744
+ updateTriggers: {
745
+ renderSubLayers: [floorKey],
746
+ },
747
+ });
748
+ }
749
+ makeLabelLayer(floorKey, useSdf = true) {
750
+ return new geo_layers_1.MVTLayer({
751
+ id: "indoor-labels",
752
+ data: "https://tiles.mapvx.com/",
753
+ binary: false,
754
+ minZoom: 19.5,
755
+ maxZoom: 24,
756
+ renderSubLayers: (props) => {
757
+ // Use area_name and poi Point features — unique per tile, no duplicates
758
+ // If logo-{name} image exists in sprite, icon has priority over text label
759
+ const labelData = (props.data || []);
760
+ const labelFeatures = labelData.filter((f) => {
761
+ var _a, _b, _c, _d, _e, _f;
762
+ if (((_a = f.properties) === null || _a === void 0 ? void 0 : _a.layerName) !== "area_name" && ((_b = f.properties) === null || _b === void 0 ? void 0 : _b.layerName) !== "poi")
763
+ return false;
764
+ if (((_c = f.geometry) === null || _c === void 0 ? void 0 : _c.type) !== "Point")
765
+ return false;
766
+ const name = ((_d = f.properties) === null || _d === void 0 ? void 0 : _d["name:latin"]) || ((_e = f.properties) === null || _e === void 0 ? void 0 : _e.name);
767
+ if (!name)
768
+ return false;
769
+ if (((_f = f.properties) === null || _f === void 0 ? void 0 : _f.floor_key) && f.properties.floor_key !== floorKey)
770
+ return false;
771
+ if (this.map.hasImage("logo-" + name))
772
+ return false; // icon has priority
773
+ return true;
774
+ });
775
+ if (!labelFeatures.length)
776
+ return null;
777
+ const textData = labelFeatures.map((f) => {
778
+ var _a, _b, _c;
779
+ return ({
780
+ position: [
781
+ ...f.geometry.coordinates.slice(0, 2),
782
+ ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height) ? Number(f.properties.height) : 5,
783
+ ],
784
+ text: ((_b = f.properties) === null || _b === void 0 ? void 0 : _b["name:latin"]) || ((_c = f.properties) === null || _c === void 0 ? void 0 : _c.name) || "",
785
+ });
786
+ });
787
+ return new layers_1.TextLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-labels`, data: textData, getPosition: (d) => d.position, getText: (d) => d.text, getSize: 16, getColor: [145, 150, 155, 255], outlineColor: useSdf ? [255, 255, 255, 255] : [0, 0, 0, 0], outlineWidth: useSdf ? 4 : 0, fontSettings: { sdf: useSdf }, fontFamily: "Open Sans, sans-serif", fontWeight: 600, billboard: true, pickable: false, characterSet: "auto", wordBreak: "break-word", maxWidth: 150 }));
788
+ },
789
+ updateTriggers: {
790
+ renderSubLayers: [floorKey],
791
+ },
792
+ });
793
+ }
794
+ makePoiIconLayer(floorKey) {
795
+ if (!this.spriteIconMapping || !this.spriteAtlasImage)
796
+ return null;
797
+ return new geo_layers_1.MVTLayer({
798
+ id: "indoor-poi-icons",
799
+ data: "https://tiles.mapvx.com/",
800
+ binary: false,
801
+ minZoom: 17,
802
+ maxZoom: 24,
803
+ renderSubLayers: (props) => {
804
+ const poiData = (props.data || []);
805
+ const poiFeatures = poiData.filter((f) => {
806
+ var _a, _b, _c;
807
+ if (((_a = f.geometry) === null || _a === void 0 ? void 0 : _a.type) !== "Point")
808
+ return false;
809
+ if (((_b = f.properties) === null || _b === void 0 ? void 0 : _b.floor_key) && f.properties.floor_key !== floorKey)
810
+ return false;
811
+ const sub = (_c = f.properties) === null || _c === void 0 ? void 0 : _c.subclass;
812
+ return sub === "elevator" || sub === "toilets";
813
+ });
814
+ if (!poiFeatures.length)
815
+ return null;
816
+ const iconData = poiFeatures.map((f) => {
817
+ var _a, _b, _c;
818
+ const tags = ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.tags) || "";
819
+ let icon;
820
+ if (tags.includes("wheelchair"))
821
+ icon = "accessible_toilets";
822
+ else if (tags.includes("changing_table"))
823
+ icon = "changing_table";
824
+ else
825
+ icon = ((_b = f.properties) === null || _b === void 0 ? void 0 : _b.subclass) || "";
826
+ return {
827
+ position: [
828
+ ...f.geometry.coordinates.slice(0, 2),
829
+ ((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : 5,
830
+ ],
831
+ icon,
832
+ };
833
+ });
834
+ return new layers_1.IconLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-poi-icons`, data: iconData, iconAtlas: this.spriteAtlasImage, iconMapping: this.spriteIconMapping, getIcon: (d) => d.icon, getPosition: (d) => d.position, getSize: 2, sizeUnits: "meters", sizeScale: 1, billboard: true, pickable: false }));
835
+ },
836
+ updateTriggers: {
837
+ renderSubLayers: [floorKey],
838
+ },
839
+ });
840
+ }
841
+ makeStoreLogoLayer(floorKey) {
842
+ if (!this.spriteIconMapping || !this.spriteAtlasImage)
843
+ return null;
844
+ return new geo_layers_1.MVTLayer({
845
+ id: "indoor-store-logos",
846
+ data: "https://tiles.mapvx.com/",
847
+ binary: false,
848
+ minZoom: 13,
849
+ maxZoom: 24,
850
+ renderSubLayers: (props) => {
851
+ const propsData = (props.data || []);
852
+ const logoFeatures = propsData.filter((f) => {
853
+ var _a, _b, _c;
854
+ if (((_a = f.geometry) === null || _a === void 0 ? void 0 : _a.type) !== "Point")
855
+ return false;
856
+ if (((_b = f.properties) === null || _b === void 0 ? void 0 : _b.floor_key) && f.properties.floor_key !== floorKey)
857
+ return false;
858
+ const name = (_c = f.properties) === null || _c === void 0 ? void 0 : _c.name;
859
+ if (!name)
860
+ return false;
861
+ return !!this.spriteIconMapping["logo-" + name];
862
+ });
863
+ if (!logoFeatures.length)
864
+ return null;
865
+ const logoData = logoFeatures.map((f) => {
866
+ var _a, _b, _c;
867
+ const name = (_a = f.properties) === null || _a === void 0 ? void 0 : _a.name;
868
+ const icon = "logo-" + name;
869
+ const rotation = ((_b = f.properties) === null || _b === void 0 ? void 0 : _b.rotation_icon) ? Number(f.properties.rotation_icon) : 0;
870
+ return {
871
+ position: [
872
+ ...f.geometry.coordinates.slice(0, 2),
873
+ ((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : 5,
874
+ ],
875
+ icon,
876
+ rotation,
877
+ };
878
+ });
879
+ return new layers_1.IconLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-store-logos`, data: logoData, iconAtlas: this.spriteAtlasImage, iconMapping: this.spriteIconMapping, getIcon: (d) => d.icon, getPosition: (d) => d.position, getAngle: (d) => -d.rotation, getSize: (d) => {
880
+ const LOGO_SCALE = {
881
+ "logo-Maxi-K": 0.4,
882
+ "logo-Ripley": 2,
883
+ "logo-Falabella": 2,
884
+ "logo-CasaIdeas": 2,
885
+ "logo-Sky Costanera": 0.6,
886
+ "logo-Easy": 1.4,
887
+ "logo-Jumbo": 2,
888
+ "logo-Decathlon": 1.4,
889
+ };
890
+ const m = this.spriteIconMapping[d.icon];
891
+ if (!m)
892
+ return 10;
893
+ const pr = m.pixelRatio;
894
+ const w = m.width / pr;
895
+ const h = m.height / pr;
896
+ const base = 10 * (h / Math.max(w, h));
897
+ return base * (LOGO_SCALE[d.icon] || 1);
898
+ }, sizeUnits: "meters", sizeScale: 1, billboard: false, pickable: false }));
899
+ },
900
+ updateTriggers: {
901
+ renderSubLayers: [floorKey],
902
+ },
903
+ });
904
+ }
905
+ updateDeckOverlay() {
906
+ if (!this.deckOverlay || !this.currentFloor)
907
+ return;
908
+ const layers = [
909
+ this.makeMVTLayer(this.currentFloor),
910
+ this.makeLabelLayer(this.currentFloor, false),
911
+ ];
912
+ const poiLayer = this.makePoiIconLayer(this.currentFloor);
913
+ if (poiLayer)
914
+ layers.push(poiLayer);
915
+ const storeLayer = this.makeStoreLogoLayer(this.currentFloor);
916
+ if (storeLayer)
917
+ layers.push(storeLayer);
918
+ this.deckOverlay.setProps({ layers });
919
+ }
920
+ // End 3D related methods ------------------------------------------------------------
492
921
  getCurrentFloor() {
493
922
  var _a;
494
923
  return (_a = this.currentFloor) !== null && _a !== void 0 ? _a : "";
@@ -508,6 +937,10 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
508
937
  if (place) {
509
938
  this.subPlacesLoad(place.mapvxId);
510
939
  }
940
+ if (this.mode === "3D") {
941
+ this.updateDeckOverlay();
942
+ this.placeEscalators();
943
+ }
511
944
  if (updateStyle) {
512
945
  this.repository
513
946
  .fetchAndParseMapStyle(place === null || place === void 0 ? void 0 : place.mapvxId)
@@ -536,6 +969,10 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
536
969
  this.innerFloors = (_a = place === null || place === void 0 ? void 0 : place.innerFloors.sort((a, b) => a.index - b.index)) !== null && _a !== void 0 ? _a : [];
537
970
  this.currentFloor =
538
971
  (_e = (_c = floorId !== null && floorId !== void 0 ? floorId : (_b = this.innerFloors.find((floor) => floor.defaultFloor)) === null || _b === void 0 ? void 0 : _b.key) !== null && _c !== void 0 ? _c : (_d = this.innerFloors[0]) === null || _d === void 0 ? void 0 : _d.key) !== null && _e !== void 0 ? _e : "";
972
+ if (this.mode === "3D") {
973
+ this.updateDeckOverlay();
974
+ this.placeEscalators();
975
+ }
539
976
  }
540
977
  updateParentPlaceAndFloor(parentPlaceId, floorId, options) {
541
978
  var _a, _b, _c, _d;
@@ -588,6 +1025,9 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
588
1025
  this.routeController.addSourcesAndLayers();
589
1026
  this.refreshCircles();
590
1027
  this.filterByFloorKey(this.currentFloor);
1028
+ if (this.mode === "3D") {
1029
+ this.updateDeckOverlay();
1030
+ }
591
1031
  }
592
1032
  addMarker(marker) {
593
1033
  var _a, _b;
@@ -1016,6 +1456,10 @@ class InternalMapVXMap extends loggeable_1.Loggeable {
1016
1456
  if (this.innerFloors.every((floor) => floor.key !== floorKey) && floorKey !== "") {
1017
1457
  this.logEvent("invalidFloorKey", { floorKey: floorKeyString });
1018
1458
  }
1459
+ if (this.mode === "3D") {
1460
+ this.updateDeckOverlay();
1461
+ this.placeEscalators();
1462
+ }
1019
1463
  this.updateFiltersTo(floorKeyString);
1020
1464
  this.updateMarkersTo(floorKeyString);
1021
1465
  this.refreshCircles();