diff --git a/package-lock.json b/package-lock.json
index bf9957f70..32a77fcfd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25841,7 +25841,7 @@
},
"packages/map-template": {
"name": "@mapsindoors/map-template",
- "version": "1.96.14",
+ "version": "1.96.15",
"dependencies": {
"@mapsindoors/components": "*",
"@mapsindoors/css": "^3.0.0",
diff --git a/packages/map-template/CHANGELOG.md b/packages/map-template/CHANGELOG.md
index 776203f81..85ff52cee 100644
--- a/packages/map-template/CHANGELOG.md
+++ b/packages/map-template/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.96.16] - 2026-03-25
+
+### Fixed
+
+- Upgraded to Web SDK 4.56.0.
+
## [1.96.15] - 2026-03-24
### Fixed
diff --git a/packages/map-template/index.html b/packages/map-template/index.html
index 4d0a9d247..2486b348e 100644
--- a/packages/map-template/index.html
+++ b/packages/map-template/index.html
@@ -6,8 +6,8 @@
MapsIndoors Web
-
diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx
index 2ec4aa697..92cf2f865 100644
--- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx
+++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx
@@ -236,8 +236,8 @@ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, p
const miSdkApiTag = document.createElement('script');
miSdkApiTag.setAttribute('type', 'text/javascript');
// Remember to update the root index.html with the same version / integrity
- miSdkApiTag.setAttribute('src', 'https://app.mapsindoors.com/mapsindoors/js/sdk/4.55.0/mapsindoors-4.55.0.js.gz');
- miSdkApiTag.setAttribute('integrity', 'sha384-oW7TEiuEViUPGMgbrtXn96vWoBrrtrT+tYYCaVNll6KZTr8GWS5dqjV0sdJOcyhk');
+ miSdkApiTag.setAttribute('src', 'https://app.mapsindoors.com/mapsindoors/js/sdk/4.56.0/mapsindoors-4.56.0.js.gz');
+ miSdkApiTag.setAttribute('integrity', 'sha384-jNY73YbOtdlv5xKtZYwPDPMWFym59MhTK1MAfgFrT1kheVpr+LvomZTbuETxf2lj');
miSdkApiTag.setAttribute('crossorigin', 'anonymous');
document.body.appendChild(miSdkApiTag);
miSdkApiTag.onload = () => {
@@ -587,6 +587,7 @@ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, p
if (currentLocation && currentLocation.id !== kioskOriginLocationId) {
if (mapsIndoorsInstance?.selectLocation) {
+ mapsIndoorsInstance.highlight?.([]);
mapsIndoorsInstance.selectLocation(currentLocation);
}
} else {
diff --git a/packages/map-template/src/components/MapWrapper/MapWrapper.jsx b/packages/map-template/src/components/MapWrapper/MapWrapper.jsx
index e689ba637..929e83259 100644
--- a/packages/map-template/src/components/MapWrapper/MapWrapper.jsx
+++ b/packages/map-template/src/components/MapWrapper/MapWrapper.jsx
@@ -12,6 +12,7 @@ import gmApiKeyState from '../../atoms/gmApiKeyState';
import mapboxAccessTokenState from '../../atoms/mapboxAccessTokenState';
import filteredLocationsState from '../../atoms/filteredLocationsState';
import filteredLocationsByExternalIDState from '../../atoms/filteredLocationsByExternalIDState';
+import currentLocationState from '../../atoms/currentLocationState';
import tileStyleState from '../../atoms/tileStyleState';
import positionControlState from '../../atoms/positionControlState';
import bearingState from '../../atoms/bearingState';
@@ -78,6 +79,7 @@ function MapWrapper({ onLocationClick, onMapPositionKnown, useMapProviderModule,
const setDirectionsService = useSetRecoilState(directionsServiceState);
const filteredLocations = useRecoilValue(filteredLocationsState);
const filteredLocationsByExternalIDs = useRecoilValue(filteredLocationsByExternalIDState);
+ const currentLocation = useRecoilValue(currentLocationState);
const tileStyle = useRecoilValue(tileStyleState);
const bearing = useRecoilValue(bearingState);
const pitch = useRecoilValue(pitchState);
@@ -175,17 +177,23 @@ function MapWrapper({ onLocationClick, onMapPositionKnown, useMapProviderModule,
* Dynamically filter or highlight location based on the "filteredLocations", "filteredLocationsByExternalIDs" and "hideNonMatches" property.
*/
useEffect(() => {
+ if (!mapsIndoorsInstance) return;
+
const locations = filteredLocations || filteredLocationsByExternalIDs;
- if (!locations || locations.length === 0 || !mapsIndoorsInstance) return;
+
+ if (currentLocation || !locations || locations.length === 0) {
+ mapsIndoorsInstance.highlight?.([]);
+ return;
+ }
+
const locationIds = locations.map(location => location.id);
- // Check if the hideNonMatches prop or highlight method in the SDK exists
if (hideNonMatches || !mapsIndoorsInstance.highlight) {
mapsIndoorsInstance.filter(locationIds);
} else {
mapsIndoorsInstance.highlight(locationIds);
}
- }, [filteredLocations, filteredLocationsByExternalIDs, mapsIndoorsInstance, hideNonMatches]);
+ }, [filteredLocations, filteredLocationsByExternalIDs, mapsIndoorsInstance, hideNonMatches, currentLocation]);
/*
* React to changes in bearing and pitch props and set them on the map if mapsIndoorsInstance exists.
diff --git a/packages/map-template/src/components/Search/Search.jsx b/packages/map-template/src/components/Search/Search.jsx
index 5537b8e17..296d472cc 100644
--- a/packages/map-template/src/components/Search/Search.jsx
+++ b/packages/map-template/src/components/Search/Search.jsx
@@ -37,6 +37,8 @@ import isNullOrUndefined from '../../helpers/isNullOrUndefined';
import venuesInSolutionState from '../../atoms/venuesInSolutionState';
import initialVenueNameState from '../../atoms/initialVenueNameState';
import primaryColorState from '../../atoms/primaryColorState';
+import mapTypeState from '../../atoms/mapTypeState';
+import { mapTypes } from '../../constants/mapTypes';
import PropTypes from 'prop-types';
Search.propTypes = {
@@ -88,6 +90,7 @@ function Search({ onSetSize, isOpen, onOpenChat }) {
const [hoveredLocation, setHoveredLocation] = useState();
const mapsIndoorsInstance = useRecoilValue(mapsIndoorsInstanceState);
+ const mapType = useRecoilValue(mapTypeState);
const setFilteredLocations = useSetRecoilState(filteredLocationsState);
@@ -372,8 +375,6 @@ function Search({ onSetSize, isOpen, onOpenChat }) {
* @param {object} location
*/
function onLocationClicked(location) {
- setCurrentLocation(location);
-
// Set the current venue to be the selected location venue.
if (location.properties.venueId.toLowerCase() !== currentVenueName.toLowerCase()) {
setCurrentVenueName(location.properties.venueId);
@@ -383,9 +384,23 @@ function Search({ onSetSize, isOpen, onOpenChat }) {
const currentFloor = mapsIndoorsInstance.getFloor();
const locationFloor = location.properties.floor;
- // Set the floor to the one that the location belongs to.
if (locationFloor !== currentFloor) {
+ // Register listener before setFloor — floor_changed fires
+ // synchronously inside setFloor(), so it would be missed otherwise.
+ mapsIndoorsInstance.once('floor_changed', () => {
+ const map = mapsIndoorsInstance.getMap();
+ if (mapType === mapTypes.Mapbox) {
+ map.once('idle', () => setCurrentLocation(location));
+ } else if (mapType === mapTypes.Google) {
+ const listener = map.addListener('idle', () => {
+ listener.remove();
+ setCurrentLocation(location);
+ });
+ }
+ });
mapsIndoorsInstance.setFloor(locationFloor);
+ } else {
+ setCurrentLocation(location);
}
Promise.all([getBottomPadding(), getLeftPadding()]).then(([bottomPadding, leftPadding]) => {
diff --git a/packages/map-template/src/components/WebComponentWrappers/ListItemLocation/ListItemLocation.jsx b/packages/map-template/src/components/WebComponentWrappers/ListItemLocation/ListItemLocation.jsx
index ed3bda887..c78fed89b 100644
--- a/packages/map-template/src/components/WebComponentWrappers/ListItemLocation/ListItemLocation.jsx
+++ b/packages/map-template/src/components/WebComponentWrappers/ListItemLocation/ListItemLocation.jsx
@@ -5,8 +5,6 @@ import { useTranslation } from 'react-i18next';
import './ListItemLocation.scss';
import showExternalIDsState from '../../../atoms/showExternalIDsState';
import PropTypes from 'prop-types';
-import { debounce } from 'lodash';
-
ListItemLocation.propTypes = {
location: PropTypes.object,
locationClicked: PropTypes.func,
@@ -34,25 +32,22 @@ function ListItemLocation({ location, locationClicked, icon, isHovered, disableH
const showExternalIDs = useRecoilValue(showExternalIDsState);
useEffect(() => {
- const clickHandler = customEvent => locationClicked(customEvent.detail);
- const hoverHandler = debounce(() => {
- // Skip hover functionality if disabled (e.g., during routing to prevent dual pins)
+ const clickHandler = customEvent => {
+ mapsIndoorsInstance.unhoverLocation();
+ locationClicked(customEvent.detail);
+ };
+ const hoverHandler = () => {
if (disableHover) return;
-
- // Check if the location is non-selectable before hovering it
if (location.properties.locationSettings?.selectable !== false) {
mapsIndoorsInstance.hoverLocation(location);
}
- }, 150);
- const unhoverHandler = debounce(() => {
- // Skip unhover functionality if disabled
+ };
+ const unhoverHandler = () => {
if (disableHover) return;
-
- // Check if the location is non-selectable before unhovering it
if (location.properties.locationSettings?.selectable !== false) {
mapsIndoorsInstance.unhoverLocation(location);
}
- }, 150);
+ };
// Add a "non-selectable" class to the non-selectable locations.
if (location.properties.locationSettings?.selectable === false) {