@maptiler/geocoding-control 0.0.32 → 0.0.36
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/README.md +4 -4
- package/dist/leaflet.js +315 -312
- package/dist/leaflet.umd.cjs +1 -1
- package/dist/lib/LeafletGeocodingControl.d.ts +1 -1
- package/dist/lib/MaplibreglGeocodingControl.d.ts +1 -1
- package/dist/lib/maplibreglMapController.d.ts +4 -0
- package/dist/lib/types.d.ts +3 -1
- package/dist/main.d.ts +1 -1
- package/dist/maplibregl.js +2046 -652
- package/dist/maplibregl.umd.cjs +22 -1
- package/dist/style.css +1 -1
- package/package.json +7 -4
- package/src/lib/GeocodingControl.svelte +44 -8
- package/src/lib/LeafletGeocodingControl.ts +1 -0
- package/src/lib/MaplibreglGeocodingControl.ts +3 -2
- package/src/lib/maplibreglMapController.ts +282 -0
- package/src/lib/types.ts +3 -1
- package/src/lib/maplibreMapController.ts +0 -149
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import type MapLibreGL from "maplibre-gl";
|
|
2
|
+
import type {
|
|
3
|
+
FitBoundsOptions,
|
|
4
|
+
MapMouseEvent,
|
|
5
|
+
LngLat,
|
|
6
|
+
Map,
|
|
7
|
+
Marker,
|
|
8
|
+
FlyToOptions,
|
|
9
|
+
GeoJSONSource,
|
|
10
|
+
} from "maplibre-gl";
|
|
11
|
+
import MarkerIcon from "./MarkerIcon.svelte";
|
|
12
|
+
import type { Feature, MapController, Proximity } from "./types";
|
|
13
|
+
import mask from "@turf/mask";
|
|
14
|
+
import union from "@turf/union";
|
|
15
|
+
import type {
|
|
16
|
+
Polygon,
|
|
17
|
+
MultiPolygon,
|
|
18
|
+
LineString,
|
|
19
|
+
MultiLineString,
|
|
20
|
+
} from "@turf/helpers";
|
|
21
|
+
|
|
22
|
+
let emptyGeojson: GeoJSON.FeatureCollection = {
|
|
23
|
+
type: "FeatureCollection",
|
|
24
|
+
features: [],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function createMaplibreglMapController(
|
|
28
|
+
map: Map,
|
|
29
|
+
maplibregl?: typeof MapLibreGL | undefined,
|
|
30
|
+
marker: boolean | maplibregl.MarkerOptions = true,
|
|
31
|
+
showResultMarkers: boolean | maplibregl.MarkerOptions = true,
|
|
32
|
+
flyToOptions: FlyToOptions = {},
|
|
33
|
+
fitBoundsOptions: FitBoundsOptions = {}
|
|
34
|
+
) {
|
|
35
|
+
let proximityChangeHandler: ((proximity: Proximity) => void) | undefined;
|
|
36
|
+
|
|
37
|
+
let mapClickHandler: ((coordinates: [number, number]) => void) | undefined;
|
|
38
|
+
|
|
39
|
+
let prevProximity: Proximity = undefined;
|
|
40
|
+
|
|
41
|
+
let markers: Marker[] = [];
|
|
42
|
+
|
|
43
|
+
let selectedMarker: maplibregl.Marker | undefined;
|
|
44
|
+
|
|
45
|
+
function addPreviewLayer() {
|
|
46
|
+
map.addSource("preview", {
|
|
47
|
+
type: "geojson",
|
|
48
|
+
data: emptyGeojson,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
map.addLayer({
|
|
52
|
+
id: "preview-fill",
|
|
53
|
+
type: "fill",
|
|
54
|
+
source: "preview",
|
|
55
|
+
layout: {},
|
|
56
|
+
paint: {
|
|
57
|
+
"fill-color": "#000",
|
|
58
|
+
"fill-opacity": 0.1,
|
|
59
|
+
},
|
|
60
|
+
filter: ["==", ["geometry-type"], "Polygon"],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
map.addLayer({
|
|
64
|
+
id: "preview-line",
|
|
65
|
+
type: "line",
|
|
66
|
+
source: "preview",
|
|
67
|
+
layout: {
|
|
68
|
+
"line-cap": "square",
|
|
69
|
+
},
|
|
70
|
+
paint: {
|
|
71
|
+
"line-width": ["case", ["==", ["geometry-type"], "Polygon"], 2, 3],
|
|
72
|
+
"line-dasharray": [1, 1],
|
|
73
|
+
"line-color": "#3170fe",
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (map.loaded()) {
|
|
79
|
+
addPreviewLayer();
|
|
80
|
+
} else {
|
|
81
|
+
map.once("load", () => {
|
|
82
|
+
addPreviewLayer();
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const handleMapClick = (e: MapMouseEvent) => {
|
|
87
|
+
mapClickHandler?.([e.lngLat.lng, e.lngLat.lat]);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleMoveEnd = () => {
|
|
91
|
+
let c: LngLat;
|
|
92
|
+
|
|
93
|
+
const proximity =
|
|
94
|
+
map.getZoom() > 9
|
|
95
|
+
? ([(c = map.getCenter().wrap()).lng, c.lat] as [number, number])
|
|
96
|
+
: undefined;
|
|
97
|
+
|
|
98
|
+
if (prevProximity !== proximity) {
|
|
99
|
+
prevProximity = proximity;
|
|
100
|
+
|
|
101
|
+
proximityChangeHandler?.(proximity);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const ctrl: MapController = {
|
|
106
|
+
setProximityChangeHandler(
|
|
107
|
+
_proximityChangeHandler: ((proximity: Proximity) => void) | undefined
|
|
108
|
+
): void {
|
|
109
|
+
if (_proximityChangeHandler) {
|
|
110
|
+
proximityChangeHandler = _proximityChangeHandler;
|
|
111
|
+
|
|
112
|
+
map.on("moveend", handleMoveEnd);
|
|
113
|
+
|
|
114
|
+
handleMoveEnd();
|
|
115
|
+
} else {
|
|
116
|
+
map.off("moveend", handleMoveEnd);
|
|
117
|
+
|
|
118
|
+
proximityChangeHandler?.(undefined);
|
|
119
|
+
|
|
120
|
+
proximityChangeHandler = undefined;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
setMapClickHandler(
|
|
125
|
+
_mapClickHandler: ((coordinates: [number, number]) => void) | undefined
|
|
126
|
+
): void {
|
|
127
|
+
mapClickHandler = _mapClickHandler;
|
|
128
|
+
|
|
129
|
+
if (mapClickHandler) {
|
|
130
|
+
map.on("click", handleMapClick);
|
|
131
|
+
} else {
|
|
132
|
+
map.off("click", handleMapClick);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
flyTo(center: [number, number], zoom: number): void {
|
|
137
|
+
map.flyTo({ center, zoom, ...flyToOptions });
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
fitBounds(bbox: [number, number, number, number], padding: number): void {
|
|
141
|
+
map.fitBounds(
|
|
142
|
+
[
|
|
143
|
+
[bbox[0], bbox[1]],
|
|
144
|
+
[bbox[2], bbox[3]],
|
|
145
|
+
],
|
|
146
|
+
{ padding, ...fitBoundsOptions }
|
|
147
|
+
);
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
indicateReverse(reverse: boolean): void {
|
|
151
|
+
map.getCanvas().style.cursor = reverse ? "crosshair" : "";
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
setMarkers(
|
|
155
|
+
markedFeatures: Feature[] | undefined,
|
|
156
|
+
picked: Feature | undefined
|
|
157
|
+
): void {
|
|
158
|
+
function setData(data: GeoJSON.GeoJSON) {
|
|
159
|
+
(map.getSource("preview") as GeoJSONSource)?.setData(data);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const marker of markers) {
|
|
163
|
+
marker.remove();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
setData(emptyGeojson);
|
|
167
|
+
|
|
168
|
+
markers.length = 0;
|
|
169
|
+
|
|
170
|
+
if (!maplibregl) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (picked) {
|
|
175
|
+
let handled = false;
|
|
176
|
+
|
|
177
|
+
if (picked.geometry.type === "GeometryCollection") {
|
|
178
|
+
const geoms = picked.geometry.geometries.filter(
|
|
179
|
+
(geometry) =>
|
|
180
|
+
geometry.type === "Polygon" || geometry.type === "MultiPolygon"
|
|
181
|
+
) as (Polygon | MultiPolygon)[];
|
|
182
|
+
|
|
183
|
+
if (geoms.length > 0) {
|
|
184
|
+
let geometry = geoms.pop()!;
|
|
185
|
+
|
|
186
|
+
for (const geom of geoms) {
|
|
187
|
+
geometry = union(geometry, geom) as unknown as
|
|
188
|
+
| Polygon
|
|
189
|
+
| MultiPolygon; // union actually returns geometry
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
setData(mask({ ...picked, geometry }));
|
|
193
|
+
|
|
194
|
+
handled = true;
|
|
195
|
+
} else {
|
|
196
|
+
const geometries = picked.geometry.geometries.filter(
|
|
197
|
+
(geometry) =>
|
|
198
|
+
geometry.type === "LineString" ||
|
|
199
|
+
geometry.type === "MultiLineString"
|
|
200
|
+
) as (LineString | MultiLineString)[];
|
|
201
|
+
|
|
202
|
+
if (geometries.length > 0) {
|
|
203
|
+
setData({
|
|
204
|
+
...picked,
|
|
205
|
+
geometry: { type: "GeometryCollection", geometries },
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
handled = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let m: Marker | undefined = undefined;
|
|
214
|
+
|
|
215
|
+
if (handled) {
|
|
216
|
+
// nothing
|
|
217
|
+
} else if (
|
|
218
|
+
picked.geometry.type === "Polygon" ||
|
|
219
|
+
picked.geometry.type === "MultiPolygon"
|
|
220
|
+
) {
|
|
221
|
+
setData(mask(picked as any));
|
|
222
|
+
} else if (
|
|
223
|
+
picked.geometry.type === "LineString" ||
|
|
224
|
+
picked.geometry.type === "MultiLineString"
|
|
225
|
+
) {
|
|
226
|
+
setData(picked as any);
|
|
227
|
+
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (typeof marker === "object") {
|
|
232
|
+
m = new maplibregl.Marker(marker);
|
|
233
|
+
} else {
|
|
234
|
+
const element = document.createElement("div");
|
|
235
|
+
|
|
236
|
+
new MarkerIcon({
|
|
237
|
+
props: { displayIn: "maplibre" },
|
|
238
|
+
target: element,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
m = new maplibregl.Marker({ element });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (m) {
|
|
245
|
+
markers.push(m.setLngLat(picked.center).addTo(map));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
for (const feature of markedFeatures ?? []) {
|
|
250
|
+
if (feature === picked) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let m: Marker;
|
|
255
|
+
|
|
256
|
+
if (typeof showResultMarkers === "object") {
|
|
257
|
+
m = new maplibregl.Marker(showResultMarkers);
|
|
258
|
+
} else {
|
|
259
|
+
const element = document.createElement("div");
|
|
260
|
+
|
|
261
|
+
new MarkerIcon({ props: { displayIn: "maplibre" }, target: element });
|
|
262
|
+
|
|
263
|
+
m = new maplibregl.Marker({ element });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
markers.push(m.setLngLat(feature.center).addTo(map));
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
setSelectedMarker(index: number): void {
|
|
271
|
+
if (selectedMarker) {
|
|
272
|
+
selectedMarker.getElement().classList.toggle("marker-selected", false);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
selectedMarker = index > -1 ? markers[index] : undefined;
|
|
276
|
+
|
|
277
|
+
selectedMarker?.getElement().classList.toggle("marker-selected", true);
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
return ctrl;
|
|
282
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
export type Feature = {
|
|
1
|
+
export type Feature = GeoJSON.Feature & {
|
|
2
2
|
id: string;
|
|
3
3
|
text: string;
|
|
4
4
|
place_name: string;
|
|
5
5
|
place_type: string;
|
|
6
6
|
center: [number, number];
|
|
7
7
|
bbox: [number, number, number, number];
|
|
8
|
+
address?: string;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export type FeatureCollection = {
|
|
12
|
+
type: "FeatureCollection";
|
|
11
13
|
features: Feature[];
|
|
12
14
|
};
|
|
13
15
|
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import type MapLibreGL from "maplibre-gl";
|
|
2
|
-
import type {
|
|
3
|
-
FitBoundsOptions,
|
|
4
|
-
MapMouseEvent,
|
|
5
|
-
LngLat,
|
|
6
|
-
Map,
|
|
7
|
-
Marker,
|
|
8
|
-
FlyToOptions,
|
|
9
|
-
} from "maplibre-gl";
|
|
10
|
-
import MarkerIcon from "./MarkerIcon.svelte";
|
|
11
|
-
import type { Feature, MapController, Proximity } from "./types";
|
|
12
|
-
|
|
13
|
-
export function createMaplibreMapController(
|
|
14
|
-
map: Map,
|
|
15
|
-
maplibregl?: typeof MapLibreGL | undefined,
|
|
16
|
-
marker: boolean | maplibregl.MarkerOptions = true,
|
|
17
|
-
showResultMarkers: boolean | maplibregl.MarkerOptions = true,
|
|
18
|
-
flyToOptions: FlyToOptions = {},
|
|
19
|
-
fitBoundsOptions: FitBoundsOptions = {}
|
|
20
|
-
) {
|
|
21
|
-
let proximityChangeHandler: ((proximity: Proximity) => void) | undefined;
|
|
22
|
-
|
|
23
|
-
let mapClickHandler: ((coordinates: [number, number]) => void) | undefined;
|
|
24
|
-
|
|
25
|
-
let prevProximity: Proximity = undefined;
|
|
26
|
-
|
|
27
|
-
let markers: Marker[] = [];
|
|
28
|
-
|
|
29
|
-
let selectedMarker: maplibregl.Marker | undefined;
|
|
30
|
-
|
|
31
|
-
const handleMapClick = (e: MapMouseEvent) => {
|
|
32
|
-
mapClickHandler?.([e.lngLat.lng, e.lngLat.lat]);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const handleMoveEnd = () => {
|
|
36
|
-
let c: LngLat;
|
|
37
|
-
|
|
38
|
-
const proximity =
|
|
39
|
-
map.getZoom() > 9
|
|
40
|
-
? ([(c = map.getCenter().wrap()).lng, c.lat] as [number, number])
|
|
41
|
-
: undefined;
|
|
42
|
-
|
|
43
|
-
if (prevProximity !== proximity) {
|
|
44
|
-
prevProximity = proximity;
|
|
45
|
-
|
|
46
|
-
proximityChangeHandler?.(proximity);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const ctrl: MapController = {
|
|
51
|
-
setProximityChangeHandler(
|
|
52
|
-
_proximityChangeHandler: ((proximity: Proximity) => void) | undefined
|
|
53
|
-
): void {
|
|
54
|
-
if (_proximityChangeHandler) {
|
|
55
|
-
proximityChangeHandler = _proximityChangeHandler;
|
|
56
|
-
|
|
57
|
-
map.on("moveend", handleMoveEnd);
|
|
58
|
-
|
|
59
|
-
handleMoveEnd();
|
|
60
|
-
} else {
|
|
61
|
-
map.off("moveend", handleMoveEnd);
|
|
62
|
-
|
|
63
|
-
proximityChangeHandler?.(undefined);
|
|
64
|
-
|
|
65
|
-
proximityChangeHandler = undefined;
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
setMapClickHandler(
|
|
70
|
-
_mapClickHandler: ((coordinates: [number, number]) => void) | undefined
|
|
71
|
-
): void {
|
|
72
|
-
mapClickHandler = _mapClickHandler;
|
|
73
|
-
|
|
74
|
-
if (mapClickHandler) {
|
|
75
|
-
map.on("click", handleMapClick);
|
|
76
|
-
} else {
|
|
77
|
-
map.off("click", handleMapClick);
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
flyTo(center: [number, number], zoom: number): void {
|
|
82
|
-
map.flyTo({ center, zoom, ...flyToOptions });
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
fitBounds(bbox: [number, number, number, number], padding: number): void {
|
|
86
|
-
map.fitBounds(
|
|
87
|
-
[
|
|
88
|
-
[bbox[0], bbox[1]],
|
|
89
|
-
[bbox[2], bbox[3]],
|
|
90
|
-
],
|
|
91
|
-
{ ...fitBoundsOptions, padding }
|
|
92
|
-
);
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
indicateReverse(reverse: boolean): void {
|
|
96
|
-
map.getCanvas().style.cursor = reverse ? "crosshair" : "";
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
setMarkers(
|
|
100
|
-
markedFeatures: Feature[] | undefined,
|
|
101
|
-
picked: Feature | undefined
|
|
102
|
-
): void {
|
|
103
|
-
for (const marker of markers) {
|
|
104
|
-
marker.remove();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
markers.length = 0;
|
|
108
|
-
|
|
109
|
-
if (!maplibregl) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
for (const feature of picked
|
|
114
|
-
? [...(markedFeatures ?? []), picked]
|
|
115
|
-
: markedFeatures ?? []) {
|
|
116
|
-
let m: Marker;
|
|
117
|
-
|
|
118
|
-
if (feature === picked && typeof marker === "object") {
|
|
119
|
-
m = new maplibregl.Marker(marker);
|
|
120
|
-
} else if (
|
|
121
|
-
feature !== picked &&
|
|
122
|
-
typeof showResultMarkers === "object"
|
|
123
|
-
) {
|
|
124
|
-
m = new maplibregl.Marker(showResultMarkers);
|
|
125
|
-
} else {
|
|
126
|
-
const element = document.createElement("div");
|
|
127
|
-
|
|
128
|
-
new MarkerIcon({ props: { displayIn: "maplibre" }, target: element });
|
|
129
|
-
|
|
130
|
-
m = new maplibregl.Marker({ element });
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
markers.push(m.setLngLat(feature.center).addTo(map));
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
setSelectedMarker(index: number): void {
|
|
138
|
-
if (selectedMarker) {
|
|
139
|
-
selectedMarker.getElement().classList.toggle("marker-selected", false);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
selectedMarker = index > -1 ? markers[index] : undefined;
|
|
143
|
-
|
|
144
|
-
selectedMarker?.getElement().classList.toggle("marker-selected", true);
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
return ctrl;
|
|
149
|
-
}
|