UNPKG

leaflet-geosearch

Version:

Adds support for address lookup (a.k.a. geocoding / geosearching) to Leaflet.

93 lines (79 loc) 2.38 kB
import AbstractProvider, { EndpointArgument, ParseArgument, ProviderOptions, SearchArgument, SearchResult, } from './provider'; import { Loader, LoaderOptions } from '@googlemaps/js-api-loader'; export interface RequestResult { results: google.maps.GeocoderResult[]; status?: google.maps.GeocoderStatus; } export interface GeocodeError { code: Exclude<google.maps.GeocoderStatus, google.maps.GeocoderStatus.OK>; endpoint: 'GEOCODER_GEOCODE'; message: string; name: 'MapsRequestError'; stack: string; } export type GoogleProviderOptions = LoaderOptions & ProviderOptions; export default class GoogleProvider extends AbstractProvider< RequestResult, google.maps.GeocoderResult > { loader: Promise<google.maps.Geocoder> | null = null; geocoder: google.maps.Geocoder | null = null; constructor(options: GoogleProviderOptions) { super(options); if (typeof window !== 'undefined') { this.loader = new Loader(options).load().then((google) => { const geocoder = new google.maps.Geocoder(); this.geocoder = geocoder; return geocoder; }); } } endpoint({ query }: EndpointArgument): never { throw new Error('Method not implemented.'); } parse( response: ParseArgument<RequestResult>, ): SearchResult<google.maps.GeocoderResult>[] { return response.data.results.map((r) => { const { lat, lng } = r.geometry.location.toJSON(); const { east, north, south, west } = r.geometry.viewport.toJSON(); return { x: lng, y: lat, label: r.formatted_address, bounds: [ [south, west], [north, east], ], raw: r, }; }); } async search( options: SearchArgument, ): Promise<SearchResult<google.maps.GeocoderResult>[]> { const geocoder = this.geocoder || (await this.loader); if (!geocoder) { throw new Error( 'GoogleMaps GeoCoder is not loaded. Are you trying to run this server side?', ); } const response = await geocoder .geocode({ address: options.query }, (response) => ({ results: response, })) .catch((e: GeocodeError) => { if (e.code !== 'ZERO_RESULTS') { console.error(`${e.code}: ${e.message}`); } return { results: [] }; }); return this.parse({ data: response }); } }