/**
 * This module allows sharing certain elements of the Map state across
 * multiple components (outside of react).
 */ import { Filter } from 'src/state' ; export interface ActiveMarkers { /** map from data driver id to marker */ markersData : Map < string , google . maps . Marker > ; } export interface MapInfo { map : google . maps . Map ; activeMarkers : ActiveMarkers ; markerClusterer : MarkerClusterer ; /**
     * The filter that is currently being used to display the markers on the map
     */ currentFilter : Filter ; clustering ? : { /** Map from original marker to position of cluster if in a cluster */ clusterMarkers : Map < google . maps . Marker , google . maps . LatLng > ; } ; } export type SearchBoxId = 'main' | 'add-information' ; interface SearchBox { searchInput : HTMLInputElement ; /**
     * This is only initialized once we have a map (we have have the search
     * components before the google maps scripts have loaded), allows for
     * delayed initializing of search boxes
     */ box ? : google . maps . places . SearchBox ; } let state = null ; class MapState { private _mapInfo : MapInfo | null = null ; private readonly searchBoxes = new Map < SearchBoxId , SearchBox > ( ) ; private _updateResultsOnNextClustering = false ; public set mapInfo ( map ) { this . _mapInfo = map ; if ( map ) { map . map . addListener ( 'bounds_changed' , ( ) => { const bounds = map . map . getBounds ( ) ; if ( bounds ) { for ( const box of this . searchBoxes . values ( ) ) { if ( box . box ) { box . box . setBounds ( bounds ) ; } } } } ) ; for ( const box of this . searchBoxes . values ( ) ) { if ( ! box . box ) { this . initializeSearchInput ( box ) ; } } } } public get mapInfo ( ) { return this . _mapInfo ; } public updateSearchInputRef = ( id , searchInput ) => { if ( searchInput ) { const searchBox = { searchInput } ; this . searchBoxes . set ( id , searchBox ) ; this . initializeSearchInput ( searchBox ) ; } else { this . searchBoxes . delete ( id ) ; } } ; private initializeSearchInput = ( search ) => { if ( ! this . mapInfo ) { return ; } if ( search . box ) { return ; } const box = new google . maps . places . SearchBox ( search . searchInput ) ; search . box = box ; box . addListener ( 'places_changed' , ( ) => { if ( ! this . mapInfo ) { return ; } const places = box . getPlaces ( ) ; const bounds = new window . google . maps . LatLngBounds ( ) ; if ( places . length === 0 ) { return ; } places . forEach ( place => { if ( ! place . geometry ) { return ; } if ( place . geometry . viewport ) { bounds . union ( place . geometry . viewport ) ; } else { bounds . extend ( place . geometry . location ) ; } } ) ; this . mapInfo . map . fitBounds ( bounds ) ; } ) ; const bounds = this . mapInfo . map . getBounds ( ) ; if ( bounds ) { box . setBounds ( bounds ) ; } } ; public set updateResultsOnNextBoundsChange ( update ) { this . _updateResultsOnNextClustering = update ; } public get updateResultsOnNextBoundsChange ( ) { return this . _updateResultsOnNextClustering ; } } export default ( ) => { if ( ! state ) { state = new MapState ( ) ; } return state ; } ;