import * as React from "react"; import { Image, ImageSourcePropType, View, StyleSheet, Text, Platform, } from "react-native"; import { Marker as MapMarkerComponent } from "./react-native-maps"; import type { MapMarkerProps as MapMarkerComponentProps, MapMarker as MapMarkerRefType, } from "react-native-maps"; import MapCallout, { renderCallout } from "./MapCallout"; import { flattenReactFragments } from "@draftbit/core"; export interface MapMarkerProps extends Omit { latitude: number; longitude: number; pinImage?: string | ImageSourcePropType; pinImageSize?: number; androidUseDefaultIconImplementation?: boolean; onPress?: (latitude: number, longitude: number) => void; } /** * Renders nothing, serves as placeholder for props * Rendering exposed as function to avoid having an intermediary component that changes the type * * This is done because the underlying package has logic dependant on the type of child * See: https://github.com/teovillanueva/react-native-web-maps/blob/5f3d0ec7c24f789c3df30c1d6d7223e638ff5868/packages/react-native-web-maps/src/components/marker-clusterer/marker-clusterer.tsx#L18 */ const MapMarker: React.FC> = () => { return null; }; export function renderMarker( { latitude, longitude, pinImage, pinImageSize = 50, androidUseDefaultIconImplementation = false, onPress, children, title, description, ...rest }: MapMarkerProps, key?: React.Key, ref?: React.Ref, onMarkerPress?: () => void ) { const childrenArray = flattenReactFragments( React.Children.toArray(children) as React.ReactElement[] ); const calloutChildren = childrenArray.filter( (child) => child.type === MapCallout ); const nonCalloutChildren = childrenArray.filter( (child) => child.type !== MapCallout ); // Add default callout for title/description if (calloutChildren.length === 0 && (title || description)) { calloutChildren.push( {title && {title}} {description && ( {description} )} ); } const shouldUseDefaultIconImplementation = Platform.OS === "android" && androidUseDefaultIconImplementation; return ( { onMarkerPress?.(); const coordinate = event.nativeEvent.coordinate; if (coordinate) { onPress?.(coordinate.latitude, coordinate.longitude); } }} icon={ shouldUseDefaultIconImplementation ? typeof pinImage === "string" ? { uri: pinImage } : (pinImage as any) : undefined } {...rest} > {nonCalloutChildren} {pinImage && !shouldUseDefaultIconImplementation && ( )} {calloutChildren.map((callout, index) => renderCallout((callout as any).props, index) )} ); } const styles = StyleSheet.create({ defaultCalloutContainer: { flex: 1, }, defaultCalloutTitle: { fontWeight: "600", textAlign: "center", maxWidth: 250, }, defaultCalloutDescription: { maxWidth: 250, }, }); export default MapMarker;