@maptiler/geocoding-control 0.0.44 → 0.0.52

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.
@@ -11,7 +11,7 @@ import type {
11
11
  LineLayerSpecification,
12
12
  } from "maplibre-gl";
13
13
  import MarkerIcon from "./MarkerIcon.svelte";
14
- import type { Feature, MapController, Proximity } from "./types";
14
+ import type { Feature, MapController, MapEvent, Proximity } from "./types";
15
15
  import union from "@turf/union";
16
16
  import type {
17
17
  Polygon,
@@ -59,9 +59,7 @@ export function createMaplibreglMapController(
59
59
  },
60
60
  }
61
61
  ) {
62
- let proximityChangeHandler: ((proximity: Proximity) => void) | undefined;
63
-
64
- let mapClickHandler: ((coordinates: [number, number]) => void) | undefined;
62
+ let eventHandler: ((e: MapEvent) => void) | undefined;
65
63
 
66
64
  let prevProximity: Proximity = undefined;
67
65
 
@@ -69,6 +67,8 @@ export function createMaplibreglMapController(
69
67
 
70
68
  let selectedMarker: maplibregl.Marker | undefined;
71
69
 
70
+ let reverseMarker: maplibregl.Marker | undefined;
71
+
72
72
  function addFullGeometryLayer() {
73
73
  if (fullGeometryStyle?.fill || fullGeometryStyle?.line) {
74
74
  map.addSource("full-geom", {
@@ -105,7 +105,10 @@ export function createMaplibreglMapController(
105
105
  }
106
106
 
107
107
  const handleMapClick = (e: MapMouseEvent) => {
108
- mapClickHandler?.([e.lngLat.lng, e.lngLat.lat]);
108
+ eventHandler?.({
109
+ type: "mapClick",
110
+ coordinates: [e.lngLat.lng, e.lngLat.lat],
111
+ });
109
112
  };
110
113
 
111
114
  const handleMoveEnd = () => {
@@ -119,37 +122,46 @@ export function createMaplibreglMapController(
119
122
  if (prevProximity !== proximity) {
120
123
  prevProximity = proximity;
121
124
 
122
- proximityChangeHandler?.(proximity);
125
+ eventHandler?.({ type: "proximityChange", proximity });
123
126
  }
124
127
  };
125
128
 
129
+ function createMarker(interactive = false) {
130
+ if (!maplibregl) {
131
+ throw new Error();
132
+ }
133
+
134
+ const element = document.createElement("div");
135
+
136
+ if (interactive) {
137
+ element.classList.add("marker-interactive");
138
+ }
139
+
140
+ new MarkerIcon({
141
+ props: { displayIn: "maplibre" },
142
+ target: element,
143
+ });
144
+
145
+ return new maplibregl.Marker({ element, offset: [1, -13] });
146
+ }
147
+
126
148
  const ctrl: MapController = {
127
- setProximityChangeHandler(
128
- _proximityChangeHandler: ((proximity: Proximity) => void) | undefined
129
- ): void {
130
- if (_proximityChangeHandler) {
131
- proximityChangeHandler = _proximityChangeHandler;
149
+ setEventHandler(handler: undefined | ((e: MapEvent) => void)): void {
150
+ if (handler) {
151
+ eventHandler = handler;
132
152
 
133
153
  map.on("moveend", handleMoveEnd);
134
154
 
135
155
  handleMoveEnd();
156
+
157
+ map.on("click", handleMapClick);
136
158
  } else {
137
159
  map.off("moveend", handleMoveEnd);
138
160
 
139
- proximityChangeHandler?.(undefined);
140
-
141
- proximityChangeHandler = undefined;
142
- }
143
- },
161
+ eventHandler?.({ type: "proximityChange", proximity: undefined });
144
162
 
145
- setMapClickHandler(
146
- _mapClickHandler: ((coordinates: [number, number]) => void) | undefined
147
- ): void {
148
- mapClickHandler = _mapClickHandler;
163
+ eventHandler = undefined;
149
164
 
150
- if (mapClickHandler) {
151
- map.on("click", handleMapClick);
152
- } else {
153
165
  map.off("click", handleMapClick);
154
166
  }
155
167
  },
@@ -169,13 +181,43 @@ export function createMaplibreglMapController(
169
181
  },
170
182
 
171
183
  indicateReverse(reverse: boolean): void {
172
- map.getCanvas().style.cursor = reverse ? "crosshair" : "";
184
+ map.getCanvasContainer().style.cursor = reverse ? "crosshair" : "";
185
+ },
186
+
187
+ setReverseMarker(coordinates: [number, number]) {
188
+ if (!maplibregl || !marker) {
189
+ return;
190
+ }
191
+
192
+ if (reverseMarker) {
193
+ if (!coordinates) {
194
+ reverseMarker.remove();
195
+
196
+ reverseMarker = undefined;
197
+ } else {
198
+ reverseMarker.setLngLat(coordinates);
199
+ }
200
+ } else if (coordinates) {
201
+ reverseMarker = (
202
+ typeof marker === "object"
203
+ ? new maplibregl.Marker(marker)
204
+ : createMarker()
205
+ )
206
+ .setLngLat(coordinates)
207
+ .addTo(map);
208
+
209
+ reverseMarker.getElement().classList.add("marker-reverse");
210
+ }
173
211
  },
174
212
 
175
213
  setMarkers(
176
214
  markedFeatures: Feature[] | undefined,
177
215
  picked: Feature | undefined
178
216
  ): void {
217
+ if (!marker) {
218
+ return;
219
+ }
220
+
179
221
  function setData(data: GeoJSON.GeoJSON) {
180
222
  (map.getSource("full-geom") as GeoJSONSource)?.setData(data);
181
223
  }
@@ -192,17 +234,6 @@ export function createMaplibreglMapController(
192
234
  return;
193
235
  }
194
236
 
195
- const createMarker = () => {
196
- const element = document.createElement("div");
197
-
198
- new MarkerIcon({
199
- props: { displayIn: "maplibre" },
200
- target: element,
201
- });
202
-
203
- return new maplibregl.Marker({ element });
204
- };
205
-
206
237
  if (picked) {
207
238
  let handled = false;
208
239
 
@@ -258,7 +289,7 @@ export function createMaplibreglMapController(
258
289
  return; // no pin for (multi)linestrings
259
290
  }
260
291
 
261
- if (showResultMarkers) {
292
+ if (marker) {
262
293
  markers.push(
263
294
  (typeof marker === "object"
264
295
  ? new maplibregl.Marker(marker)
@@ -276,14 +307,45 @@ export function createMaplibreglMapController(
276
307
  continue;
277
308
  }
278
309
 
279
- markers.push(
280
- (typeof showResultMarkers === "object"
310
+ const marker = (
311
+ typeof showResultMarkers === "object"
281
312
  ? new maplibregl.Marker(showResultMarkers)
282
- : createMarker()
313
+ : createMarker(true)
314
+ )
315
+ .setLngLat(feature.center)
316
+ .setPopup(
317
+ new maplibregl.Popup({
318
+ offset: [1, -27],
319
+ closeButton: false,
320
+ closeOnMove: true,
321
+ className: "maptiler-gc-popup",
322
+ }).setText(feature.place_name.replace(/,.*/, ""))
283
323
  )
284
- .setLngLat(feature.center)
285
- .addTo(map)
286
- );
324
+ .addTo(map);
325
+
326
+ const element = marker.getElement();
327
+
328
+ element.addEventListener("click", (e) => {
329
+ e.stopPropagation();
330
+
331
+ eventHandler?.({ type: "markerClick", id: feature.id });
332
+ });
333
+
334
+ element.addEventListener("mouseenter", () => {
335
+ eventHandler?.({ type: "markerMouseEnter", id: feature.id });
336
+
337
+ marker.togglePopup();
338
+ });
339
+
340
+ element.addEventListener("mouseleave", () => {
341
+ eventHandler?.({ type: "markerMouseLeave", id: feature.id });
342
+
343
+ marker.togglePopup();
344
+ });
345
+
346
+ element.classList.toggle("marker-fuzzy", !!feature.matching_text);
347
+
348
+ markers.push(marker);
287
349
  }
288
350
  }
289
351
  },
package/src/lib/types.ts CHANGED
@@ -6,6 +6,7 @@ export type Feature = GeoJSON.Feature & {
6
6
  center: [number, number];
7
7
  bbox: [number, number, number, number];
8
8
  address?: string;
9
+ matching_text?: string;
9
10
  };
10
11
 
11
12
  export type FeatureCollection = {
@@ -13,16 +14,18 @@ export type FeatureCollection = {
13
14
  features: Feature[];
14
15
  };
15
16
 
16
- export type MapController = {
17
- setProximityChangeHandler(
18
- proximityChangeHandler:
19
- | undefined
20
- | ((proximity: [number, number] | undefined) => void)
21
- ): void;
17
+ export type MapEvent =
18
+ | {
19
+ type: "proximityChange";
20
+ proximity: [number, number] | undefined;
21
+ }
22
+ | { type: "mapClick"; coordinates: [number, number] }
23
+ | { type: "markerClick"; id: string }
24
+ | { type: "markerMouseEnter"; id: string }
25
+ | { type: "markerMouseLeave"; id: string };
22
26
 
23
- setMapClickHandler(
24
- mapClickHandler: undefined | ((coordinates: [number, number]) => void)
25
- ): void;
27
+ export type MapController = {
28
+ setEventHandler(handler: undefined | ((e: MapEvent) => void)): void;
26
29
 
27
30
  flyTo(center: [number, number], zoom: number): void;
28
31
 
@@ -35,6 +38,8 @@ export type MapController = {
35
38
  picked: Feature | undefined
36
39
  ): void;
37
40
 
41
+ setReverseMarker(coordinates?: [number, number]): void;
42
+
38
43
  setSelectedMarker(index: number): void;
39
44
  };
40
45
 
@@ -101,12 +106,12 @@ export type ControlOptions = {
101
106
  */
102
107
  bbox?: [number, number, number, number];
103
108
 
104
- // /**
105
- // * Maximum number of results to show.
106
- // *
107
- // * @default 5
108
- // */
109
- // limit?: number;
109
+ /**
110
+ * Maximum number of results to show.
111
+ *
112
+ * @default 5
113
+ */
114
+ limit?: number;
110
115
 
111
116
  /**
112
117
  * Specify the language to use for response text and query result weighting.
@@ -114,7 +119,7 @@ export type ControlOptions = {
114
119
  * More than one value can also be specified, separated by commas.
115
120
  * Defaults to the browser's language settings.
116
121
  */
117
- language?: string;
122
+ language?: string | string[];
118
123
 
119
124
  /**
120
125
  * If `false`, indicates that search will only occur on enter key press.
@@ -124,19 +129,12 @@ export type ControlOptions = {
124
129
  */
125
130
  showResultsWhileTyping?: boolean;
126
131
 
127
- // /**
128
- // * Set to `false` to disable autocomplete.
129
- // *
130
- // * @default true
131
- // */
132
- // autocomplete?: boolean;
133
-
134
- // /**
135
- // * Set to `false` to disable fuzzy search.
136
- // *
137
- // * @default true
138
- // */
139
- // fuzzy?: boolean;
132
+ /**
133
+ * Set to `false` to disable fuzzy search.
134
+ *
135
+ * @default true
136
+ */
137
+ fuzzyMatch?: boolean;
140
138
 
141
139
  /**
142
140
  * On geocoded result what zoom level should the map animate to when a bbox isn't found in the response.
@@ -213,6 +211,20 @@ export type ControlOptions = {
213
211
  */
214
212
  showFullGeometry?: boolean;
215
213
 
214
+ /**
215
+ * Limit search to specified country(ies).
216
+ *
217
+ * @default undefined use all countries
218
+ */
219
+ country?: string | string[];
220
+
221
+ /**
222
+ * Filter of feature types to return.
223
+ *
224
+ * @default undefined all available feature types are returned
225
+ */
226
+ types?: string[];
227
+
216
228
  // TODO - missing but useful from maplibre-gl-geocoder
217
229
  // popup // If true, a Popup will be added to the map when clicking on a marker using a default set of popup options. If the value is an object, the popup will be constructed using these options. If false, no popup will be added to the map. Requires that options.maplibregl also be set. (optional, default true)
218
230
  // render // A function that specifies how the results should be rendered in the dropdown menu. This function should accepts a single Carmen GeoJSON object as input and return a string. Any HTML in the returned string will be rendered.