@mapka/maplibre-gl-sdk 0.6.0 → 0.8.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/index.js CHANGED
@@ -3,4 +3,3 @@ export * from "./types/layer.js";
3
3
  export * from "./types/marker.js";
4
4
  export * from "./types/style.js";
5
5
  export { MapkaMap as Map } from "./map.js";
6
- //# sourceMappingURL=index.js.map
package/lib/map.js CHANGED
@@ -46,4 +46,3 @@ export class MapkaMap extends maplibregl.Map {
46
46
  return this;
47
47
  }
48
48
  }
49
- //# sourceMappingURL=map.js.map
@@ -41,4 +41,3 @@ export function loadLayersIcons(map, event) {
41
41
  }
42
42
  loadIcons(map);
43
43
  }
44
- //# sourceMappingURL=icons.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/modules/markers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAuB1C,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,QAIvC;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,QAG1E"}
1
+ {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/modules/markers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AA8C1C,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,QAIvC;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,QAG1E"}
@@ -1,18 +1,38 @@
1
1
  import * as maplibregl from "maplibre-gl";
2
2
  import { get } from "es-toolkit/compat";
3
+ import { showTooltip, hideTooltip } from "./tooltip.js";
3
4
  const prevMarkers = new Set();
4
5
  function addMarkersToMap(map, markers) {
5
6
  for (const marker of prevMarkers) {
6
7
  marker.remove();
7
8
  }
8
9
  prevMarkers.clear();
9
- for (const marker of markers) {
10
- const { position, color } = marker;
10
+ for (const markerConfig of markers) {
11
+ const { position, color, tooltip } = markerConfig;
11
12
  const newMarker = new maplibregl.Marker({
12
13
  color,
13
14
  })
14
15
  .setLngLat(position)
15
16
  .addTo(map);
17
+ if (tooltip?.trigger === "click") {
18
+ const markerElement = newMarker.getElement();
19
+ markerElement.style.cursor = "pointer";
20
+ markerElement.addEventListener("click", (e) => {
21
+ e.stopPropagation();
22
+ showTooltip(newMarker, tooltip, map);
23
+ });
24
+ }
25
+ else if (tooltip?.trigger === "hover") {
26
+ const markerElement = newMarker.getElement();
27
+ markerElement.addEventListener("mouseenter", (e) => {
28
+ e.stopPropagation();
29
+ showTooltip(newMarker, tooltip, map);
30
+ });
31
+ markerElement.addEventListener("mouseleave", (e) => {
32
+ e.stopPropagation();
33
+ hideTooltip();
34
+ });
35
+ }
16
36
  prevMarkers.add(newMarker);
17
37
  }
18
38
  }
@@ -25,4 +45,3 @@ export function addMarkersStyleDiff(map, next) {
25
45
  const markers = get(next, "metadata.mapka.markers", []);
26
46
  addMarkersToMap(map, markers);
27
47
  }
28
- //# sourceMappingURL=markers.js.map
@@ -0,0 +1,15 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,306 @@
1
+ import * as maplibregl from "maplibre-gl";
2
+ let currentPopup = null;
3
+ let currentCarouselIndex = 0;
4
+ /**
5
+ * Creates the tooltip content HTML with Airbnb-style design
6
+ */
7
+ function createTooltipContent(options) {
8
+ const content = document.createElement("div");
9
+ content.className = "mapka-tooltip-content-wrapper";
10
+ // Add image carousel if images are provided
11
+ if (options.imageUrls && options.imageUrls.length > 0) {
12
+ const carouselContainer = document.createElement("div");
13
+ carouselContainer.className = "mapka-tooltip-carousel";
14
+ const carouselTrack = document.createElement("div");
15
+ carouselTrack.className = "mapka-tooltip-carousel-track";
16
+ options.imageUrls.forEach((url, index) => {
17
+ const img = document.createElement("img");
18
+ img.src = url;
19
+ img.alt = options.title || "Marker image";
20
+ img.className = "mapka-tooltip-image";
21
+ if (index === 0)
22
+ img.classList.add("active");
23
+ carouselTrack.appendChild(img);
24
+ });
25
+ carouselContainer.appendChild(carouselTrack);
26
+ // Add close button
27
+ const closeButton = document.createElement("button");
28
+ closeButton.className = "mapka-tooltip-action-btn mapka-tooltip-close";
29
+ closeButton.innerHTML = `<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="display:block;fill:none;height:16px;width:16px;stroke:currentColor;stroke-width:3;overflow:visible"><path d="m6 6 20 20M26 6 6 26"></path></svg>`;
30
+ closeButton.setAttribute("aria-label", "Close");
31
+ closeButton.addEventListener("click", (e) => {
32
+ e.stopPropagation();
33
+ hideTooltip();
34
+ });
35
+ carouselContainer.appendChild(closeButton);
36
+ // Add navigation dots if multiple images
37
+ if (options.imageUrls.length > 1) {
38
+ const dotsContainer = document.createElement("div");
39
+ dotsContainer.className = "mapka-tooltip-dots";
40
+ options.imageUrls.forEach((_, index) => {
41
+ const dot = document.createElement("button");
42
+ dot.className = "mapka-tooltip-dot";
43
+ if (index === 0)
44
+ dot.classList.add("active");
45
+ dot.setAttribute("aria-label", `Go to image ${index + 1}`);
46
+ dot.addEventListener("click", (e) => {
47
+ e.stopPropagation();
48
+ showCarouselImage(carouselTrack, dotsContainer, index);
49
+ });
50
+ dotsContainer.appendChild(dot);
51
+ });
52
+ carouselContainer.appendChild(dotsContainer);
53
+ // Add prev/next buttons
54
+ const prevButton = document.createElement("button");
55
+ prevButton.className = "mapka-tooltip-carousel-btn mapka-tooltip-carousel-prev";
56
+ prevButton.innerHTML = `<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="display:block;fill:none;height:12px;width:12px;stroke:currentColor;stroke-width:4;overflow:visible"><path fill="none" d="M20 28 8.7 16.7a1 1 0 0 1 0-1.4L20 4"></path></svg>`;
57
+ prevButton.setAttribute("aria-label", "Previous image");
58
+ prevButton.addEventListener("click", (e) => {
59
+ e.stopPropagation();
60
+ const imageCount = options.imageUrls?.length ?? 0;
61
+ const newIndex = currentCarouselIndex === 0 ? imageCount - 1 : currentCarouselIndex - 1;
62
+ showCarouselImage(carouselTrack, dotsContainer, newIndex);
63
+ });
64
+ const nextButton = document.createElement("button");
65
+ nextButton.className = "mapka-tooltip-carousel-btn mapka-tooltip-carousel-next";
66
+ nextButton.innerHTML = `<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="display:block;fill:none;height:12px;width:12px;stroke:currentColor;stroke-width:4;overflow:visible"><path fill="none" d="m12 4 11.3 11.3a1 1 0 0 1 0 1.4L12 28"></path></svg>`;
67
+ nextButton.setAttribute("aria-label", "Next image");
68
+ nextButton.addEventListener("click", (e) => {
69
+ e.stopPropagation();
70
+ const imageCount = options.imageUrls?.length ?? 0;
71
+ const newIndex = (currentCarouselIndex + 1) % imageCount;
72
+ showCarouselImage(carouselTrack, dotsContainer, newIndex);
73
+ });
74
+ carouselContainer.appendChild(prevButton);
75
+ carouselContainer.appendChild(nextButton);
76
+ }
77
+ content.appendChild(carouselContainer);
78
+ }
79
+ // Add text content section
80
+ const textContent = document.createElement("div");
81
+ textContent.className = "mapka-tooltip-text";
82
+ if (options.title) {
83
+ const title = document.createElement("h3");
84
+ title.className = "mapka-tooltip-title";
85
+ title.textContent = options.title;
86
+ textContent.appendChild(title);
87
+ }
88
+ if (options.description) {
89
+ const description = document.createElement("p");
90
+ description.className = "mapka-tooltip-description";
91
+ description.textContent = options.description;
92
+ textContent.appendChild(description);
93
+ }
94
+ content.appendChild(textContent);
95
+ return content;
96
+ }
97
+ /**
98
+ * Shows a specific image in the carousel
99
+ */
100
+ function showCarouselImage(track, dotsContainer, index) {
101
+ currentCarouselIndex = index;
102
+ const images = track.querySelectorAll(".mapka-tooltip-image");
103
+ const dots = dotsContainer.querySelectorAll(".mapka-tooltip-dot");
104
+ images.forEach((img, i) => {
105
+ img.classList.toggle("active", i === index);
106
+ });
107
+ dots.forEach((dot, i) => {
108
+ dot.classList.toggle("active", i === index);
109
+ });
110
+ track.style.transform = `translateX(-${index * 100}%)`;
111
+ }
112
+ /**
113
+ * Injects the required CSS styles for the tooltip
114
+ */
115
+ function injectStyles() {
116
+ if (document.getElementById("mapka-tooltip-styles"))
117
+ return;
118
+ const style = document.createElement("style");
119
+ style.id = "mapka-tooltip-styles";
120
+ style.textContent = `
121
+ .maplibregl-popup-content {
122
+ padding: 0 !important;
123
+ border-radius: 12px !important;
124
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12) !important;
125
+ min-width: 280px;
126
+ max-width: 320px;
127
+ }
128
+
129
+ .maplibregl-popup-close-button {
130
+ display: none !important;
131
+ }
132
+
133
+ .mapka-tooltip-content-wrapper {
134
+ border-radius: 12px;
135
+ overflow: hidden;
136
+ }
137
+
138
+ .mapka-tooltip-carousel {
139
+ position: relative;
140
+ width: 100%;
141
+ height: 200px;
142
+ overflow: hidden;
143
+ border-radius: 12px 12px 0 0;
144
+ }
145
+
146
+ .mapka-tooltip-carousel-track {
147
+ display: flex;
148
+ height: 100%;
149
+ transition: transform 0.3s ease;
150
+ }
151
+
152
+ .mapka-tooltip-image {
153
+ min-width: 100%;
154
+ height: 100%;
155
+ object-fit: cover;
156
+ display: none;
157
+ }
158
+
159
+ .mapka-tooltip-image.active {
160
+ display: block;
161
+ }
162
+
163
+ .mapka-tooltip-action-btn {
164
+ position: absolute;
165
+ top: 12px;
166
+ right: 12px;
167
+ background: rgba(255, 255, 255, 0.95);
168
+ border: none;
169
+ border-radius: 50%;
170
+ width: 32px;
171
+ height: 32px;
172
+ cursor: pointer;
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: center;
176
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
177
+ transition: background 0.2s ease, transform 0.2s ease;
178
+ color: #222;
179
+ z-index: 3;
180
+ }
181
+
182
+ .mapka-tooltip-action-btn:hover {
183
+ background: white;
184
+ transform: scale(1.05);
185
+ }
186
+
187
+ .mapka-tooltip-carousel-btn {
188
+ position: absolute;
189
+ top: 50%;
190
+ transform: translateY(-50%);
191
+ background: rgba(255, 255, 255, 0.95);
192
+ border: none;
193
+ border-radius: 50%;
194
+ width: 32px;
195
+ height: 32px;
196
+ cursor: pointer;
197
+ display: flex;
198
+ align-items: center;
199
+ justify-content: center;
200
+ z-index: 2;
201
+ transition: background 0.2s ease, transform 0.2s ease;
202
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
203
+ color: #222;
204
+ }
205
+
206
+ .mapka-tooltip-carousel-btn:hover {
207
+ background: white;
208
+ transform: translateY(-50%) scale(1.05);
209
+ }
210
+
211
+ .mapka-tooltip-carousel-prev {
212
+ left: 12px;
213
+ }
214
+
215
+ .mapka-tooltip-carousel-next {
216
+ right: 12px;
217
+ }
218
+
219
+ .mapka-tooltip-dots {
220
+ position: absolute;
221
+ bottom: 12px;
222
+ left: 50%;
223
+ transform: translateX(-50%);
224
+ display: flex;
225
+ gap: 6px;
226
+ z-index: 2;
227
+ }
228
+
229
+ .mapka-tooltip-dot {
230
+ width: 6px;
231
+ height: 6px;
232
+ border-radius: 50%;
233
+ background: rgba(255, 255, 255, 0.6);
234
+ border: none;
235
+ cursor: pointer;
236
+ padding: 0;
237
+ transition: background 0.2s ease, transform 0.2s ease;
238
+ }
239
+
240
+ .mapka-tooltip-dot:hover {
241
+ background: rgba(255, 255, 255, 0.8);
242
+ transform: scale(1.2);
243
+ }
244
+
245
+ .mapka-tooltip-dot.active {
246
+ background: white;
247
+ }
248
+
249
+ .mapka-tooltip-text {
250
+ padding: 12px 16px 16px;
251
+ }
252
+
253
+ .mapka-tooltip-title {
254
+ margin: 0 0 4px 0;
255
+ font-size: 15px;
256
+ font-weight: 600;
257
+ color: #222;
258
+ line-height: 1.3;
259
+ }
260
+
261
+ .mapka-tooltip-description {
262
+ margin: 0;
263
+ font-size: 14px;
264
+ color: #717171;
265
+ line-height: 1.4;
266
+ }
267
+ `;
268
+ document.head.appendChild(style);
269
+ }
270
+ /**
271
+ * Shows a tooltip for a marker
272
+ */
273
+ export function showTooltip(marker, options, map) {
274
+ // Hide any existing tooltip
275
+ hideTooltip();
276
+ // Inject styles if not already present
277
+ injectStyles();
278
+ // Reset carousel index
279
+ currentCarouselIndex = 0;
280
+ const content = createTooltipContent(options);
281
+ const popup = new maplibregl.Popup({
282
+ closeButton: true,
283
+ closeOnClick: false,
284
+ maxWidth: "320px",
285
+ offset: 12,
286
+ })
287
+ .setLngLat(marker.getLngLat())
288
+ .setDOMContent(content)
289
+ .addTo(map);
290
+ currentPopup = popup;
291
+ }
292
+ /**
293
+ * Hides the current tooltip
294
+ */
295
+ export function hideTooltip() {
296
+ if (currentPopup) {
297
+ currentPopup.remove();
298
+ currentPopup = null;
299
+ }
300
+ }
301
+ /**
302
+ * Gets the current visible popup
303
+ */
304
+ export function getCurrentTooltip() {
305
+ return currentPopup;
306
+ }
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=layer.js.map
@@ -1,6 +1,13 @@
1
+ export interface MapkaTooltipOptions {
2
+ trigger?: "hover" | "click";
3
+ title?: string;
4
+ description?: string;
5
+ imageUrls?: string[];
6
+ }
1
7
  export interface MapkaMarkerOptions {
2
8
  position: [number, number];
3
9
  color?: string;
4
10
  icon?: string;
11
+ tooltip?: MapkaTooltipOptions;
5
12
  }
6
13
  //# sourceMappingURL=marker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/types/marker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
1
+ {"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/types/marker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B"}
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=marker.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=style.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,0FAS1B"}
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,0FAQ1B"}
package/lib/utils/url.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { MapkaMap } from "../map.js";
2
2
  export function getMapkaUrl() {
3
- console.log("MapkaMap.env", MapkaMap.env);
4
3
  if (MapkaMap.env === "dev") {
5
4
  return "https://api.dev.mapka.dev";
6
5
  }
@@ -9,4 +8,3 @@ export function getMapkaUrl() {
9
8
  }
10
9
  return "https://api.mapka.dev";
11
10
  }
12
- //# sourceMappingURL=url.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapka/maplibre-gl-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Mapka JS SDK",
6
6
  "sideEffects": false,
@@ -12,7 +12,8 @@
12
12
  "url": "https://github.com/mapka-dev/sdk.git"
13
13
  },
14
14
  "exports": {
15
- ".": "./lib/index.js"
15
+ ".": "./lib/index.js",
16
+ "./styles.css": "./src/styles.css"
16
17
  },
17
18
  "keywords": [
18
19
  "map",
@@ -22,8 +23,9 @@
22
23
  "author": "chyzwar",
23
24
  "license": "Apache-2.0",
24
25
  "dependencies": {
25
- "es-toolkit": "^1.42.0",
26
- "maplibre-gl": "^5.13.0"
26
+ "es-toolkit": "^1.43.0",
27
+ "maplibre-gl": "^5.14.0",
28
+ "preact": "^10.28.0"
27
29
  },
28
30
  "files": [
29
31
  "src/",
@@ -32,5 +34,5 @@
32
34
  "!**/__tests__/",
33
35
  "!lib/buildInfo.json"
34
36
  ],
35
- "gitHead": "b57b649b9cff4ac0a3a0e68f3399bf3ba029d726"
37
+ "gitHead": "9526c5f5a2af4bc87584e498a57683ed03fc53d3"
36
38
  }
@@ -3,6 +3,7 @@ import { get } from "es-toolkit/compat";
3
3
  import type { StyleSpecification } from "maplibre-gl";
4
4
  import type { MapkaMap } from "../map.js";
5
5
  import type { MapkaMarkerOptions } from "../types/marker.js";
6
+ import { showTooltip, hideTooltip } from "./tooltip.js";
6
7
 
7
8
  const prevMarkers = new Set<maplibregl.Marker>();
8
9
 
@@ -12,14 +13,36 @@ function addMarkersToMap(map: MapkaMap, markers: MapkaMarkerOptions[]) {
12
13
  }
13
14
  prevMarkers.clear();
14
15
 
15
- for (const marker of markers) {
16
- const { position, color } = marker;
16
+ for (const markerConfig of markers) {
17
+ const { position, color, tooltip } = markerConfig;
17
18
  const newMarker = new maplibregl.Marker({
18
19
  color,
19
20
  })
20
21
  .setLngLat(position)
21
22
  .addTo(map);
22
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
+ });
44
+ }
45
+
23
46
  prevMarkers.add(newMarker);
24
47
  }
25
48
  }