@mapka/maplibre-gl-sdk 0.9.0 → 0.11.0
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/lib/.buildInfo.json +1 -1
- package/lib/components/PopupContent.d.ts +10 -0
- package/lib/components/PopupContent.d.ts.map +1 -0
- package/lib/components/PopupContent.js +64 -0
- package/lib/map.d.ts +24 -2
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +32 -6
- package/lib/modules/markers.d.ts +10 -2
- package/lib/modules/markers.d.ts.map +1 -1
- package/lib/modules/markers.js +118 -38
- package/lib/modules/popup.d.ts +14 -0
- package/lib/modules/popup.d.ts.map +1 -0
- package/lib/modules/popup.js +124 -0
- package/lib/types/id.d.ts +6 -0
- package/lib/types/id.d.ts.map +1 -0
- package/lib/types/id.js +1 -0
- package/lib/types/marker.d.ts +16 -18
- package/lib/types/marker.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/components/PopupContent.css +177 -0
- package/src/components/{Tooltip.tsx → PopupContent.tsx} +35 -73
- package/src/map.ts +74 -8
- package/src/modules/markers.ts +133 -43
- package/src/modules/popup.tsx +155 -0
- package/src/styles.css +21 -65
- package/src/types/id.ts +1 -0
- package/src/types/marker.ts +18 -19
- package/lib/components/Tooltip.d.ts +0 -9
- package/lib/components/Tooltip.d.ts.map +0 -1
- package/lib/components/Tooltip.js +0 -81
- package/lib/modules/tooltip.d.ts +0 -15
- package/lib/modules/tooltip.d.ts.map +0 -1
- package/lib/modules/tooltip.js +0 -39
- package/src/modules/tooltip.tsx +0 -52
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
import type { MapkaPopupContent } from "../types/marker.js";
|
|
4
|
+
interface PopupProps extends MapkaPopupContent {
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
closeButton?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function PopupContent({ title, description, closeButton, imageUrls, onFavorite, onClose, }: PopupProps): h.JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=PopupContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PopupContent.d.ts","sourceRoot":"","sources":["../../src/components/PopupContent.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,CAAC,EAAY,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,UAAU,UAAW,SAAQ,iBAAiB;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA8LD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,GACR,EAAE,UAAU,iBAqBZ"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h, Fragment } from "preact";
|
|
3
|
+
import { useState } from "preact/hooks";
|
|
4
|
+
function HeartIcon({ filled }) {
|
|
5
|
+
return (h("svg", { viewBox: "0 0 32 32", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon" },
|
|
6
|
+
h("path", { d: "M16 28c7-4.73 14-10 14-17a6.98 6.98 0 0 0-7-7c-1.8 0-3.58.68-4.95 2.05L16 8.1l-2.05-2.05a6.98 6.98 0 0 0-9.9 0A6.98 6.98 0 0 0 2 11c0 7 7 12.27 14 17z", fill: filled ? "currentColor" : "none", stroke: "currentColor", "stroke-width": "2" })));
|
|
7
|
+
}
|
|
8
|
+
function CloseIcon() {
|
|
9
|
+
return (h("svg", { viewBox: "0 0 32 32", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon" },
|
|
10
|
+
h("path", { d: "m6 6 20 20M26 6 6 26", fill: "none", stroke: "currentColor", "stroke-width": "3" })));
|
|
11
|
+
}
|
|
12
|
+
function ChevronLeftIcon() {
|
|
13
|
+
return (h("svg", { viewBox: "0 0 32 32", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon mapka-popup-icon-sm" },
|
|
14
|
+
h("path", { d: "M20 28 8.7 16.7a1 1 0 0 1 0-1.4L20 4", fill: "none", stroke: "currentColor", "stroke-width": "4" })));
|
|
15
|
+
}
|
|
16
|
+
function ChevronRightIcon() {
|
|
17
|
+
return (h("svg", { viewBox: "0 0 32 32", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon mapka-popup-icon-sm" },
|
|
18
|
+
h("path", { d: "m12 4 11.3 11.3a1 1 0 0 1 0 1.4L12 28", fill: "none", stroke: "currentColor", "stroke-width": "4" })));
|
|
19
|
+
}
|
|
20
|
+
function ImageCarousel({ imageUrls, title, onFavorite, id, closeButton, onClose, }) {
|
|
21
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
22
|
+
const handlePrev = (e) => {
|
|
23
|
+
e.stopPropagation();
|
|
24
|
+
setCurrentIndex((prev) => (prev === 0 ? imageUrls.length - 1 : prev - 1));
|
|
25
|
+
};
|
|
26
|
+
const handleNext = (e) => {
|
|
27
|
+
e.stopPropagation();
|
|
28
|
+
setCurrentIndex((prev) => (prev + 1) % imageUrls.length);
|
|
29
|
+
};
|
|
30
|
+
const handleFavoriteClick = (e) => {
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
if (onFavorite && id) {
|
|
33
|
+
onFavorite(id);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const handleCloseClick = (e) => {
|
|
37
|
+
e.stopPropagation();
|
|
38
|
+
onClose?.();
|
|
39
|
+
};
|
|
40
|
+
return (h("div", { class: "mapka-popup-carousel" },
|
|
41
|
+
h("div", { class: "mapka-popup-carousel-track", style: { transform: `translateX(-${currentIndex * 100}%)` } }, imageUrls.map((url, index) => (h("img", { key: index, src: url, alt: title || `Image ${index + 1}`, class: "mapka-popup-carousel-image" })))),
|
|
42
|
+
h("div", { class: "mapka-popup-carousel-actions" },
|
|
43
|
+
onFavorite && (h("button", { type: "button", class: "mapka-popup-action-btn", onClick: handleFavoriteClick, "aria-label": "Add to favorites" },
|
|
44
|
+
h(HeartIcon, null))),
|
|
45
|
+
closeButton && (h("button", { type: "button", class: "mapka-popup-action-btn", onClick: handleCloseClick, "aria-label": "Close" },
|
|
46
|
+
h(CloseIcon, null)))),
|
|
47
|
+
imageUrls.length > 1 && (h(Fragment, null,
|
|
48
|
+
h("button", { type: "button", class: "mapka-popup-carousel-btn mapka-popup-carousel-prev", onClick: handlePrev, "aria-label": "Previous image" },
|
|
49
|
+
h(ChevronLeftIcon, null)),
|
|
50
|
+
h("button", { type: "button", class: "mapka-popup-carousel-btn mapka-popup-carousel-next", onClick: handleNext, "aria-label": "Next image" },
|
|
51
|
+
h(ChevronRightIcon, null)),
|
|
52
|
+
h("div", { class: "mapka-popup-dots" }, imageUrls.map((_, index) => (h("button", { key: index, type: "button", class: `mapka-popup-dot ${index === currentIndex ? "mapka-popup-dot-active" : ""}`, onClick: (e) => {
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
setCurrentIndex(index);
|
|
55
|
+
}, "aria-label": `Go to image ${index + 1}` }))))))));
|
|
56
|
+
}
|
|
57
|
+
export function PopupContent({ title, description, closeButton, imageUrls, onFavorite, onClose, }) {
|
|
58
|
+
const hasImages = imageUrls && imageUrls.length > 0;
|
|
59
|
+
return (h("div", { class: "mapka-tooltip" },
|
|
60
|
+
hasImages && (h(ImageCarousel, { imageUrls: imageUrls, title: title, closeButton: closeButton, onFavorite: onFavorite, onClose: onClose })),
|
|
61
|
+
h("div", { class: "mapka-popup-content" },
|
|
62
|
+
title && h("h3", { class: "mapka-popup-title" }, title),
|
|
63
|
+
description && h("p", { class: "mapka-popup-description" }, description))));
|
|
64
|
+
}
|
package/lib/map.d.ts
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
import * as maplibregl from "maplibre-gl";
|
|
2
|
-
import type { MapOptions, StyleSwapOptions, StyleOptions, StyleSpecification } from "maplibre-gl";
|
|
2
|
+
import type { Marker, Popup, MapOptions, StyleSwapOptions, StyleOptions, StyleSpecification } from "maplibre-gl";
|
|
3
|
+
import type { MapkaMarkerOptions, MapkaPopupOptions } from "./types/marker.js";
|
|
3
4
|
export interface MapkaMapOptions extends MapOptions {
|
|
5
|
+
maxPopups?: number;
|
|
4
6
|
apiKey: string;
|
|
5
7
|
env?: "dev" | "prod" | "local";
|
|
6
8
|
}
|
|
9
|
+
export type MapMapkaPopup = {
|
|
10
|
+
id: string;
|
|
11
|
+
container: HTMLElement;
|
|
12
|
+
options: MapkaPopupOptions;
|
|
13
|
+
popup: Popup;
|
|
14
|
+
};
|
|
15
|
+
export type MapMapkaMarker = {
|
|
16
|
+
id: string;
|
|
17
|
+
options: MapkaMarkerOptions;
|
|
18
|
+
marker: Marker;
|
|
19
|
+
};
|
|
7
20
|
export declare class MapkaMap extends maplibregl.Map {
|
|
8
21
|
static env: string;
|
|
9
|
-
|
|
22
|
+
markers: MapMapkaMarker[];
|
|
23
|
+
maxPopups: number;
|
|
24
|
+
popups: MapMapkaPopup[];
|
|
25
|
+
constructor({ transformRequest, apiKey, maxPopups, ...options }: MapkaMapOptions);
|
|
10
26
|
setStyle(style: string | StyleSpecification, options?: StyleSwapOptions & StyleOptions): this;
|
|
27
|
+
addMarkers(markers: MapkaMarkerOptions[]): void;
|
|
28
|
+
updateMarkers(markers: MapkaMarkerOptions[]): void;
|
|
29
|
+
clearMarkers(): void;
|
|
30
|
+
openPopup(popup: MapkaPopupOptions, id?: string): string;
|
|
31
|
+
closePopup(id: string): void;
|
|
32
|
+
updatePopup(popup: MapkaPopupOptions, id?: string): void;
|
|
11
33
|
}
|
|
12
34
|
//# sourceMappingURL=map.d.ts.map
|
package/lib/map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAgB1C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EAGL,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAChC;AA0BD,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,QAAS,SAAQ,UAAU,CAAC,GAAG;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAU;IAErB,OAAO,EAAE,cAAc,EAAE,CAAM;IAE/B,SAAS,EAAE,MAAM,CAAK;IACtB,MAAM,EAAE,aAAa,EAAE,CAAM;gBAEjB,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAa,EAAE,GAAG,OAAO,EAAE,EAAE,eAAe;IAoBpF,QAAQ,CACb,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAClC,OAAO,GAAE,gBAAgB,GAAG,YAAiB;IAexC,UAAU,CAAC,OAAO,EAAE,kBAAkB,EAAE;IAIxC,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE;IAI3C,YAAY;IAIZ,SAAS,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,GAAE,MAA0B;IAIlE,UAAU,CAAC,EAAE,EAAE,MAAM;IAIrB,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,GAAE,MAA0B;CAG5E"}
|
package/lib/map.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as maplibregl from "maplibre-gl";
|
|
2
2
|
import { loadLayersIcons } from "./modules/icons.js";
|
|
3
|
-
import {
|
|
3
|
+
import { closeOnMapClickPopups, closePopupsById, getPopupId, openPopup, updatePopup, } from "./modules/popup.js";
|
|
4
|
+
import { addMarkers, addStyleDiffMarkers, addStyleMarkers, clearMarkers, updateMarkers, } from "./modules/markers.js";
|
|
4
5
|
const noopTransformRequest = (url) => {
|
|
5
6
|
return {
|
|
6
7
|
url,
|
|
@@ -22,27 +23,52 @@ const noopTransformStyle = (_, next) => {
|
|
|
22
23
|
};
|
|
23
24
|
export class MapkaMap extends maplibregl.Map {
|
|
24
25
|
static env = "prod";
|
|
25
|
-
|
|
26
|
+
markers = [];
|
|
27
|
+
maxPopups = 1;
|
|
28
|
+
popups = [];
|
|
29
|
+
constructor({ transformRequest, apiKey, maxPopups = 1, ...options }) {
|
|
26
30
|
super({
|
|
27
31
|
...options,
|
|
28
32
|
transformRequest: createTransformRequest(apiKey, transformRequest),
|
|
29
33
|
});
|
|
30
|
-
|
|
31
|
-
addMarkers(this);
|
|
32
|
-
});
|
|
34
|
+
this.maxPopups = maxPopups;
|
|
33
35
|
super.on("styleimagemissing", (event) => {
|
|
34
36
|
loadLayersIcons(this, event);
|
|
35
37
|
});
|
|
38
|
+
super.on("click", () => {
|
|
39
|
+
closeOnMapClickPopups(this);
|
|
40
|
+
});
|
|
41
|
+
super.on("style.load", () => {
|
|
42
|
+
addStyleMarkers(this);
|
|
43
|
+
});
|
|
36
44
|
}
|
|
37
45
|
setStyle(style, options = {}) {
|
|
38
46
|
const { transformStyle = noopTransformStyle, ...rest } = options;
|
|
39
47
|
super.setStyle(style, {
|
|
40
48
|
...rest,
|
|
41
49
|
transformStyle: (prev, next) => {
|
|
42
|
-
|
|
50
|
+
addStyleDiffMarkers(this, next);
|
|
43
51
|
return transformStyle(prev, next);
|
|
44
52
|
},
|
|
45
53
|
});
|
|
46
54
|
return this;
|
|
47
55
|
}
|
|
56
|
+
addMarkers(markers) {
|
|
57
|
+
addMarkers(this, markers);
|
|
58
|
+
}
|
|
59
|
+
updateMarkers(markers) {
|
|
60
|
+
updateMarkers(this, markers);
|
|
61
|
+
}
|
|
62
|
+
clearMarkers() {
|
|
63
|
+
clearMarkers(this);
|
|
64
|
+
}
|
|
65
|
+
openPopup(popup, id = getPopupId(popup)) {
|
|
66
|
+
return openPopup(this, popup, id);
|
|
67
|
+
}
|
|
68
|
+
closePopup(id) {
|
|
69
|
+
closePopupsById(this, id);
|
|
70
|
+
}
|
|
71
|
+
updatePopup(popup, id = getPopupId(popup)) {
|
|
72
|
+
return updatePopup(this, popup, id);
|
|
73
|
+
}
|
|
48
74
|
}
|
package/lib/modules/markers.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { StyleSpecification } from "maplibre-gl";
|
|
2
2
|
import type { MapkaMap } from "../map.js";
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
3
|
+
import type { MapkaMarkerOptions } from "../types/marker.js";
|
|
4
|
+
export declare function getMarkerId(marker: {
|
|
5
|
+
id?: string;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function addMarkers(currentMap: MapkaMap, markersOptions: MapkaMarkerOptions[]): void;
|
|
8
|
+
export declare function removeMarkersByIds(map: MapkaMap, ids: string[]): void;
|
|
9
|
+
export declare function updateMarkers(map: MapkaMap, markersOptions: MapkaMarkerOptions[]): void;
|
|
10
|
+
export declare function clearMarkers(map: MapkaMap): void;
|
|
11
|
+
export declare function addStyleMarkers(map: MapkaMap): void;
|
|
12
|
+
export declare function addStyleDiffMarkers(map: MapkaMap, next: StyleSpecification): void;
|
|
5
13
|
//# sourceMappingURL=markers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/modules/markers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/modules/markers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAU,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAqB,MAAM,oBAAoB,CAAC;AAkBhF,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAElD;AA4ED,wBAAgB,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAcpF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAK9D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAKhF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,QAKzC;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,QAK5C;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,QAG1E"}
|
package/lib/modules/markers.js
CHANGED
|
@@ -1,47 +1,127 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Marker } from "maplibre-gl";
|
|
2
2
|
import { get } from "es-toolkit/compat";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
3
|
+
import { getPopupId } from "./popup.js";
|
|
4
|
+
import { remove } from "es-toolkit";
|
|
5
|
+
/**
|
|
6
|
+
* Default marker offset
|
|
7
|
+
* @see https://github.com/maplibre/maplibre-gl-js/blob/master/src/ui/marker.ts#L457
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_MARKET_OFFSET = {
|
|
10
|
+
top: [0, 0],
|
|
11
|
+
"top-left": [0, 0],
|
|
12
|
+
"top-right": [0, 0],
|
|
13
|
+
bottom: [0, -38.1],
|
|
14
|
+
"bottom-left": [9.54594154601839, -34.14594154601839],
|
|
15
|
+
"bottom-right": [-9.54594154601839, -34.14594154601839],
|
|
16
|
+
left: [13.5, -24.6],
|
|
17
|
+
right: [-13.5, -24.6],
|
|
18
|
+
};
|
|
19
|
+
export function getMarkerId(marker) {
|
|
20
|
+
return marker.id ?? `marker-${crypto.randomUUID()}`;
|
|
21
|
+
}
|
|
22
|
+
const markerPopupOptions = (marker, popupOptions) => {
|
|
23
|
+
const latLng = marker.getLngLat().toArray();
|
|
24
|
+
if ("offset" in popupOptions) {
|
|
25
|
+
return {
|
|
26
|
+
...popupOptions,
|
|
27
|
+
lngLat: latLng,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return {
|
|
32
|
+
...popupOptions,
|
|
33
|
+
lngLat: latLng,
|
|
34
|
+
offset: DEFAULT_MARKET_OFFSET,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
function setupMarkerPopupListeners(map, marker, popup, options) {
|
|
39
|
+
const popupId = getPopupId(popup);
|
|
40
|
+
const markerElement = marker.getElement();
|
|
41
|
+
if (options.draggable) {
|
|
42
|
+
marker.on("dragend", () => {
|
|
43
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
44
|
+
map.updatePopup(markerPopupOptions(marker, popup), popupId);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
marker.on("drag", () => {
|
|
48
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
49
|
+
map.updatePopup(markerPopupOptions(marker, popup), popupId);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (popup.trigger === "always") {
|
|
54
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
55
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
35
56
|
}
|
|
36
|
-
|
|
57
|
+
markerElement.addEventListener("click", (e) => {
|
|
58
|
+
e.stopPropagation();
|
|
59
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
60
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else if (popup.trigger === "click") {
|
|
65
|
+
markerElement.style.cursor = "pointer";
|
|
66
|
+
markerElement.addEventListener("click", (e) => {
|
|
67
|
+
e.stopPropagation();
|
|
68
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
69
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else if (popup.trigger === "hover") {
|
|
74
|
+
markerElement.addEventListener("mouseenter", (e) => {
|
|
75
|
+
e.stopPropagation();
|
|
76
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
77
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
markerElement.addEventListener("mouseleave", (e) => {
|
|
81
|
+
e.stopPropagation();
|
|
82
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
83
|
+
map.closePopup(popupId);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export function addMarkers(currentMap, markersOptions) {
|
|
89
|
+
for (const markerOptions of markersOptions) {
|
|
90
|
+
const { lngLat, popup, ...options } = markerOptions;
|
|
91
|
+
const newMarker = new Marker(options).setLngLat(lngLat).addTo(currentMap);
|
|
92
|
+
currentMap.markers.push({
|
|
93
|
+
id: getMarkerId(markerOptions),
|
|
94
|
+
options: markerOptions,
|
|
95
|
+
marker: newMarker,
|
|
96
|
+
});
|
|
97
|
+
if (!popup)
|
|
98
|
+
continue;
|
|
99
|
+
setupMarkerPopupListeners(currentMap, newMarker, popup, markerOptions);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function removeMarkersByIds(map, ids) {
|
|
103
|
+
const removedMarkers = remove(map.markers, (marker) => ids.includes(marker.id));
|
|
104
|
+
for (const marker of removedMarkers) {
|
|
105
|
+
marker.marker.remove();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export function updateMarkers(map, markersOptions) {
|
|
109
|
+
const markersIds = markersOptions.map(getMarkerId);
|
|
110
|
+
removeMarkersByIds(map, markersIds);
|
|
111
|
+
addMarkers(map, markersOptions);
|
|
112
|
+
}
|
|
113
|
+
export function clearMarkers(map) {
|
|
114
|
+
for (const marker of map.markers) {
|
|
115
|
+
marker.marker.remove();
|
|
37
116
|
}
|
|
117
|
+
map.markers = [];
|
|
38
118
|
}
|
|
39
|
-
export function
|
|
119
|
+
export function addStyleMarkers(map) {
|
|
40
120
|
const style = map.getStyle();
|
|
41
121
|
const markers = get(style, "metadata.mapka.markers", []);
|
|
42
|
-
|
|
122
|
+
addMarkers(map, markers);
|
|
43
123
|
}
|
|
44
|
-
export function
|
|
124
|
+
export function addStyleDiffMarkers(map, next) {
|
|
45
125
|
const markers = get(next, "metadata.mapka.markers", []);
|
|
46
|
-
|
|
126
|
+
addMarkers(map, markers);
|
|
47
127
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Popup } from "maplibre-gl";
|
|
2
|
+
import type { MapkaPopupOptions } from "../types/marker.js";
|
|
3
|
+
import type { MapkaMap } from "../map.js";
|
|
4
|
+
export declare function getPopupId(popup: {
|
|
5
|
+
id?: string;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function getOnClose(map: MapkaMap, id: string): () => void;
|
|
8
|
+
export declare function enforceMaxPopups(map: MapkaMap): void;
|
|
9
|
+
export declare function openPopup(map: MapkaMap, options: MapkaPopupOptions, id: string): string;
|
|
10
|
+
export declare function updatePopupBaseOptions(popup: Popup, options: MapkaPopupOptions, newOptions: Omit<MapkaPopupOptions, "content">): Popup;
|
|
11
|
+
export declare function updatePopup(map: MapkaMap, { content, ...newOptions }: MapkaPopupOptions, id: string): void;
|
|
12
|
+
export declare function closeOnMapClickPopups(map: MapkaMap): void;
|
|
13
|
+
export declare function closePopupsById(map: MapkaMap, id: string): void;
|
|
14
|
+
//# sourceMappingURL=popup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/modules/popup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAEhD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,cAEnD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,QAM7C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,UAyD9E;AAID,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,SAY/C;AAED,wBAAgB,WAAW,CACzB,GAAG,EAAE,QAAQ,EACb,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,EAAE,iBAAiB,EAC7C,EAAE,EAAE,MAAM,QA6BX;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,QAQlD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAMxD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// biome-ignore lint/correctness/noUnusedImports: later fix
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
import { Popup } from "maplibre-gl";
|
|
4
|
+
import { PopupContent } from "../components/PopupContent.js";
|
|
5
|
+
import { render } from "preact";
|
|
6
|
+
import { remove } from "es-toolkit/array";
|
|
7
|
+
import { isEqual } from "es-toolkit";
|
|
8
|
+
export function getPopupId(popup) {
|
|
9
|
+
return popup.id ?? `popup-${crypto.randomUUID()}`;
|
|
10
|
+
}
|
|
11
|
+
export function getOnClose(map, id) {
|
|
12
|
+
return () => map.closePopup(id);
|
|
13
|
+
}
|
|
14
|
+
export function enforceMaxPopups(map) {
|
|
15
|
+
if (map.popups.length > map.maxPopups) {
|
|
16
|
+
const popupToRemove = map.popups.shift();
|
|
17
|
+
popupToRemove?.popup.remove();
|
|
18
|
+
popupToRemove?.container.remove();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function openPopup(map, options, id) {
|
|
22
|
+
const { lngLat, content, closeButton, ...popupOptions } = options;
|
|
23
|
+
if (content instanceof HTMLElement) {
|
|
24
|
+
const popup = new Popup({
|
|
25
|
+
...popupOptions,
|
|
26
|
+
closeButton: false,
|
|
27
|
+
closeOnClick: false,
|
|
28
|
+
})
|
|
29
|
+
.setLngLat(lngLat)
|
|
30
|
+
.setDOMContent(content)
|
|
31
|
+
.addTo(map);
|
|
32
|
+
map.popups.push({
|
|
33
|
+
container: content,
|
|
34
|
+
id,
|
|
35
|
+
options,
|
|
36
|
+
popup,
|
|
37
|
+
});
|
|
38
|
+
enforceMaxPopups(map);
|
|
39
|
+
return id;
|
|
40
|
+
}
|
|
41
|
+
else if (typeof content === "object") {
|
|
42
|
+
const onClose = getOnClose(map, id);
|
|
43
|
+
const container = document.createElement("div");
|
|
44
|
+
container.classList.add("mapka-popup-container");
|
|
45
|
+
render(h(PopupContent, { ...content, closeButton: closeButton, onClose: onClose }), container);
|
|
46
|
+
const popup = new Popup({
|
|
47
|
+
...popupOptions,
|
|
48
|
+
closeButton: false,
|
|
49
|
+
closeOnClick: false,
|
|
50
|
+
})
|
|
51
|
+
.setLngLat(lngLat)
|
|
52
|
+
.setDOMContent(container)
|
|
53
|
+
.addTo(map);
|
|
54
|
+
map.popups.push({
|
|
55
|
+
container,
|
|
56
|
+
id,
|
|
57
|
+
options,
|
|
58
|
+
popup,
|
|
59
|
+
});
|
|
60
|
+
enforceMaxPopups(map);
|
|
61
|
+
return id;
|
|
62
|
+
}
|
|
63
|
+
else if (typeof content === "function") {
|
|
64
|
+
const newContent = content(id);
|
|
65
|
+
return openPopup(map, {
|
|
66
|
+
...options,
|
|
67
|
+
content: newContent,
|
|
68
|
+
}, id);
|
|
69
|
+
}
|
|
70
|
+
throw new Error("Invalid popup content");
|
|
71
|
+
}
|
|
72
|
+
const DEFAULT_POPUP_MAX_WIDTH = "240px";
|
|
73
|
+
export function updatePopupBaseOptions(popup, options, newOptions) {
|
|
74
|
+
if (!isEqual(options.maxWidth, newOptions.maxWidth)) {
|
|
75
|
+
popup.setMaxWidth(newOptions.maxWidth ?? DEFAULT_POPUP_MAX_WIDTH);
|
|
76
|
+
}
|
|
77
|
+
if (!isEqual(options.offset, newOptions.offset)) {
|
|
78
|
+
popup.setOffset(newOptions.offset);
|
|
79
|
+
}
|
|
80
|
+
if (!isEqual(options.lngLat, newOptions.lngLat)) {
|
|
81
|
+
popup.setLngLat(newOptions.lngLat);
|
|
82
|
+
}
|
|
83
|
+
return popup;
|
|
84
|
+
}
|
|
85
|
+
export function updatePopup(map, { content, ...newOptions }, id) {
|
|
86
|
+
if (content instanceof HTMLElement) {
|
|
87
|
+
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
88
|
+
for (const { popup, options } of mapkaPopups) {
|
|
89
|
+
updatePopupBaseOptions(popup, options, newOptions);
|
|
90
|
+
popup.setDOMContent(content);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (typeof content === "object") {
|
|
94
|
+
const onClose = getOnClose(map, id);
|
|
95
|
+
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
96
|
+
for (const { popup, container, options } of mapkaPopups) {
|
|
97
|
+
const { closeButton } = options;
|
|
98
|
+
render(h(PopupContent, { ...content, closeButton: closeButton, onClose: onClose }), container);
|
|
99
|
+
updatePopupBaseOptions(popup, options, newOptions);
|
|
100
|
+
popup.setDOMContent(container);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (typeof content === "function") {
|
|
104
|
+
const newContent = content(id);
|
|
105
|
+
return updatePopup(map, {
|
|
106
|
+
...newOptions,
|
|
107
|
+
content: newContent,
|
|
108
|
+
}, id);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function closeOnMapClickPopups(map) {
|
|
112
|
+
const popupsToCloseOnMapClick = remove(map.popups, (popup) => Boolean(popup.options.closeOnClick));
|
|
113
|
+
for (const popup of popupsToCloseOnMapClick) {
|
|
114
|
+
popup.popup.remove();
|
|
115
|
+
popup.container.remove();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export function closePopupsById(map, id) {
|
|
119
|
+
const removedPopups = remove(map.popups, (popup) => popup.id === id);
|
|
120
|
+
for (const popup of removedPopups) {
|
|
121
|
+
popup.popup.remove();
|
|
122
|
+
popup.container.remove();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/types/id.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,IAAI,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
package/lib/types/id.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/types/marker.d.ts
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
count: number;
|
|
4
|
-
}
|
|
5
|
-
export interface MapkaTooltipPrice {
|
|
6
|
-
current: string;
|
|
7
|
-
original?: string;
|
|
8
|
-
suffix?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface MapkaTooltipOptions {
|
|
11
|
-
id?: string;
|
|
12
|
-
trigger?: "hover" | "click";
|
|
1
|
+
import type { MarkerOptions, PopupOptions } from "maplibre-gl";
|
|
2
|
+
export interface MapkaPopupContent {
|
|
13
3
|
title?: string;
|
|
14
|
-
rating?: MapkaTooltipRating;
|
|
15
4
|
description?: string;
|
|
16
|
-
subtitle?: string;
|
|
17
|
-
price?: MapkaTooltipPrice;
|
|
18
5
|
imageUrls?: string[];
|
|
19
6
|
onFavorite?: (id: string) => void;
|
|
20
7
|
}
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
type CreatePopupElement = (id: string) => HTMLElement;
|
|
9
|
+
type CreatePopupContent = (id: string) => MapkaPopupContent;
|
|
10
|
+
export interface MapkaPopupOptions extends PopupOptions {
|
|
11
|
+
id?: string;
|
|
12
|
+
lngLat: [number, number];
|
|
13
|
+
trigger?: "hover" | "click" | "always";
|
|
14
|
+
content: MapkaPopupContent | HTMLElement | CreatePopupElement | CreatePopupContent;
|
|
15
|
+
}
|
|
16
|
+
export type MapkaMarkerPopupOptions = Omit<MapkaPopupOptions, "lngLat">;
|
|
17
|
+
export interface MapkaMarkerOptions extends MarkerOptions {
|
|
18
|
+
id?: string;
|
|
19
|
+
lngLat: [number, number];
|
|
23
20
|
color?: string;
|
|
24
21
|
icon?: string;
|
|
25
|
-
|
|
22
|
+
popup?: Omit<MapkaPopupOptions, "lngLat">;
|
|
26
23
|
}
|
|
24
|
+
export {};
|
|
27
25
|
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/types/marker.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/types/marker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,KAAK,kBAAkB,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,WAAW,CAAC;AACtD,KAAK,kBAAkB,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,iBAAiB,CAAC;AAE5D,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,iBAAiB,GAAG,WAAW,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;CACpF;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAExE,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;CAC3C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapka/maplibre-gl-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Mapka JS SDK",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"es-toolkit": "^1.43.0",
|
|
27
|
-
"maplibre-gl": "^5.
|
|
27
|
+
"maplibre-gl": "^5.15.0",
|
|
28
28
|
"preact": "^10.28.0"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"!**/__tests__/",
|
|
35
35
|
"!lib/buildInfo.json"
|
|
36
36
|
],
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "0cab43f10e18aa9c0b063edc1612272477f09e80"
|
|
38
38
|
}
|