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