@mapka/maplibre-gl-sdk 0.16.1 → 0.16.3
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 +10 -5
- package/lib/.buildInfo.json +1 -1
- package/lib/components/ImageCarousel.d.ts +7 -0
- package/lib/components/ImageCarousel.d.ts.map +1 -0
- package/lib/components/ImageCarousel.js +22 -0
- package/lib/components/PopupContent.d.ts +5 -1
- package/lib/components/PopupContent.d.ts.map +1 -1
- package/lib/components/PopupContent.js +12 -40
- package/lib/components/PopupDataRows.d.ts +7 -0
- package/lib/components/PopupDataRows.d.ts.map +1 -0
- package/lib/components/PopupDataRows.js +22 -0
- package/lib/components/PopupList.d.ts +10 -0
- package/lib/components/PopupList.d.ts.map +1 -0
- package/lib/components/PopupList.js +8 -0
- package/lib/components/PopupListItem.d.ts +13 -0
- package/lib/components/PopupListItem.d.ts.map +1 -0
- package/lib/components/PopupListItem.js +11 -0
- package/lib/components/icons/ChevronLeftIcon.d.ts +2 -0
- package/lib/components/icons/ChevronLeftIcon.d.ts.map +1 -0
- package/lib/components/icons/ChevronLeftIcon.js +4 -0
- package/lib/components/icons/ChevronRightIcon.d.ts +2 -0
- package/lib/components/icons/ChevronRightIcon.d.ts.map +1 -0
- package/lib/components/icons/ChevronRightIcon.js +4 -0
- package/lib/components/icons/CircleIcon.d.ts.map +1 -0
- package/lib/components/icons/CloseIcon.d.ts +2 -0
- package/lib/components/icons/CloseIcon.d.ts.map +1 -0
- package/lib/components/icons/CloseIcon.js +4 -0
- package/lib/components/icons/DownloadIcon.d.ts.map +1 -0
- package/lib/components/icons/FreehandIcon.d.ts.map +1 -0
- package/lib/components/icons/HeartIcon.d.ts +4 -0
- package/lib/components/icons/HeartIcon.d.ts.map +1 -0
- package/lib/components/icons/HeartIcon.js +4 -0
- package/lib/components/icons/LineIcon.d.ts.map +1 -0
- package/lib/components/icons/PencilIcon.d.ts.map +1 -0
- package/lib/components/icons/PolygonIcon.d.ts.map +1 -0
- package/lib/components/icons/ProgressDownIcon.d.ts +2 -0
- package/lib/components/icons/ProgressDownIcon.d.ts.map +1 -0
- package/lib/components/icons/RectangleIcon.d.ts.map +1 -0
- package/lib/components/icons/SelectIcon.d.ts.map +1 -0
- package/lib/components/icons/TrashIcon.d.ts.map +1 -0
- package/lib/controls/MapkaDrawControl.js +7 -7
- package/lib/controls/MapkaExportControl.js +2 -2
- package/lib/map.d.ts +8 -7
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +15 -9
- package/lib/modules/layerPopup.d.ts +2 -1
- package/lib/modules/layerPopup.d.ts.map +1 -1
- package/lib/modules/layerPopup.js +22 -15
- package/lib/modules/markers.d.ts +5 -0
- package/lib/modules/markers.d.ts.map +1 -1
- package/lib/modules/markers.js +21 -16
- package/lib/modules/popup.d.ts +3 -10
- package/lib/modules/popup.d.ts.map +1 -1
- package/lib/modules/popup.js +116 -100
- package/lib/modules/popupGroups.d.ts +14 -0
- package/lib/modules/popupGroups.d.ts.map +1 -0
- package/lib/modules/popupGroups.js +130 -0
- package/lib/styles.css +1 -1
- package/lib/types/popup.d.ts +10 -1
- package/lib/types/popup.d.ts.map +1 -1
- package/package.json +26 -7
- package/src/components/ImageCarousel.css +73 -0
- package/src/components/ImageCarousel.tsx +76 -0
- package/src/components/PopupContent.css +52 -189
- package/src/components/PopupContent.tsx +26 -195
- package/src/components/PopupDataRows.css +41 -0
- package/src/components/PopupDataRows.tsx +39 -0
- package/src/components/PopupList.css +24 -0
- package/src/components/PopupList.tsx +27 -0
- package/src/components/PopupListItem.css +61 -0
- package/src/components/PopupListItem.tsx +40 -0
- package/src/components/icons/ChevronLeftIcon.tsx +20 -0
- package/src/components/icons/ChevronRightIcon.tsx +20 -0
- package/src/components/icons/CloseIcon.tsx +13 -0
- package/src/components/icons/HeartIcon.tsx +18 -0
- package/src/components/{ProgressDownIcon.tsx → icons/ProgressDownIcon.tsx} +0 -3
- package/src/controls/MapkaDrawControl.tsx +7 -7
- package/src/controls/MapkaExportControl.tsx +2 -2
- package/src/map.ts +22 -20
- package/src/modules/layerPopup.ts +32 -21
- package/src/modules/markers.ts +26 -16
- package/src/modules/popup.tsx +129 -112
- package/src/modules/popupGroups.ts +190 -0
- package/src/styles.css +4 -0
- package/src/types/popup.ts +12 -1
- package/lib/components/CircleIcon.d.ts.map +0 -1
- package/lib/components/DownloadIcon.d.ts.map +0 -1
- package/lib/components/FreehandIcon.d.ts.map +0 -1
- package/lib/components/LineIcon.d.ts.map +0 -1
- package/lib/components/PencilIcon.d.ts.map +0 -1
- package/lib/components/PolygonIcon.d.ts.map +0 -1
- package/lib/components/ProgressDownIcon.d.ts +0 -4
- package/lib/components/ProgressDownIcon.d.ts.map +0 -1
- package/lib/components/RectangleIcon.d.ts.map +0 -1
- package/lib/components/SelectIcon.d.ts.map +0 -1
- package/lib/components/TrashIcon.d.ts.map +0 -1
- /package/lib/components/{CircleIcon.d.ts → icons/CircleIcon.d.ts} +0 -0
- /package/lib/components/{CircleIcon.js → icons/CircleIcon.js} +0 -0
- /package/lib/components/{DownloadIcon.d.ts → icons/DownloadIcon.d.ts} +0 -0
- /package/lib/components/{DownloadIcon.js → icons/DownloadIcon.js} +0 -0
- /package/lib/components/{FreehandIcon.d.ts → icons/FreehandIcon.d.ts} +0 -0
- /package/lib/components/{FreehandIcon.js → icons/FreehandIcon.js} +0 -0
- /package/lib/components/{LineIcon.d.ts → icons/LineIcon.d.ts} +0 -0
- /package/lib/components/{LineIcon.js → icons/LineIcon.js} +0 -0
- /package/lib/components/{PencilIcon.d.ts → icons/PencilIcon.d.ts} +0 -0
- /package/lib/components/{PencilIcon.js → icons/PencilIcon.js} +0 -0
- /package/lib/components/{PolygonIcon.d.ts → icons/PolygonIcon.d.ts} +0 -0
- /package/lib/components/{PolygonIcon.js → icons/PolygonIcon.js} +0 -0
- /package/lib/components/{ProgressDownIcon.js → icons/ProgressDownIcon.js} +0 -0
- /package/lib/components/{RectangleIcon.d.ts → icons/RectangleIcon.d.ts} +0 -0
- /package/lib/components/{RectangleIcon.js → icons/RectangleIcon.js} +0 -0
- /package/lib/components/{SelectIcon.d.ts → icons/SelectIcon.d.ts} +0 -0
- /package/lib/components/{SelectIcon.js → icons/SelectIcon.js} +0 -0
- /package/lib/components/{TrashIcon.d.ts → icons/TrashIcon.d.ts} +0 -0
- /package/lib/components/{TrashIcon.js → icons/TrashIcon.js} +0 -0
- /package/src/components/{CircleIcon.tsx → icons/CircleIcon.tsx} +0 -0
- /package/src/components/{DownloadIcon.tsx → icons/DownloadIcon.tsx} +0 -0
- /package/src/components/{FreehandIcon.tsx → icons/FreehandIcon.tsx} +0 -0
- /package/src/components/{LineIcon.tsx → icons/LineIcon.tsx} +0 -0
- /package/src/components/{PencilIcon.tsx → icons/PencilIcon.tsx} +0 -0
- /package/src/components/{PolygonIcon.tsx → icons/PolygonIcon.tsx} +0 -0
- /package/src/components/{RectangleIcon.tsx → icons/RectangleIcon.tsx} +0 -0
- /package/src/components/{SelectIcon.tsx → icons/SelectIcon.tsx} +0 -0
- /package/src/components/{TrashIcon.tsx → icons/TrashIcon.tsx} +0 -0
package/lib/modules/markers.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Marker } from "maplibre-gl";
|
|
2
2
|
import { get } from "es-toolkit/compat";
|
|
3
|
-
import { getPopupId } from "./popup.js";
|
|
4
3
|
import { remove } from "es-toolkit";
|
|
5
4
|
/**
|
|
6
5
|
* Default marker offset
|
|
@@ -19,45 +18,51 @@ const DEFAULT_MARKET_OFFSET = {
|
|
|
19
18
|
export function getMarkerId(marker) {
|
|
20
19
|
return marker.id ?? `marker-${crypto.randomUUID()}`;
|
|
21
20
|
}
|
|
22
|
-
|
|
21
|
+
export function getMarkerPopupId(marker, popup) {
|
|
22
|
+
return popup.id ?? marker.id ?? `marker-popup-${crypto.randomUUID()}`;
|
|
23
|
+
}
|
|
24
|
+
const markerPopupOptions = (id, marker, popupOptions) => {
|
|
23
25
|
const latLng = marker.getLngLat().toArray();
|
|
24
26
|
if ("offset" in popupOptions) {
|
|
25
27
|
return {
|
|
26
28
|
...popupOptions,
|
|
29
|
+
id,
|
|
27
30
|
lngLat: latLng,
|
|
28
31
|
};
|
|
29
32
|
}
|
|
30
33
|
else {
|
|
31
34
|
return {
|
|
32
35
|
...popupOptions,
|
|
36
|
+
id,
|
|
33
37
|
lngLat: latLng,
|
|
34
38
|
offset: DEFAULT_MARKET_OFFSET,
|
|
35
39
|
};
|
|
36
40
|
}
|
|
37
41
|
};
|
|
38
42
|
function setupMarkerPopupListeners(map, marker, popup, options) {
|
|
39
|
-
const popupId = getPopupId(popup);
|
|
40
43
|
const markerElement = marker.getElement();
|
|
44
|
+
const popupId = getMarkerPopupId(options, popup);
|
|
45
|
+
const popupOptions = markerPopupOptions(popupId, marker, popup);
|
|
41
46
|
if (options.draggable) {
|
|
42
47
|
marker.on("dragend", () => {
|
|
43
|
-
if (map.popups.find((p) => p.
|
|
44
|
-
map.updatePopup(
|
|
48
|
+
if (map.popups.find((p) => p.ids.includes(popupId))) {
|
|
49
|
+
map.updatePopup(popupOptions);
|
|
45
50
|
}
|
|
46
51
|
});
|
|
47
52
|
marker.on("drag", () => {
|
|
48
|
-
if (map.popups.find((p) => p.
|
|
49
|
-
map.updatePopup(
|
|
53
|
+
if (map.popups.find((p) => p.ids.includes(popupId))) {
|
|
54
|
+
map.updatePopup(popupOptions);
|
|
50
55
|
}
|
|
51
56
|
});
|
|
52
57
|
}
|
|
53
58
|
if (popup.trigger === "always") {
|
|
54
|
-
if (!map.popups.find((p) => p.
|
|
55
|
-
map.openPopup(
|
|
59
|
+
if (!map.popups.find((p) => p.ids.includes(popupId))) {
|
|
60
|
+
map.openPopup(popupOptions);
|
|
56
61
|
}
|
|
57
62
|
markerElement.addEventListener("click", (e) => {
|
|
58
63
|
e.stopPropagation();
|
|
59
|
-
if (!map.popups.find((p) => p.
|
|
60
|
-
map.openPopup(
|
|
64
|
+
if (!map.popups.find((p) => p.ids.includes(popupId))) {
|
|
65
|
+
map.openPopup(popupOptions);
|
|
61
66
|
}
|
|
62
67
|
});
|
|
63
68
|
}
|
|
@@ -65,21 +70,21 @@ function setupMarkerPopupListeners(map, marker, popup, options) {
|
|
|
65
70
|
markerElement.style.cursor = "pointer";
|
|
66
71
|
markerElement.addEventListener("click", (e) => {
|
|
67
72
|
e.stopPropagation();
|
|
68
|
-
if (!map.popups.find((p) => p.
|
|
69
|
-
map.openPopup(
|
|
73
|
+
if (!map.popups.find((p) => p.ids.includes(popupId))) {
|
|
74
|
+
map.openPopup(popupOptions);
|
|
70
75
|
}
|
|
71
76
|
});
|
|
72
77
|
}
|
|
73
78
|
else if (popup.trigger === "hover") {
|
|
74
79
|
markerElement.addEventListener("mouseenter", (e) => {
|
|
75
80
|
e.stopPropagation();
|
|
76
|
-
if (!map.popups.find((p) => p.
|
|
77
|
-
map.openPopup(
|
|
81
|
+
if (!map.popups.find((p) => p.ids.includes(popupId))) {
|
|
82
|
+
map.openPopup(popupOptions);
|
|
78
83
|
}
|
|
79
84
|
});
|
|
80
85
|
markerElement.addEventListener("mouseleave", (e) => {
|
|
81
86
|
e.stopPropagation();
|
|
82
|
-
if (map.popups.find((p) => p.
|
|
87
|
+
if (map.popups.find((p) => p.ids.includes(popupId))) {
|
|
83
88
|
map.closePopup(popupId);
|
|
84
89
|
}
|
|
85
90
|
});
|
package/lib/modules/popup.d.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
import { Popup } from "maplibre-gl";
|
|
2
1
|
import type { MapkaPopupOptions } from "../types/popup.js";
|
|
3
2
|
import type { MapkaMap } from "../map.js";
|
|
4
3
|
export declare function getPopupId(popup: {
|
|
5
4
|
id?: string;
|
|
6
5
|
}): string;
|
|
7
|
-
export declare function getOnClose(map: MapkaMap, id: string): () => void;
|
|
8
6
|
export declare function enforceMaxPopups(map: MapkaMap): void;
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function updatePopupBaseOptions(popup: Popup, options: MapkaPopupOptions, newOptions: Omit<MapkaPopupOptions, "content">): Popup;
|
|
11
|
-
export declare function updatePopup(map: MapkaMap, { content, ...newOptions }: MapkaPopupOptions): void;
|
|
12
|
-
/**
|
|
13
|
-
* Close all popups that have closeOnClick set to true or undefined
|
|
14
|
-
*/
|
|
7
|
+
export declare function reconciliatePopups(map: MapkaMap, options?: MapkaPopupOptions[]): string[];
|
|
15
8
|
export declare function closeOnMapClickPopups(map: MapkaMap): void;
|
|
16
|
-
export declare function
|
|
17
|
-
export declare function
|
|
9
|
+
export declare function closePopups(map: MapkaMap): void;
|
|
10
|
+
export declare function closePopupsByIds(map: MapkaMap, ids: string[]): void;
|
|
18
11
|
//# sourceMappingURL=popup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/modules/popup.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/modules/popup.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAA6B,MAAM,mBAAmB,CAAC;AACtF,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,WAAW,CAAC;AAEzD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAEhD;AAmFD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,QAW7C;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,GAAE,iBAAiB,EAAO,YAelF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,QAclD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,QASxC;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QA+B5D"}
|
package/lib/modules/popup.js
CHANGED
|
@@ -1,146 +1,162 @@
|
|
|
1
1
|
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
2
|
import { Popup } from "maplibre-gl";
|
|
3
3
|
import { PopupContent } from "../components/PopupContent.js";
|
|
4
|
+
import { PopupList } from "../components/PopupList.js";
|
|
4
5
|
import { render } from "preact";
|
|
5
6
|
import { remove } from "es-toolkit/array";
|
|
6
|
-
import {
|
|
7
|
+
import { isPlainObject, without } from "es-toolkit";
|
|
8
|
+
import { computePopupGroups } from "./popupGroups.js";
|
|
7
9
|
export function getPopupId(popup) {
|
|
8
10
|
return popup.id ?? `popup-${crypto.randomUUID()}`;
|
|
9
11
|
}
|
|
10
|
-
|
|
11
|
-
return () => map
|
|
12
|
+
function getOnClose(map, id) {
|
|
13
|
+
return () => closePopupsByIds(map, [id]);
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
function hasObjectContent(options) {
|
|
16
|
+
return options.some((opt) => isPlainObject(opt.content));
|
|
17
|
+
}
|
|
18
|
+
function resolveContentCreators(options) {
|
|
19
|
+
return options.map((opt) => {
|
|
20
|
+
const id = getPopupId(opt);
|
|
21
|
+
if (typeof opt.content === "function") {
|
|
22
|
+
return {
|
|
23
|
+
...opt,
|
|
24
|
+
id,
|
|
25
|
+
content: opt.content(id),
|
|
26
|
+
};
|
|
19
27
|
}
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
else {
|
|
29
|
+
return {
|
|
30
|
+
...opt,
|
|
31
|
+
id,
|
|
32
|
+
content: opt.content,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
22
36
|
}
|
|
23
|
-
|
|
24
|
-
const { lngLat, content, closeButton,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.addTo(map);
|
|
34
|
-
map.popups.push({
|
|
35
|
-
container: content,
|
|
36
|
-
id,
|
|
37
|
-
options,
|
|
38
|
-
popup,
|
|
39
|
-
});
|
|
40
|
-
enforceMaxPopups(map);
|
|
41
|
-
return id;
|
|
42
|
-
}
|
|
43
|
-
else if (typeof content === "object") {
|
|
44
|
-
const onClose = getOnClose(map, id);
|
|
45
|
-
const container = document.createElement("div");
|
|
46
|
-
container.classList.add("mapka-popup-container");
|
|
47
|
-
render(_jsx(PopupContent, { ...content, closeButton: closeButton, onClose: onClose }), container);
|
|
48
|
-
const popup = new Popup({
|
|
49
|
-
...popupOptions,
|
|
37
|
+
function createNewPopup(map, options) {
|
|
38
|
+
const [{ lngLat, id, content, closeButton, ...opts }] = options;
|
|
39
|
+
const ids = options.map(getPopupId);
|
|
40
|
+
const container = document.createElement("div");
|
|
41
|
+
container.classList.add("mapka-popup-container");
|
|
42
|
+
let popup;
|
|
43
|
+
if (options.length > 1) {
|
|
44
|
+
render(_jsx(PopupList, { items: options }), container);
|
|
45
|
+
popup = new Popup({
|
|
46
|
+
...opts,
|
|
50
47
|
closeButton: false,
|
|
51
|
-
closeOnClick:
|
|
48
|
+
closeOnClick: true,
|
|
52
49
|
})
|
|
53
50
|
.setLngLat(lngLat)
|
|
54
51
|
.setDOMContent(container)
|
|
55
52
|
.addTo(map);
|
|
56
|
-
map.popups.push({
|
|
57
|
-
container,
|
|
58
|
-
id,
|
|
59
|
-
options,
|
|
60
|
-
popup,
|
|
61
|
-
});
|
|
62
|
-
enforceMaxPopups(map);
|
|
63
|
-
return id;
|
|
64
53
|
}
|
|
65
|
-
else
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
else {
|
|
55
|
+
if (content instanceof HTMLElement) {
|
|
56
|
+
popup = new Popup({
|
|
57
|
+
...opts,
|
|
58
|
+
closeButton: false,
|
|
59
|
+
})
|
|
60
|
+
.setLngLat(lngLat)
|
|
61
|
+
.setDOMContent(content)
|
|
62
|
+
.addTo(map);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
popup = new Popup({
|
|
66
|
+
...opts,
|
|
67
|
+
closeButton: false,
|
|
68
|
+
})
|
|
69
|
+
.setLngLat(lngLat)
|
|
70
|
+
.setDOMContent(container)
|
|
71
|
+
.addTo(map);
|
|
72
|
+
render(_jsx(PopupContent, { ...content, onClose: getOnClose(map, id) }), container);
|
|
73
|
+
}
|
|
71
74
|
}
|
|
72
|
-
|
|
75
|
+
if (!popup)
|
|
76
|
+
return;
|
|
77
|
+
map.popups.push({
|
|
78
|
+
container,
|
|
79
|
+
ids,
|
|
80
|
+
options,
|
|
81
|
+
popup,
|
|
82
|
+
});
|
|
83
|
+
return ids;
|
|
73
84
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
export function enforceMaxPopups(map) {
|
|
86
|
+
if (map.popups.length > map.maxPopups) {
|
|
87
|
+
const popupToRemove = map.popups.shift();
|
|
88
|
+
if (popupToRemove) {
|
|
89
|
+
popupToRemove.popup.remove();
|
|
90
|
+
if (hasObjectContent(popupToRemove.options)) {
|
|
91
|
+
render(null, popupToRemove.container);
|
|
92
|
+
}
|
|
93
|
+
popupToRemove.container.remove();
|
|
94
|
+
}
|
|
84
95
|
}
|
|
85
|
-
return popup;
|
|
86
96
|
}
|
|
87
|
-
export function
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
popup.setDOMContent(content);
|
|
97
|
+
export function reconciliatePopups(map, options = []) {
|
|
98
|
+
const resolved = resolveContentCreators(options);
|
|
99
|
+
const actions = computePopupGroups(map, resolved);
|
|
100
|
+
for (const action of actions) {
|
|
101
|
+
if (action.type === "close") {
|
|
102
|
+
closePopupsByIds(map, action.ids);
|
|
94
103
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const onClose = getOnClose(map, id);
|
|
98
|
-
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
99
|
-
for (const { popup, container, options } of mapkaPopups) {
|
|
100
|
-
const { closeButton } = options;
|
|
101
|
-
render(_jsx(PopupContent, { ...content, closeButton: closeButton, onClose: onClose }), container);
|
|
102
|
-
updatePopupBaseOptions(popup, options, newOptions);
|
|
103
|
-
popup.setDOMContent(container);
|
|
104
|
+
else if (action.type === "create") {
|
|
105
|
+
createNewPopup(map, action.options);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return updatePopup(map, {
|
|
109
|
-
...newOptions,
|
|
110
|
-
content: newContent,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
108
|
+
enforceMaxPopups(map);
|
|
109
|
+
return resolved.map((opt) => opt.id);
|
|
113
110
|
}
|
|
114
|
-
/**
|
|
115
|
-
* Close all popups that have closeOnClick set to true or undefined
|
|
116
|
-
*/
|
|
117
111
|
export function closeOnMapClickPopups(map) {
|
|
118
|
-
const popupsToCloseOnMapClick = remove(map.popups, (popup) =>
|
|
112
|
+
const popupsToCloseOnMapClick = remove(map.popups, (popup) => {
|
|
113
|
+
const [first] = popup.options;
|
|
114
|
+
return (popup.ids.length > 1 || first?.closeOnClick === true || first?.closeOnClick === undefined);
|
|
115
|
+
});
|
|
119
116
|
for (const popup of popupsToCloseOnMapClick) {
|
|
120
117
|
popup.popup.remove();
|
|
121
|
-
if (
|
|
118
|
+
if (hasObjectContent(popup.options)) {
|
|
122
119
|
render(null, popup.container);
|
|
123
120
|
}
|
|
124
121
|
popup.container.remove();
|
|
125
122
|
}
|
|
126
123
|
}
|
|
127
|
-
export function
|
|
128
|
-
const
|
|
129
|
-
for (const popup of removedPopups) {
|
|
124
|
+
export function closePopups(map) {
|
|
125
|
+
for (const popup of map.popups) {
|
|
130
126
|
popup.popup.remove();
|
|
131
|
-
if (
|
|
127
|
+
if (hasObjectContent(popup.options)) {
|
|
132
128
|
render(null, popup.container);
|
|
133
129
|
}
|
|
134
130
|
popup.container.remove();
|
|
135
131
|
}
|
|
132
|
+
map.popups = [];
|
|
136
133
|
}
|
|
137
|
-
export function
|
|
134
|
+
export function closePopupsByIds(map, ids) {
|
|
135
|
+
const toClose = [];
|
|
136
|
+
const toReRender = [];
|
|
138
137
|
for (const popup of map.popups) {
|
|
138
|
+
const itemIndex = popup.ids.findIndex((id) => ids.includes(id));
|
|
139
|
+
if (itemIndex < 0)
|
|
140
|
+
continue;
|
|
141
|
+
if (popup.ids.length === 1) {
|
|
142
|
+
toClose.push(popup);
|
|
143
|
+
}
|
|
144
|
+
else if (popup.ids.length > 1) {
|
|
145
|
+
popup.ids.splice(itemIndex, 1);
|
|
146
|
+
popup.options.splice(itemIndex, 1);
|
|
147
|
+
toClose.push(popup);
|
|
148
|
+
toReRender.push(popup);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const popup of toClose) {
|
|
139
152
|
popup.popup.remove();
|
|
140
|
-
if (
|
|
153
|
+
if (hasObjectContent(popup.options)) {
|
|
141
154
|
render(null, popup.container);
|
|
142
155
|
}
|
|
143
156
|
popup.container.remove();
|
|
157
|
+
map.popups = without(map.popups, popup);
|
|
158
|
+
}
|
|
159
|
+
for (const popup of toReRender) {
|
|
160
|
+
createNewPopup(map, popup.options);
|
|
144
161
|
}
|
|
145
|
-
map.popups = [];
|
|
146
162
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { MapkaMap, MapMapkaPopup } from "../map.js";
|
|
2
|
+
import type { MapkaPopupOptionsResolved } from "../types/popup.js";
|
|
3
|
+
export type ClosePopupAction = {
|
|
4
|
+
type: "close";
|
|
5
|
+
ids: string[];
|
|
6
|
+
};
|
|
7
|
+
export type CreatePopupAction = {
|
|
8
|
+
type: "create";
|
|
9
|
+
options: MapkaPopupOptionsResolved[];
|
|
10
|
+
};
|
|
11
|
+
export type PopupGroupAction = ClosePopupAction | CreatePopupAction;
|
|
12
|
+
export declare function actionsByChanges(popups: MapMapkaPopup[], newOptions: MapkaPopupOptionsResolved[]): PopupGroupAction[];
|
|
13
|
+
export declare function computePopupGroups(map: MapkaMap, newOptions: MapkaPopupOptionsResolved[]): PopupGroupAction[];
|
|
14
|
+
//# sourceMappingURL=popupGroups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popupGroups.d.ts","sourceRoot":"","sources":["../../src/modules/popupGroups.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,yBAAyB,EAAE,CAAA;CAAE,CAAC;AAEzF,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAkJpE,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EAAE,EACvB,UAAU,EAAE,yBAAyB,EAAE,GACtC,gBAAgB,EAAE,CAmBpB;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,QAAQ,EACb,UAAU,EAAE,yBAAyB,EAAE,GACtC,gBAAgB,EAAE,CASpB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import Supercluster from "supercluster";
|
|
2
|
+
const WORLD_BOUNDS = [-180, -90, 180, 90];
|
|
3
|
+
function clustersByLocation(previous, newOptions, zoom) {
|
|
4
|
+
const all = [...previous, ...newOptions];
|
|
5
|
+
const features = all.map(({ lngLat }, index) => ({
|
|
6
|
+
type: "Feature",
|
|
7
|
+
properties: { index },
|
|
8
|
+
geometry: {
|
|
9
|
+
type: "Point",
|
|
10
|
+
coordinates: lngLat,
|
|
11
|
+
},
|
|
12
|
+
}));
|
|
13
|
+
const sc = new Supercluster({
|
|
14
|
+
radius: 20,
|
|
15
|
+
extent: 512,
|
|
16
|
+
});
|
|
17
|
+
sc.load(features);
|
|
18
|
+
const results = sc.getClusters(WORLD_BOUNDS, zoom);
|
|
19
|
+
const clusters = [];
|
|
20
|
+
for (const { properties, geometry } of results) {
|
|
21
|
+
if ("cluster" in properties) {
|
|
22
|
+
const leaves = sc.getLeaves(properties.cluster_id, Infinity);
|
|
23
|
+
clusters.push({
|
|
24
|
+
options: leaves.map((point) => all[point.properties.index]),
|
|
25
|
+
lngLat: geometry.coordinates,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const opt = all[properties.index];
|
|
30
|
+
clusters.push({
|
|
31
|
+
options: [opt],
|
|
32
|
+
lngLat: opt.lngLat,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return clusters;
|
|
37
|
+
}
|
|
38
|
+
function clustersFromPopups(notUpdated, popups) {
|
|
39
|
+
const clusters = [];
|
|
40
|
+
for (const popup of popups) {
|
|
41
|
+
clusters.push({
|
|
42
|
+
options: popup.options.filter((opt) => notUpdated.includes(opt)),
|
|
43
|
+
lngLat: popup.popup.getLngLat().toArray(),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return clusters.filter((cluster) => cluster.options.length > 0);
|
|
47
|
+
}
|
|
48
|
+
function clusterKey(cluster) {
|
|
49
|
+
return cluster.options
|
|
50
|
+
.map((o) => o.id)
|
|
51
|
+
.sort()
|
|
52
|
+
.join("-");
|
|
53
|
+
}
|
|
54
|
+
function actionsByClustersChanges(prev, next) {
|
|
55
|
+
const prevByKey = new Map(prev.map((c) => [clusterKey(c), c]));
|
|
56
|
+
const nextByKey = new Map(next.map((c) => [clusterKey(c), c]));
|
|
57
|
+
const close = [];
|
|
58
|
+
const create = [];
|
|
59
|
+
for (const [key, cluster] of prevByKey) {
|
|
60
|
+
if (!nextByKey.has(key)) {
|
|
61
|
+
close.push({
|
|
62
|
+
type: "close",
|
|
63
|
+
ids: cluster.options.map((o) => o.id),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const [key, cluster] of nextByKey) {
|
|
68
|
+
if (!prevByKey.has(key)) {
|
|
69
|
+
create.push({
|
|
70
|
+
type: "create",
|
|
71
|
+
options: cluster.options,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { close, create };
|
|
76
|
+
}
|
|
77
|
+
function actionsByProximity(popups, newOptions, zoom) {
|
|
78
|
+
const updated = [];
|
|
79
|
+
const nonUpdated = [];
|
|
80
|
+
for (const popup of popups) {
|
|
81
|
+
for (const opt of popup.options) {
|
|
82
|
+
if (newOptions.find((o) => o.id === opt.id)) {
|
|
83
|
+
updated.push(opt);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
nonUpdated.push(opt);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const prevClusters = clustersFromPopups(nonUpdated, popups);
|
|
91
|
+
const nextClusters = clustersByLocation(nonUpdated, newOptions, zoom);
|
|
92
|
+
const { close, create } = actionsByClustersChanges(prevClusters, nextClusters);
|
|
93
|
+
const updatedIds = updated.map((opt) => opt.id);
|
|
94
|
+
const closeIds = close.flatMap((opt) => opt.ids);
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
type: "close",
|
|
98
|
+
ids: updatedIds.concat(closeIds),
|
|
99
|
+
},
|
|
100
|
+
...create,
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
export function actionsByChanges(popups, newOptions) {
|
|
104
|
+
const updated = [];
|
|
105
|
+
for (const popup of popups) {
|
|
106
|
+
if (newOptions.find((o) => popup.ids.includes(o.id))) {
|
|
107
|
+
updated.push(popup);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return [
|
|
111
|
+
...updated.map((popup) => ({
|
|
112
|
+
type: "close",
|
|
113
|
+
ids: popup.ids,
|
|
114
|
+
})),
|
|
115
|
+
{
|
|
116
|
+
type: "create",
|
|
117
|
+
options: newOptions,
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
export function computePopupGroups(map, newOptions) {
|
|
122
|
+
const popups = map.getPopups();
|
|
123
|
+
const zoom = map.getZoom();
|
|
124
|
+
if (map.scrollPopups) {
|
|
125
|
+
return actionsByProximity(popups, newOptions, zoom);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return actionsByChanges(popups, newOptions);
|
|
129
|
+
}
|
|
130
|
+
}
|