maplibre-gl-layer-control 0.1.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.mjs ADDED
@@ -0,0 +1,1166 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ function getOpacityProperty(layerType) {
5
+ switch (layerType) {
6
+ case "fill":
7
+ return "fill-opacity";
8
+ case "line":
9
+ return "line-opacity";
10
+ case "circle":
11
+ return "circle-opacity";
12
+ case "symbol":
13
+ return ["icon-opacity", "text-opacity"];
14
+ case "raster":
15
+ return "raster-opacity";
16
+ case "background":
17
+ return "background-opacity";
18
+ default:
19
+ return `${layerType}-opacity`;
20
+ }
21
+ }
22
+ function getLayerOpacity(map, layerId, layerType) {
23
+ const opacityProp = getOpacityProperty(layerType);
24
+ if (Array.isArray(opacityProp)) {
25
+ const opacity2 = map.getPaintProperty(layerId, opacityProp[0]);
26
+ return opacity2 !== void 0 && opacity2 !== null ? opacity2 : 1;
27
+ }
28
+ const opacity = map.getPaintProperty(layerId, opacityProp);
29
+ return opacity !== void 0 && opacity !== null ? opacity : 1;
30
+ }
31
+ function setLayerOpacity(map, layerId, layerType, opacity) {
32
+ const opacityProp = getOpacityProperty(layerType);
33
+ if (Array.isArray(opacityProp)) {
34
+ opacityProp.forEach((prop) => {
35
+ map.setPaintProperty(layerId, prop, opacity);
36
+ });
37
+ } else {
38
+ map.setPaintProperty(layerId, opacityProp, opacity);
39
+ }
40
+ }
41
+ function isStyleableLayerType(layerType) {
42
+ return ["fill", "line", "circle", "symbol", "raster"].includes(layerType);
43
+ }
44
+ function getLayerType(map, layerId) {
45
+ try {
46
+ const layer = map.getLayer(layerId);
47
+ return layer ? layer.type : null;
48
+ } catch (error) {
49
+ console.warn(`Failed to get layer type for ${layerId}:`, error);
50
+ return null;
51
+ }
52
+ }
53
+ function clonePaintValue(value) {
54
+ if (Array.isArray(value)) {
55
+ return value.map((item) => clonePaintValue(item));
56
+ }
57
+ if (value && typeof value === "object") {
58
+ try {
59
+ return JSON.parse(JSON.stringify(value));
60
+ } catch (error) {
61
+ return value;
62
+ }
63
+ }
64
+ return value;
65
+ }
66
+ function cacheOriginalLayerStyle(map, layerId, originalStyles) {
67
+ var _a;
68
+ if (originalStyles.has(layerId)) {
69
+ return;
70
+ }
71
+ try {
72
+ const layer = map.getLayer(layerId);
73
+ if (!layer) {
74
+ return;
75
+ }
76
+ const paint = {};
77
+ const style = map.getStyle();
78
+ const layerDef = (_a = style.layers) == null ? void 0 : _a.find((l) => l.id === layerId);
79
+ if (layer.type === "raster") {
80
+ const rasterDefaults = {
81
+ "raster-opacity": 1,
82
+ "raster-brightness-min": 0,
83
+ "raster-brightness-max": 1,
84
+ "raster-saturation": 0,
85
+ "raster-contrast": 0,
86
+ "raster-hue-rotate": 0
87
+ };
88
+ Object.assign(paint, rasterDefaults);
89
+ if (layerDef && "paint" in layerDef && layerDef.paint) {
90
+ Object.entries(layerDef.paint).forEach(([prop, value]) => {
91
+ if (prop.startsWith("raster-")) {
92
+ paint[prop] = clonePaintValue(value);
93
+ }
94
+ });
95
+ }
96
+ } else {
97
+ if (layerDef && "paint" in layerDef && layerDef.paint) {
98
+ Object.entries(layerDef.paint).forEach(([prop, value]) => {
99
+ paint[prop] = clonePaintValue(value);
100
+ });
101
+ }
102
+ }
103
+ originalStyles.set(layerId, { paint });
104
+ } catch (error) {
105
+ console.warn(`Failed to cache original style for ${layerId}:`, error);
106
+ }
107
+ }
108
+ function restoreOriginalStyle(map, layerId, originalStyles) {
109
+ const original = originalStyles.get(layerId);
110
+ if (!original) {
111
+ return {};
112
+ }
113
+ const applied = {};
114
+ Object.entries(original.paint).forEach(([property, value]) => {
115
+ try {
116
+ const restoredValue = clonePaintValue(value);
117
+ map.setPaintProperty(layerId, property, restoredValue);
118
+ applied[property] = restoredValue;
119
+ } catch (error) {
120
+ console.warn(`Failed to restore ${property} for ${layerId}:`, error);
121
+ }
122
+ });
123
+ return applied;
124
+ }
125
+ function rgbToHex(r, g, b) {
126
+ const clamp2 = (v) => Math.max(0, Math.min(255, Math.round(v)));
127
+ const toHex = (v) => {
128
+ const hex = clamp2(v).toString(16);
129
+ return hex.length === 1 ? `0${hex}` : hex;
130
+ };
131
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
132
+ }
133
+ function normalizeColor(value) {
134
+ if (typeof value === "string") {
135
+ if (value.startsWith("#")) {
136
+ if (value.length === 4) {
137
+ const r = value[1];
138
+ const g = value[2];
139
+ const b = value[3];
140
+ return `#${r}${r}${g}${g}${b}${b}`;
141
+ }
142
+ return value;
143
+ }
144
+ if (value.startsWith("rgb")) {
145
+ const match = value.match(/\d+/g);
146
+ if (match && match.length >= 3) {
147
+ const [r, g, b] = match.map((num) => parseInt(num, 10));
148
+ return rgbToHex(r, g, b);
149
+ }
150
+ }
151
+ } else if (Array.isArray(value) && value.length >= 3) {
152
+ return rgbToHex(value[0], value[1], value[2]);
153
+ }
154
+ return "#3388ff";
155
+ }
156
+ function formatNumericValue(value, step) {
157
+ let decimals = 0;
158
+ if (step && Number(step) !== 1) {
159
+ const stepNumber = Number(step);
160
+ if (stepNumber > 0 && stepNumber < 1) {
161
+ decimals = Math.min(4, Math.ceil(Math.abs(Math.log10(stepNumber))));
162
+ }
163
+ }
164
+ return value.toFixed(decimals);
165
+ }
166
+ function clamp(value, min, max) {
167
+ return Math.max(min, Math.min(max, value));
168
+ }
169
+ class LayerControl {
170
+ constructor(options = {}) {
171
+ __publicField(this, "map");
172
+ __publicField(this, "container");
173
+ __publicField(this, "button");
174
+ __publicField(this, "panel");
175
+ // State management
176
+ __publicField(this, "state");
177
+ __publicField(this, "targetLayers");
178
+ __publicField(this, "styleEditors");
179
+ // Panel width management
180
+ __publicField(this, "minPanelWidth");
181
+ __publicField(this, "maxPanelWidth");
182
+ __publicField(this, "widthSliderEl", null);
183
+ __publicField(this, "widthThumbEl", null);
184
+ __publicField(this, "widthValueEl", null);
185
+ __publicField(this, "isWidthSliderActive", false);
186
+ __publicField(this, "widthDragRectWidth", null);
187
+ __publicField(this, "widthDragStartX", null);
188
+ __publicField(this, "widthDragStartWidth", null);
189
+ __publicField(this, "widthFrame", null);
190
+ this.minPanelWidth = options.panelMinWidth || 240;
191
+ this.maxPanelWidth = options.panelMaxWidth || 420;
192
+ this.state = {
193
+ collapsed: options.collapsed !== false,
194
+ panelWidth: options.panelWidth || 320,
195
+ activeStyleEditor: null,
196
+ layerStates: options.layerStates || {},
197
+ originalStyles: /* @__PURE__ */ new Map(),
198
+ userInteractingWithSlider: false
199
+ };
200
+ this.targetLayers = options.layers || Object.keys(this.state.layerStates);
201
+ this.styleEditors = /* @__PURE__ */ new Map();
202
+ }
203
+ /**
204
+ * Called when the control is added to the map
205
+ */
206
+ onAdd(map) {
207
+ this.map = map;
208
+ if (Object.keys(this.state.layerStates).length === 0) {
209
+ this.autoDetectLayers();
210
+ }
211
+ this.container = this.createContainer();
212
+ this.button = this.createToggleButton();
213
+ this.panel = this.createPanel();
214
+ this.container.appendChild(this.button);
215
+ this.container.appendChild(this.panel);
216
+ this.updateWidthDisplay();
217
+ this.setupEventListeners();
218
+ this.buildLayerItems();
219
+ return this.container;
220
+ }
221
+ /**
222
+ * Called when the control is removed from the map
223
+ */
224
+ onRemove() {
225
+ var _a;
226
+ (_a = this.container.parentNode) == null ? void 0 : _a.removeChild(this.container);
227
+ }
228
+ /**
229
+ * Auto-detect layers from the map and populate layerStates
230
+ */
231
+ autoDetectLayers() {
232
+ const style = this.map.getStyle();
233
+ if (!style || !style.layers) {
234
+ return;
235
+ }
236
+ const allLayerIds = style.layers.map((layer) => layer.id);
237
+ if (this.targetLayers.length === 0) {
238
+ allLayerIds.forEach((layerId) => {
239
+ const layer = this.map.getLayer(layerId);
240
+ if (!layer) return;
241
+ const visibility = this.map.getLayoutProperty(layerId, "visibility");
242
+ const isVisible = visibility !== "none";
243
+ const layerType = layer.type;
244
+ const opacity = getLayerOpacity(this.map, layerId, layerType);
245
+ const friendlyName = this.generateFriendlyName(layerId);
246
+ this.state.layerStates[layerId] = {
247
+ visible: isVisible,
248
+ opacity,
249
+ name: friendlyName
250
+ };
251
+ });
252
+ } else {
253
+ const userLayers = [];
254
+ const basemapLayers = [];
255
+ allLayerIds.forEach((layerId) => {
256
+ if (this.targetLayers.includes(layerId)) {
257
+ userLayers.push(layerId);
258
+ } else {
259
+ basemapLayers.push(layerId);
260
+ }
261
+ });
262
+ if (basemapLayers.length > 0) {
263
+ this.state.layerStates["Background"] = {
264
+ visible: true,
265
+ opacity: 1,
266
+ name: "Background"
267
+ };
268
+ }
269
+ userLayers.forEach((layerId) => {
270
+ const layer = this.map.getLayer(layerId);
271
+ if (!layer) return;
272
+ const visibility = this.map.getLayoutProperty(layerId, "visibility");
273
+ const isVisible = visibility !== "none";
274
+ const layerType = layer.type;
275
+ const opacity = getLayerOpacity(this.map, layerId, layerType);
276
+ const friendlyName = this.generateFriendlyName(layerId);
277
+ this.state.layerStates[layerId] = {
278
+ visible: isVisible,
279
+ opacity,
280
+ name: friendlyName
281
+ };
282
+ });
283
+ }
284
+ this.targetLayers = Object.keys(this.state.layerStates);
285
+ }
286
+ /**
287
+ * Generate a friendly display name from a layer ID
288
+ */
289
+ generateFriendlyName(layerId) {
290
+ let name = layerId.replace(/^(layer[-_]?|gl[-_]?)/, "");
291
+ name = name.replace(/[-_]/g, " ");
292
+ name = name.replace(/\b\w/g, (char) => char.toUpperCase());
293
+ return name || layerId;
294
+ }
295
+ /**
296
+ * Create the main container element
297
+ */
298
+ createContainer() {
299
+ const container = document.createElement("div");
300
+ container.className = "maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-layer-control";
301
+ return container;
302
+ }
303
+ /**
304
+ * Create the toggle button
305
+ */
306
+ createToggleButton() {
307
+ const button = document.createElement("button");
308
+ button.type = "button";
309
+ button.title = "Layer Control";
310
+ button.setAttribute("aria-label", "Layer Control");
311
+ const icon = document.createElement("span");
312
+ icon.className = "layer-control-icon";
313
+ icon.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 3 3 8.25 12 13.5 21 8.25 12 3"></polygon><polyline points="3 12.75 12 18 21 12.75"></polyline><polyline points="3 17.25 12 22 21 17.25"></polyline></svg>';
314
+ button.appendChild(icon);
315
+ return button;
316
+ }
317
+ /**
318
+ * Create the panel element
319
+ */
320
+ createPanel() {
321
+ const panel = document.createElement("div");
322
+ panel.className = "layer-control-panel";
323
+ panel.style.width = `${this.state.panelWidth}px`;
324
+ if (!this.state.collapsed) {
325
+ panel.classList.add("expanded");
326
+ }
327
+ const header = this.createPanelHeader();
328
+ panel.appendChild(header);
329
+ return panel;
330
+ }
331
+ /**
332
+ * Create the panel header with title and width control
333
+ */
334
+ createPanelHeader() {
335
+ const header = document.createElement("div");
336
+ header.className = "layer-control-panel-header";
337
+ const title = document.createElement("span");
338
+ title.className = "layer-control-panel-title";
339
+ title.textContent = "Layers";
340
+ header.appendChild(title);
341
+ const widthControl = this.createWidthControl();
342
+ header.appendChild(widthControl);
343
+ return header;
344
+ }
345
+ /**
346
+ * Create the width control slider
347
+ */
348
+ createWidthControl() {
349
+ const widthControl = document.createElement("label");
350
+ widthControl.className = "layer-control-width-control";
351
+ widthControl.title = "Adjust layer panel width";
352
+ const widthLabel = document.createElement("span");
353
+ widthLabel.textContent = "Width";
354
+ widthControl.appendChild(widthLabel);
355
+ const widthSlider = document.createElement("div");
356
+ widthSlider.className = "layer-control-width-slider";
357
+ widthSlider.setAttribute("role", "slider");
358
+ widthSlider.setAttribute("aria-valuemin", String(this.minPanelWidth));
359
+ widthSlider.setAttribute("aria-valuemax", String(this.maxPanelWidth));
360
+ widthSlider.setAttribute("aria-valuenow", String(this.state.panelWidth));
361
+ widthSlider.setAttribute("aria-valuestep", "10");
362
+ widthSlider.setAttribute("aria-label", "Layer panel width");
363
+ widthSlider.tabIndex = 0;
364
+ const widthTrack = document.createElement("div");
365
+ widthTrack.className = "layer-control-width-track";
366
+ const widthThumb = document.createElement("div");
367
+ widthThumb.className = "layer-control-width-thumb";
368
+ widthSlider.appendChild(widthTrack);
369
+ widthSlider.appendChild(widthThumb);
370
+ this.widthSliderEl = widthSlider;
371
+ this.widthThumbEl = widthThumb;
372
+ const widthValue = document.createElement("span");
373
+ widthValue.className = "layer-control-width-value";
374
+ this.widthValueEl = widthValue;
375
+ widthControl.appendChild(widthSlider);
376
+ widthControl.appendChild(widthValue);
377
+ this.updateWidthDisplay();
378
+ this.setupWidthSliderEvents(widthSlider);
379
+ return widthControl;
380
+ }
381
+ /**
382
+ * Setup event listeners for width slider
383
+ */
384
+ setupWidthSliderEvents(widthSlider) {
385
+ widthSlider.addEventListener("pointerdown", (event) => {
386
+ event.preventDefault();
387
+ const rect = widthSlider.getBoundingClientRect();
388
+ this.widthDragRectWidth = rect.width || 1;
389
+ this.widthDragStartX = event.clientX;
390
+ this.widthDragStartWidth = this.state.panelWidth;
391
+ this.isWidthSliderActive = true;
392
+ widthSlider.setPointerCapture(event.pointerId);
393
+ this.updateWidthFromPointer(event, true);
394
+ });
395
+ widthSlider.addEventListener("pointermove", (event) => {
396
+ if (!this.isWidthSliderActive) return;
397
+ this.updateWidthFromPointer(event);
398
+ });
399
+ const endPointerDrag = (event) => {
400
+ if (!this.isWidthSliderActive) return;
401
+ if (event.pointerId !== void 0) {
402
+ try {
403
+ widthSlider.releasePointerCapture(event.pointerId);
404
+ } catch (error) {
405
+ }
406
+ }
407
+ this.isWidthSliderActive = false;
408
+ this.widthDragRectWidth = null;
409
+ this.widthDragStartX = null;
410
+ this.widthDragStartWidth = null;
411
+ this.updateWidthDisplay();
412
+ };
413
+ widthSlider.addEventListener("pointerup", endPointerDrag);
414
+ widthSlider.addEventListener("pointercancel", endPointerDrag);
415
+ widthSlider.addEventListener("lostpointercapture", endPointerDrag);
416
+ widthSlider.addEventListener("keydown", (event) => {
417
+ let handled = true;
418
+ const step = event.shiftKey ? 20 : 10;
419
+ switch (event.key) {
420
+ case "ArrowLeft":
421
+ case "ArrowDown":
422
+ this.applyPanelWidth(this.state.panelWidth - step, true);
423
+ break;
424
+ case "ArrowRight":
425
+ case "ArrowUp":
426
+ this.applyPanelWidth(this.state.panelWidth + step, true);
427
+ break;
428
+ case "Home":
429
+ this.applyPanelWidth(this.minPanelWidth, true);
430
+ break;
431
+ case "End":
432
+ this.applyPanelWidth(this.maxPanelWidth, true);
433
+ break;
434
+ case "PageUp":
435
+ this.applyPanelWidth(this.state.panelWidth + 50, true);
436
+ break;
437
+ case "PageDown":
438
+ this.applyPanelWidth(this.state.panelWidth - 50, true);
439
+ break;
440
+ default:
441
+ handled = false;
442
+ }
443
+ if (handled) {
444
+ event.preventDefault();
445
+ this.updateWidthDisplay();
446
+ }
447
+ });
448
+ }
449
+ /**
450
+ * Update panel width from pointer event
451
+ */
452
+ updateWidthFromPointer(event, resetBaseline = false) {
453
+ if (!this.widthSliderEl) return;
454
+ const sliderWidth = this.widthDragRectWidth || this.widthSliderEl.getBoundingClientRect().width || 1;
455
+ const widthRange = this.maxPanelWidth - this.minPanelWidth;
456
+ let width;
457
+ if (resetBaseline) {
458
+ const rect = this.widthSliderEl.getBoundingClientRect();
459
+ const relative = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0;
460
+ const clampedRatio = Math.min(1, Math.max(0, relative));
461
+ width = this.minPanelWidth + clampedRatio * widthRange;
462
+ this.widthDragStartWidth = width;
463
+ this.widthDragStartX = event.clientX;
464
+ } else {
465
+ const delta = event.clientX - (this.widthDragStartX || event.clientX);
466
+ width = (this.widthDragStartWidth || this.state.panelWidth) + delta / sliderWidth * widthRange;
467
+ }
468
+ this.applyPanelWidth(width, this.isWidthSliderActive);
469
+ }
470
+ /**
471
+ * Apply panel width (clamped to min/max)
472
+ */
473
+ applyPanelWidth(width, immediate = false) {
474
+ const clamped = Math.round(Math.min(this.maxPanelWidth, Math.max(this.minPanelWidth, width)));
475
+ const applyWidth = () => {
476
+ this.state.panelWidth = clamped;
477
+ const px = `${clamped}px`;
478
+ this.panel.style.width = px;
479
+ this.updateWidthDisplay();
480
+ };
481
+ if (immediate) {
482
+ applyWidth();
483
+ return;
484
+ }
485
+ if (this.widthFrame) {
486
+ cancelAnimationFrame(this.widthFrame);
487
+ }
488
+ this.widthFrame = requestAnimationFrame(() => {
489
+ applyWidth();
490
+ this.widthFrame = null;
491
+ });
492
+ }
493
+ /**
494
+ * Update width display (value label and thumb position)
495
+ */
496
+ updateWidthDisplay() {
497
+ if (this.widthValueEl) {
498
+ this.widthValueEl.textContent = `${this.state.panelWidth}px`;
499
+ }
500
+ if (this.widthSliderEl) {
501
+ this.widthSliderEl.setAttribute("aria-valuenow", String(this.state.panelWidth));
502
+ const ratio = (this.state.panelWidth - this.minPanelWidth) / (this.maxPanelWidth - this.minPanelWidth || 1);
503
+ if (this.widthThumbEl) {
504
+ const sliderWidth = this.widthSliderEl.clientWidth || 1;
505
+ const thumbWidth = this.widthThumbEl.offsetWidth || 14;
506
+ const padding = 16;
507
+ const available = Math.max(0, sliderWidth - padding - thumbWidth);
508
+ const clampedRatio = Math.min(1, Math.max(0, ratio));
509
+ const leftPx = 8 + available * clampedRatio;
510
+ this.widthThumbEl.style.left = `${leftPx}px`;
511
+ }
512
+ }
513
+ }
514
+ /**
515
+ * Setup main event listeners
516
+ */
517
+ setupEventListeners() {
518
+ this.button.addEventListener("click", () => this.toggle());
519
+ document.addEventListener("click", (e) => {
520
+ if (!this.container.contains(e.target)) {
521
+ this.collapse();
522
+ }
523
+ });
524
+ this.setupLayerChangeListeners();
525
+ }
526
+ /**
527
+ * Setup listeners for map layer changes
528
+ */
529
+ setupLayerChangeListeners() {
530
+ this.map.on("styledata", () => {
531
+ setTimeout(() => {
532
+ this.updateLayerStatesFromMap();
533
+ this.checkForNewLayers();
534
+ }, 100);
535
+ });
536
+ this.map.on("data", (e) => {
537
+ if (e.sourceDataType === "content") {
538
+ setTimeout(() => {
539
+ this.updateLayerStatesFromMap();
540
+ this.checkForNewLayers();
541
+ }, 100);
542
+ }
543
+ });
544
+ this.map.on("sourcedata", (e) => {
545
+ if (e.sourceDataType === "metadata") {
546
+ setTimeout(() => {
547
+ this.checkForNewLayers();
548
+ }, 150);
549
+ }
550
+ });
551
+ }
552
+ /**
553
+ * Toggle panel expanded/collapsed state
554
+ */
555
+ toggle() {
556
+ if (this.state.collapsed) {
557
+ this.expand();
558
+ } else {
559
+ this.collapse();
560
+ }
561
+ }
562
+ /**
563
+ * Expand the panel
564
+ */
565
+ expand() {
566
+ this.state.collapsed = false;
567
+ this.panel.classList.add("expanded");
568
+ }
569
+ /**
570
+ * Collapse the panel
571
+ */
572
+ collapse() {
573
+ this.state.collapsed = true;
574
+ this.panel.classList.remove("expanded");
575
+ }
576
+ /**
577
+ * Build layer items (called initially and when layers change)
578
+ */
579
+ buildLayerItems() {
580
+ const existingItems = this.panel.querySelectorAll(".layer-control-item");
581
+ existingItems.forEach((item) => item.remove());
582
+ this.styleEditors.clear();
583
+ Object.entries(this.state.layerStates).forEach(([layerId, state]) => {
584
+ if (this.targetLayers.length === 0 || this.targetLayers.includes(layerId)) {
585
+ this.addLayerItem(layerId, state);
586
+ }
587
+ });
588
+ }
589
+ /**
590
+ * Add a single layer item to the panel
591
+ */
592
+ addLayerItem(layerId, state) {
593
+ const item = document.createElement("div");
594
+ item.className = "layer-control-item";
595
+ item.setAttribute("data-layer-id", layerId);
596
+ const row = document.createElement("div");
597
+ row.className = "layer-control-row";
598
+ const checkbox = document.createElement("input");
599
+ checkbox.type = "checkbox";
600
+ checkbox.className = "layer-control-checkbox";
601
+ checkbox.checked = state.visible;
602
+ checkbox.addEventListener("change", () => {
603
+ this.toggleLayerVisibility(layerId, checkbox.checked);
604
+ });
605
+ const name = document.createElement("span");
606
+ name.className = "layer-control-name";
607
+ name.textContent = state.name || layerId;
608
+ name.title = state.name || layerId;
609
+ const opacity = document.createElement("input");
610
+ opacity.type = "range";
611
+ opacity.className = "layer-control-opacity";
612
+ opacity.min = "0";
613
+ opacity.max = "1";
614
+ opacity.step = "0.01";
615
+ opacity.value = String(state.opacity);
616
+ opacity.title = `Opacity: ${Math.round(state.opacity * 100)}%`;
617
+ opacity.addEventListener("mousedown", () => {
618
+ this.state.userInteractingWithSlider = true;
619
+ });
620
+ opacity.addEventListener("mouseup", () => {
621
+ this.state.userInteractingWithSlider = false;
622
+ });
623
+ opacity.addEventListener("input", () => {
624
+ this.changeLayerOpacity(layerId, parseFloat(opacity.value));
625
+ opacity.title = `Opacity: ${Math.round(parseFloat(opacity.value) * 100)}%`;
626
+ });
627
+ row.appendChild(checkbox);
628
+ row.appendChild(name);
629
+ row.appendChild(opacity);
630
+ if (layerId !== "Background") {
631
+ const styleButton = this.createStyleButton(layerId);
632
+ if (styleButton) {
633
+ row.appendChild(styleButton);
634
+ }
635
+ }
636
+ item.appendChild(row);
637
+ this.panel.appendChild(item);
638
+ }
639
+ /**
640
+ * Toggle layer visibility
641
+ */
642
+ toggleLayerVisibility(layerId, visible) {
643
+ if (layerId === "Background") {
644
+ this.toggleBackgroundVisibility(visible);
645
+ return;
646
+ }
647
+ if (this.state.layerStates[layerId]) {
648
+ this.state.layerStates[layerId].visible = visible;
649
+ }
650
+ this.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
651
+ }
652
+ /**
653
+ * Change layer opacity
654
+ */
655
+ changeLayerOpacity(layerId, opacity) {
656
+ if (layerId === "Background") {
657
+ this.changeBackgroundOpacity(opacity);
658
+ return;
659
+ }
660
+ if (this.state.layerStates[layerId]) {
661
+ this.state.layerStates[layerId].opacity = opacity;
662
+ }
663
+ const layerType = getLayerType(this.map, layerId);
664
+ if (layerType) {
665
+ setLayerOpacity(this.map, layerId, layerType, opacity);
666
+ }
667
+ }
668
+ /**
669
+ * Check if a layer is a user-added layer (vs basemap layer)
670
+ */
671
+ isUserAddedLayer(layerId) {
672
+ return this.state.layerStates[layerId] !== void 0 && layerId !== "Background";
673
+ }
674
+ /**
675
+ * Toggle visibility for all background layers (basemap layers)
676
+ */
677
+ toggleBackgroundVisibility(visible) {
678
+ if (this.state.layerStates["Background"]) {
679
+ this.state.layerStates["Background"].visible = visible;
680
+ }
681
+ const styleLayers = this.map.getStyle().layers || [];
682
+ styleLayers.forEach((layer) => {
683
+ if (!this.isUserAddedLayer(layer.id)) {
684
+ this.map.setLayoutProperty(layer.id, "visibility", visible ? "visible" : "none");
685
+ }
686
+ });
687
+ }
688
+ /**
689
+ * Change opacity for all background layers (basemap layers)
690
+ */
691
+ changeBackgroundOpacity(opacity) {
692
+ if (this.state.layerStates["Background"]) {
693
+ this.state.layerStates["Background"].opacity = opacity;
694
+ }
695
+ const styleLayers = this.map.getStyle().layers || [];
696
+ styleLayers.forEach((styleLayer) => {
697
+ if (!this.isUserAddedLayer(styleLayer.id)) {
698
+ const layerType = getLayerType(this.map, styleLayer.id);
699
+ if (layerType) {
700
+ setLayerOpacity(this.map, styleLayer.id, layerType, opacity);
701
+ }
702
+ }
703
+ });
704
+ }
705
+ /**
706
+ * Create style button for a layer
707
+ */
708
+ createStyleButton(layerId) {
709
+ if (layerId === "Background") {
710
+ return null;
711
+ }
712
+ const button = document.createElement("button");
713
+ button.className = "layer-control-style-button";
714
+ button.innerHTML = "&#9881;";
715
+ button.title = "Edit layer style";
716
+ button.setAttribute("aria-label", `Edit style for ${layerId}`);
717
+ button.addEventListener("click", (e) => {
718
+ e.stopPropagation();
719
+ this.toggleStyleEditor(layerId);
720
+ });
721
+ return button;
722
+ }
723
+ /**
724
+ * Toggle style editor for a layer
725
+ */
726
+ toggleStyleEditor(layerId) {
727
+ if (this.state.activeStyleEditor === layerId) {
728
+ this.closeStyleEditor(layerId);
729
+ return;
730
+ }
731
+ if (this.state.activeStyleEditor) {
732
+ this.closeStyleEditor(this.state.activeStyleEditor);
733
+ }
734
+ this.openStyleEditor(layerId);
735
+ }
736
+ /**
737
+ * Open style editor for a layer
738
+ */
739
+ openStyleEditor(layerId) {
740
+ const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
741
+ if (!itemEl) return;
742
+ if (!this.state.originalStyles.has(layerId)) {
743
+ const layer = this.map.getLayer(layerId);
744
+ if (layer) {
745
+ cacheOriginalLayerStyle(this.map, layerId, this.state.originalStyles);
746
+ }
747
+ }
748
+ const editor = this.createStyleEditor(layerId);
749
+ if (!editor) return;
750
+ itemEl.appendChild(editor);
751
+ this.styleEditors.set(layerId, editor);
752
+ this.state.activeStyleEditor = layerId;
753
+ setTimeout(() => {
754
+ editor.scrollIntoView({ behavior: "smooth", block: "nearest" });
755
+ }, 50);
756
+ }
757
+ /**
758
+ * Close style editor for a layer
759
+ */
760
+ closeStyleEditor(layerId) {
761
+ const editor = this.styleEditors.get(layerId);
762
+ if (editor) {
763
+ editor.remove();
764
+ this.styleEditors.delete(layerId);
765
+ }
766
+ if (this.state.activeStyleEditor === layerId) {
767
+ this.state.activeStyleEditor = null;
768
+ }
769
+ }
770
+ /**
771
+ * Create style editor UI
772
+ */
773
+ createStyleEditor(layerId) {
774
+ const layer = this.map.getLayer(layerId);
775
+ if (!layer) return null;
776
+ const editor = document.createElement("div");
777
+ editor.className = "layer-control-style-editor";
778
+ const header = document.createElement("div");
779
+ header.className = "style-editor-header";
780
+ const title = document.createElement("span");
781
+ title.className = "style-editor-title";
782
+ title.textContent = "Edit Style";
783
+ const closeBtn = document.createElement("button");
784
+ closeBtn.className = "style-editor-close";
785
+ closeBtn.innerHTML = "&times;";
786
+ closeBtn.title = "Close";
787
+ closeBtn.addEventListener("click", (e) => {
788
+ e.stopPropagation();
789
+ this.closeStyleEditor(layerId);
790
+ });
791
+ header.appendChild(title);
792
+ header.appendChild(closeBtn);
793
+ const controls = document.createElement("div");
794
+ controls.className = "style-editor-controls";
795
+ const layerType = layer.type;
796
+ this.addStyleControlsForLayerType(controls, layerId, layerType);
797
+ const actions = document.createElement("div");
798
+ actions.className = "style-editor-actions";
799
+ const resetBtn = document.createElement("button");
800
+ resetBtn.className = "style-editor-button style-editor-button-reset";
801
+ resetBtn.textContent = "Reset";
802
+ resetBtn.addEventListener("click", (e) => {
803
+ e.stopPropagation();
804
+ this.resetLayerStyle(layerId);
805
+ });
806
+ const closeActionBtn = document.createElement("button");
807
+ closeActionBtn.className = "style-editor-button style-editor-button-close";
808
+ closeActionBtn.textContent = "Close";
809
+ closeActionBtn.addEventListener("click", (e) => {
810
+ e.stopPropagation();
811
+ this.closeStyleEditor(layerId);
812
+ });
813
+ actions.appendChild(resetBtn);
814
+ actions.appendChild(closeActionBtn);
815
+ editor.appendChild(header);
816
+ editor.appendChild(controls);
817
+ editor.appendChild(actions);
818
+ return editor;
819
+ }
820
+ /**
821
+ * Add style controls based on layer type
822
+ */
823
+ addStyleControlsForLayerType(container, layerId, layerType) {
824
+ switch (layerType) {
825
+ case "fill":
826
+ this.addFillControls(container, layerId);
827
+ break;
828
+ case "line":
829
+ this.addLineControls(container, layerId);
830
+ break;
831
+ case "circle":
832
+ this.addCircleControls(container, layerId);
833
+ break;
834
+ case "raster":
835
+ this.addRasterControls(container, layerId);
836
+ break;
837
+ case "symbol":
838
+ this.addSymbolControls(container, layerId);
839
+ break;
840
+ default:
841
+ container.textContent = `Style controls for ${layerType} layers not yet implemented.`;
842
+ }
843
+ }
844
+ /**
845
+ * Add controls for fill layers
846
+ */
847
+ addFillControls(container, layerId) {
848
+ var _a;
849
+ const style = this.map.getStyle();
850
+ const layer = (_a = style.layers) == null ? void 0 : _a.find((l) => l.id === layerId);
851
+ let fillColor = void 0;
852
+ if (layer && "paint" in layer && layer.paint && "fill-color" in layer.paint) {
853
+ fillColor = layer.paint["fill-color"];
854
+ }
855
+ if (!fillColor) {
856
+ fillColor = this.map.getPaintProperty(layerId, "fill-color");
857
+ }
858
+ this.createColorControl(container, layerId, "fill-color", "Fill Color", normalizeColor(fillColor || "#088"));
859
+ const fillOpacity = this.map.getPaintProperty(layerId, "fill-opacity");
860
+ if (fillOpacity !== void 0 && typeof fillOpacity === "number") {
861
+ this.createSliderControl(container, layerId, "fill-opacity", "Fill Opacity", fillOpacity, 0, 1, 0.05);
862
+ }
863
+ const outlineColor = this.map.getPaintProperty(layerId, "fill-outline-color");
864
+ if (outlineColor !== void 0) {
865
+ this.createColorControl(container, layerId, "fill-outline-color", "Outline Color", normalizeColor(outlineColor));
866
+ }
867
+ }
868
+ /**
869
+ * Add controls for line layers
870
+ */
871
+ addLineControls(container, layerId) {
872
+ var _a;
873
+ const style = this.map.getStyle();
874
+ const layer = (_a = style.layers) == null ? void 0 : _a.find((l) => l.id === layerId);
875
+ let lineColor = void 0;
876
+ if (layer && "paint" in layer && layer.paint && "line-color" in layer.paint) {
877
+ lineColor = layer.paint["line-color"];
878
+ }
879
+ if (!lineColor) {
880
+ lineColor = this.map.getPaintProperty(layerId, "line-color");
881
+ }
882
+ this.createColorControl(container, layerId, "line-color", "Line Color", normalizeColor(lineColor || "#000"));
883
+ const lineWidth = this.map.getPaintProperty(layerId, "line-width");
884
+ this.createSliderControl(container, layerId, "line-width", "Line Width", typeof lineWidth === "number" ? lineWidth : 1, 0, 20, 0.5);
885
+ const lineOpacity = this.map.getPaintProperty(layerId, "line-opacity");
886
+ if (lineOpacity !== void 0 && typeof lineOpacity === "number") {
887
+ this.createSliderControl(container, layerId, "line-opacity", "Line Opacity", lineOpacity, 0, 1, 0.05);
888
+ }
889
+ const lineBlur = this.map.getPaintProperty(layerId, "line-blur");
890
+ if (lineBlur !== void 0 && typeof lineBlur === "number") {
891
+ this.createSliderControl(container, layerId, "line-blur", "Line Blur", lineBlur, 0, 5, 0.1);
892
+ }
893
+ }
894
+ /**
895
+ * Add controls for circle layers
896
+ */
897
+ addCircleControls(container, layerId) {
898
+ var _a;
899
+ const style = this.map.getStyle();
900
+ const layer = (_a = style.layers) == null ? void 0 : _a.find((l) => l.id === layerId);
901
+ let circleColor = void 0;
902
+ if (layer && "paint" in layer && layer.paint && "circle-color" in layer.paint) {
903
+ circleColor = layer.paint["circle-color"];
904
+ }
905
+ if (!circleColor) {
906
+ circleColor = this.map.getPaintProperty(layerId, "circle-color");
907
+ }
908
+ this.createColorControl(container, layerId, "circle-color", "Circle Color", normalizeColor(circleColor || "#000"));
909
+ const circleRadius = this.map.getPaintProperty(layerId, "circle-radius");
910
+ this.createSliderControl(container, layerId, "circle-radius", "Radius", typeof circleRadius === "number" ? circleRadius : 5, 0, 40, 0.5);
911
+ const circleOpacity = this.map.getPaintProperty(layerId, "circle-opacity");
912
+ if (circleOpacity !== void 0 && typeof circleOpacity === "number") {
913
+ this.createSliderControl(container, layerId, "circle-opacity", "Opacity", circleOpacity, 0, 1, 0.05);
914
+ }
915
+ const strokeColor = this.map.getPaintProperty(layerId, "circle-stroke-color");
916
+ if (strokeColor !== void 0) {
917
+ this.createColorControl(container, layerId, "circle-stroke-color", "Stroke Color", normalizeColor(strokeColor));
918
+ }
919
+ const strokeWidth = this.map.getPaintProperty(layerId, "circle-stroke-width");
920
+ if (strokeWidth !== void 0 && typeof strokeWidth === "number") {
921
+ this.createSliderControl(container, layerId, "circle-stroke-width", "Stroke Width", strokeWidth, 0, 10, 0.1);
922
+ }
923
+ }
924
+ /**
925
+ * Add controls for raster layers
926
+ */
927
+ addRasterControls(container, layerId) {
928
+ const rasterOpacity = this.map.getPaintProperty(layerId, "raster-opacity");
929
+ this.createSliderControl(container, layerId, "raster-opacity", "Opacity", typeof rasterOpacity === "number" ? rasterOpacity : 1, 0, 1, 0.05);
930
+ const brightnessMin = this.map.getPaintProperty(layerId, "raster-brightness-min");
931
+ this.createSliderControl(container, layerId, "raster-brightness-min", "Brightness Min", typeof brightnessMin === "number" ? brightnessMin : 0, -1, 1, 0.05);
932
+ const brightnessMax = this.map.getPaintProperty(layerId, "raster-brightness-max");
933
+ this.createSliderControl(container, layerId, "raster-brightness-max", "Brightness Max", typeof brightnessMax === "number" ? brightnessMax : 1, -1, 1, 0.05);
934
+ const saturation = this.map.getPaintProperty(layerId, "raster-saturation");
935
+ this.createSliderControl(container, layerId, "raster-saturation", "Saturation", typeof saturation === "number" ? saturation : 0, -1, 1, 0.05);
936
+ const contrast = this.map.getPaintProperty(layerId, "raster-contrast");
937
+ this.createSliderControl(container, layerId, "raster-contrast", "Contrast", typeof contrast === "number" ? contrast : 0, -1, 1, 0.05);
938
+ const hueRotate = this.map.getPaintProperty(layerId, "raster-hue-rotate");
939
+ this.createSliderControl(container, layerId, "raster-hue-rotate", "Hue Rotate", typeof hueRotate === "number" ? hueRotate : 0, 0, 360, 5);
940
+ }
941
+ /**
942
+ * Add controls for symbol layers
943
+ */
944
+ addSymbolControls(container, layerId) {
945
+ const textColor = this.map.getPaintProperty(layerId, "text-color");
946
+ if (textColor !== void 0) {
947
+ this.createColorControl(container, layerId, "text-color", "Text Color", normalizeColor(textColor));
948
+ }
949
+ const textOpacity = this.map.getPaintProperty(layerId, "text-opacity");
950
+ if (textOpacity !== void 0 && typeof textOpacity === "number") {
951
+ this.createSliderControl(container, layerId, "text-opacity", "Text Opacity", textOpacity, 0, 1, 0.05);
952
+ }
953
+ const iconOpacity = this.map.getPaintProperty(layerId, "icon-opacity");
954
+ if (iconOpacity !== void 0 && typeof iconOpacity === "number") {
955
+ this.createSliderControl(container, layerId, "icon-opacity", "Icon Opacity", iconOpacity, 0, 1, 0.05);
956
+ }
957
+ }
958
+ /**
959
+ * Create a color control
960
+ */
961
+ createColorControl(container, layerId, property, label, initialValue) {
962
+ const controlGroup = document.createElement("div");
963
+ controlGroup.className = "style-control-group";
964
+ const labelEl = document.createElement("label");
965
+ labelEl.className = "style-control-label";
966
+ labelEl.textContent = label;
967
+ const inputWrapper = document.createElement("div");
968
+ inputWrapper.className = "style-control-color-group";
969
+ const colorInput = document.createElement("input");
970
+ colorInput.type = "color";
971
+ colorInput.className = "style-control-color-picker";
972
+ colorInput.value = initialValue;
973
+ colorInput.dataset.property = property;
974
+ const hexDisplay = document.createElement("input");
975
+ hexDisplay.type = "text";
976
+ hexDisplay.className = "style-control-color-value";
977
+ hexDisplay.value = initialValue;
978
+ hexDisplay.readOnly = true;
979
+ colorInput.addEventListener("input", () => {
980
+ const color = colorInput.value;
981
+ hexDisplay.value = color;
982
+ this.map.setPaintProperty(layerId, property, color);
983
+ });
984
+ inputWrapper.appendChild(colorInput);
985
+ inputWrapper.appendChild(hexDisplay);
986
+ controlGroup.appendChild(labelEl);
987
+ controlGroup.appendChild(inputWrapper);
988
+ container.appendChild(controlGroup);
989
+ }
990
+ /**
991
+ * Create a slider control
992
+ */
993
+ createSliderControl(container, layerId, property, label, initialValue, min, max, step) {
994
+ const controlGroup = document.createElement("div");
995
+ controlGroup.className = "style-control-group";
996
+ const labelEl = document.createElement("label");
997
+ labelEl.className = "style-control-label";
998
+ labelEl.textContent = label;
999
+ const inputWrapper = document.createElement("div");
1000
+ inputWrapper.className = "style-control-input-wrapper";
1001
+ const slider = document.createElement("input");
1002
+ slider.type = "range";
1003
+ slider.className = "style-control-slider";
1004
+ slider.min = String(min);
1005
+ slider.max = String(max);
1006
+ slider.step = String(step);
1007
+ slider.value = String(initialValue);
1008
+ slider.dataset.property = property;
1009
+ const valueDisplay = document.createElement("span");
1010
+ valueDisplay.className = "style-control-value";
1011
+ valueDisplay.textContent = formatNumericValue(initialValue, step);
1012
+ slider.addEventListener("input", () => {
1013
+ const value = parseFloat(slider.value);
1014
+ valueDisplay.textContent = formatNumericValue(value, step);
1015
+ this.map.setPaintProperty(layerId, property, value);
1016
+ });
1017
+ inputWrapper.appendChild(slider);
1018
+ inputWrapper.appendChild(valueDisplay);
1019
+ controlGroup.appendChild(labelEl);
1020
+ controlGroup.appendChild(inputWrapper);
1021
+ container.appendChild(controlGroup);
1022
+ }
1023
+ /**
1024
+ * Reset layer style to original
1025
+ */
1026
+ resetLayerStyle(layerId) {
1027
+ const originalStyle = this.state.originalStyles.get(layerId);
1028
+ if (!originalStyle) return;
1029
+ restoreOriginalStyle(this.map, layerId, this.state.originalStyles);
1030
+ const editor = this.styleEditors.get(layerId);
1031
+ if (editor) {
1032
+ const sliders = editor.querySelectorAll(".style-control-slider");
1033
+ sliders.forEach((slider) => {
1034
+ var _a;
1035
+ const property = slider.dataset.property;
1036
+ if (property) {
1037
+ const value = this.map.getPaintProperty(layerId, property);
1038
+ if (value !== void 0 && typeof value === "number") {
1039
+ slider.value = String(value);
1040
+ const valueDisplay = (_a = slider.parentElement) == null ? void 0 : _a.querySelector(".style-control-value");
1041
+ if (valueDisplay) {
1042
+ const step = parseFloat(slider.step);
1043
+ valueDisplay.textContent = formatNumericValue(value, step);
1044
+ }
1045
+ }
1046
+ }
1047
+ });
1048
+ const colorPickers = editor.querySelectorAll(".style-control-color-picker");
1049
+ colorPickers.forEach((picker) => {
1050
+ var _a;
1051
+ const property = picker.dataset.property;
1052
+ if (property) {
1053
+ const value = this.map.getPaintProperty(layerId, property);
1054
+ if (value !== void 0) {
1055
+ const hexColor = normalizeColor(value);
1056
+ picker.value = hexColor;
1057
+ const hexDisplay = (_a = picker.parentElement) == null ? void 0 : _a.querySelector(".style-control-color-value");
1058
+ if (hexDisplay) {
1059
+ hexDisplay.textContent = hexColor;
1060
+ }
1061
+ }
1062
+ }
1063
+ });
1064
+ }
1065
+ }
1066
+ /**
1067
+ * Update layer states from map (sync UI with map)
1068
+ */
1069
+ updateLayerStatesFromMap() {
1070
+ if (this.state.userInteractingWithSlider) {
1071
+ return;
1072
+ }
1073
+ Object.keys(this.state.layerStates).forEach((layerId) => {
1074
+ try {
1075
+ const layer = this.map.getLayer(layerId);
1076
+ if (!layer) return;
1077
+ const visibility = this.map.getLayoutProperty(layerId, "visibility");
1078
+ const isVisible = visibility !== "none";
1079
+ const layerType = layer.type;
1080
+ const opacity = getLayerOpacity(this.map, layerId, layerType);
1081
+ if (this.state.layerStates[layerId]) {
1082
+ this.state.layerStates[layerId].visible = isVisible;
1083
+ this.state.layerStates[layerId].opacity = opacity;
1084
+ }
1085
+ this.updateUIForLayer(layerId, isVisible, opacity);
1086
+ } catch (error) {
1087
+ console.warn(`Failed to update state for layer ${layerId}:`, error);
1088
+ }
1089
+ });
1090
+ }
1091
+ /**
1092
+ * Update UI elements for a specific layer
1093
+ */
1094
+ updateUIForLayer(layerId, visible, opacity) {
1095
+ const layerItems = this.panel.querySelectorAll(".layer-control-item");
1096
+ layerItems.forEach((item) => {
1097
+ if (item.dataset.layerId === layerId) {
1098
+ const checkbox = item.querySelector(".layer-control-checkbox");
1099
+ const opacitySlider = item.querySelector(".layer-control-opacity");
1100
+ if (checkbox) {
1101
+ checkbox.checked = visible;
1102
+ }
1103
+ if (opacitySlider) {
1104
+ opacitySlider.value = String(opacity);
1105
+ opacitySlider.title = `Opacity: ${Math.round(opacity * 100)}%`;
1106
+ }
1107
+ }
1108
+ });
1109
+ }
1110
+ /**
1111
+ * Check for new layers and add them to the control
1112
+ */
1113
+ checkForNewLayers() {
1114
+ try {
1115
+ const style = this.map.getStyle();
1116
+ if (!style || !style.layers) {
1117
+ return;
1118
+ }
1119
+ const currentMapLayers = style.layers.map((layer) => layer.id).filter((id) => {
1120
+ if (this.targetLayers.length > 0) {
1121
+ return this.targetLayers.includes(id);
1122
+ }
1123
+ return true;
1124
+ });
1125
+ const newLayers = [];
1126
+ currentMapLayers.forEach((layerId) => {
1127
+ if (layerId !== "Background" && !this.state.layerStates[layerId]) {
1128
+ const layer = this.map.getLayer(layerId);
1129
+ if (layer) {
1130
+ newLayers.push(layerId);
1131
+ }
1132
+ }
1133
+ });
1134
+ if (newLayers.length > 0) {
1135
+ newLayers.forEach((layerId) => {
1136
+ const layer = this.map.getLayer(layerId);
1137
+ if (!layer) return;
1138
+ const layerType = layer.type;
1139
+ const opacity = getLayerOpacity(this.map, layerId, layerType);
1140
+ const visibility = this.map.getLayoutProperty(layerId, "visibility");
1141
+ const isVisible = visibility !== "none";
1142
+ this.state.layerStates[layerId] = {
1143
+ visible: isVisible,
1144
+ opacity,
1145
+ name: layerId.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase())
1146
+ };
1147
+ this.addLayerItem(layerId, this.state.layerStates[layerId]);
1148
+ });
1149
+ }
1150
+ } catch (error) {
1151
+ console.warn("Failed to check for new layers:", error);
1152
+ }
1153
+ }
1154
+ }
1155
+ export {
1156
+ LayerControl,
1157
+ clamp,
1158
+ formatNumericValue,
1159
+ getLayerOpacity,
1160
+ getLayerType,
1161
+ isStyleableLayerType,
1162
+ normalizeColor,
1163
+ rgbToHex,
1164
+ setLayerOpacity
1165
+ };
1166
+ //# sourceMappingURL=index.mjs.map