@cocoar/vue-map 2.12.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/dist/index.js ADDED
@@ -0,0 +1,851 @@
1
+ import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createStaticVNode as o, createTextVNode as s, createVNode as c, defineComponent as l, inject as u, normalizeClass as d, normalizeStyle as f, onBeforeUnmount as p, onMounted as m, openBlock as h, ref as g, renderList as _, renderSlot as v, shallowRef as y, toDisplayString as b, unref as x, watch as S, withCtx as C } from "vue";
2
+ import { CoarButton as w, CoarSelect as T, CoarTextInput as E, setCoarDragImageFromElement as D, useDragDrop as O } from "@cocoar/vue-ui";
3
+ //#region src/context.ts
4
+ var k = Symbol.for("coar:map-config");
5
+ //#endregion
6
+ //#region src/internal/map-model.ts
7
+ function A(e) {
8
+ let t = /* @__PURE__ */ new Map();
9
+ for (let n of e.categories ?? []) t.set(n.id, n);
10
+ return t;
11
+ }
12
+ function j(e, t) {
13
+ return (e.category ? A(t).get(e.category) : void 0)?.color ?? "#3b82f6";
14
+ }
15
+ function M(e, t) {
16
+ return e.icon ? e.icon : (e.category ? A(t).get(e.category) : void 0)?.emoji ?? "";
17
+ }
18
+ function N(e, t) {
19
+ let n = [];
20
+ return e.points.forEach((e, r) => {
21
+ e.kind === "stop" ? n.push({
22
+ index: r,
23
+ emoji: M(e, t) || "📍",
24
+ label: e.label ?? "",
25
+ lat: e.lat,
26
+ lng: e.lng
27
+ }) : e.label && n.push({
28
+ index: r,
29
+ emoji: "•",
30
+ label: e.label,
31
+ lat: e.lat,
32
+ lng: e.lng
33
+ });
34
+ }), n;
35
+ }
36
+ function P(e, t) {
37
+ let n = A(t), r = /* @__PURE__ */ new Set(), i = [];
38
+ for (let t of e.points) {
39
+ if (t.kind !== "stop" || !t.category || r.has(t.category)) continue;
40
+ r.add(t.category);
41
+ let e = n.get(t.category);
42
+ e && i.push(e);
43
+ }
44
+ return i;
45
+ }
46
+ function F(e, t) {
47
+ let n = new Map(t.basemaps.map((e) => [e.id, e])), r = (e) => {
48
+ if (!e) return;
49
+ let t = n.get(e);
50
+ return t && !t.google ? t : void 0;
51
+ };
52
+ return r(e.basemap) ?? r(t.defaultBasemap) ?? t.basemaps.find((e) => !e.google) ?? null;
53
+ }
54
+ function I(e) {
55
+ if (e.length === 0) return null;
56
+ let t = Infinity, n = Infinity, r = -Infinity, i = -Infinity;
57
+ for (let a of e) a.lat < t && (t = a.lat), a.lat > r && (r = a.lat), a.lng < n && (n = a.lng), a.lng > i && (i = a.lng);
58
+ return [[t, n], [r, i]];
59
+ }
60
+ //#endregion
61
+ //#region src/CoarMap.vue?vue&type=script&setup=true&lang.ts
62
+ var L = {
63
+ key: 0,
64
+ class: "coar-map__fallback"
65
+ }, ee = { class: "coar-map__fallback-emoji" }, R = { class: "coar-map__fallback-label" }, z = { class: "coar-map__fallback-coords" }, te = {
66
+ key: 1,
67
+ class: "coar-map__legend"
68
+ }, ne = {
69
+ key: 0,
70
+ class: "coar-map__legend-emoji"
71
+ }, re = { class: "coar-map__legend-label" }, ie = {
72
+ key: 2,
73
+ class: "coar-map__caption"
74
+ }, ae = {
75
+ key: 3,
76
+ class: "coar-map__nocfg"
77
+ }, B = /* @__PURE__ */ l({
78
+ __name: "CoarMap",
79
+ props: {
80
+ data: {},
81
+ config: {},
82
+ selected: {},
83
+ showLegend: { type: Boolean }
84
+ },
85
+ emits: ["update:selected", "point-click"],
86
+ setup(n, { expose: o, emit: c }) {
87
+ let l = n, v = c, x = u(k, void 0), C = t(() => l.config ?? x ?? null), w = {
88
+ defaultBasemap: "",
89
+ basemaps: []
90
+ }, T = g(null), E = y(null), D = g(!1), O = /* @__PURE__ */ new Map(), A = t(() => N(l.data, C.value ?? w)), B = t(() => C.value ? P(l.data, C.value) : []), V = t(() => !!l.showLegend && B.value.length > 1);
91
+ function H(e) {
92
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
93
+ }
94
+ function U(e) {
95
+ return /[;"'<>]/.test(e) ? "#3b82f6" : e;
96
+ }
97
+ function W(e) {
98
+ let t = document.createElement("div");
99
+ if (t.className = "coar-map-popup", e.label) {
100
+ let n = document.createElement("strong");
101
+ n.textContent = e.label, t.appendChild(n);
102
+ }
103
+ if (e.note) {
104
+ let n = document.createElement("div");
105
+ n.className = "coar-map-popup__note", n.textContent = e.note, t.appendChild(n);
106
+ }
107
+ return t;
108
+ }
109
+ function G(e, t) {
110
+ v("update:selected", e), v("point-click", {
111
+ point: t,
112
+ index: e
113
+ });
114
+ }
115
+ function K(e, t, n, r, i) {
116
+ let a = U(j(n, i)), o = M(n, i), s = e.divIcon({
117
+ className: "coar-map-pin-wrap",
118
+ html: `<span class="coar-map-pin" style="--coar-map-pin-color:${a}"><span class="coar-map-pin__emoji">${H(o)}</span></span>`,
119
+ iconSize: [26, 26],
120
+ iconAnchor: [13, 13],
121
+ popupAnchor: [0, -13]
122
+ }), c = e.marker([n.lat, n.lng], { icon: s });
123
+ n.label && c.bindTooltip(H(n.label)), (n.label || n.note) && c.bindPopup(W(n)), c.on("click", () => G(r, n)), c.addTo(t), O.set(r, c);
124
+ }
125
+ function q(e, t, n, r) {
126
+ let i = e.circleMarker([n.lat, n.lng], {
127
+ radius: 4,
128
+ color: "#475569",
129
+ weight: 2,
130
+ fillColor: "#ffffff",
131
+ fillOpacity: 1
132
+ });
133
+ n.label && i.bindTooltip(H(n.label)), n.note && i.bindPopup(W(n)), i.on("click", () => G(r, n)), i.addTo(t), O.set(r, i);
134
+ }
135
+ function J() {
136
+ E.value &&= (E.value.remove(), null), O.clear(), D.value = !1;
137
+ }
138
+ function Y(e) {
139
+ return O.get(e)?.getElement?.() ?? null;
140
+ }
141
+ function X() {
142
+ let e = l.selected ?? null;
143
+ for (let t of O.keys()) Y(t)?.classList.toggle("coar-map-marker--selected", t === e);
144
+ }
145
+ async function Z() {
146
+ let e = T.value, t = C.value;
147
+ if (!e || !t) return;
148
+ J();
149
+ let n = await import("leaflet"), r = n.default ?? n;
150
+ if (await import("leaflet/dist/leaflet.css"), T.value !== e) return;
151
+ let i = r.map(e);
152
+ E.value = i;
153
+ let a = F(l.data, t);
154
+ a && r.tileLayer(a.url, {
155
+ subdomains: a.subdomains ?? "abc",
156
+ attribution: a.attribution,
157
+ maxZoom: a.maxZoom ?? 19
158
+ }).addTo(i);
159
+ let o = l.data.points;
160
+ l.data.type === "route" && o.length >= 2 && r.polyline(o.map((e) => [e.lat, e.lng]), {
161
+ color: "#3b82f6",
162
+ weight: 4,
163
+ opacity: .85
164
+ }).addTo(i), o.forEach((e, n) => {
165
+ e.kind === "stop" ? K(r, i, e, n, t) : e.label && q(r, i, e, n);
166
+ });
167
+ let s = l.data.viewport;
168
+ if (s) i.setView([s.centerLat, s.centerLng], s.zoom);
169
+ else {
170
+ let e = I(o);
171
+ e ? i.fitBounds(e, { padding: [28, 28] }) : i.setView([0, 0], 2);
172
+ }
173
+ requestAnimationFrame(() => E.value?.invalidateSize()), D.value = !0, X();
174
+ }
175
+ function Q(e) {
176
+ let t = l.data.points[e];
177
+ !t || !E.value || (E.value.panTo([t.lat, t.lng]), O.get(e)?.openPopup(), (l.selected ?? null) !== e && v("update:selected", e));
178
+ }
179
+ function $(e) {
180
+ for (let t of O.keys()) Y(t)?.classList.toggle("coar-map-marker--highlight", t === e);
181
+ }
182
+ return o({
183
+ focusPoint: Q,
184
+ highlightPoint: $
185
+ }), m(Z), p(J), S([() => l.data, C], () => void Z(), { deep: !0 }), S(() => l.selected, X), (t, o) => (h(), i("div", { class: d(["coar-map", { "coar-map--ready": D.value }]) }, [
186
+ a("div", {
187
+ ref_key: "mapEl",
188
+ ref: T,
189
+ class: "coar-map__canvas"
190
+ }, null, 512),
191
+ D.value ? r("", !0) : (h(), i("ol", L, [(h(!0), i(e, null, _(A.value, (e, t) => (h(), i("li", {
192
+ key: t,
193
+ class: "coar-map__fallback-item"
194
+ }, [
195
+ a("span", ee, b(e.emoji), 1),
196
+ a("span", R, b(e.label), 1),
197
+ a("span", z, b(e.lat.toFixed(4)) + ", " + b(e.lng.toFixed(4)), 1)
198
+ ]))), 128))])),
199
+ V.value ? (h(), i("ul", te, [(h(!0), i(e, null, _(B.value, (e) => (h(), i("li", {
200
+ key: e.id,
201
+ class: "coar-map__legend-item"
202
+ }, [
203
+ a("span", {
204
+ class: "coar-map__legend-swatch",
205
+ style: f({ background: e.color })
206
+ }, null, 4),
207
+ e.emoji ? (h(), i("span", ne, b(e.emoji), 1)) : r("", !0),
208
+ a("span", re, b(e.label), 1)
209
+ ]))), 128))])) : r("", !0),
210
+ n.data.caption ? (h(), i("p", ie, b(n.data.caption), 1)) : r("", !0),
211
+ C.value ? r("", !0) : (h(), i("p", ae, [...o[0] ||= [
212
+ s("No map config provided (pass ", -1),
213
+ a("code", null, "config", -1),
214
+ s(" or provide one).", -1)
215
+ ]]))
216
+ ], 2));
217
+ }
218
+ });
219
+ //#endregion
220
+ //#region src/internal/map-edit.ts
221
+ function V(e, t) {
222
+ let n = Math.max(-90, Math.min(90, e)), r = ((t + 180) % 360 + 360) % 360 - 180;
223
+ return r === -180 && (r = 180), {
224
+ lat: n,
225
+ lng: r
226
+ };
227
+ }
228
+ function H(e, t, n, r) {
229
+ let { lat: i, lng: a } = V(e, t);
230
+ return {
231
+ kind: r,
232
+ ...n,
233
+ lat: i,
234
+ lng: a
235
+ };
236
+ }
237
+ function U(e, t) {
238
+ return Number.isInteger(e) && e >= 0 && e < t;
239
+ }
240
+ function W(e, t) {
241
+ return {
242
+ ...e,
243
+ points: t
244
+ };
245
+ }
246
+ function G(e, t, n, r = {}) {
247
+ if (e.type === "single" && e.points.length >= 1) return K(e, 0, t, n);
248
+ let i = H(t, n, r, "stop");
249
+ return W(e, [...e.points, i]);
250
+ }
251
+ function K(e, t, n, r) {
252
+ if (!U(t, e.points.length)) return e;
253
+ let { lat: i, lng: a } = V(n, r);
254
+ return W(e, e.points.map((e, n) => n === t ? {
255
+ ...e,
256
+ lat: i,
257
+ lng: a
258
+ } : e));
259
+ }
260
+ function q(e, t, n) {
261
+ if (!U(t, e.points.length)) return e;
262
+ let r = {};
263
+ for (let [e, t] of Object.entries(n)) t !== void 0 && (r[e] = t);
264
+ if ("lat" in r || "lng" in r) {
265
+ let n = e.points[t], { lat: i, lng: a } = V(r.lat ?? n.lat, r.lng ?? n.lng);
266
+ r.lat = i, r.lng = a;
267
+ }
268
+ return W(e, e.points.map((e, n) => n === t ? {
269
+ ...e,
270
+ ...r
271
+ } : e));
272
+ }
273
+ function J(e, t) {
274
+ return U(t, e.points.length) ? W(e, e.points.filter((e, n) => n !== t)) : e;
275
+ }
276
+ function Y(e, t, n) {
277
+ let r = e.points.length;
278
+ if (!U(t, r) || !U(n, r) || t === n) return e;
279
+ let i = [...e.points], [a] = i.splice(t, 1);
280
+ return i.splice(n, 0, a), W(e, i);
281
+ }
282
+ function X(e, t, n, r, i = {}) {
283
+ if (!U(t, Math.max(0, e.points.length - 1))) return e;
284
+ let a = H(n, r, i, "stop"), o = [...e.points];
285
+ return o.splice(t + 1, 0, a), W(e, o);
286
+ }
287
+ function Z(e, t) {
288
+ if (t === null) {
289
+ let t = { ...e };
290
+ return delete t.viewport, t;
291
+ }
292
+ return {
293
+ ...e,
294
+ viewport: t
295
+ };
296
+ }
297
+ function Q(e, t, n) {
298
+ return e === null ? null : e === t ? n : t < e && e <= n ? e - 1 : n <= e && e < t ? e + 1 : e;
299
+ }
300
+ function $(e, t) {
301
+ return e === null || e === t ? null : e > t ? e - 1 : e;
302
+ }
303
+ function oe(e, t, n, r, i, a) {
304
+ let o = i - n, s = a - r, c = o * o + s * s, l = c === 0 ? 0 : Math.max(0, Math.min(1, ((e - n) * o + (t - r) * s) / c)), u = n + l * o, d = r + l * s, f = e - u, p = t - d;
305
+ return {
306
+ distSq: f * f + p * p,
307
+ t: l
308
+ };
309
+ }
310
+ function se(e, t, n) {
311
+ if (e.length < 2) return null;
312
+ let r = {
313
+ segmentIndex: 0,
314
+ distSq: Infinity,
315
+ t: 0
316
+ };
317
+ for (let i = 0; i < e.length - 1; i++) {
318
+ let a = e[i], o = e[i + 1], { distSq: s, t: c } = oe(n, t, a.lng, a.lat, o.lng, o.lat);
319
+ s < r.distSq && (r = {
320
+ segmentIndex: i,
321
+ distSq: s,
322
+ t: c
323
+ });
324
+ }
325
+ let i = e[r.segmentIndex], a = e[r.segmentIndex + 1];
326
+ return {
327
+ segmentIndex: r.segmentIndex,
328
+ lat: i.lat + r.t * (a.lat - i.lat),
329
+ lng: i.lng + r.t * (a.lng - i.lng)
330
+ };
331
+ }
332
+ //#endregion
333
+ //#region src/internal/use-map-editor.ts
334
+ function ce(e) {
335
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
336
+ }
337
+ function le(e) {
338
+ return /[;"'<>]/.test(e) ? "#3b82f6" : e;
339
+ }
340
+ function ue(e, n) {
341
+ let r = y(null), i = g(!1), a = null, o = /* @__PURE__ */ new Map(), s = null, c = !1, l = g(null), u = g(!1), d = t(() => {
342
+ let e = n.selected();
343
+ return e === null ? null : n.data().points[e] ?? null;
344
+ }), f = t(() => !n.readonly() && d.value !== null);
345
+ function h(e) {
346
+ n.emitData(e);
347
+ }
348
+ function _(e) {
349
+ let t = n.data().points[e];
350
+ t && (n.emitSelected(e), n.emitPointClick({
351
+ point: t,
352
+ index: e
353
+ }));
354
+ }
355
+ function v(e, t) {
356
+ let n = le(j(e, t)), r = M(e, t);
357
+ return a.divIcon({
358
+ className: "coar-map-pin-wrap",
359
+ html: `<span class="coar-map-pin" style="--coar-map-pin-color:${n}"><span class="coar-map-pin__emoji">${ce(r)}</span></span>`,
360
+ iconSize: [26, 26],
361
+ iconAnchor: [13, 13]
362
+ });
363
+ }
364
+ function b() {
365
+ return a.divIcon({
366
+ className: "coar-map-edit-vertex-wrap",
367
+ html: "<span class=\"coar-map-edit-vertex\"></span>",
368
+ iconSize: [14, 14],
369
+ iconAnchor: [7, 7]
370
+ });
371
+ }
372
+ function x() {
373
+ return n.data().points.map((e, t) => {
374
+ let n = o.get(t)?.getLatLng();
375
+ return n ? [n.lat, n.lng] : [e.lat, e.lng];
376
+ });
377
+ }
378
+ function C() {
379
+ s && s.setLatLngs(x());
380
+ }
381
+ function w(e, t, i) {
382
+ let s = r.value;
383
+ if (!s || !a) return;
384
+ let l = n.readonly(), u = e.kind === "stop" ? v(e, i) : b(), d = a.marker([e.lat, e.lng], {
385
+ icon: u,
386
+ draggable: !l
387
+ });
388
+ e.label && d.bindTooltip(ce(e.label)), d.on("click", () => _(t)), l || (d.on("dragstart", () => {
389
+ c = !0;
390
+ }), d.on("drag", C), d.on("dragend", () => {
391
+ c = !1;
392
+ let e = d.getLatLng();
393
+ h(K(n.data(), t, e.lat, e.lng));
394
+ })), d.addTo(s), o.set(t, d);
395
+ }
396
+ function T() {
397
+ for (let e of o.values()) e.remove();
398
+ o.clear(), s?.remove(), s = null;
399
+ }
400
+ function E() {
401
+ let e = r.value, t = n.config();
402
+ if (!e || !a || !t) return;
403
+ T();
404
+ let i = n.data(), o = n.readonly();
405
+ i.type === "route" && i.points.length >= 2 && (s = a.polyline(i.points.map((e) => [e.lat, e.lng]), {
406
+ color: "#3b82f6",
407
+ weight: 4,
408
+ opacity: .85,
409
+ bubblingMouseEvents: !1
410
+ }).addTo(e), o || s.on("click", A)), i.points.forEach((e, n) => {
411
+ (e.kind === "stop" || e.label || !o) && w(e, n, t);
412
+ }), O();
413
+ }
414
+ function D(e) {
415
+ return o.get(e)?.getElement() ?? null;
416
+ }
417
+ function O() {
418
+ let e = n.selected();
419
+ for (let t of o.keys()) D(t)?.classList.toggle("coar-map-marker--selected", t === e);
420
+ }
421
+ function k(e) {
422
+ if (!n.readonly()) {
423
+ if (n.selected() !== null) {
424
+ n.emitSelected(null);
425
+ return;
426
+ }
427
+ h(G(n.data(), e.latlng.lat, e.latlng.lng));
428
+ }
429
+ }
430
+ function A(e) {
431
+ if (n.readonly()) return;
432
+ let t = se(n.data().points, e.latlng.lat, e.latlng.lng);
433
+ t && (h(X(n.data(), t.segmentIndex, t.lat, t.lng)), n.emitSelected(null));
434
+ }
435
+ function N() {
436
+ let e = r.value, t = d.value;
437
+ if (!e || !t || n.readonly()) {
438
+ l.value = null;
439
+ return;
440
+ }
441
+ let i = e.latLngToContainerPoint([t.lat, t.lng]);
442
+ l.value = {
443
+ x: i.x,
444
+ y: i.y
445
+ }, u.value = i.y < 190;
446
+ }
447
+ function P(e) {
448
+ let t = n.selected();
449
+ t !== null && h(q(n.data(), t, e));
450
+ }
451
+ function L() {
452
+ let e = n.selected();
453
+ e !== null && V(e);
454
+ }
455
+ function ee(e) {
456
+ let t = n.selected();
457
+ t !== null && H(t, t + e);
458
+ }
459
+ function R() {
460
+ n.selected() !== null && n.emitSelected(null);
461
+ }
462
+ function z(e) {
463
+ e.key === "Escape" && !n.readonly() && n.selected() !== null && (e.stopPropagation(), R());
464
+ }
465
+ function te() {
466
+ T(), r.value &&= (r.value.remove(), null), i.value = !1;
467
+ }
468
+ async function ne() {
469
+ let t = e.value, o = n.config();
470
+ if (!t || !o) return;
471
+ te();
472
+ let s = await import("leaflet");
473
+ if (a = s.default ?? s, await import("leaflet/dist/leaflet.css"), e.value !== t) return;
474
+ let c = a.map(t);
475
+ r.value = c;
476
+ let l = n.data(), u = F(l, o);
477
+ u && a.tileLayer(u.url, {
478
+ subdomains: u.subdomains ?? "abc",
479
+ attribution: u.attribution,
480
+ maxZoom: u.maxZoom ?? 19
481
+ }).addTo(c), c.on("click", k), c.on("move zoom resize", N), E();
482
+ let d = l.viewport;
483
+ if (d) c.setView([d.centerLat, d.centerLng], d.zoom);
484
+ else {
485
+ let e = I(l.points);
486
+ e ? c.fitBounds(e, { padding: [28, 28] }) : c.setView([0, 0], 2);
487
+ }
488
+ requestAnimationFrame(() => r.value?.invalidateSize()), i.value = !0, N();
489
+ }
490
+ function re(e) {
491
+ let t = n.data().points[e];
492
+ !t || !r.value || (r.value.panTo([t.lat, t.lng]), n.selected() !== e && n.emitSelected(e));
493
+ }
494
+ function ie(e) {
495
+ for (let t of o.keys()) D(t)?.classList.toggle("coar-map-marker--highlight", t === e);
496
+ }
497
+ function ae(e, t, r) {
498
+ h(G(n.data(), e, t, r));
499
+ }
500
+ function B(e, t) {
501
+ h(q(n.data(), e, t));
502
+ }
503
+ function V(e) {
504
+ let t = n.selected();
505
+ h(J(n.data(), e)), n.emitSelected($(t, e));
506
+ }
507
+ function H(e, t) {
508
+ let r = Y(n.data(), e, t);
509
+ r !== n.data() && (h(r), n.emitSelected(Q(n.selected(), e, t)));
510
+ }
511
+ function U() {
512
+ let e = r.value;
513
+ if (!e) return;
514
+ let t = e.getCenter();
515
+ h(Z(n.data(), {
516
+ centerLat: t.lat,
517
+ centerLng: t.lng,
518
+ zoom: e.getZoom()
519
+ }));
520
+ }
521
+ return m(() => {
522
+ window.addEventListener("keydown", z), ne();
523
+ }), p(() => {
524
+ window.removeEventListener("keydown", z), te();
525
+ }), S(n.config, () => void ne()), S(n.data, () => {
526
+ c || E(), N();
527
+ }, { deep: !0 }), S([n.selected, n.readonly], () => {
528
+ O(), N();
529
+ }), {
530
+ ready: i,
531
+ editPos: l,
532
+ editBelow: u,
533
+ selectedPoint: d,
534
+ editing: f,
535
+ updateSelected: P,
536
+ removeSelected: L,
537
+ moveSelected: ee,
538
+ deselect: R,
539
+ focusPoint: re,
540
+ highlightPoint: ie,
541
+ addPoint: ae,
542
+ updatePoint: B,
543
+ removePoint: V,
544
+ reorder: H,
545
+ captureViewport: U
546
+ };
547
+ }
548
+ //#endregion
549
+ //#region src/internal/MapPointForm.vue?vue&type=script&setup=true&lang.ts
550
+ var de = { class: "coar-map-form" }, fe = { class: "coar-map-form__field" }, pe = { class: "coar-map-form__field" }, me = {
551
+ key: 0,
552
+ class: "coar-map-form__field"
553
+ }, he = { class: "coar-map-form__field" }, ge = { class: "coar-map-form__actions" }, _e = /* @__PURE__ */ l({
554
+ __name: "MapPointForm",
555
+ props: {
556
+ point: {},
557
+ config: {},
558
+ type: {},
559
+ index: {},
560
+ count: {}
561
+ },
562
+ emits: [
563
+ "update",
564
+ "remove",
565
+ "move-up",
566
+ "move-down"
567
+ ],
568
+ setup(n, { emit: o }) {
569
+ let l = n, u = o, d = t(() => l.point.kind === "stop"), f = t(() => l.type === "route" && l.count > 1), p = t(() => (l.config?.categories ?? []).map((e) => ({
570
+ value: e.id,
571
+ label: e.emoji ? `${e.emoji} ${e.label}` : e.label
572
+ })));
573
+ function m(e, t) {
574
+ u("update", { [e]: t === "" ? void 0 : t });
575
+ }
576
+ function g(e) {
577
+ u("update", { category: e || void 0 });
578
+ }
579
+ return (t, o) => (h(), i("div", de, [
580
+ a("label", fe, [o[8] ||= a("span", { class: "coar-map-form__label" }, "Label", -1), c(x(E), {
581
+ "model-value": n.point.label ?? "",
582
+ size: "s",
583
+ "onUpdate:modelValue": o[0] ||= (e) => m("label", e)
584
+ }, null, 8, ["model-value"])]),
585
+ a("label", pe, [o[9] ||= a("span", { class: "coar-map-form__label" }, "Note", -1), c(x(E), {
586
+ "model-value": n.point.note ?? "",
587
+ rows: 2,
588
+ size: "s",
589
+ "onUpdate:modelValue": o[1] ||= (e) => m("note", e)
590
+ }, null, 8, ["model-value"])]),
591
+ d.value ? (h(), i(e, { key: 0 }, [p.value.length ? (h(), i("label", me, [o[10] ||= a("span", { class: "coar-map-form__label" }, "Category", -1), c(x(T), {
592
+ "model-value": n.point.category ?? null,
593
+ options: p.value,
594
+ size: "s",
595
+ clearable: "",
596
+ placeholder: "None",
597
+ "onUpdate:modelValue": o[2] ||= (e) => g(e)
598
+ }, null, 8, ["model-value", "options"])])) : r("", !0), a("label", he, [o[11] ||= a("span", { class: "coar-map-form__label" }, "Icon", -1), c(x(E), {
599
+ "model-value": n.point.icon ?? "",
600
+ size: "s",
601
+ placeholder: "emoji",
602
+ "onUpdate:modelValue": o[3] ||= (e) => m("icon", e)
603
+ }, null, 8, ["model-value"])])], 64)) : r("", !0),
604
+ a("div", ge, [
605
+ c(x(w), {
606
+ variant: "secondary",
607
+ size: "s",
608
+ onClick: o[4] ||= (e) => u("update", { kind: d.value ? "shape" : "stop" })
609
+ }, {
610
+ default: C(() => [s(b(d.value ? "Make vertex" : "Make stop"), 1)]),
611
+ _: 1
612
+ }),
613
+ f.value ? (h(), i(e, { key: 0 }, [c(x(w), {
614
+ variant: "tertiary",
615
+ size: "s",
616
+ disabled: n.index === 0,
617
+ "aria-label": "Move earlier",
618
+ onClick: o[5] ||= (e) => u("move-up")
619
+ }, {
620
+ default: C(() => [...o[12] ||= [s("↑", -1)]]),
621
+ _: 1
622
+ }, 8, ["disabled"]), c(x(w), {
623
+ variant: "tertiary",
624
+ size: "s",
625
+ disabled: n.index === n.count - 1,
626
+ "aria-label": "Move later",
627
+ onClick: o[6] ||= (e) => u("move-down")
628
+ }, {
629
+ default: C(() => [...o[13] ||= [s("↓", -1)]]),
630
+ _: 1
631
+ }, 8, ["disabled"])], 64)) : r("", !0),
632
+ c(x(w), {
633
+ class: "coar-map-form__delete",
634
+ variant: "danger",
635
+ size: "s",
636
+ onClick: o[7] ||= (e) => u("remove")
637
+ }, {
638
+ default: C(() => [...o[14] ||= [s(" Delete ", -1)]]),
639
+ _: 1
640
+ })
641
+ ])
642
+ ]));
643
+ }
644
+ }), ve = { class: "coar-map-editor__stage" }, ye = { class: "coar-map-edit-popup__close" }, be = {
645
+ key: 0,
646
+ class: "coar-map__caption"
647
+ }, xe = {
648
+ key: 1,
649
+ class: "coar-map__nocfg"
650
+ }, Se = /* @__PURE__ */ l({
651
+ __name: "CoarMapEditor",
652
+ props: {
653
+ data: {},
654
+ config: {},
655
+ selected: {},
656
+ readonly: { type: Boolean }
657
+ },
658
+ emits: [
659
+ "update:data",
660
+ "update:selected",
661
+ "point-click"
662
+ ],
663
+ setup(e, { expose: n, emit: o }) {
664
+ let l = e, p = o, m = u(k, void 0), _ = t(() => l.config ?? m ?? null), y = g(null), { ready: S, editPos: T, editBelow: E, selectedPoint: D, editing: O, updateSelected: A, removeSelected: j, moveSelected: M, deselect: N, focusPoint: P, highlightPoint: F, addPoint: I, updatePoint: L, removePoint: ee, reorder: R, captureViewport: z } = ue(y, {
665
+ data: () => l.data,
666
+ config: () => _.value,
667
+ selected: () => l.selected ?? null,
668
+ readonly: () => !!l.readonly,
669
+ emitData: (e) => p("update:data", e),
670
+ emitSelected: (e) => p("update:selected", e),
671
+ emitPointClick: (e) => p("point-click", e)
672
+ });
673
+ return n({
674
+ focusPoint: P,
675
+ highlightPoint: F,
676
+ addPoint: I,
677
+ updatePoint: L,
678
+ removePoint: ee,
679
+ reorder: R,
680
+ captureViewport: z
681
+ }), (t, n) => (h(), i("div", { class: d(["coar-map coar-map-editor", { "coar-map--ready": x(S) }]) }, [
682
+ a("div", ve, [a("div", {
683
+ ref_key: "mapEl",
684
+ ref: y,
685
+ class: "coar-map__canvas"
686
+ }, null, 512), x(O) && x(T) && x(D) && e.selected != null ? (h(), i("div", {
687
+ key: 0,
688
+ class: d(["coar-map-edit-popup", { "coar-map-edit-popup--below": x(E) }]),
689
+ style: f({
690
+ left: `${x(T).x}px`,
691
+ top: `${x(T).y}px`
692
+ })
693
+ }, [a("div", ye, [c(x(w), {
694
+ variant: "ghost",
695
+ size: "xs",
696
+ "aria-label": "Close",
697
+ onClick: x(N)
698
+ }, {
699
+ default: C(() => [...n[2] ||= [s("×", -1)]]),
700
+ _: 1
701
+ }, 8, ["onClick"])]), v(t.$slots, "point-form", {
702
+ point: x(D),
703
+ index: e.selected,
704
+ update: x(A),
705
+ remove: x(j),
706
+ moveUp: () => x(M)(-1),
707
+ moveDown: () => x(M)(1)
708
+ }, () => [c(_e, {
709
+ point: x(D),
710
+ config: _.value,
711
+ type: e.data.type,
712
+ index: e.selected,
713
+ count: e.data.points.length,
714
+ onUpdate: x(A),
715
+ onRemove: x(j),
716
+ onMoveUp: n[0] ||= (e) => x(M)(-1),
717
+ onMoveDown: n[1] ||= (e) => x(M)(1)
718
+ }, null, 8, [
719
+ "point",
720
+ "config",
721
+ "type",
722
+ "index",
723
+ "count",
724
+ "onUpdate",
725
+ "onRemove"
726
+ ])])], 6)) : r("", !0)]),
727
+ e.data.caption ? (h(), i("p", be, b(e.data.caption), 1)) : r("", !0),
728
+ _.value ? r("", !0) : (h(), i("p", xe, [...n[3] ||= [
729
+ s("No map config provided (pass ", -1),
730
+ a("code", null, "config", -1),
731
+ s(" or provide one).", -1)
732
+ ]]))
733
+ ], 2));
734
+ }
735
+ }), Ce = ["onDragover", "onDrop"], we = ["onDragstart"], Te = ["onClick", "onMouseenter"], Ee = { class: "coar-map-point-list__emoji" }, De = { class: "coar-map-point-list__label" }, Oe = { class: "coar-map-point-list__coords" }, ke = {
736
+ key: 0,
737
+ class: "coar-map-point-list__empty"
738
+ }, Ae = /* @__PURE__ */ l({
739
+ __name: "CoarMapPointList",
740
+ props: {
741
+ data: {},
742
+ selected: {},
743
+ config: {},
744
+ reorderable: { type: Boolean },
745
+ removable: { type: Boolean }
746
+ },
747
+ emits: [
748
+ "update:data",
749
+ "update:selected",
750
+ "focus",
751
+ "highlight"
752
+ ],
753
+ setup(c, { emit: l }) {
754
+ let u = c, f = l, p = g(null), m = O({ onDropAccept: ({ items: e, insertIndex: t }) => {
755
+ let n = e[0];
756
+ n == null || t == null || k(n, t);
757
+ } }), y = t(() => u.data.points);
758
+ function S(e) {
759
+ return e.kind === "stop" ? u.config ? M(e, u.config) || "📍" : e.icon || "📍" : "◇";
760
+ }
761
+ function T(e) {
762
+ return e.label || (e.kind === "shape" ? "(vertex)" : "(unnamed stop)");
763
+ }
764
+ function E(e) {
765
+ f("update:selected", e), f("focus", e);
766
+ }
767
+ function k(e, t) {
768
+ let n = t > e ? t - 1 : t;
769
+ n = Math.max(0, Math.min(y.value.length - 1, n)), n !== e && (f("update:data", Y(u.data, e, n)), f("update:selected", Q(u.selected ?? null, e, n)));
770
+ }
771
+ function A(e) {
772
+ f("update:data", J(u.data, e)), f("update:selected", $(u.selected ?? null, e));
773
+ }
774
+ function j(e, t) {
775
+ let n = e.currentTarget?.closest(".coar-map-point-list__row");
776
+ n instanceof HTMLElement && D(e, n), m.startDrag(e, [t]);
777
+ }
778
+ function N(e, t) {
779
+ if (m.onDragOver(e), !m.isDragging.value) return;
780
+ let n = e.currentTarget.getBoundingClientRect();
781
+ p.value = {
782
+ index: t,
783
+ after: e.clientY > n.top + n.height / 2
784
+ };
785
+ }
786
+ function P(e, t) {
787
+ let n = p.value?.index === t ? p.value.after : !1;
788
+ m.onDrop(e, { insertIndex: n ? t + 1 : t }), p.value = null;
789
+ }
790
+ function F() {
791
+ m.endDrag(), p.value = null;
792
+ }
793
+ function I(e) {
794
+ return !!p.value && m.isDragging.value && p.value.index === e && !p.value.after;
795
+ }
796
+ function L(e) {
797
+ return !!p.value && m.isDragging.value && p.value.index === e && p.value.after;
798
+ }
799
+ return (t, l) => (h(), i("ul", {
800
+ class: "coar-map-point-list",
801
+ onDragleave: l[1] ||= (e) => x(m).onDragLeave(e)
802
+ }, [(h(!0), i(e, null, _(y.value, (e, u) => (h(), i("li", {
803
+ key: u,
804
+ class: d(["coar-map-point-list__row", {
805
+ "coar-map-point-list__row--selected": c.selected === u,
806
+ "coar-map-point-list__row--drop-before": I(u),
807
+ "coar-map-point-list__row--drop-after": L(u)
808
+ }]),
809
+ onDragover: (e) => c.reorderable && N(e, u),
810
+ onDrop: (e) => c.reorderable && P(e, u)
811
+ }, [
812
+ c.reorderable ? (h(), i("button", {
813
+ key: 0,
814
+ type: "button",
815
+ class: "coar-map-point-list__handle",
816
+ "aria-label": "Drag to reorder",
817
+ draggable: "true",
818
+ onDragstart: (e) => j(e, u),
819
+ onDragend: F
820
+ }, [...l[2] ||= [o("<svg viewBox=\"0 0 10 16\" width=\"10\" height=\"16\" aria-hidden=\"true\"><circle cx=\"2.5\" cy=\"3\" r=\"1.2\"></circle><circle cx=\"7.5\" cy=\"3\" r=\"1.2\"></circle><circle cx=\"2.5\" cy=\"8\" r=\"1.2\"></circle><circle cx=\"7.5\" cy=\"8\" r=\"1.2\"></circle><circle cx=\"2.5\" cy=\"13\" r=\"1.2\"></circle><circle cx=\"7.5\" cy=\"13\" r=\"1.2\"></circle></svg>", 1)]], 40, we)) : r("", !0),
821
+ a("button", {
822
+ type: "button",
823
+ class: "coar-map-point-list__main",
824
+ onClick: (e) => E(u),
825
+ onMouseenter: (e) => f("highlight", u),
826
+ onMouseleave: l[0] ||= (e) => f("highlight", null)
827
+ }, [v(t.$slots, "row", {
828
+ point: e,
829
+ index: u,
830
+ selected: c.selected === u
831
+ }, () => [
832
+ a("span", Ee, b(S(e)), 1),
833
+ a("span", De, b(T(e)), 1),
834
+ a("span", Oe, b(e.lat.toFixed(3)) + ", " + b(e.lng.toFixed(3)), 1)
835
+ ])], 40, Te),
836
+ c.removable ? (h(), n(x(w), {
837
+ key: 1,
838
+ class: "coar-map-point-list__delete",
839
+ variant: "ghost",
840
+ size: "xs",
841
+ "aria-label": "Delete point",
842
+ onClick: (e) => A(u)
843
+ }, {
844
+ default: C(() => [...l[3] ||= [s("✕", -1)]]),
845
+ _: 1
846
+ }, 8, ["onClick"])) : r("", !0)
847
+ ], 42, Ce))), 128)), y.value.length ? r("", !0) : (h(), i("li", ke, "No points yet."))], 32));
848
+ }
849
+ });
850
+ //#endregion
851
+ export { k as COAR_MAP_CONFIG_KEY, B as CoarMap, Se as CoarMapEditor, Ae as CoarMapPointList, G as addPointForType, I as boundsOf, A as categoryMap, N as fallbackEntries, X as insertOnSegment, P as legendCategories, K as movePoint, se as nearestSegment, V as normalizeLatLng, J as removePoint, Y as reorderPoint, F as resolveBasemap, $ as selectionAfterRemove, Q as selectionAfterReorder, Z as setViewport, j as stopColor, M as stopEmoji, q as updatePoint };