@mapka/maplibre-gl-sdk 0.8.0 → 0.10.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 +120 -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 +17 -5
- package/lib/types/marker.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/components/PopupContent.css +177 -0
- package/src/components/PopupContent.tsx +227 -0
- package/src/map.ts +74 -8
- package/src/modules/markers.ts +137 -44
- package/src/modules/popup.tsx +155 -0
- package/src/styles.css +177 -1
- package/src/types/id.ts +1 -0
- package/src/types/marker.ts +20 -5
- package/lib/modules/tooltip.d.ts +0 -15
- package/lib/modules/tooltip.d.ts.map +0 -1
- package/lib/modules/tooltip.js +0 -306
- package/src/modules/tooltip.ts +0 -344
package/src/modules/markers.ts
CHANGED
|
@@ -1,59 +1,152 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Marker } from "maplibre-gl";
|
|
2
2
|
import { get } from "es-toolkit/compat";
|
|
3
|
-
import
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import {
|
|
3
|
+
import { getPopupId } from "./popup.js";
|
|
4
|
+
import type { Offset, StyleSpecification } from "maplibre-gl";
|
|
5
|
+
import type { MapkaMap, MapMapkaMarker } from "../map.js";
|
|
6
|
+
import type { MapkaMarkerOptions, MapkaPopupOptions } from "../types/marker.js";
|
|
7
|
+
import { remove } from "es-toolkit";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Default marker offset
|
|
11
|
+
* @see https://github.com/maplibre/maplibre-gl-js/blob/master/src/ui/marker.ts#L457
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_MARKET_OFFSET = {
|
|
14
|
+
top: [0, 0],
|
|
15
|
+
"top-left": [0, 0],
|
|
16
|
+
"top-right": [0, 0],
|
|
17
|
+
bottom: [0, -38.1],
|
|
18
|
+
"bottom-left": [9.54594154601839, -34.14594154601839],
|
|
19
|
+
"bottom-right": [-9.54594154601839, -34.14594154601839],
|
|
20
|
+
left: [13.5, -24.6],
|
|
21
|
+
right: [-13.5, -24.6],
|
|
22
|
+
} as Offset;
|
|
9
23
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
24
|
+
export function getMarkerId(marker: { id?: string }) {
|
|
25
|
+
return marker.id ?? `marker-${crypto.randomUUID()}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const markerPopupOptions = (marker: Marker, popupOptions: Omit<MapkaPopupOptions, "lngLat">) => {
|
|
29
|
+
const latLng = marker.getLngLat().toArray();
|
|
30
|
+
|
|
31
|
+
if ("offset" in popupOptions) {
|
|
32
|
+
return {
|
|
33
|
+
...popupOptions,
|
|
34
|
+
lngLat: latLng,
|
|
35
|
+
};
|
|
36
|
+
} else {
|
|
37
|
+
return {
|
|
38
|
+
...popupOptions,
|
|
39
|
+
lngLat: latLng,
|
|
40
|
+
offset: DEFAULT_MARKET_OFFSET,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function setupMarkerPopupListeners(
|
|
46
|
+
map: MapkaMap,
|
|
47
|
+
marker: Marker,
|
|
48
|
+
popup: Omit<MapkaPopupOptions, "lngLat">,
|
|
49
|
+
options: MapkaMarkerOptions,
|
|
50
|
+
) {
|
|
51
|
+
const popupId = getPopupId(popup);
|
|
52
|
+
const markerElement = marker.getElement();
|
|
53
|
+
|
|
54
|
+
if (options.draggable) {
|
|
55
|
+
marker.on("dragend", () => {
|
|
56
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
57
|
+
map.updatePopup(markerPopupOptions(marker, popup), popupId);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
marker.on("drag", () => {
|
|
61
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
62
|
+
map.updatePopup(markerPopupOptions(marker, popup), popupId);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
13
65
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const newMarker = new maplibregl.Marker({
|
|
19
|
-
color,
|
|
20
|
-
})
|
|
21
|
-
.setLngLat(position)
|
|
22
|
-
.addTo(map);
|
|
23
|
-
|
|
24
|
-
if (tooltip?.trigger === "click") {
|
|
25
|
-
const markerElement = newMarker.getElement();
|
|
26
|
-
|
|
27
|
-
markerElement.style.cursor = "pointer";
|
|
28
|
-
|
|
29
|
-
markerElement.addEventListener("click", (e) => {
|
|
30
|
-
e.stopPropagation();
|
|
31
|
-
showTooltip(newMarker, tooltip, map);
|
|
32
|
-
});
|
|
33
|
-
} else if (tooltip?.trigger === "hover") {
|
|
34
|
-
const markerElement = newMarker.getElement();
|
|
35
|
-
|
|
36
|
-
markerElement.addEventListener("mouseenter", (e) => {
|
|
37
|
-
e.stopPropagation();
|
|
38
|
-
showTooltip(newMarker, tooltip, map);
|
|
39
|
-
});
|
|
40
|
-
markerElement.addEventListener("mouseleave", (e) => {
|
|
41
|
-
e.stopPropagation();
|
|
42
|
-
hideTooltip();
|
|
43
|
-
});
|
|
66
|
+
|
|
67
|
+
if (popup.trigger === "always") {
|
|
68
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
69
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
44
70
|
}
|
|
45
71
|
|
|
46
|
-
|
|
72
|
+
markerElement.addEventListener("click", (e) => {
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
75
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
} else if (popup.trigger === "click") {
|
|
79
|
+
markerElement.style.cursor = "pointer";
|
|
80
|
+
markerElement.addEventListener("click", (e) => {
|
|
81
|
+
e.stopPropagation();
|
|
82
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
83
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
} else if (popup.trigger === "hover") {
|
|
87
|
+
markerElement.addEventListener("mouseenter", (e) => {
|
|
88
|
+
e.stopPropagation();
|
|
89
|
+
if (!map.popups.find((p) => p.id === popupId)) {
|
|
90
|
+
map.openPopup(markerPopupOptions(marker, popup), popupId);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
markerElement.addEventListener("mouseleave", (e) => {
|
|
94
|
+
e.stopPropagation();
|
|
95
|
+
if (map.popups.find((p) => p.id === popupId)) {
|
|
96
|
+
map.closePopup(popupId);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
47
99
|
}
|
|
48
100
|
}
|
|
49
101
|
|
|
50
|
-
export function addMarkers(
|
|
102
|
+
export function addMarkers(currentMap: MapkaMap, markersOptions: MapkaMarkerOptions[]) {
|
|
103
|
+
const markers: MapMapkaMarker[] = [];
|
|
104
|
+
|
|
105
|
+
for (const markerOptions of markersOptions) {
|
|
106
|
+
const { lngLat, popup, ...options } = markerOptions;
|
|
107
|
+
const newMarker = new Marker(options).setLngLat(lngLat).addTo(currentMap);
|
|
108
|
+
|
|
109
|
+
markers.push({
|
|
110
|
+
id: getMarkerId(markerOptions),
|
|
111
|
+
options: markerOptions,
|
|
112
|
+
marker: newMarker,
|
|
113
|
+
});
|
|
114
|
+
if (!popup) continue;
|
|
115
|
+
|
|
116
|
+
setupMarkerPopupListeners(currentMap, newMarker, popup, markerOptions);
|
|
117
|
+
}
|
|
118
|
+
currentMap.markers.push(...markers);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function removeMarkersByIds(map: MapkaMap, ids: string[]) {
|
|
122
|
+
const removedMarkers = remove(map.markers, (marker) => ids.includes(marker.id));
|
|
123
|
+
for (const marker of removedMarkers) {
|
|
124
|
+
marker.marker.remove();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function updateMarkers(map: MapkaMap, markersOptions: MapkaMarkerOptions[]) {
|
|
129
|
+
const markersIds = markersOptions.map(getMarkerId);
|
|
130
|
+
|
|
131
|
+
removeMarkersByIds(map, markersIds);
|
|
132
|
+
addMarkers(map, markersOptions);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function clearMarkers(map: MapkaMap) {
|
|
136
|
+
for (const marker of map.markers) {
|
|
137
|
+
marker.marker.remove();
|
|
138
|
+
}
|
|
139
|
+
map.markers = [];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function addStyleMarkers(map: MapkaMap) {
|
|
51
143
|
const style = map.getStyle();
|
|
144
|
+
|
|
52
145
|
const markers = get(style, "metadata.mapka.markers", []) as MapkaMarkerOptions[];
|
|
53
|
-
|
|
146
|
+
return addMarkers(map, markers);
|
|
54
147
|
}
|
|
55
148
|
|
|
56
|
-
export function
|
|
149
|
+
export function addStyleDiffMarkers(map: MapkaMap, next: StyleSpecification) {
|
|
57
150
|
const markers = get(next, "metadata.mapka.markers", []) as MapkaMarkerOptions[];
|
|
58
|
-
|
|
151
|
+
return addMarkers(map, markers);
|
|
59
152
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
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 type { MapkaPopupOptions } from "../types/marker.js";
|
|
8
|
+
import type { MapkaMap } from "../map.js";
|
|
9
|
+
import { isEqual } from "es-toolkit";
|
|
10
|
+
|
|
11
|
+
export function getPopupId(popup: { id?: string }) {
|
|
12
|
+
return popup.id ?? `popup-${crypto.randomUUID()}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getOnClose(map: MapkaMap, id: string) {
|
|
16
|
+
return () => map.closePopup(id);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function enforceMaxPopups(map: MapkaMap) {
|
|
20
|
+
if (map.popups.length > map.maxPopups) {
|
|
21
|
+
const popupToRemove = map.popups.shift();
|
|
22
|
+
popupToRemove?.popup.remove();
|
|
23
|
+
popupToRemove?.container.remove();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function openPopup(map: MapkaMap, options: MapkaPopupOptions, id: string) {
|
|
28
|
+
const { lngLat, content, closeButton, ...popupOptions } = options;
|
|
29
|
+
if (content instanceof HTMLElement) {
|
|
30
|
+
const popup = new Popup({
|
|
31
|
+
...popupOptions,
|
|
32
|
+
closeButton: false,
|
|
33
|
+
closeOnClick: false,
|
|
34
|
+
})
|
|
35
|
+
.setLngLat(lngLat)
|
|
36
|
+
.setDOMContent(content)
|
|
37
|
+
.addTo(map);
|
|
38
|
+
|
|
39
|
+
map.popups.push({
|
|
40
|
+
container: content,
|
|
41
|
+
id,
|
|
42
|
+
options,
|
|
43
|
+
popup,
|
|
44
|
+
});
|
|
45
|
+
enforceMaxPopups(map);
|
|
46
|
+
return id;
|
|
47
|
+
} else if (typeof content === "object") {
|
|
48
|
+
const onClose = getOnClose(map, id);
|
|
49
|
+
const container = document.createElement("div");
|
|
50
|
+
container.classList.add("mapka-popup-container");
|
|
51
|
+
|
|
52
|
+
render(<PopupContent {...content} closeButton={closeButton} onClose={onClose} />, container);
|
|
53
|
+
|
|
54
|
+
const popup = new Popup({
|
|
55
|
+
...popupOptions,
|
|
56
|
+
closeButton: false,
|
|
57
|
+
closeOnClick: false,
|
|
58
|
+
})
|
|
59
|
+
.setLngLat(lngLat)
|
|
60
|
+
.setDOMContent(container)
|
|
61
|
+
.addTo(map);
|
|
62
|
+
|
|
63
|
+
map.popups.push({
|
|
64
|
+
container,
|
|
65
|
+
id,
|
|
66
|
+
options,
|
|
67
|
+
popup,
|
|
68
|
+
});
|
|
69
|
+
enforceMaxPopups(map);
|
|
70
|
+
return id;
|
|
71
|
+
} else if (typeof content === "function") {
|
|
72
|
+
const newContent = content(id);
|
|
73
|
+
return openPopup(
|
|
74
|
+
map,
|
|
75
|
+
{
|
|
76
|
+
...options,
|
|
77
|
+
content: newContent,
|
|
78
|
+
},
|
|
79
|
+
id,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new Error("Invalid popup content");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const DEFAULT_POPUP_MAX_WIDTH = "240px";
|
|
87
|
+
|
|
88
|
+
export function updatePopupBaseOptions(
|
|
89
|
+
popup: Popup,
|
|
90
|
+
options: MapkaPopupOptions,
|
|
91
|
+
newOptions: Omit<MapkaPopupOptions, "content">,
|
|
92
|
+
) {
|
|
93
|
+
if (!isEqual(options.maxWidth, newOptions.maxWidth)) {
|
|
94
|
+
popup.setMaxWidth(newOptions.maxWidth ?? DEFAULT_POPUP_MAX_WIDTH);
|
|
95
|
+
}
|
|
96
|
+
if (!isEqual(options.offset, newOptions.offset)) {
|
|
97
|
+
popup.setOffset(newOptions.offset);
|
|
98
|
+
}
|
|
99
|
+
if (!isEqual(options.lngLat, newOptions.lngLat)) {
|
|
100
|
+
popup.setLngLat(newOptions.lngLat);
|
|
101
|
+
}
|
|
102
|
+
return popup;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function updatePopup(
|
|
106
|
+
map: MapkaMap,
|
|
107
|
+
{ content, ...newOptions }: MapkaPopupOptions,
|
|
108
|
+
id: string,
|
|
109
|
+
) {
|
|
110
|
+
if (content instanceof HTMLElement) {
|
|
111
|
+
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
112
|
+
for (const { popup, options } of mapkaPopups) {
|
|
113
|
+
updatePopupBaseOptions(popup, options, newOptions);
|
|
114
|
+
popup.setDOMContent(content);
|
|
115
|
+
}
|
|
116
|
+
} else if (typeof content === "object") {
|
|
117
|
+
const onClose = getOnClose(map, id);
|
|
118
|
+
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
119
|
+
|
|
120
|
+
for (const { popup, container, options } of mapkaPopups) {
|
|
121
|
+
const { closeButton } = options;
|
|
122
|
+
render(<PopupContent {...content} closeButton={closeButton} onClose={onClose} />, container);
|
|
123
|
+
updatePopupBaseOptions(popup, options, newOptions);
|
|
124
|
+
popup.setDOMContent(container);
|
|
125
|
+
}
|
|
126
|
+
} else if (typeof content === "function") {
|
|
127
|
+
const newContent = content(id);
|
|
128
|
+
return updatePopup(
|
|
129
|
+
map,
|
|
130
|
+
{
|
|
131
|
+
...newOptions,
|
|
132
|
+
content: newContent,
|
|
133
|
+
},
|
|
134
|
+
id,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function closeOnMapClickPopups(map: MapkaMap) {
|
|
140
|
+
const popupsToCloseOnMapClick = remove(map.popups, (popup) =>
|
|
141
|
+
Boolean(popup.options.closeOnClick),
|
|
142
|
+
);
|
|
143
|
+
for (const popup of popupsToCloseOnMapClick) {
|
|
144
|
+
popup.popup.remove();
|
|
145
|
+
popup.container.remove();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function closePopupsById(map: MapkaMap, id: string) {
|
|
150
|
+
const removedPopups = remove(map.popups, (popup) => popup.id === id);
|
|
151
|
+
for (const popup of removedPopups) {
|
|
152
|
+
popup.popup.remove();
|
|
153
|
+
popup.container.remove();
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/styles.css
CHANGED
|
@@ -804,5 +804,181 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
804
804
|
position: fixed !important;
|
|
805
805
|
top: 0 !important;
|
|
806
806
|
width: 100% !important;
|
|
807
|
-
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/* Mapka Tooltip Styles */
|
|
810
|
+
.mapka-tooltip {
|
|
811
|
+
border-radius: 12px;
|
|
812
|
+
overflow: hidden;
|
|
813
|
+
background: #fff;
|
|
814
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.mapka-popup-icon {
|
|
818
|
+
display: block;
|
|
819
|
+
fill: none;
|
|
820
|
+
height: 16px;
|
|
821
|
+
width: 16px;
|
|
822
|
+
stroke: currentColor;
|
|
823
|
+
overflow: visible;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.mapka-popup-icon-sm {
|
|
827
|
+
height: 12px;
|
|
828
|
+
width: 12px;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.mapka-popup-icon-star {
|
|
832
|
+
height: 12px;
|
|
833
|
+
width: 12px;
|
|
834
|
+
fill: currentColor;
|
|
835
|
+
stroke: none;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/* Carousel */
|
|
839
|
+
.mapka-popup-carousel {
|
|
840
|
+
position: relative;
|
|
841
|
+
width: 100%;
|
|
842
|
+
height: 200px;
|
|
843
|
+
overflow: hidden;
|
|
844
|
+
border-radius: 12px 12px 0 0;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
.mapka-popup-carousel-track {
|
|
848
|
+
display: flex;
|
|
849
|
+
height: 100%;
|
|
850
|
+
transition: transform 0.3s ease;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.mapka-popup-carousel-image {
|
|
854
|
+
min-width: 100%;
|
|
855
|
+
height: 100%;
|
|
856
|
+
object-fit: cover;
|
|
857
|
+
flex-shrink: 0;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
.mapka-popup-carousel-actions {
|
|
861
|
+
position: absolute;
|
|
862
|
+
top: 12px;
|
|
863
|
+
right: 12px;
|
|
864
|
+
display: flex;
|
|
865
|
+
gap: 8px;
|
|
866
|
+
z-index: 3;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.mapka-popup-action-btn {
|
|
870
|
+
background: rgba(255, 255, 255, 0.95);
|
|
871
|
+
border: none;
|
|
872
|
+
border-radius: 50%;
|
|
873
|
+
width: 32px;
|
|
874
|
+
height: 32px;
|
|
875
|
+
cursor: pointer;
|
|
876
|
+
display: flex;
|
|
877
|
+
align-items: center;
|
|
878
|
+
justify-content: center;
|
|
879
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
880
|
+
transition: background 0.2s ease, transform 0.2s ease;
|
|
881
|
+
color: #222;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
.mapka-popup-action-btn:hover {
|
|
885
|
+
background: #fff;
|
|
886
|
+
transform: scale(1.05);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.mapka-popup-carousel-btn {
|
|
890
|
+
position: absolute;
|
|
891
|
+
top: 50%;
|
|
892
|
+
transform: translateY(-50%);
|
|
893
|
+
background: rgba(255, 255, 255, 0.95);
|
|
894
|
+
border: none;
|
|
895
|
+
border-radius: 50%;
|
|
896
|
+
width: 28px;
|
|
897
|
+
height: 28px;
|
|
898
|
+
cursor: pointer;
|
|
899
|
+
display: flex;
|
|
900
|
+
align-items: center;
|
|
901
|
+
justify-content: center;
|
|
902
|
+
z-index: 2;
|
|
903
|
+
transition: background 0.2s ease, transform 0.2s ease;
|
|
904
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
905
|
+
color: #222;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.mapka-popup-carousel-btn:hover {
|
|
909
|
+
background: #fff;
|
|
910
|
+
transform: translateY(-50%) scale(1.05);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.mapka-popup-carousel-prev {
|
|
914
|
+
left: 12px;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
.mapka-popup-carousel-next {
|
|
918
|
+
right: 12px;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.mapka-popup-dots {
|
|
922
|
+
position: absolute;
|
|
923
|
+
bottom: 12px;
|
|
924
|
+
left: 50%;
|
|
925
|
+
transform: translateX(-50%);
|
|
926
|
+
display: flex;
|
|
927
|
+
gap: 6px;
|
|
928
|
+
z-index: 2;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.mapka-popup-dot {
|
|
932
|
+
width: 6px;
|
|
933
|
+
height: 6px;
|
|
934
|
+
border-radius: 50%;
|
|
935
|
+
background: rgba(255, 255, 255, 0.6);
|
|
936
|
+
border: none;
|
|
937
|
+
cursor: pointer;
|
|
938
|
+
padding: 0;
|
|
939
|
+
transition: background 0.2s ease, transform 0.2s ease;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
.mapka-popup-dot:hover {
|
|
943
|
+
background: rgba(255, 255, 255, 0.8);
|
|
944
|
+
transform: scale(1.2);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
.mapka-popup-dot-active {
|
|
948
|
+
background: #fff;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/* Content */
|
|
952
|
+
.mapka-popup-content {
|
|
953
|
+
padding: 12px 16px 16px;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.mapka-popup-header {
|
|
957
|
+
display: flex;
|
|
958
|
+
justify-content: space-between;
|
|
959
|
+
align-items: flex-start;
|
|
960
|
+
gap: 8px;
|
|
961
|
+
margin-bottom: 4px;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.mapka-popup-title {
|
|
965
|
+
margin: 0;
|
|
966
|
+
font-size: 15px;
|
|
967
|
+
font-weight: 600;
|
|
968
|
+
color: #222;
|
|
969
|
+
line-height: 1.3;
|
|
970
|
+
flex: 1;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
.mapka-popup-description {
|
|
975
|
+
margin: 0 0 4px 0;
|
|
976
|
+
font-size: 14px;
|
|
977
|
+
color: #717171;
|
|
978
|
+
line-height: 1.4;
|
|
979
|
+
overflow: hidden;
|
|
980
|
+
text-overflow: ellipsis;
|
|
981
|
+
display: -webkit-box;
|
|
982
|
+
-webkit-line-clamp: 2;
|
|
983
|
+
-webkit-box-orient: vertical;
|
|
808
984
|
}
|
package/src/types/id.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type WithId<T extends { id: string }> = T & { id: string };
|
package/src/types/marker.ts
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { MarkerOptions, PopupOptions } from "maplibre-gl";
|
|
2
|
+
|
|
3
|
+
export interface MapkaPopupContent {
|
|
3
4
|
title?: string;
|
|
4
5
|
description?: string;
|
|
5
6
|
imageUrls?: string[];
|
|
7
|
+
onFavorite?: (id: string) => void;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
type CreatePopupElement = (id: string) => HTMLElement;
|
|
11
|
+
type CreatePopupContent = (id: string) => MapkaPopupContent;
|
|
12
|
+
|
|
13
|
+
export interface MapkaPopupOptions extends PopupOptions {
|
|
14
|
+
id?: string;
|
|
15
|
+
lngLat: [number, number];
|
|
16
|
+
trigger?: "hover" | "click" | "always";
|
|
17
|
+
content: MapkaPopupContent | HTMLElement | CreatePopupElement | CreatePopupContent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type MapkaMarkerPopupOptions = Omit<MapkaPopupOptions, "lngLat">;
|
|
21
|
+
|
|
22
|
+
export interface MapkaMarkerOptions extends MarkerOptions {
|
|
23
|
+
id?: string;
|
|
24
|
+
lngLat: [number, number];
|
|
10
25
|
color?: string;
|
|
11
26
|
icon?: string;
|
|
12
|
-
|
|
27
|
+
popup?: Omit<MapkaPopupOptions, "lngLat">;
|
|
13
28
|
}
|
package/lib/modules/tooltip.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as maplibregl from "maplibre-gl";
|
|
2
|
-
import type { MapkaTooltipOptions } from "../types/marker.js";
|
|
3
|
-
/**
|
|
4
|
-
* Shows a tooltip for a marker
|
|
5
|
-
*/
|
|
6
|
-
export declare function showTooltip(marker: maplibregl.Marker, options: MapkaTooltipOptions, map: maplibregl.Map): void;
|
|
7
|
-
/**
|
|
8
|
-
* Hides the current tooltip
|
|
9
|
-
*/
|
|
10
|
-
export declare function hideTooltip(): void;
|
|
11
|
-
/**
|
|
12
|
-
* Gets the current visible popup
|
|
13
|
-
*/
|
|
14
|
-
export declare function getCurrentTooltip(): maplibregl.Popup | null;
|
|
15
|
-
//# sourceMappingURL=tooltip.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/modules/tooltip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAuS9D;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,CAAC,MAAM,EACzB,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,UAAU,CAAC,GAAG,QAwBpB;AAED;;GAEG;AACH,wBAAgB,WAAW,SAK1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,CAAC,KAAK,GAAG,IAAI,CAE3D"}
|