import React, { useEffect, useRef } from 'react'; import maplibregl from 'maplibre-gl'; import { createAmplifyGeocoder } from 'maplibre-gl-js-amplify'; import { useControl, useMap } from 'react-map-gl'; import type { IControl } from 'react-map-gl'; import { LocationSearchProps } from '../types/maplibre-gl-geocoder'; const LOCATION_SEARCH_OPTIONS = { maplibregl, marker: { color: '#3FB1CE' }, popup: true, showResultMarkers: { color: '#3FB1CE' }, showResultsWhileTyping: true, }; const LOCATION_SEARCH_CONTAINER = 'geocoder-container'; type AmplifyLocationSearch = IControl & { addTo: (container: string) => void; }; const LocationSearchControl = ({ position = 'top-right', ...props }: LocationSearchProps) => { useControl( () => createAmplifyGeocoder(props) as unknown as AmplifyLocationSearch, { position, } ); return null; }; const LocationSearchStandalone = (props: LocationSearchProps) => { const hasMounted = useRef(false); useEffect(() => { if (!hasMounted.current) { (createAmplifyGeocoder(props) as unknown as AmplifyLocationSearch).addTo( `#${LOCATION_SEARCH_CONTAINER}` ); hasMounted.current = true; } }, [props]); return
; }; /** * The `` component provides location search. * * [📖 Docs](https://ui.docs.amplify.aws/react/connected-components/geo#location-search) * * @example * // Used as a map control: * function App() { * return ( * * * * ); * } * * @example * // Used as a standalone component: * function App() { * return ; * } */ export const LocationSearch = (props: LocationSearchProps): JSX.Element => { const { current: map } = useMap(); /** * This logic determines whether the LocationSearch exists as part of a Map component or if it is a standalone component. * The `useControl` hook inside `LocationSearchControl` from `react-map-gl` makes it easy to add a control to a map, * but throws an error if that map doesn't exist. If the map doesn't exist, the LocationSearch is mounted to a container * upon rendering inside the `LocationSearchStandalone`. */ if (map) { return ; } return ; };