maplibre-gl-basemap-control 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,7 @@ A MapLibre GL JS control for searching and switching public basemaps. It keeps t
9
9
 
10
10
  - Search-first basemap picker inspired by QuickMapServices
11
11
  - Built-in catalog for common public basemaps, MapTiler styles, Amazon Location styles, Mapbox styles, Maptoolkit styles, Protomaps styles, and Stadia Maps basemaps
12
+ - Tianditu, Amap, and Tencent basemaps, served from inside mainland China
12
13
  - Stackable traffic overlays for TomTom, HERE, Mapbox, and Google
13
14
  - Custom basemap and provider definitions
14
15
  - MapLibre `IControl` implementation
@@ -156,6 +157,7 @@ const control = new BasemapControl({
156
157
  mapboxAccessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
157
158
  protomapsApiKey: 'YOUR_PROTOMAPS_API_KEY',
158
159
  stadiaApiKey: 'YOUR_STADIA_MAPS_API_KEY',
160
+ tiandituApiKey: 'YOUR_TIANDITU_API_KEY',
159
161
  });
160
162
  ```
161
163
 
@@ -203,6 +205,61 @@ transparent overlays, so pair them with `allowMultiple: true` to stack them over
203
205
  > this control always sends `api_key`, so a key is required here. Set `stadiaApiKey` or enter it in
204
206
  > the panel's API keys view.
205
207
 
208
+ ### China Basemaps
209
+
210
+ Most of the catalog is hosted outside mainland China with no presence inside it, so for users there
211
+ OpenStreetMap, OpenFreeMap, Protomaps, Carto, Google, and Mapbox range from slow to unreachable. The
212
+ catalog ships three providers that are served from inside China:
213
+
214
+ | Basemap id | Provider | Datum | Credential |
215
+ |------------|----------|-------|------------|
216
+ | `tianditu-vector`, `tianditu-imagery`, `tianditu-terrain` and their `-labels` overlays | Tianditu (天地图) | CGCS2000 | `tiandituApiKey` |
217
+ | `amap-street`, `amap-satellite`, `amap-labels` | Amap (高德地图) | GCJ-02 | none |
218
+ | `tencent-street`, `tencent-dark` | Tencent Maps (腾讯地图) | GCJ-02 | none |
219
+
220
+ They are searchable by their Chinese names as well as their English ones, so typing `天地图`, `高德`,
221
+ or `腾讯` into the panel's filter finds them.
222
+
223
+ > **The datum matters more than the speed.** Chinese law requires public map services to publish in
224
+ > GCJ-02, an offset datum that displaces features by roughly 100-700 m from WGS84. Neither this
225
+ > control nor MapLibre applies the shift, so WGS84 data laid over Amap or Tencent will visibly
226
+ > misalign. **Tianditu is the exception**: it publishes in CGCS2000, which is close enough to WGS84
227
+ > for web mapping, so ordinary data overlays correctly. Prefer Tianditu whenever you are also
228
+ > rendering your own data; reach for Amap or Tencent when the basemap is the whole point, or convert
229
+ > your data to GCJ-02 first.
230
+
231
+ Tianditu is China's official National Platform for Common Geospatial Information Services. Register
232
+ a free key at [console.tianditu.gov.cn](https://console.tianditu.gov.cn/api/key), then set
233
+ `tiandituApiKey` or enter it in the panel's API keys view. Its layers ride the `DataServer`
234
+ endpoint, the xyz-shaped form of its WMTS services:
235
+
236
+ ```text
237
+ https://t{0-7}.tianditu.gov.cn/DataServer?T={layer}&x={x}&y={y}&l={z}&tk={api-key}
238
+ ```
239
+
240
+ Tianditu splits every basemap from its labels, so the `-labels` overlays are separate transparent
241
+ layers. Pair them with `allowMultiple: true` to stack them over their base:
242
+
243
+ ```typescript
244
+ const control = new BasemapControl({
245
+ allowMultiple: true,
246
+ tiandituApiKey: 'YOUR_TIANDITU_API_KEY',
247
+ defaultBasemapId: 'tianditu-vector',
248
+ });
249
+ await control.addBasemap('tianditu-vector-labels');
250
+ ```
251
+
252
+ The same applies to `amap-labels`, a transparent roads-and-labels overlay meant to sit on top of
253
+ `amap-satellite`. Note that `tianditu-terrain` and `tianditu-terrain-labels` are only published to
254
+ zoom 14, where the vector and imagery layers reach 18, and Amap serves a "no imagery" placeholder
255
+ rather than a 404 past zoom 18, so `amap-satellite` caps there and lets MapLibre overzoom.
256
+
257
+ > **Terms of use.** Tianditu's key-based access is the sanctioned route and the one to build on. The
258
+ > Amap and Tencent tile endpoints are widely used but are not documented public APIs, and carry the
259
+ > same caveat as the keyless Google tiles below: fine for development and demos, but the operators
260
+ > may rate-limit, change, or block them at any time. Obtain a commercial key from the provider before
261
+ > shipping either one.
262
+
206
263
  ### Traffic Overlays
207
264
 
208
265
  The catalog ships real-time traffic overlays in the `Traffic` category. They are
@@ -302,6 +359,7 @@ API key and load straight from `https://styles.maptoolkit.org/{styleId}.json`:
302
359
  | `mapboxAccessToken` | `string` | `undefined` | Initial Mapbox access token for built-in Mapbox styles and the Mapbox Traffic overlay |
303
360
  | `protomapsApiKey` | `string` | `undefined` | Initial Protomaps API key for built-in Protomaps styles |
304
361
  | `stadiaApiKey` | `string` | `undefined` | Initial Stadia Maps API key for built-in Stadia and Stadia x Stamen basemaps |
362
+ | `tiandituApiKey` | `string` | `undefined` | Initial Tianditu API key (`tk`) for the built-in Tianditu basemaps |
305
363
  | `tomtomApiKey` | `string` | `undefined` | Initial TomTom API key for the TomTom Traffic overlays |
306
364
  | `hereApiKey` | `string` | `undefined` | Initial HERE API key for the HERE Traffic overlay |
307
365
  | `googleMapsApiKey` | `string` | `undefined` | Initial Google Maps API key (Map Tiles API) for the Google Traffic overlay and the base Google Maps/Satellite/Terrain/Hybrid basemaps (which fall back to keyless tiles without a key) |
@@ -370,6 +428,7 @@ const control = new BasemapControl({
370
428
  - `setMapboxAccessToken(accessToken)` - Set or update the Mapbox access token
371
429
  - `setProtomapsApiKey(apiKey)` - Set or update the Protomaps API key used by Protomaps styles
372
430
  - `setStadiaApiKey(apiKey)` - Set or update the Stadia Maps API key used by Stadia basemaps
431
+ - `setTiandituApiKey(apiKey)` - Set or update the Tianditu API key used by Tianditu basemaps
373
432
  - `setTomTomApiKey(apiKey)` - Set or update the TomTom API key used by TomTom Traffic overlays
374
433
  - `setHereApiKey(apiKey)` - Set or update the HERE API key used by the HERE Traffic overlay
375
434
  - `setGoogleMapsApiKey(apiKey)` - Set or update the Google Maps API key used by the Google Traffic overlay and the base Google basemaps
@@ -2,6 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  const DEFAULT_BASEMAP_PROVIDERS = [
5
+ { id: "amap", name: "Amap", category: "Regional" },
5
6
  { id: "amazon", name: "Amazon Location", category: "General" },
6
7
  { id: "carto", name: "Carto", category: "General" },
7
8
  { id: "cyclosm", name: "CyclOSM", category: "Cycling" },
@@ -21,6 +22,8 @@ const DEFAULT_BASEMAP_PROVIDERS = [
21
22
  { id: "protomaps", name: "Protomaps", category: "Vector Styles" },
22
23
  { id: "stadia", name: "Stadia Maps", category: "General" },
23
24
  { id: "swisstopo", name: "Swiss Federal Geoportal", category: "Regional" },
25
+ { id: "tencent", name: "Tencent Maps", category: "Regional" },
26
+ { id: "tianditu", name: "Tianditu", category: "Regional" },
24
27
  { id: "tomtom", name: "TomTom", category: "Traffic" },
25
28
  { id: "topplusopen", name: "TopPlusOpen", category: "Regional" },
26
29
  { id: "usgs", name: "USGS", category: "United States" },
@@ -35,6 +38,7 @@ function rasterBasemap({
35
38
  attribution,
36
39
  tiles,
37
40
  maxzoom = 19,
41
+ scheme,
38
42
  tags = []
39
43
  }) {
40
44
  return {
@@ -49,7 +53,8 @@ function rasterBasemap({
49
53
  type: "raster",
50
54
  tiles,
51
55
  tileSize: 256,
52
- maxzoom
56
+ maxzoom,
57
+ scheme
53
58
  },
54
59
  tags
55
60
  };
@@ -202,6 +207,35 @@ function stadiaRasterBasemap({
202
207
  tags: ["stadia", ...stamen ? ["stamen"] : [], ...tags]
203
208
  });
204
209
  }
210
+ const TIANDITU_HOSTS = [0, 1, 2, 3, 4, 5, 6, 7];
211
+ function tiandituRasterBasemap({
212
+ id,
213
+ name,
214
+ layer,
215
+ category,
216
+ description,
217
+ maxzoom = 18,
218
+ tags = []
219
+ }) {
220
+ return rasterBasemap({
221
+ id,
222
+ name,
223
+ provider: "tianditu",
224
+ category,
225
+ description,
226
+ attribution: TIANDITU_ATTRIBUTION,
227
+ tiles: TIANDITU_HOSTS.map(
228
+ (host) => `https://t${host}.tianditu.gov.cn/DataServer?T=${layer}&x={x}&y={y}&l={z}&tk={api-key}`
229
+ ),
230
+ maxzoom,
231
+ tags: ["tianditu", "china", "天地图", ...tags]
232
+ });
233
+ }
234
+ function amapTiles(host, query) {
235
+ return [1, 2, 3, 4].map(
236
+ (index) => `https://${host}0${index}.is.autonavi.com/appmaptile?${query}&x={x}&y={y}&z={z}`
237
+ );
238
+ }
205
239
  function sortProviders(providers) {
206
240
  return [...providers].sort((a, b) => a.name.localeCompare(b.name));
207
241
  }
@@ -216,6 +250,10 @@ const STADIA_ATTRIBUTION = '&copy; <a href="https://stadiamaps.com/" target="_bl
216
250
  const STADIA_STAMEN_ATTRIBUTION = '&copy; <a href="https://stadiamaps.com/" target="_blank" rel="noopener">Stadia Maps</a> &copy; <a href="https://stamen.com/" target="_blank" rel="noopener">Stamen Design</a> &copy; <a href="https://openmaptiles.org/" target="_blank" rel="noopener">OpenMapTiles</a> &copy; OpenStreetMap contributors';
217
251
  const PROTOMAPS_ATTRIBUTION = '<a href="https://protomaps.com" target="_blank" rel="noopener">Protomaps</a> &copy; <a href="https://openstreetmap.org" target="_blank" rel="noopener">OpenStreetMap</a>';
218
252
  const OPENFREEMAP_ATTRIBUTION = "OpenFreeMap &copy; OpenMapTiles Data from OpenStreetMap";
253
+ const TIANDITU_ATTRIBUTION = '&copy; <a href="https://www.tianditu.gov.cn" target="_blank" rel="noopener">天地图 Tianditu</a> (National Platform for Common Geospatial Information Services)';
254
+ const AMAP_ATTRIBUTION = '&copy; <a href="https://www.amap.com" target="_blank" rel="noopener">高德地图 Amap</a>';
255
+ const TENCENT_ATTRIBUTION = '&copy; <a href="https://map.qq.com" target="_blank" rel="noopener">腾讯地图 Tencent Maps</a>';
256
+ const GCJ02_WARNING = "Tiles are in the GCJ-02 datum, so WGS84 data overlaid on them appears offset by roughly 100-700 m.";
219
257
  const TOMTOM_ATTRIBUTION = "&copy; TomTom";
220
258
  const HERE_ATTRIBUTION = "&copy; HERE";
221
259
  const GOOGLE_ATTRIBUTION = "&copy; Google";
@@ -1216,6 +1254,130 @@ const DEFAULT_BASEMAPS = [
1216
1254
  maxzoom: 18,
1217
1255
  tags: ["switzerland", "imagery"]
1218
1256
  }),
1257
+ tiandituRasterBasemap({
1258
+ id: "tianditu-vector",
1259
+ name: "Tianditu Vector",
1260
+ layer: "vec_w",
1261
+ category: "Regional",
1262
+ description: "China's official street map, reachable from mainland China. Published in CGCS2000, so WGS84 data overlays without a datum shift. Pair with Tianditu Vector Labels. Requires a free Tianditu API key.",
1263
+ tags: ["vector", "street", "vec"]
1264
+ }),
1265
+ tiandituRasterBasemap({
1266
+ id: "tianditu-vector-labels",
1267
+ name: "Tianditu Vector Labels",
1268
+ layer: "cva_w",
1269
+ category: "Labels",
1270
+ description: "Place name and road label overlay for Tianditu Vector. Requires a free Tianditu API key.",
1271
+ tags: ["labels", "annotation", "overlay", "cva"]
1272
+ }),
1273
+ tiandituRasterBasemap({
1274
+ id: "tianditu-imagery",
1275
+ name: "Tianditu Imagery",
1276
+ layer: "img_w",
1277
+ category: "Imagery",
1278
+ description: "China's official satellite imagery, reachable from mainland China. Pair with Tianditu Imagery Labels. Requires a free Tianditu API key.",
1279
+ tags: ["imagery", "satellite", "img"]
1280
+ }),
1281
+ tiandituRasterBasemap({
1282
+ id: "tianditu-imagery-labels",
1283
+ name: "Tianditu Imagery Labels",
1284
+ layer: "cia_w",
1285
+ category: "Labels",
1286
+ description: "Place name and road label overlay for Tianditu Imagery. Requires a free Tianditu API key.",
1287
+ tags: ["labels", "annotation", "overlay", "cia"]
1288
+ }),
1289
+ tiandituRasterBasemap({
1290
+ id: "tianditu-terrain",
1291
+ name: "Tianditu Terrain",
1292
+ layer: "ter_w",
1293
+ category: "Terrain",
1294
+ description: "China's official shaded relief terrain map. Pair with Tianditu Terrain Labels. Requires a free Tianditu API key.",
1295
+ // The terrain pair is only published to zoom 14, unlike the vector and
1296
+ // imagery layers, which reach 18.
1297
+ maxzoom: 14,
1298
+ tags: ["terrain", "relief", "hillshade", "ter"]
1299
+ }),
1300
+ tiandituRasterBasemap({
1301
+ id: "tianditu-terrain-labels",
1302
+ name: "Tianditu Terrain Labels",
1303
+ layer: "cta_w",
1304
+ category: "Labels",
1305
+ description: "Place name label overlay for Tianditu Terrain. Requires a free Tianditu API key.",
1306
+ maxzoom: 14,
1307
+ tags: ["labels", "annotation", "overlay", "cta"]
1308
+ }),
1309
+ rasterBasemap({
1310
+ id: "amap-street",
1311
+ name: "Amap Street",
1312
+ provider: "amap",
1313
+ category: "Regional",
1314
+ description: `Amap street map of China, reachable from mainland China. ${GCJ02_WARNING}`,
1315
+ attribution: AMAP_ATTRIBUTION,
1316
+ tiles: amapTiles("wprd", "lang=zh_cn&size=1&scl=1&style=7"),
1317
+ tags: ["amap", "gaode", "高德", "china", "street", "gcj02"]
1318
+ }),
1319
+ rasterBasemap({
1320
+ id: "amap-satellite",
1321
+ name: "Amap Satellite",
1322
+ provider: "amap",
1323
+ category: "Imagery",
1324
+ description: `Amap satellite imagery, reachable from mainland China. Pair with Amap Labels. ${GCJ02_WARNING}`,
1325
+ attribution: AMAP_ATTRIBUTION,
1326
+ tiles: amapTiles("webst", "style=6"),
1327
+ // Past zoom 18 Amap returns a "no imagery" placeholder tile rather than a
1328
+ // 404, so cap here and let MapLibre overzoom instead.
1329
+ maxzoom: 18,
1330
+ tags: ["amap", "gaode", "高德", "china", "satellite", "imagery", "gcj02"]
1331
+ }),
1332
+ rasterBasemap({
1333
+ id: "amap-labels",
1334
+ name: "Amap Labels",
1335
+ provider: "amap",
1336
+ category: "Labels",
1337
+ description: `Transparent Amap road and label overlay, for use over Amap Satellite. ${GCJ02_WARNING}`,
1338
+ attribution: AMAP_ATTRIBUTION,
1339
+ tiles: amapTiles("webst", "style=8"),
1340
+ tags: [
1341
+ "amap",
1342
+ "gaode",
1343
+ "高德",
1344
+ "china",
1345
+ "labels",
1346
+ "roads",
1347
+ "overlay",
1348
+ "gcj02"
1349
+ ]
1350
+ }),
1351
+ rasterBasemap({
1352
+ id: "tencent-street",
1353
+ name: "Tencent Street",
1354
+ provider: "tencent",
1355
+ category: "Regional",
1356
+ description: `Tencent street map of China, reachable from mainland China. ${GCJ02_WARNING}`,
1357
+ attribution: TENCENT_ATTRIBUTION,
1358
+ // Tencent numbers tile rows from the bottom, so the source is TMS rather
1359
+ // than xyz; MapLibre flips `{y}` when `scheme` says so.
1360
+ tiles: [0, 1, 2, 3].map(
1361
+ (host) => `https://rt${host}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=1&scene=0`
1362
+ ),
1363
+ maxzoom: 18,
1364
+ scheme: "tms",
1365
+ tags: ["tencent", "qq", "腾讯", "china", "street", "gcj02"]
1366
+ }),
1367
+ rasterBasemap({
1368
+ id: "tencent-dark",
1369
+ name: "Tencent Dark",
1370
+ provider: "tencent",
1371
+ category: "Dark",
1372
+ description: `Dark Tencent street map for high-contrast overlays, reachable from mainland China. ${GCJ02_WARNING}`,
1373
+ attribution: TENCENT_ATTRIBUTION,
1374
+ tiles: [0, 1, 2, 3].map(
1375
+ (host) => `https://rt${host}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=4&scene=0`
1376
+ ),
1377
+ maxzoom: 18,
1378
+ scheme: "tms",
1379
+ tags: ["tencent", "qq", "腾讯", "china", "dark", "gcj02"]
1380
+ }),
1219
1381
  rasterBasemap({
1220
1382
  id: "topplusopen-color",
1221
1383
  name: "TopPlusOpen Color",
@@ -1746,6 +1908,10 @@ const PROVIDER_CREDENTIAL_HELP = {
1746
1908
  url: "https://client.stadiamaps.com/signup/",
1747
1909
  label: "Get a Stadia Maps API key"
1748
1910
  },
1911
+ tianditu: {
1912
+ url: "https://console.tianditu.gov.cn/api/key",
1913
+ label: "Get a Tianditu API key"
1914
+ },
1749
1915
  tomtom: {
1750
1916
  url: "https://developer.tomtom.com/how-to-get-tomtom-api-key",
1751
1917
  label: "Get a TomTom API key"
@@ -1759,6 +1925,13 @@ const PROVIDER_CREDENTIAL_HELP = {
1759
1925
  label: "Get a Google Maps API key"
1760
1926
  }
1761
1927
  };
1928
+ const RASTER_KEY_LABELS = {
1929
+ google: "Google Maps API key",
1930
+ here: "HERE API key",
1931
+ stadia: "Stadia Maps API key",
1932
+ tianditu: "Tianditu API key",
1933
+ tomtom: "TomTom API key"
1934
+ };
1762
1935
  const STYLE_AUTH_GRACE_MS = 2500;
1763
1936
  const MIN_PANEL_WIDTH = 240;
1764
1937
  const MIN_PANEL_HEIGHT = 200;
@@ -1817,6 +1990,7 @@ class BasemapControl {
1817
1990
  __publicField(this, "_mapboxAccessToken", "");
1818
1991
  __publicField(this, "_protomapsApiKey", "");
1819
1992
  __publicField(this, "_stadiaApiKey", "");
1993
+ __publicField(this, "_tiandituApiKey", "");
1820
1994
  __publicField(this, "_tomtomApiKey", "");
1821
1995
  __publicField(this, "_hereApiKey", "");
1822
1996
  __publicField(this, "_googleMapsApiKey", "");
@@ -1881,6 +2055,7 @@ class BasemapControl {
1881
2055
  this._mapboxAccessToken = (options == null ? void 0 : options.mapboxAccessToken) ?? "";
1882
2056
  this._protomapsApiKey = (options == null ? void 0 : options.protomapsApiKey) ?? "";
1883
2057
  this._stadiaApiKey = (options == null ? void 0 : options.stadiaApiKey) ?? "";
2058
+ this._tiandituApiKey = (options == null ? void 0 : options.tiandituApiKey) ?? "";
1884
2059
  this._tomtomApiKey = (options == null ? void 0 : options.tomtomApiKey) ?? "";
1885
2060
  this._hereApiKey = (options == null ? void 0 : options.hereApiKey) ?? "";
1886
2061
  this._googleMapsApiKey = (options == null ? void 0 : options.googleMapsApiKey) ?? "";
@@ -2024,6 +2199,12 @@ class BasemapControl {
2024
2199
  this._renderContent();
2025
2200
  this._emit({ type: "statechange", state: this.getState() });
2026
2201
  }
2202
+ setTiandituApiKey(apiKey) {
2203
+ this._tiandituApiKey = apiKey;
2204
+ this._clearError();
2205
+ this._renderContent();
2206
+ this._emit({ type: "statechange", state: this.getState() });
2207
+ }
2027
2208
  setTomTomApiKey(apiKey) {
2028
2209
  this._tomtomApiKey = apiKey;
2029
2210
  this._clearError();
@@ -2666,6 +2847,23 @@ class BasemapControl {
2666
2847
  }
2667
2848
  ]
2668
2849
  },
2850
+ {
2851
+ provider: "tianditu",
2852
+ label: "Tianditu",
2853
+ has: this._hasTiandituBasemaps(),
2854
+ fields: [
2855
+ {
2856
+ className: "basemap-control-tianditu-key",
2857
+ type: "password",
2858
+ placeholder: "Tianditu API key",
2859
+ ariaLabel: "Tianditu API key",
2860
+ value: this._tiandituApiKey,
2861
+ onInput: (value) => {
2862
+ this._tiandituApiKey = value;
2863
+ }
2864
+ }
2865
+ ]
2866
+ },
2669
2867
  {
2670
2868
  provider: "tomtom",
2671
2869
  label: "TomTom",
@@ -3085,6 +3283,9 @@ class BasemapControl {
3085
3283
  _hasStadiaBasemaps() {
3086
3284
  return this._basemaps.some((basemap) => basemap.provider === "stadia");
3087
3285
  }
3286
+ _hasTiandituBasemaps() {
3287
+ return this._basemaps.some((basemap) => basemap.provider === "tianditu");
3288
+ }
3088
3289
  _hasTomTomBasemaps() {
3089
3290
  return this._basemaps.some((basemap) => basemap.provider === "tomtom");
3090
3291
  }
@@ -3101,7 +3302,7 @@ class BasemapControl {
3101
3302
  );
3102
3303
  }
3103
3304
  _hasProviderSettings() {
3104
- return this._hasMapTilerBasemaps() || this._hasAmazonBasemaps() || this._hasMapboxBasemaps() || this._hasProtomapsBasemaps() || this._hasStadiaBasemaps() || this._hasTomTomBasemaps() || this._hasHereBasemaps() || this._hasGoogleApiKeyBasemaps();
3305
+ return this._hasMapTilerBasemaps() || this._hasAmazonBasemaps() || this._hasMapboxBasemaps() || this._hasProtomapsBasemaps() || this._hasStadiaBasemaps() || this._hasTiandituBasemaps() || this._hasTomTomBasemaps() || this._hasHereBasemaps() || this._hasGoogleApiKeyBasemaps();
3105
3306
  }
3106
3307
  _resolveStyleUrl(basemap) {
3107
3308
  if (basemap.source.type !== "style" && basemap.source.type !== "vector-style") {
@@ -3361,6 +3562,7 @@ class BasemapControl {
3361
3562
  if (provider === "tomtom") return this._tomtomApiKey.trim();
3362
3563
  if (provider === "here") return this._hereApiKey.trim();
3363
3564
  if (provider === "stadia") return this._stadiaApiKey.trim();
3565
+ if (provider === "tianditu") return this._tiandituApiKey.trim();
3364
3566
  if (provider === "google") return this._googleMapsApiKey.trim();
3365
3567
  return "";
3366
3568
  }
@@ -3388,7 +3590,7 @@ class BasemapControl {
3388
3590
  }
3389
3591
  }
3390
3592
  _missingRasterKeyError(provider) {
3391
- const label = provider === "tomtom" ? "TomTom API key" : provider === "here" ? "HERE API key" : provider === "stadia" ? "Stadia Maps API key" : provider === "google" ? "Google Maps API key" : "API key";
3593
+ const label = RASTER_KEY_LABELS[provider] ?? "API key";
3392
3594
  const helpProvider = provider in PROVIDER_CREDENTIAL_HELP ? provider : "maptiler";
3393
3595
  return new MissingCredentialError(`Enter a ${label} before applying this layer.`, helpProvider);
3394
3596
  }
@@ -3624,4 +3826,4 @@ export {
3624
3826
  getBasemapCategories as g,
3625
3827
  resolveBasemapProviders as r
3626
3828
  };
3627
- //# sourceMappingURL=BasemapControl-Cdg7HMeU.js.map
3829
+ //# sourceMappingURL=BasemapControl-CKgYscxI.js.map