@mapka/maplibre-gl-sdk 0.9.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 +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 +137 -44
- 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
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
|
@@ -814,7 +814,7 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
814
814
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
815
815
|
}
|
|
816
816
|
|
|
817
|
-
.mapka-
|
|
817
|
+
.mapka-popup-icon {
|
|
818
818
|
display: block;
|
|
819
819
|
fill: none;
|
|
820
820
|
height: 16px;
|
|
@@ -823,12 +823,12 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
823
823
|
overflow: visible;
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
-
.mapka-
|
|
826
|
+
.mapka-popup-icon-sm {
|
|
827
827
|
height: 12px;
|
|
828
828
|
width: 12px;
|
|
829
829
|
}
|
|
830
830
|
|
|
831
|
-
.mapka-
|
|
831
|
+
.mapka-popup-icon-star {
|
|
832
832
|
height: 12px;
|
|
833
833
|
width: 12px;
|
|
834
834
|
fill: currentColor;
|
|
@@ -836,7 +836,7 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
836
836
|
}
|
|
837
837
|
|
|
838
838
|
/* Carousel */
|
|
839
|
-
.mapka-
|
|
839
|
+
.mapka-popup-carousel {
|
|
840
840
|
position: relative;
|
|
841
841
|
width: 100%;
|
|
842
842
|
height: 200px;
|
|
@@ -844,20 +844,20 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
844
844
|
border-radius: 12px 12px 0 0;
|
|
845
845
|
}
|
|
846
846
|
|
|
847
|
-
.mapka-
|
|
847
|
+
.mapka-popup-carousel-track {
|
|
848
848
|
display: flex;
|
|
849
849
|
height: 100%;
|
|
850
850
|
transition: transform 0.3s ease;
|
|
851
851
|
}
|
|
852
852
|
|
|
853
|
-
.mapka-
|
|
853
|
+
.mapka-popup-carousel-image {
|
|
854
854
|
min-width: 100%;
|
|
855
855
|
height: 100%;
|
|
856
856
|
object-fit: cover;
|
|
857
857
|
flex-shrink: 0;
|
|
858
858
|
}
|
|
859
859
|
|
|
860
|
-
.mapka-
|
|
860
|
+
.mapka-popup-carousel-actions {
|
|
861
861
|
position: absolute;
|
|
862
862
|
top: 12px;
|
|
863
863
|
right: 12px;
|
|
@@ -866,7 +866,7 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
866
866
|
z-index: 3;
|
|
867
867
|
}
|
|
868
868
|
|
|
869
|
-
.mapka-
|
|
869
|
+
.mapka-popup-action-btn {
|
|
870
870
|
background: rgba(255, 255, 255, 0.95);
|
|
871
871
|
border: none;
|
|
872
872
|
border-radius: 50%;
|
|
@@ -881,12 +881,12 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
881
881
|
color: #222;
|
|
882
882
|
}
|
|
883
883
|
|
|
884
|
-
.mapka-
|
|
884
|
+
.mapka-popup-action-btn:hover {
|
|
885
885
|
background: #fff;
|
|
886
886
|
transform: scale(1.05);
|
|
887
887
|
}
|
|
888
888
|
|
|
889
|
-
.mapka-
|
|
889
|
+
.mapka-popup-carousel-btn {
|
|
890
890
|
position: absolute;
|
|
891
891
|
top: 50%;
|
|
892
892
|
transform: translateY(-50%);
|
|
@@ -905,20 +905,20 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
905
905
|
color: #222;
|
|
906
906
|
}
|
|
907
907
|
|
|
908
|
-
.mapka-
|
|
908
|
+
.mapka-popup-carousel-btn:hover {
|
|
909
909
|
background: #fff;
|
|
910
910
|
transform: translateY(-50%) scale(1.05);
|
|
911
911
|
}
|
|
912
912
|
|
|
913
|
-
.mapka-
|
|
913
|
+
.mapka-popup-carousel-prev {
|
|
914
914
|
left: 12px;
|
|
915
915
|
}
|
|
916
916
|
|
|
917
|
-
.mapka-
|
|
917
|
+
.mapka-popup-carousel-next {
|
|
918
918
|
right: 12px;
|
|
919
919
|
}
|
|
920
920
|
|
|
921
|
-
.mapka-
|
|
921
|
+
.mapka-popup-dots {
|
|
922
922
|
position: absolute;
|
|
923
923
|
bottom: 12px;
|
|
924
924
|
left: 50%;
|
|
@@ -928,7 +928,7 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
928
928
|
z-index: 2;
|
|
929
929
|
}
|
|
930
930
|
|
|
931
|
-
.mapka-
|
|
931
|
+
.mapka-popup-dot {
|
|
932
932
|
width: 6px;
|
|
933
933
|
height: 6px;
|
|
934
934
|
border-radius: 50%;
|
|
@@ -939,21 +939,21 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
939
939
|
transition: background 0.2s ease, transform 0.2s ease;
|
|
940
940
|
}
|
|
941
941
|
|
|
942
|
-
.mapka-
|
|
942
|
+
.mapka-popup-dot:hover {
|
|
943
943
|
background: rgba(255, 255, 255, 0.8);
|
|
944
944
|
transform: scale(1.2);
|
|
945
945
|
}
|
|
946
946
|
|
|
947
|
-
.mapka-
|
|
947
|
+
.mapka-popup-dot-active {
|
|
948
948
|
background: #fff;
|
|
949
949
|
}
|
|
950
950
|
|
|
951
951
|
/* Content */
|
|
952
|
-
.mapka-
|
|
952
|
+
.mapka-popup-content {
|
|
953
953
|
padding: 12px 16px 16px;
|
|
954
954
|
}
|
|
955
955
|
|
|
956
|
-
.mapka-
|
|
956
|
+
.mapka-popup-header {
|
|
957
957
|
display: flex;
|
|
958
958
|
justify-content: space-between;
|
|
959
959
|
align-items: flex-start;
|
|
@@ -961,7 +961,7 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
961
961
|
margin-bottom: 4px;
|
|
962
962
|
}
|
|
963
963
|
|
|
964
|
-
.mapka-
|
|
964
|
+
.mapka-popup-title {
|
|
965
965
|
margin: 0;
|
|
966
966
|
font-size: 15px;
|
|
967
967
|
font-weight: 600;
|
|
@@ -970,24 +970,8 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
970
970
|
flex: 1;
|
|
971
971
|
}
|
|
972
972
|
|
|
973
|
-
.mapka-tooltip-rating {
|
|
974
|
-
display: flex;
|
|
975
|
-
align-items: center;
|
|
976
|
-
gap: 4px;
|
|
977
|
-
color: #222;
|
|
978
|
-
font-size: 14px;
|
|
979
|
-
flex-shrink: 0;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
.mapka-tooltip-rating-value {
|
|
983
|
-
font-weight: 600;
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
.mapka-tooltip-rating-count {
|
|
987
|
-
color: #717171;
|
|
988
|
-
}
|
|
989
973
|
|
|
990
|
-
.mapka-
|
|
974
|
+
.mapka-popup-description {
|
|
991
975
|
margin: 0 0 4px 0;
|
|
992
976
|
font-size: 14px;
|
|
993
977
|
color: #717171;
|
|
@@ -997,32 +981,4 @@ a.maplibregl-ctrl-logo.maplibregl-compact {
|
|
|
997
981
|
display: -webkit-box;
|
|
998
982
|
-webkit-line-clamp: 2;
|
|
999
983
|
-webkit-box-orient: vertical;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
.mapka-tooltip-subtitle {
|
|
1003
|
-
margin: 0 0 8px 0;
|
|
1004
|
-
font-size: 14px;
|
|
1005
|
-
color: #717171;
|
|
1006
|
-
line-height: 1.4;
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
.mapka-tooltip-price {
|
|
1010
|
-
display: flex;
|
|
1011
|
-
align-items: baseline;
|
|
1012
|
-
gap: 6px;
|
|
1013
|
-
font-size: 14px;
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
.mapka-tooltip-price-original {
|
|
1017
|
-
color: #717171;
|
|
1018
|
-
text-decoration: line-through;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
.mapka-tooltip-price-current {
|
|
1022
|
-
font-weight: 600;
|
|
1023
|
-
color: #222;
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
.mapka-tooltip-price-suffix {
|
|
1027
|
-
color: #717171;
|
|
1028
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,29 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
value: number;
|
|
3
|
-
count: number;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface MapkaTooltipPrice {
|
|
7
|
-
current: string;
|
|
8
|
-
original?: string;
|
|
9
|
-
suffix?: string;
|
|
10
|
-
}
|
|
1
|
+
import type { MarkerOptions, PopupOptions } from "maplibre-gl";
|
|
11
2
|
|
|
12
|
-
export interface
|
|
13
|
-
id?: string;
|
|
14
|
-
trigger?: "hover" | "click";
|
|
3
|
+
export interface MapkaPopupContent {
|
|
15
4
|
title?: string;
|
|
16
|
-
rating?: MapkaTooltipRating;
|
|
17
5
|
description?: string;
|
|
18
|
-
subtitle?: string;
|
|
19
|
-
price?: MapkaTooltipPrice;
|
|
20
6
|
imageUrls?: string[];
|
|
21
7
|
onFavorite?: (id: string) => void;
|
|
22
8
|
}
|
|
23
9
|
|
|
24
|
-
|
|
25
|
-
|
|
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];
|
|
26
25
|
color?: string;
|
|
27
26
|
icon?: string;
|
|
28
|
-
|
|
27
|
+
popup?: Omit<MapkaPopupOptions, "lngLat">;
|
|
29
28
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
-
import { h } from "preact";
|
|
3
|
-
import type { MapkaTooltipOptions } from "../types/marker.js";
|
|
4
|
-
interface TooltipProps extends MapkaTooltipOptions {
|
|
5
|
-
onClose?: () => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function Tooltip({ id, title, rating, description, subtitle, price, imageUrls, onFavorite, onClose, }: TooltipProps): h.JSX.Element;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/components/Tooltip.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,CAAC,EAAY,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,UAAU,YAAa,SAAQ,mBAAmB;IAChD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AA2MD,wBAAgB,OAAO,CAAC,EACtB,EAAE,EACF,KAAK,EACL,MAAM,EACN,WAAW,EACX,QAAQ,EACR,KAAK,EACL,SAAS,EACT,UAAU,EACV,OAAO,GACR,EAAE,YAAY,iBA4Cd"}
|