@@ -11,6 +11,19 @@ import MapMarkerCluster from "./marker-cluster/MapMarkerCluster";
1111import { MapViewContext , ZoomLocation } from "./MapViewCommon" ;
1212import { MapMarkerClusterView } from "./marker-cluster" ;
1313import { flattenReactFragments } from "@draftbit/ui" ;
14+ import type { MapMarker as MapMarkerRefType } from "react-native-maps" ;
15+
16+ export interface MapMarkerContextType {
17+ onMarkerPress : ( marker : MapMarkerProps ) => void ;
18+ getMarkerRef : (
19+ marker : MapMarkerProps
20+ ) => React . Ref < MapMarkerRefType > | undefined ;
21+ }
22+
23+ export const MapMarkerContext = React . createContext < MapMarkerContextType > ( {
24+ onMarkerPress : ( ) => { } ,
25+ getMarkerRef : ( ) => undefined ,
26+ } ) ;
1427
1528export interface MapViewProps < T >
1629 extends Omit < MapViewComponentProps , "onRegionChangeComplete" > {
@@ -35,10 +48,13 @@ class MapView<T> extends React.Component<
3548 MapViewState
3649> {
3750 private mapRef : React . RefObject < any > ;
51+ private markerRefs : Map < string , React . RefObject < MapMarkerRefType > > ;
52+
3853 constructor ( props : React . PropsWithChildren < MapViewProps < T > > ) {
3954 super ( props ) ;
4055 this . state = { region : null } ;
4156 this . mapRef = React . createRef ( ) ;
57+ this . markerRefs = new Map ( ) ;
4258 }
4359
4460 componentDidUpdate ( prevProps : React . PropsWithChildren < MapViewProps < T > > ) {
@@ -163,6 +179,23 @@ class MapView<T> extends React.Component<
163179 return nearbyMarkers ;
164180 }
165181
182+ // Dismiss all other callouts except the one just pressed. Maintains that only one is opened at a time
183+ private onMarkerPress ( markerIdentifier : string ) {
184+ for ( const [ idenfitifer , markerRef ] of this . markerRefs ) {
185+ if ( idenfitifer !== markerIdentifier ) markerRef . current ?. hideCallout ( ) ;
186+ }
187+ }
188+
189+ private getMarkerRef ( markerIdentifier : string ) {
190+ if ( this . markerRefs . has ( markerIdentifier ) ) {
191+ return this . markerRefs . get ( markerIdentifier ) ;
192+ } else {
193+ const ref = React . createRef < MapMarkerRefType > ( ) ;
194+ this . markerRefs . set ( markerIdentifier , ref ) ;
195+ return ref ;
196+ }
197+ }
198+
166199 render ( ) {
167200 const {
168201 apiKey,
@@ -234,11 +267,31 @@ class MapView<T> extends React.Component<
234267 style = { [ styles . map , style ] }
235268 { ...rest }
236269 >
237- { markers . map ( ( marker , index ) => renderMarker ( marker . props , index ) ) }
238-
239- { clusters . map ( ( cluster , index ) => (
240- < React . Fragment key = { index } > { cluster } </ React . Fragment >
241- ) ) }
270+ { markers . map ( ( marker , index ) =>
271+ renderMarker (
272+ marker . props ,
273+ index ,
274+ this . getMarkerRef ( getMarkerIdentifier ( marker . props ) ) ,
275+ ( ) => this . onMarkerPress ( getMarkerIdentifier ( marker . props ) )
276+ )
277+ ) }
278+
279+ { /*
280+ Markers within clusters also need to able to assign refs and propogate press.
281+ This is done through context to prevent exposing these internal config options as props of the cluster component
282+ */ }
283+ < MapMarkerContext . Provider
284+ value = { {
285+ getMarkerRef : ( marker ) =>
286+ this . getMarkerRef ( getMarkerIdentifier ( marker ) ) ,
287+ onMarkerPress : ( marker ) =>
288+ this . onMarkerPress ( getMarkerIdentifier ( marker ) ) ,
289+ } }
290+ >
291+ { clusters . map ( ( cluster , index ) => (
292+ < React . Fragment key = { index } > { cluster } </ React . Fragment >
293+ ) ) }
294+ </ MapMarkerContext . Provider >
242295 </ MapViewComponent >
243296 </ MapViewContext . Provider >
244297 ) ;
@@ -291,4 +344,8 @@ function degreeToRadian(deg: number) {
291344 return deg * ( Math . PI / 180 ) ;
292345}
293346
347+ function getMarkerIdentifier ( marker : MapMarkerProps ) {
348+ return `marker-${ marker . latitude } -${ marker . longitude } ` ;
349+ }
350+
294351export default MapView ;
0 commit comments