@@ -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 > > ) {
@@ -162,6 +178,23 @@ class MapView<T> extends React.Component<
162178 return nearbyMarkers ;
163179 }
164180
181+ // Dismiss all other callouts except the one just pressed. Maintains that only one is opened at a time
182+ private onMarkerPress ( markerIdentifier : string ) {
183+ for ( const [ idenfitifer , markerRef ] of this . markerRefs ) {
184+ if ( idenfitifer !== markerIdentifier ) markerRef . current ?. hideCallout ( ) ;
185+ }
186+ }
187+
188+ private getMarkerRef ( markerIdentifier : string ) {
189+ if ( this . markerRefs . has ( markerIdentifier ) ) {
190+ return this . markerRefs . get ( markerIdentifier ) ;
191+ } else {
192+ const ref = React . createRef < MapMarkerRefType > ( ) ;
193+ this . markerRefs . set ( markerIdentifier , ref ) ;
194+ return ref ;
195+ }
196+ }
197+
165198 render ( ) {
166199 const {
167200 apiKey,
@@ -231,11 +264,31 @@ class MapView<T> extends React.Component<
231264 style = { [ styles . map , style ] }
232265 { ...rest }
233266 >
234- { markers . map ( ( marker , index ) => renderMarker ( marker . props , index ) ) }
267+ { markers . map ( ( marker , index ) =>
268+ renderMarker (
269+ marker . props ,
270+ index ,
271+ this . getMarkerRef ( getMarkerIdentifier ( marker . props ) ) ,
272+ ( ) => this . onMarkerPress ( getMarkerIdentifier ( marker . props ) )
273+ )
274+ ) }
235275
236- { clusters . map ( ( cluster , index ) => (
237- < React . Fragment key = { index } > { cluster } </ React . Fragment >
238- ) ) }
276+ { /*
277+ Markers within clusters also need to able to assign refs and propogate press.
278+ This is done through context to prevent exposing these internal config options as props of the cluster component
279+ */ }
280+ < MapMarkerContext . Provider
281+ value = { {
282+ getMarkerRef : ( marker ) =>
283+ this . getMarkerRef ( getMarkerIdentifier ( marker ) ) ,
284+ onMarkerPress : ( marker ) =>
285+ this . onMarkerPress ( getMarkerIdentifier ( marker ) ) ,
286+ } }
287+ >
288+ { clusters . map ( ( cluster , index ) => (
289+ < React . Fragment key = { index } > { cluster } </ React . Fragment >
290+ ) ) }
291+ </ MapMarkerContext . Provider >
239292 </ MapViewComponent >
240293 </ MapViewContext . Provider >
241294 ) ;
@@ -288,4 +341,8 @@ function degreeToRadian(deg: number) {
288341 return deg * ( Math . PI / 180 ) ;
289342}
290343
344+ function getMarkerIdentifier ( marker : MapMarkerProps ) {
345+ return `marker-${ marker . latitude } -${ marker . longitude } ` ;
346+ }
347+
291348export default MapView ;
0 commit comments