maplibre-gl-layer-control 0.11.0 → 0.13.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 +196 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +196 -22
- package/dist/index.mjs.map +1 -1
- package/dist/maplibre-gl-layer-control.css +13 -0
- package/dist/types/index.d.ts +24 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -132,6 +132,18 @@ class CustomLayerRegistry {
|
|
|
132
132
|
}
|
|
133
133
|
return null;
|
|
134
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Get native MapLibre layer IDs for a custom layer.
|
|
137
|
+
* @param layerId The custom layer ID
|
|
138
|
+
* @returns Array of native layer IDs, or null if not available
|
|
139
|
+
*/
|
|
140
|
+
getNativeLayerIds(layerId) {
|
|
141
|
+
const adapter = this.getAdapterForLayer(layerId);
|
|
142
|
+
if (adapter && adapter.getNativeLayerIds) {
|
|
143
|
+
return adapter.getNativeLayerIds(layerId);
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
135
147
|
/**
|
|
136
148
|
* Remove a custom layer through its adapter.
|
|
137
149
|
* @param layerId The layer ID to remove
|
|
@@ -685,6 +697,8 @@ class LayerControl {
|
|
|
685
697
|
__publicField(this, "excludeLayerPatterns");
|
|
686
698
|
__publicField(this, "customLayerRegistry", null);
|
|
687
699
|
__publicField(this, "customLayerUnsubscribe", null);
|
|
700
|
+
__publicField(this, "removedCustomLayerIds", /* @__PURE__ */ new Set());
|
|
701
|
+
__publicField(this, "nativeLayerGroups", /* @__PURE__ */ new Map());
|
|
688
702
|
__publicField(this, "basemapStyleUrl", null);
|
|
689
703
|
__publicField(this, "basemapLayerIds", null);
|
|
690
704
|
__publicField(this, "widthSliderEl", null);
|
|
@@ -1082,6 +1096,7 @@ class LayerControl {
|
|
|
1082
1096
|
*/
|
|
1083
1097
|
isDrawnLayer(layerId) {
|
|
1084
1098
|
const drawnLayerPatterns = [
|
|
1099
|
+
// Drawing libraries
|
|
1085
1100
|
/^gm[-_\s]/i,
|
|
1086
1101
|
// Geoman (gm-main-*, gm_*, Gm Temporary...)
|
|
1087
1102
|
/^gl-draw[-_]/i,
|
|
@@ -1092,8 +1107,15 @@ class LayerControl {
|
|
|
1092
1107
|
// Terra Draw
|
|
1093
1108
|
/^maplibre-gl-draw[-_]/i,
|
|
1094
1109
|
// MapLibre GL Draw
|
|
1095
|
-
/^draw[-_]layer/i
|
|
1110
|
+
/^draw[-_]layer/i,
|
|
1096
1111
|
// Generic draw layers
|
|
1112
|
+
// maplibre-gl-components internal layers
|
|
1113
|
+
/^measure-/i,
|
|
1114
|
+
// MeasureControl (measure-{id}-fill, measure-{id}-line)
|
|
1115
|
+
/^pmtiles-source-/i,
|
|
1116
|
+
// PMTilesLayerControl (managed via adapter)
|
|
1117
|
+
/^stac-search-footprints/i
|
|
1118
|
+
// StacSearchControl footprint layers
|
|
1097
1119
|
];
|
|
1098
1120
|
return drawnLayerPatterns.some((pattern) => pattern.test(layerId));
|
|
1099
1121
|
}
|
|
@@ -1483,7 +1505,10 @@ class LayerControl {
|
|
|
1483
1505
|
}
|
|
1484
1506
|
});
|
|
1485
1507
|
if (this.customLayerRegistry) {
|
|
1486
|
-
this.customLayerUnsubscribe = this.customLayerRegistry.onChange(() => {
|
|
1508
|
+
this.customLayerUnsubscribe = this.customLayerRegistry.onChange((event, layerId) => {
|
|
1509
|
+
if (event === "add" && layerId) {
|
|
1510
|
+
this.removedCustomLayerIds.delete(layerId);
|
|
1511
|
+
}
|
|
1487
1512
|
setTimeout(() => this.checkForNewLayers(), 100);
|
|
1488
1513
|
});
|
|
1489
1514
|
}
|
|
@@ -2090,10 +2115,32 @@ class LayerControl {
|
|
|
2090
2115
|
* Open style editor for a layer
|
|
2091
2116
|
*/
|
|
2092
2117
|
openStyleEditor(layerId) {
|
|
2118
|
+
var _a;
|
|
2093
2119
|
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
2094
2120
|
if (!itemEl) return;
|
|
2095
2121
|
const layerState = this.state.layerStates[layerId];
|
|
2096
2122
|
if (layerState == null ? void 0 : layerState.isCustomLayer) {
|
|
2123
|
+
const nativeLayerIds = (_a = this.customLayerRegistry) == null ? void 0 : _a.getNativeLayerIds(layerId);
|
|
2124
|
+
if (nativeLayerIds && nativeLayerIds.length > 0) {
|
|
2125
|
+
for (const nativeId of nativeLayerIds) {
|
|
2126
|
+
if (!this.state.originalStyles.has(nativeId)) {
|
|
2127
|
+
const nativeLayer = this.map.getLayer(nativeId);
|
|
2128
|
+
if (nativeLayer) {
|
|
2129
|
+
cacheOriginalLayerStyle(this.map, nativeId, this.state.originalStyles);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
const editor3 = this.createNativeSubLayerStyleEditor(layerId, nativeLayerIds);
|
|
2134
|
+
if (editor3) {
|
|
2135
|
+
itemEl.appendChild(editor3);
|
|
2136
|
+
this.styleEditors.set(layerId, editor3);
|
|
2137
|
+
this.state.activeStyleEditor = layerId;
|
|
2138
|
+
setTimeout(() => {
|
|
2139
|
+
editor3.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
2140
|
+
}, 50);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2097
2144
|
const editor2 = this.createCustomLayerInfoPanel(layerId);
|
|
2098
2145
|
itemEl.appendChild(editor2);
|
|
2099
2146
|
this.styleEditors.set(layerId, editor2);
|
|
@@ -2147,6 +2194,17 @@ class LayerControl {
|
|
|
2147
2194
|
content.appendChild(infoText);
|
|
2148
2195
|
const actions = document.createElement("div");
|
|
2149
2196
|
actions.className = "style-editor-actions";
|
|
2197
|
+
const removeBtn = document.createElement("button");
|
|
2198
|
+
removeBtn.className = "style-editor-button style-editor-button-remove";
|
|
2199
|
+
removeBtn.textContent = "Remove";
|
|
2200
|
+
removeBtn.title = "Remove layer from map";
|
|
2201
|
+
removeBtn.addEventListener("click", (e) => {
|
|
2202
|
+
e.stopPropagation();
|
|
2203
|
+
if (confirm("Are you sure you want to remove this layer?")) {
|
|
2204
|
+
this.closeStyleEditor(layerId);
|
|
2205
|
+
this.removeLayer(layerId);
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2150
2208
|
const closeActionBtn = document.createElement("button");
|
|
2151
2209
|
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
2152
2210
|
closeActionBtn.textContent = "Close";
|
|
@@ -2154,12 +2212,113 @@ class LayerControl {
|
|
|
2154
2212
|
e.stopPropagation();
|
|
2155
2213
|
this.closeStyleEditor(layerId);
|
|
2156
2214
|
});
|
|
2215
|
+
actions.appendChild(removeBtn);
|
|
2157
2216
|
actions.appendChild(closeActionBtn);
|
|
2158
2217
|
editor.appendChild(header);
|
|
2159
2218
|
editor.appendChild(content);
|
|
2160
2219
|
editor.appendChild(actions);
|
|
2161
2220
|
return editor;
|
|
2162
2221
|
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Create a combined style editor for custom layers with native MapLibre sublayers.
|
|
2224
|
+
* Groups controls by sublayer type (fill, line, circle, etc.).
|
|
2225
|
+
*/
|
|
2226
|
+
createNativeSubLayerStyleEditor(layerId, nativeLayerIds) {
|
|
2227
|
+
const layersByType = /* @__PURE__ */ new Map();
|
|
2228
|
+
for (const nativeId of nativeLayerIds) {
|
|
2229
|
+
const layer = this.map.getLayer(nativeId);
|
|
2230
|
+
if (layer) {
|
|
2231
|
+
const type = layer.type;
|
|
2232
|
+
if (!layersByType.has(type)) {
|
|
2233
|
+
layersByType.set(type, []);
|
|
2234
|
+
}
|
|
2235
|
+
layersByType.get(type).push(nativeId);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
if (layersByType.size === 0) return null;
|
|
2239
|
+
const editor = document.createElement("div");
|
|
2240
|
+
editor.className = "layer-control-style-editor";
|
|
2241
|
+
const header = document.createElement("div");
|
|
2242
|
+
header.className = "style-editor-header";
|
|
2243
|
+
const title = document.createElement("span");
|
|
2244
|
+
title.className = "style-editor-title";
|
|
2245
|
+
title.textContent = "Edit Style";
|
|
2246
|
+
const closeBtn = document.createElement("button");
|
|
2247
|
+
closeBtn.className = "style-editor-close";
|
|
2248
|
+
closeBtn.innerHTML = "×";
|
|
2249
|
+
closeBtn.title = "Close";
|
|
2250
|
+
closeBtn.addEventListener("click", (e) => {
|
|
2251
|
+
e.stopPropagation();
|
|
2252
|
+
this.closeStyleEditor(layerId);
|
|
2253
|
+
});
|
|
2254
|
+
header.appendChild(title);
|
|
2255
|
+
header.appendChild(closeBtn);
|
|
2256
|
+
editor.appendChild(header);
|
|
2257
|
+
const controls = document.createElement("div");
|
|
2258
|
+
controls.className = "style-editor-controls";
|
|
2259
|
+
const typeLabels = {
|
|
2260
|
+
fill: "Fill",
|
|
2261
|
+
line: "Line",
|
|
2262
|
+
circle: "Circle",
|
|
2263
|
+
symbol: "Symbol",
|
|
2264
|
+
raster: "Raster"
|
|
2265
|
+
};
|
|
2266
|
+
for (const [type, ids] of layersByType) {
|
|
2267
|
+
if (layersByType.size > 1) {
|
|
2268
|
+
const sectionHeader = document.createElement("div");
|
|
2269
|
+
sectionHeader.className = "style-editor-section-header";
|
|
2270
|
+
sectionHeader.textContent = typeLabels[type] || type;
|
|
2271
|
+
controls.appendChild(sectionHeader);
|
|
2272
|
+
}
|
|
2273
|
+
const primaryId = ids[0];
|
|
2274
|
+
this.addStyleControlsForNativeGroup(controls, ids, primaryId, type);
|
|
2275
|
+
}
|
|
2276
|
+
const actions = document.createElement("div");
|
|
2277
|
+
actions.className = "style-editor-actions";
|
|
2278
|
+
const resetBtn = document.createElement("button");
|
|
2279
|
+
resetBtn.className = "style-editor-button style-editor-button-reset";
|
|
2280
|
+
resetBtn.textContent = "Reset";
|
|
2281
|
+
resetBtn.addEventListener("click", (e) => {
|
|
2282
|
+
e.stopPropagation();
|
|
2283
|
+
for (const nativeId of nativeLayerIds) {
|
|
2284
|
+
restoreOriginalStyle(this.map, nativeId, this.state.originalStyles);
|
|
2285
|
+
}
|
|
2286
|
+
this.closeStyleEditor(layerId);
|
|
2287
|
+
this.openStyleEditor(layerId);
|
|
2288
|
+
});
|
|
2289
|
+
const removeBtn = document.createElement("button");
|
|
2290
|
+
removeBtn.className = "style-editor-button style-editor-button-remove";
|
|
2291
|
+
removeBtn.textContent = "Remove";
|
|
2292
|
+
removeBtn.title = "Remove layer from map";
|
|
2293
|
+
removeBtn.addEventListener("click", (e) => {
|
|
2294
|
+
e.stopPropagation();
|
|
2295
|
+
if (confirm("Are you sure you want to remove this layer?")) {
|
|
2296
|
+
this.closeStyleEditor(layerId);
|
|
2297
|
+
this.removeLayer(layerId);
|
|
2298
|
+
}
|
|
2299
|
+
});
|
|
2300
|
+
const closeActionBtn = document.createElement("button");
|
|
2301
|
+
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
2302
|
+
closeActionBtn.textContent = "Close";
|
|
2303
|
+
closeActionBtn.addEventListener("click", (e) => {
|
|
2304
|
+
e.stopPropagation();
|
|
2305
|
+
this.closeStyleEditor(layerId);
|
|
2306
|
+
});
|
|
2307
|
+
actions.appendChild(resetBtn);
|
|
2308
|
+
actions.appendChild(removeBtn);
|
|
2309
|
+
actions.appendChild(closeActionBtn);
|
|
2310
|
+
editor.appendChild(controls);
|
|
2311
|
+
editor.appendChild(actions);
|
|
2312
|
+
return editor;
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Add style controls for a group of native layers of the same type.
|
|
2316
|
+
* Changes to any control are applied to all layers in the group.
|
|
2317
|
+
*/
|
|
2318
|
+
addStyleControlsForNativeGroup(container, layerIds, primaryLayerId, layerType) {
|
|
2319
|
+
this.nativeLayerGroups.set(primaryLayerId, layerIds);
|
|
2320
|
+
this.addStyleControlsForLayerType(container, primaryLayerId, layerType);
|
|
2321
|
+
}
|
|
2163
2322
|
/**
|
|
2164
2323
|
* Close style editor for a layer
|
|
2165
2324
|
*/
|
|
@@ -2169,6 +2328,7 @@ class LayerControl {
|
|
|
2169
2328
|
editor.remove();
|
|
2170
2329
|
this.styleEditors.delete(layerId);
|
|
2171
2330
|
}
|
|
2331
|
+
this.nativeLayerGroups.clear();
|
|
2172
2332
|
if (this.state.activeStyleEditor === layerId) {
|
|
2173
2333
|
this.state.activeStyleEditor = null;
|
|
2174
2334
|
}
|
|
@@ -2397,7 +2557,10 @@ class LayerControl {
|
|
|
2397
2557
|
colorInput.addEventListener("input", () => {
|
|
2398
2558
|
const color = colorInput.value;
|
|
2399
2559
|
hexDisplay.value = color;
|
|
2400
|
-
this.
|
|
2560
|
+
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
2561
|
+
for (const id of targetIds) {
|
|
2562
|
+
this.map.setPaintProperty(id, property, color);
|
|
2563
|
+
}
|
|
2401
2564
|
});
|
|
2402
2565
|
inputWrapper.appendChild(colorInput);
|
|
2403
2566
|
inputWrapper.appendChild(hexDisplay);
|
|
@@ -2430,7 +2593,10 @@ class LayerControl {
|
|
|
2430
2593
|
slider.addEventListener("input", () => {
|
|
2431
2594
|
const value = parseFloat(slider.value);
|
|
2432
2595
|
valueDisplay.textContent = formatNumericValue(value, step);
|
|
2433
|
-
this.
|
|
2596
|
+
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
2597
|
+
for (const id of targetIds) {
|
|
2598
|
+
this.map.setPaintProperty(id, property, value);
|
|
2599
|
+
}
|
|
2434
2600
|
});
|
|
2435
2601
|
inputWrapper.appendChild(slider);
|
|
2436
2602
|
inputWrapper.appendChild(valueDisplay);
|
|
@@ -2629,7 +2795,7 @@ class LayerControl {
|
|
|
2629
2795
|
if (this.customLayerRegistry) {
|
|
2630
2796
|
const customLayerIds = this.customLayerRegistry.getAllLayerIds();
|
|
2631
2797
|
customLayerIds.forEach((layerId) => {
|
|
2632
|
-
if (!this.state.layerStates[layerId]) {
|
|
2798
|
+
if (!this.state.layerStates[layerId] && !this.removedCustomLayerIds.has(layerId)) {
|
|
2633
2799
|
const customState = this.customLayerRegistry.getLayerState(layerId);
|
|
2634
2800
|
if (customState) {
|
|
2635
2801
|
this.state.layerStates[layerId] = {
|
|
@@ -2670,7 +2836,10 @@ class LayerControl {
|
|
|
2670
2836
|
registerCustomAdapter(adapter) {
|
|
2671
2837
|
if (!this.customLayerRegistry) {
|
|
2672
2838
|
this.customLayerRegistry = new CustomLayerRegistry();
|
|
2673
|
-
this.customLayerUnsubscribe = this.customLayerRegistry.onChange(() => {
|
|
2839
|
+
this.customLayerUnsubscribe = this.customLayerRegistry.onChange((event, layerId) => {
|
|
2840
|
+
if (event === "add" && layerId) {
|
|
2841
|
+
this.removedCustomLayerIds.delete(layerId);
|
|
2842
|
+
}
|
|
2674
2843
|
this.checkForNewLayers();
|
|
2675
2844
|
});
|
|
2676
2845
|
}
|
|
@@ -3083,29 +3252,31 @@ class LayerControl {
|
|
|
3083
3252
|
*/
|
|
3084
3253
|
removeLayer(layerId) {
|
|
3085
3254
|
var _a, _b;
|
|
3255
|
+
this.state.isStyleOperationInProgress = true;
|
|
3086
3256
|
const layerState = this.state.layerStates[layerId];
|
|
3087
3257
|
if ((layerState == null ? void 0 : layerState.isCustomLayer) && this.customLayerRegistry) {
|
|
3258
|
+
this.removedCustomLayerIds.add(layerId);
|
|
3259
|
+
this.customLayerRegistry.setVisibility(layerId, false);
|
|
3088
3260
|
this.customLayerRegistry.removeLayer(layerId);
|
|
3089
|
-
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
}
|
|
3261
|
+
}
|
|
3262
|
+
try {
|
|
3263
|
+
const layer = this.map.getLayer(layerId);
|
|
3264
|
+
if (layer) {
|
|
3265
|
+
const sourceId = layer.source;
|
|
3266
|
+
this.map.removeLayer(layerId);
|
|
3267
|
+
if (sourceId) {
|
|
3268
|
+
const style = this.map.getStyle();
|
|
3269
|
+
const sourceStillUsed = (_a = style == null ? void 0 : style.layers) == null ? void 0 : _a.some((l) => l.source === sourceId);
|
|
3270
|
+
if (!sourceStillUsed) {
|
|
3271
|
+
try {
|
|
3272
|
+
this.map.removeSource(sourceId);
|
|
3273
|
+
} catch (e) {
|
|
3103
3274
|
}
|
|
3104
3275
|
}
|
|
3105
3276
|
}
|
|
3106
|
-
} catch (error) {
|
|
3107
|
-
console.warn(`Failed to remove layer ${layerId}:`, error);
|
|
3108
3277
|
}
|
|
3278
|
+
} catch (error) {
|
|
3279
|
+
console.warn(`Failed to remove layer ${layerId}:`, error);
|
|
3109
3280
|
}
|
|
3110
3281
|
delete this.state.layerStates[layerId];
|
|
3111
3282
|
this.state.customLayerNames.delete(layerId);
|
|
@@ -3114,6 +3285,9 @@ class LayerControl {
|
|
|
3114
3285
|
itemEl.remove();
|
|
3115
3286
|
}
|
|
3116
3287
|
(_b = this.onLayerRemove) == null ? void 0 : _b.call(this, layerId);
|
|
3288
|
+
setTimeout(() => {
|
|
3289
|
+
this.state.isStyleOperationInProgress = false;
|
|
3290
|
+
}, 200);
|
|
3117
3291
|
}
|
|
3118
3292
|
// ===== Drag and Drop Methods =====
|
|
3119
3293
|
/**
|