@@ -12,6 +12,7 @@ import {
1212 Popup ,
1313 addProtocol ,
1414 getRTLTextPluginStatus ,
15+ default as maplibregl ,
1516 removeProtocol ,
1617 setRTLTextPlugin ,
1718} from "maplibre-gl" ;
@@ -22,6 +23,10 @@ import type {
2223 StyleSpecification ,
2324} from "maplibre-gl" ;
2425import "maplibre-gl/dist/maplibre-gl.css" ;
26+ import {
27+ default as MaplibreGeocoder ,
28+ type MaplibreGeocoderApiConfig ,
29+ } from "@maplibre/maplibre-gl-geocoder" ;
2530import type { LayerSpecification } from "@maplibre/maplibre-gl-style-spec" ;
2631import { FileSource , PMTiles , Protocol } from "pmtiles" ;
2732import {
@@ -43,6 +48,7 @@ import {
4348 layersForVersion ,
4449 parseHash ,
4550} from "./utils" ;
51+ import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css" ;
4652
4753const STYLE_MAJOR_VERSION = 5 ;
4854
@@ -51,6 +57,10 @@ const DEFAULT_TILES = "https://demo-bucket.protomaps.com/v4.pmtiles";
5157const ATTRIBUTION =
5258 '<a href="https://github.com/protomaps/basemaps">Protomaps</a> © <a href="https://openstreetmap.org">OpenStreetMap</a>' ;
5359
60+ const GEOCODER_NUM_RESULTS = 10 ;
61+ const GEOCODE_EARTH_API_KEY =
62+ import . meta. env . VITE_GEOCODE_EARTH_API_KEY || "ge-36393e37d3f44f4a" ;
63+
5464function getSourceLayer ( l : LayerSpecification ) : string {
5565 if ( "source-layer" in l && l [ "source-layer" ] ) {
5666 return l [ "source-layer" ] ;
@@ -297,6 +307,41 @@ function MapLibreView(props: {
297307 } ) ,
298308 ) ;
299309
310+ const geocodeEarthResults = async (
311+ config : MaplibreGeocoderApiConfig ,
312+ endpoint : string ,
313+ ) => {
314+ const { lat, lng } = map . getCenter ( ) ;
315+ const url = `https://api.geocode.earth/v1/${ endpoint } ?api_key=${ GEOCODE_EARTH_API_KEY } &text=${ encodeURIComponent ( `${ config . query } ` ) } &focus.point.lat=${ lat } &focus.point.lon=${ lng } &size=${ GEOCODER_NUM_RESULTS } ` ;
316+ const result = await fetch ( url ) ;
317+ const json = await result . json ( ) ;
318+ for ( const f of json . features ) {
319+ const props = f . properties ;
320+ f . place_name = props ?. label ;
321+ }
322+ return json ;
323+ } ;
324+
325+ map . addControl (
326+ new MaplibreGeocoder (
327+ {
328+ getSuggestions : ( config ) =>
329+ geocodeEarthResults ( config , "autocomplete" ) ,
330+ forwardGeocode : ( config ) => geocodeEarthResults ( config , "search" ) ,
331+ } ,
332+ {
333+ maplibregl,
334+ showResultsWhileTyping : true ,
335+ placeholder : "Search a city or address" ,
336+ limit : GEOCODER_NUM_RESULTS ,
337+ proximityMinZoom : 9 ,
338+ marker : false ,
339+ flyTo : { animate : false } ,
340+ } ,
341+ ) ,
342+ "top-left" ,
343+ ) ;
344+
300345 const popup = new Popup ( {
301346 closeButton : true ,
302347 closeOnClick : false ,
0 commit comments