@premiate/strapi-plugin-maplibre-field 1.0.6

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.

Potentially problematic release.


This version of @premiate/strapi-plugin-maplibre-field might be problematic. Click here for more details.

Files changed (47) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +23 -0
  3. package/README.md +781 -0
  4. package/dist/_chunks/de-CGU2cyif.mjs +16 -0
  5. package/dist/_chunks/de-Dq_t3Z6M.js +16 -0
  6. package/dist/_chunks/en-BxxNWf9i.mjs +16 -0
  7. package/dist/_chunks/en-CgSPA-1L.js +16 -0
  8. package/dist/_chunks/es-B_cPv3G5.mjs +16 -0
  9. package/dist/_chunks/es-Sgja1XAa.js +16 -0
  10. package/dist/_chunks/fr-B3JIzyzo.js +16 -0
  11. package/dist/_chunks/fr-Dw5wEoDC.mjs +16 -0
  12. package/dist/_chunks/index-BF5T-kqa.mjs +171 -0
  13. package/dist/_chunks/index-BNnkn7JG.mjs +1778 -0
  14. package/dist/_chunks/index-CGJogtZr.js +1799 -0
  15. package/dist/_chunks/index-nbk0hg-O.js +170 -0
  16. package/dist/_chunks/it-BgWDIXzn.js +16 -0
  17. package/dist/_chunks/it-CoUEVPt6.mjs +16 -0
  18. package/dist/admin/index.js +3 -0
  19. package/dist/admin/index.mjs +4 -0
  20. package/dist/admin/src/components/Initializer.d.ts +6 -0
  21. package/dist/admin/src/components/MapInput/basemap-control.d.ts +8 -0
  22. package/dist/admin/src/components/MapInput/credits-control.d.ts +10 -0
  23. package/dist/admin/src/components/MapInput/geocoder-control.d.ts +20 -0
  24. package/dist/admin/src/components/MapInput/index.d.ts +19 -0
  25. package/dist/admin/src/components/MapInput/layer-control.d.ts +18 -0
  26. package/dist/admin/src/components/PluginIcon.d.ts +2 -0
  27. package/dist/admin/src/hooks/usePluginConfig.d.ts +2 -0
  28. package/dist/admin/src/index.d.ts +16 -0
  29. package/dist/admin/src/mutations/mutateEditViewHook.d.ts +30 -0
  30. package/dist/admin/src/services/poi-service.d.ts +160 -0
  31. package/dist/admin/src/utils/getTrad.d.ts +2 -0
  32. package/dist/admin/src/utils/pluginId.d.ts +2 -0
  33. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  34. package/dist/server/index.js +107 -0
  35. package/dist/server/index.mjs +108 -0
  36. package/dist/server/src/bootstrap.d.ts +2 -0
  37. package/dist/server/src/config/index.d.ts +61 -0
  38. package/dist/server/src/config/schema.d.ts +58 -0
  39. package/dist/server/src/controllers/config.d.ts +7 -0
  40. package/dist/server/src/controllers/index.d.ts +8 -0
  41. package/dist/server/src/destroy.d.ts +5 -0
  42. package/dist/server/src/index.d.ts +85 -0
  43. package/dist/server/src/register.d.ts +5 -0
  44. package/dist/server/src/routes/index.d.ts +9 -0
  45. package/dist/server/src/types/config.d.ts +26 -0
  46. package/logo.png +0 -0
  47. package/package.json +99 -0
@@ -0,0 +1,1778 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { useState, useEffect, useRef } from "react";
4
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
5
+ import MapLibreGeocoder from "@maplibre/maplibre-gl-geocoder";
6
+ import maplibregl from "maplibre-gl";
7
+ import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css";
8
+ import Map, { useControl, FullscreenControl, NavigationControl, GeolocateControl, Source, Layer, Marker } from "react-map-gl/maplibre";
9
+ import { Flex, Typography, Grid, Field } from "@strapi/design-system";
10
+ import { p as pluginId } from "./index-BF5T-kqa.mjs";
11
+ import { Protocol } from "pmtiles";
12
+ import "maplibre-gl/dist/maplibre-gl.css";
13
+ var __assign = function() {
14
+ __assign = Object.assign || function __assign2(t) {
15
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
16
+ s = arguments[i];
17
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
18
+ }
19
+ return t;
20
+ };
21
+ return __assign.apply(this, arguments);
22
+ };
23
+ function __rest(s, e) {
24
+ var t = {};
25
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
26
+ t[p] = s[p];
27
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
28
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
29
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
30
+ t[p[i]] = s[p[i]];
31
+ }
32
+ return t;
33
+ }
34
+ typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
35
+ var e = new Error(message);
36
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
37
+ };
38
+ var reactIs$1 = { exports: {} };
39
+ var reactIs_production_min = {};
40
+ /** @license React v16.13.1
41
+ * react-is.production.min.js
42
+ *
43
+ * Copyright (c) Facebook, Inc. and its affiliates.
44
+ *
45
+ * This source code is licensed under the MIT license found in the
46
+ * LICENSE file in the root directory of this source tree.
47
+ */
48
+ var hasRequiredReactIs_production_min;
49
+ function requireReactIs_production_min() {
50
+ if (hasRequiredReactIs_production_min) return reactIs_production_min;
51
+ hasRequiredReactIs_production_min = 1;
52
+ var b = "function" === typeof Symbol && Symbol.for, c = b ? Symbol.for("react.element") : 60103, d = b ? Symbol.for("react.portal") : 60106, e = b ? Symbol.for("react.fragment") : 60107, f = b ? Symbol.for("react.strict_mode") : 60108, g = b ? Symbol.for("react.profiler") : 60114, h = b ? Symbol.for("react.provider") : 60109, k = b ? Symbol.for("react.context") : 60110, l = b ? Symbol.for("react.async_mode") : 60111, m = b ? Symbol.for("react.concurrent_mode") : 60111, n = b ? Symbol.for("react.forward_ref") : 60112, p = b ? Symbol.for("react.suspense") : 60113, q = b ? Symbol.for("react.suspense_list") : 60120, r = b ? Symbol.for("react.memo") : 60115, t = b ? Symbol.for("react.lazy") : 60116, v = b ? Symbol.for("react.block") : 60121, w = b ? Symbol.for("react.fundamental") : 60117, x = b ? Symbol.for("react.responder") : 60118, y = b ? Symbol.for("react.scope") : 60119;
53
+ function z(a) {
54
+ if ("object" === typeof a && null !== a) {
55
+ var u = a.$$typeof;
56
+ switch (u) {
57
+ case c:
58
+ switch (a = a.type, a) {
59
+ case l:
60
+ case m:
61
+ case e:
62
+ case g:
63
+ case f:
64
+ case p:
65
+ return a;
66
+ default:
67
+ switch (a = a && a.$$typeof, a) {
68
+ case k:
69
+ case n:
70
+ case t:
71
+ case r:
72
+ case h:
73
+ return a;
74
+ default:
75
+ return u;
76
+ }
77
+ }
78
+ case d:
79
+ return u;
80
+ }
81
+ }
82
+ }
83
+ function A(a) {
84
+ return z(a) === m;
85
+ }
86
+ reactIs_production_min.AsyncMode = l;
87
+ reactIs_production_min.ConcurrentMode = m;
88
+ reactIs_production_min.ContextConsumer = k;
89
+ reactIs_production_min.ContextProvider = h;
90
+ reactIs_production_min.Element = c;
91
+ reactIs_production_min.ForwardRef = n;
92
+ reactIs_production_min.Fragment = e;
93
+ reactIs_production_min.Lazy = t;
94
+ reactIs_production_min.Memo = r;
95
+ reactIs_production_min.Portal = d;
96
+ reactIs_production_min.Profiler = g;
97
+ reactIs_production_min.StrictMode = f;
98
+ reactIs_production_min.Suspense = p;
99
+ reactIs_production_min.isAsyncMode = function(a) {
100
+ return A(a) || z(a) === l;
101
+ };
102
+ reactIs_production_min.isConcurrentMode = A;
103
+ reactIs_production_min.isContextConsumer = function(a) {
104
+ return z(a) === k;
105
+ };
106
+ reactIs_production_min.isContextProvider = function(a) {
107
+ return z(a) === h;
108
+ };
109
+ reactIs_production_min.isElement = function(a) {
110
+ return "object" === typeof a && null !== a && a.$$typeof === c;
111
+ };
112
+ reactIs_production_min.isForwardRef = function(a) {
113
+ return z(a) === n;
114
+ };
115
+ reactIs_production_min.isFragment = function(a) {
116
+ return z(a) === e;
117
+ };
118
+ reactIs_production_min.isLazy = function(a) {
119
+ return z(a) === t;
120
+ };
121
+ reactIs_production_min.isMemo = function(a) {
122
+ return z(a) === r;
123
+ };
124
+ reactIs_production_min.isPortal = function(a) {
125
+ return z(a) === d;
126
+ };
127
+ reactIs_production_min.isProfiler = function(a) {
128
+ return z(a) === g;
129
+ };
130
+ reactIs_production_min.isStrictMode = function(a) {
131
+ return z(a) === f;
132
+ };
133
+ reactIs_production_min.isSuspense = function(a) {
134
+ return z(a) === p;
135
+ };
136
+ reactIs_production_min.isValidElementType = function(a) {
137
+ return "string" === typeof a || "function" === typeof a || a === e || a === m || a === g || a === f || a === p || a === q || "object" === typeof a && null !== a && (a.$$typeof === t || a.$$typeof === r || a.$$typeof === h || a.$$typeof === k || a.$$typeof === n || a.$$typeof === w || a.$$typeof === x || a.$$typeof === y || a.$$typeof === v);
138
+ };
139
+ reactIs_production_min.typeOf = z;
140
+ return reactIs_production_min;
141
+ }
142
+ var reactIs_development = {};
143
+ /** @license React v16.13.1
144
+ * react-is.development.js
145
+ *
146
+ * Copyright (c) Facebook, Inc. and its affiliates.
147
+ *
148
+ * This source code is licensed under the MIT license found in the
149
+ * LICENSE file in the root directory of this source tree.
150
+ */
151
+ var hasRequiredReactIs_development;
152
+ function requireReactIs_development() {
153
+ if (hasRequiredReactIs_development) return reactIs_development;
154
+ hasRequiredReactIs_development = 1;
155
+ if (process.env.NODE_ENV !== "production") {
156
+ (function() {
157
+ var hasSymbol = typeof Symbol === "function" && Symbol.for;
158
+ var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103;
159
+ var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106;
160
+ var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107;
161
+ var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108;
162
+ var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114;
163
+ var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109;
164
+ var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110;
165
+ var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 60111;
166
+ var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for("react.concurrent_mode") : 60111;
167
+ var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112;
168
+ var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113;
169
+ var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for("react.suspense_list") : 60120;
170
+ var REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115;
171
+ var REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116;
172
+ var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121;
173
+ var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for("react.fundamental") : 60117;
174
+ var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for("react.responder") : 60118;
175
+ var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for("react.scope") : 60119;
176
+ function isValidElementType(type) {
177
+ return typeof type === "string" || typeof type === "function" || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
178
+ type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === "object" && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
179
+ }
180
+ function typeOf(object) {
181
+ if (typeof object === "object" && object !== null) {
182
+ var $$typeof = object.$$typeof;
183
+ switch ($$typeof) {
184
+ case REACT_ELEMENT_TYPE:
185
+ var type = object.type;
186
+ switch (type) {
187
+ case REACT_ASYNC_MODE_TYPE:
188
+ case REACT_CONCURRENT_MODE_TYPE:
189
+ case REACT_FRAGMENT_TYPE:
190
+ case REACT_PROFILER_TYPE:
191
+ case REACT_STRICT_MODE_TYPE:
192
+ case REACT_SUSPENSE_TYPE:
193
+ return type;
194
+ default:
195
+ var $$typeofType = type && type.$$typeof;
196
+ switch ($$typeofType) {
197
+ case REACT_CONTEXT_TYPE:
198
+ case REACT_FORWARD_REF_TYPE:
199
+ case REACT_LAZY_TYPE:
200
+ case REACT_MEMO_TYPE:
201
+ case REACT_PROVIDER_TYPE:
202
+ return $$typeofType;
203
+ default:
204
+ return $$typeof;
205
+ }
206
+ }
207
+ case REACT_PORTAL_TYPE:
208
+ return $$typeof;
209
+ }
210
+ }
211
+ return void 0;
212
+ }
213
+ var AsyncMode = REACT_ASYNC_MODE_TYPE;
214
+ var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
215
+ var ContextConsumer = REACT_CONTEXT_TYPE;
216
+ var ContextProvider = REACT_PROVIDER_TYPE;
217
+ var Element = REACT_ELEMENT_TYPE;
218
+ var ForwardRef = REACT_FORWARD_REF_TYPE;
219
+ var Fragment = REACT_FRAGMENT_TYPE;
220
+ var Lazy = REACT_LAZY_TYPE;
221
+ var Memo = REACT_MEMO_TYPE;
222
+ var Portal = REACT_PORTAL_TYPE;
223
+ var Profiler = REACT_PROFILER_TYPE;
224
+ var StrictMode = REACT_STRICT_MODE_TYPE;
225
+ var Suspense = REACT_SUSPENSE_TYPE;
226
+ var hasWarnedAboutDeprecatedIsAsyncMode = false;
227
+ function isAsyncMode(object) {
228
+ {
229
+ if (!hasWarnedAboutDeprecatedIsAsyncMode) {
230
+ hasWarnedAboutDeprecatedIsAsyncMode = true;
231
+ console["warn"]("The ReactIs.isAsyncMode() alias has been deprecated, and will be removed in React 17+. Update your code to use ReactIs.isConcurrentMode() instead. It has the exact same API.");
232
+ }
233
+ }
234
+ return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
235
+ }
236
+ function isConcurrentMode(object) {
237
+ return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
238
+ }
239
+ function isContextConsumer(object) {
240
+ return typeOf(object) === REACT_CONTEXT_TYPE;
241
+ }
242
+ function isContextProvider(object) {
243
+ return typeOf(object) === REACT_PROVIDER_TYPE;
244
+ }
245
+ function isElement(object) {
246
+ return typeof object === "object" && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
247
+ }
248
+ function isForwardRef(object) {
249
+ return typeOf(object) === REACT_FORWARD_REF_TYPE;
250
+ }
251
+ function isFragment(object) {
252
+ return typeOf(object) === REACT_FRAGMENT_TYPE;
253
+ }
254
+ function isLazy(object) {
255
+ return typeOf(object) === REACT_LAZY_TYPE;
256
+ }
257
+ function isMemo(object) {
258
+ return typeOf(object) === REACT_MEMO_TYPE;
259
+ }
260
+ function isPortal(object) {
261
+ return typeOf(object) === REACT_PORTAL_TYPE;
262
+ }
263
+ function isProfiler(object) {
264
+ return typeOf(object) === REACT_PROFILER_TYPE;
265
+ }
266
+ function isStrictMode(object) {
267
+ return typeOf(object) === REACT_STRICT_MODE_TYPE;
268
+ }
269
+ function isSuspense(object) {
270
+ return typeOf(object) === REACT_SUSPENSE_TYPE;
271
+ }
272
+ reactIs_development.AsyncMode = AsyncMode;
273
+ reactIs_development.ConcurrentMode = ConcurrentMode;
274
+ reactIs_development.ContextConsumer = ContextConsumer;
275
+ reactIs_development.ContextProvider = ContextProvider;
276
+ reactIs_development.Element = Element;
277
+ reactIs_development.ForwardRef = ForwardRef;
278
+ reactIs_development.Fragment = Fragment;
279
+ reactIs_development.Lazy = Lazy;
280
+ reactIs_development.Memo = Memo;
281
+ reactIs_development.Portal = Portal;
282
+ reactIs_development.Profiler = Profiler;
283
+ reactIs_development.StrictMode = StrictMode;
284
+ reactIs_development.Suspense = Suspense;
285
+ reactIs_development.isAsyncMode = isAsyncMode;
286
+ reactIs_development.isConcurrentMode = isConcurrentMode;
287
+ reactIs_development.isContextConsumer = isContextConsumer;
288
+ reactIs_development.isContextProvider = isContextProvider;
289
+ reactIs_development.isElement = isElement;
290
+ reactIs_development.isForwardRef = isForwardRef;
291
+ reactIs_development.isFragment = isFragment;
292
+ reactIs_development.isLazy = isLazy;
293
+ reactIs_development.isMemo = isMemo;
294
+ reactIs_development.isPortal = isPortal;
295
+ reactIs_development.isProfiler = isProfiler;
296
+ reactIs_development.isStrictMode = isStrictMode;
297
+ reactIs_development.isSuspense = isSuspense;
298
+ reactIs_development.isValidElementType = isValidElementType;
299
+ reactIs_development.typeOf = typeOf;
300
+ })();
301
+ }
302
+ return reactIs_development;
303
+ }
304
+ if (process.env.NODE_ENV === "production") {
305
+ reactIs$1.exports = requireReactIs_production_min();
306
+ } else {
307
+ reactIs$1.exports = requireReactIs_development();
308
+ }
309
+ var reactIsExports = reactIs$1.exports;
310
+ var reactIs = reactIsExports;
311
+ var FORWARD_REF_STATICS = {
312
+ "$$typeof": true,
313
+ render: true,
314
+ defaultProps: true,
315
+ displayName: true,
316
+ propTypes: true
317
+ };
318
+ var MEMO_STATICS = {
319
+ "$$typeof": true,
320
+ compare: true,
321
+ defaultProps: true,
322
+ displayName: true,
323
+ propTypes: true,
324
+ type: true
325
+ };
326
+ var TYPE_STATICS = {};
327
+ TYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS;
328
+ TYPE_STATICS[reactIs.Memo] = MEMO_STATICS;
329
+ function invariant(condition, message, Err) {
330
+ if (Err === void 0) {
331
+ Err = Error;
332
+ }
333
+ if (!condition) {
334
+ throw new Err(message);
335
+ }
336
+ }
337
+ var defaultErrorHandler = function(error) {
338
+ if (process.env.NODE_ENV !== "production") {
339
+ console.error(error);
340
+ }
341
+ };
342
+ var defaultWarnHandler = function(warning) {
343
+ if (process.env.NODE_ENV !== "production") {
344
+ console.warn(warning);
345
+ }
346
+ };
347
+ var DEFAULT_INTL_CONFIG = {
348
+ formats: {},
349
+ messages: {},
350
+ timeZone: void 0,
351
+ defaultLocale: "en",
352
+ defaultFormats: {},
353
+ fallbackOnEmptyString: true,
354
+ onError: defaultErrorHandler,
355
+ onWarn: defaultWarnHandler
356
+ };
357
+ function invariantIntlContext(intl) {
358
+ invariant(intl, "[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.");
359
+ }
360
+ __assign(__assign({}, DEFAULT_INTL_CONFIG), { textComponent: React.Fragment });
361
+ var IntlContext = typeof window !== "undefined" && !window.__REACT_INTL_BYPASS_GLOBAL_CONTEXT__ ? window.__REACT_INTL_CONTEXT__ || (window.__REACT_INTL_CONTEXT__ = React.createContext(null)) : React.createContext(null);
362
+ IntlContext.Consumer;
363
+ IntlContext.Provider;
364
+ var Context = IntlContext;
365
+ function useIntl() {
366
+ var intl = React.useContext(Context);
367
+ invariantIntlContext(intl);
368
+ return intl;
369
+ }
370
+ var DisplayName;
371
+ (function(DisplayName2) {
372
+ DisplayName2["formatDate"] = "FormattedDate";
373
+ DisplayName2["formatTime"] = "FormattedTime";
374
+ DisplayName2["formatNumber"] = "FormattedNumber";
375
+ DisplayName2["formatList"] = "FormattedList";
376
+ DisplayName2["formatDisplayName"] = "FormattedDisplayName";
377
+ })(DisplayName || (DisplayName = {}));
378
+ var DisplayNameParts;
379
+ (function(DisplayNameParts2) {
380
+ DisplayNameParts2["formatDate"] = "FormattedDateParts";
381
+ DisplayNameParts2["formatTime"] = "FormattedTimeParts";
382
+ DisplayNameParts2["formatNumber"] = "FormattedNumberParts";
383
+ DisplayNameParts2["formatList"] = "FormattedListParts";
384
+ })(DisplayNameParts || (DisplayNameParts = {}));
385
+ function createFormattedDateTimePartsComponent(name) {
386
+ var ComponentParts = function(props) {
387
+ var intl = useIntl();
388
+ var value = props.value, children = props.children, formatProps = __rest(props, ["value", "children"]);
389
+ var date = typeof value === "string" ? new Date(value || 0) : value;
390
+ var formattedParts = name === "formatDate" ? intl.formatDateToParts(date, formatProps) : intl.formatTimeToParts(date, formatProps);
391
+ return children(formattedParts);
392
+ };
393
+ ComponentParts.displayName = DisplayNameParts[name];
394
+ return ComponentParts;
395
+ }
396
+ function createFormattedComponent(name) {
397
+ var Component = function(props) {
398
+ var intl = useIntl();
399
+ var value = props.value, children = props.children, formatProps = __rest(
400
+ props,
401
+ ["value", "children"]
402
+ );
403
+ var formattedValue = intl[name](value, formatProps);
404
+ if (typeof children === "function") {
405
+ return children(formattedValue);
406
+ }
407
+ var Text = intl.textComponent || React.Fragment;
408
+ return React.createElement(Text, null, formattedValue);
409
+ };
410
+ Component.displayName = DisplayName[name];
411
+ return Component;
412
+ }
413
+ createFormattedComponent("formatDate");
414
+ createFormattedComponent("formatTime");
415
+ createFormattedComponent("formatNumber");
416
+ createFormattedComponent("formatList");
417
+ createFormattedComponent("formatDisplayName");
418
+ createFormattedDateTimePartsComponent("formatDate");
419
+ createFormattedDateTimePartsComponent("formatTime");
420
+ const DEFAULT_CONFIG = {
421
+ mapStyles: [
422
+ {
423
+ id: "default",
424
+ name: "Default",
425
+ url: "https://demotiles.maplibre.org/style.json",
426
+ isDefault: true
427
+ }
428
+ ],
429
+ defaultZoom: 4.5,
430
+ defaultCenter: [0, 0],
431
+ // Null Island - fallback if not configured
432
+ geocodingProvider: "nominatim",
433
+ nominatimUrl: "https://nominatim.openstreetmap.org"
434
+ };
435
+ const usePluginConfig = () => {
436
+ const [config, setConfig] = useState(DEFAULT_CONFIG);
437
+ const [loading, setLoading] = useState(true);
438
+ const { get } = useFetchClient();
439
+ useEffect(() => {
440
+ const fetchConfig = async () => {
441
+ try {
442
+ const response = await get("/maplibre-field/config");
443
+ console.log("[MapLibre Hook] Fetched config from API:", response.data);
444
+ if (response.data) {
445
+ setConfig({ ...DEFAULT_CONFIG, ...response.data });
446
+ }
447
+ } catch (error) {
448
+ console.error("[MapLibre Hook] Failed to fetch config:", error);
449
+ } finally {
450
+ setLoading(false);
451
+ }
452
+ };
453
+ fetchConfig();
454
+ }, [get]);
455
+ if (loading) {
456
+ console.log("[MapLibre Hook] Loading config...");
457
+ }
458
+ return config;
459
+ };
460
+ const USER_AGENT$2 = "strapi-plugin-maplibre-field/1.0.0 (Strapi CMS)";
461
+ function createLocationFeature(coordinates, properties = {}) {
462
+ const cleanProperties = Object.fromEntries(
463
+ Object.entries(properties).filter(([, v]) => v != null && v !== "")
464
+ );
465
+ return {
466
+ type: "Feature",
467
+ geometry: {
468
+ type: "Point",
469
+ coordinates
470
+ },
471
+ properties: cleanProperties
472
+ };
473
+ }
474
+ function calculateDistance(coord1, coord2) {
475
+ const R = 6371e3;
476
+ const φ1 = coord1[1] * Math.PI / 180;
477
+ const φ2 = coord2[1] * Math.PI / 180;
478
+ const Δφ = (coord2[1] - coord1[1]) * Math.PI / 180;
479
+ const Δλ = (coord2[0] - coord1[0]) * Math.PI / 180;
480
+ const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
481
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
482
+ return R * c;
483
+ }
484
+ async function queryCustomAPI(apiUrl, searchQuery) {
485
+ try {
486
+ console.log(`[POI Service] Fetching from: ${apiUrl}`);
487
+ const response = await fetch(apiUrl);
488
+ if (!response.ok) {
489
+ console.error(`[POI Service] HTTP error for ${apiUrl}: ${response.status} ${response.statusText}`);
490
+ throw new Error(`HTTP error! status: ${response.status}`);
491
+ }
492
+ const data = await response.json();
493
+ if (!data || data.type !== "FeatureCollection" || !Array.isArray(data.features)) {
494
+ console.error(`[POI Service] Invalid GeoJSON from ${apiUrl}`);
495
+ throw new Error("Invalid GeoJSON response format");
496
+ }
497
+ console.log(`[POI Service] Loaded ${data.features.length} features from ${apiUrl}`);
498
+ let features = data.features;
499
+ if (searchQuery && searchQuery.trim()) {
500
+ const query = searchQuery.toLowerCase();
501
+ features = features.filter((feature) => {
502
+ const name = feature.properties?.name;
503
+ return name && name.toLowerCase().includes(query);
504
+ });
505
+ }
506
+ return features;
507
+ } catch (error) {
508
+ console.error(`[POI Service] Failed to load from ${apiUrl}:`, error);
509
+ return [];
510
+ }
511
+ }
512
+ async function queryNominatim(lat, lng, radius, nominatimUrl) {
513
+ try {
514
+ const url = `${nominatimUrl}/reverse?format=jsonv2&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
515
+ console.log("[Nominatim] Querying:", url);
516
+ const response = await fetch(url, {
517
+ headers: {
518
+ "User-Agent": USER_AGENT$2
519
+ }
520
+ });
521
+ if (!response.ok) {
522
+ throw new Error(`HTTP error! status: ${response.status}`);
523
+ }
524
+ const data = await response.json();
525
+ console.log("[Nominatim] Response:", data);
526
+ if (!data) {
527
+ console.log("[Nominatim] No data returned");
528
+ return [];
529
+ }
530
+ const coordinates = [parseFloat(data.lon), parseFloat(data.lat)];
531
+ const distance = calculateDistance([lng, lat], coordinates);
532
+ console.log("[Nominatim] Distance calculated:", distance, "meters (radius:", radius, "m)");
533
+ console.log("[Nominatim] Click coords:", [lng, lat], "Result coords:", coordinates);
534
+ if (distance > radius) {
535
+ console.log("[Nominatim] POI outside radius, rejecting");
536
+ return [];
537
+ }
538
+ let poiName = data.name || data.display_name || "Unknown Location";
539
+ if (data.namedetails) {
540
+ poiName = data.namedetails.name || poiName;
541
+ }
542
+ console.log("[Nominatim] POI found:", poiName, "type:", data.type || data.class);
543
+ const poi = {
544
+ id: `nominatim-${data.place_id || Date.now()}`,
545
+ name: poiName,
546
+ type: data.type || data.class || "address",
547
+ coordinates,
548
+ address: data.display_name || "",
549
+ distance,
550
+ metadata: {
551
+ osm_id: data.osm_id,
552
+ osm_type: data.osm_type,
553
+ place_id: data.place_id,
554
+ addresstype: data.addresstype,
555
+ class: data.class,
556
+ category: data.category
557
+ },
558
+ source: "nominatim"
559
+ };
560
+ return [poi];
561
+ } catch (error) {
562
+ console.error("Nominatim query error:", error);
563
+ return [];
564
+ }
565
+ }
566
+ function geoJSONFeatureToPOI(feature, clickCoords, mapName, layerId) {
567
+ if (!feature.geometry || feature.geometry.type !== "Point") {
568
+ return null;
569
+ }
570
+ const coordinates = feature.geometry.coordinates;
571
+ const properties = feature.properties || {};
572
+ const name = properties.name || "Unnamed Location";
573
+ const poi = {
574
+ id: feature.id?.toString() || `custom-${Date.now()}-${Math.random()}`,
575
+ name,
576
+ type: properties.type || properties.sport || properties.leisure || "poi",
577
+ coordinates,
578
+ address: properties.address || "",
579
+ // Leave empty if not provided
580
+ metadata: properties,
581
+ source: "custom",
582
+ mapName,
583
+ // Include the custom map name
584
+ layerId
585
+ // Include the layer ID
586
+ };
587
+ if (clickCoords) {
588
+ poi.distance = calculateDistance(clickCoords, coordinates);
589
+ }
590
+ return poi;
591
+ }
592
+ function filterByDistance(features, clickCoords, radius) {
593
+ return features.filter((feature) => {
594
+ if (!feature.geometry || feature.geometry.type !== "Point") {
595
+ return false;
596
+ }
597
+ const featureCoords = feature.geometry.coordinates;
598
+ const distance = calculateDistance(clickCoords, featureCoords);
599
+ return distance <= radius;
600
+ });
601
+ }
602
+ function findNearestPOI(clickCoordinates, pois) {
603
+ if (!pois || pois.length === 0) {
604
+ return null;
605
+ }
606
+ let nearest = null;
607
+ let minDistance = Infinity;
608
+ for (const poi of pois) {
609
+ const distance = poi.distance ?? calculateDistance(clickCoordinates, poi.coordinates);
610
+ if (distance < minDistance) {
611
+ minDistance = distance;
612
+ nearest = { ...poi, distance };
613
+ }
614
+ }
615
+ return nearest;
616
+ }
617
+ async function searchPOIsForGeocoder(query, config) {
618
+ const results = [];
619
+ try {
620
+ if (config.customApiUrl) {
621
+ try {
622
+ const customFeatures = await queryCustomAPI(config.customApiUrl, query);
623
+ const customPOIs = customFeatures.map((feature) => geoJSONFeatureToPOI(feature, void 0, config.mapName, config.layerId)).filter((poi) => poi !== null).slice(0, 5);
624
+ results.push(...customPOIs);
625
+ } catch (error) {
626
+ console.warn("Custom API search failed:", error);
627
+ }
628
+ }
629
+ return results;
630
+ } catch (error) {
631
+ console.error("Search POIs error:", error);
632
+ return results;
633
+ }
634
+ }
635
+ async function searchNearbyPOIsForSnap(lat, lng, config) {
636
+ const results = [];
637
+ try {
638
+ const nominatimPOIs = await queryNominatim(
639
+ lat,
640
+ lng,
641
+ config.radius,
642
+ config.nominatimUrl
643
+ );
644
+ results.push(...nominatimPOIs);
645
+ if (config.customApiUrl) {
646
+ try {
647
+ const customFeatures = await queryCustomAPI(config.customApiUrl);
648
+ const nearbyFeatures = filterByDistance(
649
+ customFeatures,
650
+ [lng, lat],
651
+ config.radius
652
+ );
653
+ const customPOIs = nearbyFeatures.map((feature) => geoJSONFeatureToPOI(feature, [lng, lat], config.mapName, config.layerId)).filter((poi) => poi !== null);
654
+ results.push(...customPOIs);
655
+ } catch (error) {
656
+ console.warn("Custom API query failed, continuing with Nominatim only:", error);
657
+ }
658
+ }
659
+ return results;
660
+ } catch (error) {
661
+ console.error("Search nearby POIs error:", error);
662
+ return results;
663
+ }
664
+ }
665
+ async function queryPOIsForViewport(bounds, center, maxDisplay, config) {
666
+ const results = [];
667
+ try {
668
+ if (config.customApiUrl) {
669
+ try {
670
+ const customFeatures = await queryCustomAPI(config.customApiUrl);
671
+ const viewportFeatures = customFeatures.filter((feature) => {
672
+ if (!feature.geometry || feature.geometry.type !== "Point") {
673
+ return false;
674
+ }
675
+ const [lng, lat] = feature.geometry.coordinates;
676
+ return lat >= bounds.south && lat <= bounds.north && lng >= bounds.west && lng <= bounds.east;
677
+ });
678
+ const customPOIs = viewportFeatures.map((feature) => geoJSONFeatureToPOI(feature, center, config.mapName, config.layerId)).filter((poi) => poi !== null);
679
+ results.push(...customPOIs);
680
+ } catch (error) {
681
+ console.warn("Custom API viewport query failed:", error);
682
+ }
683
+ }
684
+ results.sort((a, b) => {
685
+ const distA = a.distance ?? calculateDistance(center, a.coordinates);
686
+ const distB = b.distance ?? calculateDistance(center, b.coordinates);
687
+ return distA - distB;
688
+ });
689
+ return results.slice(0, maxDisplay);
690
+ } catch (error) {
691
+ console.error("Query POIs for viewport error:", error);
692
+ return results;
693
+ }
694
+ }
695
+ const USER_AGENT$1 = "strapi-plugin-maplibre-field/1.0.0 (Strapi CMS)";
696
+ const GeocoderControl = ({
697
+ mapRef,
698
+ position = "top-left",
699
+ onResult
700
+ }) => {
701
+ const geocoderRef = useRef(null);
702
+ const config = usePluginConfig();
703
+ useEffect(() => {
704
+ if (!mapRef.current) return;
705
+ const map = mapRef.current.getMap();
706
+ if (!map || geocoderRef.current) return;
707
+ const geocoderApi = {
708
+ forwardGeocode: async (geocoderConfig) => {
709
+ const query = geocoderConfig.query;
710
+ if (typeof query !== "string" || !query.trim()) {
711
+ return { type: "FeatureCollection", features: [] };
712
+ }
713
+ try {
714
+ const results = [];
715
+ if (config.poiSources && config.poiSearchEnabled) {
716
+ const enabledSources = config.poiSources.filter((source) => source.enabled !== false);
717
+ for (const source of enabledSources) {
718
+ try {
719
+ const customPOIs = await searchPOIsForGeocoder(
720
+ query,
721
+ {
722
+ nominatimUrl: config.nominatimUrl || "https://nominatim.openstreetmap.org",
723
+ customApiUrl: source.apiUrl,
724
+ mapName: source.name,
725
+ radius: 100,
726
+ categories: []
727
+ }
728
+ );
729
+ const customFeatures = customPOIs.filter((poi) => poi.source === "custom").slice(0, 5).map((poi) => ({
730
+ type: "Feature",
731
+ geometry: {
732
+ type: "Point",
733
+ coordinates: poi.coordinates
734
+ },
735
+ place_name: poi.name,
736
+ properties: {
737
+ ...poi,
738
+ source: "custom",
739
+ poi_source_id: source.id
740
+ // For color lookup in render function
741
+ },
742
+ text: poi.name,
743
+ place_type: ["poi"],
744
+ center: poi.coordinates
745
+ }));
746
+ results.push(...customFeatures);
747
+ } catch (error) {
748
+ console.warn(`Custom API search failed for ${source.name}, continuing:`, error);
749
+ }
750
+ }
751
+ }
752
+ const nominatimResponse = await fetch(
753
+ `${config.nominatimUrl}/search?q=${encodeURIComponent(query)}&format=json&addressdetails=1&limit=5`,
754
+ {
755
+ headers: {
756
+ "User-Agent": USER_AGENT$1
757
+ }
758
+ }
759
+ );
760
+ if (nominatimResponse.ok) {
761
+ const nominatimData = await nominatimResponse.json();
762
+ const nominatimFeatures = nominatimData.map((result) => ({
763
+ type: "Feature",
764
+ geometry: {
765
+ type: "Point",
766
+ coordinates: [parseFloat(result.lon), parseFloat(result.lat)]
767
+ },
768
+ place_name: result.display_name,
769
+ properties: { ...result, source: "nominatim" },
770
+ text: result.display_name,
771
+ place_type: ["place"],
772
+ center: [parseFloat(result.lon), parseFloat(result.lat)]
773
+ }));
774
+ results.push(...nominatimFeatures);
775
+ }
776
+ return {
777
+ type: "FeatureCollection",
778
+ features: results
779
+ };
780
+ } catch (error) {
781
+ console.error("Geocoding error:", error);
782
+ return { type: "FeatureCollection", features: [] };
783
+ }
784
+ },
785
+ maplibregl
786
+ };
787
+ const geocoderOptions = {
788
+ marker: false,
789
+ showResultsWhileTyping: false,
790
+ // Require Enter key for Nominatim policy compliance
791
+ render: (item) => {
792
+ const properties = "properties" in item ? item.properties : void 0;
793
+ const source = properties?.source;
794
+ let dotColor = "#6c757d";
795
+ if (source === "custom") {
796
+ const poiSourceId = properties?.poi_source_id;
797
+ const poiSource = config.poiSources?.find((s) => s.id === poiSourceId);
798
+ dotColor = poiSource?.color || "#cc0000";
799
+ }
800
+ const escapeHtml = (str) => {
801
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
802
+ };
803
+ const placeName = "place_name" in item ? item.place_name : void 0;
804
+ const displayText = escapeHtml(item.text || placeName || "");
805
+ return `
806
+ <div class="maplibregl-ctrl-geocoder--suggestion">
807
+ <div class="maplibregl-ctrl-geocoder--suggestion-icon">
808
+ <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background-color:${dotColor};border:2px solid #ffffff;box-shadow:0 0 0 1px rgba(0,0,0,0.1);"></span>
809
+ </div>
810
+ <div class="maplibregl-ctrl-geocoder--suggestion-info">
811
+ <div class="maplibregl-ctrl-geocoder--suggestion-title">
812
+ ${displayText}
813
+ </div>
814
+ </div>
815
+ </div>
816
+ `;
817
+ }
818
+ };
819
+ const geocoder = new MapLibreGeocoder(geocoderApi, geocoderOptions);
820
+ if (onResult) {
821
+ geocoder.on("result", (evt) => {
822
+ onResult(evt);
823
+ });
824
+ }
825
+ map.addControl(geocoder, position);
826
+ geocoderRef.current = geocoder;
827
+ return () => {
828
+ if (geocoderRef.current && map) {
829
+ try {
830
+ map.removeControl(geocoderRef.current);
831
+ } catch (error) {
832
+ console.warn("Error removing geocoder control:", error);
833
+ }
834
+ geocoderRef.current = null;
835
+ }
836
+ };
837
+ }, [mapRef, position, onResult, config.nominatimUrl]);
838
+ return null;
839
+ };
840
+ class BasemapControl {
841
+ _map;
842
+ _container;
843
+ _styles;
844
+ _currentStyleUrl;
845
+ _onStyleChange;
846
+ constructor(styles, currentStyleUrl, onStyleChange) {
847
+ this._styles = styles;
848
+ this._currentStyleUrl = currentStyleUrl;
849
+ this._onStyleChange = onStyleChange;
850
+ }
851
+ onAdd(map) {
852
+ this._map = map;
853
+ this._container = document.createElement("div");
854
+ this._container.className = "maplibregl-ctrl maplibregl-ctrl-group";
855
+ this._container.style.display = "flex";
856
+ this._container.style.flexDirection = "row";
857
+ this._styles.forEach((style, index) => {
858
+ const button = document.createElement("button");
859
+ button.type = "button";
860
+ button.title = style.name;
861
+ button.setAttribute("aria-label", style.name);
862
+ const span = document.createElement("span");
863
+ span.textContent = style.name;
864
+ span.style.padding = "0 8px";
865
+ button.appendChild(span);
866
+ button.className = "maplibregl-ctrl-icon";
867
+ button.style.width = "auto";
868
+ button.style.height = "29px";
869
+ button.style.display = "flex";
870
+ button.style.alignItems = "center";
871
+ button.style.justifyContent = "center";
872
+ if (style.url === this._currentStyleUrl) {
873
+ button.style.backgroundColor = "rgba(0, 0, 0, 0.05)";
874
+ button.style.fontWeight = "bold";
875
+ }
876
+ if (index < this._styles.length - 1) {
877
+ button.style.borderRight = "1px solid rgba(0, 0, 0, 0.1)";
878
+ }
879
+ button.onclick = () => {
880
+ const buttons = this._container?.querySelectorAll("button");
881
+ buttons?.forEach((btn, btnIndex) => {
882
+ if (btnIndex === index) {
883
+ btn.style.backgroundColor = "rgba(0, 0, 0, 0.05)";
884
+ btn.style.fontWeight = "bold";
885
+ } else {
886
+ btn.style.backgroundColor = "";
887
+ btn.style.fontWeight = "";
888
+ }
889
+ });
890
+ this._onStyleChange(style.url);
891
+ };
892
+ this._container.appendChild(button);
893
+ });
894
+ return this._container;
895
+ }
896
+ onRemove() {
897
+ this._container?.parentNode?.removeChild(this._container);
898
+ this._map = void 0;
899
+ }
900
+ updateCurrentStyle(styleUrl) {
901
+ this._currentStyleUrl = styleUrl;
902
+ const buttons = this._container?.querySelectorAll("button");
903
+ buttons?.forEach((button, index) => {
904
+ const btn = button;
905
+ if (this._styles[index].url === styleUrl) {
906
+ btn.style.backgroundColor = "rgba(0, 0, 0, 0.05)";
907
+ btn.style.fontWeight = "bold";
908
+ } else {
909
+ btn.style.backgroundColor = "";
910
+ btn.style.fontWeight = "";
911
+ }
912
+ });
913
+ }
914
+ }
915
+ function BasemapControlComponent({
916
+ mapStyles,
917
+ currentStyleUrl,
918
+ onStyleChange
919
+ }) {
920
+ const controlRef = useControl(
921
+ () => new BasemapControl(mapStyles, currentStyleUrl, onStyleChange),
922
+ {
923
+ position: "bottom-left"
924
+ }
925
+ );
926
+ useEffect(() => {
927
+ if (controlRef && "updateCurrentStyle" in controlRef) {
928
+ controlRef.updateCurrentStyle(currentStyleUrl);
929
+ }
930
+ }, [currentStyleUrl, controlRef]);
931
+ return null;
932
+ }
933
+ class LayerControlImpl {
934
+ _map;
935
+ _container;
936
+ _layers;
937
+ _onToggle;
938
+ constructor(layers, onToggle) {
939
+ this._layers = layers;
940
+ this._onToggle = onToggle;
941
+ }
942
+ onAdd(map) {
943
+ this._map = map;
944
+ this._container = document.createElement("div");
945
+ this._container.className = "maplibregl-ctrl maplibregl-ctrl-group";
946
+ this._container.style.padding = "0";
947
+ this._render();
948
+ return this._container;
949
+ }
950
+ onRemove() {
951
+ if (this._container && this._container.parentNode) {
952
+ this._container.parentNode.removeChild(this._container);
953
+ }
954
+ this._map = void 0;
955
+ }
956
+ _render() {
957
+ if (!this._container) return;
958
+ this._container.innerHTML = "";
959
+ const button = document.createElement("button");
960
+ button.type = "button";
961
+ button.className = "maplibregl-ctrl-icon";
962
+ button.title = "Toggle Layers";
963
+ button.setAttribute("aria-label", "Toggle Layers");
964
+ button.innerHTML = `
965
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
966
+ <path d="M12 2L2 7l10 5 10-5-10-5z"/>
967
+ <path d="M2 17l10 5 10-5"/>
968
+ <path d="M2 12l10 5 10-5"/>
969
+ </svg>
970
+ `;
971
+ button.style.width = "29px";
972
+ button.style.height = "29px";
973
+ button.style.cursor = "pointer";
974
+ button.style.border = "none";
975
+ button.style.padding = "0";
976
+ button.style.display = "flex";
977
+ button.style.alignItems = "center";
978
+ button.style.justifyContent = "center";
979
+ const panel = document.createElement("div");
980
+ panel.className = "maplibregl-ctrl-layers-panel";
981
+ panel.style.display = "none";
982
+ panel.style.position = "absolute";
983
+ panel.style.top = "0";
984
+ panel.style.right = "40px";
985
+ panel.style.background = "white";
986
+ panel.style.borderRadius = "4px";
987
+ panel.style.boxShadow = "0 0 0 2px rgba(0, 0, 0, 0.1)";
988
+ panel.style.padding = "8px";
989
+ panel.style.minWidth = "180px";
990
+ panel.style.maxHeight = "300px";
991
+ panel.style.overflowY = "auto";
992
+ const title = document.createElement("div");
993
+ title.textContent = "POI Layers";
994
+ title.style.fontSize = "12px";
995
+ title.style.fontWeight = "bold";
996
+ title.style.marginBottom = "8px";
997
+ title.style.color = "#333";
998
+ title.style.fontFamily = "system-ui, -apple-system, sans-serif";
999
+ panel.appendChild(title);
1000
+ this._layers.forEach((layer) => {
1001
+ const layerItem = document.createElement("div");
1002
+ layerItem.style.display = "flex";
1003
+ layerItem.style.alignItems = "center";
1004
+ layerItem.style.padding = "4px 0";
1005
+ layerItem.style.cursor = "pointer";
1006
+ layerItem.style.fontSize = "12px";
1007
+ layerItem.style.color = "#333";
1008
+ layerItem.style.fontFamily = "system-ui, -apple-system, sans-serif";
1009
+ const circle = document.createElement("div");
1010
+ circle.style.width = "12px";
1011
+ circle.style.height = "12px";
1012
+ circle.style.borderRadius = "50%";
1013
+ circle.style.marginRight = "8px";
1014
+ circle.style.cursor = "pointer";
1015
+ circle.style.flexShrink = "0";
1016
+ circle.style.transition = "all 0.2s ease";
1017
+ if (layer.enabled && layer.color) {
1018
+ circle.style.backgroundColor = layer.color;
1019
+ circle.style.border = "none";
1020
+ } else {
1021
+ circle.style.backgroundColor = "transparent";
1022
+ circle.style.border = "2px solid #999";
1023
+ }
1024
+ layerItem.addEventListener("click", (e) => {
1025
+ e.stopPropagation();
1026
+ this._onToggle(layer.id, !layer.enabled);
1027
+ });
1028
+ const labelText = document.createElement("span");
1029
+ labelText.textContent = layer.name;
1030
+ labelText.style.userSelect = "none";
1031
+ layerItem.appendChild(circle);
1032
+ layerItem.appendChild(labelText);
1033
+ panel.appendChild(layerItem);
1034
+ });
1035
+ let isPanelOpen = false;
1036
+ button.addEventListener("click", (e) => {
1037
+ e.stopPropagation();
1038
+ isPanelOpen = !isPanelOpen;
1039
+ panel.style.display = isPanelOpen ? "block" : "none";
1040
+ });
1041
+ document.addEventListener("click", (e) => {
1042
+ if (isPanelOpen && this._container && !this._container.contains(e.target)) {
1043
+ isPanelOpen = false;
1044
+ panel.style.display = "none";
1045
+ }
1046
+ });
1047
+ this._container.appendChild(button);
1048
+ this._container.appendChild(panel);
1049
+ }
1050
+ /**
1051
+ * Update layers (e.g., when toggled externally)
1052
+ */
1053
+ updateLayers(layers) {
1054
+ this._layers = layers;
1055
+ this._render();
1056
+ }
1057
+ }
1058
+ const LayerControl = ({ mapRef, layers, onLayerToggle }) => {
1059
+ const controlRef = useRef(null);
1060
+ useEffect(() => {
1061
+ if (!mapRef.current || layers.length === 0) return;
1062
+ const map = mapRef.current.getMap();
1063
+ const control = new LayerControlImpl(layers, onLayerToggle);
1064
+ controlRef.current = control;
1065
+ map.addControl(control, "top-right");
1066
+ return () => {
1067
+ if (controlRef.current) {
1068
+ map.removeControl(controlRef.current);
1069
+ controlRef.current = null;
1070
+ }
1071
+ };
1072
+ }, [mapRef, onLayerToggle]);
1073
+ useEffect(() => {
1074
+ if (controlRef.current) {
1075
+ controlRef.current.updateLayers(layers);
1076
+ }
1077
+ }, [layers]);
1078
+ return null;
1079
+ };
1080
+ class CreditsControlImpl {
1081
+ _map;
1082
+ _container;
1083
+ onAdd(map) {
1084
+ this._map = map;
1085
+ this._container = document.createElement("div");
1086
+ this._container.className = "maplibregl-ctrl maplibregl-ctrl-attrib maplibregl-compact";
1087
+ this._render();
1088
+ return this._container;
1089
+ }
1090
+ onRemove() {
1091
+ if (this._container && this._container.parentNode) {
1092
+ this._container.parentNode.removeChild(this._container);
1093
+ }
1094
+ this._map = void 0;
1095
+ }
1096
+ _render() {
1097
+ if (!this._container) return;
1098
+ this._container.innerHTML = "";
1099
+ const button = document.createElement("button");
1100
+ button.type = "button";
1101
+ button.className = "maplibregl-ctrl-attrib-button";
1102
+ button.title = "Toggle attribution";
1103
+ button.setAttribute("aria-label", "Toggle attribution");
1104
+ button.setAttribute("type", "button");
1105
+ button.setAttribute("aria-pressed", "false");
1106
+ const panel = document.createElement("div");
1107
+ panel.className = "maplibregl-ctrl-attrib maplibregl-compact";
1108
+ panel.style.display = "none";
1109
+ panel.style.background = "rgba(255, 255, 255, 0.5)";
1110
+ panel.style.fontSize = "11px";
1111
+ panel.style.padding = "0 5px";
1112
+ panel.style.margin = "0";
1113
+ panel.style.lineHeight = "20px";
1114
+ panel.style.color = "rgba(0, 0, 0, 0.75)";
1115
+ const content = document.createElement("div");
1116
+ content.innerHTML = `
1117
+ <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">© OpenStreetMap</a> |
1118
+ <a href="https://maplibre.org/" target="_blank" rel="noopener noreferrer">MapLibre</a>
1119
+ `;
1120
+ content.querySelectorAll("a").forEach((link) => {
1121
+ link.style.color = "rgba(0, 0, 0, 0.75)";
1122
+ link.style.textDecoration = "none";
1123
+ });
1124
+ panel.appendChild(content);
1125
+ let isPanelOpen = false;
1126
+ const togglePanel = (open) => {
1127
+ isPanelOpen = open;
1128
+ panel.style.display = isPanelOpen ? "block" : "none";
1129
+ button.setAttribute("aria-pressed", isPanelOpen ? "true" : "false");
1130
+ };
1131
+ button.addEventListener("click", (e) => {
1132
+ e.stopPropagation();
1133
+ togglePanel(!isPanelOpen);
1134
+ });
1135
+ document.addEventListener("click", (e) => {
1136
+ if (isPanelOpen && this._container && !this._container.contains(e.target)) {
1137
+ togglePanel(false);
1138
+ }
1139
+ });
1140
+ this._container.appendChild(button);
1141
+ this._container.appendChild(panel);
1142
+ }
1143
+ }
1144
+ const CreditsControl = ({ mapRef }) => {
1145
+ const controlRef = useRef(null);
1146
+ useEffect(() => {
1147
+ if (!mapRef.current) return;
1148
+ const map = mapRef.current.getMap();
1149
+ const control = new CreditsControlImpl();
1150
+ controlRef.current = control;
1151
+ map.addControl(control, "bottom-right");
1152
+ return () => {
1153
+ if (controlRef.current) {
1154
+ map.removeControl(controlRef.current);
1155
+ controlRef.current = null;
1156
+ }
1157
+ };
1158
+ }, [mapRef]);
1159
+ return null;
1160
+ };
1161
+ const getTrad = (id) => `${pluginId}.${id}`;
1162
+ const USER_AGENT = "strapi-plugin-maplibre-field/1.0.0 (Strapi CMS)";
1163
+ let protocol = new Protocol();
1164
+ maplibregl.addProtocol("pmtiles", protocol.tile);
1165
+ const MapField = ({ intlLabel, name, onChange, value }) => {
1166
+ const { formatMessage } = useIntl();
1167
+ const { toggleNotification } = useNotification();
1168
+ const config = usePluginConfig();
1169
+ const mapRef = useRef(null);
1170
+ console.log("[MapLibre MapField] Using config:", config);
1171
+ const label = intlLabel || { id: "maplibre-field.label", defaultMessage: "Map" };
1172
+ let result = null;
1173
+ if (value) {
1174
+ try {
1175
+ const parsed = typeof value === "string" ? JSON.parse(value) : value;
1176
+ if (parsed && typeof parsed === "object" && parsed.geometry?.coordinates) {
1177
+ result = parsed;
1178
+ }
1179
+ } catch (error) {
1180
+ console.error("MapField: Invalid JSON value", error);
1181
+ }
1182
+ }
1183
+ const isDefaultViewState = result == null;
1184
+ let initialCoordinates = config.defaultCenter || [0, 0];
1185
+ if (result?.geometry?.coordinates && Array.isArray(result.geometry.coordinates)) {
1186
+ const [lng, lat] = result.geometry.coordinates;
1187
+ if (typeof lng === "number" && typeof lat === "number" && !isNaN(lng) && !isNaN(lat)) {
1188
+ initialCoordinates = [lng, lat];
1189
+ }
1190
+ }
1191
+ const isNullIsland = initialCoordinates[0] === 0 && initialCoordinates[1] === 0;
1192
+ const initialAddress = result?.properties?.name || result?.properties?.address || (isNullIsland ? "Null Island" : "");
1193
+ const [longitude, setLongitude] = useState(initialCoordinates[0]);
1194
+ const [latitude, setLatitude] = useState(initialCoordinates[1]);
1195
+ const [address, setAddress] = useState(initialAddress);
1196
+ const [viewState, setViewState] = useState({
1197
+ longitude: initialCoordinates[0],
1198
+ latitude: initialCoordinates[1],
1199
+ zoom: isDefaultViewState ? config.defaultZoom || 4.5 : 15
1200
+ // Use zoom 15 when coordinates are saved
1201
+ });
1202
+ const [currentStyleUrl, setCurrentStyleUrl] = useState(() => {
1203
+ if (config.mapStyles && config.mapStyles.length > 0) {
1204
+ const defaultStyle = config.mapStyles.find((s) => s.isDefault);
1205
+ return defaultStyle?.url || config.mapStyles[0].url;
1206
+ }
1207
+ return "";
1208
+ });
1209
+ const [displayedPOIs, setDisplayedPOIs] = useState([]);
1210
+ const [selectedPOI, setSelectedPOI] = useState(null);
1211
+ const [isUpdatingPOIs, setIsUpdatingPOIs] = useState(false);
1212
+ const updatePOITimerRef = useRef(null);
1213
+ const poiLayersRef = useRef([]);
1214
+ const [poiLayers, setPoiLayers] = useState(() => {
1215
+ if (!config.poiDisplayEnabled) return [];
1216
+ if (config.poiSources && config.poiSources.length > 0) {
1217
+ return config.poiSources.map((source) => ({
1218
+ id: source.id,
1219
+ name: source.name,
1220
+ enabled: source.enabled !== false,
1221
+ // Default to enabled if not specified
1222
+ color: source.color
1223
+ // Pass the color from config
1224
+ }));
1225
+ }
1226
+ return [];
1227
+ });
1228
+ useEffect(() => {
1229
+ poiLayersRef.current = poiLayers;
1230
+ }, [poiLayers]);
1231
+ useEffect(() => {
1232
+ if (config.defaultZoom && isDefaultViewState) {
1233
+ setViewState((prev) => ({
1234
+ ...prev,
1235
+ zoom: config.defaultZoom ?? prev.zoom
1236
+ }));
1237
+ }
1238
+ }, [config.defaultZoom, isDefaultViewState]);
1239
+ useEffect(() => {
1240
+ if (config.defaultCenter && isDefaultViewState) {
1241
+ const [lng, lat] = config.defaultCenter;
1242
+ const isNullIsland2 = lng === 0 && lat === 0;
1243
+ setLongitude(lng);
1244
+ setLatitude(lat);
1245
+ setAddress(isNullIsland2 ? "Null Island" : "");
1246
+ setViewState((prev) => ({
1247
+ ...prev,
1248
+ longitude: lng,
1249
+ latitude: lat
1250
+ }));
1251
+ }
1252
+ }, [config.defaultCenter, isDefaultViewState]);
1253
+ useEffect(() => {
1254
+ if (config.mapStyles && config.mapStyles.length > 0) {
1255
+ const defaultStyle = config.mapStyles.find((s) => s.isDefault);
1256
+ const newStyleUrl = defaultStyle?.url || config.mapStyles[0].url;
1257
+ if (newStyleUrl && newStyleUrl !== currentStyleUrl) {
1258
+ setCurrentStyleUrl(newStyleUrl);
1259
+ }
1260
+ }
1261
+ }, [config.mapStyles]);
1262
+ useEffect(() => {
1263
+ if (!config.poiDisplayEnabled) {
1264
+ setPoiLayers([]);
1265
+ return;
1266
+ }
1267
+ if (config.poiSources && config.poiSources.length > 0) {
1268
+ setPoiLayers(
1269
+ config.poiSources.map((source) => ({
1270
+ id: source.id,
1271
+ name: source.name,
1272
+ enabled: source.enabled !== false,
1273
+ color: source.color
1274
+ // Pass the color from config
1275
+ }))
1276
+ );
1277
+ return;
1278
+ }
1279
+ setPoiLayers([]);
1280
+ }, [config.poiDisplayEnabled, config.poiSources]);
1281
+ const handleStyleChange = (newStyleUrl) => {
1282
+ if (!mapRef.current) return;
1283
+ const map = mapRef.current.getMap();
1284
+ const currentCenter = map.getCenter();
1285
+ const currentZoom = map.getZoom();
1286
+ map.setStyle(newStyleUrl);
1287
+ map.once("styledata", () => {
1288
+ map.setCenter(currentCenter);
1289
+ map.setZoom(currentZoom);
1290
+ });
1291
+ setCurrentStyleUrl(newStyleUrl);
1292
+ };
1293
+ const handleLayerToggle = (layerId, enabled) => {
1294
+ setPoiLayers(
1295
+ (prevLayers) => prevLayers.map(
1296
+ (layer) => layer.id === layerId ? { ...layer, enabled } : layer
1297
+ )
1298
+ );
1299
+ };
1300
+ const updatePOIMarkers = async () => {
1301
+ if (updatePOITimerRef.current) {
1302
+ clearTimeout(updatePOITimerRef.current);
1303
+ }
1304
+ updatePOITimerRef.current = setTimeout(async () => {
1305
+ const currentPoiLayers = poiLayersRef.current;
1306
+ const hasEnabledLayers = currentPoiLayers.some((layer) => layer.enabled);
1307
+ if (!mapRef.current || !config.poiDisplayEnabled) {
1308
+ return;
1309
+ }
1310
+ if (!hasEnabledLayers) {
1311
+ setDisplayedPOIs([]);
1312
+ return;
1313
+ }
1314
+ if (isUpdatingPOIs) {
1315
+ return;
1316
+ }
1317
+ const map = mapRef.current.getMap();
1318
+ const zoom = map.getZoom();
1319
+ if (zoom < (config.poiMinZoom || 10)) {
1320
+ setDisplayedPOIs([]);
1321
+ return;
1322
+ }
1323
+ const bounds = map.getBounds();
1324
+ const center = map.getCenter();
1325
+ try {
1326
+ setIsUpdatingPOIs(true);
1327
+ const enabledLayers = currentPoiLayers.filter((layer) => layer.enabled);
1328
+ const allPOIs = [];
1329
+ for (const layer of enabledLayers) {
1330
+ let apiUrl = null;
1331
+ let mapName = layer.name;
1332
+ if (config.poiSources) {
1333
+ const source = config.poiSources.find((s) => s.id === layer.id);
1334
+ if (source) {
1335
+ apiUrl = source.apiUrl;
1336
+ mapName = source.name;
1337
+ }
1338
+ }
1339
+ if (apiUrl) {
1340
+ const pois = await queryPOIsForViewport(
1341
+ {
1342
+ north: bounds.getNorth(),
1343
+ south: bounds.getSouth(),
1344
+ east: bounds.getEast(),
1345
+ west: bounds.getWest()
1346
+ },
1347
+ [center.lng, center.lat],
1348
+ config.poiMaxDisplay || 100,
1349
+ {
1350
+ nominatimUrl: config.nominatimUrl || "https://nominatim.openstreetmap.org",
1351
+ customApiUrl: apiUrl,
1352
+ mapName,
1353
+ layerId: layer.id,
1354
+ // Pass the layer ID
1355
+ radius: 100,
1356
+ categories: []
1357
+ }
1358
+ );
1359
+ allPOIs.push(...pois);
1360
+ }
1361
+ }
1362
+ requestAnimationFrame(() => {
1363
+ setDisplayedPOIs(allPOIs);
1364
+ setIsUpdatingPOIs(false);
1365
+ });
1366
+ } catch (error) {
1367
+ console.error("Failed to load POIs:", error);
1368
+ setIsUpdatingPOIs(false);
1369
+ }
1370
+ }, 300);
1371
+ };
1372
+ const handlePOIClick = async (poi) => {
1373
+ setSelectedPOI(poi);
1374
+ let address2 = poi.address;
1375
+ if (!address2 || address2.trim() === "") {
1376
+ try {
1377
+ const [lng, lat] = poi.coordinates;
1378
+ const nominatimUrl = config.nominatimUrl || "https://nominatim.openstreetmap.org";
1379
+ const response = await fetch(
1380
+ `${nominatimUrl}/reverse?format=jsonv2&lat=${lat}&lon=${lng}`,
1381
+ {
1382
+ headers: {
1383
+ "User-Agent": USER_AGENT
1384
+ }
1385
+ }
1386
+ );
1387
+ if (response.ok) {
1388
+ const data = await response.json();
1389
+ address2 = data.display_name || "";
1390
+ }
1391
+ } catch (error) {
1392
+ console.warn("Reverse geocoding failed:", error);
1393
+ }
1394
+ }
1395
+ updateValues(createLocationFeature(poi.coordinates, {
1396
+ name: poi.name,
1397
+ address: address2,
1398
+ source: poi.source === "custom" ? poi.layerId : "nominatim",
1399
+ sourceId: poi.id,
1400
+ sourceLayer: poi.mapName,
1401
+ category: poi.type,
1402
+ inputMethod: "poi_click",
1403
+ metadata: poi.metadata
1404
+ }));
1405
+ toggleNotification({
1406
+ type: "success",
1407
+ message: poi.mapName ? `${poi.mapName} → ${poi.name}` : `Selected ${poi.name}`
1408
+ });
1409
+ };
1410
+ const handleMapClick = (evt) => {
1411
+ if (!mapRef.current) return;
1412
+ const map = mapRef.current.getMap();
1413
+ const poiLayer = map.getLayer("poi-circles");
1414
+ if (!poiLayer) {
1415
+ return;
1416
+ }
1417
+ const features = map.queryRenderedFeatures(evt.point, {
1418
+ layers: ["poi-circles"]
1419
+ });
1420
+ if (features && features.length > 0) {
1421
+ const feature = features[0];
1422
+ const featureName = feature.properties?.name;
1423
+ let clickedPOI = displayedPOIs.find((p) => p.name === featureName);
1424
+ if (!clickedPOI) {
1425
+ clickedPOI = displayedPOIs.find((p) => p.id === feature.id);
1426
+ }
1427
+ if (!clickedPOI && feature.id !== void 0) {
1428
+ clickedPOI = displayedPOIs.find((p) => p.id === String(feature.id));
1429
+ }
1430
+ if (clickedPOI) {
1431
+ handlePOIClick(clickedPOI);
1432
+ return;
1433
+ }
1434
+ }
1435
+ };
1436
+ const handleMapDoubleClick = async (evt) => {
1437
+ evt.preventDefault();
1438
+ const clickCoords = [evt.lngLat.lng, evt.lngLat.lat];
1439
+ const snapRadius = typeof config.poiSnapRadius === "number" ? config.poiSnapRadius : config.poiSnapRadius?.default ?? 5;
1440
+ try {
1441
+ const enabledLayers = poiLayers.filter((layer) => layer.enabled);
1442
+ const allNearbyPOIs = [];
1443
+ for (const layer of enabledLayers) {
1444
+ let apiUrl = null;
1445
+ let mapName = layer.name;
1446
+ if (config.poiSources) {
1447
+ const source = config.poiSources.find((s) => s.id === layer.id);
1448
+ if (source) {
1449
+ apiUrl = source.apiUrl;
1450
+ mapName = source.name;
1451
+ }
1452
+ }
1453
+ if (apiUrl) {
1454
+ const pois = await searchNearbyPOIsForSnap(
1455
+ clickCoords[1],
1456
+ // lat
1457
+ clickCoords[0],
1458
+ // lng
1459
+ {
1460
+ nominatimUrl: config.nominatimUrl || "https://nominatim.openstreetmap.org",
1461
+ customApiUrl: apiUrl,
1462
+ mapName,
1463
+ layerId: layer.id,
1464
+ // Pass the layer ID
1465
+ radius: snapRadius,
1466
+ categories: []
1467
+ }
1468
+ );
1469
+ allNearbyPOIs.push(...pois);
1470
+ }
1471
+ }
1472
+ const nearestPOI = findNearestPOI(clickCoords, allNearbyPOIs);
1473
+ if (nearestPOI && nearestPOI.distance !== void 0 && nearestPOI.distance <= snapRadius) {
1474
+ await handlePOIClick(nearestPOI);
1475
+ toggleNotification({
1476
+ type: "success",
1477
+ message: `${nearestPOI.name} (${Math.round(nearestPOI.distance)}m)`
1478
+ });
1479
+ } else {
1480
+ updateValues(createLocationFeature(clickCoords, {
1481
+ inputMethod: "map_click"
1482
+ }));
1483
+ toggleNotification({
1484
+ type: "info",
1485
+ message: formatMessage({
1486
+ id: getTrad("coordinates-saved"),
1487
+ defaultMessage: "Coordinates saved"
1488
+ })
1489
+ });
1490
+ }
1491
+ } catch (error) {
1492
+ console.error("Failed to search nearby POIs:", error);
1493
+ updateValues(createLocationFeature(clickCoords, {
1494
+ inputMethod: "map_click"
1495
+ }));
1496
+ toggleNotification({
1497
+ type: "info",
1498
+ message: formatMessage({
1499
+ id: getTrad("coordinates-saved"),
1500
+ defaultMessage: "Coordinates saved"
1501
+ })
1502
+ });
1503
+ }
1504
+ };
1505
+ const updateValues = (feature) => {
1506
+ if (!feature) return;
1507
+ const value2 = JSON.stringify(feature);
1508
+ setAddress(feature.properties.name || feature.properties.address || "");
1509
+ setLongitude(feature.geometry.coordinates[0]);
1510
+ setLatitude(feature.geometry.coordinates[1]);
1511
+ onChange({ target: { name, value: value2, type: "json" } });
1512
+ };
1513
+ const handleGeocoderResult = (evt) => {
1514
+ const { result: result2 } = evt;
1515
+ if (result2?.center) {
1516
+ const properties = result2.properties || {};
1517
+ const isCustomSource = properties.source === "custom";
1518
+ let name2 = result2.place_name || "";
1519
+ if (!isCustomSource && properties.display_name) {
1520
+ name2 = properties.name || properties.display_name.split(",")[0].trim();
1521
+ }
1522
+ updateValues(createLocationFeature(result2.center, {
1523
+ name: isCustomSource ? result2.place_name : name2,
1524
+ address: isCustomSource ? void 0 : result2.place_name,
1525
+ // Full address for Nominatim
1526
+ source: isCustomSource ? properties.poi_source_id : "nominatim",
1527
+ sourceId: isCustomSource ? properties.id : `nominatim-${properties.place_id}`,
1528
+ sourceLayer: isCustomSource ? properties.mapName : void 0,
1529
+ category: properties.type || properties.class,
1530
+ inputMethod: "search",
1531
+ metadata: isCustomSource ? properties.metadata : {
1532
+ osm_id: properties.osm_id,
1533
+ osm_type: properties.osm_type,
1534
+ place_id: properties.place_id,
1535
+ addresstype: properties.addresstype
1536
+ }
1537
+ }));
1538
+ }
1539
+ };
1540
+ useEffect(() => {
1541
+ if (!isDefaultViewState && mapRef.current) {
1542
+ const map = mapRef.current.getMap();
1543
+ map?.flyTo({ center: [longitude, latitude], zoom: 15 });
1544
+ }
1545
+ }, [longitude, latitude, isDefaultViewState]);
1546
+ useEffect(() => {
1547
+ let protocol2 = new Protocol();
1548
+ maplibregl.addProtocol("pmtiles", protocol2.tile);
1549
+ return () => {
1550
+ maplibregl.removeProtocol("pmtiles");
1551
+ };
1552
+ }, []);
1553
+ useEffect(() => {
1554
+ if (!mapRef.current || !config.poiDisplayEnabled) return;
1555
+ const map = mapRef.current.getMap();
1556
+ const handleMapUpdate = () => {
1557
+ updatePOIMarkers();
1558
+ };
1559
+ map.once("load", handleMapUpdate);
1560
+ map.on("moveend", handleMapUpdate);
1561
+ map.on("zoomend", handleMapUpdate);
1562
+ return () => {
1563
+ map.off("moveend", handleMapUpdate);
1564
+ map.off("zoomend", handleMapUpdate);
1565
+ if (updatePOITimerRef.current) {
1566
+ clearTimeout(updatePOITimerRef.current);
1567
+ }
1568
+ };
1569
+ }, [config.poiDisplayEnabled, config.poiMinZoom, config.poiMaxDisplay, config.poiSources]);
1570
+ useEffect(() => {
1571
+ if (!mapRef.current || !config.poiDisplayEnabled) return;
1572
+ updatePOIMarkers();
1573
+ }, [JSON.stringify(poiLayers.map((l) => ({ id: l.id, enabled: l.enabled })))]);
1574
+ useEffect(() => {
1575
+ if (!mapRef.current || !config.poiDisplayEnabled) return;
1576
+ const map = mapRef.current.getMap();
1577
+ const handleMouseEnter = () => {
1578
+ map.getCanvas().style.cursor = "pointer";
1579
+ };
1580
+ const handleMouseLeave = () => {
1581
+ map.getCanvas().style.cursor = "";
1582
+ };
1583
+ map.on("load", () => {
1584
+ map.on("mouseenter", "poi-circles", handleMouseEnter);
1585
+ map.on("mouseleave", "poi-circles", handleMouseLeave);
1586
+ });
1587
+ return () => {
1588
+ map.off("mouseenter", "poi-circles", handleMouseEnter);
1589
+ map.off("mouseleave", "poi-circles", handleMouseLeave);
1590
+ };
1591
+ }, [config.poiDisplayEnabled]);
1592
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1593
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", variant: "pi", fontWeight: "bold", children: formatMessage(label) }),
1594
+ /* @__PURE__ */ jsx(
1595
+ Flex,
1596
+ {
1597
+ direction: "column",
1598
+ alignItems: "stretch",
1599
+ style: {
1600
+ height: "500px",
1601
+ width: "100%",
1602
+ borderRadius: "4px",
1603
+ overflow: "hidden"
1604
+ },
1605
+ children: /* @__PURE__ */ jsxs(
1606
+ Map,
1607
+ {
1608
+ ref: mapRef,
1609
+ ...viewState,
1610
+ onMove: (evt) => setViewState(evt.viewState),
1611
+ onClick: handleMapClick,
1612
+ onDblClick: handleMapDoubleClick,
1613
+ mapStyle: currentStyleUrl,
1614
+ attributionControl: false,
1615
+ children: [
1616
+ /* @__PURE__ */ jsx(FullscreenControl, {}),
1617
+ /* @__PURE__ */ jsx(NavigationControl, {}),
1618
+ /* @__PURE__ */ jsx(GeolocateControl, {}),
1619
+ /* @__PURE__ */ jsx(
1620
+ GeocoderControl,
1621
+ {
1622
+ mapRef,
1623
+ position: "top-left",
1624
+ onResult: handleGeocoderResult
1625
+ }
1626
+ ),
1627
+ config.mapStyles && config.mapStyles.length > 1 && /* @__PURE__ */ jsx(
1628
+ BasemapControlComponent,
1629
+ {
1630
+ mapStyles: config.mapStyles,
1631
+ currentStyleUrl,
1632
+ onStyleChange: handleStyleChange
1633
+ }
1634
+ ),
1635
+ poiLayers.length > 0 && /* @__PURE__ */ jsx(
1636
+ LayerControl,
1637
+ {
1638
+ mapRef,
1639
+ layers: poiLayers,
1640
+ onLayerToggle: handleLayerToggle
1641
+ }
1642
+ ),
1643
+ /* @__PURE__ */ jsx(CreditsControl, { mapRef }),
1644
+ config.poiDisplayEnabled && displayedPOIs.length > 0 && (() => {
1645
+ const layerColorMap = {};
1646
+ poiLayers.forEach((layer) => {
1647
+ if (layer.color) {
1648
+ layerColorMap[layer.id] = layer.color;
1649
+ }
1650
+ });
1651
+ const colorMatchExpression = ["match", ["get", "layerId"]];
1652
+ Object.entries(layerColorMap).forEach(([layerId, color]) => {
1653
+ colorMatchExpression.push(layerId, color);
1654
+ });
1655
+ colorMatchExpression.push("#999999");
1656
+ return /* @__PURE__ */ jsxs(
1657
+ Source,
1658
+ {
1659
+ id: "poi-markers",
1660
+ type: "geojson",
1661
+ data: {
1662
+ type: "FeatureCollection",
1663
+ features: displayedPOIs.slice(0, 100).map((poi) => ({
1664
+ type: "Feature",
1665
+ id: poi.id,
1666
+ geometry: {
1667
+ type: "Point",
1668
+ coordinates: poi.coordinates
1669
+ },
1670
+ properties: {
1671
+ name: poi.name || "Unknown",
1672
+ type: poi.type || "poi",
1673
+ source: poi.source,
1674
+ layerId: poi.layerId || "",
1675
+ // Include layerId for color mapping
1676
+ isSelected: selectedPOI?.id === poi.id
1677
+ }
1678
+ }))
1679
+ },
1680
+ children: [
1681
+ /* @__PURE__ */ jsx(
1682
+ Layer,
1683
+ {
1684
+ id: "poi-circles",
1685
+ type: "circle",
1686
+ paint: {
1687
+ "circle-radius": [
1688
+ "case",
1689
+ ["get", "isSelected"],
1690
+ 12,
1691
+ // Larger radius for selected
1692
+ 10
1693
+ // Regular radius
1694
+ ],
1695
+ "circle-color": colorMatchExpression,
1696
+ // Use dynamic color mapping based on layerId for all POIs
1697
+ "circle-stroke-width": 2,
1698
+ "circle-stroke-color": "#ffffff",
1699
+ "circle-opacity": [
1700
+ "case",
1701
+ ["get", "isSelected"],
1702
+ 0.8,
1703
+ // Selected POI opacity
1704
+ 1
1705
+ // Regular POI opacity
1706
+ ]
1707
+ }
1708
+ }
1709
+ ),
1710
+ /* @__PURE__ */ jsx(
1711
+ Layer,
1712
+ {
1713
+ id: "poi-labels",
1714
+ type: "symbol",
1715
+ minzoom: 12,
1716
+ layout: {
1717
+ "text-field": ["get", "name"],
1718
+ "text-size": 12,
1719
+ "text-offset": [0, 1.5],
1720
+ "text-anchor": "top",
1721
+ "text-optional": true,
1722
+ "symbol-placement": "point",
1723
+ "text-allow-overlap": false,
1724
+ "text-ignore-placement": false
1725
+ },
1726
+ paint: {
1727
+ "text-color": "#333333",
1728
+ "text-halo-color": "#ffffff",
1729
+ "text-halo-width": 2
1730
+ }
1731
+ }
1732
+ )
1733
+ ]
1734
+ },
1735
+ `poi-source-${displayedPOIs.length}-${selectedPOI?.id || "none"}`
1736
+ );
1737
+ })(),
1738
+ /* @__PURE__ */ jsx(Marker, { longitude, latitude, color: "#1da1f2" })
1739
+ ]
1740
+ }
1741
+ )
1742
+ }
1743
+ ),
1744
+ /* @__PURE__ */ jsxs(Grid.Root, { children: [
1745
+ /* @__PURE__ */ jsx(Grid.Item, { padding: 1, col: 8, xs: 12, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
1746
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
1747
+ id: result?.properties?.sourceId ? getTrad("fields.poi-name") : getTrad("fields.address"),
1748
+ defaultMessage: result?.properties?.sourceId ? "POI Name" : "Address"
1749
+ }) }),
1750
+ /* @__PURE__ */ jsx(Field.Input, { name: "place_name", value: address, disabled: true })
1751
+ ] }) }),
1752
+ /* @__PURE__ */ jsx(Grid.Item, { padding: 1, col: 2, xs: 12, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
1753
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
1754
+ id: getTrad("fields.longitude"),
1755
+ defaultMessage: "Longitude"
1756
+ }) }),
1757
+ /* @__PURE__ */ jsx(Field.Input, { name: "longitude", value: longitude, disabled: true })
1758
+ ] }) }),
1759
+ /* @__PURE__ */ jsx(Grid.Item, { padding: 1, col: 2, xs: 12, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
1760
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
1761
+ id: getTrad("fields.latitude"),
1762
+ defaultMessage: "Latitude"
1763
+ }) }),
1764
+ /* @__PURE__ */ jsx(Field.Input, { name: "latitude", value: latitude, disabled: true })
1765
+ ] }) }),
1766
+ result?.properties?.sourceId && result?.properties?.address && /* @__PURE__ */ jsx(Grid.Item, { padding: 1, col: 12, xs: 12, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
1767
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
1768
+ id: getTrad("fields.poi-address"),
1769
+ defaultMessage: "Full Address"
1770
+ }) }),
1771
+ /* @__PURE__ */ jsx(Field.Input, { name: "poi_address", value: result.properties.address, disabled: true })
1772
+ ] }) })
1773
+ ] })
1774
+ ] });
1775
+ };
1776
+ export {
1777
+ MapField as default
1778
+ };