maplibre-gl-basemap-control 0.9.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-DjBg1WYY.js → BasemapControl-AGhhvlrX.js} +164 -4
- package/dist/BasemapControl-AGhhvlrX.js.map +1 -0
- package/dist/{BasemapControl-Cu8agB-D.cjs → BasemapControl-DXJHjc6Z.cjs} +164 -4
- 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/types.d.ts +17 -0
- package/dist/types/lib/core/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/BasemapControl-Cu8agB-D.cjs.map +0 -1
- package/dist/BasemapControl-DjBg1WYY.js.map +0 -1
|
@@ -1349,6 +1349,7 @@ const PROVIDER_CREDENTIAL_HELP = {
|
|
|
1349
1349
|
label: "Get a Google Maps API key"
|
|
1350
1350
|
}
|
|
1351
1351
|
};
|
|
1352
|
+
const STYLE_AUTH_GRACE_MS = 2500;
|
|
1352
1353
|
const MIN_PANEL_WIDTH = 240;
|
|
1353
1354
|
const MIN_PANEL_HEIGHT = 200;
|
|
1354
1355
|
const PANEL_VIEWPORT_MARGIN = 12;
|
|
@@ -1360,6 +1361,30 @@ class MissingCredentialError extends Error {
|
|
|
1360
1361
|
this.provider = provider;
|
|
1361
1362
|
}
|
|
1362
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
|
+
}
|
|
1363
1388
|
class BasemapControl {
|
|
1364
1389
|
constructor(options) {
|
|
1365
1390
|
__publicField(this, "_map");
|
|
@@ -1399,6 +1424,10 @@ class BasemapControl {
|
|
|
1399
1424
|
// The basemap whose application last failed for a missing credential, so the
|
|
1400
1425
|
// inline credential field's Enter key can re-attempt it (#837).
|
|
1401
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");
|
|
1402
1431
|
__publicField(this, "_resizeHandler", null);
|
|
1403
1432
|
__publicField(this, "_mapResizeHandler", null);
|
|
1404
1433
|
__publicField(this, "_resizeAnchor", null);
|
|
@@ -1477,7 +1506,7 @@ class BasemapControl {
|
|
|
1477
1506
|
return this._container;
|
|
1478
1507
|
}
|
|
1479
1508
|
onRemove() {
|
|
1480
|
-
var _a, _b, _c, _d;
|
|
1509
|
+
var _a, _b, _c, _d, _e;
|
|
1481
1510
|
if (this._resizeHandler) {
|
|
1482
1511
|
window.removeEventListener("resize", this._resizeHandler);
|
|
1483
1512
|
this._resizeHandler = null;
|
|
@@ -1489,10 +1518,11 @@ class BasemapControl {
|
|
|
1489
1518
|
window.removeEventListener("pointermove", this._onResizeMove);
|
|
1490
1519
|
window.removeEventListener("pointerup", this._onResizeEnd);
|
|
1491
1520
|
window.removeEventListener("pointercancel", this._onResizeEnd);
|
|
1521
|
+
(_a = this._cancelStyleWatch) == null ? void 0 : _a.call(this);
|
|
1492
1522
|
this._resizeAnchor = null;
|
|
1493
1523
|
this._resizeHandleEl = null;
|
|
1494
|
-
(
|
|
1495
|
-
(
|
|
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);
|
|
1496
1526
|
this._map = void 0;
|
|
1497
1527
|
this._mapContainer = void 0;
|
|
1498
1528
|
this._container = void 0;
|
|
@@ -1669,8 +1699,10 @@ class BasemapControl {
|
|
|
1669
1699
|
this._state = { ...this._state, loading: true, error: void 0 };
|
|
1670
1700
|
this._renderContent(true);
|
|
1671
1701
|
this._emit({ type: "statechange", state: this.getState() });
|
|
1702
|
+
const previousActiveBasemapId = this._state.activeBasemapId;
|
|
1672
1703
|
try {
|
|
1673
1704
|
let managedRaster;
|
|
1705
|
+
let resolvedStyleUrl;
|
|
1674
1706
|
if (isOverlay) {
|
|
1675
1707
|
await this._waitForStyleReady();
|
|
1676
1708
|
if (effectiveMode === "replace") {
|
|
@@ -1681,6 +1713,7 @@ class BasemapControl {
|
|
|
1681
1713
|
managedRaster = await this._addOverlay(basemap);
|
|
1682
1714
|
} else {
|
|
1683
1715
|
const styleUrl = this._resolveStyleUrl(basemap);
|
|
1716
|
+
resolvedStyleUrl = styleUrl;
|
|
1684
1717
|
const styleOptions = this._getStyleOptions(basemap);
|
|
1685
1718
|
this._removeManagedBasemap();
|
|
1686
1719
|
if (styleOptions) {
|
|
@@ -1688,6 +1721,7 @@ class BasemapControl {
|
|
|
1688
1721
|
} else {
|
|
1689
1722
|
this._map.setStyle(styleUrl);
|
|
1690
1723
|
}
|
|
1724
|
+
this._watchStyleLoad(styleUrl, basemap, previousActiveBasemapId);
|
|
1691
1725
|
}
|
|
1692
1726
|
this._applyBasemapView(basemap);
|
|
1693
1727
|
const activeBasemapIds = effectiveMode === "add" ? [...this._state.activeBasemapIds.filter((value) => value !== basemap.id), basemap.id] : [basemap.id];
|
|
@@ -1704,6 +1738,7 @@ class BasemapControl {
|
|
|
1704
1738
|
state: this.getState(),
|
|
1705
1739
|
basemap,
|
|
1706
1740
|
managedRaster,
|
|
1741
|
+
resolvedStyleUrl,
|
|
1707
1742
|
mode: effectiveMode
|
|
1708
1743
|
});
|
|
1709
1744
|
this._emit({ type: "statechange", state: this.getState() });
|
|
@@ -1720,6 +1755,131 @@ class BasemapControl {
|
|
|
1720
1755
|
throw error;
|
|
1721
1756
|
}
|
|
1722
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
|
+
}
|
|
1723
1883
|
// The public mutators rethrow after emitting the error event so callers that
|
|
1724
1884
|
// await them can react. The panel's click handler uses this instead to avoid
|
|
1725
1885
|
// unhandled promise rejections; the failure is still reported via `error`.
|
|
@@ -2892,4 +3052,4 @@ export {
|
|
|
2892
3052
|
getBasemapCategories as g,
|
|
2893
3053
|
resolveBasemapProviders as r
|
|
2894
3054
|
};
|
|
2895
|
-
//# sourceMappingURL=BasemapControl-
|
|
3055
|
+
//# sourceMappingURL=BasemapControl-AGhhvlrX.js.map
|