maplibre-gl-geoagent 0.2.0 → 0.3.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/{GeoAgentControl-C-3MIQTc.js → GeoAgentControl-DOAYVbPg.js} +5 -3575
- package/dist/GeoAgentControl-DOAYVbPg.js.map +1 -0
- package/dist/{GeoAgentControl-CKY24iWC.cjs → GeoAgentControl-DzBY1NXW.cjs} +5 -3575
- package/dist/GeoAgentControl-DzBY1NXW.cjs.map +1 -0
- package/dist/{anthropic-M2EJ1iaX.cjs → anthropic-C31X7JK8.cjs} +2 -2
- package/dist/{anthropic-M2EJ1iaX.cjs.map → anthropic-C31X7JK8.cjs.map} +1 -1
- package/dist/{anthropic-38gbSx-8.js → anthropic-DhbSHleV.js} +2 -2
- package/dist/{anthropic-38gbSx-8.js.map → anthropic-DhbSHleV.js.map} +1 -1
- package/dist/{index-BUTngzVS.cjs → index-1fng-HVi.cjs} +2 -2
- package/dist/{index-BUTngzVS.cjs.map → index-1fng-HVi.cjs.map} +1 -1
- package/dist/{index-DW6rmZdc.js → index-BU4LZEvR.js} +2 -2
- package/dist/{index-DW6rmZdc.js.map → index-BU4LZEvR.js.map} +1 -1
- package/dist/{index-DI9BALDH.js → index-Bbu2vTKz.js} +2 -2
- package/dist/{index-DI9BALDH.js.map → index-Bbu2vTKz.js.map} +1 -1
- package/dist/{index-Bc5JtMfe.cjs → index-C0CcPtSz.cjs} +2 -2
- package/dist/{index-Bc5JtMfe.cjs.map → index-C0CcPtSz.cjs.map} +1 -1
- package/dist/{index-DtsWabeI.js → index-DXB0TYg3.js} +2 -2
- package/dist/{index-DtsWabeI.js.map → index-DXB0TYg3.js.map} +1 -1
- package/dist/{index-3mfmhCHC.cjs → index-DrL1mot0.cjs} +2 -2
- package/dist/{index-3mfmhCHC.cjs.map → index-DrL1mot0.cjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/maplibre-gl-geoagent.css +0 -1195
- package/dist/react.cjs +1 -1
- package/dist/react.mjs +1 -1
- package/dist/types/lib/core/GeoAgentControl.d.ts.map +1 -1
- package/dist/types/lib/core/maplibre-tools.d.ts +0 -5
- package/dist/types/lib/core/maplibre-tools.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/GeoAgentControl-C-3MIQTc.js.map +0 -1
- package/dist/GeoAgentControl-CKY24iWC.cjs.map +0 -1
|
@@ -3518,7 +3518,7 @@ class HttpProtocol extends SerdeContext {
|
|
|
3518
3518
|
});
|
|
3519
3519
|
}
|
|
3520
3520
|
async loadEventStreamCapability() {
|
|
3521
|
-
const { EventStreamSerde } = await import("./index-
|
|
3521
|
+
const { EventStreamSerde } = await import("./index-Bbu2vTKz.js");
|
|
3522
3522
|
return new EventStreamSerde({
|
|
3523
3523
|
marshaller: this.getEventStreamMarshaller(),
|
|
3524
3524
|
serializer: this.serializer,
|
|
@@ -42205,3530 +42205,6 @@ g.walkTokens;
|
|
|
42205
42205
|
g.parseInline;
|
|
42206
42206
|
b.parse;
|
|
42207
42207
|
x.lex;
|
|
42208
|
-
var __defProp2 = Object.defineProperty;
|
|
42209
|
-
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
42210
|
-
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
42211
|
-
class CustomLayerRegistry {
|
|
42212
|
-
constructor() {
|
|
42213
|
-
__publicField2(this, "adapters", /* @__PURE__ */ new Map());
|
|
42214
|
-
__publicField2(this, "changeListeners", []);
|
|
42215
|
-
__publicField2(this, "unsubscribers", /* @__PURE__ */ new Map());
|
|
42216
|
-
}
|
|
42217
|
-
/**
|
|
42218
|
-
* Register a custom layer adapter.
|
|
42219
|
-
* @param adapter The adapter to register
|
|
42220
|
-
*/
|
|
42221
|
-
register(adapter) {
|
|
42222
|
-
this.adapters.set(adapter.type, adapter);
|
|
42223
|
-
if (adapter.onLayerChange) {
|
|
42224
|
-
const unsubscribe = adapter.onLayerChange((event, layerId) => {
|
|
42225
|
-
this.notifyChange(event, layerId);
|
|
42226
|
-
});
|
|
42227
|
-
this.unsubscribers.set(adapter.type, unsubscribe);
|
|
42228
|
-
}
|
|
42229
|
-
}
|
|
42230
|
-
/**
|
|
42231
|
-
* Unregister an adapter by type.
|
|
42232
|
-
* @param type The adapter type to unregister
|
|
42233
|
-
*/
|
|
42234
|
-
unregister(type2) {
|
|
42235
|
-
const unsubscribe = this.unsubscribers.get(type2);
|
|
42236
|
-
if (unsubscribe) {
|
|
42237
|
-
unsubscribe();
|
|
42238
|
-
this.unsubscribers.delete(type2);
|
|
42239
|
-
}
|
|
42240
|
-
this.adapters.delete(type2);
|
|
42241
|
-
}
|
|
42242
|
-
/**
|
|
42243
|
-
* Get all custom layer IDs across all adapters.
|
|
42244
|
-
* @returns Array of layer IDs
|
|
42245
|
-
*/
|
|
42246
|
-
getAllLayerIds() {
|
|
42247
|
-
const ids = [];
|
|
42248
|
-
this.adapters.forEach((adapter) => {
|
|
42249
|
-
ids.push(...adapter.getLayerIds());
|
|
42250
|
-
});
|
|
42251
|
-
return ids;
|
|
42252
|
-
}
|
|
42253
|
-
/**
|
|
42254
|
-
* Check if a layer ID is managed by any adapter.
|
|
42255
|
-
* @param layerId The layer ID to check
|
|
42256
|
-
* @returns true if the layer is managed by an adapter
|
|
42257
|
-
*/
|
|
42258
|
-
hasLayer(layerId) {
|
|
42259
|
-
for (const adapter of this.adapters.values()) {
|
|
42260
|
-
if (adapter.getLayerIds().includes(layerId)) {
|
|
42261
|
-
return true;
|
|
42262
|
-
}
|
|
42263
|
-
}
|
|
42264
|
-
return false;
|
|
42265
|
-
}
|
|
42266
|
-
/**
|
|
42267
|
-
* Get the adapter responsible for a specific layer.
|
|
42268
|
-
* @param layerId The layer ID
|
|
42269
|
-
* @returns The adapter or null if not found
|
|
42270
|
-
*/
|
|
42271
|
-
getAdapterForLayer(layerId) {
|
|
42272
|
-
for (const adapter of this.adapters.values()) {
|
|
42273
|
-
if (adapter.getLayerIds().includes(layerId)) {
|
|
42274
|
-
return adapter;
|
|
42275
|
-
}
|
|
42276
|
-
}
|
|
42277
|
-
return null;
|
|
42278
|
-
}
|
|
42279
|
-
/**
|
|
42280
|
-
* Get the state of a custom layer.
|
|
42281
|
-
* @param layerId The layer ID
|
|
42282
|
-
* @returns The layer state or null if not found
|
|
42283
|
-
*/
|
|
42284
|
-
getLayerState(layerId) {
|
|
42285
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42286
|
-
return adapter ? adapter.getLayerState(layerId) : null;
|
|
42287
|
-
}
|
|
42288
|
-
/**
|
|
42289
|
-
* Set visibility of a custom layer.
|
|
42290
|
-
* @param layerId The layer ID
|
|
42291
|
-
* @param visible Whether the layer should be visible
|
|
42292
|
-
* @returns true if the operation was handled by an adapter
|
|
42293
|
-
*/
|
|
42294
|
-
setVisibility(layerId, visible) {
|
|
42295
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42296
|
-
if (adapter) {
|
|
42297
|
-
adapter.setVisibility(layerId, visible);
|
|
42298
|
-
return true;
|
|
42299
|
-
}
|
|
42300
|
-
return false;
|
|
42301
|
-
}
|
|
42302
|
-
/**
|
|
42303
|
-
* Set opacity of a custom layer.
|
|
42304
|
-
* @param layerId The layer ID
|
|
42305
|
-
* @param opacity The opacity value (0-1)
|
|
42306
|
-
* @returns true if the operation was handled by an adapter
|
|
42307
|
-
*/
|
|
42308
|
-
setOpacity(layerId, opacity) {
|
|
42309
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42310
|
-
if (adapter) {
|
|
42311
|
-
adapter.setOpacity(layerId, opacity);
|
|
42312
|
-
return true;
|
|
42313
|
-
}
|
|
42314
|
-
return false;
|
|
42315
|
-
}
|
|
42316
|
-
/**
|
|
42317
|
-
* Get the symbol type for a custom layer (for UI display).
|
|
42318
|
-
* @param layerId The layer ID
|
|
42319
|
-
* @returns The symbol type or null if not available
|
|
42320
|
-
*/
|
|
42321
|
-
getSymbolType(layerId) {
|
|
42322
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42323
|
-
if (adapter && adapter.getSymbolType) {
|
|
42324
|
-
return adapter.getSymbolType(layerId);
|
|
42325
|
-
}
|
|
42326
|
-
return null;
|
|
42327
|
-
}
|
|
42328
|
-
/**
|
|
42329
|
-
* Get the bounds of a custom layer (for zoom-to-layer).
|
|
42330
|
-
* @param layerId The layer ID
|
|
42331
|
-
* @returns The bounds [west, south, east, north] or null if not available
|
|
42332
|
-
*/
|
|
42333
|
-
getBounds(layerId) {
|
|
42334
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42335
|
-
if (adapter && adapter.getBounds) {
|
|
42336
|
-
return adapter.getBounds(layerId);
|
|
42337
|
-
}
|
|
42338
|
-
return null;
|
|
42339
|
-
}
|
|
42340
|
-
/**
|
|
42341
|
-
* Get native MapLibre layer IDs for a custom layer.
|
|
42342
|
-
* @param layerId The custom layer ID
|
|
42343
|
-
* @returns Array of native layer IDs, or null if not available
|
|
42344
|
-
*/
|
|
42345
|
-
getNativeLayerIds(layerId) {
|
|
42346
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42347
|
-
if (adapter && adapter.getNativeLayerIds) {
|
|
42348
|
-
return adapter.getNativeLayerIds(layerId);
|
|
42349
|
-
}
|
|
42350
|
-
return null;
|
|
42351
|
-
}
|
|
42352
|
-
/**
|
|
42353
|
-
* Remove a custom layer through its adapter.
|
|
42354
|
-
* @param layerId The layer ID to remove
|
|
42355
|
-
* @returns true if the operation was handled by an adapter
|
|
42356
|
-
*/
|
|
42357
|
-
removeLayer(layerId) {
|
|
42358
|
-
const adapter = this.getAdapterForLayer(layerId);
|
|
42359
|
-
if (adapter && adapter.removeLayer) {
|
|
42360
|
-
adapter.removeLayer(layerId);
|
|
42361
|
-
return true;
|
|
42362
|
-
}
|
|
42363
|
-
return false;
|
|
42364
|
-
}
|
|
42365
|
-
/**
|
|
42366
|
-
* Subscribe to layer changes across all adapters.
|
|
42367
|
-
* @param callback Function called when layers are added or removed
|
|
42368
|
-
* @returns Unsubscribe function
|
|
42369
|
-
*/
|
|
42370
|
-
onChange(callback) {
|
|
42371
|
-
this.changeListeners.push(callback);
|
|
42372
|
-
return () => {
|
|
42373
|
-
const idx = this.changeListeners.indexOf(callback);
|
|
42374
|
-
if (idx >= 0) {
|
|
42375
|
-
this.changeListeners.splice(idx, 1);
|
|
42376
|
-
}
|
|
42377
|
-
};
|
|
42378
|
-
}
|
|
42379
|
-
notifyChange(event, layerId) {
|
|
42380
|
-
this.changeListeners.forEach((cb) => cb(event, layerId));
|
|
42381
|
-
}
|
|
42382
|
-
/**
|
|
42383
|
-
* Clean up all subscriptions and adapters.
|
|
42384
|
-
*/
|
|
42385
|
-
destroy() {
|
|
42386
|
-
this.unsubscribers.forEach((unsub) => unsub());
|
|
42387
|
-
this.unsubscribers.clear();
|
|
42388
|
-
this.adapters.clear();
|
|
42389
|
-
this.changeListeners = [];
|
|
42390
|
-
}
|
|
42391
|
-
}
|
|
42392
|
-
function getOpacityProperty(layerType) {
|
|
42393
|
-
switch (layerType) {
|
|
42394
|
-
case "fill":
|
|
42395
|
-
return "fill-opacity";
|
|
42396
|
-
case "line":
|
|
42397
|
-
return "line-opacity";
|
|
42398
|
-
case "circle":
|
|
42399
|
-
return "circle-opacity";
|
|
42400
|
-
case "symbol":
|
|
42401
|
-
return ["icon-opacity", "text-opacity"];
|
|
42402
|
-
case "raster":
|
|
42403
|
-
return "raster-opacity";
|
|
42404
|
-
case "background":
|
|
42405
|
-
return "background-opacity";
|
|
42406
|
-
case "heatmap":
|
|
42407
|
-
return "heatmap-opacity";
|
|
42408
|
-
case "fill-extrusion":
|
|
42409
|
-
return "fill-extrusion-opacity";
|
|
42410
|
-
case "hillshade":
|
|
42411
|
-
return "hillshade-exaggeration";
|
|
42412
|
-
case "color-relief":
|
|
42413
|
-
return null;
|
|
42414
|
-
default:
|
|
42415
|
-
return `${layerType}-opacity`;
|
|
42416
|
-
}
|
|
42417
|
-
}
|
|
42418
|
-
function getLayerOpacity(map, layerId, layerType) {
|
|
42419
|
-
const opacityProp = getOpacityProperty(layerType);
|
|
42420
|
-
if (opacityProp === null) {
|
|
42421
|
-
return 1;
|
|
42422
|
-
}
|
|
42423
|
-
if (Array.isArray(opacityProp)) {
|
|
42424
|
-
const opacity2 = map.getPaintProperty(layerId, opacityProp[0]);
|
|
42425
|
-
return opacity2 !== void 0 && opacity2 !== null ? opacity2 : 1;
|
|
42426
|
-
}
|
|
42427
|
-
const opacity = map.getPaintProperty(layerId, opacityProp);
|
|
42428
|
-
return opacity !== void 0 && opacity !== null ? opacity : 1;
|
|
42429
|
-
}
|
|
42430
|
-
function setLayerOpacity(map, layerId, layerType, opacity) {
|
|
42431
|
-
const opacityProp = getOpacityProperty(layerType);
|
|
42432
|
-
if (opacityProp === null) {
|
|
42433
|
-
return;
|
|
42434
|
-
}
|
|
42435
|
-
if (Array.isArray(opacityProp)) {
|
|
42436
|
-
opacityProp.forEach((prop) => {
|
|
42437
|
-
map.setPaintProperty(layerId, prop, opacity);
|
|
42438
|
-
});
|
|
42439
|
-
} else {
|
|
42440
|
-
map.setPaintProperty(layerId, opacityProp, opacity);
|
|
42441
|
-
}
|
|
42442
|
-
}
|
|
42443
|
-
function getLayerType(map, layerId) {
|
|
42444
|
-
try {
|
|
42445
|
-
const layer = map.getLayer(layerId);
|
|
42446
|
-
return layer ? layer.type : null;
|
|
42447
|
-
} catch (error) {
|
|
42448
|
-
console.warn(`Failed to get layer type for ${layerId}:`, error);
|
|
42449
|
-
return null;
|
|
42450
|
-
}
|
|
42451
|
-
}
|
|
42452
|
-
function clonePaintValue(value) {
|
|
42453
|
-
if (Array.isArray(value)) {
|
|
42454
|
-
return value.map((item) => clonePaintValue(item));
|
|
42455
|
-
}
|
|
42456
|
-
if (value && typeof value === "object") {
|
|
42457
|
-
try {
|
|
42458
|
-
return JSON.parse(JSON.stringify(value));
|
|
42459
|
-
} catch (error) {
|
|
42460
|
-
return value;
|
|
42461
|
-
}
|
|
42462
|
-
}
|
|
42463
|
-
return value;
|
|
42464
|
-
}
|
|
42465
|
-
function cacheOriginalLayerStyle(map, layerId, originalStyles) {
|
|
42466
|
-
var _a3;
|
|
42467
|
-
if (originalStyles.has(layerId)) {
|
|
42468
|
-
return;
|
|
42469
|
-
}
|
|
42470
|
-
try {
|
|
42471
|
-
const layer = map.getLayer(layerId);
|
|
42472
|
-
if (!layer) {
|
|
42473
|
-
return;
|
|
42474
|
-
}
|
|
42475
|
-
const paint = {};
|
|
42476
|
-
const style = map.getStyle();
|
|
42477
|
-
const layerDef = (_a3 = style.layers) == null ? void 0 : _a3.find((l3) => l3.id === layerId);
|
|
42478
|
-
if (layer.type === "raster") {
|
|
42479
|
-
const rasterDefaults = {
|
|
42480
|
-
"raster-opacity": 1,
|
|
42481
|
-
"raster-brightness-min": 0,
|
|
42482
|
-
"raster-brightness-max": 1,
|
|
42483
|
-
"raster-saturation": 0,
|
|
42484
|
-
"raster-contrast": 0,
|
|
42485
|
-
"raster-hue-rotate": 0
|
|
42486
|
-
};
|
|
42487
|
-
Object.assign(paint, rasterDefaults);
|
|
42488
|
-
if (layerDef && "paint" in layerDef && layerDef.paint) {
|
|
42489
|
-
Object.entries(layerDef.paint).forEach(([prop, value]) => {
|
|
42490
|
-
if (prop.startsWith("raster-")) {
|
|
42491
|
-
paint[prop] = clonePaintValue(value);
|
|
42492
|
-
}
|
|
42493
|
-
});
|
|
42494
|
-
}
|
|
42495
|
-
} else {
|
|
42496
|
-
if (layerDef && "paint" in layerDef && layerDef.paint) {
|
|
42497
|
-
Object.entries(layerDef.paint).forEach(([prop, value]) => {
|
|
42498
|
-
paint[prop] = clonePaintValue(value);
|
|
42499
|
-
});
|
|
42500
|
-
}
|
|
42501
|
-
}
|
|
42502
|
-
originalStyles.set(layerId, { paint });
|
|
42503
|
-
} catch (error) {
|
|
42504
|
-
console.warn(`Failed to cache original style for ${layerId}:`, error);
|
|
42505
|
-
}
|
|
42506
|
-
}
|
|
42507
|
-
function restoreOriginalStyle(map, layerId, originalStyles) {
|
|
42508
|
-
const original = originalStyles.get(layerId);
|
|
42509
|
-
if (!original) {
|
|
42510
|
-
return {};
|
|
42511
|
-
}
|
|
42512
|
-
const applied = {};
|
|
42513
|
-
Object.entries(original.paint).forEach(([property, value]) => {
|
|
42514
|
-
try {
|
|
42515
|
-
const restoredValue = clonePaintValue(value);
|
|
42516
|
-
map.setPaintProperty(layerId, property, restoredValue);
|
|
42517
|
-
applied[property] = restoredValue;
|
|
42518
|
-
} catch (error) {
|
|
42519
|
-
console.warn(`Failed to restore ${property} for ${layerId}:`, error);
|
|
42520
|
-
}
|
|
42521
|
-
});
|
|
42522
|
-
return applied;
|
|
42523
|
-
}
|
|
42524
|
-
function rgbToHex(r2, g2, b2) {
|
|
42525
|
-
const clamp2 = (v2) => Math.max(0, Math.min(255, Math.round(v2)));
|
|
42526
|
-
const toHex2 = (v2) => {
|
|
42527
|
-
const hex = clamp2(v2).toString(16);
|
|
42528
|
-
return hex.length === 1 ? `0${hex}` : hex;
|
|
42529
|
-
};
|
|
42530
|
-
return `#${toHex2(r2)}${toHex2(g2)}${toHex2(b2)}`;
|
|
42531
|
-
}
|
|
42532
|
-
function normalizeColor(value) {
|
|
42533
|
-
if (typeof value === "string") {
|
|
42534
|
-
if (value.startsWith("#")) {
|
|
42535
|
-
if (value.length === 4) {
|
|
42536
|
-
const r2 = value[1];
|
|
42537
|
-
const g2 = value[2];
|
|
42538
|
-
const b2 = value[3];
|
|
42539
|
-
return `#${r2}${r2}${g2}${g2}${b2}${b2}`;
|
|
42540
|
-
}
|
|
42541
|
-
return value;
|
|
42542
|
-
}
|
|
42543
|
-
if (value.startsWith("rgb")) {
|
|
42544
|
-
const match = value.match(/\d+/g);
|
|
42545
|
-
if (match && match.length >= 3) {
|
|
42546
|
-
const [r2, g2, b2] = match.map((num) => parseInt(num, 10));
|
|
42547
|
-
return rgbToHex(r2, g2, b2);
|
|
42548
|
-
}
|
|
42549
|
-
}
|
|
42550
|
-
} else if (Array.isArray(value) && value.length >= 3) {
|
|
42551
|
-
return rgbToHex(value[0], value[1], value[2]);
|
|
42552
|
-
}
|
|
42553
|
-
return "#3388ff";
|
|
42554
|
-
}
|
|
42555
|
-
function formatNumericValue(value, step) {
|
|
42556
|
-
let decimals = 0;
|
|
42557
|
-
if (step && Number(step) !== 1) {
|
|
42558
|
-
const stepNumber = Number(step);
|
|
42559
|
-
if (stepNumber > 0 && stepNumber < 1) {
|
|
42560
|
-
decimals = Math.min(4, Math.ceil(Math.abs(Math.log10(stepNumber))));
|
|
42561
|
-
}
|
|
42562
|
-
}
|
|
42563
|
-
return value.toFixed(decimals);
|
|
42564
|
-
}
|
|
42565
|
-
const COLOR_PROPERTY_MAP = {
|
|
42566
|
-
fill: ["fill-color", "fill-outline-color"],
|
|
42567
|
-
line: ["line-color"],
|
|
42568
|
-
circle: ["circle-color", "circle-stroke-color"],
|
|
42569
|
-
symbol: ["icon-color", "text-color"],
|
|
42570
|
-
background: ["background-color"],
|
|
42571
|
-
heatmap: ["heatmap-color"],
|
|
42572
|
-
"fill-extrusion": ["fill-extrusion-color"]
|
|
42573
|
-
};
|
|
42574
|
-
function extractColorFromExpression(expression) {
|
|
42575
|
-
if (!Array.isArray(expression) || expression.length === 0) return null;
|
|
42576
|
-
for (const item of expression) {
|
|
42577
|
-
if (typeof item === "string") {
|
|
42578
|
-
if (item.startsWith("#") || item.startsWith("rgb") || item.startsWith("hsl")) {
|
|
42579
|
-
return normalizeColor(item);
|
|
42580
|
-
}
|
|
42581
|
-
} else if (Array.isArray(item)) {
|
|
42582
|
-
const result = extractColorFromExpression(item);
|
|
42583
|
-
if (result) return result;
|
|
42584
|
-
}
|
|
42585
|
-
}
|
|
42586
|
-
return null;
|
|
42587
|
-
}
|
|
42588
|
-
function getLayerColor(map, layerId, layerType) {
|
|
42589
|
-
var _a3;
|
|
42590
|
-
const propertyNames2 = COLOR_PROPERTY_MAP[layerType];
|
|
42591
|
-
if (!propertyNames2) return null;
|
|
42592
|
-
for (const propertyName of propertyNames2) {
|
|
42593
|
-
try {
|
|
42594
|
-
const runtimeColor = map.getPaintProperty(layerId, propertyName);
|
|
42595
|
-
if (runtimeColor) {
|
|
42596
|
-
if (typeof runtimeColor === "string") {
|
|
42597
|
-
return normalizeColor(runtimeColor);
|
|
42598
|
-
}
|
|
42599
|
-
if (Array.isArray(runtimeColor)) {
|
|
42600
|
-
const extracted = extractColorFromExpression(runtimeColor);
|
|
42601
|
-
if (extracted) return extracted;
|
|
42602
|
-
}
|
|
42603
|
-
}
|
|
42604
|
-
} catch {
|
|
42605
|
-
}
|
|
42606
|
-
const style = map.getStyle();
|
|
42607
|
-
const layer = (_a3 = style == null ? void 0 : style.layers) == null ? void 0 : _a3.find(
|
|
42608
|
-
(l3) => l3.id === layerId
|
|
42609
|
-
);
|
|
42610
|
-
if (layer && "paint" in layer && layer.paint) {
|
|
42611
|
-
const paintColor = layer.paint[propertyName];
|
|
42612
|
-
if (paintColor) {
|
|
42613
|
-
if (typeof paintColor === "string") {
|
|
42614
|
-
return normalizeColor(paintColor);
|
|
42615
|
-
}
|
|
42616
|
-
if (Array.isArray(paintColor)) {
|
|
42617
|
-
const extracted = extractColorFromExpression(paintColor);
|
|
42618
|
-
if (extracted) return extracted;
|
|
42619
|
-
}
|
|
42620
|
-
}
|
|
42621
|
-
}
|
|
42622
|
-
}
|
|
42623
|
-
return null;
|
|
42624
|
-
}
|
|
42625
|
-
function getLayerColorFromSpec(layer) {
|
|
42626
|
-
const propertyNames2 = COLOR_PROPERTY_MAP[layer.type];
|
|
42627
|
-
if (!propertyNames2) return null;
|
|
42628
|
-
for (const propertyName of propertyNames2) {
|
|
42629
|
-
if ("paint" in layer && layer.paint) {
|
|
42630
|
-
const paintColor = layer.paint[propertyName];
|
|
42631
|
-
if (paintColor) {
|
|
42632
|
-
if (typeof paintColor === "string") {
|
|
42633
|
-
return normalizeColor(paintColor);
|
|
42634
|
-
}
|
|
42635
|
-
if (Array.isArray(paintColor)) {
|
|
42636
|
-
const extracted = extractColorFromExpression(paintColor);
|
|
42637
|
-
if (extracted) return extracted;
|
|
42638
|
-
}
|
|
42639
|
-
}
|
|
42640
|
-
}
|
|
42641
|
-
}
|
|
42642
|
-
return null;
|
|
42643
|
-
}
|
|
42644
|
-
function darkenColor(hexColor, amount) {
|
|
42645
|
-
let hex = hexColor.replace("#", "");
|
|
42646
|
-
if (hex.length === 3) {
|
|
42647
|
-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
42648
|
-
}
|
|
42649
|
-
const r2 = Math.max(
|
|
42650
|
-
0,
|
|
42651
|
-
parseInt(hex.slice(0, 2), 16) - Math.round(255 * amount)
|
|
42652
|
-
);
|
|
42653
|
-
const g2 = Math.max(
|
|
42654
|
-
0,
|
|
42655
|
-
parseInt(hex.slice(2, 4), 16) - Math.round(255 * amount)
|
|
42656
|
-
);
|
|
42657
|
-
const b2 = Math.max(
|
|
42658
|
-
0,
|
|
42659
|
-
parseInt(hex.slice(4, 6), 16) - Math.round(255 * amount)
|
|
42660
|
-
);
|
|
42661
|
-
return rgbToHex(r2, g2, b2);
|
|
42662
|
-
}
|
|
42663
|
-
function createFillSymbol(size, color) {
|
|
42664
|
-
const padding = 2;
|
|
42665
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42666
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42667
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42668
|
-
fill="${color}" stroke="${borderColor}" stroke-width="1" rx="1"/>
|
|
42669
|
-
</svg>`;
|
|
42670
|
-
}
|
|
42671
|
-
function createLineSymbol(size, color, strokeWidth = 2) {
|
|
42672
|
-
const y2 = size / 2;
|
|
42673
|
-
const padding = 2;
|
|
42674
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42675
|
-
<line x1="${padding}" y1="${y2}" x2="${size - padding}" y2="${y2}"
|
|
42676
|
-
stroke="${color}" stroke-width="${strokeWidth}" stroke-linecap="round"/>
|
|
42677
|
-
</svg>`;
|
|
42678
|
-
}
|
|
42679
|
-
function createCircleSymbol(size, color) {
|
|
42680
|
-
const cx = size / 2;
|
|
42681
|
-
const cy = size / 2;
|
|
42682
|
-
const r2 = size / 2 - 3;
|
|
42683
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42684
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42685
|
-
<circle cx="${cx}" cy="${cy}" r="${r2}" fill="${color}"
|
|
42686
|
-
stroke="${borderColor}" stroke-width="1"/>
|
|
42687
|
-
</svg>`;
|
|
42688
|
-
}
|
|
42689
|
-
function createMarkerSymbol(size, color) {
|
|
42690
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42691
|
-
const cx = size / 2;
|
|
42692
|
-
const pinWidth = size * 0.5;
|
|
42693
|
-
const pinHeight = size * 0.7;
|
|
42694
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42695
|
-
<path d="M${cx} ${size - 2}
|
|
42696
|
-
L${cx - pinWidth / 2} ${size - pinHeight}
|
|
42697
|
-
A${pinWidth / 2} ${pinWidth / 2} 0 1 1 ${cx + pinWidth / 2} ${size - pinHeight}
|
|
42698
|
-
Z"
|
|
42699
|
-
fill="${color}" stroke="${borderColor}" stroke-width="1"/>
|
|
42700
|
-
<circle cx="${cx}" cy="${size - pinHeight - pinWidth / 4}" r="${pinWidth / 5}" fill="white"/>
|
|
42701
|
-
</svg>`;
|
|
42702
|
-
}
|
|
42703
|
-
function createRasterSymbol(size) {
|
|
42704
|
-
const padding = 2;
|
|
42705
|
-
const id2 = `rasterGrad_${Math.random().toString(36).slice(2, 9)}`;
|
|
42706
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42707
|
-
<defs>
|
|
42708
|
-
<linearGradient id="${id2}" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
42709
|
-
<stop offset="0%" stop-color="#e0e0e0"/>
|
|
42710
|
-
<stop offset="50%" stop-color="#808080"/>
|
|
42711
|
-
<stop offset="100%" stop-color="#404040"/>
|
|
42712
|
-
</linearGradient>
|
|
42713
|
-
</defs>
|
|
42714
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42715
|
-
fill="url(#${id2})" rx="1"/>
|
|
42716
|
-
</svg>`;
|
|
42717
|
-
}
|
|
42718
|
-
function createBackgroundSymbol(size, color) {
|
|
42719
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42720
|
-
<rect x="1" y="1" width="${size - 2}" height="${size - 2}" fill="${color}" rx="2"/>
|
|
42721
|
-
<rect x="3" y="3" width="${size - 6}" height="${size - 6}" fill="none"
|
|
42722
|
-
stroke="white" stroke-width="1" stroke-opacity="0.5" rx="1"/>
|
|
42723
|
-
</svg>`;
|
|
42724
|
-
}
|
|
42725
|
-
function createHeatmapSymbol(size) {
|
|
42726
|
-
const padding = 2;
|
|
42727
|
-
const id2 = `heatmapGrad_${Math.random().toString(36).slice(2, 9)}`;
|
|
42728
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42729
|
-
<defs>
|
|
42730
|
-
<radialGradient id="${id2}" cx="50%" cy="50%" r="50%">
|
|
42731
|
-
<stop offset="0%" stop-color="#ffff00"/>
|
|
42732
|
-
<stop offset="50%" stop-color="#ff8800"/>
|
|
42733
|
-
<stop offset="100%" stop-color="#ff0000"/>
|
|
42734
|
-
</radialGradient>
|
|
42735
|
-
</defs>
|
|
42736
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42737
|
-
fill="url(#${id2})" rx="1"/>
|
|
42738
|
-
</svg>`;
|
|
42739
|
-
}
|
|
42740
|
-
function createHillshadeSymbol(size) {
|
|
42741
|
-
const padding = 2;
|
|
42742
|
-
const id2 = `hillshadeGrad_${Math.random().toString(36).slice(2, 9)}`;
|
|
42743
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42744
|
-
<defs>
|
|
42745
|
-
<linearGradient id="${id2}" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
42746
|
-
<stop offset="0%" stop-color="#ffffff"/>
|
|
42747
|
-
<stop offset="100%" stop-color="#666666"/>
|
|
42748
|
-
</linearGradient>
|
|
42749
|
-
</defs>
|
|
42750
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42751
|
-
fill="url(#${id2})" rx="1"/>
|
|
42752
|
-
</svg>`;
|
|
42753
|
-
}
|
|
42754
|
-
function createFillExtrusionSymbol(size, color) {
|
|
42755
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42756
|
-
const topColor = color;
|
|
42757
|
-
const sideColor = darkenColor(color, 0.2);
|
|
42758
|
-
const depth = 3;
|
|
42759
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42760
|
-
<polygon points="${2 + depth},2 ${size - 2},2 ${size - 2},${size - 2 - depth} ${size - 2 - depth},${size - 2} 2,${size - 2} 2,${2 + depth}"
|
|
42761
|
-
fill="${topColor}" stroke="${borderColor}" stroke-width="1"/>
|
|
42762
|
-
<polygon points="2,${2 + depth} ${2 + depth},2 ${2 + depth},${size - 2 - depth} 2,${size - 2}"
|
|
42763
|
-
fill="${sideColor}" stroke="${borderColor}" stroke-width="0.5"/>
|
|
42764
|
-
<polygon points="${2 + depth},${size - 2 - depth} ${size - 2},${size - 2 - depth} ${size - 2 - depth},${size - 2} 2,${size - 2}"
|
|
42765
|
-
fill="${sideColor}" stroke="${borderColor}" stroke-width="0.5"/>
|
|
42766
|
-
</svg>`;
|
|
42767
|
-
}
|
|
42768
|
-
function createDefaultSymbol(size, color) {
|
|
42769
|
-
const padding = 2;
|
|
42770
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42771
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42772
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42773
|
-
fill="${color}" stroke="${borderColor}" stroke-width="1"/>
|
|
42774
|
-
</svg>`;
|
|
42775
|
-
}
|
|
42776
|
-
function createCOGSymbol(size, color) {
|
|
42777
|
-
const padding = 2;
|
|
42778
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42779
|
-
const cellSize = (size - padding * 2) / 2;
|
|
42780
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42781
|
-
<rect x="${padding}" y="${padding}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5"/>
|
|
42782
|
-
<rect x="${padding + cellSize}" y="${padding}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.8"/>
|
|
42783
|
-
<rect x="${padding}" y="${padding + cellSize}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.6"/>
|
|
42784
|
-
<rect x="${padding + cellSize}" y="${padding + cellSize}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" opacity="0.4"/>
|
|
42785
|
-
</svg>`;
|
|
42786
|
-
}
|
|
42787
|
-
function createZarrSymbol(size, color) {
|
|
42788
|
-
const padding = 2;
|
|
42789
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42790
|
-
const innerSize = size - padding * 2;
|
|
42791
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42792
|
-
<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"/>
|
|
42793
|
-
<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"/>
|
|
42794
|
-
<rect x="${padding}" y="${padding + 2}" width="${innerSize - 2}" height="${innerSize - 2}" fill="${color}" stroke="${borderColor}" stroke-width="0.5" rx="1"/>
|
|
42795
|
-
<line x1="${padding + 3}" y1="${padding + 5}" x2="${padding + innerSize - 5}" y2="${padding + 5}" stroke="${borderColor}" stroke-width="0.5" opacity="0.5"/>
|
|
42796
|
-
<line x1="${padding + 3}" y1="${padding + 8}" x2="${padding + innerSize - 5}" y2="${padding + 8}" stroke="${borderColor}" stroke-width="0.5" opacity="0.5"/>
|
|
42797
|
-
</svg>`;
|
|
42798
|
-
}
|
|
42799
|
-
function createCustomRasterSymbol(size, color) {
|
|
42800
|
-
const padding = 2;
|
|
42801
|
-
const borderColor = darkenColor(color, 0.3);
|
|
42802
|
-
const id2 = `customRasterGrad_${Math.random().toString(36).slice(2, 9)}`;
|
|
42803
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42804
|
-
<defs>
|
|
42805
|
-
<linearGradient id="${id2}" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
42806
|
-
<stop offset="0%" stop-color="${color}"/>
|
|
42807
|
-
<stop offset="100%" stop-color="${darkenColor(color, 0.4)}"/>
|
|
42808
|
-
</linearGradient>
|
|
42809
|
-
</defs>
|
|
42810
|
-
<rect x="${padding}" y="${padding}" width="${size - padding * 2}" height="${size - padding * 2}"
|
|
42811
|
-
fill="url(#${id2})" stroke="${borderColor}" stroke-width="1" rx="1"/>
|
|
42812
|
-
<line x1="${size / 2}" y1="${padding}" x2="${size / 2}" y2="${size - padding}" stroke="${borderColor}" stroke-width="0.5" opacity="0.3"/>
|
|
42813
|
-
<line x1="${padding}" y1="${size / 2}" x2="${size - padding}" y2="${size / 2}" stroke="${borderColor}" stroke-width="0.5" opacity="0.3"/>
|
|
42814
|
-
</svg>`;
|
|
42815
|
-
}
|
|
42816
|
-
function createStackedLayersSymbol(size) {
|
|
42817
|
-
const colors = ["#a8d4a8", "#8ec4e8", "#d4c4a8"];
|
|
42818
|
-
const borderColor = "#666666";
|
|
42819
|
-
return `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
|
|
42820
|
-
<rect x="4" y="1" width="${size - 6}" height="${size - 6}" fill="${colors[2]}" stroke="${borderColor}" stroke-width="0.75" rx="1"/>
|
|
42821
|
-
<rect x="2" y="3" width="${size - 6}" height="${size - 6}" fill="${colors[1]}" stroke="${borderColor}" stroke-width="0.75" rx="1"/>
|
|
42822
|
-
<rect x="0" y="5" width="${size - 6}" height="${size - 6}" fill="${colors[0]}" stroke="${borderColor}" stroke-width="0.75" rx="1"/>
|
|
42823
|
-
</svg>`;
|
|
42824
|
-
}
|
|
42825
|
-
function createLayerSymbolSVG(layerType, color, options = {}) {
|
|
42826
|
-
const size = options.size || 16;
|
|
42827
|
-
const strokeWidth = options.strokeWidth || 2;
|
|
42828
|
-
const fillColor = color || "#888888";
|
|
42829
|
-
switch (layerType) {
|
|
42830
|
-
case "fill":
|
|
42831
|
-
return createFillSymbol(size, fillColor);
|
|
42832
|
-
case "line":
|
|
42833
|
-
return createLineSymbol(size, fillColor, strokeWidth);
|
|
42834
|
-
case "circle":
|
|
42835
|
-
return createCircleSymbol(size, fillColor);
|
|
42836
|
-
case "symbol":
|
|
42837
|
-
return createMarkerSymbol(size, fillColor);
|
|
42838
|
-
case "raster":
|
|
42839
|
-
return createRasterSymbol(size);
|
|
42840
|
-
case "background":
|
|
42841
|
-
return createBackgroundSymbol(size, fillColor);
|
|
42842
|
-
case "heatmap":
|
|
42843
|
-
return createHeatmapSymbol(size);
|
|
42844
|
-
case "hillshade":
|
|
42845
|
-
return createHillshadeSymbol(size);
|
|
42846
|
-
case "fill-extrusion":
|
|
42847
|
-
return createFillExtrusionSymbol(size, fillColor);
|
|
42848
|
-
case "background-group":
|
|
42849
|
-
return createStackedLayersSymbol(size);
|
|
42850
|
-
case "cog":
|
|
42851
|
-
return createCOGSymbol(size, fillColor);
|
|
42852
|
-
case "zarr":
|
|
42853
|
-
return createZarrSymbol(size, fillColor);
|
|
42854
|
-
case "custom-raster":
|
|
42855
|
-
return createCustomRasterSymbol(size, fillColor);
|
|
42856
|
-
default:
|
|
42857
|
-
return createDefaultSymbol(size, fillColor);
|
|
42858
|
-
}
|
|
42859
|
-
}
|
|
42860
|
-
function createBackgroundGroupSymbolSVG(size = 16) {
|
|
42861
|
-
return createStackedLayersSymbol(size);
|
|
42862
|
-
}
|
|
42863
|
-
class LayerControl {
|
|
42864
|
-
constructor(options = {}) {
|
|
42865
|
-
__publicField2(this, "map");
|
|
42866
|
-
__publicField2(this, "mapContainer");
|
|
42867
|
-
__publicField2(this, "container");
|
|
42868
|
-
__publicField2(this, "button");
|
|
42869
|
-
__publicField2(this, "panel");
|
|
42870
|
-
__publicField2(this, "resizeHandler", null);
|
|
42871
|
-
__publicField2(this, "mapResizeHandler", null);
|
|
42872
|
-
__publicField2(this, "state");
|
|
42873
|
-
__publicField2(this, "targetLayers");
|
|
42874
|
-
__publicField2(this, "styleEditors");
|
|
42875
|
-
__publicField2(this, "initialSourceIds", null);
|
|
42876
|
-
__publicField2(this, "initialLayerIds", null);
|
|
42877
|
-
__publicField2(this, "initialLayerStates");
|
|
42878
|
-
__publicField2(this, "minPanelWidth");
|
|
42879
|
-
__publicField2(this, "maxPanelWidth");
|
|
42880
|
-
__publicField2(this, "maxPanelHeight");
|
|
42881
|
-
__publicField2(this, "showStyleEditor");
|
|
42882
|
-
__publicField2(this, "showOpacitySlider");
|
|
42883
|
-
__publicField2(this, "showLayerSymbol");
|
|
42884
|
-
__publicField2(this, "excludeDrawnLayers");
|
|
42885
|
-
__publicField2(this, "excludeLayerPatterns");
|
|
42886
|
-
__publicField2(this, "customLayerRegistry", null);
|
|
42887
|
-
__publicField2(this, "customLayerUnsubscribe", null);
|
|
42888
|
-
__publicField2(this, "removedCustomLayerIds", /* @__PURE__ */ new Set());
|
|
42889
|
-
__publicField2(this, "nativeLayerGroups", /* @__PURE__ */ new Map());
|
|
42890
|
-
__publicField2(this, "basemapStyleUrl", null);
|
|
42891
|
-
__publicField2(this, "basemapLayerIds", null);
|
|
42892
|
-
__publicField2(this, "widthSliderEl", null);
|
|
42893
|
-
__publicField2(this, "widthThumbEl", null);
|
|
42894
|
-
__publicField2(this, "widthValueEl", null);
|
|
42895
|
-
__publicField2(this, "isWidthSliderActive", false);
|
|
42896
|
-
__publicField2(this, "widthDragRectWidth", null);
|
|
42897
|
-
__publicField2(this, "widthDragStartX", null);
|
|
42898
|
-
__publicField2(this, "widthDragStartWidth", null);
|
|
42899
|
-
__publicField2(this, "widthFrame", null);
|
|
42900
|
-
__publicField2(this, "contextMenuEl", null);
|
|
42901
|
-
__publicField2(this, "enableContextMenu");
|
|
42902
|
-
__publicField2(this, "enableDragAndDrop");
|
|
42903
|
-
__publicField2(this, "onLayerRename");
|
|
42904
|
-
__publicField2(this, "onLayerReorder");
|
|
42905
|
-
__publicField2(this, "onLayerRemove");
|
|
42906
|
-
this.minPanelWidth = options.panelMinWidth || 240;
|
|
42907
|
-
this.maxPanelWidth = options.panelMaxWidth || 420;
|
|
42908
|
-
this.maxPanelHeight = options.panelMaxHeight || 600;
|
|
42909
|
-
this.showStyleEditor = options.showStyleEditor !== false;
|
|
42910
|
-
this.showOpacitySlider = options.showOpacitySlider !== false;
|
|
42911
|
-
this.showLayerSymbol = options.showLayerSymbol !== false;
|
|
42912
|
-
this.excludeDrawnLayers = options.excludeDrawnLayers !== false;
|
|
42913
|
-
this.excludeLayerPatterns = this.wildcardPatternsToRegex(options.excludeLayers || []);
|
|
42914
|
-
this.enableContextMenu = options.enableContextMenu !== false;
|
|
42915
|
-
this.enableDragAndDrop = options.enableDragAndDrop !== false;
|
|
42916
|
-
this.onLayerRename = options.onLayerRename;
|
|
42917
|
-
this.onLayerReorder = options.onLayerReorder;
|
|
42918
|
-
this.onLayerRemove = options.onLayerRemove;
|
|
42919
|
-
this.initialLayerStates = options.layerStates || {};
|
|
42920
|
-
this.state = {
|
|
42921
|
-
collapsed: options.collapsed !== false,
|
|
42922
|
-
panelWidth: options.panelWidth || 350,
|
|
42923
|
-
activeStyleEditor: null,
|
|
42924
|
-
layerStates: {},
|
|
42925
|
-
originalStyles: /* @__PURE__ */ new Map(),
|
|
42926
|
-
userInteractingWithSlider: false,
|
|
42927
|
-
backgroundLegendOpen: false,
|
|
42928
|
-
backgroundLayerVisibility: /* @__PURE__ */ new Map(),
|
|
42929
|
-
onlyRenderedFilter: false,
|
|
42930
|
-
contextMenu: {
|
|
42931
|
-
visible: false,
|
|
42932
|
-
targetLayerId: null,
|
|
42933
|
-
x: 0,
|
|
42934
|
-
y: 0
|
|
42935
|
-
},
|
|
42936
|
-
renamingLayerId: null,
|
|
42937
|
-
customLayerNames: /* @__PURE__ */ new Map(),
|
|
42938
|
-
drag: {
|
|
42939
|
-
active: false,
|
|
42940
|
-
layerId: null,
|
|
42941
|
-
startY: 0,
|
|
42942
|
-
currentY: 0,
|
|
42943
|
-
placeholder: null,
|
|
42944
|
-
draggedElement: null
|
|
42945
|
-
},
|
|
42946
|
-
isStyleOperationInProgress: false
|
|
42947
|
-
};
|
|
42948
|
-
this.targetLayers = options.layers || Object.keys(this.initialLayerStates);
|
|
42949
|
-
this.styleEditors = /* @__PURE__ */ new Map();
|
|
42950
|
-
if (options.customLayerAdapters && options.customLayerAdapters.length > 0) {
|
|
42951
|
-
this.customLayerRegistry = new CustomLayerRegistry();
|
|
42952
|
-
options.customLayerAdapters.forEach((adapter) => {
|
|
42953
|
-
this.customLayerRegistry.register(adapter);
|
|
42954
|
-
});
|
|
42955
|
-
}
|
|
42956
|
-
this.basemapStyleUrl = options.basemapStyleUrl || null;
|
|
42957
|
-
}
|
|
42958
|
-
/**
|
|
42959
|
-
* Called when the control is added to the map
|
|
42960
|
-
*/
|
|
42961
|
-
onAdd(map) {
|
|
42962
|
-
this.map = map;
|
|
42963
|
-
this.mapContainer = map.getContainer();
|
|
42964
|
-
const style = this.map.getStyle();
|
|
42965
|
-
if (style && style.sources) {
|
|
42966
|
-
this.initialSourceIds = new Set(Object.keys(style.sources));
|
|
42967
|
-
} else {
|
|
42968
|
-
this.initialSourceIds = /* @__PURE__ */ new Set();
|
|
42969
|
-
}
|
|
42970
|
-
if (style && style.layers) {
|
|
42971
|
-
this.initialLayerIds = new Set(style.layers.map((layer) => layer.id));
|
|
42972
|
-
} else {
|
|
42973
|
-
this.initialLayerIds = /* @__PURE__ */ new Set();
|
|
42974
|
-
}
|
|
42975
|
-
this.container = this.createContainer();
|
|
42976
|
-
this.button = this.createToggleButton();
|
|
42977
|
-
this.panel = this.createPanel();
|
|
42978
|
-
this.container.appendChild(this.button);
|
|
42979
|
-
this.mapContainer.appendChild(this.panel);
|
|
42980
|
-
if (this.enableContextMenu) {
|
|
42981
|
-
this.contextMenuEl = this.createContextMenu();
|
|
42982
|
-
this.mapContainer.appendChild(this.contextMenuEl);
|
|
42983
|
-
}
|
|
42984
|
-
this.updateWidthDisplay();
|
|
42985
|
-
this.setupEventListeners();
|
|
42986
|
-
if (this.basemapStyleUrl && !this.basemapLayerIds) {
|
|
42987
|
-
this.fetchBasemapStyle().then(() => {
|
|
42988
|
-
if (Object.keys(this.state.layerStates).length === 0) {
|
|
42989
|
-
this.autoDetectLayers();
|
|
42990
|
-
}
|
|
42991
|
-
this.buildLayerItems();
|
|
42992
|
-
}).catch((error) => {
|
|
42993
|
-
console.warn("Failed to fetch basemap style, falling back to heuristic detection:", error);
|
|
42994
|
-
if (Object.keys(this.state.layerStates).length === 0) {
|
|
42995
|
-
this.autoDetectLayers();
|
|
42996
|
-
}
|
|
42997
|
-
this.buildLayerItems();
|
|
42998
|
-
});
|
|
42999
|
-
} else {
|
|
43000
|
-
if (Object.keys(this.state.layerStates).length === 0) {
|
|
43001
|
-
this.autoDetectLayers();
|
|
43002
|
-
}
|
|
43003
|
-
this.buildLayerItems();
|
|
43004
|
-
}
|
|
43005
|
-
if (!this.state.collapsed) {
|
|
43006
|
-
requestAnimationFrame(() => {
|
|
43007
|
-
this.updatePanelPosition();
|
|
43008
|
-
});
|
|
43009
|
-
}
|
|
43010
|
-
return this.container;
|
|
43011
|
-
}
|
|
43012
|
-
/**
|
|
43013
|
-
* Fetch the basemap style JSON and extract layer IDs.
|
|
43014
|
-
* This provides reliable distinction between basemap and user-added layers.
|
|
43015
|
-
*/
|
|
43016
|
-
async fetchBasemapStyle() {
|
|
43017
|
-
if (!this.basemapStyleUrl) return;
|
|
43018
|
-
try {
|
|
43019
|
-
const response = await fetch(this.basemapStyleUrl);
|
|
43020
|
-
if (!response.ok) {
|
|
43021
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
43022
|
-
}
|
|
43023
|
-
const styleJson = await response.json();
|
|
43024
|
-
if (styleJson && Array.isArray(styleJson.layers)) {
|
|
43025
|
-
this.basemapLayerIds = new Set(
|
|
43026
|
-
styleJson.layers.map((layer) => layer.id)
|
|
43027
|
-
);
|
|
43028
|
-
} else {
|
|
43029
|
-
this.basemapLayerIds = /* @__PURE__ */ new Set();
|
|
43030
|
-
}
|
|
43031
|
-
} catch (error) {
|
|
43032
|
-
console.warn("Failed to fetch basemap style from URL:", this.basemapStyleUrl, error);
|
|
43033
|
-
throw error;
|
|
43034
|
-
}
|
|
43035
|
-
}
|
|
43036
|
-
/**
|
|
43037
|
-
* Called when the control is removed from the map
|
|
43038
|
-
*/
|
|
43039
|
-
onRemove() {
|
|
43040
|
-
var _a3, _b3, _c3;
|
|
43041
|
-
if (this.customLayerUnsubscribe) {
|
|
43042
|
-
this.customLayerUnsubscribe();
|
|
43043
|
-
this.customLayerUnsubscribe = null;
|
|
43044
|
-
}
|
|
43045
|
-
if (this.customLayerRegistry) {
|
|
43046
|
-
this.customLayerRegistry.destroy();
|
|
43047
|
-
this.customLayerRegistry = null;
|
|
43048
|
-
}
|
|
43049
|
-
if (this.resizeHandler) {
|
|
43050
|
-
window.removeEventListener("resize", this.resizeHandler);
|
|
43051
|
-
this.resizeHandler = null;
|
|
43052
|
-
}
|
|
43053
|
-
if (this.mapResizeHandler) {
|
|
43054
|
-
this.map.off("resize", this.mapResizeHandler);
|
|
43055
|
-
this.mapResizeHandler = null;
|
|
43056
|
-
}
|
|
43057
|
-
if (this.contextMenuEl) {
|
|
43058
|
-
(_a3 = this.contextMenuEl.parentNode) == null ? void 0 : _a3.removeChild(this.contextMenuEl);
|
|
43059
|
-
this.contextMenuEl = null;
|
|
43060
|
-
}
|
|
43061
|
-
this.cleanupDragState();
|
|
43062
|
-
(_b3 = this.panel.parentNode) == null ? void 0 : _b3.removeChild(this.panel);
|
|
43063
|
-
(_c3 = this.container.parentNode) == null ? void 0 : _c3.removeChild(this.container);
|
|
43064
|
-
}
|
|
43065
|
-
/**
|
|
43066
|
-
* Auto-detect layers from the map and populate layerStates
|
|
43067
|
-
*/
|
|
43068
|
-
autoDetectLayers() {
|
|
43069
|
-
const style = this.map.getStyle();
|
|
43070
|
-
if (!style || !style.layers) {
|
|
43071
|
-
return;
|
|
43072
|
-
}
|
|
43073
|
-
const allLayerIds = style.layers.map((layer) => layer.id);
|
|
43074
|
-
if (this.targetLayers.length === 0) {
|
|
43075
|
-
const userAddedLayers = [];
|
|
43076
|
-
const backgroundLayerIds = [];
|
|
43077
|
-
const useBasemapStyleDetection = this.basemapLayerIds !== null && this.basemapLayerIds.size > 0;
|
|
43078
|
-
const userAddedSourceIds = useBasemapStyleDetection ? /* @__PURE__ */ new Set() : this.detectUserAddedSources();
|
|
43079
|
-
allLayerIds.forEach((layerId) => {
|
|
43080
|
-
const layer = this.map.getLayer(layerId);
|
|
43081
|
-
if (!layer) return;
|
|
43082
|
-
if (this.excludeDrawnLayers && this.isDrawnLayer(layerId)) {
|
|
43083
|
-
backgroundLayerIds.push(layerId);
|
|
43084
|
-
return;
|
|
43085
|
-
}
|
|
43086
|
-
if (this.isExcludedByPattern(layerId)) {
|
|
43087
|
-
backgroundLayerIds.push(layerId);
|
|
43088
|
-
return;
|
|
43089
|
-
}
|
|
43090
|
-
if (useBasemapStyleDetection) {
|
|
43091
|
-
if (this.basemapLayerIds.has(layerId)) {
|
|
43092
|
-
backgroundLayerIds.push(layerId);
|
|
43093
|
-
} else {
|
|
43094
|
-
userAddedLayers.push(layerId);
|
|
43095
|
-
}
|
|
43096
|
-
} else {
|
|
43097
|
-
const sourceId = layer.source;
|
|
43098
|
-
if (sourceId && userAddedSourceIds.has(sourceId)) {
|
|
43099
|
-
userAddedLayers.push(layerId);
|
|
43100
|
-
} else {
|
|
43101
|
-
backgroundLayerIds.push(layerId);
|
|
43102
|
-
}
|
|
43103
|
-
}
|
|
43104
|
-
});
|
|
43105
|
-
if (backgroundLayerIds.length > 0) {
|
|
43106
|
-
this.state.layerStates["Background"] = {
|
|
43107
|
-
visible: true,
|
|
43108
|
-
opacity: 1,
|
|
43109
|
-
name: "Background"
|
|
43110
|
-
};
|
|
43111
|
-
}
|
|
43112
|
-
userAddedLayers.forEach((layerId) => {
|
|
43113
|
-
const layer = this.map.getLayer(layerId);
|
|
43114
|
-
if (!layer) return;
|
|
43115
|
-
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
43116
|
-
const isVisible = visibility !== "none";
|
|
43117
|
-
const layerType = layer.type;
|
|
43118
|
-
const opacity = getLayerOpacity(this.map, layerId, layerType);
|
|
43119
|
-
const friendlyName = this.generateFriendlyName(layerId);
|
|
43120
|
-
this.state.layerStates[layerId] = this.mergeWithUserState(layerId, {
|
|
43121
|
-
visible: isVisible,
|
|
43122
|
-
opacity,
|
|
43123
|
-
name: friendlyName
|
|
43124
|
-
});
|
|
43125
|
-
});
|
|
43126
|
-
} else {
|
|
43127
|
-
const userLayers = [];
|
|
43128
|
-
const basemapLayers = [];
|
|
43129
|
-
allLayerIds.forEach((layerId) => {
|
|
43130
|
-
if (this.isExcludedByPattern(layerId)) {
|
|
43131
|
-
basemapLayers.push(layerId);
|
|
43132
|
-
return;
|
|
43133
|
-
}
|
|
43134
|
-
if (this.targetLayers.includes(layerId)) {
|
|
43135
|
-
userLayers.push(layerId);
|
|
43136
|
-
} else {
|
|
43137
|
-
basemapLayers.push(layerId);
|
|
43138
|
-
}
|
|
43139
|
-
});
|
|
43140
|
-
if (basemapLayers.length > 0) {
|
|
43141
|
-
this.state.layerStates["Background"] = {
|
|
43142
|
-
visible: true,
|
|
43143
|
-
opacity: 1,
|
|
43144
|
-
name: "Background"
|
|
43145
|
-
};
|
|
43146
|
-
}
|
|
43147
|
-
userLayers.forEach((layerId) => {
|
|
43148
|
-
const layer = this.map.getLayer(layerId);
|
|
43149
|
-
if (!layer) return;
|
|
43150
|
-
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
43151
|
-
const isVisible = visibility !== "none";
|
|
43152
|
-
const layerType = layer.type;
|
|
43153
|
-
const opacity = getLayerOpacity(this.map, layerId, layerType);
|
|
43154
|
-
const friendlyName = this.generateFriendlyName(layerId);
|
|
43155
|
-
this.state.layerStates[layerId] = this.mergeWithUserState(layerId, {
|
|
43156
|
-
visible: isVisible,
|
|
43157
|
-
opacity,
|
|
43158
|
-
name: friendlyName
|
|
43159
|
-
});
|
|
43160
|
-
});
|
|
43161
|
-
}
|
|
43162
|
-
if (this.customLayerRegistry) {
|
|
43163
|
-
const customLayerIds = this.customLayerRegistry.getAllLayerIds();
|
|
43164
|
-
customLayerIds.forEach((layerId) => {
|
|
43165
|
-
if (this.state.layerStates[layerId]) return;
|
|
43166
|
-
const customState = this.customLayerRegistry.getLayerState(layerId);
|
|
43167
|
-
if (customState) {
|
|
43168
|
-
this.state.layerStates[layerId] = {
|
|
43169
|
-
visible: customState.visible,
|
|
43170
|
-
opacity: customState.opacity,
|
|
43171
|
-
name: customState.name,
|
|
43172
|
-
isCustomLayer: true,
|
|
43173
|
-
customLayerType: this.customLayerRegistry.getSymbolType(layerId) || void 0
|
|
43174
|
-
};
|
|
43175
|
-
}
|
|
43176
|
-
});
|
|
43177
|
-
}
|
|
43178
|
-
this.targetLayers = Object.keys(this.state.layerStates);
|
|
43179
|
-
}
|
|
43180
|
-
/**
|
|
43181
|
-
* Detect which sources are user-added (not from the basemap style)
|
|
43182
|
-
* User-added sources are identified by:
|
|
43183
|
-
* - Sources that were NOT present when the control was first added
|
|
43184
|
-
* - Additionally for sources added later:
|
|
43185
|
-
* - GeoJSON sources with inline data objects (not URL strings)
|
|
43186
|
-
* - Image, video, canvas sources
|
|
43187
|
-
* - Raster, raster-dem, vector sources from non-basemap tile providers
|
|
43188
|
-
*/
|
|
43189
|
-
detectUserAddedSources() {
|
|
43190
|
-
const userAddedSources = /* @__PURE__ */ new Set();
|
|
43191
|
-
const style = this.map.getStyle();
|
|
43192
|
-
if (!style || !style.sources) return userAddedSources;
|
|
43193
|
-
const basemapDomains = /* @__PURE__ */ new Set();
|
|
43194
|
-
const knownBasemapProviders = [
|
|
43195
|
-
"demotiles.maplibre.org",
|
|
43196
|
-
"api.maptiler.com",
|
|
43197
|
-
"tiles.stadiamaps.com",
|
|
43198
|
-
"api.mapbox.com",
|
|
43199
|
-
"basemaps.cartocdn.com",
|
|
43200
|
-
"tiles.mapbox.com",
|
|
43201
|
-
"a.basemaps.cartocdn.com",
|
|
43202
|
-
"b.basemaps.cartocdn.com",
|
|
43203
|
-
"c.basemaps.cartocdn.com",
|
|
43204
|
-
"d.basemaps.cartocdn.com",
|
|
43205
|
-
"tiles.arcgis.com",
|
|
43206
|
-
"server.arcgisonline.com",
|
|
43207
|
-
"services.arcgisonline.com"
|
|
43208
|
-
];
|
|
43209
|
-
const spriteUrl = style.sprite;
|
|
43210
|
-
if (spriteUrl && typeof spriteUrl === "string") {
|
|
43211
|
-
try {
|
|
43212
|
-
const url = new URL(spriteUrl);
|
|
43213
|
-
basemapDomains.add(url.hostname);
|
|
43214
|
-
} catch {
|
|
43215
|
-
}
|
|
43216
|
-
}
|
|
43217
|
-
if (style.glyphs) {
|
|
43218
|
-
try {
|
|
43219
|
-
const url = new URL(style.glyphs.replace("{fontstack}", "x").replace("{range}", "x"));
|
|
43220
|
-
basemapDomains.add(url.hostname);
|
|
43221
|
-
} catch {
|
|
43222
|
-
}
|
|
43223
|
-
}
|
|
43224
|
-
for (const [sourceId, source] of Object.entries(style.sources)) {
|
|
43225
|
-
if (this.initialSourceIds && this.initialSourceIds.has(sourceId)) {
|
|
43226
|
-
continue;
|
|
43227
|
-
}
|
|
43228
|
-
const src = source;
|
|
43229
|
-
const sourceType = src.type;
|
|
43230
|
-
if (sourceType === "image" || sourceType === "video" || sourceType === "canvas") {
|
|
43231
|
-
userAddedSources.add(sourceId);
|
|
43232
|
-
continue;
|
|
43233
|
-
}
|
|
43234
|
-
if (sourceType === "geojson") {
|
|
43235
|
-
if (src.data && typeof src.data === "object") {
|
|
43236
|
-
userAddedSources.add(sourceId);
|
|
43237
|
-
} else if (src.data && typeof src.data === "string") {
|
|
43238
|
-
try {
|
|
43239
|
-
const url = new URL(src.data);
|
|
43240
|
-
const isBasemap = knownBasemapProviders.some((p) => url.hostname.includes(p)) || basemapDomains.has(url.hostname);
|
|
43241
|
-
if (!isBasemap) {
|
|
43242
|
-
userAddedSources.add(sourceId);
|
|
43243
|
-
}
|
|
43244
|
-
} catch {
|
|
43245
|
-
userAddedSources.add(sourceId);
|
|
43246
|
-
}
|
|
43247
|
-
}
|
|
43248
|
-
continue;
|
|
43249
|
-
}
|
|
43250
|
-
if (sourceType === "raster" || sourceType === "raster-dem" || sourceType === "vector") {
|
|
43251
|
-
const tileUrl = src.url || src.tiles && src.tiles[0] || "";
|
|
43252
|
-
if (tileUrl) {
|
|
43253
|
-
try {
|
|
43254
|
-
const url = new URL(tileUrl.replace(/{[^}]+}/g, "0"));
|
|
43255
|
-
const hostname = url.hostname;
|
|
43256
|
-
const isKnownBasemap = knownBasemapProviders.some(
|
|
43257
|
-
(provider) => hostname === provider || hostname.endsWith("." + provider)
|
|
43258
|
-
);
|
|
43259
|
-
const matchesBasemapDomain = basemapDomains.has(hostname);
|
|
43260
|
-
if (!isKnownBasemap && !matchesBasemapDomain) {
|
|
43261
|
-
userAddedSources.add(sourceId);
|
|
43262
|
-
}
|
|
43263
|
-
} catch {
|
|
43264
|
-
userAddedSources.add(sourceId);
|
|
43265
|
-
}
|
|
43266
|
-
}
|
|
43267
|
-
}
|
|
43268
|
-
}
|
|
43269
|
-
return userAddedSources;
|
|
43270
|
-
}
|
|
43271
|
-
/**
|
|
43272
|
-
* Generate a friendly display name from a layer ID
|
|
43273
|
-
*/
|
|
43274
|
-
generateFriendlyName(layerId) {
|
|
43275
|
-
let name = layerId.replace(/^(layer[-_]?|gl[-_]?)/, "");
|
|
43276
|
-
name = name.replace(/[-_]/g, " ");
|
|
43277
|
-
name = name.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
43278
|
-
return name || layerId;
|
|
43279
|
-
}
|
|
43280
|
-
/**
|
|
43281
|
-
* Merge auto-detected layer state with user-provided initial state.
|
|
43282
|
-
* User-provided values take precedence over detected values.
|
|
43283
|
-
*/
|
|
43284
|
-
mergeWithUserState(layerId, detected) {
|
|
43285
|
-
const userState = this.initialLayerStates[layerId];
|
|
43286
|
-
if (!userState) return detected;
|
|
43287
|
-
return {
|
|
43288
|
-
visible: userState.visible ?? detected.visible,
|
|
43289
|
-
opacity: userState.opacity ?? detected.opacity,
|
|
43290
|
-
name: userState.name ?? detected.name,
|
|
43291
|
-
...userState.isCustomLayer !== void 0 && { isCustomLayer: userState.isCustomLayer },
|
|
43292
|
-
...userState.customLayerType !== void 0 && { customLayerType: userState.customLayerType }
|
|
43293
|
-
};
|
|
43294
|
-
}
|
|
43295
|
-
/**
|
|
43296
|
-
* Check if a layer ID belongs to a drawing library (Geoman, Mapbox GL Draw, etc.)
|
|
43297
|
-
* @param layerId The layer ID to check
|
|
43298
|
-
* @returns true if the layer is from a drawing library
|
|
43299
|
-
*/
|
|
43300
|
-
isDrawnLayer(layerId) {
|
|
43301
|
-
const drawnLayerPatterns = [
|
|
43302
|
-
// Drawing libraries
|
|
43303
|
-
/^gm[-_\s]/i,
|
|
43304
|
-
// Geoman (gm-main-*, gm_*, Gm Temporary...)
|
|
43305
|
-
/^gl-draw[-_]/i,
|
|
43306
|
-
// Mapbox GL Draw
|
|
43307
|
-
/^mapbox-gl-draw[-_]/i,
|
|
43308
|
-
// Mapbox GL Draw alternative
|
|
43309
|
-
/^terra-draw[-_]/i,
|
|
43310
|
-
// Terra Draw
|
|
43311
|
-
/^maplibre-gl-draw[-_]/i,
|
|
43312
|
-
// MapLibre GL Draw
|
|
43313
|
-
/^draw[-_]layer/i,
|
|
43314
|
-
// Generic draw layers
|
|
43315
|
-
// maplibre-gl-components internal layers
|
|
43316
|
-
/^measure-/i,
|
|
43317
|
-
// MeasureControl (measure-{id}-fill, measure-{id}-line)
|
|
43318
|
-
/^pmtiles-source-/i,
|
|
43319
|
-
// PMTilesLayerControl (managed via adapter)
|
|
43320
|
-
/^stac-search-footprints/i
|
|
43321
|
-
// StacSearchControl footprint layers
|
|
43322
|
-
];
|
|
43323
|
-
return drawnLayerPatterns.some((pattern2) => pattern2.test(layerId));
|
|
43324
|
-
}
|
|
43325
|
-
/**
|
|
43326
|
-
* Convert wildcard patterns (e.g., '*-temp-*', 'debug-*') to RegExp objects
|
|
43327
|
-
*/
|
|
43328
|
-
wildcardPatternsToRegex(patterns) {
|
|
43329
|
-
return patterns.map((pattern2) => {
|
|
43330
|
-
const escaped = pattern2.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
43331
|
-
const regexStr = escaped.replace(/\*/g, ".*");
|
|
43332
|
-
return new RegExp(`^${regexStr}$`, "i");
|
|
43333
|
-
});
|
|
43334
|
-
}
|
|
43335
|
-
/**
|
|
43336
|
-
* Check if a layer matches any of the user-defined exclusion patterns
|
|
43337
|
-
*/
|
|
43338
|
-
isExcludedByPattern(layerId) {
|
|
43339
|
-
return this.excludeLayerPatterns.some((pattern2) => pattern2.test(layerId));
|
|
43340
|
-
}
|
|
43341
|
-
/**
|
|
43342
|
-
* Create the main container element
|
|
43343
|
-
*/
|
|
43344
|
-
createContainer() {
|
|
43345
|
-
const container = document.createElement("div");
|
|
43346
|
-
container.className = "maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-layer-control";
|
|
43347
|
-
return container;
|
|
43348
|
-
}
|
|
43349
|
-
/**
|
|
43350
|
-
* Create the toggle button
|
|
43351
|
-
*/
|
|
43352
|
-
createToggleButton() {
|
|
43353
|
-
const button = document.createElement("button");
|
|
43354
|
-
button.type = "button";
|
|
43355
|
-
button.title = "Layer Control";
|
|
43356
|
-
button.setAttribute("aria-label", "Layer Control");
|
|
43357
|
-
const icon = document.createElement("span");
|
|
43358
|
-
icon.className = "layer-control-icon";
|
|
43359
|
-
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>';
|
|
43360
|
-
button.appendChild(icon);
|
|
43361
|
-
return button;
|
|
43362
|
-
}
|
|
43363
|
-
/**
|
|
43364
|
-
* Create the panel element
|
|
43365
|
-
*/
|
|
43366
|
-
createPanel() {
|
|
43367
|
-
const panel = document.createElement("div");
|
|
43368
|
-
panel.className = "layer-control-panel";
|
|
43369
|
-
panel.style.width = `${this.state.panelWidth}px`;
|
|
43370
|
-
panel.style.maxHeight = `${this.maxPanelHeight}px`;
|
|
43371
|
-
if (!this.state.collapsed) {
|
|
43372
|
-
panel.classList.add("expanded");
|
|
43373
|
-
}
|
|
43374
|
-
const header = this.createPanelHeader();
|
|
43375
|
-
panel.appendChild(header);
|
|
43376
|
-
const actionButtons = this.createActionButtons();
|
|
43377
|
-
panel.appendChild(actionButtons);
|
|
43378
|
-
return panel;
|
|
43379
|
-
}
|
|
43380
|
-
/**
|
|
43381
|
-
* Detect which corner the control is positioned in
|
|
43382
|
-
* @returns The position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
|
43383
|
-
*/
|
|
43384
|
-
getControlPosition() {
|
|
43385
|
-
const parent = this.container.parentElement;
|
|
43386
|
-
if (!parent) return "top-right";
|
|
43387
|
-
if (parent.classList.contains("maplibregl-ctrl-top-left")) return "top-left";
|
|
43388
|
-
if (parent.classList.contains("maplibregl-ctrl-top-right")) return "top-right";
|
|
43389
|
-
if (parent.classList.contains("maplibregl-ctrl-bottom-left")) return "bottom-left";
|
|
43390
|
-
if (parent.classList.contains("maplibregl-ctrl-bottom-right")) return "bottom-right";
|
|
43391
|
-
return "top-right";
|
|
43392
|
-
}
|
|
43393
|
-
/**
|
|
43394
|
-
* Update the panel position based on button location and control corner
|
|
43395
|
-
* Positions the panel next to the button, expanding in the appropriate direction
|
|
43396
|
-
*/
|
|
43397
|
-
updatePanelPosition() {
|
|
43398
|
-
if (!this.button || !this.panel || !this.mapContainer) return;
|
|
43399
|
-
const buttonRect = this.button.getBoundingClientRect();
|
|
43400
|
-
const mapRect = this.mapContainer.getBoundingClientRect();
|
|
43401
|
-
const position = this.getControlPosition();
|
|
43402
|
-
const buttonTop = buttonRect.top - mapRect.top;
|
|
43403
|
-
const buttonBottom = mapRect.bottom - buttonRect.bottom;
|
|
43404
|
-
const buttonLeft = buttonRect.left - mapRect.left;
|
|
43405
|
-
const buttonRight = mapRect.right - buttonRect.right;
|
|
43406
|
-
const panelGap = 5;
|
|
43407
|
-
this.panel.style.top = "";
|
|
43408
|
-
this.panel.style.bottom = "";
|
|
43409
|
-
this.panel.style.left = "";
|
|
43410
|
-
this.panel.style.right = "";
|
|
43411
|
-
switch (position) {
|
|
43412
|
-
case "top-left":
|
|
43413
|
-
this.panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;
|
|
43414
|
-
this.panel.style.left = `${buttonLeft}px`;
|
|
43415
|
-
break;
|
|
43416
|
-
case "top-right":
|
|
43417
|
-
this.panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;
|
|
43418
|
-
this.panel.style.right = `${buttonRight}px`;
|
|
43419
|
-
break;
|
|
43420
|
-
case "bottom-left":
|
|
43421
|
-
this.panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;
|
|
43422
|
-
this.panel.style.left = `${buttonLeft}px`;
|
|
43423
|
-
break;
|
|
43424
|
-
case "bottom-right":
|
|
43425
|
-
this.panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;
|
|
43426
|
-
this.panel.style.right = `${buttonRight}px`;
|
|
43427
|
-
break;
|
|
43428
|
-
}
|
|
43429
|
-
}
|
|
43430
|
-
/**
|
|
43431
|
-
* Create action buttons for Show All / Hide All
|
|
43432
|
-
*/
|
|
43433
|
-
createActionButtons() {
|
|
43434
|
-
const container = document.createElement("div");
|
|
43435
|
-
container.className = "layer-control-actions";
|
|
43436
|
-
const showAllBtn = document.createElement("button");
|
|
43437
|
-
showAllBtn.type = "button";
|
|
43438
|
-
showAllBtn.className = "layer-control-action-btn";
|
|
43439
|
-
showAllBtn.textContent = "Show All";
|
|
43440
|
-
showAllBtn.title = "Show all layers";
|
|
43441
|
-
showAllBtn.addEventListener("click", () => this.setAllLayersVisibility(true));
|
|
43442
|
-
const hideAllBtn = document.createElement("button");
|
|
43443
|
-
hideAllBtn.type = "button";
|
|
43444
|
-
hideAllBtn.className = "layer-control-action-btn";
|
|
43445
|
-
hideAllBtn.textContent = "Hide All";
|
|
43446
|
-
hideAllBtn.title = "Hide all layers";
|
|
43447
|
-
hideAllBtn.addEventListener("click", () => this.setAllLayersVisibility(false));
|
|
43448
|
-
container.appendChild(showAllBtn);
|
|
43449
|
-
container.appendChild(hideAllBtn);
|
|
43450
|
-
return container;
|
|
43451
|
-
}
|
|
43452
|
-
/**
|
|
43453
|
-
* Set visibility of all layers
|
|
43454
|
-
*/
|
|
43455
|
-
setAllLayersVisibility(visible) {
|
|
43456
|
-
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
43457
|
-
this.toggleLayerVisibility(layerId, visible);
|
|
43458
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
43459
|
-
if (itemEl) {
|
|
43460
|
-
const checkbox = itemEl.querySelector(".layer-control-checkbox");
|
|
43461
|
-
if (checkbox) {
|
|
43462
|
-
checkbox.checked = visible;
|
|
43463
|
-
checkbox.indeterminate = false;
|
|
43464
|
-
}
|
|
43465
|
-
}
|
|
43466
|
-
});
|
|
43467
|
-
}
|
|
43468
|
-
/**
|
|
43469
|
-
* Create the panel header with title and width control
|
|
43470
|
-
*/
|
|
43471
|
-
createPanelHeader() {
|
|
43472
|
-
const header = document.createElement("div");
|
|
43473
|
-
header.className = "layer-control-panel-header";
|
|
43474
|
-
const title2 = document.createElement("span");
|
|
43475
|
-
title2.className = "layer-control-panel-title";
|
|
43476
|
-
title2.textContent = "Layers";
|
|
43477
|
-
header.appendChild(title2);
|
|
43478
|
-
const widthControl = this.createWidthControl();
|
|
43479
|
-
header.appendChild(widthControl);
|
|
43480
|
-
return header;
|
|
43481
|
-
}
|
|
43482
|
-
/**
|
|
43483
|
-
* Create the width control slider
|
|
43484
|
-
*/
|
|
43485
|
-
createWidthControl() {
|
|
43486
|
-
const widthControl = document.createElement("label");
|
|
43487
|
-
widthControl.className = "layer-control-width-control";
|
|
43488
|
-
widthControl.title = "Adjust layer panel width";
|
|
43489
|
-
const widthLabel = document.createElement("span");
|
|
43490
|
-
widthLabel.textContent = "Width";
|
|
43491
|
-
widthControl.appendChild(widthLabel);
|
|
43492
|
-
const widthSlider = document.createElement("div");
|
|
43493
|
-
widthSlider.className = "layer-control-width-slider";
|
|
43494
|
-
widthSlider.setAttribute("role", "slider");
|
|
43495
|
-
widthSlider.setAttribute("aria-valuemin", String(this.minPanelWidth));
|
|
43496
|
-
widthSlider.setAttribute("aria-valuemax", String(this.maxPanelWidth));
|
|
43497
|
-
widthSlider.setAttribute("aria-valuenow", String(this.state.panelWidth));
|
|
43498
|
-
widthSlider.setAttribute("aria-valuestep", "10");
|
|
43499
|
-
widthSlider.setAttribute("aria-label", "Layer panel width");
|
|
43500
|
-
widthSlider.tabIndex = 0;
|
|
43501
|
-
const widthTrack = document.createElement("div");
|
|
43502
|
-
widthTrack.className = "layer-control-width-track";
|
|
43503
|
-
const widthThumb = document.createElement("div");
|
|
43504
|
-
widthThumb.className = "layer-control-width-thumb";
|
|
43505
|
-
widthSlider.appendChild(widthTrack);
|
|
43506
|
-
widthSlider.appendChild(widthThumb);
|
|
43507
|
-
this.widthSliderEl = widthSlider;
|
|
43508
|
-
this.widthThumbEl = widthThumb;
|
|
43509
|
-
const widthValue = document.createElement("span");
|
|
43510
|
-
widthValue.className = "layer-control-width-value";
|
|
43511
|
-
this.widthValueEl = widthValue;
|
|
43512
|
-
widthControl.appendChild(widthSlider);
|
|
43513
|
-
widthControl.appendChild(widthValue);
|
|
43514
|
-
this.updateWidthDisplay();
|
|
43515
|
-
this.setupWidthSliderEvents(widthSlider);
|
|
43516
|
-
return widthControl;
|
|
43517
|
-
}
|
|
43518
|
-
/**
|
|
43519
|
-
* Setup event listeners for width slider
|
|
43520
|
-
*/
|
|
43521
|
-
setupWidthSliderEvents(widthSlider) {
|
|
43522
|
-
widthSlider.addEventListener("pointerdown", (event) => {
|
|
43523
|
-
event.preventDefault();
|
|
43524
|
-
const rect = widthSlider.getBoundingClientRect();
|
|
43525
|
-
this.widthDragRectWidth = rect.width || 1;
|
|
43526
|
-
this.widthDragStartX = event.clientX;
|
|
43527
|
-
this.widthDragStartWidth = this.state.panelWidth;
|
|
43528
|
-
this.isWidthSliderActive = true;
|
|
43529
|
-
widthSlider.setPointerCapture(event.pointerId);
|
|
43530
|
-
this.updateWidthFromPointer(event, true);
|
|
43531
|
-
});
|
|
43532
|
-
widthSlider.addEventListener("pointermove", (event) => {
|
|
43533
|
-
if (!this.isWidthSliderActive) return;
|
|
43534
|
-
this.updateWidthFromPointer(event);
|
|
43535
|
-
});
|
|
43536
|
-
const endPointerDrag = (event) => {
|
|
43537
|
-
if (!this.isWidthSliderActive) return;
|
|
43538
|
-
if (event.pointerId !== void 0) {
|
|
43539
|
-
try {
|
|
43540
|
-
widthSlider.releasePointerCapture(event.pointerId);
|
|
43541
|
-
} catch (error) {
|
|
43542
|
-
}
|
|
43543
|
-
}
|
|
43544
|
-
this.isWidthSliderActive = false;
|
|
43545
|
-
this.widthDragRectWidth = null;
|
|
43546
|
-
this.widthDragStartX = null;
|
|
43547
|
-
this.widthDragStartWidth = null;
|
|
43548
|
-
this.updateWidthDisplay();
|
|
43549
|
-
};
|
|
43550
|
-
widthSlider.addEventListener("pointerup", endPointerDrag);
|
|
43551
|
-
widthSlider.addEventListener("pointercancel", endPointerDrag);
|
|
43552
|
-
widthSlider.addEventListener("lostpointercapture", endPointerDrag);
|
|
43553
|
-
widthSlider.addEventListener("keydown", (event) => {
|
|
43554
|
-
let handled = true;
|
|
43555
|
-
const step = event.shiftKey ? 20 : 10;
|
|
43556
|
-
switch (event.key) {
|
|
43557
|
-
case "ArrowLeft":
|
|
43558
|
-
case "ArrowDown":
|
|
43559
|
-
this.applyPanelWidth(this.state.panelWidth - step, true);
|
|
43560
|
-
break;
|
|
43561
|
-
case "ArrowRight":
|
|
43562
|
-
case "ArrowUp":
|
|
43563
|
-
this.applyPanelWidth(this.state.panelWidth + step, true);
|
|
43564
|
-
break;
|
|
43565
|
-
case "Home":
|
|
43566
|
-
this.applyPanelWidth(this.minPanelWidth, true);
|
|
43567
|
-
break;
|
|
43568
|
-
case "End":
|
|
43569
|
-
this.applyPanelWidth(this.maxPanelWidth, true);
|
|
43570
|
-
break;
|
|
43571
|
-
case "PageUp":
|
|
43572
|
-
this.applyPanelWidth(this.state.panelWidth + 50, true);
|
|
43573
|
-
break;
|
|
43574
|
-
case "PageDown":
|
|
43575
|
-
this.applyPanelWidth(this.state.panelWidth - 50, true);
|
|
43576
|
-
break;
|
|
43577
|
-
default:
|
|
43578
|
-
handled = false;
|
|
43579
|
-
}
|
|
43580
|
-
if (handled) {
|
|
43581
|
-
event.preventDefault();
|
|
43582
|
-
this.updateWidthDisplay();
|
|
43583
|
-
}
|
|
43584
|
-
});
|
|
43585
|
-
}
|
|
43586
|
-
/**
|
|
43587
|
-
* Update panel width from pointer event
|
|
43588
|
-
*/
|
|
43589
|
-
updateWidthFromPointer(event, resetBaseline = false) {
|
|
43590
|
-
if (!this.widthSliderEl) return;
|
|
43591
|
-
const sliderWidth = this.widthDragRectWidth || this.widthSliderEl.getBoundingClientRect().width || 1;
|
|
43592
|
-
const widthRange = this.maxPanelWidth - this.minPanelWidth;
|
|
43593
|
-
let width;
|
|
43594
|
-
if (resetBaseline) {
|
|
43595
|
-
const rect = this.widthSliderEl.getBoundingClientRect();
|
|
43596
|
-
const relative = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0;
|
|
43597
|
-
const clampedRatio = Math.min(1, Math.max(0, relative));
|
|
43598
|
-
width = this.minPanelWidth + clampedRatio * widthRange;
|
|
43599
|
-
this.widthDragStartWidth = width;
|
|
43600
|
-
this.widthDragStartX = event.clientX;
|
|
43601
|
-
} else {
|
|
43602
|
-
const delta = event.clientX - (this.widthDragStartX || event.clientX);
|
|
43603
|
-
width = (this.widthDragStartWidth || this.state.panelWidth) + delta / sliderWidth * widthRange;
|
|
43604
|
-
}
|
|
43605
|
-
this.applyPanelWidth(width, this.isWidthSliderActive);
|
|
43606
|
-
}
|
|
43607
|
-
/**
|
|
43608
|
-
* Apply panel width (clamped to min/max)
|
|
43609
|
-
*/
|
|
43610
|
-
applyPanelWidth(width, immediate = false) {
|
|
43611
|
-
const clamped = Math.round(Math.min(this.maxPanelWidth, Math.max(this.minPanelWidth, width)));
|
|
43612
|
-
const applyWidth = () => {
|
|
43613
|
-
this.state.panelWidth = clamped;
|
|
43614
|
-
const px = `${clamped}px`;
|
|
43615
|
-
this.panel.style.width = px;
|
|
43616
|
-
this.updateWidthDisplay();
|
|
43617
|
-
};
|
|
43618
|
-
if (immediate) {
|
|
43619
|
-
applyWidth();
|
|
43620
|
-
return;
|
|
43621
|
-
}
|
|
43622
|
-
if (this.widthFrame) {
|
|
43623
|
-
cancelAnimationFrame(this.widthFrame);
|
|
43624
|
-
}
|
|
43625
|
-
this.widthFrame = requestAnimationFrame(() => {
|
|
43626
|
-
applyWidth();
|
|
43627
|
-
this.widthFrame = null;
|
|
43628
|
-
});
|
|
43629
|
-
}
|
|
43630
|
-
/**
|
|
43631
|
-
* Update width display (value label and thumb position)
|
|
43632
|
-
*/
|
|
43633
|
-
updateWidthDisplay() {
|
|
43634
|
-
if (this.widthValueEl) {
|
|
43635
|
-
this.widthValueEl.textContent = `${this.state.panelWidth}px`;
|
|
43636
|
-
}
|
|
43637
|
-
if (this.widthSliderEl) {
|
|
43638
|
-
this.widthSliderEl.setAttribute("aria-valuenow", String(this.state.panelWidth));
|
|
43639
|
-
const ratio = (this.state.panelWidth - this.minPanelWidth) / (this.maxPanelWidth - this.minPanelWidth || 1);
|
|
43640
|
-
if (this.widthThumbEl) {
|
|
43641
|
-
const sliderWidth = this.widthSliderEl.clientWidth;
|
|
43642
|
-
if (sliderWidth === 0) {
|
|
43643
|
-
requestAnimationFrame(() => this.updateWidthDisplay());
|
|
43644
|
-
return;
|
|
43645
|
-
}
|
|
43646
|
-
const thumbWidth = this.widthThumbEl.offsetWidth || 14;
|
|
43647
|
-
const padding = 16;
|
|
43648
|
-
const available = Math.max(0, sliderWidth - padding - thumbWidth);
|
|
43649
|
-
const clampedRatio = Math.min(1, Math.max(0, ratio));
|
|
43650
|
-
const leftPx = 8 + available * clampedRatio;
|
|
43651
|
-
this.widthThumbEl.style.left = `${leftPx}px`;
|
|
43652
|
-
}
|
|
43653
|
-
}
|
|
43654
|
-
}
|
|
43655
|
-
/**
|
|
43656
|
-
* Setup main event listeners
|
|
43657
|
-
*/
|
|
43658
|
-
setupEventListeners() {
|
|
43659
|
-
this.button.addEventListener("click", () => this.toggle());
|
|
43660
|
-
document.addEventListener("click", (e2) => {
|
|
43661
|
-
const target = e2.target;
|
|
43662
|
-
if (this.contextMenuEl && this.state.contextMenu.visible) {
|
|
43663
|
-
if (!this.contextMenuEl.contains(target)) {
|
|
43664
|
-
this.hideContextMenu();
|
|
43665
|
-
}
|
|
43666
|
-
}
|
|
43667
|
-
if (!this.container.contains(target) && !this.panel.contains(target)) {
|
|
43668
|
-
this.collapse();
|
|
43669
|
-
}
|
|
43670
|
-
});
|
|
43671
|
-
this.resizeHandler = () => {
|
|
43672
|
-
if (!this.state.collapsed) {
|
|
43673
|
-
this.updatePanelPosition();
|
|
43674
|
-
}
|
|
43675
|
-
};
|
|
43676
|
-
window.addEventListener("resize", this.resizeHandler);
|
|
43677
|
-
this.mapResizeHandler = () => {
|
|
43678
|
-
if (!this.state.collapsed) {
|
|
43679
|
-
this.updatePanelPosition();
|
|
43680
|
-
}
|
|
43681
|
-
};
|
|
43682
|
-
this.map.on("resize", this.mapResizeHandler);
|
|
43683
|
-
this.setupLayerChangeListeners();
|
|
43684
|
-
}
|
|
43685
|
-
/**
|
|
43686
|
-
* Setup listeners for map layer changes
|
|
43687
|
-
*/
|
|
43688
|
-
setupLayerChangeListeners() {
|
|
43689
|
-
this.map.on("styledata", () => {
|
|
43690
|
-
setTimeout(() => {
|
|
43691
|
-
this.updateLayerStatesFromMap();
|
|
43692
|
-
this.checkForNewLayers();
|
|
43693
|
-
}, 100);
|
|
43694
|
-
});
|
|
43695
|
-
this.map.on("data", (e2) => {
|
|
43696
|
-
if (e2.sourceDataType === "content") {
|
|
43697
|
-
setTimeout(() => {
|
|
43698
|
-
this.updateLayerStatesFromMap();
|
|
43699
|
-
this.checkForNewLayers();
|
|
43700
|
-
}, 100);
|
|
43701
|
-
}
|
|
43702
|
-
});
|
|
43703
|
-
this.map.on("sourcedata", (e2) => {
|
|
43704
|
-
if (e2.sourceDataType === "metadata") {
|
|
43705
|
-
setTimeout(() => {
|
|
43706
|
-
this.checkForNewLayers();
|
|
43707
|
-
}, 150);
|
|
43708
|
-
}
|
|
43709
|
-
});
|
|
43710
|
-
if (this.customLayerRegistry) {
|
|
43711
|
-
this.customLayerUnsubscribe = this.customLayerRegistry.onChange((event, layerId) => {
|
|
43712
|
-
if (event === "add" && layerId) {
|
|
43713
|
-
this.removedCustomLayerIds.delete(layerId);
|
|
43714
|
-
}
|
|
43715
|
-
setTimeout(() => this.checkForNewLayers(), 100);
|
|
43716
|
-
});
|
|
43717
|
-
}
|
|
43718
|
-
}
|
|
43719
|
-
/**
|
|
43720
|
-
* Toggle panel expanded/collapsed state
|
|
43721
|
-
*/
|
|
43722
|
-
toggle() {
|
|
43723
|
-
if (this.state.collapsed) {
|
|
43724
|
-
this.expand();
|
|
43725
|
-
} else {
|
|
43726
|
-
this.collapse();
|
|
43727
|
-
}
|
|
43728
|
-
}
|
|
43729
|
-
/**
|
|
43730
|
-
* Expand the panel
|
|
43731
|
-
*/
|
|
43732
|
-
expand() {
|
|
43733
|
-
this.state.collapsed = false;
|
|
43734
|
-
this.panel.classList.add("expanded");
|
|
43735
|
-
this.updatePanelPosition();
|
|
43736
|
-
}
|
|
43737
|
-
/**
|
|
43738
|
-
* Collapse the panel
|
|
43739
|
-
*/
|
|
43740
|
-
collapse() {
|
|
43741
|
-
this.state.collapsed = true;
|
|
43742
|
-
this.panel.classList.remove("expanded");
|
|
43743
|
-
}
|
|
43744
|
-
/**
|
|
43745
|
-
* Build layer items (called initially and when layers change)
|
|
43746
|
-
*/
|
|
43747
|
-
buildLayerItems() {
|
|
43748
|
-
const existingItems = this.panel.querySelectorAll(".layer-control-item");
|
|
43749
|
-
existingItems.forEach((item) => item.remove());
|
|
43750
|
-
this.styleEditors.clear();
|
|
43751
|
-
Object.entries(this.state.layerStates).forEach(([layerId, state]) => {
|
|
43752
|
-
if (this.targetLayers.length === 0 || this.targetLayers.includes(layerId)) {
|
|
43753
|
-
this.addLayerItem(layerId, state);
|
|
43754
|
-
}
|
|
43755
|
-
});
|
|
43756
|
-
}
|
|
43757
|
-
/**
|
|
43758
|
-
* Add a single layer item to the panel
|
|
43759
|
-
*/
|
|
43760
|
-
addLayerItem(layerId, state) {
|
|
43761
|
-
const item = document.createElement("div");
|
|
43762
|
-
item.className = "layer-control-item";
|
|
43763
|
-
item.setAttribute("data-layer-id", layerId);
|
|
43764
|
-
const row = document.createElement("div");
|
|
43765
|
-
row.className = "layer-control-row";
|
|
43766
|
-
if (this.enableDragAndDrop) {
|
|
43767
|
-
if (layerId === "Background") {
|
|
43768
|
-
const disabledHandle = this.createDisabledDragHandle();
|
|
43769
|
-
row.appendChild(disabledHandle);
|
|
43770
|
-
} else {
|
|
43771
|
-
const dragHandle = this.createDragHandle(layerId);
|
|
43772
|
-
row.appendChild(dragHandle);
|
|
43773
|
-
}
|
|
43774
|
-
}
|
|
43775
|
-
const checkbox = document.createElement("input");
|
|
43776
|
-
checkbox.type = "checkbox";
|
|
43777
|
-
checkbox.className = "layer-control-checkbox";
|
|
43778
|
-
checkbox.checked = state.visible;
|
|
43779
|
-
checkbox.addEventListener("change", () => {
|
|
43780
|
-
this.toggleLayerVisibility(layerId, checkbox.checked);
|
|
43781
|
-
});
|
|
43782
|
-
const displayName = this.state.customLayerNames.get(layerId) || state.name || layerId;
|
|
43783
|
-
const name = document.createElement("span");
|
|
43784
|
-
name.className = "layer-control-name";
|
|
43785
|
-
name.textContent = displayName;
|
|
43786
|
-
name.title = displayName;
|
|
43787
|
-
row.appendChild(checkbox);
|
|
43788
|
-
if (this.showLayerSymbol) {
|
|
43789
|
-
if (layerId === "Background") {
|
|
43790
|
-
const symbol = this.createBackgroundGroupSymbol();
|
|
43791
|
-
row.appendChild(symbol);
|
|
43792
|
-
} else {
|
|
43793
|
-
const symbol = this.createLayerSymbol(layerId);
|
|
43794
|
-
if (symbol) {
|
|
43795
|
-
row.appendChild(symbol);
|
|
43796
|
-
}
|
|
43797
|
-
}
|
|
43798
|
-
}
|
|
43799
|
-
row.appendChild(name);
|
|
43800
|
-
if (this.showOpacitySlider) {
|
|
43801
|
-
const opacity = document.createElement("input");
|
|
43802
|
-
opacity.type = "range";
|
|
43803
|
-
opacity.className = "layer-control-opacity";
|
|
43804
|
-
opacity.min = "0";
|
|
43805
|
-
opacity.max = "1";
|
|
43806
|
-
opacity.step = "0.01";
|
|
43807
|
-
opacity.value = String(state.opacity);
|
|
43808
|
-
opacity.title = `Opacity: ${Math.round(state.opacity * 100)}%`;
|
|
43809
|
-
opacity.addEventListener("mousedown", () => {
|
|
43810
|
-
this.state.userInteractingWithSlider = true;
|
|
43811
|
-
});
|
|
43812
|
-
opacity.addEventListener("mouseup", () => {
|
|
43813
|
-
this.state.userInteractingWithSlider = false;
|
|
43814
|
-
});
|
|
43815
|
-
opacity.addEventListener("input", () => {
|
|
43816
|
-
this.changeLayerOpacity(layerId, parseFloat(opacity.value));
|
|
43817
|
-
opacity.title = `Opacity: ${Math.round(parseFloat(opacity.value) * 100)}%`;
|
|
43818
|
-
});
|
|
43819
|
-
row.appendChild(opacity);
|
|
43820
|
-
}
|
|
43821
|
-
if (this.showStyleEditor) {
|
|
43822
|
-
if (layerId === "Background") {
|
|
43823
|
-
const legendButton = this.createBackgroundLegendButton();
|
|
43824
|
-
row.appendChild(legendButton);
|
|
43825
|
-
} else {
|
|
43826
|
-
const styleButton = this.createStyleButton(layerId);
|
|
43827
|
-
if (styleButton) {
|
|
43828
|
-
row.appendChild(styleButton);
|
|
43829
|
-
}
|
|
43830
|
-
}
|
|
43831
|
-
}
|
|
43832
|
-
item.appendChild(row);
|
|
43833
|
-
if (this.enableContextMenu && layerId !== "Background") {
|
|
43834
|
-
row.addEventListener("contextmenu", (e2) => {
|
|
43835
|
-
e2.preventDefault();
|
|
43836
|
-
e2.stopPropagation();
|
|
43837
|
-
this.showContextMenu(layerId, e2.clientX, e2.clientY);
|
|
43838
|
-
});
|
|
43839
|
-
}
|
|
43840
|
-
this.panel.appendChild(item);
|
|
43841
|
-
}
|
|
43842
|
-
/**
|
|
43843
|
-
* Create a symbol element for a layer
|
|
43844
|
-
* @param layerId The layer ID
|
|
43845
|
-
* @returns The symbol HTML element, or null if layer not found
|
|
43846
|
-
*/
|
|
43847
|
-
createLayerSymbol(layerId) {
|
|
43848
|
-
const layerState = this.state.layerStates[layerId];
|
|
43849
|
-
if (layerState == null ? void 0 : layerState.isCustomLayer) {
|
|
43850
|
-
const symbolType = layerState.customLayerType || "custom-raster";
|
|
43851
|
-
const color2 = "#4a90d9";
|
|
43852
|
-
const svgMarkup2 = createLayerSymbolSVG(symbolType, color2);
|
|
43853
|
-
const symbolContainer2 = document.createElement("span");
|
|
43854
|
-
symbolContainer2.className = "layer-control-symbol";
|
|
43855
|
-
symbolContainer2.innerHTML = svgMarkup2;
|
|
43856
|
-
symbolContainer2.title = `Layer type: ${symbolType}`;
|
|
43857
|
-
return symbolContainer2;
|
|
43858
|
-
}
|
|
43859
|
-
const layer = this.map.getLayer(layerId);
|
|
43860
|
-
if (!layer) return null;
|
|
43861
|
-
const layerType = layer.type;
|
|
43862
|
-
const color = getLayerColor(this.map, layerId, layerType);
|
|
43863
|
-
const svgMarkup = createLayerSymbolSVG(layerType, color);
|
|
43864
|
-
const symbolContainer = document.createElement("span");
|
|
43865
|
-
symbolContainer.className = "layer-control-symbol";
|
|
43866
|
-
symbolContainer.innerHTML = svgMarkup;
|
|
43867
|
-
symbolContainer.title = `Layer type: ${layerType}`;
|
|
43868
|
-
return symbolContainer;
|
|
43869
|
-
}
|
|
43870
|
-
/**
|
|
43871
|
-
* Create a symbol element for a background layer
|
|
43872
|
-
* @param layer The layer specification
|
|
43873
|
-
* @returns The symbol HTML element
|
|
43874
|
-
*/
|
|
43875
|
-
createBackgroundLayerSymbol(layer) {
|
|
43876
|
-
const color = getLayerColorFromSpec(layer);
|
|
43877
|
-
const svgMarkup = createLayerSymbolSVG(layer.type, color, { size: 14 });
|
|
43878
|
-
const symbolContainer = document.createElement("span");
|
|
43879
|
-
symbolContainer.className = "background-legend-layer-symbol";
|
|
43880
|
-
symbolContainer.innerHTML = svgMarkup;
|
|
43881
|
-
symbolContainer.title = `Layer type: ${layer.type}`;
|
|
43882
|
-
return symbolContainer;
|
|
43883
|
-
}
|
|
43884
|
-
/**
|
|
43885
|
-
* Create a symbol element for the Background layer group
|
|
43886
|
-
* Shows a stacked layers icon to represent multiple background layers
|
|
43887
|
-
* @returns The symbol HTML element
|
|
43888
|
-
*/
|
|
43889
|
-
createBackgroundGroupSymbol() {
|
|
43890
|
-
const svgMarkup = createBackgroundGroupSymbolSVG(16);
|
|
43891
|
-
const symbolContainer = document.createElement("span");
|
|
43892
|
-
symbolContainer.className = "layer-control-symbol";
|
|
43893
|
-
symbolContainer.innerHTML = svgMarkup;
|
|
43894
|
-
symbolContainer.title = "Background layers";
|
|
43895
|
-
return symbolContainer;
|
|
43896
|
-
}
|
|
43897
|
-
/**
|
|
43898
|
-
* Toggle layer visibility
|
|
43899
|
-
*/
|
|
43900
|
-
toggleLayerVisibility(layerId, visible) {
|
|
43901
|
-
var _a3;
|
|
43902
|
-
if (layerId === "Background") {
|
|
43903
|
-
this.toggleBackgroundVisibility(visible);
|
|
43904
|
-
return;
|
|
43905
|
-
}
|
|
43906
|
-
this.state.isStyleOperationInProgress = true;
|
|
43907
|
-
if (this.state.layerStates[layerId]) {
|
|
43908
|
-
this.state.layerStates[layerId].visible = visible;
|
|
43909
|
-
}
|
|
43910
|
-
if ((_a3 = this.customLayerRegistry) == null ? void 0 : _a3.setVisibility(layerId, visible)) {
|
|
43911
|
-
setTimeout(() => {
|
|
43912
|
-
this.state.isStyleOperationInProgress = false;
|
|
43913
|
-
}, 200);
|
|
43914
|
-
return;
|
|
43915
|
-
}
|
|
43916
|
-
this.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
|
|
43917
|
-
setTimeout(() => {
|
|
43918
|
-
this.state.isStyleOperationInProgress = false;
|
|
43919
|
-
}, 200);
|
|
43920
|
-
}
|
|
43921
|
-
/**
|
|
43922
|
-
* Change layer opacity
|
|
43923
|
-
*/
|
|
43924
|
-
changeLayerOpacity(layerId, opacity) {
|
|
43925
|
-
var _a3;
|
|
43926
|
-
if (layerId === "Background") {
|
|
43927
|
-
this.changeBackgroundOpacity(opacity);
|
|
43928
|
-
return;
|
|
43929
|
-
}
|
|
43930
|
-
this.state.isStyleOperationInProgress = true;
|
|
43931
|
-
if (this.state.layerStates[layerId]) {
|
|
43932
|
-
this.state.layerStates[layerId].opacity = opacity;
|
|
43933
|
-
}
|
|
43934
|
-
if ((_a3 = this.customLayerRegistry) == null ? void 0 : _a3.setOpacity(layerId, opacity)) {
|
|
43935
|
-
setTimeout(() => {
|
|
43936
|
-
this.state.isStyleOperationInProgress = false;
|
|
43937
|
-
}, 200);
|
|
43938
|
-
return;
|
|
43939
|
-
}
|
|
43940
|
-
const layerType = getLayerType(this.map, layerId);
|
|
43941
|
-
if (layerType) {
|
|
43942
|
-
setLayerOpacity(this.map, layerId, layerType, opacity);
|
|
43943
|
-
}
|
|
43944
|
-
setTimeout(() => {
|
|
43945
|
-
this.state.isStyleOperationInProgress = false;
|
|
43946
|
-
}, 200);
|
|
43947
|
-
}
|
|
43948
|
-
/**
|
|
43949
|
-
* Check if a layer is a user-added layer (vs basemap layer)
|
|
43950
|
-
* Used primarily for the background legend to determine which layers are background
|
|
43951
|
-
*/
|
|
43952
|
-
isUserAddedLayer(layerId) {
|
|
43953
|
-
if (this.state.layerStates[layerId] !== void 0 && layerId !== "Background") {
|
|
43954
|
-
return true;
|
|
43955
|
-
}
|
|
43956
|
-
if (this.basemapLayerIds !== null && this.basemapLayerIds.size > 0) {
|
|
43957
|
-
return !this.basemapLayerIds.has(layerId);
|
|
43958
|
-
}
|
|
43959
|
-
if (this.initialLayerIds !== null && !this.initialLayerIds.has(layerId)) {
|
|
43960
|
-
return true;
|
|
43961
|
-
}
|
|
43962
|
-
const layer = this.map.getLayer(layerId);
|
|
43963
|
-
if (layer) {
|
|
43964
|
-
const sourceId = layer.source;
|
|
43965
|
-
if (sourceId) {
|
|
43966
|
-
const userAddedSourceIds = this.detectUserAddedSources();
|
|
43967
|
-
return userAddedSourceIds.has(sourceId);
|
|
43968
|
-
}
|
|
43969
|
-
}
|
|
43970
|
-
return false;
|
|
43971
|
-
}
|
|
43972
|
-
/**
|
|
43973
|
-
* Toggle visibility for all background layers (basemap layers)
|
|
43974
|
-
*/
|
|
43975
|
-
toggleBackgroundVisibility(visible) {
|
|
43976
|
-
if (this.state.layerStates["Background"]) {
|
|
43977
|
-
this.state.layerStates["Background"].visible = visible;
|
|
43978
|
-
}
|
|
43979
|
-
const styleLayers = this.map.getStyle().layers || [];
|
|
43980
|
-
styleLayers.forEach((layer) => {
|
|
43981
|
-
if (!this.isUserAddedLayer(layer.id)) {
|
|
43982
|
-
this.state.backgroundLayerVisibility.set(layer.id, visible);
|
|
43983
|
-
this.map.setLayoutProperty(layer.id, "visibility", visible ? "visible" : "none");
|
|
43984
|
-
}
|
|
43985
|
-
});
|
|
43986
|
-
if (this.state.backgroundLegendOpen) {
|
|
43987
|
-
const legendPanel = this.panel.querySelector(".layer-control-background-legend");
|
|
43988
|
-
if (legendPanel) {
|
|
43989
|
-
const checkboxes = legendPanel.querySelectorAll(".background-legend-checkbox");
|
|
43990
|
-
checkboxes.forEach((checkbox) => {
|
|
43991
|
-
checkbox.checked = visible;
|
|
43992
|
-
});
|
|
43993
|
-
}
|
|
43994
|
-
}
|
|
43995
|
-
}
|
|
43996
|
-
/**
|
|
43997
|
-
* Change opacity for all background layers (basemap layers)
|
|
43998
|
-
*/
|
|
43999
|
-
changeBackgroundOpacity(opacity) {
|
|
44000
|
-
if (this.state.layerStates["Background"]) {
|
|
44001
|
-
this.state.layerStates["Background"].opacity = opacity;
|
|
44002
|
-
}
|
|
44003
|
-
const styleLayers = this.map.getStyle().layers || [];
|
|
44004
|
-
styleLayers.forEach((styleLayer) => {
|
|
44005
|
-
if (!this.isUserAddedLayer(styleLayer.id)) {
|
|
44006
|
-
const layerType = getLayerType(this.map, styleLayer.id);
|
|
44007
|
-
if (layerType) {
|
|
44008
|
-
setLayerOpacity(this.map, styleLayer.id, layerType, opacity);
|
|
44009
|
-
}
|
|
44010
|
-
}
|
|
44011
|
-
});
|
|
44012
|
-
}
|
|
44013
|
-
// ===== Background Legend Methods =====
|
|
44014
|
-
/**
|
|
44015
|
-
* Create legend button for Background layer
|
|
44016
|
-
*/
|
|
44017
|
-
createBackgroundLegendButton() {
|
|
44018
|
-
const button = document.createElement("button");
|
|
44019
|
-
button.className = "layer-control-style-button layer-control-background-legend-button";
|
|
44020
|
-
button.innerHTML = "⚙";
|
|
44021
|
-
button.title = "Show background layer details";
|
|
44022
|
-
button.setAttribute("aria-label", "Show background layer visibility controls");
|
|
44023
|
-
button.setAttribute("aria-expanded", String(this.state.backgroundLegendOpen));
|
|
44024
|
-
button.addEventListener("click", (e2) => {
|
|
44025
|
-
e2.stopPropagation();
|
|
44026
|
-
this.toggleBackgroundLegend();
|
|
44027
|
-
});
|
|
44028
|
-
return button;
|
|
44029
|
-
}
|
|
44030
|
-
/**
|
|
44031
|
-
* Toggle background legend panel visibility
|
|
44032
|
-
*/
|
|
44033
|
-
toggleBackgroundLegend() {
|
|
44034
|
-
if (this.state.backgroundLegendOpen) {
|
|
44035
|
-
this.closeBackgroundLegend();
|
|
44036
|
-
} else {
|
|
44037
|
-
this.openBackgroundLegend();
|
|
44038
|
-
}
|
|
44039
|
-
}
|
|
44040
|
-
/**
|
|
44041
|
-
* Open background legend panel
|
|
44042
|
-
*/
|
|
44043
|
-
openBackgroundLegend() {
|
|
44044
|
-
if (this.state.activeStyleEditor) {
|
|
44045
|
-
this.closeStyleEditor(this.state.activeStyleEditor);
|
|
44046
|
-
}
|
|
44047
|
-
const itemEl = this.panel.querySelector('[data-layer-id="Background"]');
|
|
44048
|
-
if (!itemEl) return;
|
|
44049
|
-
let legendPanel = itemEl.querySelector(".layer-control-background-legend");
|
|
44050
|
-
if (legendPanel) {
|
|
44051
|
-
const layerList = legendPanel.querySelector(".background-legend-layer-list");
|
|
44052
|
-
if (layerList) {
|
|
44053
|
-
this.populateBackgroundLayerList(layerList);
|
|
44054
|
-
}
|
|
44055
|
-
} else {
|
|
44056
|
-
legendPanel = this.createBackgroundLegendPanel();
|
|
44057
|
-
itemEl.appendChild(legendPanel);
|
|
44058
|
-
}
|
|
44059
|
-
this.state.backgroundLegendOpen = true;
|
|
44060
|
-
const button = itemEl.querySelector(".layer-control-background-legend-button");
|
|
44061
|
-
if (button) {
|
|
44062
|
-
button.setAttribute("aria-expanded", "true");
|
|
44063
|
-
button.classList.add("active");
|
|
44064
|
-
}
|
|
44065
|
-
setTimeout(() => {
|
|
44066
|
-
legendPanel == null ? void 0 : legendPanel.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
44067
|
-
}, 50);
|
|
44068
|
-
}
|
|
44069
|
-
/**
|
|
44070
|
-
* Close background legend panel
|
|
44071
|
-
*/
|
|
44072
|
-
closeBackgroundLegend() {
|
|
44073
|
-
const itemEl = this.panel.querySelector('[data-layer-id="Background"]');
|
|
44074
|
-
if (!itemEl) return;
|
|
44075
|
-
const legendPanel = itemEl.querySelector(".layer-control-background-legend");
|
|
44076
|
-
if (legendPanel) {
|
|
44077
|
-
legendPanel.remove();
|
|
44078
|
-
}
|
|
44079
|
-
this.state.backgroundLegendOpen = false;
|
|
44080
|
-
const button = itemEl.querySelector(".layer-control-background-legend-button");
|
|
44081
|
-
if (button) {
|
|
44082
|
-
button.setAttribute("aria-expanded", "false");
|
|
44083
|
-
button.classList.remove("active");
|
|
44084
|
-
}
|
|
44085
|
-
}
|
|
44086
|
-
/**
|
|
44087
|
-
* Create the background legend panel with individual layer controls
|
|
44088
|
-
*/
|
|
44089
|
-
createBackgroundLegendPanel() {
|
|
44090
|
-
const panel = document.createElement("div");
|
|
44091
|
-
panel.className = "layer-control-background-legend";
|
|
44092
|
-
const header = document.createElement("div");
|
|
44093
|
-
header.className = "background-legend-header";
|
|
44094
|
-
const title2 = document.createElement("span");
|
|
44095
|
-
title2.className = "background-legend-title";
|
|
44096
|
-
title2.textContent = "Background Layers";
|
|
44097
|
-
const closeBtn = document.createElement("button");
|
|
44098
|
-
closeBtn.className = "background-legend-close";
|
|
44099
|
-
closeBtn.innerHTML = "×";
|
|
44100
|
-
closeBtn.title = "Close";
|
|
44101
|
-
closeBtn.addEventListener("click", (e2) => {
|
|
44102
|
-
e2.stopPropagation();
|
|
44103
|
-
this.closeBackgroundLegend();
|
|
44104
|
-
});
|
|
44105
|
-
header.appendChild(title2);
|
|
44106
|
-
header.appendChild(closeBtn);
|
|
44107
|
-
const actionsRow = document.createElement("div");
|
|
44108
|
-
actionsRow.className = "background-legend-actions";
|
|
44109
|
-
const showAllBtn = document.createElement("button");
|
|
44110
|
-
showAllBtn.className = "background-legend-action-btn";
|
|
44111
|
-
showAllBtn.textContent = "Show All";
|
|
44112
|
-
showAllBtn.addEventListener("click", () => this.setAllBackgroundLayersVisibility(true));
|
|
44113
|
-
const hideAllBtn = document.createElement("button");
|
|
44114
|
-
hideAllBtn.className = "background-legend-action-btn";
|
|
44115
|
-
hideAllBtn.textContent = "Hide All";
|
|
44116
|
-
hideAllBtn.addEventListener("click", () => this.setAllBackgroundLayersVisibility(false));
|
|
44117
|
-
actionsRow.appendChild(showAllBtn);
|
|
44118
|
-
actionsRow.appendChild(hideAllBtn);
|
|
44119
|
-
const filterRow = document.createElement("div");
|
|
44120
|
-
filterRow.className = "background-legend-filter";
|
|
44121
|
-
const filterCheckbox = document.createElement("input");
|
|
44122
|
-
filterCheckbox.type = "checkbox";
|
|
44123
|
-
filterCheckbox.className = "background-legend-filter-checkbox";
|
|
44124
|
-
filterCheckbox.id = "background-legend-only-rendered";
|
|
44125
|
-
filterCheckbox.checked = this.state.onlyRenderedFilter;
|
|
44126
|
-
filterCheckbox.addEventListener("change", () => {
|
|
44127
|
-
this.state.onlyRenderedFilter = filterCheckbox.checked;
|
|
44128
|
-
const layerList2 = panel.querySelector(".background-legend-layer-list");
|
|
44129
|
-
if (layerList2) {
|
|
44130
|
-
this.populateBackgroundLayerList(layerList2);
|
|
44131
|
-
}
|
|
44132
|
-
});
|
|
44133
|
-
const filterLabel = document.createElement("label");
|
|
44134
|
-
filterLabel.className = "background-legend-filter-label";
|
|
44135
|
-
filterLabel.htmlFor = "background-legend-only-rendered";
|
|
44136
|
-
filterLabel.textContent = "Only rendered";
|
|
44137
|
-
filterRow.appendChild(filterCheckbox);
|
|
44138
|
-
filterRow.appendChild(filterLabel);
|
|
44139
|
-
const layerList = document.createElement("div");
|
|
44140
|
-
layerList.className = "background-legend-layer-list";
|
|
44141
|
-
this.populateBackgroundLayerList(layerList);
|
|
44142
|
-
panel.appendChild(header);
|
|
44143
|
-
panel.appendChild(actionsRow);
|
|
44144
|
-
panel.appendChild(filterRow);
|
|
44145
|
-
panel.appendChild(layerList);
|
|
44146
|
-
return panel;
|
|
44147
|
-
}
|
|
44148
|
-
/**
|
|
44149
|
-
* Check if a layer is currently rendered in the map viewport
|
|
44150
|
-
*/
|
|
44151
|
-
isLayerRendered(layerId) {
|
|
44152
|
-
try {
|
|
44153
|
-
const layer = this.map.getLayer(layerId);
|
|
44154
|
-
if (!layer) return false;
|
|
44155
|
-
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
44156
|
-
if (visibility === "none") return false;
|
|
44157
|
-
if (layer.type === "raster" || layer.type === "hillshade") {
|
|
44158
|
-
return true;
|
|
44159
|
-
}
|
|
44160
|
-
if (layer.type === "background") {
|
|
44161
|
-
return true;
|
|
44162
|
-
}
|
|
44163
|
-
const features = this.map.queryRenderedFeatures({ layers: [layerId] });
|
|
44164
|
-
return features.length > 0;
|
|
44165
|
-
} catch (error) {
|
|
44166
|
-
return true;
|
|
44167
|
-
}
|
|
44168
|
-
}
|
|
44169
|
-
/**
|
|
44170
|
-
* Populate the background layer list with individual layers
|
|
44171
|
-
*/
|
|
44172
|
-
populateBackgroundLayerList(container) {
|
|
44173
|
-
container.innerHTML = "";
|
|
44174
|
-
const styleLayers = this.map.getStyle().layers || [];
|
|
44175
|
-
styleLayers.forEach((layer) => {
|
|
44176
|
-
if (!this.isUserAddedLayer(layer.id)) {
|
|
44177
|
-
if (this.excludeDrawnLayers && this.isDrawnLayer(layer.id)) {
|
|
44178
|
-
return;
|
|
44179
|
-
}
|
|
44180
|
-
if (this.isExcludedByPattern(layer.id)) {
|
|
44181
|
-
return;
|
|
44182
|
-
}
|
|
44183
|
-
if (this.state.onlyRenderedFilter && !this.isLayerRendered(layer.id)) {
|
|
44184
|
-
return;
|
|
44185
|
-
}
|
|
44186
|
-
const layerRow = document.createElement("div");
|
|
44187
|
-
layerRow.className = "background-legend-layer-row";
|
|
44188
|
-
layerRow.setAttribute("data-background-layer-id", layer.id);
|
|
44189
|
-
const checkbox = document.createElement("input");
|
|
44190
|
-
checkbox.type = "checkbox";
|
|
44191
|
-
checkbox.className = "background-legend-checkbox";
|
|
44192
|
-
const visibility = this.map.getLayoutProperty(layer.id, "visibility");
|
|
44193
|
-
const isVisible = visibility !== "none";
|
|
44194
|
-
checkbox.checked = isVisible;
|
|
44195
|
-
this.state.backgroundLayerVisibility.set(layer.id, isVisible);
|
|
44196
|
-
checkbox.addEventListener("change", () => {
|
|
44197
|
-
this.toggleIndividualBackgroundLayer(layer.id, checkbox.checked);
|
|
44198
|
-
});
|
|
44199
|
-
const name = document.createElement("span");
|
|
44200
|
-
name.className = "background-legend-layer-name";
|
|
44201
|
-
name.textContent = this.generateFriendlyName(layer.id);
|
|
44202
|
-
name.title = layer.id;
|
|
44203
|
-
const typeIndicator = document.createElement("span");
|
|
44204
|
-
typeIndicator.className = "background-legend-layer-type";
|
|
44205
|
-
typeIndicator.textContent = layer.type;
|
|
44206
|
-
layerRow.appendChild(checkbox);
|
|
44207
|
-
if (this.showLayerSymbol) {
|
|
44208
|
-
const symbol = this.createBackgroundLayerSymbol(layer);
|
|
44209
|
-
if (symbol) {
|
|
44210
|
-
layerRow.appendChild(symbol);
|
|
44211
|
-
}
|
|
44212
|
-
}
|
|
44213
|
-
layerRow.appendChild(name);
|
|
44214
|
-
layerRow.appendChild(typeIndicator);
|
|
44215
|
-
container.appendChild(layerRow);
|
|
44216
|
-
}
|
|
44217
|
-
});
|
|
44218
|
-
if (container.children.length === 0) {
|
|
44219
|
-
const emptyMsg = document.createElement("p");
|
|
44220
|
-
emptyMsg.className = "background-legend-empty";
|
|
44221
|
-
emptyMsg.textContent = this.state.onlyRenderedFilter ? "No rendered layers in current view." : "No background layers found.";
|
|
44222
|
-
container.appendChild(emptyMsg);
|
|
44223
|
-
}
|
|
44224
|
-
}
|
|
44225
|
-
/**
|
|
44226
|
-
* Toggle visibility of an individual background layer
|
|
44227
|
-
*/
|
|
44228
|
-
toggleIndividualBackgroundLayer(layerId, visible) {
|
|
44229
|
-
this.state.backgroundLayerVisibility.set(layerId, visible);
|
|
44230
|
-
this.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
|
|
44231
|
-
this.updateBackgroundCheckboxState();
|
|
44232
|
-
}
|
|
44233
|
-
/**
|
|
44234
|
-
* Set visibility for all background layers
|
|
44235
|
-
*/
|
|
44236
|
-
setAllBackgroundLayersVisibility(visible) {
|
|
44237
|
-
const styleLayers = this.map.getStyle().layers || [];
|
|
44238
|
-
styleLayers.forEach((layer) => {
|
|
44239
|
-
if (!this.isUserAddedLayer(layer.id)) {
|
|
44240
|
-
this.state.backgroundLayerVisibility.set(layer.id, visible);
|
|
44241
|
-
this.map.setLayoutProperty(layer.id, "visibility", visible ? "visible" : "none");
|
|
44242
|
-
}
|
|
44243
|
-
});
|
|
44244
|
-
const legendPanel = this.panel.querySelector(".layer-control-background-legend");
|
|
44245
|
-
if (legendPanel) {
|
|
44246
|
-
const checkboxes = legendPanel.querySelectorAll(".background-legend-checkbox");
|
|
44247
|
-
checkboxes.forEach((checkbox) => {
|
|
44248
|
-
checkbox.checked = visible;
|
|
44249
|
-
});
|
|
44250
|
-
}
|
|
44251
|
-
this.updateBackgroundCheckboxState();
|
|
44252
|
-
}
|
|
44253
|
-
/**
|
|
44254
|
-
* Update the main Background checkbox based on individual layer states
|
|
44255
|
-
*/
|
|
44256
|
-
updateBackgroundCheckboxState() {
|
|
44257
|
-
const styleLayers = this.map.getStyle().layers || [];
|
|
44258
|
-
let anyVisible = false;
|
|
44259
|
-
let allVisible = true;
|
|
44260
|
-
styleLayers.forEach((layer) => {
|
|
44261
|
-
if (!this.isUserAddedLayer(layer.id)) {
|
|
44262
|
-
const visible = this.state.backgroundLayerVisibility.get(layer.id);
|
|
44263
|
-
if (visible === true) anyVisible = true;
|
|
44264
|
-
if (visible === false) allVisible = false;
|
|
44265
|
-
}
|
|
44266
|
-
});
|
|
44267
|
-
const backgroundItem = this.panel.querySelector('[data-layer-id="Background"]');
|
|
44268
|
-
if (backgroundItem) {
|
|
44269
|
-
const checkbox = backgroundItem.querySelector(".layer-control-checkbox");
|
|
44270
|
-
if (checkbox) {
|
|
44271
|
-
checkbox.checked = anyVisible;
|
|
44272
|
-
checkbox.indeterminate = anyVisible && !allVisible;
|
|
44273
|
-
}
|
|
44274
|
-
}
|
|
44275
|
-
if (this.state.layerStates["Background"]) {
|
|
44276
|
-
this.state.layerStates["Background"].visible = anyVisible;
|
|
44277
|
-
}
|
|
44278
|
-
}
|
|
44279
|
-
/**
|
|
44280
|
-
* Create style button for a layer
|
|
44281
|
-
*/
|
|
44282
|
-
createStyleButton(layerId) {
|
|
44283
|
-
if (layerId === "Background") {
|
|
44284
|
-
return null;
|
|
44285
|
-
}
|
|
44286
|
-
const layerState = this.state.layerStates[layerId];
|
|
44287
|
-
const isCustomLayer = (layerState == null ? void 0 : layerState.isCustomLayer) === true;
|
|
44288
|
-
const button = document.createElement("button");
|
|
44289
|
-
button.className = "layer-control-style-button";
|
|
44290
|
-
button.innerHTML = "⚙";
|
|
44291
|
-
if (isCustomLayer) {
|
|
44292
|
-
button.title = "Layer info (style editing not available)";
|
|
44293
|
-
button.setAttribute("aria-label", `Layer info for ${layerId}`);
|
|
44294
|
-
} else {
|
|
44295
|
-
button.title = "Edit layer style";
|
|
44296
|
-
button.setAttribute("aria-label", `Edit style for ${layerId}`);
|
|
44297
|
-
}
|
|
44298
|
-
button.addEventListener("click", (e2) => {
|
|
44299
|
-
e2.stopPropagation();
|
|
44300
|
-
this.toggleStyleEditor(layerId);
|
|
44301
|
-
});
|
|
44302
|
-
return button;
|
|
44303
|
-
}
|
|
44304
|
-
/**
|
|
44305
|
-
* Toggle style editor for a layer
|
|
44306
|
-
*/
|
|
44307
|
-
toggleStyleEditor(layerId) {
|
|
44308
|
-
if (this.state.activeStyleEditor === layerId) {
|
|
44309
|
-
this.closeStyleEditor(layerId);
|
|
44310
|
-
return;
|
|
44311
|
-
}
|
|
44312
|
-
if (this.state.activeStyleEditor) {
|
|
44313
|
-
this.closeStyleEditor(this.state.activeStyleEditor);
|
|
44314
|
-
}
|
|
44315
|
-
this.openStyleEditor(layerId);
|
|
44316
|
-
}
|
|
44317
|
-
/**
|
|
44318
|
-
* Open style editor for a layer
|
|
44319
|
-
*/
|
|
44320
|
-
openStyleEditor(layerId) {
|
|
44321
|
-
var _a3;
|
|
44322
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
44323
|
-
if (!itemEl) return;
|
|
44324
|
-
const layerState = this.state.layerStates[layerId];
|
|
44325
|
-
if (layerState == null ? void 0 : layerState.isCustomLayer) {
|
|
44326
|
-
const nativeLayerIds = (_a3 = this.customLayerRegistry) == null ? void 0 : _a3.getNativeLayerIds(layerId);
|
|
44327
|
-
if (nativeLayerIds && nativeLayerIds.length > 0) {
|
|
44328
|
-
for (const nativeId of nativeLayerIds) {
|
|
44329
|
-
if (!this.state.originalStyles.has(nativeId)) {
|
|
44330
|
-
const nativeLayer = this.map.getLayer(nativeId);
|
|
44331
|
-
if (nativeLayer) {
|
|
44332
|
-
cacheOriginalLayerStyle(this.map, nativeId, this.state.originalStyles);
|
|
44333
|
-
}
|
|
44334
|
-
}
|
|
44335
|
-
}
|
|
44336
|
-
const editor3 = this.createNativeSubLayerStyleEditor(layerId, nativeLayerIds);
|
|
44337
|
-
if (editor3) {
|
|
44338
|
-
itemEl.appendChild(editor3);
|
|
44339
|
-
this.styleEditors.set(layerId, editor3);
|
|
44340
|
-
this.state.activeStyleEditor = layerId;
|
|
44341
|
-
setTimeout(() => {
|
|
44342
|
-
editor3.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
44343
|
-
}, 50);
|
|
44344
|
-
return;
|
|
44345
|
-
}
|
|
44346
|
-
}
|
|
44347
|
-
const editor2 = this.createCustomLayerInfoPanel(layerId);
|
|
44348
|
-
itemEl.appendChild(editor2);
|
|
44349
|
-
this.styleEditors.set(layerId, editor2);
|
|
44350
|
-
this.state.activeStyleEditor = layerId;
|
|
44351
|
-
setTimeout(() => {
|
|
44352
|
-
editor2.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
44353
|
-
}, 50);
|
|
44354
|
-
return;
|
|
44355
|
-
}
|
|
44356
|
-
if (!this.state.originalStyles.has(layerId)) {
|
|
44357
|
-
const layer = this.map.getLayer(layerId);
|
|
44358
|
-
if (layer) {
|
|
44359
|
-
cacheOriginalLayerStyle(this.map, layerId, this.state.originalStyles);
|
|
44360
|
-
}
|
|
44361
|
-
}
|
|
44362
|
-
const editor = this.createStyleEditor(layerId);
|
|
44363
|
-
if (!editor) return;
|
|
44364
|
-
itemEl.appendChild(editor);
|
|
44365
|
-
this.styleEditors.set(layerId, editor);
|
|
44366
|
-
this.state.activeStyleEditor = layerId;
|
|
44367
|
-
setTimeout(() => {
|
|
44368
|
-
editor.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
44369
|
-
}, 50);
|
|
44370
|
-
}
|
|
44371
|
-
/**
|
|
44372
|
-
* Create info panel for custom layers (style editing not supported)
|
|
44373
|
-
*/
|
|
44374
|
-
createCustomLayerInfoPanel(layerId) {
|
|
44375
|
-
const editor = document.createElement("div");
|
|
44376
|
-
editor.className = "layer-control-style-editor layer-control-custom-info";
|
|
44377
|
-
const header = document.createElement("div");
|
|
44378
|
-
header.className = "style-editor-header";
|
|
44379
|
-
const title2 = document.createElement("span");
|
|
44380
|
-
title2.className = "style-editor-title";
|
|
44381
|
-
title2.textContent = "Layer Info";
|
|
44382
|
-
const closeBtn = document.createElement("button");
|
|
44383
|
-
closeBtn.className = "style-editor-close";
|
|
44384
|
-
closeBtn.innerHTML = "×";
|
|
44385
|
-
closeBtn.title = "Close";
|
|
44386
|
-
closeBtn.addEventListener("click", (e2) => {
|
|
44387
|
-
e2.stopPropagation();
|
|
44388
|
-
this.closeStyleEditor(layerId);
|
|
44389
|
-
});
|
|
44390
|
-
header.appendChild(title2);
|
|
44391
|
-
header.appendChild(closeBtn);
|
|
44392
|
-
const content = document.createElement("div");
|
|
44393
|
-
content.className = "style-editor-controls";
|
|
44394
|
-
const infoText = document.createElement("p");
|
|
44395
|
-
infoText.className = "layer-control-custom-info-text";
|
|
44396
|
-
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.`;
|
|
44397
|
-
content.appendChild(infoText);
|
|
44398
|
-
const actions = document.createElement("div");
|
|
44399
|
-
actions.className = "style-editor-actions";
|
|
44400
|
-
const removeBtn = document.createElement("button");
|
|
44401
|
-
removeBtn.className = "style-editor-button style-editor-button-remove";
|
|
44402
|
-
removeBtn.textContent = "Remove";
|
|
44403
|
-
removeBtn.title = "Remove layer from map";
|
|
44404
|
-
removeBtn.addEventListener("click", (e2) => {
|
|
44405
|
-
e2.stopPropagation();
|
|
44406
|
-
this.showRemoveConfirmation(editor, () => {
|
|
44407
|
-
this.closeStyleEditor(layerId);
|
|
44408
|
-
this.removeLayer(layerId);
|
|
44409
|
-
});
|
|
44410
|
-
});
|
|
44411
|
-
const closeActionBtn = document.createElement("button");
|
|
44412
|
-
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
44413
|
-
closeActionBtn.textContent = "Close";
|
|
44414
|
-
closeActionBtn.addEventListener("click", (e2) => {
|
|
44415
|
-
e2.stopPropagation();
|
|
44416
|
-
this.closeStyleEditor(layerId);
|
|
44417
|
-
});
|
|
44418
|
-
actions.appendChild(removeBtn);
|
|
44419
|
-
actions.appendChild(closeActionBtn);
|
|
44420
|
-
editor.appendChild(header);
|
|
44421
|
-
editor.appendChild(content);
|
|
44422
|
-
editor.appendChild(actions);
|
|
44423
|
-
return editor;
|
|
44424
|
-
}
|
|
44425
|
-
/**
|
|
44426
|
-
* Create a combined style editor for custom layers with native MapLibre sublayers.
|
|
44427
|
-
* Groups controls by sublayer type (fill, line, circle, etc.).
|
|
44428
|
-
*/
|
|
44429
|
-
createNativeSubLayerStyleEditor(layerId, nativeLayerIds) {
|
|
44430
|
-
const layersByType = /* @__PURE__ */ new Map();
|
|
44431
|
-
for (const nativeId of nativeLayerIds) {
|
|
44432
|
-
const layer = this.map.getLayer(nativeId);
|
|
44433
|
-
if (layer) {
|
|
44434
|
-
const type2 = layer.type;
|
|
44435
|
-
if (!layersByType.has(type2)) {
|
|
44436
|
-
layersByType.set(type2, []);
|
|
44437
|
-
}
|
|
44438
|
-
layersByType.get(type2).push(nativeId);
|
|
44439
|
-
}
|
|
44440
|
-
}
|
|
44441
|
-
if (layersByType.size === 0) return null;
|
|
44442
|
-
const editor = document.createElement("div");
|
|
44443
|
-
editor.className = "layer-control-style-editor";
|
|
44444
|
-
const header = document.createElement("div");
|
|
44445
|
-
header.className = "style-editor-header";
|
|
44446
|
-
const title2 = document.createElement("span");
|
|
44447
|
-
title2.className = "style-editor-title";
|
|
44448
|
-
title2.textContent = "Edit Style";
|
|
44449
|
-
const closeBtn = document.createElement("button");
|
|
44450
|
-
closeBtn.className = "style-editor-close";
|
|
44451
|
-
closeBtn.innerHTML = "×";
|
|
44452
|
-
closeBtn.title = "Close";
|
|
44453
|
-
closeBtn.addEventListener("click", (e2) => {
|
|
44454
|
-
e2.stopPropagation();
|
|
44455
|
-
this.closeStyleEditor(layerId);
|
|
44456
|
-
});
|
|
44457
|
-
header.appendChild(title2);
|
|
44458
|
-
header.appendChild(closeBtn);
|
|
44459
|
-
editor.appendChild(header);
|
|
44460
|
-
const controls = document.createElement("div");
|
|
44461
|
-
controls.className = "style-editor-controls";
|
|
44462
|
-
const typeLabels = {
|
|
44463
|
-
fill: "Fill",
|
|
44464
|
-
line: "Line",
|
|
44465
|
-
circle: "Circle",
|
|
44466
|
-
symbol: "Symbol",
|
|
44467
|
-
raster: "Raster"
|
|
44468
|
-
};
|
|
44469
|
-
for (const [type2, ids] of layersByType) {
|
|
44470
|
-
if (layersByType.size > 1) {
|
|
44471
|
-
const sectionHeader = document.createElement("div");
|
|
44472
|
-
sectionHeader.className = "style-editor-section-header";
|
|
44473
|
-
sectionHeader.textContent = typeLabels[type2] || type2;
|
|
44474
|
-
controls.appendChild(sectionHeader);
|
|
44475
|
-
}
|
|
44476
|
-
const primaryId = ids[0];
|
|
44477
|
-
this.addStyleControlsForNativeGroup(controls, ids, primaryId, type2);
|
|
44478
|
-
}
|
|
44479
|
-
const actions = document.createElement("div");
|
|
44480
|
-
actions.className = "style-editor-actions";
|
|
44481
|
-
const resetBtn = document.createElement("button");
|
|
44482
|
-
resetBtn.className = "style-editor-button style-editor-button-reset";
|
|
44483
|
-
resetBtn.textContent = "Reset";
|
|
44484
|
-
resetBtn.addEventListener("click", (e2) => {
|
|
44485
|
-
e2.stopPropagation();
|
|
44486
|
-
for (const nativeId of nativeLayerIds) {
|
|
44487
|
-
restoreOriginalStyle(this.map, nativeId, this.state.originalStyles);
|
|
44488
|
-
}
|
|
44489
|
-
this.closeStyleEditor(layerId);
|
|
44490
|
-
this.openStyleEditor(layerId);
|
|
44491
|
-
});
|
|
44492
|
-
const removeBtn = document.createElement("button");
|
|
44493
|
-
removeBtn.className = "style-editor-button style-editor-button-remove";
|
|
44494
|
-
removeBtn.textContent = "Remove";
|
|
44495
|
-
removeBtn.title = "Remove layer from map";
|
|
44496
|
-
removeBtn.addEventListener("click", (e2) => {
|
|
44497
|
-
e2.stopPropagation();
|
|
44498
|
-
this.showRemoveConfirmation(editor, () => {
|
|
44499
|
-
this.closeStyleEditor(layerId);
|
|
44500
|
-
this.removeLayer(layerId);
|
|
44501
|
-
});
|
|
44502
|
-
});
|
|
44503
|
-
const closeActionBtn = document.createElement("button");
|
|
44504
|
-
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
44505
|
-
closeActionBtn.textContent = "Close";
|
|
44506
|
-
closeActionBtn.addEventListener("click", (e2) => {
|
|
44507
|
-
e2.stopPropagation();
|
|
44508
|
-
this.closeStyleEditor(layerId);
|
|
44509
|
-
});
|
|
44510
|
-
actions.appendChild(resetBtn);
|
|
44511
|
-
actions.appendChild(removeBtn);
|
|
44512
|
-
actions.appendChild(closeActionBtn);
|
|
44513
|
-
editor.appendChild(controls);
|
|
44514
|
-
editor.appendChild(actions);
|
|
44515
|
-
return editor;
|
|
44516
|
-
}
|
|
44517
|
-
/**
|
|
44518
|
-
* Add style controls for a group of native layers of the same type.
|
|
44519
|
-
* Changes to any control are applied to all layers in the group.
|
|
44520
|
-
*/
|
|
44521
|
-
addStyleControlsForNativeGroup(container, layerIds, primaryLayerId, layerType) {
|
|
44522
|
-
this.nativeLayerGroups.set(primaryLayerId, layerIds);
|
|
44523
|
-
this.addStyleControlsForLayerType(container, primaryLayerId, layerType);
|
|
44524
|
-
}
|
|
44525
|
-
/**
|
|
44526
|
-
* Close style editor for a layer
|
|
44527
|
-
*/
|
|
44528
|
-
closeStyleEditor(layerId) {
|
|
44529
|
-
const editor = this.styleEditors.get(layerId);
|
|
44530
|
-
if (editor) {
|
|
44531
|
-
editor.remove();
|
|
44532
|
-
this.styleEditors.delete(layerId);
|
|
44533
|
-
}
|
|
44534
|
-
this.nativeLayerGroups.clear();
|
|
44535
|
-
if (this.state.activeStyleEditor === layerId) {
|
|
44536
|
-
this.state.activeStyleEditor = null;
|
|
44537
|
-
}
|
|
44538
|
-
}
|
|
44539
|
-
/**
|
|
44540
|
-
* Create style editor UI
|
|
44541
|
-
*/
|
|
44542
|
-
createStyleEditor(layerId) {
|
|
44543
|
-
const layer = this.map.getLayer(layerId);
|
|
44544
|
-
if (!layer) return null;
|
|
44545
|
-
const editor = document.createElement("div");
|
|
44546
|
-
editor.className = "layer-control-style-editor";
|
|
44547
|
-
const header = document.createElement("div");
|
|
44548
|
-
header.className = "style-editor-header";
|
|
44549
|
-
const title2 = document.createElement("span");
|
|
44550
|
-
title2.className = "style-editor-title";
|
|
44551
|
-
title2.textContent = "Edit Style";
|
|
44552
|
-
const closeBtn = document.createElement("button");
|
|
44553
|
-
closeBtn.className = "style-editor-close";
|
|
44554
|
-
closeBtn.innerHTML = "×";
|
|
44555
|
-
closeBtn.title = "Close";
|
|
44556
|
-
closeBtn.addEventListener("click", (e2) => {
|
|
44557
|
-
e2.stopPropagation();
|
|
44558
|
-
this.closeStyleEditor(layerId);
|
|
44559
|
-
});
|
|
44560
|
-
header.appendChild(title2);
|
|
44561
|
-
header.appendChild(closeBtn);
|
|
44562
|
-
const controls = document.createElement("div");
|
|
44563
|
-
controls.className = "style-editor-controls";
|
|
44564
|
-
const layerType = layer.type;
|
|
44565
|
-
this.addStyleControlsForLayerType(controls, layerId, layerType);
|
|
44566
|
-
const actions = document.createElement("div");
|
|
44567
|
-
actions.className = "style-editor-actions";
|
|
44568
|
-
const resetBtn = document.createElement("button");
|
|
44569
|
-
resetBtn.className = "style-editor-button style-editor-button-reset";
|
|
44570
|
-
resetBtn.textContent = "Reset";
|
|
44571
|
-
resetBtn.addEventListener("click", (e2) => {
|
|
44572
|
-
e2.stopPropagation();
|
|
44573
|
-
this.resetLayerStyle(layerId);
|
|
44574
|
-
});
|
|
44575
|
-
const removeBtn = document.createElement("button");
|
|
44576
|
-
removeBtn.className = "style-editor-button style-editor-button-remove";
|
|
44577
|
-
removeBtn.textContent = "Remove";
|
|
44578
|
-
removeBtn.title = "Remove layer from map";
|
|
44579
|
-
removeBtn.addEventListener("click", (e2) => {
|
|
44580
|
-
e2.stopPropagation();
|
|
44581
|
-
this.showRemoveConfirmation(editor, () => {
|
|
44582
|
-
this.closeStyleEditor(layerId);
|
|
44583
|
-
this.removeLayer(layerId);
|
|
44584
|
-
});
|
|
44585
|
-
});
|
|
44586
|
-
const closeActionBtn = document.createElement("button");
|
|
44587
|
-
closeActionBtn.className = "style-editor-button style-editor-button-close";
|
|
44588
|
-
closeActionBtn.textContent = "Close";
|
|
44589
|
-
closeActionBtn.addEventListener("click", (e2) => {
|
|
44590
|
-
e2.stopPropagation();
|
|
44591
|
-
this.closeStyleEditor(layerId);
|
|
44592
|
-
});
|
|
44593
|
-
actions.appendChild(resetBtn);
|
|
44594
|
-
actions.appendChild(removeBtn);
|
|
44595
|
-
actions.appendChild(closeActionBtn);
|
|
44596
|
-
editor.appendChild(header);
|
|
44597
|
-
editor.appendChild(controls);
|
|
44598
|
-
editor.appendChild(actions);
|
|
44599
|
-
return editor;
|
|
44600
|
-
}
|
|
44601
|
-
/**
|
|
44602
|
-
* Add style controls based on layer type
|
|
44603
|
-
*/
|
|
44604
|
-
addStyleControlsForLayerType(container, layerId, layerType) {
|
|
44605
|
-
switch (layerType) {
|
|
44606
|
-
case "fill":
|
|
44607
|
-
this.addFillControls(container, layerId);
|
|
44608
|
-
break;
|
|
44609
|
-
case "line":
|
|
44610
|
-
this.addLineControls(container, layerId);
|
|
44611
|
-
break;
|
|
44612
|
-
case "circle":
|
|
44613
|
-
this.addCircleControls(container, layerId);
|
|
44614
|
-
break;
|
|
44615
|
-
case "raster":
|
|
44616
|
-
this.addRasterControls(container, layerId);
|
|
44617
|
-
break;
|
|
44618
|
-
case "symbol":
|
|
44619
|
-
this.addSymbolControls(container, layerId);
|
|
44620
|
-
break;
|
|
44621
|
-
default:
|
|
44622
|
-
container.textContent = `Style controls for ${layerType} layers not yet implemented.`;
|
|
44623
|
-
}
|
|
44624
|
-
}
|
|
44625
|
-
/**
|
|
44626
|
-
* Add controls for fill layers
|
|
44627
|
-
*/
|
|
44628
|
-
addFillControls(container, layerId) {
|
|
44629
|
-
var _a3;
|
|
44630
|
-
const style = this.map.getStyle();
|
|
44631
|
-
const layer = (_a3 = style.layers) == null ? void 0 : _a3.find((l3) => l3.id === layerId);
|
|
44632
|
-
let fillColor = void 0;
|
|
44633
|
-
if (layer && "paint" in layer && layer.paint && "fill-color" in layer.paint) {
|
|
44634
|
-
fillColor = layer.paint["fill-color"];
|
|
44635
|
-
}
|
|
44636
|
-
if (!fillColor) {
|
|
44637
|
-
fillColor = this.map.getPaintProperty(layerId, "fill-color");
|
|
44638
|
-
}
|
|
44639
|
-
this.createColorControl(container, layerId, "fill-color", "Fill Color", normalizeColor(fillColor || "#088"));
|
|
44640
|
-
const fillOpacity = this.map.getPaintProperty(layerId, "fill-opacity");
|
|
44641
|
-
if (fillOpacity !== void 0 && typeof fillOpacity === "number") {
|
|
44642
|
-
this.createSliderControl(container, layerId, "fill-opacity", "Fill Opacity", fillOpacity, 0, 1, 0.05);
|
|
44643
|
-
}
|
|
44644
|
-
const outlineColor = this.map.getPaintProperty(layerId, "fill-outline-color");
|
|
44645
|
-
if (outlineColor !== void 0) {
|
|
44646
|
-
this.createColorControl(container, layerId, "fill-outline-color", "Outline Color", normalizeColor(outlineColor));
|
|
44647
|
-
}
|
|
44648
|
-
}
|
|
44649
|
-
/**
|
|
44650
|
-
* Add controls for line layers
|
|
44651
|
-
*/
|
|
44652
|
-
addLineControls(container, layerId) {
|
|
44653
|
-
var _a3;
|
|
44654
|
-
const style = this.map.getStyle();
|
|
44655
|
-
const layer = (_a3 = style.layers) == null ? void 0 : _a3.find((l3) => l3.id === layerId);
|
|
44656
|
-
let lineColor = void 0;
|
|
44657
|
-
if (layer && "paint" in layer && layer.paint && "line-color" in layer.paint) {
|
|
44658
|
-
lineColor = layer.paint["line-color"];
|
|
44659
|
-
}
|
|
44660
|
-
if (!lineColor) {
|
|
44661
|
-
lineColor = this.map.getPaintProperty(layerId, "line-color");
|
|
44662
|
-
}
|
|
44663
|
-
this.createColorControl(container, layerId, "line-color", "Line Color", normalizeColor(lineColor || "#000"));
|
|
44664
|
-
const lineWidth = this.map.getPaintProperty(layerId, "line-width");
|
|
44665
|
-
this.createSliderControl(container, layerId, "line-width", "Line Width", typeof lineWidth === "number" ? lineWidth : 1, 0, 20, 0.5);
|
|
44666
|
-
const lineOpacity = this.map.getPaintProperty(layerId, "line-opacity");
|
|
44667
|
-
if (lineOpacity !== void 0 && typeof lineOpacity === "number") {
|
|
44668
|
-
this.createSliderControl(container, layerId, "line-opacity", "Line Opacity", lineOpacity, 0, 1, 0.05);
|
|
44669
|
-
}
|
|
44670
|
-
const lineBlur = this.map.getPaintProperty(layerId, "line-blur");
|
|
44671
|
-
if (lineBlur !== void 0 && typeof lineBlur === "number") {
|
|
44672
|
-
this.createSliderControl(container, layerId, "line-blur", "Line Blur", lineBlur, 0, 5, 0.1);
|
|
44673
|
-
}
|
|
44674
|
-
}
|
|
44675
|
-
/**
|
|
44676
|
-
* Add controls for circle layers
|
|
44677
|
-
*/
|
|
44678
|
-
addCircleControls(container, layerId) {
|
|
44679
|
-
var _a3;
|
|
44680
|
-
const style = this.map.getStyle();
|
|
44681
|
-
const layer = (_a3 = style.layers) == null ? void 0 : _a3.find((l3) => l3.id === layerId);
|
|
44682
|
-
let circleColor = void 0;
|
|
44683
|
-
if (layer && "paint" in layer && layer.paint && "circle-color" in layer.paint) {
|
|
44684
|
-
circleColor = layer.paint["circle-color"];
|
|
44685
|
-
}
|
|
44686
|
-
if (!circleColor) {
|
|
44687
|
-
circleColor = this.map.getPaintProperty(layerId, "circle-color");
|
|
44688
|
-
}
|
|
44689
|
-
this.createColorControl(container, layerId, "circle-color", "Circle Color", normalizeColor(circleColor || "#000"));
|
|
44690
|
-
const circleRadius = this.map.getPaintProperty(layerId, "circle-radius");
|
|
44691
|
-
this.createSliderControl(container, layerId, "circle-radius", "Radius", typeof circleRadius === "number" ? circleRadius : 5, 0, 40, 0.5);
|
|
44692
|
-
const circleOpacity = this.map.getPaintProperty(layerId, "circle-opacity");
|
|
44693
|
-
if (circleOpacity !== void 0 && typeof circleOpacity === "number") {
|
|
44694
|
-
this.createSliderControl(container, layerId, "circle-opacity", "Opacity", circleOpacity, 0, 1, 0.05);
|
|
44695
|
-
}
|
|
44696
|
-
const strokeColor = this.map.getPaintProperty(layerId, "circle-stroke-color");
|
|
44697
|
-
if (strokeColor !== void 0) {
|
|
44698
|
-
this.createColorControl(container, layerId, "circle-stroke-color", "Stroke Color", normalizeColor(strokeColor));
|
|
44699
|
-
}
|
|
44700
|
-
const strokeWidth = this.map.getPaintProperty(layerId, "circle-stroke-width");
|
|
44701
|
-
if (strokeWidth !== void 0 && typeof strokeWidth === "number") {
|
|
44702
|
-
this.createSliderControl(container, layerId, "circle-stroke-width", "Stroke Width", strokeWidth, 0, 10, 0.1);
|
|
44703
|
-
}
|
|
44704
|
-
}
|
|
44705
|
-
/**
|
|
44706
|
-
* Add controls for raster layers
|
|
44707
|
-
*/
|
|
44708
|
-
addRasterControls(container, layerId) {
|
|
44709
|
-
const rasterOpacity = this.map.getPaintProperty(layerId, "raster-opacity");
|
|
44710
|
-
this.createSliderControl(container, layerId, "raster-opacity", "Opacity", typeof rasterOpacity === "number" ? rasterOpacity : 1, 0, 1, 0.05);
|
|
44711
|
-
const brightnessMin = this.map.getPaintProperty(layerId, "raster-brightness-min");
|
|
44712
|
-
this.createSliderControl(container, layerId, "raster-brightness-min", "Brightness Min", typeof brightnessMin === "number" ? brightnessMin : 0, -1, 1, 0.05);
|
|
44713
|
-
const brightnessMax = this.map.getPaintProperty(layerId, "raster-brightness-max");
|
|
44714
|
-
this.createSliderControl(container, layerId, "raster-brightness-max", "Brightness Max", typeof brightnessMax === "number" ? brightnessMax : 1, -1, 1, 0.05);
|
|
44715
|
-
const saturation = this.map.getPaintProperty(layerId, "raster-saturation");
|
|
44716
|
-
this.createSliderControl(container, layerId, "raster-saturation", "Saturation", typeof saturation === "number" ? saturation : 0, -1, 1, 0.05);
|
|
44717
|
-
const contrast = this.map.getPaintProperty(layerId, "raster-contrast");
|
|
44718
|
-
this.createSliderControl(container, layerId, "raster-contrast", "Contrast", typeof contrast === "number" ? contrast : 0, -1, 1, 0.05);
|
|
44719
|
-
const hueRotate = this.map.getPaintProperty(layerId, "raster-hue-rotate");
|
|
44720
|
-
this.createSliderControl(container, layerId, "raster-hue-rotate", "Hue Rotate", typeof hueRotate === "number" ? hueRotate : 0, 0, 350, 5);
|
|
44721
|
-
}
|
|
44722
|
-
/**
|
|
44723
|
-
* Add controls for symbol layers
|
|
44724
|
-
*/
|
|
44725
|
-
addSymbolControls(container, layerId) {
|
|
44726
|
-
const textColor = this.map.getPaintProperty(layerId, "text-color");
|
|
44727
|
-
if (textColor !== void 0) {
|
|
44728
|
-
this.createColorControl(container, layerId, "text-color", "Text Color", normalizeColor(textColor));
|
|
44729
|
-
}
|
|
44730
|
-
const textOpacity = this.map.getPaintProperty(layerId, "text-opacity");
|
|
44731
|
-
if (textOpacity !== void 0 && typeof textOpacity === "number") {
|
|
44732
|
-
this.createSliderControl(container, layerId, "text-opacity", "Text Opacity", textOpacity, 0, 1, 0.05);
|
|
44733
|
-
}
|
|
44734
|
-
const iconOpacity = this.map.getPaintProperty(layerId, "icon-opacity");
|
|
44735
|
-
if (iconOpacity !== void 0 && typeof iconOpacity === "number") {
|
|
44736
|
-
this.createSliderControl(container, layerId, "icon-opacity", "Icon Opacity", iconOpacity, 0, 1, 0.05);
|
|
44737
|
-
}
|
|
44738
|
-
}
|
|
44739
|
-
/**
|
|
44740
|
-
* Create a color control
|
|
44741
|
-
*/
|
|
44742
|
-
createColorControl(container, layerId, property, label, initialValue) {
|
|
44743
|
-
const controlGroup = document.createElement("div");
|
|
44744
|
-
controlGroup.className = "style-control-group";
|
|
44745
|
-
const labelEl = document.createElement("label");
|
|
44746
|
-
labelEl.className = "style-control-label";
|
|
44747
|
-
labelEl.textContent = label;
|
|
44748
|
-
const inputWrapper = document.createElement("div");
|
|
44749
|
-
inputWrapper.className = "style-control-color-group";
|
|
44750
|
-
const colorInput = document.createElement("input");
|
|
44751
|
-
colorInput.type = "color";
|
|
44752
|
-
colorInput.className = "style-control-color-picker";
|
|
44753
|
-
colorInput.value = initialValue;
|
|
44754
|
-
colorInput.dataset.property = property;
|
|
44755
|
-
const hexDisplay = document.createElement("input");
|
|
44756
|
-
hexDisplay.type = "text";
|
|
44757
|
-
hexDisplay.className = "style-control-color-value";
|
|
44758
|
-
hexDisplay.value = initialValue;
|
|
44759
|
-
hexDisplay.readOnly = true;
|
|
44760
|
-
colorInput.addEventListener("input", () => {
|
|
44761
|
-
const color = colorInput.value;
|
|
44762
|
-
hexDisplay.value = color;
|
|
44763
|
-
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
44764
|
-
for (const id2 of targetIds) {
|
|
44765
|
-
this.map.setPaintProperty(id2, property, color);
|
|
44766
|
-
}
|
|
44767
|
-
});
|
|
44768
|
-
inputWrapper.appendChild(colorInput);
|
|
44769
|
-
inputWrapper.appendChild(hexDisplay);
|
|
44770
|
-
controlGroup.appendChild(labelEl);
|
|
44771
|
-
controlGroup.appendChild(inputWrapper);
|
|
44772
|
-
container.appendChild(controlGroup);
|
|
44773
|
-
}
|
|
44774
|
-
/**
|
|
44775
|
-
* Create a slider control
|
|
44776
|
-
*/
|
|
44777
|
-
createSliderControl(container, layerId, property, label, initialValue, min, max, step) {
|
|
44778
|
-
const controlGroup = document.createElement("div");
|
|
44779
|
-
controlGroup.className = "style-control-group";
|
|
44780
|
-
const labelEl = document.createElement("label");
|
|
44781
|
-
labelEl.className = "style-control-label";
|
|
44782
|
-
labelEl.textContent = label;
|
|
44783
|
-
const inputWrapper = document.createElement("div");
|
|
44784
|
-
inputWrapper.className = "style-control-input-wrapper";
|
|
44785
|
-
const slider = document.createElement("input");
|
|
44786
|
-
slider.type = "range";
|
|
44787
|
-
slider.className = "style-control-slider";
|
|
44788
|
-
slider.min = String(min);
|
|
44789
|
-
slider.max = String(max);
|
|
44790
|
-
slider.step = String(step);
|
|
44791
|
-
slider.value = String(initialValue);
|
|
44792
|
-
slider.dataset.property = property;
|
|
44793
|
-
const valueDisplay = document.createElement("span");
|
|
44794
|
-
valueDisplay.className = "style-control-value";
|
|
44795
|
-
valueDisplay.textContent = formatNumericValue(initialValue, step);
|
|
44796
|
-
slider.addEventListener("input", () => {
|
|
44797
|
-
const value = parseFloat(slider.value);
|
|
44798
|
-
valueDisplay.textContent = formatNumericValue(value, step);
|
|
44799
|
-
const targetIds = this.nativeLayerGroups.get(layerId) || [layerId];
|
|
44800
|
-
for (const id2 of targetIds) {
|
|
44801
|
-
this.map.setPaintProperty(id2, property, value);
|
|
44802
|
-
}
|
|
44803
|
-
});
|
|
44804
|
-
inputWrapper.appendChild(slider);
|
|
44805
|
-
inputWrapper.appendChild(valueDisplay);
|
|
44806
|
-
controlGroup.appendChild(labelEl);
|
|
44807
|
-
controlGroup.appendChild(inputWrapper);
|
|
44808
|
-
container.appendChild(controlGroup);
|
|
44809
|
-
}
|
|
44810
|
-
/**
|
|
44811
|
-
* Reset layer style to original
|
|
44812
|
-
*/
|
|
44813
|
-
resetLayerStyle(layerId) {
|
|
44814
|
-
const originalStyle = this.state.originalStyles.get(layerId);
|
|
44815
|
-
if (!originalStyle) return;
|
|
44816
|
-
restoreOriginalStyle(this.map, layerId, this.state.originalStyles);
|
|
44817
|
-
const editor = this.styleEditors.get(layerId);
|
|
44818
|
-
if (editor) {
|
|
44819
|
-
const sliders = editor.querySelectorAll(".style-control-slider");
|
|
44820
|
-
sliders.forEach((slider) => {
|
|
44821
|
-
var _a3;
|
|
44822
|
-
const property = slider.dataset.property;
|
|
44823
|
-
if (property) {
|
|
44824
|
-
const value = this.map.getPaintProperty(layerId, property);
|
|
44825
|
-
if (value !== void 0 && typeof value === "number") {
|
|
44826
|
-
slider.value = String(value);
|
|
44827
|
-
const valueDisplay = (_a3 = slider.parentElement) == null ? void 0 : _a3.querySelector(".style-control-value");
|
|
44828
|
-
if (valueDisplay) {
|
|
44829
|
-
const step = parseFloat(slider.step);
|
|
44830
|
-
valueDisplay.textContent = formatNumericValue(value, step);
|
|
44831
|
-
}
|
|
44832
|
-
}
|
|
44833
|
-
}
|
|
44834
|
-
});
|
|
44835
|
-
const colorPickers = editor.querySelectorAll(".style-control-color-picker");
|
|
44836
|
-
colorPickers.forEach((picker) => {
|
|
44837
|
-
var _a3;
|
|
44838
|
-
const property = picker.dataset.property;
|
|
44839
|
-
if (property) {
|
|
44840
|
-
const value = this.map.getPaintProperty(layerId, property);
|
|
44841
|
-
if (value !== void 0) {
|
|
44842
|
-
const hexColor = normalizeColor(value);
|
|
44843
|
-
picker.value = hexColor;
|
|
44844
|
-
const hexDisplay = (_a3 = picker.parentElement) == null ? void 0 : _a3.querySelector(".style-control-color-value");
|
|
44845
|
-
if (hexDisplay) {
|
|
44846
|
-
hexDisplay.textContent = hexColor;
|
|
44847
|
-
}
|
|
44848
|
-
}
|
|
44849
|
-
}
|
|
44850
|
-
});
|
|
44851
|
-
}
|
|
44852
|
-
}
|
|
44853
|
-
/**
|
|
44854
|
-
* Update layer states from map (sync UI with map)
|
|
44855
|
-
*/
|
|
44856
|
-
updateLayerStatesFromMap() {
|
|
44857
|
-
if (this.state.userInteractingWithSlider) {
|
|
44858
|
-
return;
|
|
44859
|
-
}
|
|
44860
|
-
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
44861
|
-
var _a3;
|
|
44862
|
-
try {
|
|
44863
|
-
if ((_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.isCustomLayer) {
|
|
44864
|
-
return;
|
|
44865
|
-
}
|
|
44866
|
-
if (layerId === "Background") {
|
|
44867
|
-
return;
|
|
44868
|
-
}
|
|
44869
|
-
const layer = this.map.getLayer(layerId);
|
|
44870
|
-
if (!layer) return;
|
|
44871
|
-
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
44872
|
-
const isVisible = visibility !== "none";
|
|
44873
|
-
const layerType = layer.type;
|
|
44874
|
-
const opacity = getLayerOpacity(this.map, layerId, layerType);
|
|
44875
|
-
if (this.state.layerStates[layerId]) {
|
|
44876
|
-
this.state.layerStates[layerId].visible = isVisible;
|
|
44877
|
-
this.state.layerStates[layerId].opacity = opacity;
|
|
44878
|
-
}
|
|
44879
|
-
this.updateUIForLayer(layerId, isVisible, opacity);
|
|
44880
|
-
} catch (error) {
|
|
44881
|
-
console.warn(`Failed to update state for layer ${layerId}:`, error);
|
|
44882
|
-
}
|
|
44883
|
-
});
|
|
44884
|
-
}
|
|
44885
|
-
/**
|
|
44886
|
-
* Update UI elements for a specific layer
|
|
44887
|
-
*/
|
|
44888
|
-
updateUIForLayer(layerId, visible, opacity) {
|
|
44889
|
-
const layerItems = this.panel.querySelectorAll(".layer-control-item");
|
|
44890
|
-
layerItems.forEach((item) => {
|
|
44891
|
-
if (item.dataset.layerId === layerId) {
|
|
44892
|
-
const checkbox = item.querySelector(".layer-control-checkbox");
|
|
44893
|
-
const opacitySlider = item.querySelector(".layer-control-opacity");
|
|
44894
|
-
if (checkbox) {
|
|
44895
|
-
checkbox.checked = visible;
|
|
44896
|
-
}
|
|
44897
|
-
if (opacitySlider) {
|
|
44898
|
-
opacitySlider.value = String(opacity);
|
|
44899
|
-
opacitySlider.title = `Opacity: ${Math.round(opacity * 100)}%`;
|
|
44900
|
-
}
|
|
44901
|
-
}
|
|
44902
|
-
});
|
|
44903
|
-
}
|
|
44904
|
-
/**
|
|
44905
|
-
* Check for new layers and add them to the control, remove deleted layers
|
|
44906
|
-
*/
|
|
44907
|
-
checkForNewLayers() {
|
|
44908
|
-
if (this.state.isStyleOperationInProgress) {
|
|
44909
|
-
return;
|
|
44910
|
-
}
|
|
44911
|
-
try {
|
|
44912
|
-
const style = this.map.getStyle();
|
|
44913
|
-
if (!style || !style.layers) {
|
|
44914
|
-
return;
|
|
44915
|
-
}
|
|
44916
|
-
const currentMapLayerIds = new Set(style.layers.map((layer) => layer.id));
|
|
44917
|
-
const isAutoDetectMode = this.targetLayers.length === 0 || this.targetLayers.length === 1 && this.targetLayers[0] === "Background" || this.targetLayers.every((id2) => id2 === "Background" || this.state.layerStates[id2]);
|
|
44918
|
-
const newLayers = [];
|
|
44919
|
-
const useBasemapStyleDetection = this.basemapLayerIds !== null && this.basemapLayerIds.size > 0;
|
|
44920
|
-
const useInitialLayerDetection = !useBasemapStyleDetection && this.initialLayerIds !== null && this.initialLayerIds.size > 0;
|
|
44921
|
-
currentMapLayerIds.forEach((layerId) => {
|
|
44922
|
-
if (layerId !== "Background" && !this.state.layerStates[layerId]) {
|
|
44923
|
-
const layer = this.map.getLayer(layerId);
|
|
44924
|
-
if (layer) {
|
|
44925
|
-
if (this.initialLayerIds !== null && this.initialLayerIds.has(layerId)) {
|
|
44926
|
-
return;
|
|
44927
|
-
}
|
|
44928
|
-
if (isAutoDetectMode) {
|
|
44929
|
-
if (this.excludeDrawnLayers && this.isDrawnLayer(layerId)) {
|
|
44930
|
-
return;
|
|
44931
|
-
}
|
|
44932
|
-
if (this.isExcludedByPattern(layerId)) {
|
|
44933
|
-
return;
|
|
44934
|
-
}
|
|
44935
|
-
if (!this.isUserAddedLayer(layerId)) {
|
|
44936
|
-
return;
|
|
44937
|
-
}
|
|
44938
|
-
if (useBasemapStyleDetection) {
|
|
44939
|
-
if (this.basemapLayerIds.has(layerId)) {
|
|
44940
|
-
return;
|
|
44941
|
-
}
|
|
44942
|
-
} else if (useInitialLayerDetection) {
|
|
44943
|
-
if (this.initialLayerIds.has(layerId)) {
|
|
44944
|
-
const userAddedSourceIds = this.detectUserAddedSources();
|
|
44945
|
-
const sourceId = layer.source;
|
|
44946
|
-
if (!sourceId || !userAddedSourceIds.has(sourceId)) {
|
|
44947
|
-
return;
|
|
44948
|
-
}
|
|
44949
|
-
}
|
|
44950
|
-
} else {
|
|
44951
|
-
const userAddedSourceIds = this.detectUserAddedSources();
|
|
44952
|
-
const sourceId = layer.source;
|
|
44953
|
-
if (!sourceId || !userAddedSourceIds.has(sourceId)) {
|
|
44954
|
-
return;
|
|
44955
|
-
}
|
|
44956
|
-
}
|
|
44957
|
-
}
|
|
44958
|
-
newLayers.push(layerId);
|
|
44959
|
-
}
|
|
44960
|
-
}
|
|
44961
|
-
});
|
|
44962
|
-
const removedLayers = [];
|
|
44963
|
-
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
44964
|
-
const state = this.state.layerStates[layerId];
|
|
44965
|
-
if (layerId !== "Background" && !state.isCustomLayer && !currentMapLayerIds.has(layerId)) {
|
|
44966
|
-
removedLayers.push(layerId);
|
|
44967
|
-
}
|
|
44968
|
-
});
|
|
44969
|
-
if (removedLayers.length > 0) {
|
|
44970
|
-
removedLayers.forEach((layerId) => {
|
|
44971
|
-
delete this.state.layerStates[layerId];
|
|
44972
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
44973
|
-
if (itemEl) {
|
|
44974
|
-
itemEl.remove();
|
|
44975
|
-
}
|
|
44976
|
-
if (this.state.activeStyleEditor === layerId) {
|
|
44977
|
-
this.state.activeStyleEditor = null;
|
|
44978
|
-
}
|
|
44979
|
-
this.styleEditors.delete(layerId);
|
|
44980
|
-
});
|
|
44981
|
-
}
|
|
44982
|
-
if (newLayers.length > 0) {
|
|
44983
|
-
newLayers.forEach((layerId) => {
|
|
44984
|
-
const layer = this.map.getLayer(layerId);
|
|
44985
|
-
if (!layer) return;
|
|
44986
|
-
const layerType = layer.type;
|
|
44987
|
-
const opacity = getLayerOpacity(this.map, layerId, layerType);
|
|
44988
|
-
const visibility = this.map.getLayoutProperty(layerId, "visibility");
|
|
44989
|
-
const isVisible = visibility !== "none";
|
|
44990
|
-
this.state.layerStates[layerId] = {
|
|
44991
|
-
visible: isVisible,
|
|
44992
|
-
opacity,
|
|
44993
|
-
name: this.generateFriendlyName(layerId)
|
|
44994
|
-
};
|
|
44995
|
-
this.addLayerItem(layerId, this.state.layerStates[layerId]);
|
|
44996
|
-
});
|
|
44997
|
-
}
|
|
44998
|
-
if (this.customLayerRegistry) {
|
|
44999
|
-
const customLayerIds = this.customLayerRegistry.getAllLayerIds();
|
|
45000
|
-
customLayerIds.forEach((layerId) => {
|
|
45001
|
-
if (!this.state.layerStates[layerId] && !this.removedCustomLayerIds.has(layerId)) {
|
|
45002
|
-
const customState = this.customLayerRegistry.getLayerState(layerId);
|
|
45003
|
-
if (customState) {
|
|
45004
|
-
this.state.layerStates[layerId] = {
|
|
45005
|
-
visible: customState.visible,
|
|
45006
|
-
opacity: customState.opacity,
|
|
45007
|
-
name: customState.name,
|
|
45008
|
-
isCustomLayer: true,
|
|
45009
|
-
customLayerType: this.customLayerRegistry.getSymbolType(layerId) || void 0
|
|
45010
|
-
};
|
|
45011
|
-
this.addLayerItem(layerId, this.state.layerStates[layerId]);
|
|
45012
|
-
}
|
|
45013
|
-
}
|
|
45014
|
-
});
|
|
45015
|
-
Object.keys(this.state.layerStates).forEach((layerId) => {
|
|
45016
|
-
const state = this.state.layerStates[layerId];
|
|
45017
|
-
if (state.isCustomLayer && !customLayerIds.includes(layerId)) {
|
|
45018
|
-
delete this.state.layerStates[layerId];
|
|
45019
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
45020
|
-
if (itemEl) {
|
|
45021
|
-
itemEl.remove();
|
|
45022
|
-
}
|
|
45023
|
-
if (this.state.activeStyleEditor === layerId) {
|
|
45024
|
-
this.state.activeStyleEditor = null;
|
|
45025
|
-
}
|
|
45026
|
-
this.styleEditors.delete(layerId);
|
|
45027
|
-
}
|
|
45028
|
-
});
|
|
45029
|
-
}
|
|
45030
|
-
} catch (error) {
|
|
45031
|
-
console.warn("Failed to check for new layers:", error);
|
|
45032
|
-
}
|
|
45033
|
-
}
|
|
45034
|
-
/**
|
|
45035
|
-
* Register a custom layer adapter dynamically.
|
|
45036
|
-
* This allows adding adapters after the LayerControl has been initialized.
|
|
45037
|
-
* @param adapter The custom layer adapter to register
|
|
45038
|
-
*/
|
|
45039
|
-
registerCustomAdapter(adapter) {
|
|
45040
|
-
if (!this.customLayerRegistry) {
|
|
45041
|
-
this.customLayerRegistry = new CustomLayerRegistry();
|
|
45042
|
-
this.customLayerUnsubscribe = this.customLayerRegistry.onChange((event, layerId) => {
|
|
45043
|
-
if (event === "add" && layerId) {
|
|
45044
|
-
this.removedCustomLayerIds.delete(layerId);
|
|
45045
|
-
}
|
|
45046
|
-
this.checkForNewLayers();
|
|
45047
|
-
});
|
|
45048
|
-
}
|
|
45049
|
-
this.customLayerRegistry.register(adapter);
|
|
45050
|
-
if (this.panel) {
|
|
45051
|
-
this.checkForNewLayers();
|
|
45052
|
-
}
|
|
45053
|
-
}
|
|
45054
|
-
// ===== Context Menu Methods =====
|
|
45055
|
-
/**
|
|
45056
|
-
* Create context menu element
|
|
45057
|
-
*/
|
|
45058
|
-
createContextMenu() {
|
|
45059
|
-
const menu = document.createElement("div");
|
|
45060
|
-
menu.className = "layer-control-context-menu";
|
|
45061
|
-
menu.style.display = "none";
|
|
45062
|
-
const renameItem = this.createContextMenuItem("Rename", "✏️", () => {
|
|
45063
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45064
|
-
this.startRenaming(this.state.contextMenu.targetLayerId);
|
|
45065
|
-
}
|
|
45066
|
-
this.hideContextMenu();
|
|
45067
|
-
});
|
|
45068
|
-
const zoomItem = this.createContextMenuItem("Zoom to Layer", "🔍", () => {
|
|
45069
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45070
|
-
this.zoomToLayer(this.state.contextMenu.targetLayerId);
|
|
45071
|
-
}
|
|
45072
|
-
this.hideContextMenu();
|
|
45073
|
-
});
|
|
45074
|
-
const sep1 = document.createElement("div");
|
|
45075
|
-
sep1.className = "context-menu-separator";
|
|
45076
|
-
const moveUpItem = this.createContextMenuItem("Move Up", "↑", () => {
|
|
45077
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45078
|
-
this.moveLayerUp(this.state.contextMenu.targetLayerId);
|
|
45079
|
-
}
|
|
45080
|
-
this.hideContextMenu();
|
|
45081
|
-
});
|
|
45082
|
-
const moveTopItem = this.createContextMenuItem("Move to Top", "⤒", () => {
|
|
45083
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45084
|
-
this.moveLayerToTop(this.state.contextMenu.targetLayerId);
|
|
45085
|
-
}
|
|
45086
|
-
this.hideContextMenu();
|
|
45087
|
-
});
|
|
45088
|
-
const moveDownItem = this.createContextMenuItem("Move Down", "↓", () => {
|
|
45089
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45090
|
-
this.moveLayerDown(this.state.contextMenu.targetLayerId);
|
|
45091
|
-
}
|
|
45092
|
-
this.hideContextMenu();
|
|
45093
|
-
});
|
|
45094
|
-
const moveBottomItem = this.createContextMenuItem("Move to Bottom", "⤓", () => {
|
|
45095
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45096
|
-
this.moveLayerToBottom(this.state.contextMenu.targetLayerId);
|
|
45097
|
-
}
|
|
45098
|
-
this.hideContextMenu();
|
|
45099
|
-
});
|
|
45100
|
-
const sep2 = document.createElement("div");
|
|
45101
|
-
sep2.className = "context-menu-separator";
|
|
45102
|
-
const removeItem = this.createContextMenuItem("Remove Layer", "🗑️", () => {
|
|
45103
|
-
if (this.state.contextMenu.targetLayerId) {
|
|
45104
|
-
this.removeLayer(this.state.contextMenu.targetLayerId);
|
|
45105
|
-
}
|
|
45106
|
-
this.hideContextMenu();
|
|
45107
|
-
}, true);
|
|
45108
|
-
menu.appendChild(renameItem);
|
|
45109
|
-
menu.appendChild(zoomItem);
|
|
45110
|
-
menu.appendChild(sep1);
|
|
45111
|
-
menu.appendChild(moveUpItem);
|
|
45112
|
-
menu.appendChild(moveTopItem);
|
|
45113
|
-
menu.appendChild(moveDownItem);
|
|
45114
|
-
menu.appendChild(moveBottomItem);
|
|
45115
|
-
menu.appendChild(sep2);
|
|
45116
|
-
menu.appendChild(removeItem);
|
|
45117
|
-
return menu;
|
|
45118
|
-
}
|
|
45119
|
-
/**
|
|
45120
|
-
* Create a context menu item
|
|
45121
|
-
*/
|
|
45122
|
-
createContextMenuItem(label, icon, onClick, isDanger = false) {
|
|
45123
|
-
const item = document.createElement("div");
|
|
45124
|
-
item.className = "context-menu-item" + (isDanger ? " context-menu-item-danger" : "");
|
|
45125
|
-
const iconEl = document.createElement("span");
|
|
45126
|
-
iconEl.className = "context-menu-item-icon";
|
|
45127
|
-
iconEl.textContent = icon;
|
|
45128
|
-
const labelEl = document.createElement("span");
|
|
45129
|
-
labelEl.className = "context-menu-item-label";
|
|
45130
|
-
labelEl.textContent = label;
|
|
45131
|
-
item.appendChild(iconEl);
|
|
45132
|
-
item.appendChild(labelEl);
|
|
45133
|
-
item.addEventListener("click", (e2) => {
|
|
45134
|
-
e2.stopPropagation();
|
|
45135
|
-
onClick();
|
|
45136
|
-
});
|
|
45137
|
-
return item;
|
|
45138
|
-
}
|
|
45139
|
-
/**
|
|
45140
|
-
* Show context menu at position
|
|
45141
|
-
*/
|
|
45142
|
-
showContextMenu(layerId, x2, y2) {
|
|
45143
|
-
if (!this.contextMenuEl) return;
|
|
45144
|
-
this.state.contextMenu = {
|
|
45145
|
-
visible: true,
|
|
45146
|
-
targetLayerId: layerId,
|
|
45147
|
-
x: x2,
|
|
45148
|
-
y: y2
|
|
45149
|
-
};
|
|
45150
|
-
const mapRect = this.mapContainer.getBoundingClientRect();
|
|
45151
|
-
let menuX = x2 - mapRect.left;
|
|
45152
|
-
let menuY = y2 - mapRect.top;
|
|
45153
|
-
this.contextMenuEl.style.display = "block";
|
|
45154
|
-
const menuRect = this.contextMenuEl.getBoundingClientRect();
|
|
45155
|
-
if (menuX + menuRect.width > mapRect.width) {
|
|
45156
|
-
menuX = mapRect.width - menuRect.width - 5;
|
|
45157
|
-
}
|
|
45158
|
-
if (menuY + menuRect.height > mapRect.height) {
|
|
45159
|
-
menuY = mapRect.height - menuRect.height - 5;
|
|
45160
|
-
}
|
|
45161
|
-
this.contextMenuEl.style.left = `${menuX}px`;
|
|
45162
|
-
this.contextMenuEl.style.top = `${menuY}px`;
|
|
45163
|
-
}
|
|
45164
|
-
/**
|
|
45165
|
-
* Hide context menu
|
|
45166
|
-
*/
|
|
45167
|
-
hideContextMenu() {
|
|
45168
|
-
if (!this.contextMenuEl) return;
|
|
45169
|
-
this.state.contextMenu = {
|
|
45170
|
-
visible: false,
|
|
45171
|
-
targetLayerId: null,
|
|
45172
|
-
x: 0,
|
|
45173
|
-
y: 0
|
|
45174
|
-
};
|
|
45175
|
-
this.contextMenuEl.style.display = "none";
|
|
45176
|
-
}
|
|
45177
|
-
/**
|
|
45178
|
-
* Start renaming a layer
|
|
45179
|
-
*/
|
|
45180
|
-
startRenaming(layerId) {
|
|
45181
|
-
var _a3;
|
|
45182
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
45183
|
-
if (!itemEl) return;
|
|
45184
|
-
const nameEl = itemEl.querySelector(".layer-control-name");
|
|
45185
|
-
if (!nameEl) return;
|
|
45186
|
-
this.state.renamingLayerId = layerId;
|
|
45187
|
-
const currentName = this.state.customLayerNames.get(layerId) || ((_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.name) || layerId;
|
|
45188
|
-
const input = document.createElement("input");
|
|
45189
|
-
input.type = "text";
|
|
45190
|
-
input.className = "layer-control-name-input";
|
|
45191
|
-
input.value = currentName;
|
|
45192
|
-
const finishRename = () => {
|
|
45193
|
-
var _a22;
|
|
45194
|
-
const newName = input.value.trim() || currentName;
|
|
45195
|
-
const oldName = currentName;
|
|
45196
|
-
if (newName !== oldName) {
|
|
45197
|
-
this.state.customLayerNames.set(layerId, newName);
|
|
45198
|
-
if (this.state.layerStates[layerId]) {
|
|
45199
|
-
this.state.layerStates[layerId].name = newName;
|
|
45200
|
-
}
|
|
45201
|
-
(_a22 = this.onLayerRename) == null ? void 0 : _a22.call(this, layerId, oldName, newName);
|
|
45202
|
-
}
|
|
45203
|
-
const newNameEl = document.createElement("span");
|
|
45204
|
-
newNameEl.className = "layer-control-name";
|
|
45205
|
-
newNameEl.textContent = newName;
|
|
45206
|
-
newNameEl.title = newName;
|
|
45207
|
-
input.replaceWith(newNameEl);
|
|
45208
|
-
this.state.renamingLayerId = null;
|
|
45209
|
-
};
|
|
45210
|
-
input.addEventListener("blur", finishRename);
|
|
45211
|
-
input.addEventListener("keydown", (e2) => {
|
|
45212
|
-
if (e2.key === "Enter") {
|
|
45213
|
-
e2.preventDefault();
|
|
45214
|
-
finishRename();
|
|
45215
|
-
} else if (e2.key === "Escape") {
|
|
45216
|
-
e2.preventDefault();
|
|
45217
|
-
const newNameEl = document.createElement("span");
|
|
45218
|
-
newNameEl.className = "layer-control-name";
|
|
45219
|
-
newNameEl.textContent = currentName;
|
|
45220
|
-
newNameEl.title = currentName;
|
|
45221
|
-
input.replaceWith(newNameEl);
|
|
45222
|
-
this.state.renamingLayerId = null;
|
|
45223
|
-
}
|
|
45224
|
-
});
|
|
45225
|
-
nameEl.replaceWith(input);
|
|
45226
|
-
input.focus();
|
|
45227
|
-
input.select();
|
|
45228
|
-
}
|
|
45229
|
-
/**
|
|
45230
|
-
* Zoom to a layer's bounds
|
|
45231
|
-
*/
|
|
45232
|
-
zoomToLayer(layerId) {
|
|
45233
|
-
const layerState = this.state.layerStates[layerId];
|
|
45234
|
-
if ((layerState == null ? void 0 : layerState.isCustomLayer) && this.customLayerRegistry) {
|
|
45235
|
-
const bounds = this.customLayerRegistry.getBounds(layerId);
|
|
45236
|
-
if (bounds) {
|
|
45237
|
-
this.map.fitBounds(bounds, { padding: 50 });
|
|
45238
|
-
return;
|
|
45239
|
-
}
|
|
45240
|
-
}
|
|
45241
|
-
const layer = this.map.getLayer(layerId);
|
|
45242
|
-
if (!layer) return;
|
|
45243
|
-
try {
|
|
45244
|
-
const sourceId = layer.source;
|
|
45245
|
-
let features = sourceId ? this.map.querySourceFeatures(sourceId) : [];
|
|
45246
|
-
if (features.length === 0) {
|
|
45247
|
-
features = this.map.queryRenderedFeatures({ layers: [layerId] });
|
|
45248
|
-
}
|
|
45249
|
-
if (features.length === 0) return;
|
|
45250
|
-
let minLng = Infinity, minLat = Infinity, maxLng = -Infinity, maxLat = -Infinity;
|
|
45251
|
-
features.forEach((feature) => {
|
|
45252
|
-
if (!feature.geometry) return;
|
|
45253
|
-
const processCoords = (coords) => {
|
|
45254
|
-
if (typeof coords[0] === "number") {
|
|
45255
|
-
const [lng, lat] = coords;
|
|
45256
|
-
minLng = Math.min(minLng, lng);
|
|
45257
|
-
minLat = Math.min(minLat, lat);
|
|
45258
|
-
maxLng = Math.max(maxLng, lng);
|
|
45259
|
-
maxLat = Math.max(maxLat, lat);
|
|
45260
|
-
} else {
|
|
45261
|
-
coords.forEach(processCoords);
|
|
45262
|
-
}
|
|
45263
|
-
};
|
|
45264
|
-
if (feature.geometry.type === "Point") {
|
|
45265
|
-
processCoords(feature.geometry.coordinates);
|
|
45266
|
-
} else if (feature.geometry.type === "LineString" || feature.geometry.type === "MultiPoint") {
|
|
45267
|
-
feature.geometry.coordinates.forEach(processCoords);
|
|
45268
|
-
} else if (feature.geometry.type === "Polygon" || feature.geometry.type === "MultiLineString") {
|
|
45269
|
-
feature.geometry.coordinates.forEach((ring) => ring.forEach(processCoords));
|
|
45270
|
-
} else if (feature.geometry.type === "MultiPolygon") {
|
|
45271
|
-
feature.geometry.coordinates.forEach(
|
|
45272
|
-
(polygon) => polygon.forEach((ring) => ring.forEach(processCoords))
|
|
45273
|
-
);
|
|
45274
|
-
}
|
|
45275
|
-
});
|
|
45276
|
-
if (minLng !== Infinity && minLat !== Infinity && maxLng !== -Infinity && maxLat !== -Infinity) {
|
|
45277
|
-
this.map.fitBounds([[minLng, minLat], [maxLng, maxLat]], { padding: 50 });
|
|
45278
|
-
}
|
|
45279
|
-
} catch (error) {
|
|
45280
|
-
console.warn(`Failed to zoom to layer ${layerId}:`, error);
|
|
45281
|
-
}
|
|
45282
|
-
}
|
|
45283
|
-
/**
|
|
45284
|
-
* Get user layer IDs in current map order (top to bottom in UI = high z-index to low)
|
|
45285
|
-
* Includes both MapLibre layers and custom layers managed by adapters.
|
|
45286
|
-
*/
|
|
45287
|
-
getUserLayerIdsInMapOrder() {
|
|
45288
|
-
const style = this.map.getStyle();
|
|
45289
|
-
if (!(style == null ? void 0 : style.layers)) return [];
|
|
45290
|
-
const mapLayerIds = style.layers.map((l3) => l3.id);
|
|
45291
|
-
const userLayerIds = Object.keys(this.state.layerStates).filter((id2) => id2 !== "Background");
|
|
45292
|
-
const mapLibreLayers = userLayerIds.filter((id2) => mapLayerIds.includes(id2));
|
|
45293
|
-
const customLayers = userLayerIds.filter(
|
|
45294
|
-
(id2) => {
|
|
45295
|
-
var _a3;
|
|
45296
|
-
return ((_a3 = this.state.layerStates[id2]) == null ? void 0 : _a3.isCustomLayer) && !mapLayerIds.includes(id2);
|
|
45297
|
-
}
|
|
45298
|
-
);
|
|
45299
|
-
const sortedMapLibreLayers = mapLibreLayers.sort((a2, b2) => mapLayerIds.indexOf(b2) - mapLayerIds.indexOf(a2));
|
|
45300
|
-
return [...customLayers, ...sortedMapLibreLayers];
|
|
45301
|
-
}
|
|
45302
|
-
/**
|
|
45303
|
-
* Check if a layer is a MapLibre layer (not a custom layer)
|
|
45304
|
-
*/
|
|
45305
|
-
isMapLibreLayer(layerId) {
|
|
45306
|
-
return this.map.getLayer(layerId) !== void 0;
|
|
45307
|
-
}
|
|
45308
|
-
/**
|
|
45309
|
-
* Find the next MapLibre layer ID in a direction from a given index
|
|
45310
|
-
* @param layerIds Array of layer IDs
|
|
45311
|
-
* @param startIndex Index to start searching from
|
|
45312
|
-
* @param direction 1 for forward (toward bottom), -1 for backward (toward top)
|
|
45313
|
-
* @returns MapLibre layer ID or undefined if not found
|
|
45314
|
-
*/
|
|
45315
|
-
findNextMapLibreLayer(layerIds, startIndex, direction) {
|
|
45316
|
-
for (let i2 = startIndex; direction === 1 ? i2 < layerIds.length : i2 >= 0; i2 += direction) {
|
|
45317
|
-
if (this.isMapLibreLayer(layerIds[i2])) {
|
|
45318
|
-
return layerIds[i2];
|
|
45319
|
-
}
|
|
45320
|
-
}
|
|
45321
|
-
return void 0;
|
|
45322
|
-
}
|
|
45323
|
-
/**
|
|
45324
|
-
* Move a layer up in UI (higher rendering order = move to higher z-index)
|
|
45325
|
-
*/
|
|
45326
|
-
moveLayerUp(layerId) {
|
|
45327
|
-
var _a3, _b3;
|
|
45328
|
-
const layerIds = this.getUserLayerIdsInMapOrder();
|
|
45329
|
-
const index = layerIds.indexOf(layerId);
|
|
45330
|
-
if (index <= 0) return;
|
|
45331
|
-
const isCustom = (_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.isCustomLayer;
|
|
45332
|
-
if (!isCustom && this.isMapLibreLayer(layerId)) {
|
|
45333
|
-
try {
|
|
45334
|
-
const targetBeforeId = index >= 2 ? this.findNextMapLibreLayer(layerIds, index - 2, -1) : void 0;
|
|
45335
|
-
this.map.moveLayer(layerId, targetBeforeId);
|
|
45336
|
-
} catch (e2) {
|
|
45337
|
-
}
|
|
45338
|
-
}
|
|
45339
|
-
const newLayerStates = {};
|
|
45340
|
-
const orderedIds = [...layerIds];
|
|
45341
|
-
[orderedIds[index], orderedIds[index - 1]] = [orderedIds[index - 1], orderedIds[index]];
|
|
45342
|
-
if (this.state.layerStates["Background"]) {
|
|
45343
|
-
newLayerStates["Background"] = this.state.layerStates["Background"];
|
|
45344
|
-
}
|
|
45345
|
-
orderedIds.forEach((id2) => {
|
|
45346
|
-
if (this.state.layerStates[id2]) {
|
|
45347
|
-
newLayerStates[id2] = this.state.layerStates[id2];
|
|
45348
|
-
}
|
|
45349
|
-
});
|
|
45350
|
-
this.state.layerStates = newLayerStates;
|
|
45351
|
-
this.buildLayerItems();
|
|
45352
|
-
(_b3 = this.onLayerReorder) == null ? void 0 : _b3.call(this, this.getUserLayerIdsInMapOrder());
|
|
45353
|
-
}
|
|
45354
|
-
/**
|
|
45355
|
-
* Move a layer to the top (highest rendering order)
|
|
45356
|
-
*/
|
|
45357
|
-
moveLayerToTop(layerId) {
|
|
45358
|
-
var _a3, _b3;
|
|
45359
|
-
const layerIds = this.getUserLayerIdsInMapOrder();
|
|
45360
|
-
const index = layerIds.indexOf(layerId);
|
|
45361
|
-
if (index <= 0) return;
|
|
45362
|
-
const isCustom = (_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.isCustomLayer;
|
|
45363
|
-
if (!isCustom && this.isMapLibreLayer(layerId)) {
|
|
45364
|
-
try {
|
|
45365
|
-
this.map.moveLayer(layerId);
|
|
45366
|
-
} catch (e2) {
|
|
45367
|
-
}
|
|
45368
|
-
}
|
|
45369
|
-
const newLayerStates = {};
|
|
45370
|
-
const orderedIds = [...layerIds];
|
|
45371
|
-
orderedIds.splice(index, 1);
|
|
45372
|
-
orderedIds.unshift(layerId);
|
|
45373
|
-
if (this.state.layerStates["Background"]) {
|
|
45374
|
-
newLayerStates["Background"] = this.state.layerStates["Background"];
|
|
45375
|
-
}
|
|
45376
|
-
orderedIds.forEach((id2) => {
|
|
45377
|
-
if (this.state.layerStates[id2]) {
|
|
45378
|
-
newLayerStates[id2] = this.state.layerStates[id2];
|
|
45379
|
-
}
|
|
45380
|
-
});
|
|
45381
|
-
this.state.layerStates = newLayerStates;
|
|
45382
|
-
this.buildLayerItems();
|
|
45383
|
-
(_b3 = this.onLayerReorder) == null ? void 0 : _b3.call(this, this.getUserLayerIdsInMapOrder());
|
|
45384
|
-
}
|
|
45385
|
-
/**
|
|
45386
|
-
* Move a layer down in UI (lower rendering order = move to lower z-index)
|
|
45387
|
-
*/
|
|
45388
|
-
moveLayerDown(layerId) {
|
|
45389
|
-
var _a3, _b3;
|
|
45390
|
-
const layerIds = this.getUserLayerIdsInMapOrder();
|
|
45391
|
-
const index = layerIds.indexOf(layerId);
|
|
45392
|
-
if (index < 0 || index >= layerIds.length - 1) return;
|
|
45393
|
-
const isCustom = (_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.isCustomLayer;
|
|
45394
|
-
if (!isCustom && this.isMapLibreLayer(layerId)) {
|
|
45395
|
-
const belowLayerId = this.findNextMapLibreLayer(layerIds, index + 1, 1);
|
|
45396
|
-
if (belowLayerId) {
|
|
45397
|
-
try {
|
|
45398
|
-
this.map.moveLayer(layerId, belowLayerId);
|
|
45399
|
-
} catch (e2) {
|
|
45400
|
-
}
|
|
45401
|
-
}
|
|
45402
|
-
}
|
|
45403
|
-
const newLayerStates = {};
|
|
45404
|
-
const orderedIds = [...layerIds];
|
|
45405
|
-
[orderedIds[index], orderedIds[index + 1]] = [orderedIds[index + 1], orderedIds[index]];
|
|
45406
|
-
if (this.state.layerStates["Background"]) {
|
|
45407
|
-
newLayerStates["Background"] = this.state.layerStates["Background"];
|
|
45408
|
-
}
|
|
45409
|
-
orderedIds.forEach((id2) => {
|
|
45410
|
-
if (this.state.layerStates[id2]) {
|
|
45411
|
-
newLayerStates[id2] = this.state.layerStates[id2];
|
|
45412
|
-
}
|
|
45413
|
-
});
|
|
45414
|
-
this.state.layerStates = newLayerStates;
|
|
45415
|
-
this.buildLayerItems();
|
|
45416
|
-
(_b3 = this.onLayerReorder) == null ? void 0 : _b3.call(this, this.getUserLayerIdsInMapOrder());
|
|
45417
|
-
}
|
|
45418
|
-
/**
|
|
45419
|
-
* Move a layer to the bottom (lowest rendering order among user layers)
|
|
45420
|
-
*/
|
|
45421
|
-
moveLayerToBottom(layerId) {
|
|
45422
|
-
var _a3, _b3;
|
|
45423
|
-
const layerIds = this.getUserLayerIdsInMapOrder();
|
|
45424
|
-
if (layerIds.length <= 1) return;
|
|
45425
|
-
const index = layerIds.indexOf(layerId);
|
|
45426
|
-
if (index < 0 || index === layerIds.length - 1) return;
|
|
45427
|
-
const isCustom = (_a3 = this.state.layerStates[layerId]) == null ? void 0 : _a3.isCustomLayer;
|
|
45428
|
-
if (!isCustom && this.isMapLibreLayer(layerId)) {
|
|
45429
|
-
const bottomLayerId = this.findNextMapLibreLayer(layerIds, layerIds.length - 1, -1);
|
|
45430
|
-
if (bottomLayerId && bottomLayerId !== layerId) {
|
|
45431
|
-
try {
|
|
45432
|
-
this.map.moveLayer(layerId, bottomLayerId);
|
|
45433
|
-
} catch (e2) {
|
|
45434
|
-
}
|
|
45435
|
-
}
|
|
45436
|
-
}
|
|
45437
|
-
const newLayerStates = {};
|
|
45438
|
-
const orderedIds = [...layerIds];
|
|
45439
|
-
orderedIds.splice(index, 1);
|
|
45440
|
-
orderedIds.push(layerId);
|
|
45441
|
-
if (this.state.layerStates["Background"]) {
|
|
45442
|
-
newLayerStates["Background"] = this.state.layerStates["Background"];
|
|
45443
|
-
}
|
|
45444
|
-
orderedIds.forEach((id2) => {
|
|
45445
|
-
if (this.state.layerStates[id2]) {
|
|
45446
|
-
newLayerStates[id2] = this.state.layerStates[id2];
|
|
45447
|
-
}
|
|
45448
|
-
});
|
|
45449
|
-
this.state.layerStates = newLayerStates;
|
|
45450
|
-
this.buildLayerItems();
|
|
45451
|
-
(_b3 = this.onLayerReorder) == null ? void 0 : _b3.call(this, this.getUserLayerIdsInMapOrder());
|
|
45452
|
-
}
|
|
45453
|
-
/**
|
|
45454
|
-
* Show inline remove confirmation instead of browser confirm() dialog.
|
|
45455
|
-
* Works in Jupyter notebooks where native dialogs may not appear.
|
|
45456
|
-
*/
|
|
45457
|
-
showRemoveConfirmation(container, onConfirm) {
|
|
45458
|
-
const existing = container.querySelector(".layer-control-remove-confirm");
|
|
45459
|
-
if (existing) {
|
|
45460
|
-
existing.remove();
|
|
45461
|
-
}
|
|
45462
|
-
const confirmEl = document.createElement("div");
|
|
45463
|
-
confirmEl.className = "layer-control-remove-confirm";
|
|
45464
|
-
const message = document.createElement("div");
|
|
45465
|
-
message.className = "layer-control-remove-confirm-message";
|
|
45466
|
-
message.innerHTML = `
|
|
45467
|
-
<svg class="layer-control-remove-confirm-icon" viewBox="0 0 20 20" fill="currentColor">
|
|
45468
|
-
<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"/>
|
|
45469
|
-
</svg>
|
|
45470
|
-
<span>Remove this layer?</span>
|
|
45471
|
-
`;
|
|
45472
|
-
const buttons = document.createElement("div");
|
|
45473
|
-
buttons.className = "layer-control-remove-confirm-buttons";
|
|
45474
|
-
const cancelBtn = document.createElement("button");
|
|
45475
|
-
cancelBtn.className = "layer-control-remove-confirm-btn layer-control-remove-confirm-btn-cancel";
|
|
45476
|
-
cancelBtn.textContent = "Cancel";
|
|
45477
|
-
cancelBtn.addEventListener("click", (e2) => {
|
|
45478
|
-
e2.stopPropagation();
|
|
45479
|
-
confirmEl.remove();
|
|
45480
|
-
});
|
|
45481
|
-
const confirmBtn = document.createElement("button");
|
|
45482
|
-
confirmBtn.className = "layer-control-remove-confirm-btn layer-control-remove-confirm-btn-confirm";
|
|
45483
|
-
confirmBtn.textContent = "Remove";
|
|
45484
|
-
confirmBtn.addEventListener("click", (e2) => {
|
|
45485
|
-
e2.stopPropagation();
|
|
45486
|
-
confirmEl.remove();
|
|
45487
|
-
onConfirm();
|
|
45488
|
-
});
|
|
45489
|
-
buttons.appendChild(cancelBtn);
|
|
45490
|
-
buttons.appendChild(confirmBtn);
|
|
45491
|
-
confirmEl.appendChild(message);
|
|
45492
|
-
confirmEl.appendChild(buttons);
|
|
45493
|
-
container.appendChild(confirmEl);
|
|
45494
|
-
requestAnimationFrame(() => {
|
|
45495
|
-
confirmEl.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
45496
|
-
});
|
|
45497
|
-
}
|
|
45498
|
-
/**
|
|
45499
|
-
* Remove a layer from the map
|
|
45500
|
-
*/
|
|
45501
|
-
removeLayer(layerId) {
|
|
45502
|
-
var _a3, _b3;
|
|
45503
|
-
this.state.isStyleOperationInProgress = true;
|
|
45504
|
-
const layerState = this.state.layerStates[layerId];
|
|
45505
|
-
if ((layerState == null ? void 0 : layerState.isCustomLayer) && this.customLayerRegistry) {
|
|
45506
|
-
this.removedCustomLayerIds.add(layerId);
|
|
45507
|
-
this.customLayerRegistry.setVisibility(layerId, false);
|
|
45508
|
-
this.customLayerRegistry.removeLayer(layerId);
|
|
45509
|
-
}
|
|
45510
|
-
try {
|
|
45511
|
-
const layer = this.map.getLayer(layerId);
|
|
45512
|
-
if (layer) {
|
|
45513
|
-
const sourceId = layer.source;
|
|
45514
|
-
this.map.removeLayer(layerId);
|
|
45515
|
-
if (sourceId) {
|
|
45516
|
-
const style = this.map.getStyle();
|
|
45517
|
-
const sourceStillUsed = (_a3 = style == null ? void 0 : style.layers) == null ? void 0 : _a3.some((l3) => l3.source === sourceId);
|
|
45518
|
-
if (!sourceStillUsed) {
|
|
45519
|
-
try {
|
|
45520
|
-
this.map.removeSource(sourceId);
|
|
45521
|
-
} catch (e2) {
|
|
45522
|
-
}
|
|
45523
|
-
}
|
|
45524
|
-
}
|
|
45525
|
-
}
|
|
45526
|
-
} catch (error) {
|
|
45527
|
-
console.warn(`Failed to remove layer ${layerId}:`, error);
|
|
45528
|
-
}
|
|
45529
|
-
delete this.state.layerStates[layerId];
|
|
45530
|
-
this.state.customLayerNames.delete(layerId);
|
|
45531
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
45532
|
-
if (itemEl) {
|
|
45533
|
-
itemEl.remove();
|
|
45534
|
-
}
|
|
45535
|
-
(_b3 = this.onLayerRemove) == null ? void 0 : _b3.call(this, layerId);
|
|
45536
|
-
setTimeout(() => {
|
|
45537
|
-
this.state.isStyleOperationInProgress = false;
|
|
45538
|
-
}, 200);
|
|
45539
|
-
}
|
|
45540
|
-
// ===== Drag and Drop Methods =====
|
|
45541
|
-
/**
|
|
45542
|
-
* Create drag handle element
|
|
45543
|
-
*/
|
|
45544
|
-
createDragHandle(layerId) {
|
|
45545
|
-
const handle = document.createElement("div");
|
|
45546
|
-
handle.className = "layer-control-drag-handle";
|
|
45547
|
-
handle.innerHTML = `<svg viewBox="0 0 16 16" fill="currentColor">
|
|
45548
|
-
<circle cx="5" cy="3" r="1.5"/>
|
|
45549
|
-
<circle cx="11" cy="3" r="1.5"/>
|
|
45550
|
-
<circle cx="5" cy="8" r="1.5"/>
|
|
45551
|
-
<circle cx="11" cy="8" r="1.5"/>
|
|
45552
|
-
<circle cx="5" cy="13" r="1.5"/>
|
|
45553
|
-
<circle cx="11" cy="13" r="1.5"/>
|
|
45554
|
-
</svg>`;
|
|
45555
|
-
handle.title = "Drag to reorder";
|
|
45556
|
-
handle.addEventListener("pointerdown", (e2) => {
|
|
45557
|
-
e2.preventDefault();
|
|
45558
|
-
e2.stopPropagation();
|
|
45559
|
-
this.startDrag(layerId, e2);
|
|
45560
|
-
});
|
|
45561
|
-
return handle;
|
|
45562
|
-
}
|
|
45563
|
-
/**
|
|
45564
|
-
* Create a disabled drag handle for alignment (used for Background layer)
|
|
45565
|
-
*/
|
|
45566
|
-
createDisabledDragHandle() {
|
|
45567
|
-
const handle = document.createElement("div");
|
|
45568
|
-
handle.className = "layer-control-drag-handle layer-control-drag-handle-disabled";
|
|
45569
|
-
handle.innerHTML = `<svg viewBox="0 0 16 16" fill="currentColor">
|
|
45570
|
-
<circle cx="5" cy="3" r="1.5"/>
|
|
45571
|
-
<circle cx="11" cy="3" r="1.5"/>
|
|
45572
|
-
<circle cx="5" cy="8" r="1.5"/>
|
|
45573
|
-
<circle cx="11" cy="8" r="1.5"/>
|
|
45574
|
-
<circle cx="5" cy="13" r="1.5"/>
|
|
45575
|
-
<circle cx="11" cy="13" r="1.5"/>
|
|
45576
|
-
</svg>`;
|
|
45577
|
-
return handle;
|
|
45578
|
-
}
|
|
45579
|
-
/**
|
|
45580
|
-
* Start dragging a layer
|
|
45581
|
-
*/
|
|
45582
|
-
startDrag(layerId, e2) {
|
|
45583
|
-
var _a3;
|
|
45584
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
45585
|
-
if (!itemEl) return;
|
|
45586
|
-
const rect = itemEl.getBoundingClientRect();
|
|
45587
|
-
this.state.drag = {
|
|
45588
|
-
active: true,
|
|
45589
|
-
layerId,
|
|
45590
|
-
startY: e2.clientY,
|
|
45591
|
-
currentY: e2.clientY,
|
|
45592
|
-
placeholder: null,
|
|
45593
|
-
draggedElement: null
|
|
45594
|
-
};
|
|
45595
|
-
this.panel.classList.add("dragging-active");
|
|
45596
|
-
itemEl.classList.add("dragging");
|
|
45597
|
-
const placeholder = document.createElement("div");
|
|
45598
|
-
placeholder.className = "layer-control-drop-placeholder";
|
|
45599
|
-
placeholder.style.height = `${rect.height}px`;
|
|
45600
|
-
(_a3 = itemEl.parentNode) == null ? void 0 : _a3.insertBefore(placeholder, itemEl);
|
|
45601
|
-
this.state.drag.placeholder = placeholder;
|
|
45602
|
-
const clone2 = itemEl.cloneNode(true);
|
|
45603
|
-
clone2.classList.remove("dragging");
|
|
45604
|
-
clone2.className = "layer-control-item layer-control-item-dragging";
|
|
45605
|
-
clone2.style.width = `${rect.width}px`;
|
|
45606
|
-
clone2.style.left = `${rect.left}px`;
|
|
45607
|
-
clone2.style.top = `${rect.top}px`;
|
|
45608
|
-
document.body.appendChild(clone2);
|
|
45609
|
-
this.state.drag.draggedElement = clone2;
|
|
45610
|
-
const onMove = (moveE) => this.onDragMove(moveE);
|
|
45611
|
-
const onEnd = (endE) => {
|
|
45612
|
-
document.removeEventListener("pointermove", onMove);
|
|
45613
|
-
document.removeEventListener("pointerup", onEnd);
|
|
45614
|
-
document.removeEventListener("pointercancel", onEnd);
|
|
45615
|
-
this.endDrag(endE);
|
|
45616
|
-
};
|
|
45617
|
-
document.addEventListener("pointermove", onMove);
|
|
45618
|
-
document.addEventListener("pointerup", onEnd);
|
|
45619
|
-
document.addEventListener("pointercancel", onEnd);
|
|
45620
|
-
}
|
|
45621
|
-
/**
|
|
45622
|
-
* Handle drag move
|
|
45623
|
-
*/
|
|
45624
|
-
onDragMove(e2) {
|
|
45625
|
-
var _a3, _b3;
|
|
45626
|
-
if (!this.state.drag.active || !this.state.drag.draggedElement) return;
|
|
45627
|
-
const placeholder = this.state.drag.placeholder;
|
|
45628
|
-
if (!placeholder) return;
|
|
45629
|
-
const deltaY = e2.clientY - this.state.drag.startY;
|
|
45630
|
-
const clone2 = this.state.drag.draggedElement;
|
|
45631
|
-
const currentTop = parseFloat(clone2.style.top) || 0;
|
|
45632
|
-
clone2.style.top = `${currentTop + deltaY}px`;
|
|
45633
|
-
this.state.drag.startY = e2.clientY;
|
|
45634
|
-
this.state.drag.currentY = e2.clientY;
|
|
45635
|
-
const items2 = Array.from(this.panel.querySelectorAll(".layer-control-item:not(.dragging)")).filter((item) => item.dataset.layerId !== "Background");
|
|
45636
|
-
for (const item of items2) {
|
|
45637
|
-
const itemRect = item.getBoundingClientRect();
|
|
45638
|
-
if (e2.clientY >= itemRect.top && e2.clientY <= itemRect.bottom) {
|
|
45639
|
-
const itemMiddle = itemRect.top + itemRect.height / 2;
|
|
45640
|
-
if (e2.clientY < itemMiddle) {
|
|
45641
|
-
if (placeholder.nextSibling !== item) {
|
|
45642
|
-
(_a3 = item.parentNode) == null ? void 0 : _a3.insertBefore(placeholder, item);
|
|
45643
|
-
}
|
|
45644
|
-
} else {
|
|
45645
|
-
if (placeholder.previousSibling !== item) {
|
|
45646
|
-
(_b3 = item.parentNode) == null ? void 0 : _b3.insertBefore(placeholder, item.nextSibling);
|
|
45647
|
-
}
|
|
45648
|
-
}
|
|
45649
|
-
break;
|
|
45650
|
-
}
|
|
45651
|
-
}
|
|
45652
|
-
}
|
|
45653
|
-
/**
|
|
45654
|
-
* End dragging
|
|
45655
|
-
*/
|
|
45656
|
-
endDrag(_e2) {
|
|
45657
|
-
var _a3;
|
|
45658
|
-
if (!this.state.drag.active) return;
|
|
45659
|
-
const layerId = this.state.drag.layerId;
|
|
45660
|
-
const placeholder = this.state.drag.placeholder;
|
|
45661
|
-
const itemEl = this.panel.querySelector(`[data-layer-id="${layerId}"]`);
|
|
45662
|
-
if (itemEl && placeholder) {
|
|
45663
|
-
(_a3 = placeholder.parentNode) == null ? void 0 : _a3.insertBefore(itemEl, placeholder);
|
|
45664
|
-
itemEl.classList.remove("dragging");
|
|
45665
|
-
}
|
|
45666
|
-
this.cleanupDragState();
|
|
45667
|
-
this.applyUIOrderToMap();
|
|
45668
|
-
}
|
|
45669
|
-
/**
|
|
45670
|
-
* Clean up drag state
|
|
45671
|
-
*/
|
|
45672
|
-
cleanupDragState() {
|
|
45673
|
-
if (this.state.drag.draggedElement) {
|
|
45674
|
-
this.state.drag.draggedElement.remove();
|
|
45675
|
-
}
|
|
45676
|
-
if (this.state.drag.placeholder) {
|
|
45677
|
-
this.state.drag.placeholder.remove();
|
|
45678
|
-
}
|
|
45679
|
-
this.panel.classList.remove("dragging-active");
|
|
45680
|
-
this.panel.querySelectorAll(".layer-control-item.dragging").forEach((el) => {
|
|
45681
|
-
el.classList.remove("dragging");
|
|
45682
|
-
});
|
|
45683
|
-
this.state.drag = {
|
|
45684
|
-
active: false,
|
|
45685
|
-
layerId: null,
|
|
45686
|
-
startY: 0,
|
|
45687
|
-
currentY: 0,
|
|
45688
|
-
placeholder: null,
|
|
45689
|
-
draggedElement: null
|
|
45690
|
-
};
|
|
45691
|
-
}
|
|
45692
|
-
/**
|
|
45693
|
-
* Apply UI order to map layers
|
|
45694
|
-
*/
|
|
45695
|
-
applyUIOrderToMap() {
|
|
45696
|
-
var _a3, _b3;
|
|
45697
|
-
this.state.isStyleOperationInProgress = true;
|
|
45698
|
-
const items2 = this.panel.querySelectorAll(".layer-control-item");
|
|
45699
|
-
const uiLayerIds = [];
|
|
45700
|
-
items2.forEach((item) => {
|
|
45701
|
-
const layerId = item.dataset.layerId;
|
|
45702
|
-
if (layerId && layerId !== "Background") {
|
|
45703
|
-
uiLayerIds.push(layerId);
|
|
45704
|
-
}
|
|
45705
|
-
});
|
|
45706
|
-
const reversedIds = [...uiLayerIds].reverse();
|
|
45707
|
-
const style = this.map.getStyle();
|
|
45708
|
-
const mapLibreLayerIds = new Set(((_a3 = style == null ? void 0 : style.layers) == null ? void 0 : _a3.map((l3) => l3.id)) || []);
|
|
45709
|
-
for (let i2 = 0; i2 < reversedIds.length; i2++) {
|
|
45710
|
-
const layerId = reversedIds[i2];
|
|
45711
|
-
if (!mapLibreLayerIds.has(layerId)) {
|
|
45712
|
-
continue;
|
|
45713
|
-
}
|
|
45714
|
-
let beforeId = void 0;
|
|
45715
|
-
for (let j2 = i2 - 1; j2 >= 0; j2--) {
|
|
45716
|
-
if (mapLibreLayerIds.has(reversedIds[j2])) {
|
|
45717
|
-
beforeId = reversedIds[j2];
|
|
45718
|
-
break;
|
|
45719
|
-
}
|
|
45720
|
-
}
|
|
45721
|
-
try {
|
|
45722
|
-
this.map.moveLayer(layerId, beforeId);
|
|
45723
|
-
} catch (e2) {
|
|
45724
|
-
}
|
|
45725
|
-
}
|
|
45726
|
-
(_b3 = this.onLayerReorder) == null ? void 0 : _b3.call(this, uiLayerIds);
|
|
45727
|
-
setTimeout(() => {
|
|
45728
|
-
this.state.isStyleOperationInProgress = false;
|
|
45729
|
-
}, 200);
|
|
45730
|
-
}
|
|
45731
|
-
}
|
|
45732
42208
|
const DEFAULT_BASEMAPS = {
|
|
45733
42209
|
liberty: "https://tiles.openfreemap.org/styles/liberty",
|
|
45734
42210
|
positron: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
|
|
@@ -45948,9 +42424,6 @@ function toJsonValue(value) {
|
|
|
45948
42424
|
return String(value);
|
|
45949
42425
|
}
|
|
45950
42426
|
}
|
|
45951
|
-
function basemapStyleUrl(style) {
|
|
45952
|
-
return typeof style === "string" && /^https?:\/\//.test(style) ? style : void 0;
|
|
45953
|
-
}
|
|
45954
42427
|
class MapLibreAgentTools {
|
|
45955
42428
|
constructor(map, options) {
|
|
45956
42429
|
__publicField(this, "map");
|
|
@@ -45958,34 +42431,13 @@ class MapLibreAgentTools {
|
|
|
45958
42431
|
__publicField(this, "allowCodeExecution");
|
|
45959
42432
|
__publicField(this, "allowDestructiveTools");
|
|
45960
42433
|
__publicField(this, "overlays", new globalThis.Map());
|
|
45961
|
-
__publicField(this, "layerControl", null);
|
|
45962
|
-
__publicField(this, "pendingLayerControlInstallHandler", null);
|
|
45963
42434
|
this.map = map;
|
|
45964
42435
|
this.basemaps = { ...DEFAULT_BASEMAPS, ...options.basemaps };
|
|
45965
42436
|
this.allowCodeExecution = options.allowCodeExecution;
|
|
45966
42437
|
this.allowDestructiveTools = options.allowDestructiveTools;
|
|
45967
42438
|
}
|
|
45968
42439
|
destroy() {
|
|
45969
|
-
if (this.pendingLayerControlInstallHandler) {
|
|
45970
|
-
this.map.off("load", this.pendingLayerControlInstallHandler);
|
|
45971
|
-
this.pendingLayerControlInstallHandler = null;
|
|
45972
|
-
}
|
|
45973
42440
|
this.clearOverlays();
|
|
45974
|
-
this.removeLayerControl();
|
|
45975
|
-
}
|
|
45976
|
-
installDefaultLayerControl() {
|
|
45977
|
-
if (this.layerControl || this.pendingLayerControlInstallHandler) {
|
|
45978
|
-
return;
|
|
45979
|
-
}
|
|
45980
|
-
if (this.map.loaded()) {
|
|
45981
|
-
this.installLayerControl();
|
|
45982
|
-
return;
|
|
45983
|
-
}
|
|
45984
|
-
this.pendingLayerControlInstallHandler = () => {
|
|
45985
|
-
this.pendingLayerControlInstallHandler = null;
|
|
45986
|
-
this.installLayerControl();
|
|
45987
|
-
};
|
|
45988
|
-
this.map.once("load", this.pendingLayerControlInstallHandler);
|
|
45989
42441
|
}
|
|
45990
42442
|
createTools() {
|
|
45991
42443
|
const optionalStyleSchema = record(string(), any()).optional().describe("Optional MapLibre-compatible paint/style values.");
|
|
@@ -46256,11 +42708,9 @@ class MapLibreAgentTools {
|
|
|
46256
42708
|
if (typeof style === "string" && this.basemaps[style]) {
|
|
46257
42709
|
style = this.basemaps[style];
|
|
46258
42710
|
}
|
|
46259
|
-
this.removeLayerControl();
|
|
46260
42711
|
this.map.setStyle(style);
|
|
46261
42712
|
await new Promise((resolve2) => this.map.once("style.load", () => resolve2()));
|
|
46262
42713
|
await this.restoreOverlaysAfterStyleChange();
|
|
46263
|
-
this.installLayerControl(style);
|
|
46264
42714
|
return `Basemap changed to ${rawStyle}.`;
|
|
46265
42715
|
}
|
|
46266
42716
|
if (command === "add_marker") {
|
|
@@ -46630,25 +43080,6 @@ ${code2}
|
|
|
46630
43080
|
}
|
|
46631
43081
|
}
|
|
46632
43082
|
}
|
|
46633
|
-
installLayerControl(style) {
|
|
46634
|
-
this.removeLayerControl();
|
|
46635
|
-
const styleUrl = style ? basemapStyleUrl(style) : void 0;
|
|
46636
|
-
this.layerControl = new LayerControl({
|
|
46637
|
-
collapsed: true,
|
|
46638
|
-
...styleUrl ? { basemapStyleUrl: styleUrl } : {},
|
|
46639
|
-
panelWidth: 320,
|
|
46640
|
-
panelMinWidth: 240,
|
|
46641
|
-
panelMaxWidth: 420
|
|
46642
|
-
});
|
|
46643
|
-
this.map.addControl(this.layerControl, "top-right");
|
|
46644
|
-
}
|
|
46645
|
-
removeLayerControl() {
|
|
46646
|
-
if (!this.layerControl) {
|
|
46647
|
-
return;
|
|
46648
|
-
}
|
|
46649
|
-
this.map.removeControl(this.layerControl);
|
|
46650
|
-
this.layerControl = null;
|
|
46651
|
-
}
|
|
46652
43083
|
requireDestructiveApproval(action) {
|
|
46653
43084
|
if (!this.allowDestructiveTools()) {
|
|
46654
43085
|
throw new Error(`${action} is disabled. Enable layer removal first.`);
|
|
@@ -46799,7 +43230,6 @@ class GeoAgentControl {
|
|
|
46799
43230
|
allowCodeExecution: () => this.state.allowCodeExecution,
|
|
46800
43231
|
allowDestructiveTools: () => this.state.allowDestructiveTools
|
|
46801
43232
|
});
|
|
46802
|
-
this.tools.installDefaultLayerControl();
|
|
46803
43233
|
this.setupEventListeners();
|
|
46804
43234
|
this.loadProviderSettings();
|
|
46805
43235
|
this.setStatus("Ready", "connected");
|
|
@@ -47458,7 +43888,7 @@ ${markdown.trim()}`;
|
|
|
47458
43888
|
}
|
|
47459
43889
|
async createProviderModel(providerId, modelId, apiKey, bedrockRegion) {
|
|
47460
43890
|
if (providerId === "openai-responses" || providerId === "openai-chat") {
|
|
47461
|
-
const { OpenAIModel } = await import("./index-
|
|
43891
|
+
const { OpenAIModel } = await import("./index-BU4LZEvR.js");
|
|
47462
43892
|
return new OpenAIModel({
|
|
47463
43893
|
api: providerId === "openai-responses" ? "responses" : "chat",
|
|
47464
43894
|
modelId,
|
|
@@ -47469,7 +43899,7 @@ ${markdown.trim()}`;
|
|
|
47469
43899
|
});
|
|
47470
43900
|
}
|
|
47471
43901
|
if (providerId === "anthropic") {
|
|
47472
|
-
const { AnthropicModel } = await import("./anthropic-
|
|
43902
|
+
const { AnthropicModel } = await import("./anthropic-DhbSHleV.js");
|
|
47473
43903
|
return new AnthropicModel({
|
|
47474
43904
|
modelId,
|
|
47475
43905
|
apiKey,
|
|
@@ -47479,7 +43909,7 @@ ${markdown.trim()}`;
|
|
|
47479
43909
|
});
|
|
47480
43910
|
}
|
|
47481
43911
|
if (providerId === "google") {
|
|
47482
|
-
const { GoogleModel } = await import("./index-
|
|
43912
|
+
const { GoogleModel } = await import("./index-DXB0TYg3.js");
|
|
47483
43913
|
return new GoogleModel({
|
|
47484
43914
|
modelId,
|
|
47485
43915
|
apiKey
|
|
@@ -47689,4 +44119,4 @@ export {
|
|
|
47689
44119
|
toJsonValue as t,
|
|
47690
44120
|
warnOnce as w
|
|
47691
44121
|
};
|
|
47692
|
-
//# sourceMappingURL=GeoAgentControl-
|
|
44122
|
+
//# sourceMappingURL=GeoAgentControl-DOAYVbPg.js.map
|