From 506aed17eff2d8a80fd712b2c6fd80db65be4a30 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Sun, 3 May 2026 12:37:17 +1000 Subject: [PATCH] fix: avoid recentering google maps on inline options --- .../GoogleMaps/ScriptGoogleMaps.vue | 21 ++++++++++-- test/unit/google-maps-regressions.test.ts | 32 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue b/packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue index 98d0c75d6..d82afc180 100644 --- a/packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +++ b/packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue @@ -259,6 +259,21 @@ function isLocationQuery(s: string | any) { return typeof s === 'string' && (s.split(',').length > 2 || s.includes('+')) } +type ScriptGoogleMapsCenter = ScriptGoogleMapsProps['center'] | google.maps.MapOptions['center'] + +function getCenterWatchKey(center: ScriptGoogleMapsCenter): string | undefined { + const raw = toRaw(center) + if (!raw) + return undefined + if (typeof raw === 'string') + return `query:${raw}` + const lat = typeof (raw as any).lat === 'function' ? (raw as any).lat() : (raw as any).lat + const lng = typeof (raw as any).lng === 'function' ? (raw as any).lng() : (raw as any).lng + if (lat != null && lng != null) + return `latlng:${lat},${lng}` + return undefined +} + const queryToLatLngCache = new Map() async function resolveQueryToLatLng(query: string) { @@ -449,14 +464,14 @@ onMounted(() => { // Clear centerOverride when the controlled center prop changes so external // updates take effect (otherwise centerOverride, written from the user's // pan during re-init, would permanently win over future prop updates). - watch([() => props.center, () => props.mapOptions?.center], () => { + watch([() => getCenterWatchKey(props.center), () => getCenterWatchKey(props.mapOptions?.center)], () => { centerOverride.value = undefined }) - watch([() => options.value.center, isMapReady, map], async (next) => { + watch([() => getCenterWatchKey(options.value.center), isMapReady, map], async () => { if (!map.value) { return } - let center = toRaw(next[0]) + let center = toRaw(options.value.center) if (center) { if (isLocationQuery(center) && isMapReady.value) { center = await resolveQueryToLatLng(center as string) diff --git a/test/unit/google-maps-regressions.test.ts b/test/unit/google-maps-regressions.test.ts index ecf0025ac..b0af3b00a 100644 --- a/test/unit/google-maps-regressions.test.ts +++ b/test/unit/google-maps-regressions.test.ts @@ -455,6 +455,38 @@ describe('google Maps Regressions', () => { expect(map.setCenter).not.toHaveBeenCalled() }) + + it('uses a stable center watch key for equivalent inline mapOptions centers', () => { + function getCenterWatchKey(center: any) { + if (!center) + return undefined + if (typeof center === 'string') + return `query:${center}` + const lat = typeof center.lat === 'function' ? center.lat() : center.lat + const lng = typeof center.lng === 'function' ? center.lng() : center.lng + if (lat != null && lng != null) + return `latlng:${lat},${lng}` + return center + } + + const firstRender = { center: { lat: -34.397, lng: 150.644 }, zoom: 8 } + const secondRender = { center: { lat: -34.397, lng: 150.644 }, zoom: 8 } + + expect(firstRender.center).not.toBe(secondRender.center) + expect(getCenterWatchKey(firstRender.center)).toBe(getCenterWatchKey(secondRender.center)) + }) + + it('changes the center watch key when coordinates actually change', () => { + function getCenterWatchKey(center: any) { + const lat = typeof center.lat === 'function' ? center.lat() : center.lat + const lng = typeof center.lng === 'function' ? center.lng() : center.lng + return `latlng:${lat},${lng}` + } + + expect(getCenterWatchKey({ lat: -34.397, lng: 150.644 })) + .not + .toBe(getCenterWatchKey({ lat: -34.387, lng: 150.654 })) + }) }) describe('infoWindow group close', () => {