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) {