maplibre-gl-layer-control 0.12.0 → 0.14.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 +206 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +206 -7
- package/dist/index.mjs.map +1 -1
- package/dist/maplibre-gl-layer-control.css +88 -0
- package/dist/types/index.d.ts +28 -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
|
|
@@ -686,6 +698,7 @@ class LayerControl {
|
|
|
686
698
|
__publicField(this, "customLayerRegistry", null);
|
|
687
699
|
__publicField(this, "customLayerUnsubscribe", null);
|
|
688
700
|
__publicField(this, "removedCustomLayerIds", /* @__PURE__ */ new Set());
|
|
701
|
+
__publicField(this, "nativeLayerGroups", /* @__PURE__ */ new Map());
|
|
689
702
|
__publicField(this, "basemapStyleUrl", null);
|
|
690
703
|
__publicField(this, "basemapLayerIds", null);
|
|
691
704
|
__publicField(this, "widthSliderEl", null);
|
|
@@ -1083,6 +1096,7 @@ class LayerControl {
|
|
|
1083
1096
|
*/
|
|
1084
1097
|
isDrawnLayer(layerId) {
|
|
1085
1098
|
const drawnLayerPatterns = [
|
|
1099
|
+
// Drawing libraries
|
|
1086
1100
|
/^gm[-_\s]/i,
|
|
1087
1101
|
// Geoman (gm-main-*, gm_*, Gm Temporary...)
|
|
1088
1102
|
/^gl-draw[-_]/i,
|
|
@@ -1093,8 +1107,15 @@ class LayerControl {
|
|
|
1093
1107
|
// Terra Draw
|
|
1094
1108
|
/^maplibre-gl-draw[-_]/i,
|
|
1095
1109
|
// MapLibre GL Draw
|
|
1096
|
-
/^draw[-_]layer/i
|
|
1110
|
+
/^draw[-_]layer/i,
|
|
1097
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
|
|
1098
1119
|
];
|
|
1099
1120
|
return drawnLayerPatterns.some((pattern) => pattern.test(layerId));
|
|
1100
1121
|
}
|
|
@@ -2094,10 +2115,32 @@ class LayerControl {
|
|
|
2094
2115
|
* Open style editor for a layer
|
|
2095
2116
|
*/
|
|
2096
2117
|
openStyleEditor(layerId) {
|
|
2118
|
+
var _a;
|
|
2097
2119
|
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
2098
2120
|
if (!itemEl) return;
|
|
2099
2121
|
const layerState = this.state.layerStates[layerId];
|
|
2100
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
|
+
}
|
|
2101
2144
|
const editor2 = this.createCustomLayerInfoPanel(layerId);
|
|
2102
2145
|
itemEl.appendChild(editor2);
|
|
2103
2146
|
this.styleEditors.set(layerId, editor2);
|
|
@@ -2157,10 +2200,10 @@ class LayerControl {
|
|
|
2157
2200
|
removeBtn.title = "Remove layer from map";
|
|
2158
2201
|
removeBtn.addEventListener("click", (e) => {
|
|
2159
2202
|
e.stopPropagation();
|
|
2160
|
-
|
|
2203
|
+
this.showRemoveConfirmation(editor, () => {
|
|
2161
2204
|
this.closeStyleEditor(layerId);
|
|
2162
2205
|
this.removeLayer(layerId);
|
|
2163
|
-
}
|
|
2206
|
+
});
|
|
2164
2207
|
});
|
|
2165
2208
|
const closeActionBtn = document.createElement("button");
|
|
2166
2209
|
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
@@ -2176,6 +2219,106 @@ class LayerControl {
|
|
|
2176
2219
|
editor.appendChild(actions);
|
|
2177
2220
|
return editor;
|
|
2178
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
|
+
this.showRemoveConfirmation(editor, () => {
|
|
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
|
+
}
|
|
2179
2322
|
/**
|
|
2180
2323
|
* Close style editor for a layer
|
|
2181
2324
|
*/
|
|
@@ -2185,6 +2328,7 @@ class LayerControl {
|
|
|
2185
2328
|
editor.remove();
|
|
2186
2329
|
this.styleEditors.delete(layerId);
|
|
2187
2330
|
}
|
|
2331
|
+
this.nativeLayerGroups.clear();
|
|
2188
2332
|
if (this.state.activeStyleEditor === layerId) {
|
|
2189
2333
|
this.state.activeStyleEditor = null;
|
|
2190
2334
|
}
|
|
@@ -2231,10 +2375,10 @@ class LayerControl {
|
|
|
2231
2375
|
removeBtn.title = "Remove layer from map";
|
|
2232
2376
|
removeBtn.addEventListener("click", (e) => {
|
|
2233
2377
|
e.stopPropagation();
|
|
2234
|
-
|
|
2378
|
+
this.showRemoveConfirmation(editor, () => {
|
|
2235
2379
|
this.closeStyleEditor(layerId);
|
|
2236
2380
|
this.removeLayer(layerId);
|
|
2237
|
-
}
|
|
2381
|
+
});
|
|
2238
2382
|
});
|
|
2239
2383
|
const closeActionBtn = document.createElement("button");
|
|
2240
2384
|
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
@@ -2413,7 +2557,10 @@ class LayerControl {
|
|
|
2413
2557
|
colorInput.addEventListener("input", () => {
|
|
2414
2558
|
const color = colorInput.value;
|
|
2415
2559
|
hexDisplay.value = color;
|
|
2416
|
-
this.
|
|
2560
|
+
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
2561
|
+
for (const id of targetIds) {
|
|
2562
|
+
this.map.setPaintProperty(id, property, color);
|
|
2563
|
+
}
|
|
2417
2564
|
});
|
|
2418
2565
|
inputWrapper.appendChild(colorInput);
|
|
2419
2566
|
inputWrapper.appendChild(hexDisplay);
|
|
@@ -2446,7 +2593,10 @@ class LayerControl {
|
|
|
2446
2593
|
slider.addEventListener("input", () => {
|
|
2447
2594
|
const value = parseFloat(slider.value);
|
|
2448
2595
|
valueDisplay.textContent = formatNumericValue(value, step);
|
|
2449
|
-
this.
|
|
2596
|
+
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
2597
|
+
for (const id of targetIds) {
|
|
2598
|
+
this.map.setPaintProperty(id, property, value);
|
|
2599
|
+
}
|
|
2450
2600
|
});
|
|
2451
2601
|
inputWrapper.appendChild(slider);
|
|
2452
2602
|
inputWrapper.appendChild(valueDisplay);
|
|
@@ -3097,11 +3247,57 @@ class LayerControl {
|
|
|
3097
3247
|
this.buildLayerItems();
|
|
3098
3248
|
(_b = this.onLayerReorder) == null ? void 0 : _b.call(this, this.getUserLayerIdsInMapOrder());
|
|
3099
3249
|
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Show inline remove confirmation instead of browser confirm() dialog.
|
|
3252
|
+
* Works in Jupyter notebooks where native dialogs may not appear.
|
|
3253
|
+
*/
|
|
3254
|
+
showRemoveConfirmation(container, onConfirm) {
|
|
3255
|
+
const existing = container.querySelector(".layer-control-remove-confirm");
|
|
3256
|
+
if (existing) {
|
|
3257
|
+
existing.remove();
|
|
3258
|
+
}
|
|
3259
|
+
const confirmEl = document.createElement("div");
|
|
3260
|
+
confirmEl.className = "layer-control-remove-confirm";
|
|
3261
|
+
const message = document.createElement("div");
|
|
3262
|
+
message.className = "layer-control-remove-confirm-message";
|
|
3263
|
+
message.innerHTML = `
|
|
3264
|
+
<svg class="layer-control-remove-confirm-icon" viewBox="0 0 20 20" fill="currentColor">
|
|
3265
|
+
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/>
|
|
3266
|
+
</svg>
|
|
3267
|
+
<span>Remove this layer?</span>
|
|
3268
|
+
`;
|
|
3269
|
+
const buttons = document.createElement("div");
|
|
3270
|
+
buttons.className = "layer-control-remove-confirm-buttons";
|
|
3271
|
+
const cancelBtn = document.createElement("button");
|
|
3272
|
+
cancelBtn.className = "layer-control-remove-confirm-btn layer-control-remove-confirm-btn-cancel";
|
|
3273
|
+
cancelBtn.textContent = "Cancel";
|
|
3274
|
+
cancelBtn.addEventListener("click", (e) => {
|
|
3275
|
+
e.stopPropagation();
|
|
3276
|
+
confirmEl.remove();
|
|
3277
|
+
});
|
|
3278
|
+
const confirmBtn = document.createElement("button");
|
|
3279
|
+
confirmBtn.className = "layer-control-remove-confirm-btn layer-control-remove-confirm-btn-confirm";
|
|
3280
|
+
confirmBtn.textContent = "Remove";
|
|
3281
|
+
confirmBtn.addEventListener("click", (e) => {
|
|
3282
|
+
e.stopPropagation();
|
|
3283
|
+
confirmEl.remove();
|
|
3284
|
+
onConfirm();
|
|
3285
|
+
});
|
|
3286
|
+
buttons.appendChild(cancelBtn);
|
|
3287
|
+
buttons.appendChild(confirmBtn);
|
|
3288
|
+
confirmEl.appendChild(message);
|
|
3289
|
+
confirmEl.appendChild(buttons);
|
|
3290
|
+
container.appendChild(confirmEl);
|
|
3291
|
+
requestAnimationFrame(() => {
|
|
3292
|
+
confirmEl.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
3293
|
+
});
|
|
3294
|
+
}
|
|
3100
3295
|
/**
|
|
3101
3296
|
* Remove a layer from the map
|
|
3102
3297
|
*/
|
|
3103
3298
|
removeLayer(layerId) {
|
|
3104
3299
|
var _a, _b;
|
|
3300
|
+
this.state.isStyleOperationInProgress = true;
|
|
3105
3301
|
const layerState = this.state.layerStates[layerId];
|
|
3106
3302
|
if ((layerState == null ? void 0 : layerState.isCustomLayer) && this.customLayerRegistry) {
|
|
3107
3303
|
this.removedCustomLayerIds.add(layerId);
|
|
@@ -3134,6 +3330,9 @@ class LayerControl {
|
|
|
3134
3330
|
itemEl.remove();
|
|
3135
3331
|
}
|
|
3136
3332
|
(_b = this.onLayerRemove) == null ? void 0 : _b.call(this, layerId);
|
|
3333
|
+
setTimeout(() => {
|
|
3334
|
+
this.state.isStyleOperationInProgress = false;
|
|
3335
|
+
}, 200);
|
|
3137
3336
|
}
|
|
3138
3337
|
// ===== Drag and Drop Methods =====
|
|
3139
3338
|
/**
|