@mapka/maplibre-gl-sdk 0.16.3 → 0.17.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/README.md +29 -2
- package/lib/.buildInfo.json +1 -1
- package/lib/components/PopupList.d.ts.map +1 -1
- package/lib/components/PopupList.js +26 -2
- package/lib/components/icons/ChevronDownIcon.d.ts +2 -0
- package/lib/components/icons/ChevronDownIcon.d.ts.map +1 -0
- package/lib/components/icons/ChevronDownIcon.js +4 -0
- package/lib/components/icons/ChevronUpIcon.d.ts +2 -0
- package/lib/components/icons/ChevronUpIcon.d.ts.map +1 -0
- package/lib/components/icons/ChevronUpIcon.js +4 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/map.d.ts.map +1 -1
- package/lib/modules/icons.d.ts +8 -4
- package/lib/modules/icons.d.ts.map +1 -1
- package/lib/modules/icons.js +69 -31
- package/lib/modules/markers.d.ts.map +1 -1
- package/lib/modules/markers.js +55 -2
- package/lib/modules/popupGroups.d.ts.map +1 -1
- package/lib/styles.css +1 -1
- package/lib/types/marker.d.ts +4 -2
- package/lib/types/marker.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/components/PopupContent.css +7 -5
- package/src/components/PopupList.css +59 -12
- package/src/components/PopupList.tsx +83 -8
- package/src/components/icons/ChevronDownIcon.tsx +20 -0
- package/src/components/icons/ChevronUpIcon.tsx +20 -0
- package/src/controls/MapkaDrawControl.css +1 -3
- package/src/index.ts +2 -0
- package/src/map.ts +7 -1
- package/src/modules/icons.ts +74 -38
- package/src/modules/markers.css +18 -0
- package/src/modules/markers.ts +67 -3
- package/src/modules/popupGroups.ts +0 -1
- package/src/styles.css +1 -1
- package/src/types/marker.ts +4 -2
- package/lib/components/PopupListItem.d.ts +0 -13
- package/lib/components/PopupListItem.d.ts.map +0 -1
- package/lib/components/PopupListItem.js +0 -11
- package/src/components/PopupListItem.css +0 -61
- package/src/components/PopupListItem.tsx +0 -40
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopupList.d.ts","sourceRoot":"","sources":["../../src/components/PopupList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PopupList.d.ts","sourceRoot":"","sources":["../../src/components/PopupList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAMnE,UAAU,oBAAoB;IAC5B,KAAK,EAAE,yBAAyB,EAAE,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,eAEnE;AA0CD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,oBAAoB,gCA8CxD"}
|
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from "preact/hooks";
|
|
3
|
+
import { PopupContent } from "./PopupContent.js";
|
|
4
|
+
import { ChevronUpIcon } from "./icons/ChevronUpIcon.js";
|
|
5
|
+
import { ChevronDownIcon } from "./icons/ChevronDownIcon.js";
|
|
6
|
+
import { noop } from "es-toolkit";
|
|
3
7
|
export function PopupCustomElement({ popup }) {
|
|
4
8
|
return popup;
|
|
5
9
|
}
|
|
10
|
+
function PopupListNav({ index, total, onPrev, onNext }) {
|
|
11
|
+
const isFirst = index === 0;
|
|
12
|
+
const isLast = index === total - 1;
|
|
13
|
+
return (_jsxs("div", { class: "mapka-popup-list-nav", children: [_jsx("button", { type: "button", class: "mapka-popup-list-nav-btn", onClick: onPrev, disabled: isFirst, "aria-label": "Previous popup", children: _jsx(ChevronUpIcon, {}) }), _jsxs("div", { class: "mapka-popup-list-nav-counter", children: [_jsx("span", { children: index + 1 }), _jsx("span", { class: "mapka-popup-list-nav-counter-divider" }), _jsx("span", { children: total })] }), _jsx("button", { type: "button", class: "mapka-popup-list-nav-btn", onClick: onNext, disabled: isLast, "aria-label": "Next popup", children: _jsx(ChevronDownIcon, {}) })] }));
|
|
14
|
+
}
|
|
6
15
|
export function PopupList({ items }) {
|
|
7
|
-
|
|
16
|
+
const [index, setIndex] = useState(0);
|
|
17
|
+
const safeIndex = Math.min(index, items.length - 1);
|
|
18
|
+
const handlePrev = (e) => {
|
|
19
|
+
e.stopPropagation();
|
|
20
|
+
if (safeIndex > 0) {
|
|
21
|
+
setIndex(safeIndex - 1);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const handleNext = (e) => {
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
if (safeIndex < items.length - 1) {
|
|
27
|
+
setIndex(safeIndex + 1);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const { id, content } = items[safeIndex];
|
|
31
|
+
return (_jsxs("div", { class: "mapka-popup-list-wrapper", children: [_jsx("div", { class: "mapka-popup-list", children: content instanceof HTMLElement ? (_jsx(PopupCustomElement, { popup: content }, id)) : (_jsx(PopupContent, { title: content.title, description: content.description, rows: content.rows, imageUrls: content.imageUrls, primaryAction: content.primaryAction, closeButton: false, onClose: noop }, id)) }), items.length > 1 && (_jsx(PopupListNav, { index: safeIndex, total: items.length, onPrev: handlePrev, onNext: handleNext }))] }));
|
|
8
32
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChevronDownIcon.d.ts","sourceRoot":"","sources":["../../../src/components/icons/ChevronDownIcon.tsx"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,iCAmB9B"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
export function ChevronDownIcon() {
|
|
3
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon mapka-popup-icon-sm", children: _jsx("path", { d: "M3 6 7.3 10.3a1 1 0 0 0 1.4 0L13 6", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }));
|
|
4
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChevronUpIcon.d.ts","sourceRoot":"","sources":["../../../src/components/icons/ChevronUpIcon.tsx"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,iCAmB5B"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
export function ChevronUpIcon() {
|
|
3
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", class: "mapka-popup-icon mapka-popup-icon-sm", children: _jsx("path", { d: "M3 10 7.3 5.7a1 1 0 0 1 1.4 0L13 10", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }));
|
|
4
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ export { MapkaMap as Map } from "./map.js";
|
|
|
9
9
|
export { MapkaMapOptions as MapOptions } from "./map.js";
|
|
10
10
|
export { MapkaExportControl, MapkaExportControlOptions, } from "./controls/MapkaExportControl.js";
|
|
11
11
|
export { MapkaDrawControl, MapkaDrawControlOptions, DrawMode, } from "./controls/MapkaDrawControl.js";
|
|
12
|
+
export { loadMarkerIcon } from "./modules/icons.js";
|
|
12
13
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,IAAI,UAAU,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,QAAQ,GACT,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,IAAI,UAAU,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,QAAQ,GACT,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -8,3 +8,4 @@ export * from "./constants/styles.js";
|
|
|
8
8
|
export { MapkaMap as Map } from "./map.js";
|
|
9
9
|
export { MapkaExportControl, } from "./controls/MapkaExportControl.js";
|
|
10
10
|
export { MapkaDrawControl, } from "./controls/MapkaDrawControl.js";
|
|
11
|
+
export { loadMarkerIcon } from "./modules/icons.js";
|
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;AAW1C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EAGL,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAChC;AA0BD,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACrC,SAAS,EAAE,WAAW,CAAC;IACvB,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,UAAU,MAAM;IACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,QAAS,SAAQ,UAAU,CAAC,GAAG;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAU;IAErB,MAAM,EAAE,MAAM,CAAW;IACzB,OAAO,EAAE,cAAc,EAAE,CAAM;IAE/B,SAAS,EAAE,MAAM,CAAK;IACtB,YAAY,EAAE,OAAO,CAAQ;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAM;gBAEjB,
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAW1C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EAGL,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAChC;AA0BD,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACrC,SAAS,EAAE,WAAW,CAAC;IACvB,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,UAAU,MAAM;IACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,QAAS,SAAQ,UAAU,CAAC,GAAG;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAU;IAErB,MAAM,EAAE,MAAM,CAAW;IACzB,OAAO,EAAE,cAAc,EAAE,CAAM;IAE/B,SAAS,EAAE,MAAM,CAAK;IACtB,YAAY,EAAE,OAAO,CAAQ;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAM;gBAEjB,EACjB,gBAAgB,EAChB,MAAM,EACN,SAAa,EACb,YAAmB,EACnB,GAAG,OAAO,EACX,EAAE,eAAe;IA0BX,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,aAAa;IAIb,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,iBAAiB,EAAE;IAIxD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE;IAIhC,WAAW,CAAC,KAAK,EAAE,iBAAiB;IAIpC,SAAS;IAIT,YAAY;IAIN,MAAM,CAAC,OAAO,CAAC,EAAE,kBAAkB;IAIzC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAIrE"}
|
package/lib/modules/icons.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { MapkaMap } from "../map.js";
|
|
2
2
|
import type { MapStyleImageMissingEvent } from "maplibre-gl";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
4
|
+
* Fetch an icon's SVG source from the Mapka API.
|
|
5
|
+
* Batched and cached across callers; concurrent requests for the same
|
|
6
|
+
* id share one fetch.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadMarkerIcon(id: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Load any icons that are missing from the map from the Mapka API.
|
|
11
|
+
* @see https://github.com/mapbox/mapbox-gl-js/issues/5529
|
|
8
12
|
*/
|
|
9
13
|
export declare function loadLayersIcons(map: MapkaMap, event: MapStyleImageMissingEvent): void;
|
|
10
14
|
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/modules/icons.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/modules/icons.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AA8C7D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,yBAAyB,QAiB9E"}
|
package/lib/modules/icons.js
CHANGED
|
@@ -1,43 +1,81 @@
|
|
|
1
|
+
import ky from "ky";
|
|
1
2
|
import { debounce, uniq } from "es-toolkit";
|
|
2
3
|
import { getMapkaUrl } from "../utils/url.js";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
const svgCache = new Map();
|
|
5
|
+
const pendingResolvers = new Map();
|
|
6
|
+
let pendingIds = [];
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
+
* Debounced batch fetch: pulls unique pending ids, hits the icons API
|
|
9
|
+
* in one request, populates svgCache, and resolves waiting callers.
|
|
8
10
|
*/
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
+
const flushIcons = debounce(() => {
|
|
12
|
+
const idsToFetch = uniq(pendingIds).filter((id) => !svgCache.has(id));
|
|
13
|
+
if (idsToFetch.length === 0)
|
|
11
14
|
return;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const search = new URLSearchParams(iconsToLoad.map((id) => ["ids", id]));
|
|
20
|
-
fetch(`${getMapkaUrl()}/v1/icons?${search}`)
|
|
21
|
-
.then((response) => response.json())
|
|
15
|
+
pendingIds = [];
|
|
16
|
+
ky.get(`${getMapkaUrl()}/v1/icons`, {
|
|
17
|
+
searchParams: idsToFetch.map((id) => ["ids", id]),
|
|
18
|
+
})
|
|
19
|
+
.json()
|
|
22
20
|
.then((data) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
for (const { id, svg } of data) {
|
|
22
|
+
svgCache.set(id, svg);
|
|
23
|
+
const resolver = pendingResolvers.get(id);
|
|
24
|
+
if (resolver) {
|
|
25
|
+
resolver.resolve(svg);
|
|
26
|
+
pendingResolvers.delete(id);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.catch((err) => {
|
|
31
|
+
for (const id of idsToFetch) {
|
|
32
|
+
const resolver = pendingResolvers.get(id);
|
|
33
|
+
if (resolver) {
|
|
34
|
+
resolver.reject(err);
|
|
35
|
+
pendingResolvers.delete(id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
28
38
|
});
|
|
29
39
|
}, 50);
|
|
30
40
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
41
|
+
* Fetch an icon's SVG source from the Mapka API.
|
|
42
|
+
* Batched and cached across callers; concurrent requests for the same
|
|
43
|
+
* id share one fetch.
|
|
44
|
+
*/
|
|
45
|
+
export function loadMarkerIcon(id) {
|
|
46
|
+
const cached = svgCache.get(id);
|
|
47
|
+
if (cached)
|
|
48
|
+
return Promise.resolve(cached);
|
|
49
|
+
const existing = pendingResolvers.get(id);
|
|
50
|
+
if (existing)
|
|
51
|
+
return existing.promise;
|
|
52
|
+
const resolver = Promise.withResolvers();
|
|
53
|
+
pendingResolvers.set(id, resolver);
|
|
54
|
+
pendingIds.push(id);
|
|
55
|
+
flushIcons();
|
|
56
|
+
return resolver.promise;
|
|
57
|
+
}
|
|
58
|
+
const isStyleImage = (id) => id.includes(":");
|
|
59
|
+
/**
|
|
60
|
+
* Load any icons that are missing from the map from the Mapka API.
|
|
61
|
+
* @see https://github.com/mapbox/mapbox-gl-js/issues/5529
|
|
35
62
|
*/
|
|
36
63
|
export function loadLayersIcons(map, event) {
|
|
37
|
-
if (event.id
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
if (map.hasImage(event.id) || !isStyleImage(event.id))
|
|
65
|
+
return;
|
|
66
|
+
loadMarkerIcon(event.id)
|
|
67
|
+
.then((svg) => {
|
|
68
|
+
if (map.hasImage(event.id))
|
|
69
|
+
return;
|
|
70
|
+
const img = new Image(15, 15);
|
|
71
|
+
img.onload = () => {
|
|
72
|
+
if (!map.hasImage(event.id)) {
|
|
73
|
+
map.addImage(event.id, img);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
img.src = `data:image/svg+xml;charset=utf-8;base64,${btoa(svg)}`;
|
|
77
|
+
})
|
|
78
|
+
.catch((err) => {
|
|
79
|
+
map.logger.warn(`[mapka] Failed to load layer icon "${event.id}":`, err);
|
|
80
|
+
});
|
|
43
81
|
}
|
|
@@ -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":"AAIA,OAAO,KAAK,EAAyB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAwB7D,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAElD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAE/E;AAqID,wBAAgB,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAqBpF;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,aAAa,CAAC,GAAG,EAAE,QAAQ,QAK1C;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,6 +1,12 @@
|
|
|
1
1
|
import { Marker } from "maplibre-gl";
|
|
2
2
|
import { get } from "es-toolkit/compat";
|
|
3
3
|
import { remove } from "es-toolkit";
|
|
4
|
+
import { loadMarkerIcon } from "./icons.js";
|
|
5
|
+
/**
|
|
6
|
+
* Offset for the default pin so the tip sits on the LngLat anchor point.
|
|
7
|
+
* Value taken from maplibre-gl-js: (shadow translate-y + ellipse cy) - (height/2) ≈ 14.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_PIN_OFFSET = [0, -14];
|
|
4
10
|
/**
|
|
5
11
|
* Default marker offset
|
|
6
12
|
* @see https://github.com/maplibre/maplibre-gl-js/blob/master/src/ui/marker.ts#L457
|
|
@@ -90,10 +96,57 @@ function setupMarkerPopupListeners(map, marker, popup, options) {
|
|
|
90
96
|
});
|
|
91
97
|
}
|
|
92
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Apply `color` (as SVG `fill`) to the fetched icon SVG inside `element`.
|
|
101
|
+
*
|
|
102
|
+
* Override every descendant whose `fill` attribute is set and not `"none"`,
|
|
103
|
+
* then set `fill` on the root `<svg>` itself so paths that omit the
|
|
104
|
+
* attribute (common in maki — they inherit the browser default) pick up the
|
|
105
|
+
* user color via SVG cascading. `fill="none"` is preserved so outline-only
|
|
106
|
+
* shapes keep their transparency.
|
|
107
|
+
*
|
|
108
|
+
* Only invoked for icon markers; the default maplibre pin handles its own
|
|
109
|
+
* color via `MarkerOptions.color`.
|
|
110
|
+
*/
|
|
111
|
+
function applyMarkerColors(element, color) {
|
|
112
|
+
if (!color) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
for (const el of element.querySelectorAll('[fill]:not([fill="none"])')) {
|
|
116
|
+
el.setAttribute("fill", color);
|
|
117
|
+
}
|
|
118
|
+
const svg = element.querySelector("svg");
|
|
119
|
+
if (svg && !svg.hasAttribute("fill")) {
|
|
120
|
+
svg.setAttribute("fill", color);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function createMarkerElement(currentMap, options) {
|
|
124
|
+
const { color, icon } = options;
|
|
125
|
+
if (!icon) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const element = document.createElement("div");
|
|
129
|
+
element.className = "mapka-marker-icon";
|
|
130
|
+
element.dataset.iconId = icon;
|
|
131
|
+
loadMarkerIcon(icon)
|
|
132
|
+
.then((svg) => {
|
|
133
|
+
element.innerHTML = svg;
|
|
134
|
+
applyMarkerColors(element, color);
|
|
135
|
+
})
|
|
136
|
+
.catch((err) => {
|
|
137
|
+
currentMap.logger.warn(`[mapka] Failed to load marker icon "${icon}":`, err);
|
|
138
|
+
});
|
|
139
|
+
return element;
|
|
140
|
+
}
|
|
93
141
|
export function addMarkers(currentMap, markersOptions) {
|
|
94
142
|
for (const markerOptions of markersOptions) {
|
|
95
|
-
const { lngLat, popup, ...
|
|
96
|
-
const
|
|
143
|
+
const { lngLat, popup, icon, offset = DEFAULT_PIN_OFFSET, ...rest } = markerOptions;
|
|
144
|
+
const markerOpts = {
|
|
145
|
+
...rest,
|
|
146
|
+
element: createMarkerElement(currentMap, markerOptions),
|
|
147
|
+
offset,
|
|
148
|
+
};
|
|
149
|
+
const newMarker = new Marker(markerOpts).setLngLat(lngLat).addTo(currentMap);
|
|
97
150
|
currentMap.markers.push({
|
|
98
151
|
id: getMarkerId(markerOptions),
|
|
99
152
|
options: markerOptions,
|
|
@@ -1 +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;
|
|
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;AAiJpE,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"}
|