maplibre-gl-layer-control 0.5.0 → 0.6.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.cjs +353 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +353 -12
- package/dist/index.mjs.map +1 -1
- package/dist/maplibre-gl-layer-control.css +12 -0
- package/dist/types/index.d.ts +113 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,145 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
+
class CustomLayerRegistry {
|
|
7
|
+
constructor() {
|
|
8
|
+
__publicField(this, "adapters", /* @__PURE__ */ new Map());
|
|
9
|
+
__publicField(this, "changeListeners", []);
|
|
10
|
+
__publicField(this, "unsubscribers", []);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register a custom layer adapter.
|
|
14
|
+
* @param adapter The adapter to register
|
|
15
|
+
*/
|
|
16
|
+
register(adapter) {
|
|
17
|
+
this.adapters.set(adapter.type, adapter);
|
|
18
|
+
if (adapter.onLayerChange) {
|
|
19
|
+
const unsubscribe = adapter.onLayerChange((event, layerId) => {
|
|
20
|
+
this.notifyChange(event, layerId);
|
|
21
|
+
});
|
|
22
|
+
this.unsubscribers.push(unsubscribe);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Unregister an adapter by type.
|
|
27
|
+
* @param type The adapter type to unregister
|
|
28
|
+
*/
|
|
29
|
+
unregister(type) {
|
|
30
|
+
this.adapters.delete(type);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get all custom layer IDs across all adapters.
|
|
34
|
+
* @returns Array of layer IDs
|
|
35
|
+
*/
|
|
36
|
+
getAllLayerIds() {
|
|
37
|
+
const ids = [];
|
|
38
|
+
this.adapters.forEach((adapter) => {
|
|
39
|
+
ids.push(...adapter.getLayerIds());
|
|
40
|
+
});
|
|
41
|
+
return ids;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a layer ID is managed by any adapter.
|
|
45
|
+
* @param layerId The layer ID to check
|
|
46
|
+
* @returns true if the layer is managed by an adapter
|
|
47
|
+
*/
|
|
48
|
+
hasLayer(layerId) {
|
|
49
|
+
for (const adapter of this.adapters.values()) {
|
|
50
|
+
if (adapter.getLayerIds().includes(layerId)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the adapter responsible for a specific layer.
|
|
58
|
+
* @param layerId The layer ID
|
|
59
|
+
* @returns The adapter or null if not found
|
|
60
|
+
*/
|
|
61
|
+
getAdapterForLayer(layerId) {
|
|
62
|
+
for (const adapter of this.adapters.values()) {
|
|
63
|
+
if (adapter.getLayerIds().includes(layerId)) {
|
|
64
|
+
return adapter;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the state of a custom layer.
|
|
71
|
+
* @param layerId The layer ID
|
|
72
|
+
* @returns The layer state or null if not found
|
|
73
|
+
*/
|
|
74
|
+
getLayerState(layerId) {
|
|
75
|
+
const adapter = this.getAdapterForLayer(layerId);
|
|
76
|
+
return adapter ? adapter.getLayerState(layerId) : null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Set visibility of a custom layer.
|
|
80
|
+
* @param layerId The layer ID
|
|
81
|
+
* @param visible Whether the layer should be visible
|
|
82
|
+
* @returns true if the operation was handled by an adapter
|
|
83
|
+
*/
|
|
84
|
+
setVisibility(layerId, visible) {
|
|
85
|
+
const adapter = this.getAdapterForLayer(layerId);
|
|
86
|
+
if (adapter) {
|
|
87
|
+
adapter.setVisibility(layerId, visible);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Set opacity of a custom layer.
|
|
94
|
+
* @param layerId The layer ID
|
|
95
|
+
* @param opacity The opacity value (0-1)
|
|
96
|
+
* @returns true if the operation was handled by an adapter
|
|
97
|
+
*/
|
|
98
|
+
setOpacity(layerId, opacity) {
|
|
99
|
+
const adapter = this.getAdapterForLayer(layerId);
|
|
100
|
+
if (adapter) {
|
|
101
|
+
adapter.setOpacity(layerId, opacity);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the symbol type for a custom layer (for UI display).
|
|
108
|
+
* @param layerId The layer ID
|
|
109
|
+
* @returns The symbol type or null if not available
|
|
110
|
+
*/
|
|
111
|
+
getSymbolType(layerId) {
|
|
112
|
+
const adapter = this.getAdapterForLayer(layerId);
|
|
113
|
+
if (adapter && adapter.getSymbolType) {
|
|
114
|
+
return adapter.getSymbolType(layerId);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Subscribe to layer changes across all adapters.
|
|
120
|
+
* @param callback Function called when layers are added or removed
|
|
121
|
+
* @returns Unsubscribe function
|
|
122
|
+
*/
|
|
123
|
+
onChange(callback) {
|
|
124
|
+
this.changeListeners.push(callback);
|
|
125
|
+
return () => {
|
|
126
|
+
const idx = this.changeListeners.indexOf(callback);
|
|
127
|
+
if (idx >= 0) {
|
|
128
|
+
this.changeListeners.splice(idx, 1);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
notifyChange(event, layerId) {
|
|
133
|
+
this.changeListeners.forEach((cb) => cb(event, layerId));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clean up all subscriptions and adapters.
|
|
137
|
+
*/
|
|
138
|
+
destroy() {
|
|
139
|
+
this.unsubscribers.forEach((unsub) => unsub());
|
|
140
|
+
this.unsubscribers = [];
|
|
141
|
+
this.adapters.clear();
|
|
142
|
+
this.changeListeners = [];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
6
145
|
function getOpacityProperty(layerType) {
|
|
7
146
|
switch (layerType) {
|
|
8
147
|
case "fill":
|
|
@@ -379,6 +518,46 @@ function createDefaultSymbol(size, color) {
|
|
|
379
518
|
fill="${color}" stroke="${borderColor}" stroke-width="1"/>
|
|
380
519
|
</svg>`;
|
|
381
520
|
}
|
|
521
|
+
function createCOGSymbol(size, color) {
|
|
522
|
+
const padding = 2;
|
|
523
|
+
const borderColor = darkenColor(color, 0.3);
|
|
524
|
+
const cellSize = (size - padding * 2) / 2;
|
|
525
|
+
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
526
|
+
<rect x="${padding}" y="${padding}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5"/>
|
|
527
|
+
<rect x="${padding + cellSize}" y="${padding}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.8"/>
|
|
528
|
+
<rect x="${padding}" y="${padding + cellSize}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.6"/>
|
|
529
|
+
<rect x="${padding + cellSize}" y="${padding + cellSize}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.4"/>
|
|
530
|
+
</svg>`;
|
|
531
|
+
}
|
|
532
|
+
function createZarrSymbol(size, color) {
|
|
533
|
+
const padding = 2;
|
|
534
|
+
const borderColor = darkenColor(color, 0.3);
|
|
535
|
+
const innerSize = size - padding * 2;
|
|
536
|
+
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
537
|
+
<rect x="${padding + 2}" y="${padding}" width="${innerSize - 2}" height="${innerSize - 2}" fill="${darkenColor(color, 0.2)}" stroke="${borderColor}" stroke-width="0.5" rx="1"/>
|
|
538
|
+
<rect x="${padding + 1}" y="${padding + 1}" width="${innerSize - 2}" height="${innerSize - 2}" fill="${darkenColor(color, 0.1)}" stroke="${borderColor}" stroke-width="0.5" rx="1"/>
|
|
539
|
+
<rect x="${padding}" y="${padding + 2}" width="${innerSize - 2}" height="${innerSize - 2}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" rx="1"/>
|
|
540
|
+
<line x1="${padding + 3}" y1="${padding + 5}" x2="${padding + innerSize - 5}" y2="${padding + 5}" stroke="${borderColor}" stroke-width="0.5" opacity="0.5"/>
|
|
541
|
+
<line x1="${padding + 3}" y1="${padding + 8}" x2="${padding + innerSize - 5}" y2="${padding + 8}" stroke="${borderColor}" stroke-width="0.5" opacity="0.5"/>
|
|
542
|
+
</svg>`;
|
|
543
|
+
}
|
|
544
|
+
function createCustomRasterSymbol(size, color) {
|
|
545
|
+
const padding = 2;
|
|
546
|
+
const borderColor = darkenColor(color, 0.3);
|
|
547
|
+
const id = `customRasterGrad_${Math.random().toString(36).slice(2, 9)}`;
|
|
548
|
+
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
549
|
+
<defs>
|
|
550
|
+
<linearGradient id="${id}" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
551
|
+
<stop offset="0%" stop-color="${color}"/>
|
|
552
|
+
<stop offset="100%" stop-color="${darkenColor(color, 0.4)}"/>
|
|
553
|
+
</linearGradient>
|
|
554
|
+
</defs>
|
|
555
|
+
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
556
|
+
fill="url(#${id})" stroke="${borderColor}" stroke-width="1" rx="1"/>
|
|
557
|
+
<line x1="${size / 2}" y1="${padding}" x2="${size / 2}" y2="${size - padding}" stroke="${borderColor}" stroke-width="0.5" opacity="0.3"/>
|
|
558
|
+
<line x1="${padding}" y1="${size / 2}" x2="${size - padding}" y2="${size / 2}" stroke="${borderColor}" stroke-width="0.5" opacity="0.3"/>
|
|
559
|
+
</svg>`;
|
|
560
|
+
}
|
|
382
561
|
function createStackedLayersSymbol(size) {
|
|
383
562
|
const colors = ["#a8d4a8", "#8ec4e8", "#d4c4a8"];
|
|
384
563
|
const borderColor = "#666666";
|
|
@@ -413,6 +592,12 @@ function createLayerSymbolSVG(layerType, color, options = {}) {
|
|
|
413
592
|
return createFillExtrusionSymbol(size, fillColor);
|
|
414
593
|
case "background-group":
|
|
415
594
|
return createStackedLayersSymbol(size);
|
|
595
|
+
case "cog":
|
|
596
|
+
return createCOGSymbol(size, fillColor);
|
|
597
|
+
case "zarr":
|
|
598
|
+
return createZarrSymbol(size, fillColor);
|
|
599
|
+
case "custom-raster":
|
|
600
|
+
return createCustomRasterSymbol(size, fillColor);
|
|
416
601
|
default:
|
|
417
602
|
return createDefaultSymbol(size, fillColor);
|
|
418
603
|
}
|
|
@@ -438,6 +623,8 @@ class LayerControl {
|
|
|
438
623
|
__publicField(this, "showOpacitySlider");
|
|
439
624
|
__publicField(this, "showLayerSymbol");
|
|
440
625
|
__publicField(this, "excludeDrawnLayers");
|
|
626
|
+
__publicField(this, "customLayerRegistry", null);
|
|
627
|
+
__publicField(this, "customLayerUnsubscribe", null);
|
|
441
628
|
__publicField(this, "widthSliderEl", null);
|
|
442
629
|
__publicField(this, "widthThumbEl", null);
|
|
443
630
|
__publicField(this, "widthValueEl", null);
|
|
@@ -455,7 +642,7 @@ class LayerControl {
|
|
|
455
642
|
this.excludeDrawnLayers = options.excludeDrawnLayers !== false;
|
|
456
643
|
this.state = {
|
|
457
644
|
collapsed: options.collapsed !== false,
|
|
458
|
-
panelWidth: options.panelWidth ||
|
|
645
|
+
panelWidth: options.panelWidth || 348,
|
|
459
646
|
activeStyleEditor: null,
|
|
460
647
|
layerStates: options.layerStates || {},
|
|
461
648
|
originalStyles: /* @__PURE__ */ new Map(),
|
|
@@ -466,6 +653,12 @@ class LayerControl {
|
|
|
466
653
|
};
|
|
467
654
|
this.targetLayers = options.layers || Object.keys(this.state.layerStates);
|
|
468
655
|
this.styleEditors = /* @__PURE__ */ new Map();
|
|
656
|
+
if (options.customLayerAdapters && options.customLayerAdapters.length > 0) {
|
|
657
|
+
this.customLayerRegistry = new CustomLayerRegistry();
|
|
658
|
+
options.customLayerAdapters.forEach((adapter) => {
|
|
659
|
+
this.customLayerRegistry.register(adapter);
|
|
660
|
+
});
|
|
661
|
+
}
|
|
469
662
|
}
|
|
470
663
|
/**
|
|
471
664
|
* Called when the control is added to the map
|
|
@@ -490,6 +683,14 @@ class LayerControl {
|
|
|
490
683
|
*/
|
|
491
684
|
onRemove() {
|
|
492
685
|
var _a;
|
|
686
|
+
if (this.customLayerUnsubscribe) {
|
|
687
|
+
this.customLayerUnsubscribe();
|
|
688
|
+
this.customLayerUnsubscribe = null;
|
|
689
|
+
}
|
|
690
|
+
if (this.customLayerRegistry) {
|
|
691
|
+
this.customLayerRegistry.destroy();
|
|
692
|
+
this.customLayerRegistry = null;
|
|
693
|
+
}
|
|
493
694
|
(_a = this.container.parentNode) == null ? void 0 : _a.removeChild(this.container);
|
|
494
695
|
}
|
|
495
696
|
/**
|
|
@@ -572,6 +773,22 @@ class LayerControl {
|
|
|
572
773
|
};
|
|
573
774
|
});
|
|
574
775
|
}
|
|
776
|
+
if (this.customLayerRegistry) {
|
|
777
|
+
const customLayerIds = this.customLayerRegistry.getAllLayerIds();
|
|
778
|
+
customLayerIds.forEach((layerId) => {
|
|
779
|
+
if (this.state.layerStates[layerId]) return;
|
|
780
|
+
const customState = this.customLayerRegistry.getLayerState(layerId);
|
|
781
|
+
if (customState) {
|
|
782
|
+
this.state.layerStates[layerId] = {
|
|
783
|
+
visible: customState.visible,
|
|
784
|
+
opacity: customState.opacity,
|
|
785
|
+
name: customState.name,
|
|
786
|
+
isCustomLayer: true,
|
|
787
|
+
customLayerType: this.customLayerRegistry.getSymbolType(layerId) || void 0
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
}
|
|
575
792
|
this.targetLayers = Object.keys(this.state.layerStates);
|
|
576
793
|
}
|
|
577
794
|
/**
|
|
@@ -644,8 +861,8 @@ class LayerControl {
|
|
|
644
861
|
*/
|
|
645
862
|
isDrawnLayer(layerId) {
|
|
646
863
|
const drawnLayerPatterns = [
|
|
647
|
-
/^gm[-_]/i,
|
|
648
|
-
// Geoman (gm-main-*, gm_
|
|
864
|
+
/^gm[-_\s]/i,
|
|
865
|
+
// Geoman (gm-main-*, gm_*, Gm Temporary...)
|
|
649
866
|
/^gl-draw[-_]/i,
|
|
650
867
|
// Mapbox GL Draw
|
|
651
868
|
/^mapbox-gl-draw[-_]/i,
|
|
@@ -725,12 +942,7 @@ class LayerControl {
|
|
|
725
942
|
*/
|
|
726
943
|
setAllLayersVisibility(visible) {
|
|
727
944
|
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
728
|
-
|
|
729
|
-
this.toggleBackgroundVisibility(visible);
|
|
730
|
-
} else {
|
|
731
|
-
this.state.layerStates[layerId].visible = visible;
|
|
732
|
-
this.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
|
|
733
|
-
}
|
|
945
|
+
this.toggleLayerVisibility(layerId, visible);
|
|
734
946
|
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
735
947
|
if (itemEl) {
|
|
736
948
|
const checkbox = itemEl.querySelector(".layer-control-checkbox");
|
|
@@ -965,6 +1177,11 @@ class LayerControl {
|
|
|
965
1177
|
}, 150);
|
|
966
1178
|
}
|
|
967
1179
|
});
|
|
1180
|
+
if (this.customLayerRegistry) {
|
|
1181
|
+
this.customLayerUnsubscribe = this.customLayerRegistry.onChange(() => {
|
|
1182
|
+
setTimeout(() => this.checkForNewLayers(), 100);
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
968
1185
|
}
|
|
969
1186
|
/**
|
|
970
1187
|
* Toggle panel expanded/collapsed state
|
|
@@ -1077,6 +1294,17 @@ class LayerControl {
|
|
|
1077
1294
|
* @returns The symbol HTML element, or null if layer not found
|
|
1078
1295
|
*/
|
|
1079
1296
|
createLayerSymbol(layerId) {
|
|
1297
|
+
const layerState = this.state.layerStates[layerId];
|
|
1298
|
+
if (layerState == null ? void 0 : layerState.isCustomLayer) {
|
|
1299
|
+
const symbolType = layerState.customLayerType || "custom-raster";
|
|
1300
|
+
const color2 = "#4a90d9";
|
|
1301
|
+
const svgMarkup2 = createLayerSymbolSVG(symbolType, color2);
|
|
1302
|
+
const symbolContainer2 = document.createElement("span");
|
|
1303
|
+
symbolContainer2.className = "layer-control-symbol";
|
|
1304
|
+
symbolContainer2.innerHTML = svgMarkup2;
|
|
1305
|
+
symbolContainer2.title = `Layer type: ${symbolType}`;
|
|
1306
|
+
return symbolContainer2;
|
|
1307
|
+
}
|
|
1080
1308
|
const layer = this.map.getLayer(layerId);
|
|
1081
1309
|
if (!layer) return null;
|
|
1082
1310
|
const layerType = layer.type;
|
|
@@ -1119,6 +1347,7 @@ class LayerControl {
|
|
|
1119
1347
|
* Toggle layer visibility
|
|
1120
1348
|
*/
|
|
1121
1349
|
toggleLayerVisibility(layerId, visible) {
|
|
1350
|
+
var _a;
|
|
1122
1351
|
if (layerId === "Background") {
|
|
1123
1352
|
this.toggleBackgroundVisibility(visible);
|
|
1124
1353
|
return;
|
|
@@ -1126,12 +1355,16 @@ class LayerControl {
|
|
|
1126
1355
|
if (this.state.layerStates[layerId]) {
|
|
1127
1356
|
this.state.layerStates[layerId].visible = visible;
|
|
1128
1357
|
}
|
|
1358
|
+
if ((_a = this.customLayerRegistry) == null ? void 0 : _a.setVisibility(layerId, visible)) {
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1129
1361
|
this.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
|
|
1130
1362
|
}
|
|
1131
1363
|
/**
|
|
1132
1364
|
* Change layer opacity
|
|
1133
1365
|
*/
|
|
1134
1366
|
changeLayerOpacity(layerId, opacity) {
|
|
1367
|
+
var _a;
|
|
1135
1368
|
if (layerId === "Background") {
|
|
1136
1369
|
this.changeBackgroundOpacity(opacity);
|
|
1137
1370
|
return;
|
|
@@ -1139,6 +1372,9 @@ class LayerControl {
|
|
|
1139
1372
|
if (this.state.layerStates[layerId]) {
|
|
1140
1373
|
this.state.layerStates[layerId].opacity = opacity;
|
|
1141
1374
|
}
|
|
1375
|
+
if ((_a = this.customLayerRegistry) == null ? void 0 : _a.setOpacity(layerId, opacity)) {
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1142
1378
|
const layerType = getLayerType(this.map, layerId);
|
|
1143
1379
|
if (layerType) {
|
|
1144
1380
|
setLayerOpacity(this.map, layerId, layerType, opacity);
|
|
@@ -1355,6 +1591,9 @@ class LayerControl {
|
|
|
1355
1591
|
const styleLayers = this.map.getStyle().layers || [];
|
|
1356
1592
|
styleLayers.forEach((layer) => {
|
|
1357
1593
|
if (!this.isUserAddedLayer(layer.id)) {
|
|
1594
|
+
if (this.excludeDrawnLayers && this.isDrawnLayer(layer.id)) {
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1358
1597
|
if (this.state.onlyRenderedFilter && !this.isLayerRendered(layer.id)) {
|
|
1359
1598
|
return;
|
|
1360
1599
|
}
|
|
@@ -1458,11 +1697,18 @@ class LayerControl {
|
|
|
1458
1697
|
if (layerId === "Background") {
|
|
1459
1698
|
return null;
|
|
1460
1699
|
}
|
|
1700
|
+
const layerState = this.state.layerStates[layerId];
|
|
1701
|
+
const isCustomLayer = (layerState == null ? void 0 : layerState.isCustomLayer) === true;
|
|
1461
1702
|
const button = document.createElement("button");
|
|
1462
1703
|
button.className = "layer-control-style-button";
|
|
1463
1704
|
button.innerHTML = "⚙";
|
|
1464
|
-
|
|
1465
|
-
|
|
1705
|
+
if (isCustomLayer) {
|
|
1706
|
+
button.title = "Layer info (style editing not available)";
|
|
1707
|
+
button.setAttribute("aria-label", `Layer info for ${layerId}`);
|
|
1708
|
+
} else {
|
|
1709
|
+
button.title = "Edit layer style";
|
|
1710
|
+
button.setAttribute("aria-label", `Edit style for ${layerId}`);
|
|
1711
|
+
}
|
|
1466
1712
|
button.addEventListener("click", (e) => {
|
|
1467
1713
|
e.stopPropagation();
|
|
1468
1714
|
this.toggleStyleEditor(layerId);
|
|
@@ -1488,6 +1734,17 @@ class LayerControl {
|
|
|
1488
1734
|
openStyleEditor(layerId) {
|
|
1489
1735
|
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
1490
1736
|
if (!itemEl) return;
|
|
1737
|
+
const layerState = this.state.layerStates[layerId];
|
|
1738
|
+
if (layerState == null ? void 0 : layerState.isCustomLayer) {
|
|
1739
|
+
const editor2 = this.createCustomLayerInfoPanel(layerId, layerState.customLayerType);
|
|
1740
|
+
itemEl.appendChild(editor2);
|
|
1741
|
+
this.styleEditors.set(layerId, editor2);
|
|
1742
|
+
this.state.activeStyleEditor = layerId;
|
|
1743
|
+
setTimeout(() => {
|
|
1744
|
+
editor2.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
1745
|
+
}, 50);
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1491
1748
|
if (!this.state.originalStyles.has(layerId)) {
|
|
1492
1749
|
const layer = this.map.getLayer(layerId);
|
|
1493
1750
|
if (layer) {
|
|
@@ -1503,6 +1760,49 @@ class LayerControl {
|
|
|
1503
1760
|
editor.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
1504
1761
|
}, 50);
|
|
1505
1762
|
}
|
|
1763
|
+
/**
|
|
1764
|
+
* Create info panel for custom layers (style editing not supported)
|
|
1765
|
+
*/
|
|
1766
|
+
createCustomLayerInfoPanel(layerId, layerType) {
|
|
1767
|
+
const editor = document.createElement("div");
|
|
1768
|
+
editor.className = "layer-control-style-editor layer-control-custom-info";
|
|
1769
|
+
const header = document.createElement("div");
|
|
1770
|
+
header.className = "style-editor-header";
|
|
1771
|
+
const title = document.createElement("span");
|
|
1772
|
+
title.className = "style-editor-title";
|
|
1773
|
+
title.textContent = "Layer Info";
|
|
1774
|
+
const closeBtn = document.createElement("button");
|
|
1775
|
+
closeBtn.className = "style-editor-close";
|
|
1776
|
+
closeBtn.innerHTML = "×";
|
|
1777
|
+
closeBtn.title = "Close";
|
|
1778
|
+
closeBtn.addEventListener("click", (e) => {
|
|
1779
|
+
e.stopPropagation();
|
|
1780
|
+
this.closeStyleEditor(layerId);
|
|
1781
|
+
});
|
|
1782
|
+
header.appendChild(title);
|
|
1783
|
+
header.appendChild(closeBtn);
|
|
1784
|
+
const content = document.createElement("div");
|
|
1785
|
+
content.className = "style-editor-controls";
|
|
1786
|
+
const infoText = document.createElement("p");
|
|
1787
|
+
infoText.className = "layer-control-custom-info-text";
|
|
1788
|
+
const typeLabel = layerType ? layerType.toUpperCase() : "Custom";
|
|
1789
|
+
infoText.textContent = `This is a ${typeLabel} layer. Style editing is not available for this layer type. Use the visibility toggle and opacity slider to control the layer.`;
|
|
1790
|
+
content.appendChild(infoText);
|
|
1791
|
+
const actions = document.createElement("div");
|
|
1792
|
+
actions.className = "style-editor-actions";
|
|
1793
|
+
const closeActionBtn = document.createElement("button");
|
|
1794
|
+
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
1795
|
+
closeActionBtn.textContent = "Close";
|
|
1796
|
+
closeActionBtn.addEventListener("click", (e) => {
|
|
1797
|
+
e.stopPropagation();
|
|
1798
|
+
this.closeStyleEditor(layerId);
|
|
1799
|
+
});
|
|
1800
|
+
actions.appendChild(closeActionBtn);
|
|
1801
|
+
editor.appendChild(header);
|
|
1802
|
+
editor.appendChild(content);
|
|
1803
|
+
editor.appendChild(actions);
|
|
1804
|
+
return editor;
|
|
1805
|
+
}
|
|
1506
1806
|
/**
|
|
1507
1807
|
* Close style editor for a layer
|
|
1508
1808
|
*/
|
|
@@ -1820,7 +2120,14 @@ class LayerControl {
|
|
|
1820
2120
|
return;
|
|
1821
2121
|
}
|
|
1822
2122
|
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
2123
|
+
var _a;
|
|
1823
2124
|
try {
|
|
2125
|
+
if ((_a = this.state.layerStates[layerId]) == null ? void 0 : _a.isCustomLayer) {
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
if (layerId === "Background") {
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
1824
2131
|
const layer = this.map.getLayer(layerId);
|
|
1825
2132
|
if (!layer) return;
|
|
1826
2133
|
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
@@ -1888,7 +2195,8 @@ class LayerControl {
|
|
|
1888
2195
|
});
|
|
1889
2196
|
const removedLayers = [];
|
|
1890
2197
|
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
1891
|
-
|
|
2198
|
+
const state = this.state.layerStates[layerId];
|
|
2199
|
+
if (layerId !== "Background" && !state.isCustomLayer && !currentMapLayerIds.has(layerId)) {
|
|
1892
2200
|
removedLayers.push(layerId);
|
|
1893
2201
|
}
|
|
1894
2202
|
});
|
|
@@ -1921,11 +2229,44 @@ class LayerControl {
|
|
|
1921
2229
|
this.addLayerItem(layerId, this.state.layerStates[layerId]);
|
|
1922
2230
|
});
|
|
1923
2231
|
}
|
|
2232
|
+
if (this.customLayerRegistry) {
|
|
2233
|
+
const customLayerIds = this.customLayerRegistry.getAllLayerIds();
|
|
2234
|
+
customLayerIds.forEach((layerId) => {
|
|
2235
|
+
if (!this.state.layerStates[layerId]) {
|
|
2236
|
+
const customState = this.customLayerRegistry.getLayerState(layerId);
|
|
2237
|
+
if (customState) {
|
|
2238
|
+
this.state.layerStates[layerId] = {
|
|
2239
|
+
visible: customState.visible,
|
|
2240
|
+
opacity: customState.opacity,
|
|
2241
|
+
name: customState.name,
|
|
2242
|
+
isCustomLayer: true,
|
|
2243
|
+
customLayerType: this.customLayerRegistry.getSymbolType(layerId) || void 0
|
|
2244
|
+
};
|
|
2245
|
+
this.addLayerItem(layerId, this.state.layerStates[layerId]);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
});
|
|
2249
|
+
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
2250
|
+
const state = this.state.layerStates[layerId];
|
|
2251
|
+
if (state.isCustomLayer && !customLayerIds.includes(layerId)) {
|
|
2252
|
+
delete this.state.layerStates[layerId];
|
|
2253
|
+
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
2254
|
+
if (itemEl) {
|
|
2255
|
+
itemEl.remove();
|
|
2256
|
+
}
|
|
2257
|
+
if (this.state.activeStyleEditor === layerId) {
|
|
2258
|
+
this.state.activeStyleEditor = null;
|
|
2259
|
+
}
|
|
2260
|
+
this.styleEditors.delete(layerId);
|
|
2261
|
+
}
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
1924
2264
|
} catch (error) {
|
|
1925
2265
|
console.warn("Failed to check for new layers:", error);
|
|
1926
2266
|
}
|
|
1927
2267
|
}
|
|
1928
2268
|
}
|
|
2269
|
+
exports.CustomLayerRegistry = CustomLayerRegistry;
|
|
1929
2270
|
exports.LayerControl = LayerControl;
|
|
1930
2271
|
exports.clamp = clamp;
|
|
1931
2272
|
exports.createBackgroundGroupSymbolSVG = createBackgroundGroupSymbolSVG;
|