maplibre-gl-layer-control 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -156,12 +156,23 @@ function getOpacityProperty(layerType) {
156
156
  return "raster-opacity";
157
157
  case "background":
158
158
  return "background-opacity";
159
+ case "heatmap":
160
+ return "heatmap-opacity";
161
+ case "fill-extrusion":
162
+ return "fill-extrusion-opacity";
163
+ case "hillshade":
164
+ return "hillshade-exaggeration";
165
+ case "color-relief":
166
+ return null;
159
167
  default:
160
168
  return `${layerType}-opacity`;
161
169
  }
162
170
  }
163
171
  function getLayerOpacity(map, layerId, layerType) {
164
172
  const opacityProp = getOpacityProperty(layerType);
173
+ if (opacityProp === null) {
174
+ return 1;
175
+ }
165
176
  if (Array.isArray(opacityProp)) {
166
177
  const opacity2 = map.getPaintProperty(layerId, opacityProp[0]);
167
178
  return opacity2 !== void 0 && opacity2 !== null ? opacity2 : 1;
@@ -171,6 +182,9 @@ function getLayerOpacity(map, layerId, layerType) {
171
182
  }
172
183
  function setLayerOpacity(map, layerId, layerType, opacity) {
173
184
  const opacityProp = getOpacityProperty(layerType);
185
+ if (opacityProp === null) {
186
+ return;
187
+ }
174
188
  if (Array.isArray(opacityProp)) {
175
189
  opacityProp.forEach((prop) => {
176
190
  map.setPaintProperty(layerId, prop, opacity);
@@ -180,7 +194,16 @@ function setLayerOpacity(map, layerId, layerType, opacity) {
180
194
  }
181
195
  }
182
196
  function isStyleableLayerType(layerType) {
183
- return ["fill", "line", "circle", "symbol", "raster"].includes(layerType);
197
+ return [
198
+ "fill",
199
+ "line",
200
+ "circle",
201
+ "symbol",
202
+ "raster",
203
+ "heatmap",
204
+ "fill-extrusion",
205
+ "hillshade"
206
+ ].includes(layerType);
184
207
  }
185
208
  function getLayerType(map, layerId) {
186
209
  try {
@@ -703,9 +726,9 @@ class LayerControl {
703
726
  }
704
727
  const allLayerIds = style.layers.map((layer) => layer.id);
705
728
  if (this.targetLayers.length === 0) {
706
- const originalSourceIds = this.getOriginalStyleSourceIds();
707
729
  const userAddedLayers = [];
708
730
  const backgroundLayerIds = [];
731
+ const userAddedSourceIds = this.detectUserAddedSources();
709
732
  allLayerIds.forEach((layerId) => {
710
733
  const layer = this.map.getLayer(layerId);
711
734
  if (!layer) return;
@@ -714,10 +737,10 @@ class LayerControl {
714
737
  return;
715
738
  }
716
739
  const sourceId = layer.source;
717
- if (!sourceId || originalSourceIds.has(sourceId)) {
718
- backgroundLayerIds.push(layerId);
719
- } else {
740
+ if (sourceId && userAddedSourceIds.has(sourceId)) {
720
741
  userAddedLayers.push(layerId);
742
+ } else {
743
+ backgroundLayerIds.push(layerId);
721
744
  }
722
745
  });
723
746
  if (backgroundLayerIds.length > 0) {
@@ -792,58 +815,90 @@ class LayerControl {
792
815
  this.targetLayers = Object.keys(this.state.layerStates);
793
816
  }
794
817
  /**
795
- * Get the source IDs that were part of the original style (from the style URL)
796
- * Sources added via map.addSource() are considered user-added
818
+ * Detect which sources are user-added (not from the basemap style)
819
+ * User-added sources are identified by:
820
+ * - GeoJSON sources with inline data objects (not URL strings)
821
+ * - Image, video, canvas sources (always user-added)
822
+ * - Raster, raster-dem, vector sources from non-basemap tile providers
797
823
  */
798
- getOriginalStyleSourceIds() {
799
- const originalSourceIds = /* @__PURE__ */ new Set();
824
+ detectUserAddedSources() {
825
+ const userAddedSources = /* @__PURE__ */ new Set();
800
826
  const style = this.map.getStyle();
801
- if (!style || !style.sources) return originalSourceIds;
827
+ if (!style || !style.sources) return userAddedSources;
828
+ const basemapDomains = /* @__PURE__ */ new Set();
829
+ const knownBasemapProviders = [
830
+ "demotiles.maplibre.org",
831
+ "api.maptiler.com",
832
+ "tiles.stadiamaps.com",
833
+ "api.mapbox.com",
834
+ "basemaps.cartocdn.com",
835
+ "tiles.mapbox.com",
836
+ "a.basemaps.cartocdn.com",
837
+ "b.basemaps.cartocdn.com",
838
+ "c.basemaps.cartocdn.com",
839
+ "d.basemaps.cartocdn.com",
840
+ "tiles.arcgis.com",
841
+ "server.arcgisonline.com",
842
+ "services.arcgisonline.com"
843
+ ];
802
844
  const spriteUrl = style.sprite;
803
- const glyphsUrl = style.glyphs;
804
- let styleBaseDomain = "";
805
- if (spriteUrl) {
845
+ if (spriteUrl && typeof spriteUrl === "string") {
806
846
  try {
807
- const url = new URL(typeof spriteUrl === "string" ? spriteUrl : "");
808
- styleBaseDomain = url.hostname;
847
+ const url = new URL(spriteUrl);
848
+ basemapDomains.add(url.hostname);
809
849
  } catch {
810
850
  }
811
- } else if (glyphsUrl) {
851
+ }
852
+ if (style.glyphs) {
812
853
  try {
813
- const url = new URL(glyphsUrl.replace("{fontstack}", "test").replace("{range}", "test"));
814
- styleBaseDomain = url.hostname;
854
+ const url = new URL(style.glyphs.replace("{fontstack}", "x").replace("{range}", "x"));
855
+ basemapDomains.add(url.hostname);
815
856
  } catch {
816
857
  }
817
858
  }
818
- Object.entries(style.sources).forEach(([sourceId, source]) => {
859
+ for (const [sourceId, source] of Object.entries(style.sources)) {
819
860
  const src = source;
820
- let sourceUrl = src.url || src.tiles && src.tiles[0] || "";
821
- if (sourceUrl) {
822
- try {
823
- const url = new URL(sourceUrl);
824
- if (styleBaseDomain && url.hostname === styleBaseDomain) {
825
- originalSourceIds.add(sourceId);
826
- return;
827
- }
828
- const basemapDomains = [
829
- "demotiles.maplibre.org",
830
- "api.maptiler.com",
831
- "tiles.stadiamaps.com",
832
- "api.mapbox.com",
833
- "basemaps.cartocdn.com"
834
- ];
835
- if (basemapDomains.some((domain) => url.hostname.includes(domain))) {
836
- originalSourceIds.add(sourceId);
837
- return;
861
+ const sourceType = src.type;
862
+ if (sourceType === "image" || sourceType === "video" || sourceType === "canvas") {
863
+ userAddedSources.add(sourceId);
864
+ continue;
865
+ }
866
+ if (sourceType === "geojson") {
867
+ if (src.data && typeof src.data === "object") {
868
+ userAddedSources.add(sourceId);
869
+ } else if (src.data && typeof src.data === "string") {
870
+ try {
871
+ const url = new URL(src.data);
872
+ const isBasemap = knownBasemapProviders.some((p) => url.hostname.includes(p)) || basemapDomains.has(url.hostname);
873
+ if (!isBasemap) {
874
+ userAddedSources.add(sourceId);
875
+ }
876
+ } catch {
877
+ userAddedSources.add(sourceId);
838
878
  }
839
- } catch {
840
879
  }
880
+ continue;
841
881
  }
842
- if (!src.data && !sourceUrl && src.type !== "geojson") {
843
- originalSourceIds.add(sourceId);
882
+ if (sourceType === "raster" || sourceType === "raster-dem" || sourceType === "vector") {
883
+ const tileUrl = src.url || src.tiles && src.tiles[0] || "";
884
+ if (tileUrl) {
885
+ try {
886
+ const url = new URL(tileUrl.replace(/{[^}]+}/g, "0"));
887
+ const hostname = url.hostname;
888
+ const isKnownBasemap = knownBasemapProviders.some(
889
+ (provider) => hostname === provider || hostname.endsWith("." + provider)
890
+ );
891
+ const matchesBasemapDomain = basemapDomains.has(hostname);
892
+ if (!isKnownBasemap && !matchesBasemapDomain) {
893
+ userAddedSources.add(sourceId);
894
+ }
895
+ } catch {
896
+ userAddedSources.add(sourceId);
897
+ }
898
+ }
844
899
  }
845
- });
846
- return originalSourceIds;
900
+ }
901
+ return userAddedSources;
847
902
  }
848
903
  /**
849
904
  * Generate a friendly display name from a layer ID
@@ -2172,9 +2227,9 @@ class LayerControl {
2172
2227
  return;
2173
2228
  }
2174
2229
  const currentMapLayerIds = new Set(style.layers.map((layer) => layer.id));
2175
- const originalSourceIds = this.getOriginalStyleSourceIds();
2176
2230
  const isAutoDetectMode = this.targetLayers.length === 0 || this.targetLayers.length === 1 && this.targetLayers[0] === "Background" || this.targetLayers.every((id) => id === "Background" || this.state.layerStates[id]);
2177
2231
  const newLayers = [];
2232
+ const userAddedSourceIds = isAutoDetectMode ? this.detectUserAddedSources() : /* @__PURE__ */ new Set();
2178
2233
  currentMapLayerIds.forEach((layerId) => {
2179
2234
  if (layerId !== "Background" && !this.state.layerStates[layerId]) {
2180
2235
  const layer = this.map.getLayer(layerId);
@@ -2184,7 +2239,7 @@ class LayerControl {
2184
2239
  return;
2185
2240
  }
2186
2241
  const sourceId = layer.source;
2187
- if (!sourceId || originalSourceIds.has(sourceId)) {
2242
+ if (!sourceId || !userAddedSourceIds.has(sourceId)) {
2188
2243
  return;
2189
2244
  }
2190
2245
  }