Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 35 additions & 29 deletions components/src/maplibre/Geocoder/Geocoder.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script lang="ts">
import maplibre from 'maplibre-gl';
import MaplibreGeocoder, { type CarmenGeojsonFeature, type MaplibreGeocoderApi } from '@maplibre/maplibre-gl-geocoder';
import MaplibreGeocoder, {
type CarmenGeojsonFeature,
type MaplibreGeocoderApi
} from '@maplibre/maplibre-gl-geocoder';
import { MaptilerGeocoderAPI } from './GeocoderAPIs';

import type { Attachment } from 'svelte/attachments';
Expand All @@ -12,10 +15,11 @@
countries = 'de',
languages = 'en',
types = [],
bbox,
placeholder,
limit = 3,
size = "default",
map,
size = 'default',
map
}: GeocoderProps = $props();

const countriesArr = $derived(Array.isArray(countries) ? countries : [countries]);
Expand All @@ -25,37 +29,39 @@
// Future: initialise a different GeocoderAPI depending on "service"
let geocoderAPI: MaplibreGeocoderApi = $derived(new MaptilerGeocoderAPI(key));

const geocoder = new MaplibreGeocoder(geocoderAPI, {
maplibregl: maplibre,
language: languagesArr.join(','),
countries: countriesArr.join(','),
types: typesArr.join(','),
showResultsWhileTyping: true,
showResultMarkers: false,
debounceSearch: 25,
placeholder,
limit
});

const handleResult = (r: {result: CarmenGeojsonFeature}) => {
const res = r.result
if(res.bbox && map){
map.fitBounds([
[res.bbox[0], res.bbox[1]],
[res.bbox[2], res.bbox[3]],
])
}
const geocoder = $derived(
new MaplibreGeocoder(geocoderAPI, {
maplibregl: maplibre,
language: languagesArr.join(','),
countries: countriesArr.join(','),
types: typesArr.join(','),
bbox: bbox,
showResultsWhileTyping: true,
showResultMarkers: false,
debounceSearch: 25,
placeholder,
limit
})
);

}
const handleResult = (r: { result: CarmenGeojsonFeature }) => {
const res = r.result;
if (res.bbox && map) {
map.fitBounds([
[res.bbox[0], res.bbox[1]],
[res.bbox[2], res.bbox[3]]
]);
}
};

const attachGeocoder: Attachment = (el) => {
geocoder.addTo(el as HTMLElement);
geocoder.on("result", handleResult)
}
geocoder.addTo(el as HTMLElement);
geocoder.on('result', handleResult);
};
</script>

<div class={["container", size]} {@attach attachGeocoder}></div>
<div class={['container', size]} {@attach attachGeocoder}></div>

<style lang="scss">
@use "geocoder.scss"
@use 'geocoder.scss';
</style>
1 change: 1 addition & 0 deletions components/src/maplibre/Geocoder/GeocoderAPIs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class MaptilerGeocoderAPI implements MaplibreGeocoderApi {
country: config.countries || '',
language: config.language || '',
types: config.types || '',
bbox: config.bbox?.join(',') || '',
key: this.key || ''
}).filter(([_, value]) => {
return value !== '';
Expand Down
73 changes: 38 additions & 35 deletions components/src/maplibre/Geocoder/GeocoderProps.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
import { Map } from "maplibre-gl";
import { Map } from 'maplibre-gl';
import {
type GeocodingCountry,
type GeocodingLanguage,
type GeocodingPlaceType,
type GeocodingService
} from '../types';

type GeocodingCountry,
type GeocodingLanguage,
type GeocodingPlaceType,
type GeocodingService
} from '../types';

export default interface GeocoderProps {
map?: Map | null
service: GeocodingService;
/**
* API key for selected geocoding `service`
*/
key: string;
/**
* Limit the number of returned suggestions
*/
limit?: number;
/**
* Limit search to one or more countries
*/
countries?: GeocodingCountry | GeocodingCountry[];
/**
* Limit search to one or more result type.
*/
types?: GeocodingPlaceType | GeocodingPlaceType[];
/**
* Limit search to one or more languages. The UI is localised to the first language specified if [available](https://github.com/maplibre/maplibre-gl-geocoder/blob/main/lib/localization.ts).
*/
languages?: GeocodingLanguage | GeocodingLanguage[];
/**
* Overwrite the default input placeholder
*/
placeholder?: string;
size?: "small" | "default"
}
map?: Map | null;
service: GeocodingService;
/**
* API key for selected geocoding `service`
*/
key: string;
/**
* Limit the number of returned suggestions
*/
limit?: number;
/**
* Limit search to one or more countries
*/
countries?: GeocodingCountry | GeocodingCountry[];
/**
* Limit search to one or more result type
*/
types?: GeocodingPlaceType | GeocodingPlaceType[];
/**
* Limit search to a [w, s, e, n] bounding box
*/
bbox?: number[];
/**
* Limit search to one or more languages. The UI is localised to the first language specified if [available](https://github.com/maplibre/maplibre-gl-geocoder/blob/main/lib/localization.ts).
*/
languages?: GeocodingLanguage | GeocodingLanguage[];
/**
* Overwrite the default input placeholder
*/
placeholder?: string;
size?: 'small' | 'default';
}
1 change: 1 addition & 0 deletions components/src/maplibre/GeocoderControl/GeocoderAPIs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class MaptilerGeocoderAPI implements MaplibreGeocoderApi {
country: config.countries || '',
language: config.language || '',
types: config.types || '',
bbox: config.bbox?.join(',') || '',
key: this.key || ''
}).filter(([_, value]) => {
return value !== '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@
<DesignTokens theme="light">
<div class="container">
<Map style={SWRDataLabLight()} initialLocation={{ lat: 51, lng: 10, zoom: 20 }}>
<GeocoderControl
languages="de"
service="maptiler"
key="V32kPHZjMa0Mkn6YvSzA"
/>
<GeocoderControl languages="de" service="maptiler" key="V32kPHZjMa0Mkn6YvSzA" />
</Map>
</div>
</DesignTokens>
Expand Down Expand Up @@ -119,6 +115,22 @@
</div>
</DesignTokens>
</Story>
<Story asChild name="bbox">
<DesignTokens theme="light">
<div class="container">
<Map style={SWRDataLabLight()} initialLocation={{ lat: 51, lng: 10, zoom: 20 }}>
<GeocoderControl
position="top-right"
languages="de"
service="maptiler"
placeholder="Try 'Frankfurt'"
bbox={[13.579, 51.994, 15.531, 52.674]}
key="V32kPHZjMa0Mkn6YvSzA"
/>
</Map>
</div>
</DesignTokens>
</Story>

<style>
.container {
Expand Down
31 changes: 17 additions & 14 deletions components/src/maplibre/GeocoderControl/GeocoderControl.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import MapControl from '../MapControl/MapControl.svelte';
import type GeocoderProps from '../Geocoder/GeocoderProps';

interface GeocoderControlProps extends Omit<GeocoderProps, "map">{
interface GeocoderControlProps extends Omit<GeocoderProps, 'map'> {
position?: ControlPosition;
}

Expand All @@ -15,8 +15,8 @@
countries = 'de',
languages = 'en',
types = [],
size="default",
placeholder,
bbox,
position = 'top-left',
limit = 3
}: GeocoderControlProps = $props();
Expand All @@ -28,21 +28,24 @@
// Future: initialise a different GeocoderAPI depending on "service"
let geocoderAPI: MaplibreGeocoderApi = $derived(new MaptilerGeocoderAPI(key));

const geocoder = $derived(new MaplibreGeocoder(geocoderAPI, {
maplibregl: maplibre,
language: languagesArr.join(','),
countries: countriesArr.join(','),
types: typesArr.join(','),
showResultsWhileTyping: true,
showResultMarkers: false,
debounceSearch: 25,
placeholder,
limit
}));
const geocoder = $derived(
new MaplibreGeocoder(geocoderAPI, {
maplibregl: maplibre,
language: languagesArr.join(','),
countries: countriesArr.join(','),
types: typesArr.join(','),
bbox,
showResultsWhileTyping: true,
showResultMarkers: false,
debounceSearch: 25,
placeholder,
limit
})
);
</script>

<MapControl control={geocoder} {position} />

<style lang="scss">
@use "../Geocoder/geocoder.scss"
@use '../Geocoder/geocoder.scss';
</style>
Loading