@maptiler/geocoding-control 0.0.78 → 0.0.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ClearIcon.svelte.d.ts +23 -0
- package/GeocodingControl.svelte +685 -0
- package/GeocodingControl.svelte.d.ts +66 -0
- package/LoadingIcon.svelte.d.ts +23 -0
- package/{src/lib/MarkerIcon.svelte → MarkerIcon.svelte} +1 -2
- package/MarkerIcon.svelte.d.ts +16 -0
- package/ReverseGeocodingIcon.svelte.d.ts +23 -0
- package/SearchIcon.svelte.d.ts +23 -0
- package/leaflet-controller.js +1 -0
- package/leaflet-controller.js.map +1 -0
- package/leaflet-controller.umd.js +1 -0
- package/leaflet-controller.umd.js.map +1 -0
- package/leaflet.js +3998 -4021
- package/leaflet.js.map +1 -0
- package/leaflet.umd.js +6 -5
- package/leaflet.umd.js.map +1 -0
- package/maplibregl-controller.js +1 -0
- package/maplibregl-controller.js.map +1 -0
- package/maplibregl-controller.umd.js +1 -0
- package/maplibregl-controller.umd.js.map +1 -0
- package/maplibregl.js +4089 -4112
- package/maplibregl.js.map +1 -0
- package/maplibregl.umd.js +6 -5
- package/maplibregl.umd.js.map +1 -0
- package/package.json +23 -23
- package/react.js +571 -649
- package/react.js.map +1 -0
- package/react.umd.js +2 -1
- package/react.umd.js.map +1 -0
- package/style.css +1 -1
- package/src/AppLeaflet.svelte +0 -55
- package/src/AppMaplibregl.svelte +0 -45
- package/src/lib/GeocodingControl.svelte +0 -839
- package/src/lib/LeafletGeocodingControl.ts +0 -154
- package/src/lib/MaplibreglGeocodingControl.ts +0 -160
- package/src/lib/ReactGeocodingControl.ts +0 -158
- package/src/lib/leafletMapController.ts +0 -305
- package/src/lib/maplibreglMapController.ts +0 -366
- package/src/lib/mask.ts +0 -70
- package/src/lib/types.ts +0 -235
- package/src/main-copy.ts +0 -59
- package/src/main.ts +0 -65
- package/src/vite-env.d.ts +0 -2
- /package/{src/lib/ClearIcon.svelte → ClearIcon.svelte} +0 -0
- /package/{src/lib/LoadingIcon.svelte → LoadingIcon.svelte} +0 -0
- /package/{src/lib/ReverseGeocodingIcon.svelte → ReverseGeocodingIcon.svelte} +0 -0
- /package/{src/lib/SearchIcon.svelte → SearchIcon.svelte} +0 -0
- /package/{maplibre.d.ts → maplibregl.d.ts} +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} ClearIconProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} ClearIconEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} ClearIconSlots */
|
|
4
|
+
export default class ClearIcon extends SvelteComponentTyped<{
|
|
5
|
+
[x: string]: never;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {}> {
|
|
9
|
+
}
|
|
10
|
+
export type ClearIconProps = typeof __propDef.props;
|
|
11
|
+
export type ClearIconEvents = typeof __propDef.events;
|
|
12
|
+
export type ClearIconSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponentTyped } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
[x: string]: never;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
<script>import { createEventDispatcher } from "svelte";
|
|
2
|
+
import { onDestroy } from "svelte/internal";
|
|
3
|
+
import ReverseGeocodingIcon from "./ReverseGeocodingIcon.svelte";
|
|
4
|
+
import ClearIcon from "./ClearIcon.svelte";
|
|
5
|
+
import LoadingIcon from "./LoadingIcon.svelte";
|
|
6
|
+
import MarkerIcon from "./MarkerIcon.svelte";
|
|
7
|
+
import SearchIcon from "./SearchIcon.svelte";
|
|
8
|
+
let className = undefined;
|
|
9
|
+
export { className as class };
|
|
10
|
+
export let apiKey;
|
|
11
|
+
export let bbox = undefined;
|
|
12
|
+
export let clearButtonTitle = "clear";
|
|
13
|
+
export let clearOnBlur = false;
|
|
14
|
+
export let collapsed = false;
|
|
15
|
+
export let country = undefined;
|
|
16
|
+
export let debounceSearch = 200;
|
|
17
|
+
export let enableReverse = false;
|
|
18
|
+
export let errorMessage = "Searching failed";
|
|
19
|
+
export let filter = () => true;
|
|
20
|
+
export let flyTo = true;
|
|
21
|
+
export let fuzzyMatch = true;
|
|
22
|
+
export let language = undefined;
|
|
23
|
+
export let limit = undefined;
|
|
24
|
+
export let mapController = undefined;
|
|
25
|
+
export let minLength = 2;
|
|
26
|
+
export let noResultsMessage = "No results found";
|
|
27
|
+
export let placeholder = "Search";
|
|
28
|
+
export let proximity = undefined;
|
|
29
|
+
export let reverseActive = enableReverse === "always";
|
|
30
|
+
export let reverseButtonTitle = "toggle reverse geocoding";
|
|
31
|
+
export let searchValue = "";
|
|
32
|
+
export let showFullGeometry = true;
|
|
33
|
+
export let showPlaceType = false;
|
|
34
|
+
export let showResultsWhileTyping = true;
|
|
35
|
+
export let trackProximity = true;
|
|
36
|
+
export let types = undefined;
|
|
37
|
+
export let zoom = 16;
|
|
38
|
+
export let fetchParameters = {};
|
|
39
|
+
export function focus() {
|
|
40
|
+
input.focus();
|
|
41
|
+
}
|
|
42
|
+
export function blur() {
|
|
43
|
+
input.blur();
|
|
44
|
+
}
|
|
45
|
+
export function setQuery(value, submit = true) {
|
|
46
|
+
searchValue = value;
|
|
47
|
+
if (submit) {
|
|
48
|
+
selectedItemIndex = -1;
|
|
49
|
+
handleOnSubmit();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
handleInput();
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
input.focus();
|
|
55
|
+
input.select();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let focused = false;
|
|
60
|
+
let listFeatures;
|
|
61
|
+
let markedFeatures;
|
|
62
|
+
let picked;
|
|
63
|
+
let lastSearchUrl = "";
|
|
64
|
+
let input;
|
|
65
|
+
let selectedItemIndex = -1;
|
|
66
|
+
let error;
|
|
67
|
+
let cachedFeatures = [];
|
|
68
|
+
let abortController;
|
|
69
|
+
let searchTimeoutRef;
|
|
70
|
+
let focusedDelayed;
|
|
71
|
+
const dispatch = createEventDispatcher();
|
|
72
|
+
$: if (!trackProximity) {
|
|
73
|
+
proximity = undefined;
|
|
74
|
+
}
|
|
75
|
+
$: if (showFullGeometry &&
|
|
76
|
+
picked &&
|
|
77
|
+
!picked.address &&
|
|
78
|
+
picked.geometry.type === "Point") {
|
|
79
|
+
search(picked.id, { byId: true }).catch((err) => (error = err));
|
|
80
|
+
}
|
|
81
|
+
$: if (mapController && picked && flyTo) {
|
|
82
|
+
if (!picked.bbox ||
|
|
83
|
+
(picked.bbox[0] === picked.bbox[2] && picked.bbox[1] === picked.bbox[3])) {
|
|
84
|
+
mapController.flyTo(picked.center, zoom);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
mapController.fitBounds(unwrapBbox(picked.bbox), 50);
|
|
88
|
+
}
|
|
89
|
+
listFeatures = undefined;
|
|
90
|
+
markedFeatures = undefined;
|
|
91
|
+
selectedItemIndex = -1;
|
|
92
|
+
}
|
|
93
|
+
$: if (markedFeatures !== listFeatures) {
|
|
94
|
+
markedFeatures = undefined;
|
|
95
|
+
}
|
|
96
|
+
$: if (mapController) {
|
|
97
|
+
mapController.setMarkers(markedFeatures, picked);
|
|
98
|
+
}
|
|
99
|
+
$: if (!searchValue) {
|
|
100
|
+
picked = undefined;
|
|
101
|
+
listFeatures = undefined;
|
|
102
|
+
error = undefined;
|
|
103
|
+
markedFeatures = listFeatures;
|
|
104
|
+
}
|
|
105
|
+
// highlight selected marker
|
|
106
|
+
$: mapController?.setSelectedMarker(selectedItemIndex);
|
|
107
|
+
// close dropdown in the next cycle so that the selected item event has the chance to fire
|
|
108
|
+
$: setTimeout(() => {
|
|
109
|
+
focusedDelayed = focused;
|
|
110
|
+
if (clearOnBlur && !focused) {
|
|
111
|
+
searchValue = "";
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// clear selection on edit
|
|
115
|
+
$: {
|
|
116
|
+
searchValue;
|
|
117
|
+
selectedItemIndex = -1;
|
|
118
|
+
}
|
|
119
|
+
$: selected = listFeatures?.[selectedItemIndex];
|
|
120
|
+
$: {
|
|
121
|
+
const m = /^(-?\d+(?:\.\d*)?),(-?\d+(?:\.\d*)?)$/.exec(searchValue);
|
|
122
|
+
mapController?.setReverseMarker(m ? [Number(m[1]), Number(m[2])] : undefined);
|
|
123
|
+
}
|
|
124
|
+
$: dispatch("select", selected);
|
|
125
|
+
$: dispatch("pick", picked);
|
|
126
|
+
$: dispatch("optionsVisibilityChange", focusedDelayed && !!listFeatures);
|
|
127
|
+
$: dispatch("featuresListed", listFeatures);
|
|
128
|
+
$: dispatch("featuresMarked", markedFeatures);
|
|
129
|
+
$: dispatch("reverseToggle", reverseActive);
|
|
130
|
+
$: dispatch("queryChange", searchValue);
|
|
131
|
+
$: if (mapController) {
|
|
132
|
+
mapController.indicateReverse(reverseActive);
|
|
133
|
+
}
|
|
134
|
+
$: if (mapController) {
|
|
135
|
+
mapController.setEventHandler((e) => {
|
|
136
|
+
switch (e.type) {
|
|
137
|
+
case "mapClick":
|
|
138
|
+
if (reverseActive) {
|
|
139
|
+
handleReverse(e.coordinates);
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
case "proximityChange":
|
|
143
|
+
proximity = trackProximity ? e.proximity : undefined;
|
|
144
|
+
break;
|
|
145
|
+
case "markerClick":
|
|
146
|
+
{
|
|
147
|
+
const feature = listFeatures?.find((feature) => feature.id === e.id);
|
|
148
|
+
if (feature) {
|
|
149
|
+
pick(feature);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
case "markerMouseEnter":
|
|
154
|
+
selectedItemIndex = !focusedDelayed
|
|
155
|
+
? -1
|
|
156
|
+
: listFeatures?.findIndex((feature) => feature.id === e.id) ?? -1;
|
|
157
|
+
break;
|
|
158
|
+
case "markerMouseLeave":
|
|
159
|
+
selectedItemIndex = -1;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
onDestroy(() => {
|
|
165
|
+
if (mapController) {
|
|
166
|
+
mapController.setEventHandler(undefined);
|
|
167
|
+
mapController.indicateReverse(false);
|
|
168
|
+
mapController.setSelectedMarker(-1);
|
|
169
|
+
mapController.setMarkers(undefined, undefined);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
function handleOnSubmit(event) {
|
|
173
|
+
if (searchTimeoutRef) {
|
|
174
|
+
clearTimeout(searchTimeoutRef);
|
|
175
|
+
searchTimeoutRef = undefined;
|
|
176
|
+
}
|
|
177
|
+
if (selectedItemIndex > -1 && listFeatures) {
|
|
178
|
+
picked = listFeatures[selectedItemIndex];
|
|
179
|
+
searchValue = picked.place_name.replace(/,.*/, "");
|
|
180
|
+
error = undefined;
|
|
181
|
+
markedFeatures = undefined;
|
|
182
|
+
selectedItemIndex = -1;
|
|
183
|
+
}
|
|
184
|
+
else if (searchValue) {
|
|
185
|
+
const zoomTo = event || !isQuerReverse();
|
|
186
|
+
search(searchValue, { exact: true })
|
|
187
|
+
.then(() => {
|
|
188
|
+
markedFeatures = listFeatures;
|
|
189
|
+
picked = undefined;
|
|
190
|
+
if (zoomTo) {
|
|
191
|
+
zoomToResults();
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
.catch((err) => (error = err));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function isQuerReverse() {
|
|
198
|
+
return /^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(searchValue);
|
|
199
|
+
}
|
|
200
|
+
async function search(searchValue, { byId = false, exact = false, } = {}) {
|
|
201
|
+
error = undefined;
|
|
202
|
+
const isReverse = isQuerReverse();
|
|
203
|
+
const sp = new URLSearchParams();
|
|
204
|
+
if (language != undefined) {
|
|
205
|
+
sp.set("language", Array.isArray(language) ? language.join(",") : language);
|
|
206
|
+
}
|
|
207
|
+
if (types) {
|
|
208
|
+
sp.set("types", types.join(","));
|
|
209
|
+
}
|
|
210
|
+
if (!isReverse) {
|
|
211
|
+
if (bbox) {
|
|
212
|
+
sp.set("bbox", bbox.map((c) => c.toFixed(6)).join(","));
|
|
213
|
+
}
|
|
214
|
+
if (country) {
|
|
215
|
+
sp.set("country", Array.isArray(country) ? country.join(",") : country);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!byId) {
|
|
219
|
+
if (proximity) {
|
|
220
|
+
sp.set("proximity", proximity.map((c) => c.toFixed(6)).join(","));
|
|
221
|
+
}
|
|
222
|
+
if (exact || !showResultsWhileTyping) {
|
|
223
|
+
sp.set("autocomplete", "false");
|
|
224
|
+
}
|
|
225
|
+
sp.set("fuzzyMatch", String(fuzzyMatch));
|
|
226
|
+
}
|
|
227
|
+
if (limit !== undefined) {
|
|
228
|
+
sp.set("limit", String(limit));
|
|
229
|
+
}
|
|
230
|
+
sp.set("key", apiKey);
|
|
231
|
+
const url = import.meta.env.VITE_API_URL +
|
|
232
|
+
"/" +
|
|
233
|
+
encodeURIComponent(searchValue) +
|
|
234
|
+
".json?" +
|
|
235
|
+
sp.toString();
|
|
236
|
+
if (url === lastSearchUrl) {
|
|
237
|
+
if (byId) {
|
|
238
|
+
listFeatures = undefined;
|
|
239
|
+
picked = cachedFeatures[0];
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
listFeatures = cachedFeatures;
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
lastSearchUrl = url;
|
|
247
|
+
abortController?.abort();
|
|
248
|
+
const ac = new AbortController();
|
|
249
|
+
abortController = ac;
|
|
250
|
+
let res;
|
|
251
|
+
try {
|
|
252
|
+
res = await fetch(url, {
|
|
253
|
+
signal: ac.signal,
|
|
254
|
+
...fetchParameters,
|
|
255
|
+
}).finally(() => {
|
|
256
|
+
if (ac === abortController) {
|
|
257
|
+
abortController = undefined;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
if (e && typeof e === "object" && e.name === "AbortError") {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
throw new Error();
|
|
266
|
+
}
|
|
267
|
+
if (!res.ok) {
|
|
268
|
+
throw new Error();
|
|
269
|
+
}
|
|
270
|
+
const featureCollection = await res.json();
|
|
271
|
+
dispatch("response", { url, featureCollection });
|
|
272
|
+
if (byId) {
|
|
273
|
+
listFeatures = undefined;
|
|
274
|
+
picked = featureCollection.features[0];
|
|
275
|
+
cachedFeatures = [picked];
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
listFeatures = featureCollection.features.filter(filter);
|
|
279
|
+
cachedFeatures = listFeatures;
|
|
280
|
+
if (isReverse) {
|
|
281
|
+
input.focus();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function zoomToResults() {
|
|
286
|
+
if (!markedFeatures?.length || !flyTo) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const bbox = [180, 90, -180, -90];
|
|
290
|
+
const fuzzyOnly = !markedFeatures.some((feature) => !feature.matching_text);
|
|
291
|
+
for (const feature of markedFeatures) {
|
|
292
|
+
if (fuzzyOnly || !feature.matching_text) {
|
|
293
|
+
bbox[0] = Math.min(bbox[0], feature.bbox?.[0] ?? feature.center[0]);
|
|
294
|
+
bbox[1] = Math.min(bbox[1], feature.bbox?.[1] ?? feature.center[1]);
|
|
295
|
+
bbox[2] = Math.max(bbox[2], feature.bbox?.[2] ?? feature.center[0]);
|
|
296
|
+
bbox[3] = Math.max(bbox[3], feature.bbox?.[3] ?? feature.center[1]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (mapController && markedFeatures.length > 0) {
|
|
300
|
+
if (picked && bbox[0] === bbox[2] && bbox[1] === bbox[3]) {
|
|
301
|
+
mapController.flyTo(picked.center, zoom);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
mapController.fitBounds(unwrapBbox(bbox), 50);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// taken from Leaflet
|
|
309
|
+
function wrapNum(x, range, includeMax) {
|
|
310
|
+
const max = range[1], min = range[0], d = max - min;
|
|
311
|
+
return x === max && includeMax ? x : ((((x - min) % d) + d) % d) + min;
|
|
312
|
+
}
|
|
313
|
+
function handleReverse(coordinates) {
|
|
314
|
+
reverseActive = enableReverse === "always";
|
|
315
|
+
setQuery(wrapNum(coordinates[0], [-180, 180], true).toFixed(6) +
|
|
316
|
+
"," +
|
|
317
|
+
coordinates[1].toFixed(6));
|
|
318
|
+
}
|
|
319
|
+
function handleKeyDown(e) {
|
|
320
|
+
if (!listFeatures) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
let dir = e.key === "ArrowDown" ? 1 : e.key === "ArrowUp" ? -1 : 0;
|
|
324
|
+
if (dir) {
|
|
325
|
+
if (selectedItemIndex === -1 && dir === -1) {
|
|
326
|
+
selectedItemIndex = listFeatures.length;
|
|
327
|
+
}
|
|
328
|
+
selectedItemIndex += dir;
|
|
329
|
+
if (selectedItemIndex >= listFeatures.length) {
|
|
330
|
+
selectedItemIndex = -1;
|
|
331
|
+
}
|
|
332
|
+
e.preventDefault();
|
|
333
|
+
}
|
|
334
|
+
else if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(e.key)) {
|
|
335
|
+
selectedItemIndex = -1;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function handleInput(debounce = true) {
|
|
339
|
+
if (showResultsWhileTyping && searchValue.length > minLength) {
|
|
340
|
+
if (searchTimeoutRef) {
|
|
341
|
+
clearTimeout(searchTimeoutRef);
|
|
342
|
+
}
|
|
343
|
+
const sv = searchValue;
|
|
344
|
+
searchTimeoutRef = window.setTimeout(() => {
|
|
345
|
+
search(sv).catch((err) => (error = err));
|
|
346
|
+
}, debounce ? debounceSearch : 0);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
listFeatures = undefined;
|
|
350
|
+
error = undefined;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function pick(feature) {
|
|
354
|
+
picked = feature;
|
|
355
|
+
searchValue = feature.place_name;
|
|
356
|
+
selectedItemIndex = -1;
|
|
357
|
+
}
|
|
358
|
+
function unwrapBbox(bbox0) {
|
|
359
|
+
let bbox = [...bbox0];
|
|
360
|
+
if (bbox[2] < bbox[0]) {
|
|
361
|
+
bbox[2] += 360;
|
|
362
|
+
}
|
|
363
|
+
return bbox;
|
|
364
|
+
}
|
|
365
|
+
</script>
|
|
366
|
+
|
|
367
|
+
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
368
|
+
<form
|
|
369
|
+
tabindex="0"
|
|
370
|
+
on:submit|preventDefault={handleOnSubmit}
|
|
371
|
+
class:can-collapse={collapsed && searchValue === ""}
|
|
372
|
+
class={className}
|
|
373
|
+
>
|
|
374
|
+
<div class="input-group">
|
|
375
|
+
<button type="button" on:click={() => input.focus()}>
|
|
376
|
+
<SearchIcon />
|
|
377
|
+
</button>
|
|
378
|
+
|
|
379
|
+
<input
|
|
380
|
+
bind:this={input}
|
|
381
|
+
bind:value={searchValue}
|
|
382
|
+
on:focus={() => (focused = true)}
|
|
383
|
+
on:blur={() => (focused = false)}
|
|
384
|
+
on:keydown={handleKeyDown}
|
|
385
|
+
on:input={() => handleInput()}
|
|
386
|
+
{placeholder}
|
|
387
|
+
aria-label={placeholder}
|
|
388
|
+
/>
|
|
389
|
+
|
|
390
|
+
<div class="clear-button-container">
|
|
391
|
+
<button
|
|
392
|
+
type="button"
|
|
393
|
+
on:click={() => {
|
|
394
|
+
searchValue = "";
|
|
395
|
+
input.focus();
|
|
396
|
+
}}
|
|
397
|
+
class:displayable={searchValue !== ""}
|
|
398
|
+
title={clearButtonTitle}
|
|
399
|
+
>
|
|
400
|
+
<ClearIcon />
|
|
401
|
+
</button>
|
|
402
|
+
|
|
403
|
+
{#if abortController}
|
|
404
|
+
<LoadingIcon />
|
|
405
|
+
{/if}
|
|
406
|
+
</div>
|
|
407
|
+
|
|
408
|
+
{#if enableReverse === true}
|
|
409
|
+
<button
|
|
410
|
+
type="button"
|
|
411
|
+
class:active={reverseActive}
|
|
412
|
+
title={reverseButtonTitle}
|
|
413
|
+
on:click={() => (reverseActive = !reverseActive)}
|
|
414
|
+
>
|
|
415
|
+
<ReverseGeocodingIcon />
|
|
416
|
+
</button>
|
|
417
|
+
{/if}
|
|
418
|
+
|
|
419
|
+
<slot />
|
|
420
|
+
</div>
|
|
421
|
+
|
|
422
|
+
{#if error}
|
|
423
|
+
<div class="error">{errorMessage}</div>
|
|
424
|
+
{:else if !focusedDelayed}
|
|
425
|
+
{""}
|
|
426
|
+
{:else if listFeatures?.length === 0}
|
|
427
|
+
<div class="no-results">{noResultsMessage}</div>
|
|
428
|
+
{:else if focusedDelayed && listFeatures?.length}
|
|
429
|
+
<ul
|
|
430
|
+
on:mouseleave={() => (selectedItemIndex = -1)}
|
|
431
|
+
on:blur={() => undefined}
|
|
432
|
+
>
|
|
433
|
+
{#each listFeatures as feature, i}
|
|
434
|
+
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
435
|
+
<li
|
|
436
|
+
tabindex="0"
|
|
437
|
+
data-selected={selectedItemIndex === i}
|
|
438
|
+
class:selected={selectedItemIndex === i}
|
|
439
|
+
on:mouseenter={() => (selectedItemIndex = i)}
|
|
440
|
+
on:focus={() => pick(feature)}
|
|
441
|
+
>
|
|
442
|
+
<!-- <MarkerIcon displayIn="list" /> -->
|
|
443
|
+
<span class="texts">
|
|
444
|
+
<span class="line1">
|
|
445
|
+
<span class="primary">
|
|
446
|
+
{feature.place_name.replace(/,.*/, "")}
|
|
447
|
+
</span>
|
|
448
|
+
<span class="secondary">
|
|
449
|
+
{feature.place_name.replace(/[^,]*,?\s*/, "")}
|
|
450
|
+
</span>
|
|
451
|
+
</span>
|
|
452
|
+
{#if showPlaceType}
|
|
453
|
+
<span class="line2">
|
|
454
|
+
{feature.properties?.place_type_name?.[0] ??
|
|
455
|
+
feature.place_type[0]}
|
|
456
|
+
</span>
|
|
457
|
+
{/if}
|
|
458
|
+
</span>
|
|
459
|
+
</li>
|
|
460
|
+
{/each}
|
|
461
|
+
</ul>
|
|
462
|
+
{/if}
|
|
463
|
+
</form>
|
|
464
|
+
|
|
465
|
+
<style>
|
|
466
|
+
form,
|
|
467
|
+
form *,
|
|
468
|
+
form *:after,
|
|
469
|
+
form *:before {
|
|
470
|
+
box-sizing: border-box;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
form {
|
|
474
|
+
font-family: "Open Sans", "Ubuntu", "Helvetica Neue", Arial, Helvetica,
|
|
475
|
+
sans-serif;
|
|
476
|
+
position: relative;
|
|
477
|
+
background-color: #fff;
|
|
478
|
+
width: 100%;
|
|
479
|
+
z-index: 10;
|
|
480
|
+
border-radius: 4px;
|
|
481
|
+
transition: max-width 0.25s;
|
|
482
|
+
box-shadow: 0px 5px 10px rgba(51, 51, 89, 0.15);
|
|
483
|
+
--color-text: #444952;
|
|
484
|
+
--color-icon-button: #444952;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
form.can-collapse {
|
|
488
|
+
max-width: 35px;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
form,
|
|
492
|
+
form:focus-within,
|
|
493
|
+
form:hover {
|
|
494
|
+
max-width: 240px;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
input {
|
|
498
|
+
font: inherit;
|
|
499
|
+
font-size: 14px;
|
|
500
|
+
width: 100%;
|
|
501
|
+
border: 0;
|
|
502
|
+
background-color: transparent;
|
|
503
|
+
margin: 0;
|
|
504
|
+
height: 36px;
|
|
505
|
+
color: #444952;
|
|
506
|
+
white-space: nowrap;
|
|
507
|
+
overflow: hidden;
|
|
508
|
+
padding: 0;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
input:focus {
|
|
512
|
+
color: #444952;
|
|
513
|
+
outline: 0;
|
|
514
|
+
outline: none;
|
|
515
|
+
box-shadow: none;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
ul,
|
|
519
|
+
div.error,
|
|
520
|
+
div.no-results {
|
|
521
|
+
background-color: #fff;
|
|
522
|
+
border-radius: 4px;
|
|
523
|
+
left: 0;
|
|
524
|
+
list-style: none;
|
|
525
|
+
margin: 0;
|
|
526
|
+
padding: 0;
|
|
527
|
+
position: absolute;
|
|
528
|
+
width: 100%;
|
|
529
|
+
top: calc(100% + 6px);
|
|
530
|
+
font-size: 14px;
|
|
531
|
+
box-shadow: 0px 2px 8px rgba(51, 51, 89, 0.15);
|
|
532
|
+
line-height: 16px;
|
|
533
|
+
overflow: hidden;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
:global(.maplibregl-ctrl-bottom-left) ul,
|
|
537
|
+
:global(.maplibregl-ctrl-bottom-right) ul {
|
|
538
|
+
top: auto;
|
|
539
|
+
bottom: 100%;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
li {
|
|
543
|
+
text-align: left;
|
|
544
|
+
cursor: default;
|
|
545
|
+
display: grid;
|
|
546
|
+
grid-template-columns: 1fr;
|
|
547
|
+
color: var(--color-text);
|
|
548
|
+
padding: 8px 0px;
|
|
549
|
+
font-size: 14px;
|
|
550
|
+
line-height: 18px;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
li:first-child {
|
|
554
|
+
padding-top: 10px;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
li:last-child {
|
|
558
|
+
padding-bottom: 10px;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.texts {
|
|
562
|
+
padding: 0 17px;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.texts > * {
|
|
566
|
+
white-space: nowrap;
|
|
567
|
+
display: block;
|
|
568
|
+
min-width: fit-content;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
li.selected .texts > * {
|
|
572
|
+
animation: backAndForth 5s linear infinite;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.primary {
|
|
576
|
+
font-weight: 600;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
li.selected .primary {
|
|
580
|
+
color: #2b8bfb;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.secondary {
|
|
584
|
+
color: #aeb6c7;
|
|
585
|
+
padding-left: 4px;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.line2 {
|
|
589
|
+
color: #aeb6c7;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
li.selected {
|
|
593
|
+
background-color: #f3f6ff;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
button:hover {
|
|
597
|
+
background-color: transparent;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
button:hover :global(svg),
|
|
601
|
+
button.active :global(svg) {
|
|
602
|
+
fill: #6b7c92;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
button {
|
|
606
|
+
padding: 0;
|
|
607
|
+
margin: 0;
|
|
608
|
+
border: 0;
|
|
609
|
+
background-color: transparent;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.input-group {
|
|
613
|
+
display: flex;
|
|
614
|
+
align-items: stretch;
|
|
615
|
+
gap: 7px;
|
|
616
|
+
padding-inline: 8px;
|
|
617
|
+
outline: #c1cfe4 solid 1.5px;
|
|
618
|
+
border-radius: 4px;
|
|
619
|
+
overflow: hidden;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.input-group:hover .displayable {
|
|
623
|
+
visibility: visible;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
.input-group:focus-within {
|
|
627
|
+
outline: #2b8bfb solid 1.5px;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
div.error,
|
|
631
|
+
div.no-results {
|
|
632
|
+
font: inherit;
|
|
633
|
+
font-size: 14px;
|
|
634
|
+
padding: 6px 10px;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
div.error {
|
|
638
|
+
color: #e25041;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
div.no-results {
|
|
642
|
+
color: var(--color-text);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
.clear-button-container {
|
|
646
|
+
position: relative;
|
|
647
|
+
display: flex;
|
|
648
|
+
align-items: stretch;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
.clear-button-container button {
|
|
652
|
+
visibility: hidden;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
@keyframes backAndForth {
|
|
656
|
+
0% {
|
|
657
|
+
transform: translateX(0);
|
|
658
|
+
}
|
|
659
|
+
10% {
|
|
660
|
+
transform: translateX(0);
|
|
661
|
+
}
|
|
662
|
+
45% {
|
|
663
|
+
transform: translateX(calc(-100% + 206px));
|
|
664
|
+
}
|
|
665
|
+
55% {
|
|
666
|
+
transform: translateX(calc(-100% + 206px));
|
|
667
|
+
}
|
|
668
|
+
90% {
|
|
669
|
+
transform: translateX(0);
|
|
670
|
+
}
|
|
671
|
+
100% {
|
|
672
|
+
transform: translateX(0);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
form.can-collapse button:not(:nth-of-type(1)) {
|
|
677
|
+
opacity: 0;
|
|
678
|
+
transition: opacity 0.25s;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
form.can-collapse:focus-within :not(:nth-of-type(1)),
|
|
682
|
+
form.can-collapse:hover :not(:nth-of-type(1)) {
|
|
683
|
+
opacity: 1;
|
|
684
|
+
}
|
|
685
|
+
</style>
|