@vis.gl/react-google-maps
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -7,2 +7,12 @@ /// <reference types="google.maps" /> | ||
} | ||
/** | ||
* Copy of the `google.maps.CollisionBehavior` constants. | ||
* They have to be duplicated here since we can't wait for the maps API to load to be able to use them. | ||
*/ | ||
export declare const CollisionBehavior: { | ||
readonly REQUIRED: "REQUIRED"; | ||
readonly REQUIRED_AND_HIDES_OPTIONAL: "REQUIRED_AND_HIDES_OPTIONAL"; | ||
readonly OPTIONAL_AND_HIDES_LOWER_PRIORITY: "OPTIONAL_AND_HIDES_LOWER_PRIORITY"; | ||
}; | ||
export type CollisionBehavior = (typeof CollisionBehavior)[keyof typeof CollisionBehavior]; | ||
export declare const AdvancedMarkerContext: React.Context<AdvancedMarkerContextValue | null>; | ||
@@ -15,3 +25,6 @@ type AdvancedMarkerEventProps = { | ||
}; | ||
export type AdvancedMarkerProps = PropsWithChildren<Omit<google.maps.marker.AdvancedMarkerElementOptions, 'gmpDraggable' | 'map'> & AdvancedMarkerEventProps & { | ||
export type AdvancedMarkerProps = PropsWithChildren<Omit<google.maps.marker.AdvancedMarkerElementOptions, 'gmpDraggable' | 'gmpClickable' | 'content' | 'map' | 'collisionBehavior'> & AdvancedMarkerEventProps & { | ||
draggable?: boolean; | ||
clickable?: boolean; | ||
collisionBehavior?: CollisionBehavior; | ||
/** | ||
@@ -26,6 +39,8 @@ * A className for the content element. | ||
style?: CSSProperties; | ||
draggable?: boolean; | ||
}>; | ||
export type AdvancedMarkerRef = google.maps.marker.AdvancedMarkerElement | null; | ||
export declare const AdvancedMarker: React.ForwardRefExoticComponent<Omit<google.maps.marker.AdvancedMarkerElementOptions, "gmpDraggable" | "map"> & AdvancedMarkerEventProps & { | ||
export declare const AdvancedMarker: React.ForwardRefExoticComponent<Omit<google.maps.marker.AdvancedMarkerElementOptions, "gmpDraggable" | "gmpClickable" | "content" | "map" | "collisionBehavior"> & AdvancedMarkerEventProps & { | ||
draggable?: boolean | undefined; | ||
clickable?: boolean | undefined; | ||
collisionBehavior?: CollisionBehavior | undefined; | ||
/** | ||
@@ -40,3 +55,2 @@ * A className for the content element. | ||
style?: React.CSSProperties | undefined; | ||
draggable?: boolean | undefined; | ||
} & { | ||
@@ -43,0 +57,0 @@ children?: React.ReactNode; |
@@ -37,2 +37,6 @@ /// <reference types="google.maps" /> | ||
controlled?: boolean; | ||
/** | ||
* Enable caching of map-instances created by this component. | ||
*/ | ||
reuseMaps?: boolean; | ||
defaultCenter?: google.maps.LatLngLiteral; | ||
@@ -39,0 +43,0 @@ defaultZoom?: number; |
@@ -11,3 +11,2 @@ /// <reference types="google.maps" /> | ||
onZoomChanged: (event: MapCameraChangedEvent) => void; | ||
onProjectionChanged: (event: MapCameraChangedEvent) => void; | ||
onCameraChanged: (event: MapCameraChangedEvent) => void; | ||
@@ -25,2 +24,3 @@ onClick: (event: MapMouseEvent) => void; | ||
onIdle: (event: MapEvent) => void; | ||
onProjectionChanged: (event: MapEvent) => void; | ||
onIsFractionalZoomEnabledChanged: (event: MapEvent) => void; | ||
@@ -27,0 +27,0 @@ onMapCapabilitiesChanged: (event: MapEvent) => void; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="google.maps" /> | ||
/** | ||
@@ -6,2 +5,2 @@ * Internally used to bind events to google maps API objects. | ||
*/ | ||
export declare function useMapsEventListener(target?: google.maps.MVCObject | null, name?: string, callback?: ((arg?: unknown) => void) | null): void; | ||
export declare function useMapsEventListener<T extends (...args: any[]) => void>(target?: object | null, name?: string, callback?: T | null): void; |
{ | ||
"name": "@vis.gl/react-google-maps", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "React components and hooks for Google Maps.", | ||
@@ -5,0 +5,0 @@ "source": "src/index.ts", |
@@ -13,3 +13,2 @@ import {useEffect} from 'react'; | ||
onZoomChanged: (event: MapCameraChangedEvent) => void; | ||
onProjectionChanged: (event: MapCameraChangedEvent) => void; | ||
onCameraChanged: (event: MapCameraChangedEvent) => void; | ||
@@ -33,2 +32,3 @@ | ||
// configuration events | ||
onProjectionChanged: (event: MapEvent) => void; | ||
onIsFractionalZoomEnabledChanged: (event: MapEvent) => void; | ||
@@ -184,3 +184,2 @@ onMapCapabilitiesChanged: (event: MapEvent) => void; | ||
'heading_changed', | ||
'projection_changed', | ||
'tilt_changed', | ||
@@ -187,0 +186,0 @@ 'zoom_changed' |
@@ -15,2 +15,34 @@ import {Ref, useEffect, useRef, useState} from 'react'; | ||
/** | ||
* Stores a stack of map-instances for each mapId. Whenever an | ||
* instance is used, it is removed from the stack while in use, | ||
* and returned to the stack when the component unmounts. | ||
* This allows us to correctly implement caching for multiple | ||
* maps om the same page, while reusing as much as possible. | ||
* | ||
* FIXME: while it should in theory be possible to reuse maps solely | ||
* based on the mapId (as all other parameters can be changed at | ||
* runtime), we don't yet have good enough tracking of options to | ||
* reliably unset all the options that have been set. | ||
*/ | ||
class CachedMapStack { | ||
static entries: {[key: string]: google.maps.Map[]} = {}; | ||
static has(key: string) { | ||
return this.entries[key] && this.entries[key].length > 0; | ||
} | ||
static pop(key: string) { | ||
if (!this.entries[key]) return null; | ||
return this.entries[key].pop() || null; | ||
} | ||
static push(key: string, value: google.maps.Map) { | ||
if (!this.entries[key]) this.entries[key] = []; | ||
this.entries[key].push(value); | ||
} | ||
} | ||
/** | ||
* The main hook takes care of creating map-instances and registering them in | ||
@@ -43,2 +75,3 @@ * the api-provider context. | ||
defaultTilt, | ||
reuseMaps, | ||
@@ -85,10 +118,30 @@ ...mapOptions | ||
const {addMapInstance, removeMapInstance} = context; | ||
const mapId = props.mapId; | ||
const newMap = new google.maps.Map(container, mapOptions); | ||
const cacheKey = mapId || 'default'; | ||
let mapDiv: HTMLElement; | ||
let map: google.maps.Map; | ||
setMap(newMap); | ||
addMapInstance(newMap, id); | ||
if (reuseMaps && CachedMapStack.has(cacheKey)) { | ||
map = CachedMapStack.pop(cacheKey) as google.maps.Map; | ||
mapDiv = map.getDiv(); | ||
container.appendChild(mapDiv); | ||
map.setOptions(mapOptions); | ||
// detaching the element from the DOM lets the map fall back to its default | ||
// size, setting the center will trigger reloading the map. | ||
setTimeout(() => map.setCenter(map.getCenter()!), 0); | ||
} else { | ||
mapDiv = document.createElement('div'); | ||
mapDiv.style.height = '100%'; | ||
container.appendChild(mapDiv); | ||
map = new google.maps.Map(mapDiv, mapOptions); | ||
} | ||
setMap(map); | ||
addMapInstance(map, id); | ||
if (defaultBounds) { | ||
newMap.fitBounds(defaultBounds); | ||
map.fitBounds(defaultBounds); | ||
} | ||
@@ -98,3 +151,3 @@ | ||
else if (!hasZoom || !hasCenter) { | ||
newMap.fitBounds({east: 180, west: -180, south: -90, north: 90}); | ||
map.fitBounds({east: 180, west: -180, south: -90, north: 90}); | ||
} | ||
@@ -107,3 +160,3 @@ | ||
if (savedMapId !== mapId) { | ||
newMap.setOptions(savedCameraState); | ||
map.setOptions(savedCameraState); | ||
} | ||
@@ -119,5 +172,13 @@ } | ||
// remove all event-listeners to minimize memory-leaks | ||
google.maps.event.clearInstanceListeners(newMap); | ||
// detach the map-div from the dom | ||
mapDiv.remove(); | ||
if (reuseMaps) { | ||
// push back on the stack | ||
CachedMapStack.push(cacheKey, map); | ||
} else { | ||
// remove all event-listeners to minimize the possibility of memory-leaks | ||
google.maps.event.clearInstanceListeners(map); | ||
} | ||
setMap(null); | ||
@@ -124,0 +185,0 @@ removeMapInstance(id); |
@@ -0,1 +1,2 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import {useEffect} from 'react'; | ||
@@ -7,6 +8,6 @@ | ||
*/ | ||
export function useMapsEventListener( | ||
target?: google.maps.MVCObject | null, | ||
export function useMapsEventListener<T extends (...args: any[]) => void>( | ||
target?: object | null, | ||
name?: string, | ||
callback?: ((arg?: unknown) => void) | null | ||
callback?: T | null | ||
) { | ||
@@ -13,0 +14,0 @@ useEffect(() => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
535924
90
7189