@phila/layerboard 2.2.0 → 3.0.0-beta.1

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.mjs ADDED
@@ -0,0 +1,2603 @@
1
+ import { defineComponent as we, ref as $, watch as xe, computed as R, onMounted as Ze, onUnmounted as Lt, createElementBlock as L, openBlock as f, createVNode as ee, unref as _, withCtx as Ne, createBlock as X, createCommentVNode as I, Fragment as ie, renderList as re, useAttrs as Ft, toRef as Mt, normalizeClass as ne, createElementVNode as F, toDisplayString as j, withDirectives as St, mergeProps as ot, vModelDynamic as Et, createTextVNode as he, normalizeProps as dt, guardReactiveProps as ft, renderSlot as se, withModifiers as zt, normalizeStyle as Y, readonly as V, provide as U, resolveComponent as _t, vShow as It } from "vue";
2
+ import { Map as Ot, DrawTool as Rt, RasterLayer as pt, CircleLayer as yt, FillLayer as Dt, LineLayer as et, MapMarker as At, MapPopup as Nt } from "@phila/phila-ui-map-core";
3
+ import { cn as nt, Icon as me, BaseLink as Zt, ActionContent as gt } from "@phila/phila-ui-core";
4
+ function Ue(e, n, o = {}) {
5
+ const t = { type: "Feature" };
6
+ return (o.id === 0 || o.id) && (t.id = o.id), o.bbox && (t.bbox = o.bbox), t.properties = n || {}, t.geometry = e, t;
7
+ }
8
+ function Bt(e, n, o = {}) {
9
+ for (const l of e) {
10
+ if (l.length < 4)
11
+ throw new Error(
12
+ "Each LinearRing of a Polygon must have 4 or more Positions."
13
+ );
14
+ if (l[l.length - 1].length !== l[0].length)
15
+ throw new Error("First and last Position are not equivalent.");
16
+ for (let a = 0; a < l[l.length - 1].length; a++)
17
+ if (l[l.length - 1][a] !== l[0][a])
18
+ throw new Error("First and last Position are not equivalent.");
19
+ }
20
+ return Ue({
21
+ type: "Polygon",
22
+ coordinates: e
23
+ }, n, o);
24
+ }
25
+ function Wt(e, n, o = {}) {
26
+ if (e.length < 2)
27
+ throw new Error("coordinates must be an array of two or more positions");
28
+ return Ue({
29
+ type: "LineString",
30
+ coordinates: e
31
+ }, n, o);
32
+ }
33
+ function Ut(e, n, o = {}) {
34
+ return Ue({
35
+ type: "MultiLineString",
36
+ coordinates: e
37
+ }, n, o);
38
+ }
39
+ function Vt(e, n, o = {}) {
40
+ return Ue({
41
+ type: "MultiPolygon",
42
+ coordinates: e
43
+ }, n, o);
44
+ }
45
+ function jt(e) {
46
+ return e.type === "Feature" ? e.geometry : e;
47
+ }
48
+ function qt(e, n, o) {
49
+ var t = e.length, l = Te(e[0], n), a = [], c, p, d;
50
+ let S, y;
51
+ for (o || (o = []), c = 1; c < t; c++) {
52
+ for (S = e[c - 1], y = e[c], p = d = Te(y, n); ; )
53
+ if (l | p) {
54
+ if (l & p)
55
+ break;
56
+ l ? (S = it(S, y, l, n), l = Te(S, n)) : (y = it(S, y, p, n), p = Te(y, n));
57
+ } else {
58
+ a.push(S), p !== d ? (a.push(y), c < t - 1 && (o.push(a), a = [])) : c === t - 1 && a.push(y);
59
+ break;
60
+ }
61
+ l = d;
62
+ }
63
+ return a.length && o.push(a), o;
64
+ }
65
+ function Gt(e, n) {
66
+ var o, t, l, a, c, p, d;
67
+ for (t = 1; t <= 8; t *= 2) {
68
+ for (o = [], l = e[e.length - 1], a = !(Te(l, n) & t), c = 0; c < e.length; c++)
69
+ p = e[c], d = !(Te(p, n) & t), d !== a && o.push(it(l, p, t, n)), d && o.push(p), l = p, a = d;
70
+ if (e = o, !e.length) break;
71
+ }
72
+ return o;
73
+ }
74
+ function it(e, n, o, t) {
75
+ return o & 8 ? [e[0] + (n[0] - e[0]) * (t[3] - e[1]) / (n[1] - e[1]), t[3]] : o & 4 ? [e[0] + (n[0] - e[0]) * (t[1] - e[1]) / (n[1] - e[1]), t[1]] : o & 2 ? [t[2], e[1] + (n[1] - e[1]) * (t[2] - e[0]) / (n[0] - e[0])] : o & 1 ? [t[0], e[1] + (n[1] - e[1]) * (t[0] - e[0]) / (n[0] - e[0])] : null;
76
+ }
77
+ function Te(e, n) {
78
+ var o = 0;
79
+ return e[0] < n[0] ? o |= 1 : e[0] > n[2] && (o |= 2), e[1] < n[1] ? o |= 4 : e[1] > n[3] && (o |= 8), o;
80
+ }
81
+ function Ht(e, n) {
82
+ const o = jt(e), t = o.type, l = e.type === "Feature" ? e.properties : {};
83
+ let a = o.coordinates;
84
+ switch (t) {
85
+ case "LineString":
86
+ case "MultiLineString": {
87
+ const c = [];
88
+ return t === "LineString" && (a = [a]), a.forEach((p) => {
89
+ qt(p, n, c);
90
+ }), c.length === 1 ? Wt(c[0], l) : Ut(c, l);
91
+ }
92
+ case "Polygon":
93
+ return Bt(mt(a, n), l);
94
+ case "MultiPolygon":
95
+ return Vt(
96
+ a.map((c) => mt(c, n)),
97
+ l
98
+ );
99
+ default:
100
+ throw new Error("geometry " + t + " not supported");
101
+ }
102
+ }
103
+ function mt(e, n) {
104
+ const o = [];
105
+ for (const t of e) {
106
+ const l = Gt(t, n);
107
+ l.length > 0 && ((l[0][0] !== l[l.length - 1][0] || l[0][1] !== l[l.length - 1][1]) && l.push(l[0]), l.length >= 4 && o.push(l));
108
+ }
109
+ return o;
110
+ }
111
+ var Jt = Ht;
112
+ const Qt = { class: "map-panel" }, Kt = /* @__PURE__ */ we({
113
+ __name: "MapPanel",
114
+ props: {
115
+ visibleLayers: {},
116
+ layerOpacities: {},
117
+ layerList: {},
118
+ tiledLayers: {},
119
+ visibleTiledLayers: {},
120
+ tiledLayerOpacities: {},
121
+ cyclomediaConfig: {},
122
+ pictometryCredentials: {},
123
+ basemapControlPosition: { default: "top-right" },
124
+ navigationControlPosition: { default: "bottom-right" },
125
+ geolocationControlPosition: { default: "bottom-right" },
126
+ searchControlPosition: { default: "top-left" },
127
+ drawControlPosition: { default: "bottom-left" },
128
+ cyclomediaButtonPosition: { default: "top-right" },
129
+ pictometryButtonPosition: { default: "top-right" },
130
+ initialZoom: {},
131
+ initialCenter: {}
132
+ },
133
+ emits: ["zoom", "layerLoading", "layerError"],
134
+ setup(e, { emit: n }) {
135
+ const o = e, t = n, l = $(null), a = $(null), c = $(0);
136
+ function p(i) {
137
+ t("zoom", i), a.value && (c.value = d(a.value));
138
+ }
139
+ function d(i) {
140
+ const u = i.getZoom(), x = i.getCenter().lat, k = 559082264028e-3, T = x * Math.PI / 180;
141
+ return k * Math.cos(T) / Math.pow(2, u);
142
+ }
143
+ const S = $({}), y = $(null), h = $(/* @__PURE__ */ new Set()), s = ["fema-100-year-floodplain", "fema-500-year-floodplain"];
144
+ async function v(i, u, r, x) {
145
+ const k = encodeURIComponent(x || "1=1"), T = JSON.stringify({
146
+ xmin: u.west,
147
+ ymin: u.south,
148
+ xmax: u.east,
149
+ ymax: u.north,
150
+ spatialReference: { wkid: 4326 }
151
+ }), O = 2e3;
152
+ let B = 0, W = [], K = !0;
153
+ for (; K; ) {
154
+ const G = `${i}/query?where=${k}&geometry=${encodeURIComponent(T)}&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&outFields=*&returnGeometry=true&resultRecordCount=${O}&resultOffset=${B}&f=geojson`, A = await fetch(G);
155
+ if (!A.ok)
156
+ throw new Error(`HTTP ${A.status}: ${A.statusText}`);
157
+ const H = await A.json();
158
+ H.features && H.features.length > 0 ? (W = W.concat(H.features), B += H.features.length, K = H.features.length === O) : K = !1;
159
+ }
160
+ if (s.includes(r)) {
161
+ const G = [u.west, u.south, u.east, u.north];
162
+ W = W.map((A) => {
163
+ if (A.geometry && (A.geometry.type === "Polygon" || A.geometry.type === "MultiPolygon"))
164
+ try {
165
+ return Jt(A, G);
166
+ } catch (H) {
167
+ return console.warn(`Failed to clip feature in ${r}:`, H), A;
168
+ }
169
+ return A;
170
+ });
171
+ }
172
+ return {
173
+ type: "FeatureCollection",
174
+ features: W
175
+ };
176
+ }
177
+ async function E(i, u) {
178
+ const r = u.map(async (x) => {
179
+ const k = o.layerList.find((T) => T.config.id === x)?.config;
180
+ if (k) {
181
+ t("layerLoading", x, !0);
182
+ try {
183
+ const T = await v(k.url, i, x, k.where);
184
+ S.value = { ...S.value, [x]: T }, t("layerError", x, null);
185
+ } catch (T) {
186
+ const O = T instanceof Error ? T.message : "Failed to load";
187
+ t("layerError", x, O), console.error(`Error loading ${x}:`, T);
188
+ } finally {
189
+ t("layerLoading", x, !1);
190
+ }
191
+ }
192
+ });
193
+ await Promise.all(r);
194
+ }
195
+ async function m(i) {
196
+ const u = [...o.visibleLayers];
197
+ await E(i, u);
198
+ }
199
+ function C(i) {
200
+ y.value = i.bounds, m(i.bounds);
201
+ }
202
+ function g(i) {
203
+ a.value = i;
204
+ const u = i.getBounds();
205
+ y.value = {
206
+ west: u.getWest(),
207
+ south: u.getSouth(),
208
+ east: u.getEast(),
209
+ north: u.getNorth()
210
+ };
211
+ const r = i.getZoom();
212
+ t("zoom", r), c.value = d(i), m(y.value);
213
+ }
214
+ xe(
215
+ () => o.visibleLayers.size,
216
+ async () => {
217
+ if (oe.value.length > 0 && te(), y.value) {
218
+ const i = new Set(o.visibleLayers), u = [...i].filter(
219
+ (r) => !h.value.has(r)
220
+ );
221
+ h.value = new Set(i), u.length > 0 && await E(y.value, u);
222
+ }
223
+ }
224
+ );
225
+ function w(i) {
226
+ return o.visibleLayers.has(i);
227
+ }
228
+ function z(i) {
229
+ return !!S.value[i.id];
230
+ }
231
+ const M = R(
232
+ () => o.layerList.filter((i) => i.config.type === "circle" && w(i.config.id) && z(i.config)).map((i) => i.config)
233
+ ), N = R(
234
+ () => o.layerList.filter((i) => i.config.type === "fill" && w(i.config.id) && z(i.config)).map((i) => i.config)
235
+ ), q = R(
236
+ () => o.layerList.filter((i) => i.config.type === "fill" && i.config.outlinePaint && w(i.config.id) && z(i.config)).map((i) => i.config)
237
+ ), ce = R(
238
+ () => o.layerList.filter((i) => i.config.type === "line" && w(i.config.id) && z(i.config)).map((i) => i.config)
239
+ );
240
+ function Le(i) {
241
+ return o.visibleTiledLayers?.has(i) ?? !1;
242
+ }
243
+ function Se(i) {
244
+ return o.tiledLayerOpacities?.[i] ?? 1;
245
+ }
246
+ function je(i) {
247
+ return `${i.replace(/\/$/, "")}/tile/{z}/{y}/{x}`;
248
+ }
249
+ function qe(i) {
250
+ return {
251
+ type: "raster",
252
+ tiles: [je(i.url)],
253
+ tileSize: 256,
254
+ attribution: i.attribution || ""
255
+ };
256
+ }
257
+ const Me = $({}), Ie = $(/* @__PURE__ */ new Set());
258
+ async function Ee(i) {
259
+ if (!Ie.value.has(i.id)) {
260
+ Ie.value.add(i.id);
261
+ try {
262
+ const u = i.url.replace(/\/$/, ""), r = await fetch(`${u}?f=json`);
263
+ if (!r.ok) {
264
+ console.warn(`[MapPanel] Failed to fetch metadata for ${i.id}: ${r.status}`);
265
+ return;
266
+ }
267
+ const x = await r.json();
268
+ let k = x.minScale || 0, T = x.maxScale || 0;
269
+ if (x.layers && x.layers.length > 0)
270
+ for (const O of x.layers)
271
+ O.maxScale && O.maxScale > 0 && (T === 0 || O.maxScale < T) && (T = O.maxScale);
272
+ T === 0 && (T = 72e3), Me.value = {
273
+ ...Me.value,
274
+ [i.id]: { minScale: k, maxScale: T }
275
+ }, console.log(`[MapPanel] Fetched scale metadata for ${i.id}: minScale=${k}, maxScale=${T}`);
276
+ } catch (u) {
277
+ console.warn(`[MapPanel] Error fetching metadata for ${i.id}:`, u);
278
+ }
279
+ }
280
+ }
281
+ Ze(() => {
282
+ if (o.tiledLayers)
283
+ for (const i of o.tiledLayers)
284
+ i.scaleBasedRendering && Ee(i);
285
+ });
286
+ function Oe(i) {
287
+ if (!i.scaleBasedRendering)
288
+ return "tiled";
289
+ const u = Me.value[i.id];
290
+ if (!u)
291
+ return "tiled";
292
+ const r = c.value;
293
+ return r === 0 || r > u.maxScale ? "tiled" : "dynamic";
294
+ }
295
+ const Ge = R(() => o.tiledLayers ? o.tiledLayers.filter((i) => Le(i.id) ? i.scaleBasedRendering ? Oe(i) === "tiled" : !0 : !1) : []), He = R(() => o.tiledLayers ? o.tiledLayers.filter((i) => Le(i.id) && i.scaleBasedRendering ? Oe(i) === "dynamic" : !1) : []);
296
+ function Ce(i) {
297
+ return {
298
+ type: "raster",
299
+ tiles: [`${i.url.replace(/\/$/, "")}/export?bbox={bbox-epsg-3857}&bboxSR=3857&imageSR=3857&size=256,256&format=png32&transparent=true&f=image`],
300
+ tileSize: 256,
301
+ attribution: i.attribution || ""
302
+ };
303
+ }
304
+ function de(i) {
305
+ return { type: "geojson", data: S.value[i.id] };
306
+ }
307
+ function ke(i) {
308
+ return o.layerOpacities[i] ?? 1;
309
+ }
310
+ function fe(i) {
311
+ const u = ke(i.id), r = i.type === "circle" ? "circle-opacity" : i.type === "fill" ? "fill-opacity" : "line-opacity";
312
+ if (i.type === "fill" && i.paint["fill-opacity"] === 0)
313
+ return { ...i.paint, "fill-opacity": 0 };
314
+ const x = i.type === "circle" ? "circle-color" : i.type === "fill" ? "fill-color" : "line-color", k = { ...i.paint }, T = k[x], O = k[r] === 1, B = typeof T == "string" && T.startsWith("rgba(");
315
+ if (O && B) {
316
+ if (u === 1)
317
+ return k;
318
+ {
319
+ const W = T.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);
320
+ if (W && W[4]) {
321
+ const [, K, G, A, H] = W, Ye = parseFloat(H) * u;
322
+ k[x] = `rgba(${K}, ${G}, ${A}, ${Ye})`, k[r] = 1;
323
+ }
324
+ return k;
325
+ }
326
+ }
327
+ if (B) {
328
+ const W = T.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);
329
+ if (W) {
330
+ const [, K, G, A] = W;
331
+ k[x] = `rgb(${K}, ${G}, ${A})`;
332
+ }
333
+ }
334
+ return k[r] = u, k;
335
+ }
336
+ function Je(i) {
337
+ const u = ke(i.id);
338
+ return { ...i.outlinePaint, "line-opacity": u };
339
+ }
340
+ const oe = $([]), pe = $(null), J = $(0);
341
+ function $e(i) {
342
+ const u = i.replace(/-outline$/, "");
343
+ return o.layerList.find((x) => x.config.id === u)?.config;
344
+ }
345
+ function ve(i, u) {
346
+ return i.replace(/\{([^}]+)\}/g, (r, x) => {
347
+ const k = u[x];
348
+ return k == null ? "" : String(k);
349
+ });
350
+ }
351
+ function Qe(i, u) {
352
+ if (i == null) return "-";
353
+ if (u?.dateFormat && typeof i == "number") {
354
+ const r = new Date(i);
355
+ switch (u.dateFormat) {
356
+ case "shortDateShortTime":
357
+ return r.toLocaleString();
358
+ case "longMonthDayYear":
359
+ return r.toLocaleDateString(void 0, { month: "long", day: "numeric", year: "numeric" });
360
+ case "shortDate":
361
+ return r.toLocaleDateString();
362
+ case "longDate":
363
+ return r.toLocaleDateString(void 0, { weekday: "long", month: "long", day: "numeric", year: "numeric" });
364
+ default:
365
+ return r.toLocaleDateString();
366
+ }
367
+ }
368
+ if (typeof i == "number") {
369
+ if (i > 1e12 && !u)
370
+ return new Date(i).toLocaleDateString();
371
+ const r = u?.places, x = u?.digitSeparator ?? !0;
372
+ if (r !== void 0) {
373
+ const k = i.toFixed(r);
374
+ if (x) {
375
+ const T = k.split("."), O = T[0] || "0", B = T[1], W = O.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
376
+ return B ? `${W}.${B}` : W;
377
+ }
378
+ return k;
379
+ }
380
+ return x ? i.toLocaleString() : String(i);
381
+ }
382
+ return String(i);
383
+ }
384
+ function Re(i) {
385
+ const u = /* @__PURE__ */ new Set();
386
+ return i.filter((r) => {
387
+ const k = `${r.layer.id.replace(/-outline$/, "")}:${JSON.stringify(r.properties)}`;
388
+ return u.has(k) ? !1 : (u.add(k), !0);
389
+ });
390
+ }
391
+ function ye(i, u) {
392
+ const r = /* @__PURE__ */ new Map();
393
+ return u.forEach((x, k) => {
394
+ r.set(x.id, k);
395
+ }), i.sort((x, k) => {
396
+ const T = x.layer.id.replace(/-outline$/, ""), O = k.layer.id.replace(/-outline$/, ""), B = r.get(T) ?? -1;
397
+ return (r.get(O) ?? -1) - B;
398
+ });
399
+ }
400
+ function Pe(i) {
401
+ const u = a.value;
402
+ if (!u) return;
403
+ const r = [];
404
+ o.layerList.forEach((G) => {
405
+ const A = G.config;
406
+ o.visibleLayers.has(A.id) && (r.push(A.id), A.outlinePaint && r.push(`${A.id}-outline`));
407
+ });
408
+ const x = u.project([i.lngLat.lng, i.lngLat.lat]), k = u.queryRenderedFeatures(x, {
409
+ layers: r
410
+ });
411
+ if (k.length === 0) return;
412
+ const T = Re(k), O = o.layerList.map((G) => G.config), B = ye(T, O), W = B.map((G) => {
413
+ const A = G.layer.id.replace(/-outline$/, ""), H = $e(A);
414
+ return H ? {
415
+ layerId: H.id,
416
+ layerTitle: H.title,
417
+ properties: G.properties || {},
418
+ popupConfig: H.popup
419
+ } : null;
420
+ }).filter((G) => G !== null);
421
+ if (W.length === 0) return;
422
+ oe.value = W, J.value = 0, pe.value = [i.lngLat.lng, i.lngLat.lat];
423
+ const K = B[0];
424
+ if (K && K.geometry) {
425
+ const G = K.layer.id.replace(/-outline$/, ""), A = $e(G);
426
+ if (A) {
427
+ const H = rt(K.geometry), Ye = st(A.id, A.type);
428
+ ge.value = {
429
+ geometry: K.geometry,
430
+ geometryType: H,
431
+ layerId: A.id,
432
+ properties: K.properties || {},
433
+ originalStyle: Ye
434
+ };
435
+ }
436
+ }
437
+ }
438
+ function te() {
439
+ oe.value = [], pe.value = null, J.value = 0, ge.value = null;
440
+ }
441
+ function be(i) {
442
+ if (oe.value.length === 0) return;
443
+ const u = i.target;
444
+ if (!(u.tagName === "INPUT" || u.tagName === "TEXTAREA" || u.isContentEditable))
445
+ switch (i.key) {
446
+ case "ArrowLeft":
447
+ case "ArrowUp":
448
+ i.preventDefault(), De();
449
+ break;
450
+ case "ArrowRight":
451
+ case "ArrowDown":
452
+ i.preventDefault(), le();
453
+ break;
454
+ case "Escape":
455
+ i.preventDefault(), te();
456
+ break;
457
+ }
458
+ }
459
+ Ze(() => {
460
+ window.addEventListener("keydown", be);
461
+ }), Lt(() => {
462
+ window.removeEventListener("keydown", be);
463
+ });
464
+ function le() {
465
+ const i = oe.value.length;
466
+ i <= 1 || (J.value = (J.value + 1) % i);
467
+ }
468
+ function De() {
469
+ const i = oe.value.length;
470
+ i <= 1 || (J.value = (J.value - 1 + i) % i);
471
+ }
472
+ const b = R(() => oe.value.length === 0 ? null : oe.value[J.value]), P = R(() => {
473
+ const i = b.value;
474
+ return !i || !i.popupConfig ? i?.layerTitle || "" : ve(i.popupConfig.title, i.properties);
475
+ }), ae = R(() => {
476
+ const i = b.value;
477
+ if (!i) return "";
478
+ let u = '<div class="popup-content">';
479
+ if (u += `<h3 class="popup-title">${P.value}</h3>`, i.popupConfig?.fields?.length) {
480
+ u += '<table class="popup-table">';
481
+ for (const r of i.popupConfig.fields) {
482
+ const x = Qe(i.properties[r.field], r.format);
483
+ u += `<tr><th>${r.label}</th><td>${x}</td></tr>`;
484
+ }
485
+ u += "</table>";
486
+ } else
487
+ u += '<p class="popup-no-fields">No additional information available.</p>';
488
+ return u += "</div>", u;
489
+ }), Z = $({
490
+ type: "FeatureCollection",
491
+ features: []
492
+ }), Q = $({
493
+ type: "FeatureCollection",
494
+ features: []
495
+ }), Ke = {
496
+ "circle-radius": ["get", "highlightRadius"],
497
+ "circle-color": "#00FFFF",
498
+ "circle-opacity": 0.8,
499
+ "circle-stroke-width": 2,
500
+ "circle-stroke-color": "#FFFFFF"
501
+ }, Xe = {
502
+ "line-width": ["get", "highlightWidth"],
503
+ "line-color": "#00FFFF",
504
+ "line-opacity": 0.9
505
+ }, ge = $(null);
506
+ function rt(i) {
507
+ return i.type;
508
+ }
509
+ function st(i, u) {
510
+ const r = $e(i);
511
+ if (!r) return { radius: 5, width: 2 };
512
+ const x = r.paint || {};
513
+ if (u === "circle") {
514
+ const k = x["circle-radius"];
515
+ return typeof k == "number" ? { radius: k } : { radius: 5 };
516
+ }
517
+ if (u === "line" || u === "fill") {
518
+ const k = x["line-width"];
519
+ if (typeof k == "number")
520
+ return { width: k };
521
+ if (r.outlinePaint && r.outlinePaint["line-width"]) {
522
+ const T = r.outlinePaint["line-width"];
523
+ if (typeof T == "number")
524
+ return { width: T };
525
+ }
526
+ return { width: 2 };
527
+ }
528
+ return { radius: 5, width: 2 };
529
+ }
530
+ function ct(i) {
531
+ return !i || i.length === 0 ? [] : i[0] ?? [];
532
+ }
533
+ function $t(i) {
534
+ const { geometry: u, geometryType: r, originalStyle: x } = i;
535
+ if (r === "Point" || r === "MultiPoint") {
536
+ const T = (x.radius || 5) + 3;
537
+ return {
538
+ type: "FeatureCollection",
539
+ features: [{
540
+ type: "Feature",
541
+ geometry: u,
542
+ properties: {
543
+ highlightRadius: T
544
+ }
545
+ }]
546
+ };
547
+ }
548
+ if (r === "LineString" || r === "MultiLineString") {
549
+ const T = (x.width || 2) + 3;
550
+ return {
551
+ type: "FeatureCollection",
552
+ features: [{
553
+ type: "Feature",
554
+ geometry: u,
555
+ properties: {
556
+ highlightWidth: T
557
+ }
558
+ }]
559
+ };
560
+ }
561
+ if (r === "Polygon") {
562
+ const k = u.coordinates, T = ct(k), B = (x.width || 2) + 3;
563
+ return {
564
+ type: "FeatureCollection",
565
+ features: [{
566
+ type: "Feature",
567
+ geometry: {
568
+ type: "LineString",
569
+ coordinates: T
570
+ },
571
+ properties: {
572
+ highlightWidth: B
573
+ }
574
+ }]
575
+ };
576
+ }
577
+ if (r === "MultiPolygon") {
578
+ const k = u.coordinates, O = (x.width || 2) + 3;
579
+ return {
580
+ type: "FeatureCollection",
581
+ features: k.map((W) => ({
582
+ type: "Feature",
583
+ geometry: {
584
+ type: "LineString",
585
+ coordinates: ct(W)
586
+ },
587
+ properties: {
588
+ highlightWidth: O
589
+ }
590
+ }))
591
+ };
592
+ }
593
+ return {
594
+ type: "FeatureCollection",
595
+ features: []
596
+ };
597
+ }
598
+ function Pt(i) {
599
+ if (!i) {
600
+ xt();
601
+ return;
602
+ }
603
+ const u = $t(i);
604
+ i.geometryType === "Point" || i.geometryType === "MultiPoint" ? (Z.value = u, Q.value = { type: "FeatureCollection", features: [] }) : (Q.value = u, Z.value = { type: "FeatureCollection", features: [] });
605
+ }
606
+ function xt() {
607
+ Z.value = { type: "FeatureCollection", features: [] }, Q.value = { type: "FeatureCollection", features: [] };
608
+ }
609
+ xe(ge, (i) => {
610
+ Pt(i);
611
+ }), xe(
612
+ () => o.visibleLayers,
613
+ (i) => {
614
+ ge.value && !i.has(ge.value.layerId) && (ge.value = null, te());
615
+ },
616
+ { deep: !0 }
617
+ ), xe(J, () => {
618
+ const i = b.value;
619
+ if (!i) {
620
+ ge.value = null;
621
+ return;
622
+ }
623
+ const u = a.value;
624
+ if (!u || !pe.value) return;
625
+ const r = [];
626
+ o.layerList.forEach((O) => {
627
+ const B = O.config;
628
+ o.visibleLayers.has(B.id) && (r.push(B.id), B.outlinePaint && r.push(`${B.id}-outline`));
629
+ });
630
+ const x = u.project(pe.value), T = u.queryRenderedFeatures(x, {
631
+ layers: r
632
+ }).find((O) => O.layer.id.replace(/-outline$/, "") === i.layerId && JSON.stringify(O.properties) === JSON.stringify(i.properties));
633
+ if (T && T.geometry) {
634
+ const O = $e(i.layerId);
635
+ if (O) {
636
+ const B = rt(T.geometry), W = st(O.id, O.type);
637
+ ge.value = {
638
+ geometry: T.geometry,
639
+ geometryType: B,
640
+ layerId: O.id,
641
+ properties: T.properties || {},
642
+ originalStyle: W
643
+ };
644
+ }
645
+ }
646
+ });
647
+ const ut = $(null);
648
+ function Tt(i) {
649
+ const [u, r] = i.geometry.coordinates;
650
+ ut.value = [u, r];
651
+ }
652
+ return (i, u) => (f(), L("div", Qt, [
653
+ ee(_(Ot), {
654
+ ref_key: "mapRef",
655
+ ref: l,
656
+ zoom: o.initialZoom,
657
+ center: o.initialCenter,
658
+ "navigation-controls": { position: o.navigationControlPosition },
659
+ "geolocation-control": { position: o.geolocationControlPosition },
660
+ "basemap-change-controls": { toggle: !0, dropdown: !0, position: o.basemapControlPosition },
661
+ "map-search-control": { position: o.searchControlPosition },
662
+ "enable-cyclomedia": !0,
663
+ "cyclomedia-config": o.cyclomediaConfig,
664
+ "cyclomedia-button-position": o.cyclomediaButtonPosition,
665
+ "enable-pictometry": !0,
666
+ "pictometry-credentials": o.pictometryCredentials,
667
+ "pictometry-button-position": o.pictometryButtonPosition,
668
+ "tool-panel-layout": "vertical",
669
+ "tool-panel-split-ratio": 50,
670
+ onZoom: p,
671
+ onClick: te,
672
+ onMoveend: C,
673
+ onLoad: g,
674
+ onSearchResult: Tt
675
+ }, {
676
+ default: Ne(() => [
677
+ o.drawControlPosition !== null ? (f(), X(_(Rt), {
678
+ key: 0,
679
+ position: o.drawControlPosition
680
+ }, null, 8, ["position"])) : I("", !0),
681
+ (f(!0), L(ie, null, re(Ge.value, (r) => (f(), X(_(pt), {
682
+ key: "tiled-" + r.id,
683
+ id: "tiled-" + r.id,
684
+ source: qe(r),
685
+ paint: { "raster-opacity": Se(r.id) },
686
+ minzoom: r.minZoom,
687
+ maxzoom: r.maxZoom
688
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
689
+ (f(!0), L(ie, null, re(He.value, (r) => (f(), X(_(pt), {
690
+ key: "dynamic-" + r.id,
691
+ id: "dynamic-" + r.id,
692
+ source: Ce(r),
693
+ paint: { "raster-opacity": Se(r.id) },
694
+ minzoom: r.minZoom,
695
+ maxzoom: r.maxZoom
696
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
697
+ (f(!0), L(ie, null, re(M.value, (r) => (f(), X(_(yt), {
698
+ key: r.id,
699
+ id: r.id,
700
+ source: de(r),
701
+ paint: fe(r),
702
+ minzoom: r.minZoom,
703
+ maxzoom: r.maxZoom,
704
+ "before-id": "highlight-circles",
705
+ onClick: Pe
706
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
707
+ (f(!0), L(ie, null, re(N.value, (r) => (f(), X(_(Dt), {
708
+ key: r.id,
709
+ id: r.id,
710
+ source: de(r),
711
+ paint: fe(r),
712
+ minzoom: r.minZoom,
713
+ maxzoom: r.maxZoom,
714
+ "before-id": "highlight-circles",
715
+ onClick: Pe
716
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
717
+ (f(!0), L(ie, null, re(q.value, (r) => (f(), X(_(et), {
718
+ key: r.id + "-outline",
719
+ id: r.id + "-outline",
720
+ source: de(r),
721
+ paint: Je(r),
722
+ minzoom: r.minZoom,
723
+ maxzoom: r.maxZoom,
724
+ "before-id": "highlight-lines",
725
+ onClick: Pe
726
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
727
+ (f(!0), L(ie, null, re(ce.value, (r) => (f(), X(_(et), {
728
+ key: r.id,
729
+ id: r.id,
730
+ source: de(r),
731
+ paint: fe(r),
732
+ minzoom: r.minZoom,
733
+ maxzoom: r.maxZoom,
734
+ "before-id": "highlight-lines",
735
+ onClick: Pe
736
+ }, null, 8, ["id", "source", "paint", "minzoom", "maxzoom"]))), 128)),
737
+ ee(_(yt), {
738
+ key: "highlight-circles-layer",
739
+ id: "highlight-circles",
740
+ source: { type: "geojson", data: Z.value },
741
+ paint: Ke
742
+ }, null, 8, ["source"]),
743
+ ee(_(et), {
744
+ key: "highlight-lines-layer",
745
+ id: "highlight-lines",
746
+ source: { type: "geojson", data: Q.value },
747
+ paint: Xe
748
+ }, null, 8, ["source"]),
749
+ ee(_(At), {
750
+ "lng-lat": ut.value,
751
+ color: "#2176d2"
752
+ }, null, 8, ["lng-lat"]),
753
+ b.value && pe.value ? (f(), X(_(Nt), {
754
+ key: 1,
755
+ "lng-lat": pe.value,
756
+ html: ae.value,
757
+ "close-on-click": !1,
758
+ "show-navigation": oe.value.length > 1,
759
+ "current-feature-index": J.value,
760
+ "total-features": oe.value.length,
761
+ "layer-name": b.value.layerTitle,
762
+ onClose: te,
763
+ onNext: le,
764
+ onPrevious: De
765
+ }, null, 8, ["lng-lat", "html", "show-navigation", "current-feature-index", "total-features", "layer-name"])) : I("", !0)
766
+ ]),
767
+ _: 1
768
+ }, 8, ["zoom", "center", "navigation-controls", "geolocation-control", "basemap-change-controls", "map-search-control", "cyclomedia-config", "cyclomedia-button-position", "pictometry-credentials", "pictometry-button-position"])
769
+ ]));
770
+ }
771
+ }), _e = (e, n) => {
772
+ const o = e.__vccOpts || e;
773
+ for (const [t, l] of n)
774
+ o[t] = l;
775
+ return o;
776
+ }, Xt = /* @__PURE__ */ _e(Kt, [["__scopeId", "data-v-38b78874"]]), Yt = ["disabled"], eo = /* @__PURE__ */ we({
777
+ inheritAttrs: !1,
778
+ __name: "PhlButton",
779
+ props: {
780
+ href: {},
781
+ to: {},
782
+ target: {},
783
+ rel: {},
784
+ disabled: { type: Boolean, default: !1 },
785
+ clickTarget: {},
786
+ variant: { default: "primary" },
787
+ size: { default: "medium" },
788
+ iconOnly: { type: Boolean, default: !1 },
789
+ iconRight: { type: Boolean },
790
+ text: {},
791
+ className: {},
792
+ iconDefinition: {},
793
+ iconClass: {},
794
+ src: {},
795
+ svgRaw: {}
796
+ },
797
+ setup(e) {
798
+ const n = e, o = (c) => "href" in c && c.href !== void 0 || "to" in c && c.to !== void 0, t = R(() => nt(
799
+ "phila-button",
800
+ `phila-button--${n.variant}`,
801
+ n.size && `is-${n.size}`,
802
+ n.iconOnly && "icon-button",
803
+ n.iconOnly && n.variant === "standard" && "icon-button--standard",
804
+ n.className
805
+ )), l = R(() => o(n) ? "to" in n && n.to !== void 0 ? {
806
+ to: n.to,
807
+ disabled: n.disabled,
808
+ className: t.value
809
+ } : {
810
+ href: n.href,
811
+ target: n.target,
812
+ rel: n.rel,
813
+ disabled: n.disabled,
814
+ className: t.value
815
+ } : {}), a = R(
816
+ () => ({
817
+ iconDefinition: n.iconDefinition,
818
+ iconClass: n.iconClass,
819
+ src: n.src,
820
+ iconRight: n.iconRight,
821
+ iconOnly: n.iconOnly,
822
+ text: n.text,
823
+ size: n.size
824
+ })
825
+ );
826
+ return (c, p) => o(n) ? (f(), X(_(Zt), ot({ key: 0 }, { ...l.value, ...c.$attrs }, { role: "button" }), {
827
+ default: Ne(() => [
828
+ ee(_(gt), dt(ft(a.value)), {
829
+ default: Ne(() => [
830
+ se(c.$slots, "default", {}, () => [
831
+ he(j(n.text), 1)
832
+ ])
833
+ ]),
834
+ _: 3
835
+ }, 16)
836
+ ]),
837
+ _: 3
838
+ }, 16)) : (f(), L("button", ot({
839
+ key: 1,
840
+ type: "button",
841
+ disabled: n.disabled,
842
+ class: t.value
843
+ }, c.$attrs), [
844
+ ee(_(gt), dt(ft(a.value)), {
845
+ default: Ne(() => [
846
+ se(c.$slots, "default", {}, () => [
847
+ he(j(n.text), 1)
848
+ ])
849
+ ]),
850
+ _: 3
851
+ }, 16)
852
+ ], 16, Yt));
853
+ }
854
+ });
855
+ var to = {
856
+ prefix: "fas",
857
+ iconName: "circle-exclamation",
858
+ icon: [512, 512, ["exclamation-circle"], "f06a", "M256 512a256 256 0 1 1 0-512 256 256 0 1 1 0 512zm0-192a32 32 0 1 0 0 64 32 32 0 1 0 0-64zm0-192c-18.2 0-32.7 15.5-31.4 33.7l7.4 104c.9 12.6 11.4 22.3 23.9 22.3 12.6 0 23-9.7 23.9-22.3l7.4-104c1.3-18.2-13.1-33.7-31.4-33.7z"]
859
+ }, oo = to, no = {
860
+ prefix: "fas",
861
+ iconName: "xmark",
862
+ icon: [384, 512, [128473, 10005, 10006, 10060, 215, "close", "multiply", "remove", "times"], "f00d", "M55.1 73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L147.2 256 9.9 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192.5 301.3 329.9 438.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.8 256 375.1 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192.5 210.7 55.1 73.4z"]
863
+ }, io = no;
864
+ const lo = ["for"], ao = { class: "state-layer" }, ro = { class: "content" }, so = { class: "input-text-container" }, co = ["id", "placeholder"], uo = {
865
+ key: 1,
866
+ class: "has-text-body-small phila-supporting-text"
867
+ }, fo = {
868
+ key: 2,
869
+ class: "has-text-body-small phila-error-text"
870
+ }, po = /* @__PURE__ */ we({
871
+ inheritAttrs: !1,
872
+ __name: "TextField",
873
+ props: {
874
+ className: { default: "" },
875
+ label: { default: "" },
876
+ id: { default: `phila-text-field-${Math.random().toString(36).substring(2, 9)}` },
877
+ supportingText: { default: "" },
878
+ placeholder: { default: "" },
879
+ leadingIcon: { default: "" },
880
+ trailingIcon: { default: "" },
881
+ error: { default() {
882
+ return [];
883
+ } }
884
+ },
885
+ setup(e, { emit: n }) {
886
+ const o = Ft(), t = e, l = R(() => typeof t.error == "string" ? t.error : t.error[0]), a = Mt(t, "id"), c = R(() => {
887
+ const S = ["default-class"];
888
+ return o.disabled != null && S.push("phila-input--disabled"), l.value && S.push("phila-input--error"), o.required != null && S.push("phila-input--required"), nt(...S);
889
+ }), p = $(""), d = R(() => {
890
+ const S = [];
891
+ return p.value !== "" && S.push("phila-text-field--filled"), t.className && S.push(t.className), nt(...S);
892
+ });
893
+ return (S, y) => (f(), L("div", {
894
+ class: ne(["phila-input", c.value])
895
+ }, [
896
+ t.label ? (f(), L("label", {
897
+ key: 0,
898
+ for: a.value,
899
+ class: "has-text-label-small phila-label"
900
+ }, j(t.label), 9, lo)) : I("", !0),
901
+ F("div", {
902
+ class: ne(["phila-text-field", d.value])
903
+ }, [
904
+ F("div", ao, [
905
+ t.leadingIcon ? (f(), X(_(me), {
906
+ key: 0,
907
+ "icon-class": t.leadingIcon,
908
+ inline: ""
909
+ }, null, 8, ["icon-class"])) : I("", !0),
910
+ F("div", ro, [
911
+ F("div", so, [
912
+ St(F("input", ot({
913
+ id: a.value,
914
+ "onUpdate:modelValue": y[0] || (y[0] = (h) => p.value = h),
915
+ class: "phila-text-field-input has-text-body-default",
916
+ placeholder: t.placeholder
917
+ }, _(o)), null, 16, co), [
918
+ [Et, p.value]
919
+ ])
920
+ ])
921
+ ]),
922
+ p.value != "" ? (f(), X(_(eo), {
923
+ key: 1,
924
+ variant: "standard",
925
+ size: "extra-small",
926
+ "icon-only": "",
927
+ icon: _(io),
928
+ onClick: y[1] || (y[1] = (h) => p.value = "")
929
+ }, null, 8, ["icon"])) : I("", !0),
930
+ t.trailingIcon ? (f(), X(_(me), {
931
+ key: 2,
932
+ "icon-class": t.trailingIcon,
933
+ inline: ""
934
+ }, null, 8, ["icon-class"])) : I("", !0)
935
+ ])
936
+ ], 2),
937
+ t.supportingText ? (f(), L("div", uo, j(t.supportingText), 1)) : I("", !0),
938
+ l.value ? (f(), L("div", fo, [
939
+ ee(_(me), {
940
+ "icon-definition": _(oo),
941
+ size: "small",
942
+ inline: ""
943
+ }, null, 8, ["icon-definition"]),
944
+ he(" " + j(l.value), 1)
945
+ ])) : I("", !0)
946
+ ], 2));
947
+ }
948
+ });
949
+ var yo = {
950
+ prefix: "fas",
951
+ iconName: "caret-right",
952
+ icon: [256, 512, [], "f0da", "M249.3 235.8c10.2 12.6 9.5 31.1-2.2 42.8l-128 128c-9.2 9.2-22.9 11.9-34.9 6.9S64.5 396.9 64.5 384l0-256c0-12.9 7.8-24.6 19.8-29.6s25.7-2.2 34.9 6.9l128 128 2.2 2.4z"]
953
+ }, go = {
954
+ prefix: "fas",
955
+ iconName: "caret-left",
956
+ icon: [256, 512, [], "f0d9", "M7.7 235.8c-10.3 12.6-9.5 31.1 2.2 42.8l128 128c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6l0-256c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9l-128 128-2.2 2.4z"]
957
+ }, ht = {
958
+ prefix: "fas",
959
+ iconName: "xmark",
960
+ icon: [384, 512, [128473, 10005, 10006, 10060, 215, "close", "multiply", "remove", "times"], "f00d", "M55.1 73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L147.2 256 9.9 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192.5 301.3 329.9 438.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.8 256 375.1 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192.5 210.7 55.1 73.4z"]
961
+ }, mo = {
962
+ prefix: "fas",
963
+ iconName: "bars",
964
+ icon: [448, 512, ["navicon"], "f0c9", "M0 96C0 78.3 14.3 64 32 64l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32L32 448c-17.7 0-32-14.3-32-32s14.3-32 32-32l384 0c17.7 0 32 14.3 32 32z"]
965
+ }, ho = {
966
+ prefix: "fas",
967
+ iconName: "circle-info",
968
+ icon: [512, 512, ["info-circle"], "f05a", "M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zM224 160a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm-8 64l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z"]
969
+ };
970
+ const vo = { class: "layer-panel" }, bo = {
971
+ key: 0,
972
+ class: "search-box"
973
+ }, wo = {
974
+ key: 1,
975
+ class: "topics-container"
976
+ }, Lo = { class: "layer-row" }, So = ["href"], Co = {
977
+ key: 1,
978
+ class: "metadata-placeholder"
979
+ }, ko = ["checked", "disabled", "onChange"], $o = { class: "layer-title" }, Po = {
980
+ key: 0,
981
+ class: "loading-indicator"
982
+ }, xo = ["title"], To = {
983
+ key: 2,
984
+ class: "zoom-indicator"
985
+ }, Fo = {
986
+ key: 0,
987
+ class: "opacity-control"
988
+ }, Mo = { class: "opacity-label" }, Eo = ["value", "onInput"], zo = {
989
+ key: 1,
990
+ class: "layer-legend"
991
+ }, _o = { class: "legend-label" }, Io = {
992
+ key: 0,
993
+ class: "no-results"
994
+ }, Oo = /* @__PURE__ */ we({
995
+ __name: "LayerPanel",
996
+ props: {
997
+ layerList: {},
998
+ visibleLayers: {},
999
+ layerOpacities: {},
1000
+ loadingLayers: {},
1001
+ layerErrors: {},
1002
+ currentZoom: {},
1003
+ searchQuery: {},
1004
+ layerMetadata: {},
1005
+ mode: { default: "flat" },
1006
+ showSearch: { type: Boolean, default: !0 },
1007
+ showOpacity: { type: Boolean, default: !0 },
1008
+ showLegend: { type: Boolean, default: !0 },
1009
+ searchPlaceholder: { default: "Search layers..." }
1010
+ },
1011
+ emits: ["toggleLayer", "setOpacity", "updateSearch"],
1012
+ setup(e, { emit: n }) {
1013
+ const o = e, t = n, l = R(() => {
1014
+ if (!o.searchQuery.trim())
1015
+ return o.layerList;
1016
+ const C = o.searchQuery.toLowerCase();
1017
+ return o.layerList.filter(
1018
+ (g) => g.config.title.toLowerCase().includes(C)
1019
+ );
1020
+ });
1021
+ function a(C) {
1022
+ let g = C.split("?")[0] || C;
1023
+ return g = g.replace(/\/query$/, ""), g = g.replace(/\/$/, ""), g.toLowerCase();
1024
+ }
1025
+ function c(C) {
1026
+ const g = a(C);
1027
+ return o.layerMetadata[g] || null;
1028
+ }
1029
+ const p = R(() => o.layerList.some((C) => c(C.config.url)));
1030
+ function d(C) {
1031
+ return o.visibleLayers.has(C);
1032
+ }
1033
+ function S(C) {
1034
+ return o.layerOpacities[C] ?? 1;
1035
+ }
1036
+ function y(C) {
1037
+ return o.loadingLayers.has(C);
1038
+ }
1039
+ function h(C) {
1040
+ return o.layerErrors[C] || null;
1041
+ }
1042
+ function s(C) {
1043
+ const g = o.currentZoom, w = C.minZoom, z = C.maxZoom;
1044
+ return !(w !== void 0 && g < w || z !== void 0 && g > z);
1045
+ }
1046
+ const v = R({
1047
+ get: () => o.searchQuery,
1048
+ set: (C) => t("updateSearch", C)
1049
+ });
1050
+ function E(C) {
1051
+ t("toggleLayer", C);
1052
+ }
1053
+ function m(C, g) {
1054
+ const w = g.target, z = parseFloat(w.value);
1055
+ t("setOpacity", C, z);
1056
+ }
1057
+ return (C, g) => (f(), L("aside", vo, [
1058
+ e.showSearch ? (f(), L("div", bo, [
1059
+ ee(_(po), {
1060
+ modelValue: v.value,
1061
+ "onUpdate:modelValue": g[0] || (g[0] = (w) => v.value = w),
1062
+ placeholder: e.searchPlaceholder,
1063
+ "class-name": "layer-search-field"
1064
+ }, null, 8, ["modelValue", "placeholder"])
1065
+ ])) : I("", !0),
1066
+ e.mode === "topics" ? (f(), L("div", wo, [
1067
+ se(C.$slots, "topics", {}, () => [
1068
+ g[2] || (g[2] = F("div", { class: "no-topics" }, ' No topic components provided. Use the "topics" slot to add TopicAccordion components. ', -1))
1069
+ ], !0)
1070
+ ])) : (f(), L("div", {
1071
+ key: 2,
1072
+ class: ne(["layer-list", { "has-metadata": p.value }])
1073
+ }, [
1074
+ (f(!0), L(ie, null, re(l.value, (w) => (f(), L("div", {
1075
+ key: w.config.id,
1076
+ class: "layer-item"
1077
+ }, [
1078
+ F("div", Lo, [
1079
+ c(w.config.url) ? (f(), L("a", {
1080
+ key: 0,
1081
+ href: c(w.config.url) || "",
1082
+ target: "_blank",
1083
+ rel: "noopener noreferrer",
1084
+ class: "metadata-link",
1085
+ title: "View metadata",
1086
+ onClick: g[1] || (g[1] = zt(() => {
1087
+ }, ["stop"]))
1088
+ }, [
1089
+ ee(_(me), {
1090
+ "icon-definition": _(ho),
1091
+ size: "small",
1092
+ inline: "",
1093
+ decorative: ""
1094
+ }, null, 8, ["icon-definition"])
1095
+ ], 8, So)) : p.value ? (f(), L("span", Co)) : I("", !0),
1096
+ F("label", {
1097
+ class: ne(["layer-checkbox", {
1098
+ "layer-unavailable": !s(w.config),
1099
+ "layer-error": h(w.config.id)
1100
+ }])
1101
+ }, [
1102
+ F("input", {
1103
+ type: "checkbox",
1104
+ checked: d(w.config.id),
1105
+ disabled: !s(w.config),
1106
+ onChange: (z) => E(w.config.id)
1107
+ }, null, 40, ko),
1108
+ F("span", $o, [
1109
+ he(j(w.config.title) + " ", 1),
1110
+ y(w.config.id) ? (f(), L("span", Po, " Loading... ")) : I("", !0),
1111
+ h(w.config.id) ? (f(), L("span", {
1112
+ key: 1,
1113
+ class: "error-indicator",
1114
+ title: h(w.config.id) || ""
1115
+ }, " Error ", 8, xo)) : I("", !0),
1116
+ s(w.config) ? I("", !0) : (f(), L("span", To, " (zoom in) "))
1117
+ ])
1118
+ ], 2)
1119
+ ]),
1120
+ e.showOpacity && d(w.config.id) ? (f(), L("div", Fo, [
1121
+ F("label", Mo, " Opacity: " + j(Math.round(S(w.config.id) * 100)) + "% ", 1),
1122
+ F("input", {
1123
+ type: "range",
1124
+ min: "0",
1125
+ max: "1",
1126
+ step: "0.05",
1127
+ value: S(w.config.id),
1128
+ class: "opacity-slider",
1129
+ onInput: (z) => m(w.config.id, z)
1130
+ }, null, 40, Eo)
1131
+ ])) : I("", !0),
1132
+ e.showLegend && d(w.config.id) && w.config.legend?.length ? (f(), L("ul", zo, [
1133
+ (f(!0), L(ie, null, re(w.config.legend, (z, M) => (f(), L("li", {
1134
+ key: M,
1135
+ class: "legend-item"
1136
+ }, [
1137
+ z.type === "circle" ? (f(), L("span", {
1138
+ key: 0,
1139
+ class: "legend-symbol legend-circle",
1140
+ style: Y({ backgroundColor: z.color })
1141
+ }, null, 4)) : z.type === "line" ? (f(), L("span", {
1142
+ key: 1,
1143
+ class: "legend-symbol legend-line",
1144
+ style: Y({
1145
+ backgroundColor: z.color,
1146
+ height: `${z.width || 2}px`
1147
+ })
1148
+ }, null, 4)) : z.type === "fill" ? (f(), L("span", {
1149
+ key: 2,
1150
+ class: "legend-symbol legend-fill",
1151
+ style: Y({ backgroundColor: z.color })
1152
+ }, null, 4)) : I("", !0),
1153
+ F("span", _o, j(z.label), 1)
1154
+ ]))), 128))
1155
+ ])) : I("", !0)
1156
+ ]))), 128)),
1157
+ l.value.length === 0 ? (f(), L("div", Io, ' No layers match "' + j(e.searchQuery) + '" ', 1)) : I("", !0)
1158
+ ], 2))
1159
+ ]));
1160
+ }
1161
+ }), Ro = /* @__PURE__ */ _e(Oo, [["__scopeId", "data-v-82d84fbe"]]);
1162
+ function D(e) {
1163
+ if (!e || !Array.isArray(e) || e.length < 3) return "#888888";
1164
+ const n = e[0], o = e[1], t = e[2], a = (e[3] ?? 255) / 255;
1165
+ return a === 1 ? `#${n.toString(16).padStart(2, "0")}${o.toString(16).padStart(2, "0")}${t.toString(16).padStart(2, "0")}` : `rgba(${n}, ${o}, ${t}, ${a.toFixed(2)})`;
1166
+ }
1167
+ function ue(e) {
1168
+ return e !== void 0 ? e : 1;
1169
+ }
1170
+ const Do = 559082264;
1171
+ function vt(e) {
1172
+ return !e || e <= 0 ? null : Math.round(Math.log2(Do / e) * 100) / 100;
1173
+ }
1174
+ function Ao(e, n) {
1175
+ const o = {};
1176
+ if (e && e > 0) {
1177
+ const t = vt(e);
1178
+ t !== null && (o.minZoom = t);
1179
+ }
1180
+ if (n && n > 0) {
1181
+ const t = vt(n);
1182
+ t !== null && (o.maxZoom = t);
1183
+ }
1184
+ return o;
1185
+ }
1186
+ function Ve(e) {
1187
+ if (!e) return "fill";
1188
+ switch (e.type) {
1189
+ case "esriSFS":
1190
+ return "fill";
1191
+ case "esriSLS":
1192
+ return "line";
1193
+ case "esriSMS":
1194
+ return "circle";
1195
+ case "esriPMS":
1196
+ return "circle";
1197
+ case "esriPFS":
1198
+ return "fill";
1199
+ default:
1200
+ return "fill";
1201
+ }
1202
+ }
1203
+ function Fe(e) {
1204
+ return !(!e || e.style === "esriSLSNull" || e.color === null || e.width === 0 || e.color && e.color[3] === 0);
1205
+ }
1206
+ function tt(e) {
1207
+ return String(e);
1208
+ }
1209
+ function Ct(e, n, o) {
1210
+ const t = e.symbol, l = Ve(t);
1211
+ console.log("[Transformer] convertSimpleRenderer - geomType:", l, "symbol:", t);
1212
+ let a = {}, c = [], p = null;
1213
+ if (l === "fill" && t) {
1214
+ const d = t.color === null ? 0 : t.color?.[3] ?? 255, S = d === 0 ? "rgba(0, 0, 0, 0)" : D(t.color), y = d === 0 ? 0 : d < 255 ? 1 : ue(n);
1215
+ if (console.log(`[Transformer] Fill layer opacity calculation for "${o}":`, {
1216
+ symbolColor: t.color,
1217
+ fillAlpha: d,
1218
+ layerOpacity: n,
1219
+ fillOpacity: y,
1220
+ fillColor: S
1221
+ }), a = {
1222
+ "fill-color": S,
1223
+ "fill-opacity": y
1224
+ }, Fe(t.outline)) {
1225
+ const h = t.outline.width || 1, s = D(t.outline.color);
1226
+ console.log("[Transformer] Fill layer with outline:", {
1227
+ fillAlpha: d,
1228
+ outlineWidth: h,
1229
+ outlineColor: s,
1230
+ willCreateOutlinePaint: h > 1 || d === 0
1231
+ }), d !== 0 && (a["fill-outline-color"] = s), (h > 1 || d === 0) && (p = {
1232
+ "line-color": s,
1233
+ "line-width": h
1234
+ }, console.log("[Transformer] Created outlinePaint:", p));
1235
+ } else
1236
+ console.log("[Transformer] No visible outline for fill layer, hasVisibleOutline returned false");
1237
+ c = [{
1238
+ type: "fill",
1239
+ color: D(t.color),
1240
+ label: e.label || "Feature"
1241
+ }];
1242
+ } else if (l === "line" && t)
1243
+ a = {
1244
+ "line-color": D(t.color),
1245
+ "line-width": t.width || 1,
1246
+ "line-opacity": ue(n)
1247
+ }, c = [{
1248
+ type: "line",
1249
+ color: D(t.color),
1250
+ width: t.width || 1,
1251
+ label: e.label || "Feature"
1252
+ }];
1253
+ else if (l === "circle" && t) {
1254
+ const d = Math.round((t.size || 6) * 0.71 * 100) / 100;
1255
+ a = {
1256
+ "circle-color": D(t.color),
1257
+ "circle-radius": d,
1258
+ "circle-opacity": ue(n)
1259
+ }, Fe(t.outline) && (a["circle-stroke-color"] = D(t.outline.color), a["circle-stroke-width"] = t.outline.width || 1), c = [{
1260
+ type: "circle",
1261
+ color: D(t.color),
1262
+ label: e.label || "Feature"
1263
+ }];
1264
+ }
1265
+ return { paint: a, legend: c, geomType: l, outlinePaint: p };
1266
+ }
1267
+ function No(e, n, o) {
1268
+ const t = e.field1, l = e.uniqueValueInfos || [], a = e.defaultSymbol;
1269
+ if (l.length === 0)
1270
+ return Ct({ ...e, symbol: a }, n);
1271
+ const c = l[0]?.symbol || a, p = Ve(c);
1272
+ let d = {}, S = [], y = null;
1273
+ if (p === "fill") {
1274
+ const h = ["match", ["to-string", ["get", t]]];
1275
+ for (const s of l) {
1276
+ h.push(tt(s.value)), h.push(D(s.symbol?.color));
1277
+ const v = String(s.value), m = o?.get(v) || s.label || v;
1278
+ S.push({
1279
+ type: "fill",
1280
+ color: D(s.symbol?.color),
1281
+ label: m
1282
+ });
1283
+ }
1284
+ if (h.push(a ? D(a.color) : "#888888"), d = {
1285
+ "fill-color": h,
1286
+ "fill-opacity": ue(n)
1287
+ }, Fe(c?.outline)) {
1288
+ const s = c.outline.width || 1, v = D(c.outline.color);
1289
+ d["fill-outline-color"] = v, s > 1 && (y = {
1290
+ "line-color": v,
1291
+ "line-width": s
1292
+ });
1293
+ }
1294
+ } else if (p === "line") {
1295
+ const h = ["match", ["to-string", ["get", t]]];
1296
+ for (const s of l) {
1297
+ h.push(tt(s.value)), h.push(D(s.symbol?.color));
1298
+ const v = String(s.value), m = o?.get(v) || s.label || v;
1299
+ S.push({
1300
+ type: "line",
1301
+ color: D(s.symbol?.color),
1302
+ width: s.symbol?.width || 1,
1303
+ label: m
1304
+ });
1305
+ }
1306
+ h.push(a ? D(a.color) : "#888888"), d = {
1307
+ "line-color": h,
1308
+ "line-width": c?.width || 2,
1309
+ "line-opacity": ue(n)
1310
+ };
1311
+ } else if (p === "circle") {
1312
+ const h = ["match", ["to-string", ["get", t]]];
1313
+ for (const v of l) {
1314
+ h.push(tt(v.value)), h.push(D(v.symbol?.color));
1315
+ const E = String(v.value), C = o?.get(E) || v.label || E;
1316
+ S.push({
1317
+ type: "circle",
1318
+ color: D(v.symbol?.color),
1319
+ label: C
1320
+ });
1321
+ }
1322
+ h.push(a ? D(a.color) : "#888888");
1323
+ const s = Math.round((c?.size || 6) * 0.71 * 100) / 100;
1324
+ d = {
1325
+ "circle-color": h,
1326
+ "circle-radius": s,
1327
+ "circle-opacity": ue(n)
1328
+ }, Fe(c?.outline) && (d["circle-stroke-color"] = D(c.outline.color), d["circle-stroke-width"] = c.outline.width || 1);
1329
+ }
1330
+ return { paint: d, legend: S, geomType: p, outlinePaint: y };
1331
+ }
1332
+ function Zo(e, n) {
1333
+ const o = e.field, t = e.classBreakInfos || [], l = e.visualVariables?.find((y) => y.type === "colorInfo");
1334
+ if (l?.stops && l.stops.length > 0)
1335
+ return Bo(l, o, e, n);
1336
+ if (t.length === 0)
1337
+ return { paint: {}, legend: [], geomType: "fill", outlinePaint: null };
1338
+ const a = t[0]?.symbol, c = Ve(a);
1339
+ let p = {}, d = [], S = null;
1340
+ if (c === "fill") {
1341
+ const y = ["step", ["get", o]];
1342
+ y.push(D(t[0]?.symbol?.color));
1343
+ for (let h = 0; h < t.length; h++) {
1344
+ const s = t[h];
1345
+ h > 0 && (y.push(t[h - 1].classMaxValue), y.push(D(s.symbol?.color))), d.push({
1346
+ type: "fill",
1347
+ color: D(s.symbol?.color),
1348
+ label: s.label || `${s.classMaxValue}`
1349
+ });
1350
+ }
1351
+ if (p = {
1352
+ "fill-color": y,
1353
+ "fill-opacity": ue(n)
1354
+ }, Fe(a?.outline)) {
1355
+ const h = a.outline.width || 1, s = D(a.outline.color);
1356
+ p["fill-outline-color"] = s, h > 1 && (S = {
1357
+ "line-color": s,
1358
+ "line-width": h
1359
+ });
1360
+ }
1361
+ } else if (c === "line") {
1362
+ const y = ["step", ["get", o]];
1363
+ y.push(D(t[0]?.symbol?.color));
1364
+ let h = e.minValue ?? 0;
1365
+ for (let v = 0; v < t.length; v++) {
1366
+ const E = t[v];
1367
+ v > 0 && (y.push(t[v - 1].classMaxValue), y.push(D(E.symbol?.color))), d.push({
1368
+ type: "line",
1369
+ color: D(E.symbol?.color),
1370
+ width: E.symbol?.width || a?.width || 2,
1371
+ label: E.label || `${h} - ${E.classMaxValue}`
1372
+ }), h = E.classMaxValue + 1;
1373
+ }
1374
+ const s = a?.width || 2;
1375
+ p = {
1376
+ "line-color": y,
1377
+ "line-width": s,
1378
+ "line-opacity": ue(n)
1379
+ };
1380
+ }
1381
+ return { paint: p, legend: d, geomType: c, outlinePaint: S };
1382
+ }
1383
+ function Bo(e, n, o, t) {
1384
+ const l = e.stops || [];
1385
+ if (l.length === 0)
1386
+ return { paint: {}, legend: [], geomType: "fill", outlinePaint: null };
1387
+ const a = o.classBreakInfos?.[0]?.symbol || o.defaultSymbol, c = Ve(a);
1388
+ let p = {}, d = [], S = null;
1389
+ if (c === "fill") {
1390
+ const y = ["interpolate", ["linear"], ["get", n]];
1391
+ for (const s of l)
1392
+ y.push(s.value), y.push(D(s.color)), d.push({
1393
+ type: "fill",
1394
+ color: D(s.color),
1395
+ label: s.label || `${s.value}`
1396
+ });
1397
+ if (p = {
1398
+ "fill-color": [
1399
+ "case",
1400
+ ["==", ["get", n], null],
1401
+ "rgba(0, 0, 0, 0)",
1402
+ // Transparent for null/no-data values
1403
+ y
1404
+ // Otherwise use the interpolated color
1405
+ ],
1406
+ "fill-opacity": ue(t)
1407
+ }, Fe(a?.outline)) {
1408
+ const s = a.outline.width || 1, v = D(a.outline.color);
1409
+ p["fill-outline-color"] = v, s > 1 && (S = {
1410
+ "line-color": v,
1411
+ "line-width": s
1412
+ });
1413
+ }
1414
+ }
1415
+ return { paint: p, legend: d, geomType: c, outlinePaint: S };
1416
+ }
1417
+ function Wo(e, n, o, t) {
1418
+ if (!e?.renderer)
1419
+ return console.warn("[Transformer] No renderer found in drawingInfo - layer will use service default (not available in WebMap)"), { paint: {}, legend: [], geomType: "fill", outlinePaint: null };
1420
+ const l = e.renderer;
1421
+ switch (l.type) {
1422
+ case "simple":
1423
+ return Ct(l, n, t);
1424
+ case "uniqueValue":
1425
+ return No(l, n, o);
1426
+ case "classBreaks":
1427
+ return Zo(l, n);
1428
+ default:
1429
+ return console.warn(`Unknown renderer type: ${l.type}`), { paint: {}, legend: [], geomType: "fill", outlinePaint: null };
1430
+ }
1431
+ }
1432
+ function Uo(e) {
1433
+ if (!e) return null;
1434
+ const n = e.title || "", t = (e.fieldInfos || []).filter((l) => l.visible === !0).map((l) => {
1435
+ const a = {
1436
+ field: l.fieldName,
1437
+ label: l.label || l.fieldName
1438
+ };
1439
+ return l.format && (a.format = {}, l.format.dateFormat && (a.format.dateFormat = l.format.dateFormat), l.format.digitSeparator !== void 0 && (a.format.digitSeparator = l.format.digitSeparator), l.format.places !== void 0 && (a.format.places = l.format.places), Object.keys(a.format).length === 0 && delete a.format), a;
1440
+ });
1441
+ return {
1442
+ title: n,
1443
+ fields: t
1444
+ };
1445
+ }
1446
+ function Vo(e) {
1447
+ return e?.definitionExpression;
1448
+ }
1449
+ function jo(e) {
1450
+ return (e.includes("_") ? e.split("_").slice(1).join(" ") : e).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
1451
+ }
1452
+ function qo(e) {
1453
+ return e.includes("_") ? e.split("_").slice(1).join(" ") : e;
1454
+ }
1455
+ function Go(e) {
1456
+ const n = /* @__PURE__ */ new Map();
1457
+ if (!e)
1458
+ return n;
1459
+ const o = e.split(`
1460
+ `), t = /^(\d{1,3})\s+(.+)$/;
1461
+ for (const l of o) {
1462
+ const a = l.trim().match(t);
1463
+ if (a) {
1464
+ const [, c, p] = a;
1465
+ c && p && n.set(c, p.trim());
1466
+ }
1467
+ }
1468
+ return n;
1469
+ }
1470
+ async function Ho(e) {
1471
+ try {
1472
+ console.log(`[Transformer] Fetching service metadata from: ${e}`);
1473
+ const n = await fetch(`${e}?f=json`);
1474
+ if (!n.ok)
1475
+ return console.warn(`[Transformer] Failed to fetch service metadata: ${n.status}`), null;
1476
+ const o = await n.json();
1477
+ return o.drawingInfo ? {
1478
+ drawingInfo: o.drawingInfo,
1479
+ description: o.description
1480
+ } : null;
1481
+ } catch (n) {
1482
+ return console.error("[Transformer] Error fetching service metadata:", n), null;
1483
+ }
1484
+ }
1485
+ async function kt(e) {
1486
+ const n = e.operationalLayers || [], o = [], t = ["Zoning and Planning_Land Use"];
1487
+ console.log("🔄 [Transformer] ===== STARTING FRESH TRANSFORMATION ====="), console.log("[Transformer] Starting transformation of", n.length, "layers");
1488
+ for (const l of n) {
1489
+ if (!l.url) {
1490
+ console.log(`Skipping layer without URL: ${l.title}`);
1491
+ continue;
1492
+ }
1493
+ if (l.itemId === "4f39b829b96d437da9231727d9c91fab") {
1494
+ console.log(`Skipping layer with under-construction itemId: ${l.title}`);
1495
+ continue;
1496
+ }
1497
+ console.log("[Transformer] Processing layer:", l.title), console.log(`[Transformer] Layer "${l.title}" - Renderer type:`, l.layerDefinition?.drawingInfo?.renderer?.type);
1498
+ try {
1499
+ let a = l.layerDefinition?.drawingInfo, c;
1500
+ const p = !a || !a.renderer, d = t.includes(l.title);
1501
+ if ((p || d) && l.url) {
1502
+ console.log(d ? `[Transformer] Layer "${l.title}" configured to use service renderer instead of WebMap renderer` : `[Transformer] Layer "${l.title}" has no renderer in WebMap, fetching from service...`);
1503
+ const M = await Ho(l.url);
1504
+ M ? (a = M.drawingInfo, console.log(`[Transformer] Fetched renderer from service for "${l.title}":`, M.drawingInfo?.renderer?.type), M.description && (c = Go(M.description), c.size > 0 && console.log(`[Transformer] Parsed ${c.size} custom labels from service description`))) : console.warn(`[Transformer] Failed to fetch renderer from service for "${l.title}"`);
1505
+ }
1506
+ const { paint: S, legend: y, geomType: h, outlinePaint: s } = Wo(
1507
+ a,
1508
+ l.opacity,
1509
+ c,
1510
+ l.title
1511
+ );
1512
+ console.log(`[Transformer] Layer "${l.title}" - Result: geomType=${h}, hasOutlinePaint=${!!s}`);
1513
+ const v = Uo(l.popupInfo), E = Vo(l.layerDefinition), m = Ao(
1514
+ l.layerDefinition?.minScale,
1515
+ l.layerDefinition?.maxScale
1516
+ ), C = jo(l.title), g = qo(l.title);
1517
+ let w = l.opacity ?? 1;
1518
+ const z = {
1519
+ id: C,
1520
+ title: g,
1521
+ type: h,
1522
+ url: l.url,
1523
+ opacity: w,
1524
+ paint: S,
1525
+ legend: y,
1526
+ popup: v
1527
+ };
1528
+ E && (z.where = E), m.minZoom !== void 0 && (z.minZoom = m.minZoom), m.maxZoom !== void 0 && (z.maxZoom = m.maxZoom), s && (z.outlinePaint = s), o.push(z);
1529
+ } catch (a) {
1530
+ console.error(`Error transforming layer ${l.title}:`, a);
1531
+ }
1532
+ }
1533
+ return o.sort((l, a) => l.title.localeCompare(a.title)), o;
1534
+ }
1535
+ const bt = {}, at = "376af635c84643cd816a8c5d017a53aa", Dn = at;
1536
+ function Be(e, n) {
1537
+ let o = `https://www.arcgis.com/sharing/rest/content/items/${e}/data?f=json`;
1538
+ return n && (o += `&token=${n}`), o;
1539
+ }
1540
+ function An() {
1541
+ return Be(at);
1542
+ }
1543
+ const We = /* @__PURE__ */ new Map(), ze = /* @__PURE__ */ new Map();
1544
+ function Jo(e) {
1545
+ e ? (We.delete(e), ze.delete(e)) : (We.clear(), ze.clear());
1546
+ }
1547
+ let Ae, wt = 0;
1548
+ async function Qo() {
1549
+ const e = typeof import.meta < "u" && bt?.VITE_AGO_USERNAME, n = typeof import.meta < "u" && bt?.VITE_AGO_PASSWORD;
1550
+ if (!(!e || !n)) {
1551
+ if (Ae && Date.now() < wt - 3e5)
1552
+ return console.log("[LayerConfigService] Using cached ArcGIS token"), Ae;
1553
+ console.log("[LayerConfigService] Generating new ArcGIS token...");
1554
+ try {
1555
+ const t = await (await fetch("https://www.arcgis.com/sharing/rest/generateToken", {
1556
+ method: "POST",
1557
+ headers: {
1558
+ "Content-Type": "application/x-www-form-urlencoded"
1559
+ },
1560
+ body: new URLSearchParams({
1561
+ f: "json",
1562
+ username: e,
1563
+ password: n,
1564
+ referer: window.location.origin || "https://localhost",
1565
+ expiration: "120"
1566
+ // 2 hours
1567
+ })
1568
+ })).json();
1569
+ if (t.error) {
1570
+ console.error("[LayerConfigService] Failed to generate token:", t.error);
1571
+ return;
1572
+ }
1573
+ return Ae = t.token, wt = t.expires, console.log("[LayerConfigService] ArcGIS token generated successfully"), Ae;
1574
+ } catch (o) {
1575
+ console.error("[LayerConfigService] Error generating ArcGIS token:", o);
1576
+ return;
1577
+ }
1578
+ }
1579
+ }
1580
+ async function Ko(e, n) {
1581
+ const o = Be(e, n);
1582
+ console.log(`[LayerConfigService] Fetching WebMap from: ${Be(e)}${n ? " (with token)" : ""}`);
1583
+ const t = await fetch(o);
1584
+ if (!t.ok)
1585
+ throw new Error(`Failed to fetch WebMap: ${t.status} ${t.statusText}`);
1586
+ const l = await t.json();
1587
+ if (l.error)
1588
+ throw new Error(`ArcGIS error: ${l.error.message || l.error.code || "Unknown error"}`);
1589
+ return l;
1590
+ }
1591
+ async function Xo(e) {
1592
+ try {
1593
+ console.log(`[LayerConfigService] Loading configs in DYNAMIC mode for WebMap: ${e}`);
1594
+ const n = await Qo(), o = await Ko(e, n);
1595
+ console.log("[LayerConfigService] Transforming WebMap to layer configs");
1596
+ const t = await kt(o);
1597
+ return console.log(`[LayerConfigService] Successfully loaded ${t.length} layer configs`), t;
1598
+ } catch (n) {
1599
+ throw console.error("[LayerConfigService] Error loading dynamic configs:", n), new Error(`Failed to load dynamic layer configs: ${n instanceof Error ? n.message : "Unknown error"}`);
1600
+ }
1601
+ }
1602
+ async function lt(e = at) {
1603
+ const n = We.get(e);
1604
+ if (n)
1605
+ return console.log(`[LayerConfigService] ⚠️ Returning CACHED configs for ${e} (transformer will NOT run)`), console.log("[LayerConfigService] To force refresh, call clearCache() or reload with Ctrl+Shift+R"), n;
1606
+ const o = ze.get(e);
1607
+ if (o)
1608
+ return console.log(`[LayerConfigService] Load already in progress for ${e}, waiting...`), o;
1609
+ console.log(`[LayerConfigService] Mode: dynamic, WebMap: ${e}`);
1610
+ const t = (async () => {
1611
+ try {
1612
+ const l = await Xo(e);
1613
+ return We.set(e, l), l;
1614
+ } finally {
1615
+ ze.delete(e);
1616
+ }
1617
+ })();
1618
+ return ze.set(e, t), t;
1619
+ }
1620
+ function Yo(e) {
1621
+ const n = $({}), o = /* @__PURE__ */ new Map();
1622
+ for (const s of e)
1623
+ n.value[s.id] = {
1624
+ data: null,
1625
+ loading: !1,
1626
+ error: null,
1627
+ lastFetched: null
1628
+ };
1629
+ async function t(s) {
1630
+ const v = s.id;
1631
+ n.value = {
1632
+ ...n.value,
1633
+ [v]: {
1634
+ data: n.value[v]?.data ?? null,
1635
+ lastFetched: n.value[v]?.lastFetched ?? null,
1636
+ loading: !0,
1637
+ error: null
1638
+ }
1639
+ };
1640
+ try {
1641
+ let E;
1642
+ if (s.type === "http-get") {
1643
+ const m = await fetch(s.url, {
1644
+ method: "GET",
1645
+ ...s.options
1646
+ });
1647
+ if (!m.ok)
1648
+ throw new Error(`HTTP ${m.status}: ${m.statusText}`);
1649
+ E = await m.json();
1650
+ } else if (s.type === "http-post") {
1651
+ const m = await fetch(s.url, {
1652
+ method: "POST",
1653
+ ...s.options
1654
+ });
1655
+ if (!m.ok)
1656
+ throw new Error(`HTTP ${m.status}: ${m.statusText}`);
1657
+ E = await m.json();
1658
+ } else if (s.type === "esri") {
1659
+ const C = `${s.url.replace(/\/$/, "")}/query?where=1%3D1&outFields=*&returnGeometry=false&f=json`, g = await fetch(C, s.options);
1660
+ if (!g.ok)
1661
+ throw new Error(`HTTP ${g.status}: ${g.statusText}`);
1662
+ E = (await g.json()).features?.map((z) => z.attributes) || [];
1663
+ } else
1664
+ throw new Error(`Unknown data source type: ${s.type}`);
1665
+ s.transform && (E = s.transform(E)), n.value = {
1666
+ ...n.value,
1667
+ [v]: {
1668
+ data: E,
1669
+ loading: !1,
1670
+ error: null,
1671
+ lastFetched: Date.now()
1672
+ }
1673
+ };
1674
+ } catch (E) {
1675
+ const m = E instanceof Error ? E.message : "Unknown error";
1676
+ console.error(`Failed to fetch data source "${v}":`, m), n.value = {
1677
+ ...n.value,
1678
+ [v]: {
1679
+ data: n.value[v]?.data ?? null,
1680
+ lastFetched: n.value[v]?.lastFetched ?? null,
1681
+ loading: !1,
1682
+ error: m
1683
+ }
1684
+ };
1685
+ }
1686
+ }
1687
+ async function l() {
1688
+ await Promise.all(e.map((s) => t(s)));
1689
+ }
1690
+ async function a(s) {
1691
+ const v = e.find((E) => E.id === s);
1692
+ v ? await t(v) : console.warn(`Data source "${s}" not found`);
1693
+ }
1694
+ function c(s) {
1695
+ return n.value[s]?.data ?? null;
1696
+ }
1697
+ const p = R(() => Object.values(n.value).some((s) => s.loading));
1698
+ function d(s) {
1699
+ return n.value[s]?.loading ?? !1;
1700
+ }
1701
+ function S(s) {
1702
+ return n.value[s]?.error ?? null;
1703
+ }
1704
+ function y() {
1705
+ for (const s of e)
1706
+ if (s.pollInterval && s.pollInterval > 0) {
1707
+ const v = window.setInterval(() => {
1708
+ t(s);
1709
+ }, s.pollInterval);
1710
+ o.set(s.id, v);
1711
+ }
1712
+ }
1713
+ function h() {
1714
+ for (const [, s] of o)
1715
+ window.clearInterval(s);
1716
+ o.clear();
1717
+ }
1718
+ return Ze(() => {
1719
+ l(), y();
1720
+ }), Lt(() => {
1721
+ h();
1722
+ }), {
1723
+ /** Reactive state for all data sources */
1724
+ state: V(n),
1725
+ /** Whether any data source is currently loading */
1726
+ isLoading: p,
1727
+ /** Fetch all data sources */
1728
+ fetchAll: l,
1729
+ /** Refetch a specific data source by id */
1730
+ refetch: a,
1731
+ /** Get data for a specific source */
1732
+ getData: c,
1733
+ /** Check if a specific source is loading */
1734
+ isSourceLoading: d,
1735
+ /** Get error for a specific source */
1736
+ getError: S,
1737
+ /** Stop all polling (useful for cleanup) */
1738
+ stopPolling: h
1739
+ };
1740
+ }
1741
+ const en = { class: "layerboard-layout" }, tn = {
1742
+ key: 0,
1743
+ class: "layerboard-subtitle"
1744
+ }, on = { class: "layerboard-mobile-menu-content" }, nn = { class: "layerboard-main" }, ln = {
1745
+ key: 0,
1746
+ class: "layerboard-loading"
1747
+ }, an = {
1748
+ key: 1,
1749
+ class: "layerboard-error"
1750
+ }, rn = { key: 0 }, sn = { key: 1 }, cn = { class: "layerboard-modal" }, un = /* @__PURE__ */ we({
1751
+ __name: "Layerboard",
1752
+ props: {
1753
+ title: {},
1754
+ subtitle: {},
1755
+ webMapId: {},
1756
+ themeColor: { default: "#0f4d90" },
1757
+ cyclomediaConfig: {},
1758
+ pictometryCredentials: {},
1759
+ showDefaultSidebar: { type: Boolean, default: !0 },
1760
+ sidebarWidth: { default: "30%" },
1761
+ sidebarLabel: { default: "Layers" },
1762
+ mapLabel: { default: "Map" },
1763
+ fetchMetadata: { type: Boolean, default: !1 },
1764
+ tiledLayers: { default: () => [] },
1765
+ dataSources: { default: () => [] },
1766
+ layerStyleOverrides: { default: () => ({}) },
1767
+ basemapControlPosition: { default: "top-right" },
1768
+ navigationControlPosition: { default: "bottom-right" },
1769
+ geolocationControlPosition: { default: "bottom-right" },
1770
+ searchControlPosition: { default: "top-left" },
1771
+ drawControlPosition: { default: "bottom-left" },
1772
+ cyclomediaButtonPosition: { default: "top-right" },
1773
+ pictometryButtonPosition: { default: "top-right" },
1774
+ initialZoom: {},
1775
+ initialCenter: {}
1776
+ },
1777
+ emits: ["configs-loaded", "load-error", "zoom"],
1778
+ setup(e, { expose: n, emit: o }) {
1779
+ const t = e, l = o, a = $([]), c = $(!0), p = $(null), d = $(12), S = $(""), y = $(/* @__PURE__ */ new Set()), h = $({}), s = $(/* @__PURE__ */ new Set()), v = $({}), E = $({}), m = $(/* @__PURE__ */ new Set()), C = $({});
1780
+ function g() {
1781
+ const b = {};
1782
+ for (const P of t.tiledLayers)
1783
+ b[P.id] = P.opacity ?? 1;
1784
+ C.value = b;
1785
+ }
1786
+ function w(b) {
1787
+ m.value.has(b) ? m.value.delete(b) : m.value.add(b), m.value = new Set(m.value);
1788
+ }
1789
+ function z(b, P) {
1790
+ P ? m.value.add(b) : m.value.delete(b), m.value = new Set(m.value);
1791
+ }
1792
+ function M(b, P) {
1793
+ C.value = { ...C.value, [b]: P };
1794
+ }
1795
+ const N = t.dataSources.length > 0 ? Yo(t.dataSources) : null, q = R(() => N?.state.value ?? {}), ce = R(() => N?.isLoading.value ?? !1);
1796
+ function Le(b) {
1797
+ return N?.getData(b) ?? null;
1798
+ }
1799
+ function Se(b) {
1800
+ return N?.refetch(b) ?? Promise.resolve();
1801
+ }
1802
+ U("layerboard-layers", V(a)), U("layerboard-visible", y), U("layerboard-opacities", h), U("layerboard-loading", V(s)), U("layerboard-errors", V(v)), U("layerboard-zoom", V(d)), U("layerboard-toggle-layer", Ce), U("layerboard-set-layer-visible", de), U("layerboard-set-layers-visible", ke), U("layerboard-set-opacity", fe), U("layerboard-tiled-layers", V(R(() => t.tiledLayers))), U("layerboard-visible-tiled", m), U("layerboard-tiled-opacities", C), U("layerboard-toggle-tiled", w), U("layerboard-set-tiled-opacity", M), U("layerboard-set-tiled-visible", z), U("layerboard-data-sources-state", q), U("layerboard-data-sources-loading", ce), U("layerboard-get-data-source", Le), U("layerboard-refetch-data-source", Se);
1803
+ const je = R(() => ({
1804
+ backgroundColor: t.themeColor
1805
+ })), qe = R(() => ({
1806
+ backgroundColor: t.themeColor
1807
+ })), Me = R(() => ({
1808
+ backgroundColor: t.themeColor
1809
+ })), Ie = R(() => ({
1810
+ width: ye.value ? "0" : t.sidebarWidth
1811
+ }));
1812
+ async function Ee() {
1813
+ try {
1814
+ c.value = !0, p.value = null;
1815
+ const P = (await lt(t.webMapId)).map((Z) => {
1816
+ const Q = t.layerStyleOverrides[Z.id];
1817
+ return Q ? (console.log(`[Layerboard] Applying style override for layer: ${Z.id}`), {
1818
+ ...Z,
1819
+ paint: Q.paint ?? Z.paint,
1820
+ outlinePaint: Q.outlinePaint ?? Z.outlinePaint,
1821
+ legend: Q.legend ?? Z.legend,
1822
+ type: Q.type ?? Z.type
1823
+ }) : Z;
1824
+ });
1825
+ a.value = P.map((Z) => ({
1826
+ config: Z,
1827
+ component: Z.type
1828
+ }));
1829
+ const ae = {};
1830
+ P.forEach((Z) => {
1831
+ ae[Z.id] = Z.opacity ?? 1;
1832
+ }), h.value = ae, console.log(`[Layerboard] Loaded ${P.length} layer configs from WebMap ${t.webMapId}`), console.log("[Layerboard] Layer IDs:", P.map((Z) => Z.id)), l("configs-loaded", P);
1833
+ } catch (b) {
1834
+ console.error("[Layerboard] Failed to load layer configs:", b);
1835
+ const P = b instanceof Error ? b.message : "Failed to load layer configurations";
1836
+ p.value = P, l("load-error", P);
1837
+ } finally {
1838
+ c.value = !1;
1839
+ }
1840
+ }
1841
+ function Oe(b) {
1842
+ let P = b.split("?")[0] || b;
1843
+ return P = P.replace(/\/query$/, ""), P = P.replace(/\/$/, ""), P.toLowerCase();
1844
+ }
1845
+ async function Ge() {
1846
+ if (t.fetchMetadata)
1847
+ try {
1848
+ const b = "https://phl.carto.com/api/v2/sql?q=" + encodeURIComponent(
1849
+ "select url_text, COALESCE(representation, '') as representation from phl.knack_metadata_reps_endpoints_join WHERE ( format = 'API' OR format = 'GeoService' ) AND url_text IS NOT null"
1850
+ ), P = await fetch(b);
1851
+ if (!P.ok) return;
1852
+ const ae = await P.json(), Z = {};
1853
+ for (const Q of ae.rows || [])
1854
+ if (Q.url_text && Q.representation) {
1855
+ const Ke = Oe(Q.url_text), Xe = `https://metadata.phila.gov/#home/representationdetails/${Q.representation}/`;
1856
+ Z[Ke] = Xe;
1857
+ }
1858
+ E.value = Z;
1859
+ } catch (b) {
1860
+ console.error("[Layerboard] Error fetching metadata:", b);
1861
+ }
1862
+ }
1863
+ function He(b) {
1864
+ d.value = b, l("zoom", b);
1865
+ }
1866
+ function Ce(b) {
1867
+ y.value.has(b) ? y.value.delete(b) : y.value.add(b), y.value = new Set(y.value);
1868
+ }
1869
+ function de(b, P) {
1870
+ P ? y.value.add(b) : y.value.delete(b), y.value = new Set(y.value);
1871
+ }
1872
+ function ke(b, P) {
1873
+ for (const ae of b)
1874
+ P ? y.value.add(ae) : y.value.delete(ae);
1875
+ y.value = new Set(y.value);
1876
+ }
1877
+ function fe(b, P) {
1878
+ h.value = { ...h.value, [b]: P };
1879
+ }
1880
+ function Je(b, P) {
1881
+ P ? s.value.add(b) : s.value.delete(b), s.value = new Set(s.value);
1882
+ }
1883
+ function oe(b, P) {
1884
+ if (P)
1885
+ v.value = { ...v.value, [b]: P };
1886
+ else {
1887
+ const { [b]: ae, ...Z } = v.value;
1888
+ v.value = Z;
1889
+ }
1890
+ }
1891
+ function pe(b) {
1892
+ S.value = b;
1893
+ }
1894
+ const J = $("map");
1895
+ function $e() {
1896
+ J.value = J.value === "sidebar" ? "map" : "sidebar";
1897
+ }
1898
+ const ve = $(!1);
1899
+ function Qe() {
1900
+ ve.value = !ve.value;
1901
+ }
1902
+ function Re() {
1903
+ ve.value = !1;
1904
+ }
1905
+ const ye = $(!1);
1906
+ function Pe() {
1907
+ ye.value = !ye.value;
1908
+ }
1909
+ const te = $(!1);
1910
+ function be() {
1911
+ te.value = !0;
1912
+ }
1913
+ function le() {
1914
+ te.value = !1;
1915
+ }
1916
+ function De(b) {
1917
+ b.target.classList.contains("layerboard-modal-backdrop") && le();
1918
+ }
1919
+ return U("layerboard-open-modal", be), U("layerboard-close-modal", le), U("layerboard-is-modal-open", V(te)), n({
1920
+ /** Layer configurations */
1921
+ layerList: a,
1922
+ /** Set of visible layer IDs */
1923
+ visibleLayers: y,
1924
+ /** Layer opacity values */
1925
+ layerOpacities: h,
1926
+ /** Set of currently loading layer IDs */
1927
+ loadingLayers: s,
1928
+ /** Map of layer errors by ID */
1929
+ layerErrors: v,
1930
+ /** Current map zoom level */
1931
+ currentZoom: d,
1932
+ /** Toggle a layer's visibility */
1933
+ toggleLayer: Ce,
1934
+ /** Set a layer's visibility explicitly */
1935
+ setLayerVisible: de,
1936
+ /** Set multiple layers' visibility at once */
1937
+ setLayersVisible: ke,
1938
+ /** Set a layer's opacity */
1939
+ setLayerOpacity: fe,
1940
+ /** Reload layer configurations */
1941
+ reloadConfigs: Ee,
1942
+ /** Clear configuration cache */
1943
+ clearCache: () => Jo(t.webMapId),
1944
+ // Tiled layer APIs
1945
+ /** Set of visible tiled layer IDs */
1946
+ visibleTiledLayers: m,
1947
+ /** Tiled layer opacity values */
1948
+ tiledLayerOpacities: C,
1949
+ /** Toggle a tiled layer's visibility */
1950
+ toggleTiledLayer: w,
1951
+ /** Set a tiled layer's visibility explicitly */
1952
+ setTiledLayerVisible: z,
1953
+ /** Set a tiled layer's opacity */
1954
+ setTiledLayerOpacity: M,
1955
+ // Data source APIs
1956
+ /** State of all data sources */
1957
+ dataSourcesState: q,
1958
+ /** Whether any data source is loading */
1959
+ dataSourcesLoading: ce,
1960
+ /** Get data from a specific data source */
1961
+ getDataSourceData: Le,
1962
+ /** Refetch a specific data source */
1963
+ refetchDataSource: Se,
1964
+ // Modal APIs
1965
+ /** Whether the modal is currently open */
1966
+ isModalOpen: te,
1967
+ /** Open the modal */
1968
+ openModal: be,
1969
+ /** Close the modal */
1970
+ closeModal: le
1971
+ }), Ze(() => {
1972
+ Ee(), Ge(), g();
1973
+ }), (b, P) => (f(), L("div", en, [
1974
+ F("header", {
1975
+ class: "layerboard-header",
1976
+ style: Y(je.value)
1977
+ }, [
1978
+ P[1] || (P[1] = F("a", {
1979
+ href: "https://www.phila.gov/",
1980
+ class: "layerboard-logo layerboard-desktop-only"
1981
+ }, [
1982
+ F("img", {
1983
+ src: "https://standards.phila.gov/img/logo/city-of-philadelphia-yellow-white.png",
1984
+ alt: "City of Philadelphia"
1985
+ })
1986
+ ], -1)),
1987
+ P[2] || (P[2] = F("span", { class: "layerboard-header-divider layerboard-desktop-only" }, null, -1)),
1988
+ F("button", {
1989
+ class: "layerboard-hamburger layerboard-mobile-only",
1990
+ onClick: Qe,
1991
+ "aria-label": "Toggle menu"
1992
+ }, [
1993
+ ee(_(me), {
1994
+ "icon-definition": _(mo),
1995
+ size: "medium",
1996
+ decorative: ""
1997
+ }, null, 8, ["icon-definition"])
1998
+ ]),
1999
+ se(b.$slots, "header", {}, () => [
2000
+ F("h1", null, j(e.title), 1),
2001
+ e.subtitle ? (f(), L("span", tn, j(e.subtitle), 1)) : I("", !0)
2002
+ ], !0),
2003
+ ve.value ? (f(), L("div", {
2004
+ key: 0,
2005
+ class: "layerboard-mobile-menu",
2006
+ style: Y({ backgroundColor: e.themeColor })
2007
+ }, [
2008
+ F("div", on, [
2009
+ se(b.$slots, "footer", {
2010
+ openModal: be,
2011
+ closeModal: le,
2012
+ isModalOpen: te.value
2013
+ }, () => [
2014
+ P[0] || (P[0] = he(" City of Philadelphia ", -1))
2015
+ ], !0)
2016
+ ]),
2017
+ F("button", {
2018
+ class: "layerboard-mobile-menu-close",
2019
+ onClick: Re,
2020
+ "aria-label": "Close menu"
2021
+ }, [
2022
+ ee(_(me), {
2023
+ "icon-definition": _(ht),
2024
+ size: "medium",
2025
+ decorative: ""
2026
+ }, null, 8, ["icon-definition"])
2027
+ ])
2028
+ ], 4)) : I("", !0),
2029
+ ve.value ? (f(), L("div", {
2030
+ key: 1,
2031
+ class: "layerboard-mobile-menu-backdrop",
2032
+ onClick: Re
2033
+ })) : I("", !0)
2034
+ ], 4),
2035
+ F("div", nn, [
2036
+ c.value ? (f(), L("div", ln, [
2037
+ F("div", {
2038
+ class: "layerboard-spinner",
2039
+ style: Y({ borderTopColor: e.themeColor })
2040
+ }, null, 4),
2041
+ F("p", null, "Loading " + j(e.title) + "...", 1)
2042
+ ])) : p.value ? (f(), L("div", an, [
2043
+ P[3] || (P[3] = F("h2", null, "Error Loading Layers", -1)),
2044
+ F("p", null, j(p.value), 1),
2045
+ F("button", {
2046
+ class: "layerboard-retry-button",
2047
+ style: Y({ backgroundColor: e.themeColor }),
2048
+ onClick: Ee
2049
+ }, " Retry ", 4)
2050
+ ])) : (f(), L(ie, { key: 2 }, [
2051
+ F("aside", {
2052
+ class: ne(["layerboard-sidebar", { "is-active": J.value === "sidebar" }]),
2053
+ style: Y(Ie.value)
2054
+ }, [
2055
+ se(b.$slots, "sidebar", {
2056
+ layers: a.value,
2057
+ visibleLayers: y.value,
2058
+ layerOpacities: h.value,
2059
+ loadingLayers: s.value,
2060
+ layerErrors: v.value,
2061
+ currentZoom: d.value,
2062
+ toggleLayer: Ce,
2063
+ setLayerVisible: de,
2064
+ setLayersVisible: ke,
2065
+ setOpacity: fe,
2066
+ tiledLayers: e.tiledLayers,
2067
+ visibleTiledLayers: m.value,
2068
+ tiledLayerOpacities: C.value,
2069
+ toggleTiledLayer: w,
2070
+ setTiledLayerVisible: z,
2071
+ setTiledLayerOpacity: M,
2072
+ dataSourcesState: q.value,
2073
+ dataSourcesLoading: ce.value,
2074
+ getDataSource: Le,
2075
+ refetchDataSource: Se
2076
+ }, () => [
2077
+ e.showDefaultSidebar ? (f(), X(Ro, {
2078
+ key: 0,
2079
+ "layer-list": a.value,
2080
+ "visible-layers": y.value,
2081
+ "layer-opacities": h.value,
2082
+ "loading-layers": s.value,
2083
+ "layer-errors": v.value,
2084
+ "current-zoom": d.value,
2085
+ "search-query": S.value,
2086
+ "layer-metadata": E.value,
2087
+ onToggleLayer: Ce,
2088
+ onSetOpacity: fe,
2089
+ onUpdateSearch: pe
2090
+ }, null, 8, ["layer-list", "visible-layers", "layer-opacities", "loading-layers", "layer-errors", "current-zoom", "search-query", "layer-metadata"])) : I("", !0)
2091
+ ], !0)
2092
+ ], 6),
2093
+ F("div", {
2094
+ class: ne(["layerboard-map", { "is-active": J.value === "map" }])
2095
+ }, [
2096
+ ee(Xt, {
2097
+ "visible-layers": y.value,
2098
+ "layer-opacities": h.value,
2099
+ "layer-list": a.value,
2100
+ "tiled-layers": e.tiledLayers,
2101
+ "visible-tiled-layers": m.value,
2102
+ "tiled-layer-opacities": C.value,
2103
+ "cyclomedia-config": e.cyclomediaConfig,
2104
+ "pictometry-credentials": e.pictometryCredentials,
2105
+ "basemap-control-position": e.basemapControlPosition,
2106
+ "navigation-control-position": e.navigationControlPosition,
2107
+ "geolocation-control-position": e.geolocationControlPosition,
2108
+ "search-control-position": e.searchControlPosition,
2109
+ "draw-control-position": e.drawControlPosition,
2110
+ "cyclomedia-button-position": e.cyclomediaButtonPosition,
2111
+ "pictometry-button-position": e.pictometryButtonPosition,
2112
+ "initial-zoom": e.initialZoom,
2113
+ "initial-center": e.initialCenter,
2114
+ onZoom: He,
2115
+ onLayerLoading: Je,
2116
+ onLayerError: oe
2117
+ }, null, 8, ["visible-layers", "layer-opacities", "layer-list", "tiled-layers", "visible-tiled-layers", "tiled-layer-opacities", "cyclomedia-config", "pictometry-credentials", "basemap-control-position", "navigation-control-position", "geolocation-control-position", "search-control-position", "draw-control-position", "cyclomedia-button-position", "pictometry-button-position", "initial-zoom", "initial-center"])
2118
+ ], 2),
2119
+ F("button", {
2120
+ class: ne(["layerboard-sidebar-toggle", { "is-collapsed": ye.value }]),
2121
+ style: Y({ left: ye.value ? "0" : t.sidebarWidth }),
2122
+ onClick: Pe,
2123
+ "aria-label": "Toggle sidebar"
2124
+ }, [
2125
+ ee(_(me), {
2126
+ "icon-definition": ye.value ? _(yo) : _(go),
2127
+ size: "medium",
2128
+ decorative: ""
2129
+ }, null, 8, ["icon-definition"])
2130
+ ], 6)
2131
+ ], 64))
2132
+ ]),
2133
+ F("button", {
2134
+ class: "layerboard-mobile-toggle",
2135
+ style: Y(Me.value),
2136
+ onClick: $e
2137
+ }, [
2138
+ J.value === "map" ? (f(), L("span", rn, j(e.sidebarLabel), 1)) : (f(), L("span", sn, j(e.mapLabel), 1))
2139
+ ], 4),
2140
+ F("footer", {
2141
+ class: "layerboard-footer",
2142
+ style: Y(qe.value)
2143
+ }, [
2144
+ se(b.$slots, "footer", {
2145
+ openModal: be,
2146
+ closeModal: le,
2147
+ isModalOpen: te.value
2148
+ }, () => [
2149
+ P[4] || (P[4] = he(" City of Philadelphia ", -1))
2150
+ ], !0)
2151
+ ], 4),
2152
+ te.value ? (f(), L("div", {
2153
+ key: 0,
2154
+ class: "layerboard-modal-backdrop",
2155
+ onClick: De
2156
+ }, [
2157
+ F("div", cn, [
2158
+ F("button", {
2159
+ class: "layerboard-modal-close",
2160
+ onClick: le,
2161
+ "aria-label": "Close modal"
2162
+ }, [
2163
+ ee(_(me), {
2164
+ "icon-definition": _(ht),
2165
+ size: "medium",
2166
+ decorative: ""
2167
+ }, null, 8, ["icon-definition"])
2168
+ ]),
2169
+ se(b.$slots, "modal", { closeModal: le }, void 0, !0)
2170
+ ])
2171
+ ])) : I("", !0)
2172
+ ]));
2173
+ }
2174
+ }), Nn = /* @__PURE__ */ _e(un, [["__scopeId", "data-v-54d854f8"]]), dn = ["aria-expanded"], fn = {
2175
+ key: 0,
2176
+ class: "topic-icon"
2177
+ }, pn = { class: "topic-title" }, yn = { class: "topic-content" }, gn = /* @__PURE__ */ we({
2178
+ __name: "TopicAccordion",
2179
+ props: {
2180
+ title: {},
2181
+ icon: {},
2182
+ expanded: { type: Boolean, default: !1 },
2183
+ layerIds: { default: () => [] },
2184
+ headerClass: {}
2185
+ },
2186
+ emits: ["toggle", "layerChange"],
2187
+ setup(e, { emit: n }) {
2188
+ const o = e, t = n, l = $(o.expanded);
2189
+ xe(
2190
+ () => o.expanded,
2191
+ (c) => {
2192
+ l.value = c;
2193
+ }
2194
+ );
2195
+ function a() {
2196
+ l.value = !l.value, t("toggle", l.value);
2197
+ }
2198
+ return (c, p) => {
2199
+ const d = _t("font-awesome-icon");
2200
+ return f(), L("div", {
2201
+ class: ne(["topic-accordion", { "is-expanded": l.value }])
2202
+ }, [
2203
+ F("button", {
2204
+ class: ne(["topic-header", e.headerClass]),
2205
+ type: "button",
2206
+ "aria-expanded": l.value,
2207
+ onClick: a
2208
+ }, [
2209
+ e.icon || c.$slots.icon ? (f(), L("span", fn, [
2210
+ se(c.$slots, "icon", {}, () => [
2211
+ e.icon ? (f(), X(d, {
2212
+ key: 0,
2213
+ icon: ["fas", e.icon]
2214
+ }, null, 8, ["icon"])) : I("", !0)
2215
+ ], !0)
2216
+ ])) : I("", !0),
2217
+ F("span", pn, j(e.title), 1),
2218
+ F("span", {
2219
+ class: ne(["topic-chevron", { "is-rotated": l.value }])
2220
+ }, [...p[0] || (p[0] = [
2221
+ F("svg", {
2222
+ xmlns: "http://www.w3.org/2000/svg",
2223
+ width: "20",
2224
+ height: "20",
2225
+ viewBox: "0 0 24 24",
2226
+ fill: "none",
2227
+ stroke: "currentColor",
2228
+ "stroke-width": "2",
2229
+ "stroke-linecap": "round",
2230
+ "stroke-linejoin": "round"
2231
+ }, [
2232
+ F("polyline", { points: "6 9 12 15 18 9" })
2233
+ ], -1)
2234
+ ])], 2)
2235
+ ], 10, dn),
2236
+ St(F("div", yn, [
2237
+ se(c.$slots, "default", {}, () => [
2238
+ p[1] || (p[1] = F("p", { class: "topic-empty" }, "No content provided for this topic.", -1))
2239
+ ], !0)
2240
+ ], 512), [
2241
+ [It, l.value]
2242
+ ])
2243
+ ], 2);
2244
+ };
2245
+ }
2246
+ }), Zn = /* @__PURE__ */ _e(gn, [["__scopeId", "data-v-fb48c75b"]]), mn = { class: "layer-checkbox-set" }, hn = ["checked", "disabled", "onChange"], vn = { class: "layer-title" }, bn = {
2247
+ key: 0,
2248
+ class: "loading-indicator"
2249
+ }, wn = ["title"], Ln = {
2250
+ key: 2,
2251
+ class: "zoom-indicator"
2252
+ }, Sn = { class: "layer-title" }, Cn = {
2253
+ key: 0,
2254
+ class: "loading-indicator"
2255
+ }, kn = ["title"], $n = {
2256
+ key: 2,
2257
+ class: "zoom-indicator"
2258
+ }, Pn = {
2259
+ key: 2,
2260
+ class: "opacity-control"
2261
+ }, xn = { class: "opacity-label" }, Tn = ["value", "onInput"], Fn = {
2262
+ key: 3,
2263
+ class: "layer-legend"
2264
+ }, Mn = { class: "legend-label" }, En = {
2265
+ key: 0,
2266
+ class: "empty-state"
2267
+ }, zn = /* @__PURE__ */ we({
2268
+ __name: "LayerCheckboxSet",
2269
+ props: {
2270
+ layers: {},
2271
+ visibleLayerIds: {},
2272
+ layerOpacities: { default: () => ({}) },
2273
+ loadingLayerIds: { default: () => /* @__PURE__ */ new Set() },
2274
+ layerErrors: { default: () => ({}) },
2275
+ currentZoom: { default: 12 },
2276
+ showOpacity: { type: Boolean, default: !0 },
2277
+ showLegend: { type: Boolean, default: !0 }
2278
+ },
2279
+ emits: ["toggleLayer", "setOpacity"],
2280
+ setup(e, { emit: n }) {
2281
+ const o = e, t = n;
2282
+ function l(m) {
2283
+ return o.visibleLayerIds.has(m);
2284
+ }
2285
+ function a(m) {
2286
+ return o.layerOpacities[m] ?? 1;
2287
+ }
2288
+ function c(m) {
2289
+ return o.loadingLayerIds.has(m);
2290
+ }
2291
+ function p(m) {
2292
+ return o.layerErrors[m] || null;
2293
+ }
2294
+ function d(m) {
2295
+ const C = o.currentZoom, g = m.minZoom, w = m.maxZoom;
2296
+ return !(g !== void 0 && C < g || w !== void 0 && C > w);
2297
+ }
2298
+ function S(m) {
2299
+ return m.displayOptions?.shouldShowCheckbox !== !1;
2300
+ }
2301
+ function y(m) {
2302
+ return o.showOpacity ? m.displayOptions?.shouldShowSlider !== !1 : !1;
2303
+ }
2304
+ function h(m) {
2305
+ return o.showLegend ? m.displayOptions?.shouldShowLegendBox !== !1 : !1;
2306
+ }
2307
+ function s(m) {
2308
+ return m.displayOptions?.layerNameChange || m.title;
2309
+ }
2310
+ function v(m) {
2311
+ t("toggleLayer", m);
2312
+ }
2313
+ function E(m, C) {
2314
+ const g = C.target;
2315
+ t("setOpacity", m, parseFloat(g.value));
2316
+ }
2317
+ return (m, C) => (f(), L("div", mn, [
2318
+ (f(!0), L(ie, null, re(e.layers, (g) => (f(), L("div", {
2319
+ key: g.id,
2320
+ class: "layer-item"
2321
+ }, [
2322
+ S(g) ? (f(), L("label", {
2323
+ key: 0,
2324
+ class: ne(["layer-checkbox", {
2325
+ "layer-unavailable": !d(g),
2326
+ "layer-error": p(g.id)
2327
+ }])
2328
+ }, [
2329
+ F("input", {
2330
+ type: "checkbox",
2331
+ checked: l(g.id),
2332
+ disabled: !d(g),
2333
+ onChange: (w) => v(g.id)
2334
+ }, null, 40, hn),
2335
+ F("span", vn, [
2336
+ he(j(s(g)) + " ", 1),
2337
+ c(g.id) ? (f(), L("span", bn, " Loading... ")) : I("", !0),
2338
+ p(g.id) ? (f(), L("span", {
2339
+ key: 1,
2340
+ class: "error-indicator",
2341
+ title: p(g.id) || ""
2342
+ }, " Error ", 8, wn)) : I("", !0),
2343
+ d(g) ? I("", !0) : (f(), L("span", Ln, " (zoom in) "))
2344
+ ])
2345
+ ], 2)) : (f(), L("div", {
2346
+ key: 1,
2347
+ class: ne(["layer-label-only", {
2348
+ "layer-unavailable": !d(g),
2349
+ "layer-error": p(g.id)
2350
+ }])
2351
+ }, [
2352
+ F("span", Sn, [
2353
+ he(j(s(g)) + " ", 1),
2354
+ c(g.id) ? (f(), L("span", Cn, " Loading... ")) : I("", !0),
2355
+ p(g.id) ? (f(), L("span", {
2356
+ key: 1,
2357
+ class: "error-indicator",
2358
+ title: p(g.id) || ""
2359
+ }, " Error ", 8, kn)) : I("", !0),
2360
+ d(g) ? I("", !0) : (f(), L("span", $n, " (zoom in) "))
2361
+ ])
2362
+ ], 2)),
2363
+ y(g) && l(g.id) ? (f(), L("div", Pn, [
2364
+ F("label", xn, " Opacity: " + j(Math.round(a(g.id) * 100)) + "% ", 1),
2365
+ F("input", {
2366
+ type: "range",
2367
+ min: "0",
2368
+ max: "1",
2369
+ step: "0.05",
2370
+ value: a(g.id),
2371
+ class: "opacity-slider",
2372
+ onInput: (w) => E(g.id, w)
2373
+ }, null, 40, Tn)
2374
+ ])) : I("", !0),
2375
+ h(g) && l(g.id) && g.legend?.length ? (f(), L("ul", Fn, [
2376
+ (f(!0), L(ie, null, re(g.legend, (w, z) => (f(), L("li", {
2377
+ key: z,
2378
+ class: "legend-item"
2379
+ }, [
2380
+ w.type === "circle" ? (f(), L("span", {
2381
+ key: 0,
2382
+ class: "legend-symbol legend-circle",
2383
+ style: Y({ backgroundColor: w.color })
2384
+ }, null, 4)) : w.type === "line" ? (f(), L("span", {
2385
+ key: 1,
2386
+ class: "legend-symbol legend-line",
2387
+ style: Y({
2388
+ backgroundColor: w.color,
2389
+ height: `${w.width || 2}px`
2390
+ })
2391
+ }, null, 4)) : w.type === "fill" ? (f(), L("span", {
2392
+ key: 2,
2393
+ class: "legend-symbol legend-fill",
2394
+ style: Y({ backgroundColor: w.color })
2395
+ }, null, 4)) : I("", !0),
2396
+ F("span", Mn, j(w.label), 1)
2397
+ ]))), 128))
2398
+ ])) : I("", !0)
2399
+ ]))), 128)),
2400
+ e.layers.length === 0 ? (f(), L("div", En, " No layers available ")) : I("", !0)
2401
+ ]));
2402
+ }
2403
+ }), Bn = /* @__PURE__ */ _e(zn, [["__scopeId", "data-v-cc5e50fd"]]);
2404
+ function Wn(e) {
2405
+ const n = $([]), o = $(/* @__PURE__ */ new Set()), t = $({}), l = $(/* @__PURE__ */ new Set()), a = $({}), c = $(""), p = $(!1), d = $(!1), S = $(null), y = R(() => {
2406
+ if (!c.value.trim())
2407
+ return n.value;
2408
+ const M = c.value.toLowerCase();
2409
+ return n.value.filter(
2410
+ (N) => N.title.toLowerCase().includes(M)
2411
+ );
2412
+ }), h = R(() => n.value.map((M) => ({
2413
+ config: M,
2414
+ component: M.type
2415
+ // "circle", "fill", or "line"
2416
+ })));
2417
+ async function s() {
2418
+ if (d.value) {
2419
+ console.warn("[useLayerboard] Already initialized");
2420
+ return;
2421
+ }
2422
+ p.value = !0, S.value = null;
2423
+ try {
2424
+ let M;
2425
+ e.mode === "dynamic" || !e.mode ? e.webMapId ? M = await v(e.webMapId) : M = await lt() : M = await lt(), n.value = M;
2426
+ const N = {};
2427
+ M.forEach((q) => {
2428
+ N[q.id] = q.opacity ?? 1;
2429
+ }), t.value = N, d.value = !0, console.log(`[useLayerboard] Initialized with ${M.length} layers`);
2430
+ } catch (M) {
2431
+ S.value = M instanceof Error ? M : new Error("Failed to initialize layerboard"), console.error("[useLayerboard] Initialization error:", M);
2432
+ } finally {
2433
+ p.value = !1;
2434
+ }
2435
+ }
2436
+ async function v(M) {
2437
+ const N = Be(M);
2438
+ console.log(`[useLayerboard] Fetching WebMap from: ${N}`);
2439
+ const q = await fetch(N);
2440
+ if (!q.ok)
2441
+ throw new Error(`Failed to fetch WebMap: ${q.status} ${q.statusText}`);
2442
+ const ce = await q.json();
2443
+ return kt(ce);
2444
+ }
2445
+ function E(M) {
2446
+ const N = new Set(o.value);
2447
+ N.has(M) ? N.delete(M) : N.add(M), o.value = N;
2448
+ }
2449
+ function m(M, N) {
2450
+ t.value = {
2451
+ ...t.value,
2452
+ [M]: Math.max(0, Math.min(1, N))
2453
+ };
2454
+ }
2455
+ function C(M) {
2456
+ c.value = M;
2457
+ }
2458
+ function g(M, N) {
2459
+ const q = new Set(l.value);
2460
+ N ? q.add(M) : q.delete(M), l.value = q;
2461
+ }
2462
+ function w(M, N) {
2463
+ if (N)
2464
+ a.value = { ...a.value, [M]: N };
2465
+ else {
2466
+ const { [M]: q, ...ce } = a.value;
2467
+ a.value = ce;
2468
+ }
2469
+ }
2470
+ function z() {
2471
+ n.value = [], o.value = /* @__PURE__ */ new Set(), t.value = {}, l.value = /* @__PURE__ */ new Set(), a.value = {}, c.value = "", p.value = !1, d.value = !1, S.value = null;
2472
+ }
2473
+ return {
2474
+ // State (readonly)
2475
+ layerConfigs: V(n),
2476
+ visibleLayers: V(o),
2477
+ layerOpacities: V(t),
2478
+ loadingLayers: V(l),
2479
+ layerErrors: V(a),
2480
+ searchQuery: V(c),
2481
+ isLoading: V(p),
2482
+ isInitialized: V(d),
2483
+ error: V(S),
2484
+ // Computed
2485
+ filteredLayerConfigs: y,
2486
+ layerList: h,
2487
+ // Config
2488
+ config: e,
2489
+ // Methods
2490
+ initialize: s,
2491
+ toggleLayer: E,
2492
+ setLayerOpacity: m,
2493
+ filterLayers: C,
2494
+ setLayerLoading: g,
2495
+ setLayerError: w,
2496
+ reset: z
2497
+ };
2498
+ }
2499
+ function Un() {
2500
+ const e = $([]), n = $(/* @__PURE__ */ new Set()), o = $(/* @__PURE__ */ new Set());
2501
+ function t(a) {
2502
+ n.value.has(a) ? n.value.delete(a) : n.value.add(a);
2503
+ }
2504
+ function l(a) {
2505
+ e.value = a;
2506
+ }
2507
+ return {
2508
+ layers: R(() => e.value),
2509
+ visibleLayerIds: R(() => n.value),
2510
+ loadingLayerIds: R(() => o.value),
2511
+ toggleLayer: t,
2512
+ setLayers: l
2513
+ };
2514
+ }
2515
+ function _n(e) {
2516
+ const n = $(null), o = $(!1), t = $(null), l = $(0);
2517
+ async function a(d = {}) {
2518
+ o.value = !0, t.value = null;
2519
+ const S = e.pageSize || 2e3;
2520
+ let y = 0, h = [], s = !0;
2521
+ try {
2522
+ for (; s; ) {
2523
+ const E = e.url.replace(/\/$/, ""), m = encodeURIComponent(d.where || e.where || "1=1");
2524
+ let C = `${E}/query?where=${m}&outFields=*&returnGeometry=true&resultRecordCount=${S}&resultOffset=${y}&f=geojson`;
2525
+ if (d.bounds) {
2526
+ const z = JSON.stringify({
2527
+ xmin: d.bounds.west,
2528
+ ymin: d.bounds.south,
2529
+ xmax: d.bounds.east,
2530
+ ymax: d.bounds.north,
2531
+ spatialReference: { wkid: 4326 }
2532
+ });
2533
+ C += `&geometry=${encodeURIComponent(z)}&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects`;
2534
+ }
2535
+ const g = await fetch(C);
2536
+ if (!g.ok)
2537
+ throw new Error(`HTTP ${g.status}: ${g.statusText}`);
2538
+ const w = await g.json();
2539
+ w.features && w.features.length > 0 ? (h = h.concat(w.features), y += w.features.length, s = w.features.length === S) : s = !1;
2540
+ }
2541
+ const v = {
2542
+ type: "FeatureCollection",
2543
+ features: h
2544
+ };
2545
+ return n.value = v, l.value = h.length, v;
2546
+ } catch (v) {
2547
+ const E = v instanceof Error ? v : new Error("Failed to fetch features");
2548
+ throw t.value = E, E;
2549
+ } finally {
2550
+ o.value = !1;
2551
+ }
2552
+ }
2553
+ function c() {
2554
+ n.value = null, l.value = 0, t.value = null;
2555
+ }
2556
+ async function p(d = {}) {
2557
+ return a(d);
2558
+ }
2559
+ return {
2560
+ // State (readonly)
2561
+ data: V(n),
2562
+ isLoading: V(o),
2563
+ error: V(t),
2564
+ totalFeatures: V(l),
2565
+ // Config
2566
+ config: e,
2567
+ // Methods
2568
+ fetch: a,
2569
+ refetch: p,
2570
+ clear: c
2571
+ };
2572
+ }
2573
+ function Vn(e, n, o) {
2574
+ const t = _n(e);
2575
+ return xe(
2576
+ n,
2577
+ async (l) => {
2578
+ if (l) {
2579
+ const a = o(l);
2580
+ await t.fetch(a);
2581
+ }
2582
+ },
2583
+ { immediate: !0 }
2584
+ ), t;
2585
+ }
2586
+ export {
2587
+ Bn as LayerCheckboxSet,
2588
+ Ro as LayerPanel,
2589
+ Nn as Layerboard,
2590
+ Xt as MapPanel,
2591
+ Zn as TopicAccordion,
2592
+ Dn as WEBMAP_ID,
2593
+ Be as buildWebMapUrl,
2594
+ Jo as clearCache,
2595
+ lt as getLayerConfigs,
2596
+ An as getWebMapUrl,
2597
+ kt as transformWebMapToLayerConfigs,
2598
+ Yo as useApiDataSources,
2599
+ _n as useDataSource,
2600
+ Un as useLayerConfig,
2601
+ Wn as useLayerboard,
2602
+ Vn as useReactiveDataSource
2603
+ };