@maptiler/geocoding-control
Advanced tools
Comparing version 0.0.36 to 0.0.37
@@ -29,2 +29,6 @@ import * as L from "leaflet"; | ||
flyTo?: boolean | (L.ZoomPanOptions & L.FitBoundsOptions); | ||
/** | ||
* Style for full feature geometry GeoJSON. | ||
*/ | ||
fullGeometryStyle?: L.PathOptions | L.StyleFunction; | ||
}; | ||
@@ -36,3 +40,3 @@ export declare class GeocodingControl extends L.Control { | ||
setOptions(options: LeafletControlOptions): void; | ||
setQuery(value: string, submit?: boolean): void; | ||
setQuery(value: string, submit?: boolean | "always"): void; | ||
setReverseMode(value: boolean): void; | ||
@@ -39,0 +43,0 @@ focus(): void; |
import * as L from "leaflet"; | ||
import type { MapController } from "./types"; | ||
export declare function createLeafletMapController(map: L.Map, marker?: boolean | L.MarkerOptions, showResultMarkers?: boolean | L.MarkerOptions, flyToOptions?: L.ZoomPanOptions, flyToBounds?: L.FitBoundsOptions): MapController; | ||
export declare function createLeafletMapController(map: L.Map, marker?: boolean | L.MarkerOptions, showResultMarkers?: boolean | L.MarkerOptions, flyToOptions?: L.ZoomPanOptions, flyToBounds?: L.FitBoundsOptions, fullGeometryStyle?: L.PathOptions | L.StyleFunction): MapController; |
@@ -1,2 +0,2 @@ | ||
import { type Map, type IControl, type MarkerOptions, type FlyToOptions, type FitBoundsOptions, Evented } from "maplibre-gl"; | ||
import { type Map, type IControl, type MarkerOptions, type FlyToOptions, type FitBoundsOptions, Evented, type FillLayerSpecification, type LineLayerSpecification } from "maplibre-gl"; | ||
import type maplibregl from "maplibre-gl"; | ||
@@ -38,2 +38,9 @@ import type { ControlOptions } from "./types"; | ||
flyTo?: boolean | (FlyToOptions & FitBoundsOptions); | ||
/** | ||
* Style for full feature geometry GeoJSON. | ||
*/ | ||
fullGeometryStyle?: { | ||
fill: Pick<FillLayerSpecification, "layout" | "paint" | "filter">; | ||
line: Pick<LineLayerSpecification, "layout" | "paint" | "filter">; | ||
}; | ||
}; | ||
@@ -45,3 +52,3 @@ export declare class GeocodingControl extends Evented implements IControl { | ||
setOptions(options: MapLibreControlOptions): void; | ||
setQuery(value: string, submit?: boolean): void; | ||
setQuery(value: string, submit?: boolean | "always"): void; | ||
setReverseMode(value: boolean): void; | ||
@@ -48,0 +55,0 @@ focus(): void; |
import type MapLibreGL from "maplibre-gl"; | ||
import type { FitBoundsOptions, Map, FlyToOptions } from "maplibre-gl"; | ||
import type { FitBoundsOptions, Map, FlyToOptions, FillLayerSpecification, LineLayerSpecification } from "maplibre-gl"; | ||
import type { MapController } from "./types"; | ||
export declare function createMaplibreglMapController(map: Map, maplibregl?: typeof MapLibreGL | undefined, marker?: boolean | maplibregl.MarkerOptions, showResultMarkers?: boolean | maplibregl.MarkerOptions, flyToOptions?: FlyToOptions, fitBoundsOptions?: FitBoundsOptions): MapController; | ||
export declare function createMaplibreglMapController(map: Map, maplibregl?: typeof MapLibreGL | undefined, marker?: boolean | maplibregl.MarkerOptions, showResultMarkers?: boolean | maplibregl.MarkerOptions, flyToOptions?: FlyToOptions, fitBoundsOptions?: FitBoundsOptions, fullGeometryStyle?: { | ||
fill: Pick<FillLayerSpecification, "layout" | "paint" | "filter">; | ||
line: Pick<LineLayerSpecification, "layout" | "paint" | "filter">; | ||
}): MapController; |
@@ -119,8 +119,20 @@ export declare type Feature = GeoJSON.Feature & { | ||
/** | ||
* Set to `true` to enable reverse geocoding button with title _toggle reverse geocoding_ or set the button title directly. | ||
* Set to `true` to enable reverse geocoding button with title. Set to `"always"` to reverse geocoding be always active. | ||
* | ||
* @default false | ||
*/ | ||
enableReverse?: boolean | string; | ||
enableReverse?: boolean | "always"; | ||
/** | ||
* Reverse toggle button title. | ||
* | ||
* @default "toggle reverse geocoding" | ||
*/ | ||
reverseButtonTitle?: string; | ||
/** | ||
* Clear button title. | ||
* | ||
* @default "clear" | ||
*/ | ||
clearButtonTitle?: string; | ||
/** | ||
* Set to `true` to show place type. | ||
@@ -131,2 +143,8 @@ * | ||
showPlaceType?: boolean; | ||
/** | ||
* Set to `true` to show full feature geometry of the chosen result. Otherwise only marker will be shown. | ||
* | ||
* @default true | ||
*/ | ||
showFullGeometry?: boolean; | ||
}; |
{ | ||
"name": "@maptiler/geocoding-control", | ||
"version": "0.0.36", | ||
"version": "0.0.37", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "scripts": { |
@@ -102,3 +102,7 @@ # MapTiler Geocoding control for MapLibre GL JS and Leaflet | ||
- `class`: `string` - Class of the root element. | ||
- `enableReverse`: `boolean | string` - Set to `true` to enable reverse geocoding button with title _toggle reverse geocoding_ or set the button title directly. Default `false`. | ||
- `enableReverse`: `boolean | "always""` - Set to `true` to enable reverse geocoding button with title. Set to `"always"` to reverse geocoding be always active. Default `false`. | ||
- `reverseButtonTitle`: `string` - Reverse toggle button title. Default `"toggle reverse geocoding"`. | ||
- `clearButtonTitle`: `string` - Clear button title. Default `"clear"`. | ||
- `showFullGeometry`: `boolean` - Set to `true` to show full feature geometry of the chosen result. Otherwise only marker will be shown. Default `true`. | ||
- `fullGeometryStyle`: `{ fill: Pick<FillLayerSpecification, "layout" | "paint" | "filter">; line: Pick<LineLayerSpecification, "layout" | "paint" | "filter">; } | (L.PathOptions | L.StyleFunction)` - style of the full feature geometry. See Mapplibre GL JS or Leaflet documentation. | ||
@@ -110,3 +114,3 @@ Methods: | ||
- `blur(): void` - blur the query input box | ||
- `setReverseMode(value: boolean): void` - set reverse mode | ||
- `setReverseMode(value: boolean | "always"): void` - set reverse mode | ||
@@ -113,0 +117,0 @@ Events: |
@@ -35,2 +35,7 @@ import * as L from "leaflet"; | ||
flyTo?: boolean | (L.ZoomPanOptions & L.FitBoundsOptions); | ||
/** | ||
* Style for full feature geometry GeoJSON. | ||
*/ | ||
fullGeometryStyle?: L.PathOptions | L.StyleFunction; | ||
}; | ||
@@ -57,3 +62,9 @@ | ||
const { marker, showResultMarkers, flyTo, ...restOptions } = this.#options; | ||
const { | ||
marker, | ||
showResultMarkers, | ||
flyTo, | ||
fullGeometryStyle, | ||
...restOptions | ||
} = this.#options; | ||
@@ -67,3 +78,4 @@ const flyToOptions = typeof flyTo === "boolean" ? {} : flyTo; | ||
flyToOptions, | ||
flyToOptions | ||
flyToOptions, | ||
fullGeometryStyle | ||
); | ||
@@ -101,3 +113,9 @@ | ||
const { marker, showResultMarkers, flyTo, ...restOptions } = this.#options; | ||
const { | ||
marker, | ||
showResultMarkers, | ||
flyTo, | ||
fullGeometryStyle, | ||
...restOptions | ||
} = this.#options; | ||
@@ -107,3 +125,3 @@ this.#gc?.$set(restOptions); | ||
setQuery(value: string, submit = true) { | ||
setQuery(value: string, submit: boolean | "always" = true) { | ||
(this.#gc as any)?.setQuery(value, submit); | ||
@@ -110,0 +128,0 @@ } |
import * as L from "leaflet"; | ||
import MarkerIcon from "./MarkerIcon.svelte"; | ||
import type { Feature, MapController, Proximity } from "./types"; | ||
import type { | ||
Polygon, | ||
MultiPolygon, | ||
LineString, | ||
MultiLineString, | ||
} from "@turf/helpers"; | ||
import mask from "@turf/mask"; | ||
import union from "@turf/union"; | ||
@@ -10,3 +18,17 @@ export function createLeafletMapController( | ||
flyToOptions: L.ZoomPanOptions = {}, | ||
flyToBounds: L.FitBoundsOptions = {} | ||
flyToBounds: L.FitBoundsOptions = {}, | ||
fullGeometryStyle: L.PathOptions | L.StyleFunction = (feature) => { | ||
const type = feature?.geometry?.type; | ||
const weight = type === "LineString" || type === "MultiLineString" ? 3 : 2; | ||
return { | ||
color: "#3170fe", | ||
fillColor: "#000", | ||
fillOpacity: 0.1, | ||
weight, | ||
dashArray: [weight, weight], | ||
lineCap: "butt", | ||
}; | ||
} | ||
) { | ||
@@ -23,2 +45,6 @@ let proximityChangeHandler: ((proximity: Proximity) => void) | undefined; | ||
let resultLayer = L.geoJSON(undefined, { | ||
style: fullGeometryStyle, | ||
}).addTo(map); | ||
const handleMoveEnd = () => { | ||
@@ -81,3 +107,3 @@ if (!proximityChangeHandler) { | ||
flyTo(center: [number, number], zoom: number) { | ||
map.flyTo(center, zoom, flyToOptions); | ||
map.flyTo(center, zoom, { duration: 2, ...flyToOptions }); | ||
}, | ||
@@ -91,3 +117,3 @@ | ||
], | ||
{ ...flyToBounds, padding: [padding, padding] } | ||
{ padding: [padding, padding], duration: 2, ...flyToBounds } | ||
); | ||
@@ -104,2 +130,10 @@ }, | ||
): void { | ||
function setData(data?: GeoJSON.GeoJSON) { | ||
resultLayer.clearLayers(); | ||
if (data) { | ||
resultLayer.addData(data); | ||
} | ||
} | ||
for (const marker of markers) { | ||
@@ -111,27 +145,92 @@ marker.remove(); | ||
for (const feature of picked | ||
? [...(markedFeatures ?? []), picked] | ||
: markedFeatures ?? []) { | ||
let m: L.Marker; | ||
setData(); | ||
const pos: L.LatLngExpression = [feature.center[1], feature.center[0]]; | ||
const createMarker = (pos: L.LatLngExpression) => { | ||
const element = document.createElement("div"); | ||
if (feature === picked && typeof marker === "object") { | ||
m = new L.Marker(pos, marker); | ||
new MarkerIcon({ props: { displayIn: "leaflet" }, target: element }); | ||
return new L.Marker(pos, { | ||
icon: new L.DivIcon({ html: element, className: "" }), | ||
}); | ||
}; | ||
if (picked) { | ||
let handled = false; | ||
if (picked.geometry.type === "GeometryCollection") { | ||
const geoms = picked.geometry.geometries.filter( | ||
(geometry) => | ||
geometry.type === "Polygon" || geometry.type === "MultiPolygon" | ||
) as (Polygon | MultiPolygon)[]; | ||
if (geoms.length > 0) { | ||
let geometry = geoms.pop()!; | ||
for (const geom of geoms) { | ||
geometry = union(geometry, geom) as unknown as | ||
| Polygon | ||
| MultiPolygon; // union actually returns geometry | ||
} | ||
setData(mask({ ...picked, geometry })); | ||
handled = true; | ||
} else { | ||
const geometries = picked.geometry.geometries.filter( | ||
(geometry) => | ||
geometry.type === "LineString" || | ||
geometry.type === "MultiLineString" | ||
) as (LineString | MultiLineString)[]; | ||
if (geometries.length > 0) { | ||
setData({ | ||
...picked, | ||
geometry: { type: "GeometryCollection", geometries }, | ||
}); | ||
handled = true; | ||
} | ||
} | ||
} | ||
if (handled) { | ||
// nothing | ||
} else if ( | ||
feature !== picked && | ||
typeof showResultMarkers === "object" | ||
picked.geometry.type === "Polygon" || | ||
picked.geometry.type === "MultiPolygon" | ||
) { | ||
m = new L.Marker(pos, showResultMarkers); | ||
} else { | ||
const element = document.createElement("div"); | ||
setData(mask(picked as any)); | ||
} else if ( | ||
picked.geometry.type === "LineString" || | ||
picked.geometry.type === "MultiLineString" | ||
) { | ||
setData(picked as any); | ||
new MarkerIcon({ props: { displayIn: "leaflet" }, target: element }); | ||
return; // no pin for (multi)linestrings | ||
} | ||
m = new L.Marker(pos, { | ||
icon: new L.DivIcon({ html: element, className: "" }), | ||
}); | ||
const pos: L.LatLngExpression = [picked.center[1], picked.center[0]]; | ||
markers.push( | ||
(typeof marker === "object" | ||
? new L.Marker(pos, marker) | ||
: createMarker(pos) | ||
).addTo(map) | ||
); | ||
} | ||
for (const feature of markedFeatures ?? []) { | ||
if (feature === picked) { | ||
continue; | ||
} | ||
markers.push(m.addTo(map)); | ||
const pos: L.LatLngExpression = [feature.center[1], feature.center[0]]; | ||
markers.push( | ||
(typeof showResultMarkers === "object" | ||
? new L.Marker(pos, showResultMarkers) | ||
: createMarker(pos) | ||
).addTo(map) | ||
); | ||
} | ||
@@ -138,0 +237,0 @@ }, |
@@ -8,2 +8,4 @@ import { | ||
Evented, | ||
type FillLayerSpecification, | ||
type LineLayerSpecification, | ||
} from "maplibre-gl"; | ||
@@ -53,2 +55,10 @@ import type maplibregl from "maplibre-gl"; | ||
flyTo?: boolean | (FlyToOptions & FitBoundsOptions); | ||
/** | ||
* Style for full feature geometry GeoJSON. | ||
*/ | ||
fullGeometryStyle?: { | ||
fill: Pick<FillLayerSpecification, "layout" | "paint" | "filter">; | ||
line: Pick<LineLayerSpecification, "layout" | "paint" | "filter">; | ||
}; | ||
}; | ||
@@ -73,4 +83,10 @@ | ||
const { maplibregl, marker, showResultMarkers, flyTo, ...restOptions } = | ||
this.#options; | ||
const { | ||
maplibregl, | ||
marker, | ||
showResultMarkers, | ||
flyTo, | ||
fullGeometryStyle, | ||
...restOptions | ||
} = this.#options; | ||
@@ -85,3 +101,4 @@ const flyToOptions = typeof flyTo === "boolean" ? {} : flyTo; | ||
flyToOptions, | ||
flyToOptions | ||
flyToOptions, | ||
fullGeometryStyle | ||
); | ||
@@ -119,4 +136,10 @@ | ||
const { maplibregl, marker, showResultMarkers, flyTo, ...restOptions } = | ||
this.#options; | ||
const { | ||
maplibregl, | ||
marker, | ||
showResultMarkers, | ||
flyTo, | ||
fullGeometryStyle, | ||
...restOptions | ||
} = this.#options; | ||
@@ -126,3 +149,3 @@ this.#gc?.$set(restOptions); | ||
setQuery(value: string, submit = true) { | ||
setQuery(value: string, submit: boolean | "always" = true) { | ||
(this.#gc as any)?.setQuery(value, submit); | ||
@@ -129,0 +152,0 @@ } |
@@ -10,2 +10,4 @@ import type MapLibreGL from "maplibre-gl"; | ||
GeoJSONSource, | ||
FillLayerSpecification, | ||
LineLayerSpecification, | ||
} from "maplibre-gl"; | ||
@@ -34,3 +36,25 @@ import MarkerIcon from "./MarkerIcon.svelte"; | ||
flyToOptions: FlyToOptions = {}, | ||
fitBoundsOptions: FitBoundsOptions = {} | ||
fitBoundsOptions: FitBoundsOptions = {}, | ||
fullGeometryStyle: { | ||
fill: Pick<FillLayerSpecification, "layout" | "paint" | "filter">; | ||
line: Pick<LineLayerSpecification, "layout" | "paint" | "filter">; | ||
} = { | ||
fill: { | ||
layout: {}, | ||
paint: { | ||
"fill-color": "#000", | ||
"fill-opacity": 0.1, | ||
}, | ||
}, | ||
line: { | ||
layout: { | ||
"line-cap": "square", | ||
}, | ||
paint: { | ||
"line-width": ["case", ["==", ["geometry-type"], "Polygon"], 2, 3], | ||
"line-dasharray": [1, 1], | ||
"line-color": "#3170fe", | ||
}, | ||
}, | ||
} | ||
) { | ||
@@ -47,4 +71,4 @@ let proximityChangeHandler: ((proximity: Proximity) => void) | undefined; | ||
function addPreviewLayer() { | ||
map.addSource("preview", { | ||
function addFullGeometryLayer() { | ||
map.addSource("full-geom", { | ||
type: "geojson", | ||
@@ -55,10 +79,6 @@ data: emptyGeojson, | ||
map.addLayer({ | ||
id: "preview-fill", | ||
...fullGeometryStyle.fill, | ||
id: "full-geom-fill", | ||
type: "fill", | ||
source: "preview", | ||
layout: {}, | ||
paint: { | ||
"fill-color": "#000", | ||
"fill-opacity": 0.1, | ||
}, | ||
source: "full-geom", | ||
filter: ["==", ["geometry-type"], "Polygon"], | ||
@@ -68,13 +88,6 @@ }); | ||
map.addLayer({ | ||
id: "preview-line", | ||
...fullGeometryStyle.line, | ||
id: "full-geom-line", | ||
type: "line", | ||
source: "preview", | ||
layout: { | ||
"line-cap": "square", | ||
}, | ||
paint: { | ||
"line-width": ["case", ["==", ["geometry-type"], "Polygon"], 2, 3], | ||
"line-dasharray": [1, 1], | ||
"line-color": "#3170fe", | ||
}, | ||
source: "full-geom", | ||
}); | ||
@@ -84,6 +97,6 @@ } | ||
if (map.loaded()) { | ||
addPreviewLayer(); | ||
addFullGeometryLayer(); | ||
} else { | ||
map.once("load", () => { | ||
addPreviewLayer(); | ||
addFullGeometryLayer(); | ||
}); | ||
@@ -165,3 +178,3 @@ } | ||
function setData(data: GeoJSON.GeoJSON) { | ||
(map.getSource("preview") as GeoJSONSource)?.setData(data); | ||
(map.getSource("full-geom") as GeoJSONSource)?.setData(data); | ||
} | ||
@@ -173,6 +186,6 @@ | ||
markers.length = 0; | ||
setData(emptyGeojson); | ||
markers.length = 0; | ||
if (!maplibregl) { | ||
@@ -182,2 +195,13 @@ return; | ||
const createMarker = () => { | ||
const element = document.createElement("div"); | ||
new MarkerIcon({ | ||
props: { displayIn: "maplibre" }, | ||
target: element, | ||
}); | ||
return new maplibregl.Marker({ element }); | ||
}; | ||
if (picked) { | ||
@@ -222,4 +246,2 @@ let handled = false; | ||
let m: Marker | undefined = undefined; | ||
if (handled) { | ||
@@ -238,21 +260,13 @@ // nothing | ||
return; | ||
return; // no pin for (multi)linestrings | ||
} | ||
if (typeof marker === "object") { | ||
m = new maplibregl.Marker(marker); | ||
} else { | ||
const element = document.createElement("div"); | ||
new MarkerIcon({ | ||
props: { displayIn: "maplibre" }, | ||
target: element, | ||
}); | ||
m = new maplibregl.Marker({ element }); | ||
} | ||
if (m) { | ||
markers.push(m.setLngLat(picked.center).addTo(map)); | ||
} | ||
markers.push( | ||
(typeof marker === "object" | ||
? new maplibregl.Marker(marker) | ||
: createMarker() | ||
) | ||
.setLngLat(picked.center) | ||
.addTo(map) | ||
); | ||
} | ||
@@ -265,15 +279,10 @@ | ||
let m: Marker; | ||
if (typeof showResultMarkers === "object") { | ||
m = new maplibregl.Marker(showResultMarkers); | ||
} else { | ||
const element = document.createElement("div"); | ||
new MarkerIcon({ props: { displayIn: "maplibre" }, target: element }); | ||
m = new maplibregl.Marker({ element }); | ||
} | ||
markers.push(m.setLngLat(feature.center).addTo(map)); | ||
markers.push( | ||
(typeof showResultMarkers === "object" | ||
? new maplibregl.Marker(showResultMarkers) | ||
: createMarker() | ||
) | ||
.setLngLat(feature.center) | ||
.addTo(map) | ||
); | ||
} | ||
@@ -280,0 +289,0 @@ }, |
@@ -182,9 +182,23 @@ export type Feature = GeoJSON.Feature & { | ||
/** | ||
* Set to `true` to enable reverse geocoding button with title _toggle reverse geocoding_ or set the button title directly. | ||
* Set to `true` to enable reverse geocoding button with title. Set to `"always"` to reverse geocoding be always active. | ||
* | ||
* @default false | ||
*/ | ||
enableReverse?: boolean | string; | ||
enableReverse?: boolean | "always"; | ||
/** | ||
* Reverse toggle button title. | ||
* | ||
* @default "toggle reverse geocoding" | ||
*/ | ||
reverseButtonTitle?: string; | ||
/** | ||
* Clear button title. | ||
* | ||
* @default "clear" | ||
*/ | ||
clearButtonTitle?: string; | ||
/** | ||
* Set to `true` to show place type. | ||
@@ -196,2 +210,9 @@ * | ||
/** | ||
* Set to `true` to show full feature geometry of the chosen result. Otherwise only marker will be shown. | ||
* | ||
* @default true | ||
*/ | ||
showFullGeometry?: boolean; | ||
// TODO - missing but useful from maplibre-gl-geocoder | ||
@@ -198,0 +219,0 @@ // 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) |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
343628
6483
184
24
9