maplibre-gl-basemap-control 0.8.0 → 0.10.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/{BasemapControl-C9T87uJx.js → BasemapControl-AGhhvlrX.js} +247 -16
- package/dist/BasemapControl-AGhhvlrX.js.map +1 -0
- package/dist/{BasemapControl-Dl0aWr1N.cjs → BasemapControl-DXJHjc6Z.cjs} +247 -16
- package/dist/BasemapControl-DXJHjc6Z.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.mjs +1 -1
- package/dist/types/lib/core/BasemapControl.d.ts +4 -0
- package/dist/types/lib/core/BasemapControl.d.ts.map +1 -1
- package/dist/types/lib/core/catalog.d.ts.map +1 -1
- package/dist/types/lib/core/types.d.ts +17 -0
- package/dist/types/lib/core/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/BasemapControl-C9T87uJx.js.map +0 -1
- package/dist/BasemapControl-Dl0aWr1N.cjs.map +0 -1
|
@@ -5,6 +5,7 @@ const DEFAULT_BASEMAP_PROVIDERS = [
|
|
|
5
5
|
{ id: "amazon", name: "Amazon Location", category: "General" },
|
|
6
6
|
{ id: "carto", name: "Carto", category: "General" },
|
|
7
7
|
{ id: "cyclosm", name: "CyclOSM", category: "Cycling" },
|
|
8
|
+
{ id: "eox", name: "EOX", category: "Imagery" },
|
|
8
9
|
{ id: "esri", name: "ESRI", category: "Imagery" },
|
|
9
10
|
{ id: "google", name: "Google", category: "General" },
|
|
10
11
|
{ id: "here", name: "HERE", category: "Traffic" },
|
|
@@ -149,6 +150,8 @@ const OPENFREEMAP_ATTRIBUTION = "OpenFreeMap © OpenMapTiles Data from OpenS
|
|
|
149
150
|
const TOMTOM_ATTRIBUTION = "© TomTom";
|
|
150
151
|
const HERE_ATTRIBUTION = "© HERE";
|
|
151
152
|
const GOOGLE_ATTRIBUTION = "© Google";
|
|
153
|
+
const EOX_S2CLOUDLESS_ATTRIBUTION = 'Sentinel-2 cloudless <a href="https://cloudless.eox.at" target="_blank" rel="noopener">EOxCloudless</a> by EOX IT Services GmbH (Contains modified Copernicus Sentinel data 2025)';
|
|
154
|
+
const EOX_TERRAIN_LIGHT_ATTRIBUTION = 'Terrain Light <a href="https://maps.eox.at" target="_blank" rel="noopener">EOX</a> (Data © OpenStreetMap contributors and others, Rendering © EOX)';
|
|
152
155
|
const MAPBOX_TRAFFIC_CONGESTION_COLORS = [
|
|
153
156
|
"match",
|
|
154
157
|
["get", "congestion"],
|
|
@@ -517,7 +520,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
517
520
|
category: "Labels",
|
|
518
521
|
description: "Carto Positron labels layer.",
|
|
519
522
|
attribution: CARTO_ATTRIBUTION,
|
|
520
|
-
tiles: [
|
|
523
|
+
tiles: [
|
|
524
|
+
"https://a.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png"
|
|
525
|
+
],
|
|
521
526
|
maxzoom: 20,
|
|
522
527
|
tags: ["carto", "labels"]
|
|
523
528
|
}),
|
|
@@ -582,7 +587,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
582
587
|
category: "Street",
|
|
583
588
|
description: "Carto Voyager without labels.",
|
|
584
589
|
attribution: CARTO_ATTRIBUTION,
|
|
585
|
-
tiles: [
|
|
590
|
+
tiles: [
|
|
591
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png"
|
|
592
|
+
],
|
|
586
593
|
maxzoom: 20,
|
|
587
594
|
tags: ["carto", "voyager", "no labels"]
|
|
588
595
|
}),
|
|
@@ -593,7 +600,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
593
600
|
category: "Labels",
|
|
594
601
|
description: "Carto Voyager labels layer.",
|
|
595
602
|
attribution: CARTO_ATTRIBUTION,
|
|
596
|
-
tiles: [
|
|
603
|
+
tiles: [
|
|
604
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png"
|
|
605
|
+
],
|
|
597
606
|
maxzoom: 20,
|
|
598
607
|
tags: ["carto", "voyager", "labels"]
|
|
599
608
|
}),
|
|
@@ -604,7 +613,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
604
613
|
category: "Street",
|
|
605
614
|
description: "Carto Voyager labels-under variant.",
|
|
606
615
|
attribution: CARTO_ATTRIBUTION,
|
|
607
|
-
tiles: [
|
|
616
|
+
tiles: [
|
|
617
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
|
|
618
|
+
],
|
|
608
619
|
maxzoom: 20,
|
|
609
620
|
tags: ["carto", "voyager", "labels"]
|
|
610
621
|
}),
|
|
@@ -726,6 +737,39 @@ const DEFAULT_BASEMAPS = [
|
|
|
726
737
|
],
|
|
727
738
|
tags: ["esri", "terrain"]
|
|
728
739
|
}),
|
|
740
|
+
rasterBasemap({
|
|
741
|
+
id: "eox-s2cloudless-2025",
|
|
742
|
+
name: "EOX Sentinel-2 cloudless 2025",
|
|
743
|
+
provider: "eox",
|
|
744
|
+
category: "Imagery",
|
|
745
|
+
description: "Cloudless Sentinel-2 satellite mosaic for 2025 (non-commercial use).",
|
|
746
|
+
attribution: EOX_S2CLOUDLESS_ATTRIBUTION,
|
|
747
|
+
tiles: [
|
|
748
|
+
"https://tiles.maps.eox.at/wmts/1.0.0/s2cloudless-2025_3857/default/GoogleMapsCompatible/{z}/{y}/{x}.jpg"
|
|
749
|
+
],
|
|
750
|
+
maxzoom: 16,
|
|
751
|
+
tags: [
|
|
752
|
+
"eox",
|
|
753
|
+
"sentinel",
|
|
754
|
+
"satellite",
|
|
755
|
+
"imagery",
|
|
756
|
+
"cloudless",
|
|
757
|
+
"copernicus"
|
|
758
|
+
]
|
|
759
|
+
}),
|
|
760
|
+
rasterBasemap({
|
|
761
|
+
id: "eox-terrain-light",
|
|
762
|
+
name: "EOX Terrain Light",
|
|
763
|
+
provider: "eox",
|
|
764
|
+
category: "Terrain",
|
|
765
|
+
description: "Light terrain basemap from EOX Maps (non-commercial use).",
|
|
766
|
+
attribution: EOX_TERRAIN_LIGHT_ATTRIBUTION,
|
|
767
|
+
tiles: [
|
|
768
|
+
"https://tiles.maps.eox.at/wmts/1.0.0/terrain-light_3857/default/GoogleMapsCompatible/{z}/{y}/{x}.jpg"
|
|
769
|
+
],
|
|
770
|
+
maxzoom: 14,
|
|
771
|
+
tags: ["eox", "terrain", "light", "hillshade"]
|
|
772
|
+
}),
|
|
729
773
|
rasterBasemap({
|
|
730
774
|
id: "nasa-gibs-blue-marble",
|
|
731
775
|
name: "Blue Marble",
|
|
@@ -1111,7 +1155,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
1111
1155
|
provider: "tomtom",
|
|
1112
1156
|
description: "TomTom traffic speeds relative to free-flow speed. Requires a TomTom API key.",
|
|
1113
1157
|
attribution: TOMTOM_ATTRIBUTION,
|
|
1114
|
-
tiles: [
|
|
1158
|
+
tiles: [
|
|
1159
|
+
"https://api.tomtom.com/traffic/map/4/tile/flow/relative0/{z}/{x}/{y}.png?key={api-key}"
|
|
1160
|
+
],
|
|
1115
1161
|
tags: ["tomtom", "flow", "relative"]
|
|
1116
1162
|
}),
|
|
1117
1163
|
rasterTrafficBasemap({
|
|
@@ -1120,7 +1166,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
1120
1166
|
provider: "tomtom",
|
|
1121
1167
|
description: "TomTom traffic colored by absolute speed. Requires a TomTom API key.",
|
|
1122
1168
|
attribution: TOMTOM_ATTRIBUTION,
|
|
1123
|
-
tiles: [
|
|
1169
|
+
tiles: [
|
|
1170
|
+
"https://api.tomtom.com/traffic/map/4/tile/flow/absolute/{z}/{x}/{y}.png?key={api-key}"
|
|
1171
|
+
],
|
|
1124
1172
|
tags: ["tomtom", "flow", "absolute"]
|
|
1125
1173
|
}),
|
|
1126
1174
|
rasterTrafficBasemap({
|
|
@@ -1140,7 +1188,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
1140
1188
|
provider: "here",
|
|
1141
1189
|
description: "HERE real-time traffic flow overlay. Requires a HERE API key.",
|
|
1142
1190
|
attribution: HERE_ATTRIBUTION,
|
|
1143
|
-
tiles: [
|
|
1191
|
+
tiles: [
|
|
1192
|
+
"https://traffic.maps.hereapi.com/v3/flow/mc/{z}/{x}/{y}/png?apiKey={api-key}"
|
|
1193
|
+
],
|
|
1144
1194
|
tags: ["here", "flow"]
|
|
1145
1195
|
}),
|
|
1146
1196
|
{
|
|
@@ -1161,7 +1211,17 @@ const DEFAULT_BASEMAPS = [
|
|
|
1161
1211
|
"line-cap": "round"
|
|
1162
1212
|
},
|
|
1163
1213
|
paint: {
|
|
1164
|
-
"line-width": [
|
|
1214
|
+
"line-width": [
|
|
1215
|
+
"interpolate",
|
|
1216
|
+
["linear"],
|
|
1217
|
+
["zoom"],
|
|
1218
|
+
6,
|
|
1219
|
+
1.5,
|
|
1220
|
+
14,
|
|
1221
|
+
4,
|
|
1222
|
+
18,
|
|
1223
|
+
8
|
|
1224
|
+
],
|
|
1165
1225
|
"line-color": MAPBOX_TRAFFIC_CONGESTION_COLORS
|
|
1166
1226
|
}
|
|
1167
1227
|
},
|
|
@@ -1177,7 +1237,9 @@ const DEFAULT_BASEMAPS = [
|
|
|
1177
1237
|
attribution: GOOGLE_ATTRIBUTION,
|
|
1178
1238
|
source: {
|
|
1179
1239
|
type: "raster",
|
|
1180
|
-
tiles: [
|
|
1240
|
+
tiles: [
|
|
1241
|
+
"https://tile.googleapis.com/v1/2dtiles/{z}/{x}/{y}?session={session}&key={api-key}"
|
|
1242
|
+
],
|
|
1181
1243
|
tileSize: 256,
|
|
1182
1244
|
maxzoom: 22,
|
|
1183
1245
|
googleSession: {
|
|
@@ -1198,12 +1260,17 @@ function combineProviders(defaults, custom = []) {
|
|
|
1198
1260
|
function resolveBasemapProviders(basemaps, customProviders = [], includeDefaultProviders = true) {
|
|
1199
1261
|
const byId = /* @__PURE__ */ new Map();
|
|
1200
1262
|
if (includeDefaultProviders) {
|
|
1201
|
-
DEFAULT_BASEMAP_PROVIDERS.forEach(
|
|
1263
|
+
DEFAULT_BASEMAP_PROVIDERS.forEach(
|
|
1264
|
+
(provider) => byId.set(provider.id, provider)
|
|
1265
|
+
);
|
|
1202
1266
|
}
|
|
1203
1267
|
customProviders.forEach((provider) => byId.set(provider.id, provider));
|
|
1204
1268
|
basemaps.forEach((basemap) => {
|
|
1205
1269
|
if (basemap.provider && !byId.has(basemap.provider)) {
|
|
1206
|
-
byId.set(basemap.provider, {
|
|
1270
|
+
byId.set(basemap.provider, {
|
|
1271
|
+
id: basemap.provider,
|
|
1272
|
+
name: basemap.provider
|
|
1273
|
+
});
|
|
1207
1274
|
}
|
|
1208
1275
|
});
|
|
1209
1276
|
return sortProviders([...byId.values()]);
|
|
@@ -1232,7 +1299,11 @@ function filterBasemaps(basemaps, filter) {
|
|
|
1232
1299
|
});
|
|
1233
1300
|
}
|
|
1234
1301
|
function getBasemapCategories(basemaps) {
|
|
1235
|
-
return [
|
|
1302
|
+
return [
|
|
1303
|
+
...new Set(
|
|
1304
|
+
basemaps.map((basemap) => basemap.category).filter(Boolean)
|
|
1305
|
+
)
|
|
1306
|
+
].sort();
|
|
1236
1307
|
}
|
|
1237
1308
|
const DEFAULT_OPTIONS = {
|
|
1238
1309
|
collapsed: true,
|
|
@@ -1278,6 +1349,7 @@ const PROVIDER_CREDENTIAL_HELP = {
|
|
|
1278
1349
|
label: "Get a Google Maps API key"
|
|
1279
1350
|
}
|
|
1280
1351
|
};
|
|
1352
|
+
const STYLE_AUTH_GRACE_MS = 2500;
|
|
1281
1353
|
const MIN_PANEL_WIDTH = 240;
|
|
1282
1354
|
const MIN_PANEL_HEIGHT = 200;
|
|
1283
1355
|
const PANEL_VIEWPORT_MARGIN = 12;
|
|
@@ -1289,6 +1361,30 @@ class MissingCredentialError extends Error {
|
|
|
1289
1361
|
this.provider = provider;
|
|
1290
1362
|
}
|
|
1291
1363
|
}
|
|
1364
|
+
class BasemapLoadError extends Error {
|
|
1365
|
+
constructor(message, provider, status) {
|
|
1366
|
+
super(message);
|
|
1367
|
+
__publicField(this, "provider");
|
|
1368
|
+
__publicField(this, "status");
|
|
1369
|
+
this.name = "BasemapLoadError";
|
|
1370
|
+
this.provider = provider;
|
|
1371
|
+
this.status = status;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
function extractErrorUrl(error) {
|
|
1375
|
+
if (error && typeof error === "object" && "url" in error) {
|
|
1376
|
+
const url = error.url;
|
|
1377
|
+
if (typeof url === "string") return url;
|
|
1378
|
+
}
|
|
1379
|
+
return void 0;
|
|
1380
|
+
}
|
|
1381
|
+
function extractErrorStatus(error) {
|
|
1382
|
+
if (error && typeof error === "object" && "status" in error) {
|
|
1383
|
+
const status = error.status;
|
|
1384
|
+
if (typeof status === "number" && status > 0) return status;
|
|
1385
|
+
}
|
|
1386
|
+
return void 0;
|
|
1387
|
+
}
|
|
1292
1388
|
class BasemapControl {
|
|
1293
1389
|
constructor(options) {
|
|
1294
1390
|
__publicField(this, "_map");
|
|
@@ -1328,6 +1424,10 @@ class BasemapControl {
|
|
|
1328
1424
|
// The basemap whose application last failed for a missing credential, so the
|
|
1329
1425
|
// inline credential field's Enter key can re-attempt it (#837).
|
|
1330
1426
|
__publicField(this, "_lastFailedBasemapId");
|
|
1427
|
+
// Detaches the listeners watching the in-flight style load (see
|
|
1428
|
+
// _watchStyleLoad). Set while a style swap is settling, cleared once it
|
|
1429
|
+
// succeeds, fails, or is superseded by a newer swap.
|
|
1430
|
+
__publicField(this, "_cancelStyleWatch");
|
|
1331
1431
|
__publicField(this, "_resizeHandler", null);
|
|
1332
1432
|
__publicField(this, "_mapResizeHandler", null);
|
|
1333
1433
|
__publicField(this, "_resizeAnchor", null);
|
|
@@ -1406,7 +1506,7 @@ class BasemapControl {
|
|
|
1406
1506
|
return this._container;
|
|
1407
1507
|
}
|
|
1408
1508
|
onRemove() {
|
|
1409
|
-
var _a, _b, _c, _d;
|
|
1509
|
+
var _a, _b, _c, _d, _e;
|
|
1410
1510
|
if (this._resizeHandler) {
|
|
1411
1511
|
window.removeEventListener("resize", this._resizeHandler);
|
|
1412
1512
|
this._resizeHandler = null;
|
|
@@ -1418,10 +1518,11 @@ class BasemapControl {
|
|
|
1418
1518
|
window.removeEventListener("pointermove", this._onResizeMove);
|
|
1419
1519
|
window.removeEventListener("pointerup", this._onResizeEnd);
|
|
1420
1520
|
window.removeEventListener("pointercancel", this._onResizeEnd);
|
|
1521
|
+
(_a = this._cancelStyleWatch) == null ? void 0 : _a.call(this);
|
|
1421
1522
|
this._resizeAnchor = null;
|
|
1422
1523
|
this._resizeHandleEl = null;
|
|
1423
|
-
(
|
|
1424
|
-
(
|
|
1524
|
+
(_c = (_b = this._panel) == null ? void 0 : _b.parentNode) == null ? void 0 : _c.removeChild(this._panel);
|
|
1525
|
+
(_e = (_d = this._container) == null ? void 0 : _d.parentNode) == null ? void 0 : _e.removeChild(this._container);
|
|
1425
1526
|
this._map = void 0;
|
|
1426
1527
|
this._mapContainer = void 0;
|
|
1427
1528
|
this._container = void 0;
|
|
@@ -1598,8 +1699,10 @@ class BasemapControl {
|
|
|
1598
1699
|
this._state = { ...this._state, loading: true, error: void 0 };
|
|
1599
1700
|
this._renderContent(true);
|
|
1600
1701
|
this._emit({ type: "statechange", state: this.getState() });
|
|
1702
|
+
const previousActiveBasemapId = this._state.activeBasemapId;
|
|
1601
1703
|
try {
|
|
1602
1704
|
let managedRaster;
|
|
1705
|
+
let resolvedStyleUrl;
|
|
1603
1706
|
if (isOverlay) {
|
|
1604
1707
|
await this._waitForStyleReady();
|
|
1605
1708
|
if (effectiveMode === "replace") {
|
|
@@ -1610,6 +1713,7 @@ class BasemapControl {
|
|
|
1610
1713
|
managedRaster = await this._addOverlay(basemap);
|
|
1611
1714
|
} else {
|
|
1612
1715
|
const styleUrl = this._resolveStyleUrl(basemap);
|
|
1716
|
+
resolvedStyleUrl = styleUrl;
|
|
1613
1717
|
const styleOptions = this._getStyleOptions(basemap);
|
|
1614
1718
|
this._removeManagedBasemap();
|
|
1615
1719
|
if (styleOptions) {
|
|
@@ -1617,6 +1721,7 @@ class BasemapControl {
|
|
|
1617
1721
|
} else {
|
|
1618
1722
|
this._map.setStyle(styleUrl);
|
|
1619
1723
|
}
|
|
1724
|
+
this._watchStyleLoad(styleUrl, basemap, previousActiveBasemapId);
|
|
1620
1725
|
}
|
|
1621
1726
|
this._applyBasemapView(basemap);
|
|
1622
1727
|
const activeBasemapIds = effectiveMode === "add" ? [...this._state.activeBasemapIds.filter((value) => value !== basemap.id), basemap.id] : [basemap.id];
|
|
@@ -1633,6 +1738,7 @@ class BasemapControl {
|
|
|
1633
1738
|
state: this.getState(),
|
|
1634
1739
|
basemap,
|
|
1635
1740
|
managedRaster,
|
|
1741
|
+
resolvedStyleUrl,
|
|
1636
1742
|
mode: effectiveMode
|
|
1637
1743
|
});
|
|
1638
1744
|
this._emit({ type: "statechange", state: this.getState() });
|
|
@@ -1649,6 +1755,131 @@ class BasemapControl {
|
|
|
1649
1755
|
throw error;
|
|
1650
1756
|
}
|
|
1651
1757
|
}
|
|
1758
|
+
// Watches the asynchronous style load that `setStyle` kicked off for a style
|
|
1759
|
+
// basemap, and rolls back to the previous basemap (reporting the failure
|
|
1760
|
+
// through the `error` event) when the new style cannot actually render. Two
|
|
1761
|
+
// failure modes are caught so a broken provider basemap never leaves a blank
|
|
1762
|
+
// map:
|
|
1763
|
+
//
|
|
1764
|
+
// 1. The style *document* request fails outright (matched by URL), e.g. an
|
|
1765
|
+
// unreachable host or a descriptor that 404s. Detected whether or not
|
|
1766
|
+
// `style.load` ever fires.
|
|
1767
|
+
// 2. The descriptor loads but the provider rejects the credentials when the
|
|
1768
|
+
// first tiles are fetched (401/403). Amazon Location, for instance,
|
|
1769
|
+
// serves the style JSON publicly but 403s every tile for a bad API key,
|
|
1770
|
+
// so the descriptor "loads" while the map stays empty. This is only
|
|
1771
|
+
// treated as fatal for credentialed providers, and only briefly after
|
|
1772
|
+
// the descriptor loads, so an isolated transient tile error on a healthy
|
|
1773
|
+
// basemap is ignored.
|
|
1774
|
+
_watchStyleLoad(styleUrl, basemap, previousActiveBasemapId) {
|
|
1775
|
+
var _a;
|
|
1776
|
+
const map = this._map;
|
|
1777
|
+
if (!map) return;
|
|
1778
|
+
(_a = this._cancelStyleWatch) == null ? void 0 : _a.call(this);
|
|
1779
|
+
const isCredentialed = basemap.provider in PROVIDER_CREDENTIAL_HELP;
|
|
1780
|
+
let settled = false;
|
|
1781
|
+
let graceTimer;
|
|
1782
|
+
const cleanup = () => {
|
|
1783
|
+
if (settled) return;
|
|
1784
|
+
settled = true;
|
|
1785
|
+
if (graceTimer !== void 0) clearTimeout(graceTimer);
|
|
1786
|
+
map.off("style.load", onLoad);
|
|
1787
|
+
map.off("error", onError);
|
|
1788
|
+
if (this._cancelStyleWatch === cleanup) this._cancelStyleWatch = void 0;
|
|
1789
|
+
};
|
|
1790
|
+
const fail = (cause) => {
|
|
1791
|
+
cleanup();
|
|
1792
|
+
this._handleStyleLoadFailure(basemap, previousActiveBasemapId, cause);
|
|
1793
|
+
};
|
|
1794
|
+
const onLoad = () => {
|
|
1795
|
+
if (!isCredentialed) {
|
|
1796
|
+
cleanup();
|
|
1797
|
+
} else if (graceTimer === void 0) {
|
|
1798
|
+
graceTimer = setTimeout(cleanup, STYLE_AUTH_GRACE_MS);
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
const onError = (event) => {
|
|
1802
|
+
const error = event == null ? void 0 : event.error;
|
|
1803
|
+
if (extractErrorUrl(error) === styleUrl) {
|
|
1804
|
+
fail(error);
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
if (isCredentialed) {
|
|
1808
|
+
const status = extractErrorStatus(error);
|
|
1809
|
+
if (status === 401 || status === 403) fail(error);
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
this._cancelStyleWatch = cleanup;
|
|
1813
|
+
map.once("style.load", onLoad);
|
|
1814
|
+
map.on("error", onError);
|
|
1815
|
+
}
|
|
1816
|
+
// Rolls back a failed style swap: restores the previously active basemap (when
|
|
1817
|
+
// it is a style basemap the control owns), then reports the failure inline and
|
|
1818
|
+
// through the `error` event. When the failing provider needs an API key, the
|
|
1819
|
+
// inline credential field is revealed so the user can correct the key and
|
|
1820
|
+
// retry without losing their map.
|
|
1821
|
+
_handleStyleLoadFailure(failedBasemap, previousActiveBasemapId, cause) {
|
|
1822
|
+
this._restorePreviousBasemap(previousActiveBasemapId, failedBasemap.id);
|
|
1823
|
+
const status = extractErrorStatus(cause);
|
|
1824
|
+
const credentialProvider = failedBasemap.provider in PROVIDER_CREDENTIAL_HELP ? failedBasemap.provider : void 0;
|
|
1825
|
+
const hint = credentialProvider ? " Check the API key and try again." : " Check your connection and try again.";
|
|
1826
|
+
const error = new BasemapLoadError(
|
|
1827
|
+
`Could not load the "${failedBasemap.name}" basemap${status ? ` (HTTP ${status})` : ""}.${hint}`,
|
|
1828
|
+
failedBasemap.provider,
|
|
1829
|
+
status
|
|
1830
|
+
);
|
|
1831
|
+
this._state = { ...this._state, loading: false, error: error.message };
|
|
1832
|
+
this._missingCredentialProvider = credentialProvider;
|
|
1833
|
+
this._lastFailedBasemapId = credentialProvider ? failedBasemap.id : void 0;
|
|
1834
|
+
this._activeView = "basemaps";
|
|
1835
|
+
this._renderContent(true);
|
|
1836
|
+
this._handleError(error, failedBasemap);
|
|
1837
|
+
}
|
|
1838
|
+
// Reapplies the previously active style basemap after a failed swap. Only a
|
|
1839
|
+
// control-owned style/vector-style basemap can be reapplied; when the previous
|
|
1840
|
+
// basemap is unknown, a raster overlay, or a style the host owns, the panel
|
|
1841
|
+
// state is pointed back at it (so the failed basemap is not highlighted) and
|
|
1842
|
+
// the host is left to restore its own style from the emitted `error` event.
|
|
1843
|
+
_restorePreviousBasemap(previousActiveBasemapId, failedBasemapId) {
|
|
1844
|
+
const map = this._map;
|
|
1845
|
+
const previous = previousActiveBasemapId && previousActiveBasemapId !== failedBasemapId ? this._basemaps.find((candidate) => candidate.id === previousActiveBasemapId) : void 0;
|
|
1846
|
+
const pointStateAtPrevious = () => {
|
|
1847
|
+
this._state = {
|
|
1848
|
+
...this._state,
|
|
1849
|
+
activeBasemapId: previousActiveBasemapId,
|
|
1850
|
+
activeBasemapIds: previousActiveBasemapId ? [previousActiveBasemapId] : []
|
|
1851
|
+
};
|
|
1852
|
+
};
|
|
1853
|
+
if (!map || !previous || previous.source.type !== "style" && previous.source.type !== "vector-style") {
|
|
1854
|
+
pointStateAtPrevious();
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1857
|
+
try {
|
|
1858
|
+
const styleUrl = this._resolveStyleUrl(previous);
|
|
1859
|
+
const styleOptions = this._getStyleOptions(previous);
|
|
1860
|
+
this._removeManagedBasemap();
|
|
1861
|
+
if (styleOptions) {
|
|
1862
|
+
map.setStyle(styleUrl, styleOptions);
|
|
1863
|
+
} else {
|
|
1864
|
+
map.setStyle(styleUrl);
|
|
1865
|
+
}
|
|
1866
|
+
this._state = {
|
|
1867
|
+
...this._state,
|
|
1868
|
+
activeBasemapId: previous.id,
|
|
1869
|
+
activeBasemapIds: [previous.id]
|
|
1870
|
+
};
|
|
1871
|
+
this._emit({
|
|
1872
|
+
type: "basemapchange",
|
|
1873
|
+
state: this.getState(),
|
|
1874
|
+
basemap: previous,
|
|
1875
|
+
resolvedStyleUrl: styleUrl,
|
|
1876
|
+
restored: true,
|
|
1877
|
+
mode: "replace"
|
|
1878
|
+
});
|
|
1879
|
+
} catch {
|
|
1880
|
+
pointStateAtPrevious();
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1652
1883
|
// The public mutators rethrow after emitting the error event so callers that
|
|
1653
1884
|
// await them can react. The panel's click handler uses this instead to avoid
|
|
1654
1885
|
// unhandled promise rejections; the failure is still reported via `error`.
|
|
@@ -2821,4 +3052,4 @@ export {
|
|
|
2821
3052
|
getBasemapCategories as g,
|
|
2822
3053
|
resolveBasemapProviders as r
|
|
2823
3054
|
};
|
|
2824
|
-
//# sourceMappingURL=BasemapControl-
|
|
3055
|
+
//# sourceMappingURL=BasemapControl-AGhhvlrX.js.map
|