UNPKG

react-map-gl

Version:

React components for MapLibre GL JS and Mapbox GL JS

1,607 lines • 50.7 kB
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// dist/mapbox.js
var mapbox_exports = {};
__export(mapbox_exports, {
  AttributionControl: () => AttributionControl,
  FullscreenControl: () => FullscreenControl,
  GeolocateControl: () => GeolocateControl,
  Layer: () => Layer,
  Map: () => Map,
  MapProvider: () => MapProvider,
  Marker: () => Marker,
  NavigationControl: () => NavigationControl,
  Popup: () => Popup,
  ScaleControl: () => ScaleControl,
  Source: () => Source,
  default: () => Map,
  useControl: () => useControl,
  useMap: () => useMap
});
module.exports = __toCommonJS(mapbox_exports);

// ../react-mapbox/src/components/map.tsx
var React2 = __toESM(require("react"), 1);
var import_react3 = require("react");

// ../react-mapbox/src/components/use-map.tsx
var React = __toESM(require("react"), 1);
var import_react = require("react");
var MountedMapsContext = React.createContext(null);
var MapProvider = (props) => {
  const [maps, setMaps] = (0, import_react.useState)({});
  const onMapMount = (0, import_react.useCallback)((map, id = "default") => {
    setMaps((currMaps) => {
      if (id === "current") {
        throw new Error("'current' cannot be used as map id");
      }
      if (currMaps[id]) {
        throw new Error(`Multiple maps with the same id: ${id}`);
      }
      return { ...currMaps, [id]: map };
    });
  }, []);
  const onMapUnmount = (0, import_react.useCallback)((id = "default") => {
    setMaps((currMaps) => {
      if (currMaps[id]) {
        const nextMaps = { ...currMaps };
        delete nextMaps[id];
        return nextMaps;
      }
      return currMaps;
    });
  }, []);
  return /* @__PURE__ */ React.createElement(
    MountedMapsContext.Provider,
    {
      value: {
        maps,
        onMapMount,
        onMapUnmount
      }
    },
    props.children
  );
};
function useMap() {
  var _a;
  const maps = (_a = (0, import_react.useContext)(MountedMapsContext)) == null ? void 0 : _a.maps;
  const currentMap = (0, import_react.useContext)(MapContext);
  const mapsWithCurrent = (0, import_react.useMemo)(() => {
    return { ...maps, current: currentMap == null ? void 0 : currentMap.map };
  }, [maps, currentMap]);
  return mapsWithCurrent;
}

// ../react-mapbox/src/utils/transform.ts
function transformToViewState(tr) {
  return {
    longitude: tr.center.lng,
    latitude: tr.center.lat,
    zoom: tr._seaLevelZoom ?? tr.zoom,
    pitch: tr.pitch,
    bearing: tr.bearing,
    padding: tr.padding,
    elevation: tr._centerAltitude
  };
}
function isViewStateControlled(v) {
  return Number.isFinite(v.longitude) || Number.isFinite(v.latitude) || Number.isFinite(v.zoom) || Number.isFinite(v.pitch) || Number.isFinite(v.bearing);
}
function compareViewStateWithTransform(tr, v) {
  if (Number.isFinite(v.longitude) && tr.center.lng !== v.longitude) {
    return true;
  }
  if (Number.isFinite(v.latitude) && tr.center.lat !== v.latitude) {
    return true;
  }
  if (Number.isFinite(v.bearing) && tr.bearing !== v.bearing) {
    return true;
  }
  if (Number.isFinite(v.pitch) && tr.pitch !== v.pitch) {
    return true;
  }
  if (Number.isFinite(v.zoom) && (tr._seaLevelZoom ?? tr.zoom) !== v.zoom) {
    return true;
  }
  if (v.padding && !tr.isPaddingEqual(v.padding)) {
    return true;
  }
  return false;
}
function noOp() {
}
function applyViewStateToTransform(tr, v) {
  const constrain = tr._constrain;
  const calcMatrices = tr._calcMatrices;
  tr._constrain = noOp;
  tr._calcMatrices = noOp;
  if (Number.isFinite(v.bearing)) {
    tr.bearing = v.bearing;
  }
  if (Number.isFinite(v.pitch)) {
    tr.pitch = v.pitch;
  }
  if (v.padding && !tr.isPaddingEqual(v.padding)) {
    tr.padding = v.padding;
  }
  if (Number.isFinite(v.longitude) || Number.isFinite(v.latitude)) {
    const center = tr.center;
    tr._center = new center.constructor(v.longitude ?? center.lng, v.latitude ?? center.lat);
  }
  if (Number.isFinite(v.zoom)) {
    tr._centerAltitude = v.elevation ?? 0;
    if (tr.elevation) {
      tr._seaLevelZoom = v.zoom;
      const mercatorElevation = tr.pixelsPerMeter / tr.worldSize * tr._centerAltitude;
      const altitude = tr._mercatorZfromZoom(v.zoom);
      const minHeight = tr._mercatorZfromZoom(tr._maxZoom);
      const height = Math.max(altitude - mercatorElevation, minHeight);
      tr._setZoom(tr._zoomFromMercatorZ(height));
    } else {
      tr._seaLevelZoom = null;
      tr.zoom = v.zoom;
    }
  }
  tr._constrain = constrain;
  tr._calcMatrices = calcMatrices;
  if (!tr._unmodified) {
    tr._constrain();
    tr._calcMatrices();
  }
}

// ../react-mapbox/src/mapbox/proxy-transform.ts
var unproxiedMethods = /* @__PURE__ */ new Set([
  "_calcMatrices",
  "_calcFogMatrices",
  "_updateCameraState",
  "_updateSeaLevelZoom"
]);
function createProxyTransform(tr) {
  let internalUpdate = false;
  let reactViewState = {};
  const controlledTransform = tr;
  let proposedTransform = null;
  const handlers = {
    get(target, prop) {
      if (prop === "$reactViewState") {
        return reactViewState;
      }
      if (prop === "$proposedTransform") {
        return proposedTransform;
      }
      if (prop === "$internalUpdate") {
        return internalUpdate;
      }
      if (prop === "_setZoom") {
        return (z) => {
          if (internalUpdate) {
            proposedTransform == null ? void 0 : proposedTransform[prop](z);
          }
          if (!Number.isFinite(reactViewState.zoom)) {
            controlledTransform[prop](z);
          }
        };
      }
      if (internalUpdate && prop === "_translateCameraConstrained" && isViewStateControlled(reactViewState)) {
        proposedTransform = proposedTransform || controlledTransform.clone();
      }
      if (unproxiedMethods.has(prop)) {
        return function(...parms) {
          proposedTransform == null ? void 0 : proposedTransform[prop](...parms);
          controlledTransform[prop](...parms);
        };
      }
      if (internalUpdate && proposedTransform) {
        return proposedTransform[prop];
      }
      return controlledTransform[prop];
    },
    set(target, prop, value) {
      if (prop === "$reactViewState") {
        reactViewState = value;
        applyViewStateToTransform(controlledTransform, reactViewState);
        return true;
      }
      if (prop === "$proposedTransform") {
        proposedTransform = value;
        return true;
      }
      if (prop === "$internalUpdate") {
        internalUpdate = value;
        return true;
      }
      let controlledValue = value;
      if (prop === "center" || prop === "_center") {
        if (Number.isFinite(reactViewState.longitude) || Number.isFinite(reactViewState.latitude)) {
          controlledValue = new value.constructor(
            reactViewState.longitude ?? value.lng,
            reactViewState.latitude ?? value.lat
          );
        }
      } else if (prop === "zoom" || prop === "_zoom" || prop === "_seaLevelZoom") {
        if (Number.isFinite(reactViewState.zoom)) {
          controlledValue = controlledTransform[prop];
        }
      } else if (prop === "_centerAltitude") {
        if (Number.isFinite(reactViewState.elevation)) {
          controlledValue = controlledTransform[prop];
        }
      } else if (prop === "pitch" || prop === "_pitch") {
        if (Number.isFinite(reactViewState.pitch)) {
          controlledValue = controlledTransform[prop];
        }
      } else if (prop === "bearing" || prop === "rotation" || prop === "angle") {
        if (Number.isFinite(reactViewState.bearing)) {
          controlledValue = controlledTransform[prop];
        }
      }
      if (internalUpdate && controlledValue !== value) {
        proposedTransform = proposedTransform || controlledTransform.clone();
      }
      if (internalUpdate && proposedTransform) {
        proposedTransform[prop] = value;
      }
      controlledTransform[prop] = controlledValue;
      return true;
    }
  };
  return new Proxy(tr, handlers);
}

// ../react-mapbox/src/utils/style-utils.ts
var refProps = ["type", "source", "source-layer", "minzoom", "maxzoom", "filter", "layout"];
function normalizeStyle(style) {
  if (!style) {
    return null;
  }
  if (typeof style === "string") {
    return style;
  }
  if ("toJS" in style) {
    style = style.toJS();
  }
  if (!style.layers) {
    return style;
  }
  const layerIndex = {};
  for (const layer of style.layers) {
    layerIndex[layer.id] = layer;
  }
  const layers = style.layers.map((layer) => {
    let normalizedLayer = null;
    if ("interactive" in layer) {
      normalizedLayer = Object.assign({}, layer);
      delete normalizedLayer.interactive;
    }
    const layerRef = layerIndex[layer.ref];
    if (layerRef) {
      normalizedLayer = normalizedLayer || Object.assign({}, layer);
      delete normalizedLayer.ref;
      for (const propName of refProps) {
        if (propName in layerRef) {
          normalizedLayer[propName] = layerRef[propName];
        }
      }
    }
    return normalizedLayer || layer;
  });
  return { ...style, layers };
}

// ../react-mapbox/src/utils/deep-equal.ts
function arePointsEqual(a, b) {
  const ax = Array.isArray(a) ? a[0] : a ? a.x : 0;
  const ay = Array.isArray(a) ? a[1] : a ? a.y : 0;
  const bx = Array.isArray(b) ? b[0] : b ? b.x : 0;
  const by = Array.isArray(b) ? b[1] : b ? b.y : 0;
  return ax === bx && ay === by;
}
function deepEqual(a, b) {
  if (a === b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  if (Array.isArray(a)) {
    if (!Array.isArray(b) || a.length !== b.length) {
      return false;
    }
    for (let i = 0; i < a.length; i++) {
      if (!deepEqual(a[i], b[i])) {
        return false;
      }
    }
    return true;
  } else if (Array.isArray(b)) {
    return false;
  }
  if (typeof a === "object" && typeof b === "object") {
    const aKeys = Object.keys(a);
    const bKeys = Object.keys(b);
    if (aKeys.length !== bKeys.length) {
      return false;
    }
    for (const key of aKeys) {
      if (!b.hasOwnProperty(key)) {
        return false;
      }
      if (!deepEqual(a[key], b[key])) {
        return false;
      }
    }
    return true;
  }
  return false;
}

// ../react-mapbox/src/mapbox/mapbox.ts
var DEFAULT_STYLE = { version: 8, sources: {}, layers: [] };
var DEFAULT_SETTINGS = {
  minZoom: 0,
  maxZoom: 22,
  minPitch: 0,
  maxPitch: 85,
  maxBounds: [-180, -85.051129, 180, 85.051129],
  projection: "mercator",
  renderWorldCopies: true
};
var pointerEvents = {
  mousedown: "onMouseDown",
  mouseup: "onMouseUp",
  mouseover: "onMouseOver",
  mousemove: "onMouseMove",
  click: "onClick",
  dblclick: "onDblClick",
  mouseenter: "onMouseEnter",
  mouseleave: "onMouseLeave",
  mouseout: "onMouseOut",
  contextmenu: "onContextMenu",
  touchstart: "onTouchStart",
  touchend: "onTouchEnd",
  touchmove: "onTouchMove",
  touchcancel: "onTouchCancel"
};
var cameraEvents = {
  movestart: "onMoveStart",
  move: "onMove",
  moveend: "onMoveEnd",
  dragstart: "onDragStart",
  drag: "onDrag",
  dragend: "onDragEnd",
  zoomstart: "onZoomStart",
  zoom: "onZoom",
  zoomend: "onZoomEnd",
  rotatestart: "onRotateStart",
  rotate: "onRotate",
  rotateend: "onRotateEnd",
  pitchstart: "onPitchStart",
  pitch: "onPitch",
  pitchend: "onPitchEnd"
};
var otherEvents = {
  wheel: "onWheel",
  boxzoomstart: "onBoxZoomStart",
  boxzoomend: "onBoxZoomEnd",
  boxzoomcancel: "onBoxZoomCancel",
  resize: "onResize",
  load: "onLoad",
  render: "onRender",
  idle: "onIdle",
  remove: "onRemove",
  data: "onData",
  styledata: "onStyleData",
  sourcedata: "onSourceData",
  error: "onError"
};
var settingNames = [
  "minZoom",
  "maxZoom",
  "minPitch",
  "maxPitch",
  "maxBounds",
  "projection",
  "renderWorldCopies"
];
var handlerNames = [
  "scrollZoom",
  "boxZoom",
  "dragRotate",
  "dragPan",
  "keyboard",
  "doubleClickZoom",
  "touchZoomRotate",
  "touchPitch"
];
var _Mapbox = class _Mapbox {
  constructor(MapClass, props, container) {
    /** mapboxgl.Map instance */
    this._map = null;
    // Internal states
    /** Making updates driven by React props. Do not trigger React callbacks to avoid infinite loop */
    this._internalUpdate = false;
    /** Map is currently rendering */
    this._inRender = false;
    /** Map features under the pointer */
    this._hoveredFeatures = null;
    /** View state changes driven by React props
     * They still need to fire move/etc. events because controls such as marker/popup
     * subscribe to the move event internally to update their position
     * React callbacks like onMove are not called for these */
    this._deferredEvents = {
      move: false,
      zoom: false,
      pitch: false,
      rotate: false
    };
    this._onEvent = (e) => {
      const cb = this.props[otherEvents[e.type]];
      if (cb) {
        cb(e);
      } else if (e.type === "error") {
        console.error(e.error);
      }
    };
    this._onPointerEvent = (e) => {
      if (e.type === "mousemove" || e.type === "mouseout") {
        this._updateHover(e);
      }
      const cb = this.props[pointerEvents[e.type]];
      if (cb) {
        if (this.props.interactiveLayerIds && e.type !== "mouseover" && e.type !== "mouseout") {
          e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point);
        }
        cb(e);
        delete e.features;
      }
    };
    this._onCameraEvent = (e) => {
      if (!this._internalUpdate) {
        const cb = this.props[cameraEvents[e.type]];
        const tr = this._proxyTransform;
        if (cb) {
          e.viewState = transformToViewState(tr.$proposedTransform ?? tr);
          cb(e);
        }
        if (e.type === "moveend") {
          tr.$proposedTransform = null;
        }
      }
      if (e.type in this._deferredEvents) {
        this._deferredEvents[e.type] = false;
      }
    };
    this._MapClass = MapClass;
    this.props = props;
    this._initialize(container);
  }
  get map() {
    return this._map;
  }
  get transform() {
    return this._map.transform;
  }
  setProps(props) {
    const oldProps = this.props;
    this.props = props;
    const settingsChanged = this._updateSettings(props, oldProps);
    const sizeChanged = this._updateSize(props);
    const viewStateChanged = this._updateViewState(props, true);
    this._updateStyle(props, oldProps);
    this._updateStyleComponents(props, oldProps);
    this._updateHandlers(props, oldProps);
    if (settingsChanged || sizeChanged || viewStateChanged && !this._map.isMoving()) {
      this.redraw();
    }
  }
  static reuse(props, container) {
    const that = _Mapbox.savedMaps.pop();
    if (!that) {
      return null;
    }
    const map = that.map;
    const oldContainer = map.getContainer();
    container.className = oldContainer.className;
    while (oldContainer.childNodes.length > 0) {
      container.appendChild(oldContainer.childNodes[0]);
    }
    map._container = container;
    that.setProps({ ...props, styleDiffing: false });
    map.resize();
    const { initialViewState } = props;
    if (initialViewState) {
      if (initialViewState.bounds) {
        map.fitBounds(initialViewState.bounds, { ...initialViewState.fitBoundsOptions, duration: 0 });
      } else {
        that._updateViewState(initialViewState, false);
      }
    }
    if (map.isStyleLoaded()) {
      map.fire("load");
    } else {
      map.once("styledata", () => map.fire("load"));
    }
    map._update();
    return that;
  }
  /* eslint-disable complexity,max-statements */
  _initialize(container) {
    const { props } = this;
    const { mapStyle = DEFAULT_STYLE } = props;
    const mapOptions = {
      ...props,
      ...props.initialViewState,
      accessToken: props.mapboxAccessToken || getAccessTokenFromEnv() || null,
      container,
      style: normalizeStyle(mapStyle)
    };
    const viewState = mapOptions.initialViewState || mapOptions.viewState || mapOptions;
    Object.assign(mapOptions, {
      center: [viewState.longitude || 0, viewState.latitude || 0],
      zoom: viewState.zoom || 0,
      pitch: viewState.pitch || 0,
      bearing: viewState.bearing || 0
    });
    if (props.gl) {
      const getContext = HTMLCanvasElement.prototype.getContext;
      HTMLCanvasElement.prototype.getContext = () => {
        HTMLCanvasElement.prototype.getContext = getContext;
        return props.gl;
      };
    }
    const map = new this._MapClass(mapOptions);
    if (viewState.padding) {
      map.setPadding(viewState.padding);
    }
    if (props.cursor) {
      map.getCanvas().style.cursor = props.cursor;
    }
    this._createProxyTransform(map);
    const renderMap = map._render;
    map._render = (arg) => {
      this._inRender = true;
      renderMap.call(map, arg);
      this._inRender = false;
    };
    const runRenderTaskQueue = map._renderTaskQueue.run;
    map._renderTaskQueue.run = (arg) => {
      this._proxyTransform.$internalUpdate = true;
      runRenderTaskQueue.call(map._renderTaskQueue, arg);
      this._proxyTransform.$internalUpdate = false;
      this._fireDefferedEvents();
    };
    const jumpTo = map.jumpTo;
    map.jumpTo = (...args) => {
      this._proxyTransform.$internalUpdate = true;
      jumpTo.apply(map, args);
      this._proxyTransform.$internalUpdate = false;
      return map;
    };
    const fireEvent = map.fire;
    map.fire = this._fireEvent.bind(this, fireEvent);
    map.on("styledata", () => {
      this._updateStyleComponents(this.props, {});
    });
    map.on("sourcedata", () => {
      this._updateStyleComponents(this.props, {});
    });
    for (const eventName in pointerEvents) {
      map.on(eventName, this._onPointerEvent);
    }
    for (const eventName in cameraEvents) {
      map.on(eventName, this._onCameraEvent);
    }
    for (const eventName in otherEvents) {
      map.on(eventName, this._onEvent);
    }
    this._map = map;
  }
  /* eslint-enable complexity,max-statements */
  recycle() {
    const container = this.map.getContainer();
    const children = container.querySelector("[mapboxgl-children]");
    children == null ? void 0 : children.remove();
    _Mapbox.savedMaps.push(this);
  }
  destroy() {
    this._map.remove();
  }
  // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next
  // render cycle, which is managed by Mapbox's animation loop.
  // This removes the synchronization issue caused by requestAnimationFrame.
  redraw() {
    const map = this._map;
    if (!this._inRender && map.style) {
      if (map._frame) {
        map._frame.cancel();
        map._frame = null;
      }
      map._render();
    }
  }
  _createProxyTransform(map) {
    const proxyTransform = createProxyTransform(map.transform);
    map.transform = proxyTransform;
    map.painter.transform = proxyTransform;
    this._proxyTransform = proxyTransform;
  }
  /* Trigger map resize if size is controlled
     @param {object} nextProps
     @returns {bool} true if size has changed
   */
  _updateSize(nextProps) {
    const { viewState } = nextProps;
    if (viewState) {
      const map = this._map;
      if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) {
        map.resize();
        return true;
      }
    }
    return false;
  }
  // Adapted from map.jumpTo
  /* Update camera to match props
     @param {object} nextProps
     @param {bool} triggerEvents - should fire camera events
     @returns {bool} true if anything is changed
   */
  _updateViewState(nextProps, triggerEvents) {
    const viewState = nextProps.viewState || nextProps;
    const tr = this._proxyTransform;
    const { zoom, pitch, bearing } = tr;
    const changed = compareViewStateWithTransform(this._proxyTransform, viewState);
    tr.$reactViewState = viewState;
    if (changed && triggerEvents) {
      const deferredEvents = this._deferredEvents;
      deferredEvents.move = true;
      deferredEvents.zoom ||= zoom !== tr.zoom;
      deferredEvents.rotate ||= bearing !== tr.bearing;
      deferredEvents.pitch ||= pitch !== tr.pitch;
    }
    return changed;
  }
  /* Update camera constraints and projection settings to match props
     @param {object} nextProps
     @param {object} currProps
     @returns {bool} true if anything is changed
   */
  _updateSettings(nextProps, currProps) {
    const map = this._map;
    let changed = false;
    for (const propName of settingNames) {
      const propPresent = propName in nextProps || propName in currProps;
      if (propPresent && !deepEqual(nextProps[propName], currProps[propName])) {
        changed = true;
        const nextValue = propName in nextProps ? nextProps[propName] : DEFAULT_SETTINGS[propName];
        const setter = map[`set${propName[0].toUpperCase()}${propName.slice(1)}`];
        setter == null ? void 0 : setter.call(map, nextValue);
      }
    }
    return changed;
  }
  /* Update map style to match props
     @param {object} nextProps
     @param {object} currProps
     @returns {bool} true if style is changed
   */
  _updateStyle(nextProps, currProps) {
    if (nextProps.cursor !== currProps.cursor) {
      this._map.getCanvas().style.cursor = nextProps.cursor || "";
    }
    if (nextProps.mapStyle !== currProps.mapStyle) {
      const { mapStyle = DEFAULT_STYLE, styleDiffing = true } = nextProps;
      const options = {
        diff: styleDiffing
      };
      if ("localIdeographFontFamily" in nextProps) {
        options.localIdeographFontFamily = nextProps.localIdeographFontFamily;
      }
      this._map.setStyle(normalizeStyle(mapStyle), options);
      return true;
    }
    return false;
  }
  /* Update fog, light and terrain to match props
     @param {object} nextProps
     @param {object} currProps
     @returns {bool} true if anything is changed
   */
  _updateStyleComponents(nextProps, currProps) {
    const map = this._map;
    let changed = false;
    if (map.isStyleLoaded()) {
      if ("light" in nextProps && map.setLight && !deepEqual(nextProps.light, currProps.light)) {
        changed = true;
        map.setLight(nextProps.light);
      }
      if ("fog" in nextProps && map.setFog && !deepEqual(nextProps.fog, currProps.fog)) {
        changed = true;
        map.setFog(nextProps.fog);
      }
      if ("terrain" in nextProps && map.setTerrain && !deepEqual(nextProps.terrain, currProps.terrain)) {
        if (!nextProps.terrain || map.getSource(nextProps.terrain.source)) {
          changed = true;
          map.setTerrain(nextProps.terrain);
        }
      }
    }
    return changed;
  }
  /* Update interaction handlers to match props
     @param {object} nextProps
     @param {object} currProps
     @returns {bool} true if anything is changed
   */
  _updateHandlers(nextProps, currProps) {
    const map = this._map;
    let changed = false;
    for (const propName of handlerNames) {
      const newValue = nextProps[propName] ?? true;
      const oldValue = currProps[propName] ?? true;
      if (!deepEqual(newValue, oldValue)) {
        changed = true;
        if (newValue) {
          map[propName].enable(newValue);
        } else {
          map[propName].disable();
        }
      }
    }
    return changed;
  }
  _queryRenderedFeatures(point) {
    const map = this._map;
    const { interactiveLayerIds = [] } = this.props;
    try {
      return map.queryRenderedFeatures(point, {
        layers: interactiveLayerIds.filter(map.getLayer.bind(map))
      });
    } catch {
      return [];
    }
  }
  _updateHover(e) {
    var _a;
    const { props } = this;
    const shouldTrackHoveredFeatures = props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave);
    if (shouldTrackHoveredFeatures) {
      const eventType = e.type;
      const wasHovering = ((_a = this._hoveredFeatures) == null ? void 0 : _a.length) > 0;
      const features = this._queryRenderedFeatures(e.point);
      const isHovering = features.length > 0;
      if (!isHovering && wasHovering) {
        e.type = "mouseleave";
        this._onPointerEvent(e);
      }
      this._hoveredFeatures = features;
      if (isHovering && !wasHovering) {
        e.type = "mouseenter";
        this._onPointerEvent(e);
      }
      e.type = eventType;
    } else {
      this._hoveredFeatures = null;
    }
  }
  _fireEvent(baseFire, event, properties) {
    const map = this._map;
    const tr = this._proxyTransform;
    const internal = tr.$internalUpdate;
    try {
      tr.$internalUpdate = false;
      baseFire.call(map, event, properties);
    } finally {
      tr.$internalUpdate = internal;
    }
    return map;
  }
  // If there are camera changes driven by props, invoke camera events so that DOM controls are synced
  _fireDefferedEvents() {
    const map = this._map;
    this._internalUpdate = true;
    for (const eventType in this._deferredEvents) {
      if (this._deferredEvents[eventType]) {
        map.fire(eventType);
      }
    }
    this._internalUpdate = false;
  }
};
_Mapbox.savedMaps = [];
var Mapbox = _Mapbox;
function getAccessTokenFromEnv() {
  let accessToken = null;
  if (typeof location !== "undefined") {
    const match = /access_token=([^&\/]*)/.exec(location.search);
    accessToken = match && match[1];
  }
  try {
    accessToken = accessToken || process.env.MapboxAccessToken;
  } catch {
  }
  try {
    accessToken = accessToken || process.env.REACT_APP_MAPBOX_ACCESS_TOKEN;
  } catch {
  }
  return accessToken;
}

// ../react-mapbox/src/mapbox/create-ref.ts
var skipMethods = [
  "setMaxBounds",
  "setMinZoom",
  "setMaxZoom",
  "setMinPitch",
  "setMaxPitch",
  "setRenderWorldCopies",
  "setProjection",
  "setStyle",
  "addSource",
  "removeSource",
  "addLayer",
  "removeLayer",
  "setLayerZoomRange",
  "setFilter",
  "setPaintProperty",
  "setLayoutProperty",
  "setLight",
  "setTerrain",
  "setFog",
  "remove"
];
function createRef(mapInstance) {
  if (!mapInstance) {
    return null;
  }
  const map = mapInstance.map;
  const ref = {
    getMap: () => map,
    // Overwrite getters to use our shadow transform
    getCenter: () => mapInstance.transform.center,
    getZoom: () => mapInstance.transform.zoom,
    getBearing: () => mapInstance.transform.bearing,
    getPitch: () => mapInstance.transform.pitch,
    getPadding: () => mapInstance.transform.padding,
    getBounds: () => mapInstance.transform.getBounds(),
    project: (lnglat) => {
      const tr = map.transform;
      map.transform = mapInstance.transform;
      const result = map.project(lnglat);
      map.transform = tr;
      return result;
    },
    unproject: (point) => {
      const tr = map.transform;
      map.transform = mapInstance.transform;
      const result = map.unproject(point);
      map.transform = tr;
      return result;
    },
    // options diverge between mapbox and maplibre
    queryTerrainElevation: (lnglat, options) => {
      const tr = map.transform;
      map.transform = mapInstance.transform;
      const result = map.queryTerrainElevation(lnglat, options);
      map.transform = tr;
      return result;
    },
    queryRenderedFeatures: (geometry, options) => {
      const tr = map.transform;
      map.transform = mapInstance.transform;
      const result = map.queryRenderedFeatures(geometry, options);
      map.transform = tr;
      return result;
    }
  };
  for (const key of getMethodNames(map)) {
    if (!(key in ref) && !skipMethods.includes(key)) {
      ref[key] = map[key].bind(map);
    }
  }
  return ref;
}
function getMethodNames(obj) {
  const result = /* @__PURE__ */ new Set();
  let proto = obj;
  while (proto) {
    for (const key of Object.getOwnPropertyNames(proto)) {
      if (key[0] !== "_" && typeof obj[key] === "function" && key !== "fire" && key !== "setEventedParent") {
        result.add(key);
      }
    }
    proto = Object.getPrototypeOf(proto);
  }
  return Array.from(result);
}

// ../react-mapbox/src/utils/use-isomorphic-layout-effect.ts
var import_react2 = require("react");
var useIsomorphicLayoutEffect = typeof document !== "undefined" ? import_react2.useLayoutEffect : import_react2.useEffect;
var use_isomorphic_layout_effect_default = useIsomorphicLayoutEffect;

// ../react-mapbox/src/utils/set-globals.ts
var globalSettings = [
  "baseApiUrl",
  "maxParallelImageRequests",
  "workerClass",
  "workerCount",
  "workerUrl"
];
function setGlobals(mapLib, props) {
  for (const key of globalSettings) {
    if (key in props) {
      mapLib[key] = props[key];
    }
  }
  const {
    RTLTextPlugin = "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js"
  } = props;
  if (RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === "unavailable") {
    mapLib.setRTLTextPlugin(
      RTLTextPlugin,
      (error) => {
        if (error) {
          console.error(error);
        }
      },
      true
    );
  }
}

// ../react-mapbox/src/components/map.tsx
var MapContext = React2.createContext(null);
function _Map(props, ref) {
  const mountedMapsContext = (0, import_react3.useContext)(MountedMapsContext);
  const [mapInstance, setMapInstance] = (0, import_react3.useState)(null);
  const containerRef = (0, import_react3.useRef)();
  const { current: contextValue } = (0, import_react3.useRef)({ mapLib: null, map: null });
  (0, import_react3.useEffect)(() => {
    const mapLib = props.mapLib;
    let isMounted = true;
    let mapbox;
    Promise.resolve(mapLib || import("mapbox-gl")).then((module2) => {
      if (!isMounted) {
        return;
      }
      if (!module2) {
        throw new Error("Invalid mapLib");
      }
      const mapboxgl = "Map" in module2 ? module2 : module2.default;
      if (!mapboxgl.Map) {
        throw new Error("Invalid mapLib");
      }
      setGlobals(mapboxgl, props);
      if (props.reuseMaps) {
        mapbox = Mapbox.reuse(props, containerRef.current);
      }
      if (!mapbox) {
        mapbox = new Mapbox(mapboxgl.Map, props, containerRef.current);
      }
      contextValue.map = createRef(mapbox);
      contextValue.mapLib = mapboxgl;
      setMapInstance(mapbox);
      mountedMapsContext == null ? void 0 : mountedMapsContext.onMapMount(contextValue.map, props.id);
    }).catch((error) => {
      const { onError } = props;
      if (onError) {
        onError({
          type: "error",
          target: null,
          error
        });
      } else {
        console.error(error);
      }
    });
    return () => {
      isMounted = false;
      if (mapbox) {
        mountedMapsContext == null ? void 0 : mountedMapsContext.onMapUnmount(props.id);
        if (props.reuseMaps) {
          mapbox.recycle();
        } else {
          mapbox.destroy();
        }
      }
    };
  }, []);
  use_isomorphic_layout_effect_default(() => {
    if (mapInstance) {
      mapInstance.setProps(props);
    }
  });
  (0, import_react3.useImperativeHandle)(ref, () => contextValue.map, [mapInstance]);
  const style = (0, import_react3.useMemo)(
    () => ({
      position: "relative",
      width: "100%",
      height: "100%",
      ...props.style
    }),
    [props.style]
  );
  const CHILD_CONTAINER_STYLE = {
    height: "100%"
  };
  return /* @__PURE__ */ React2.createElement("div", { id: props.id, ref: containerRef, style }, mapInstance && /* @__PURE__ */ React2.createElement(MapContext.Provider, { value: contextValue }, /* @__PURE__ */ React2.createElement("div", { "mapboxgl-children": "", style: CHILD_CONTAINER_STYLE }, props.children)));
}
var Map = React2.forwardRef(_Map);

// ../react-mapbox/src/components/marker.ts
var React3 = __toESM(require("react"), 1);
var import_react_dom = require("react-dom");
var import_react4 = require("react");

// ../react-mapbox/src/utils/apply-react-style.ts
var unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/;
function applyReactStyle(element, styles) {
  if (!element || !styles) {
    return;
  }
  const style = element.style;
  for (const key in styles) {
    const value = styles[key];
    if (Number.isFinite(value) && !unitlessNumber.test(key)) {
      style[key] = `${value}px`;
    } else {
      style[key] = value;
    }
  }
}

// ../react-mapbox/src/utils/compare-class-names.ts
function compareClassNames(prevClassName, nextClassName) {
  if (prevClassName === nextClassName) {
    return null;
  }
  const prevClassList = getClassList(prevClassName);
  const nextClassList = getClassList(nextClassName);
  const diff = [];
  for (const c of nextClassList) {
    if (!prevClassList.has(c)) {
      diff.push(c);
    }
  }
  for (const c of prevClassList) {
    if (!nextClassList.has(c)) {
      diff.push(c);
    }
  }
  return diff.length === 0 ? null : diff;
}
function getClassList(className) {
  return new Set(className ? className.trim().split(/\s+/) : []);
}

// ../react-mapbox/src/components/marker.ts
var Marker = (0, import_react4.memo)(
  (0, import_react4.forwardRef)((props, ref) => {
    const { map, mapLib } = (0, import_react4.useContext)(MapContext);
    const thisRef = (0, import_react4.useRef)({ props });
    const marker = (0, import_react4.useMemo)(() => {
      let hasChildren = false;
      React3.Children.forEach(props.children, (el) => {
        if (el) {
          hasChildren = true;
        }
      });
      const options = {
        ...props,
        element: hasChildren ? document.createElement("div") : null
      };
      const mk = new mapLib.Marker(options);
      mk.setLngLat([props.longitude, props.latitude]);
      mk.getElement().addEventListener("click", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onClick) == null ? void 0 : _b.call(_a, {
          type: "click",
          target: mk,
          originalEvent: e
        });
      });
      mk.on("dragstart", (e) => {
        var _a, _b;
        const evt = e;
        evt.lngLat = marker.getLngLat();
        (_b = (_a = thisRef.current.props).onDragStart) == null ? void 0 : _b.call(_a, evt);
      });
      mk.on("drag", (e) => {
        var _a, _b;
        const evt = e;
        evt.lngLat = marker.getLngLat();
        (_b = (_a = thisRef.current.props).onDrag) == null ? void 0 : _b.call(_a, evt);
      });
      mk.on("dragend", (e) => {
        var _a, _b;
        const evt = e;
        evt.lngLat = marker.getLngLat();
        (_b = (_a = thisRef.current.props).onDragEnd) == null ? void 0 : _b.call(_a, evt);
      });
      return mk;
    }, []);
    (0, import_react4.useEffect)(() => {
      marker.addTo(map.getMap());
      return () => {
        marker.remove();
      };
    }, []);
    const {
      longitude,
      latitude,
      offset,
      style,
      draggable = false,
      popup = null,
      rotation = 0,
      rotationAlignment = "auto",
      pitchAlignment = "auto"
    } = props;
    (0, import_react4.useEffect)(() => {
      applyReactStyle(marker.getElement(), style);
    }, [style]);
    (0, import_react4.useImperativeHandle)(ref, () => marker, []);
    const oldProps = thisRef.current.props;
    if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
      marker.setLngLat([longitude, latitude]);
    }
    if (offset && !arePointsEqual(marker.getOffset(), offset)) {
      marker.setOffset(offset);
    }
    if (marker.isDraggable() !== draggable) {
      marker.setDraggable(draggable);
    }
    if (marker.getRotation() !== rotation) {
      marker.setRotation(rotation);
    }
    if (marker.getRotationAlignment() !== rotationAlignment) {
      marker.setRotationAlignment(rotationAlignment);
    }
    if (marker.getPitchAlignment() !== pitchAlignment) {
      marker.setPitchAlignment(pitchAlignment);
    }
    if (marker.getPopup() !== popup) {
      marker.setPopup(popup);
    }
    const classNameDiff = compareClassNames(oldProps.className, props.className);
    if (classNameDiff) {
      for (const c of classNameDiff) {
        marker.toggleClassName(c);
      }
    }
    thisRef.current.props = props;
    return (0, import_react_dom.createPortal)(props.children, marker.getElement());
  })
);

// ../react-mapbox/src/components/popup.ts
var import_react_dom2 = require("react-dom");
var import_react5 = require("react");
var Popup = (0, import_react5.memo)(
  (0, import_react5.forwardRef)((props, ref) => {
    const { map, mapLib } = (0, import_react5.useContext)(MapContext);
    const container = (0, import_react5.useMemo)(() => {
      return document.createElement("div");
    }, []);
    const thisRef = (0, import_react5.useRef)({ props });
    const popup = (0, import_react5.useMemo)(() => {
      const options = { ...props };
      const pp = new mapLib.Popup(options);
      pp.setLngLat([props.longitude, props.latitude]);
      pp.once("open", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onOpen) == null ? void 0 : _b.call(_a, e);
      });
      return pp;
    }, []);
    (0, import_react5.useEffect)(() => {
      const onClose = (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onClose) == null ? void 0 : _b.call(_a, e);
      };
      popup.on("close", onClose);
      popup.setDOMContent(container).addTo(map.getMap());
      return () => {
        popup.off("close", onClose);
        if (popup.isOpen()) {
          popup.remove();
        }
      };
    }, []);
    (0, import_react5.useEffect)(() => {
      applyReactStyle(popup.getElement(), props.style);
    }, [props.style]);
    (0, import_react5.useImperativeHandle)(ref, () => popup, []);
    if (popup.isOpen()) {
      const oldProps = thisRef.current.props;
      if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) {
        popup.setLngLat([props.longitude, props.latitude]);
      }
      if (props.offset && !deepEqual(oldProps.offset, props.offset)) {
        popup.options.anchor = props.anchor;
        popup.setOffset(props.offset);
      }
      if (oldProps.anchor !== props.anchor || oldProps.maxWidth !== props.maxWidth) {
        popup.setMaxWidth(props.maxWidth);
      }
      const classNameDiff = compareClassNames(oldProps.className, props.className);
      if (classNameDiff) {
        for (const c of classNameDiff) {
          popup.toggleClassName(c);
        }
      }
      thisRef.current.props = props;
    }
    return (0, import_react_dom2.createPortal)(props.children, container);
  })
);

// ../react-mapbox/src/components/attribution-control.ts
var import_react7 = require("react");

// ../react-mapbox/src/components/use-control.ts
var import_react6 = require("react");
function useControl(onCreate, arg1, arg2, arg3) {
  const context = (0, import_react6.useContext)(MapContext);
  const ctrl = (0, import_react6.useMemo)(() => onCreate(context), []);
  (0, import_react6.useEffect)(() => {
    const opts = arg3 || arg2 || arg1;
    const onAdd = typeof arg1 === "function" && typeof arg2 === "function" ? arg1 : null;
    const onRemove = typeof arg2 === "function" ? arg2 : typeof arg1 === "function" ? arg1 : null;
    const { map } = context;
    if (!map.hasControl(ctrl)) {
      map.addControl(ctrl, opts == null ? void 0 : opts.position);
      if (onAdd) {
        onAdd(context);
      }
    }
    return () => {
      if (onRemove) {
        onRemove(context);
      }
      if (map.hasControl(ctrl)) {
        map.removeControl(ctrl);
      }
    };
  }, []);
  return ctrl;
}

// ../react-mapbox/src/components/attribution-control.ts
function _AttributionControl(props) {
  const ctrl = useControl(({ mapLib }) => new mapLib.AttributionControl(props), {
    position: props.position
  });
  (0, import_react7.useEffect)(() => {
    applyReactStyle(ctrl._container, props.style);
  }, [props.style]);
  return null;
}
var AttributionControl = (0, import_react7.memo)(_AttributionControl);

// ../react-mapbox/src/components/fullscreen-control.ts
var import_react8 = require("react");
function _FullscreenControl(props) {
  const ctrl = useControl(
    ({ mapLib }) => new mapLib.FullscreenControl({
      container: props.containerId && document.getElementById(props.containerId)
    }),
    { position: props.position }
  );
  (0, import_react8.useEffect)(() => {
    applyReactStyle(ctrl._controlContainer, props.style);
  }, [props.style]);
  return null;
}
var FullscreenControl = (0, import_react8.memo)(_FullscreenControl);

// ../react-mapbox/src/components/geolocate-control.ts
var import_react9 = require("react");
function _GeolocateControl(props, ref) {
  const thisRef = (0, import_react9.useRef)({ props });
  const ctrl = useControl(
    ({ mapLib }) => {
      const gc = new mapLib.GeolocateControl(props);
      const setupUI = gc._setupUI.bind(gc);
      gc._setupUI = (args) => {
        if (!gc._container.hasChildNodes()) {
          setupUI(args);
        }
      };
      gc.on("geolocate", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onGeolocate) == null ? void 0 : _b.call(_a, e);
      });
      gc.on("error", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onError) == null ? void 0 : _b.call(_a, e);
      });
      gc.on("outofmaxbounds", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onOutOfMaxBounds) == null ? void 0 : _b.call(_a, e);
      });
      gc.on("trackuserlocationstart", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onTrackUserLocationStart) == null ? void 0 : _b.call(_a, e);
      });
      gc.on("trackuserlocationend", (e) => {
        var _a, _b;
        (_b = (_a = thisRef.current.props).onTrackUserLocationEnd) == null ? void 0 : _b.call(_a, e);
      });
      return gc;
    },
    { position: props.position }
  );
  thisRef.current.props = props;
  (0, import_react9.useImperativeHandle)(ref, () => ctrl, []);
  (0, import_react9.useEffect)(() => {
    applyReactStyle(ctrl._container, props.style);
  }, [props.style]);
  return null;
}
var GeolocateControl = (0, import_react9.memo)((0, import_react9.forwardRef)(_GeolocateControl));

// ../react-mapbox/src/components/navigation-control.ts
var import_react10 = require("react");
function _NavigationControl(props) {
  const ctrl = useControl(({ mapLib }) => new mapLib.NavigationControl(props), {
    position: props.position
  });
  (0, import_react10.useEffect)(() => {
    applyReactStyle(ctrl._container, props.style);
  }, [props.style]);
  return null;
}
var NavigationControl = (0, import_react10.memo)(_NavigationControl);

// ../react-mapbox/src/components/scale-control.ts
var import_react11 = require("react");
function _ScaleControl(props) {
  const ctrl = useControl(({ mapLib }) => new mapLib.ScaleControl(props), {
    position: props.position
  });
  const propsRef = (0, import_react11.useRef)(props);
  const prevProps = propsRef.current;
  propsRef.current = props;
  const { style } = props;
  if (props.maxWidth !== void 0 && props.maxWidth !== prevProps.maxWidth) {
    ctrl.options.maxWidth = props.maxWidth;
  }
  if (props.unit !== void 0 && props.unit !== prevProps.unit) {
    ctrl.setUnit(props.unit);
  }
  (0, import_react11.useEffect)(() => {
    applyReactStyle(ctrl._container, style);
  }, [style]);
  return null;
}
var ScaleControl = (0, import_react11.memo)(_ScaleControl);

// ../react-mapbox/src/components/source.ts
var React4 = __toESM(require("react"), 1);
var import_react12 = require("react");

// ../react-mapbox/src/utils/assert.ts
function assert(condition, message) {
  if (!condition) {
    throw new Error(message);
  }
}

// ../react-mapbox/src/utils/remove-source.ts
function removeSource(map, id) {
  var _a;
  const terrain = (_a = map.style) == null ? void 0 : _a.terrain;
  try {
    map.removeSource(id);
  } catch (error) {
    if (!(error instanceof TypeError) || !terrain || terrain.properties !== void 0) {
      throw error;
    }
    console.error(error);
  }
}

// ../react-mapbox/src/components/source.ts
var sourceCounter = 0;
function createSource(map, id, props) {
  if (map.style && map.style._loaded) {
    const options = { ...props };
    delete options.id;
    delete options.children;
    map.addSource(id, options);
    return map.getSource(id);
  }
  return null;
}
function updateSource(source, props, prevProps) {
  assert(props.id === prevProps.id, "source id changed");
  assert(props.type === prevProps.type, "source type changed");
  let changedKey = "";
  let changedKeyCount = 0;
  for (const key in props) {
    if (key !== "children" && key !== "id" && !deepEqual(prevProps[key], props[key])) {
      changedKey = key;
      changedKeyCount++;
    }
  }
  if (!changedKeyCount) {
    return;
  }
  const type = props.type;
  if (type === "geojson") {
    source.setData(props.data);
  } else if (type === "image") {
    source.updateImage({
      url: props.url,
      coordinates: props.coordinates
    });
  } else if ("setCoordinates" in source && changedKeyCount === 1 && changedKey === "coordinates") {
    source.setCoordinates(props.coordinates);
  } else if ("setUrl" in source && changedKey === "url") {
    source.setUrl(props.url);
  } else if ("setTiles" in source && changedKey === "tiles") {
    source.setTiles(props.tiles);
  } else {
    console.warn(`Unable to update <Source> prop: ${changedKey}`);
  }
}
function Source(props) {
  const map = (0, import_react12.useContext)(MapContext).map.getMap();
  const propsRef = (0, import_react12.useRef)(props);
  const [, setStyleLoaded] = (0, import_react12.useState)(0);
  const id = (0, import_react12.useMemo)(() => props.id || `jsx-source-${sourceCounter++}`, []);
  (0, import_react12.useEffect)(() => {
    if (map) {
      const forceUpdate = () => setTimeout(() => setStyleLoaded((version) => version + 1), 0);
      map.on("styledata", forceUpdate);
      forceUpdate();
      return () => {
        var _a;
        map.off("styledata", forceUpdate);
        if (map.style && map.style._loaded && map.getSource(id)) {
          const allLayers = (_a = map.getStyle()) == null ? void 0 : _a.layers;
          if (allLayers) {
            for (const layer of allLayers) {
              if (layer.source === id) {
                map.removeLayer(layer.id);
              }
            }
          }
          removeSource(map, id);
        }
      };
    }
    return void 0;
  }, [map]);
  let source = map && map.style && map.getSource(id);
  if (source) {
    updateSource(source, props, propsRef.current);
  } else {
    source = createSource(map, id, props);
  }
  propsRef.current = props;
  return source && React4.Children.map(
    props.children,
    (child) => child && (0, import_react12.cloneElement)(child, {
      source: id
    })
  ) || null;
}

// ../react-mapbox/src/components/layer.ts
var import_react13 = require("react");
function updateLayer(map, id, props, prevProps) {
  assert(props.id === prevProps.id, "layer id changed");
  assert(props.type === prevProps.type, "layer type changed");
  if (props.type === "custom" || prevProps.type === "custom") {
    return;
  }
  const { layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId } = props;
  if (beforeId !== prevProps.beforeId) {
    map.moveLayer(id, beforeId);
  }
  if (layout !== prevProps.layout) {
    const prevLayout = prevProps.layout || {};
    for (const key in layout) {
      if (!deepEqual(layout[key], prevLayout[key])) {
        map.setLayoutProperty(id, key, layout[key]);
      }
    }
    for (const key in prevLayout) {
      if (!layout.hasOwnProperty(key)) {
        map.setLayoutProperty(id, key, void 0);
      }
    }
  }
  if (paint !== prevProps.paint) {
    const prevPaint = prevProps.paint || {};
    for (const key in paint) {
      if (!deepEqual(paint[key], prevPaint[key])) {
        map.setPaintProperty(id, key, paint[key]);
      }
    }
    for (const key in prevPaint) {
      if (!paint.hasOwnProperty(key)) {
        map.setPaintProperty(id, key, void 0);
      }
    }
  }
  if (!deepEqual(filter, prevProps.filter)) {
    map.setFilter(id, filter);
  }
  if (minzoom !== prevProps.minzoom || maxzoom !== prevProps.maxzoom) {
    map.setLayerZoomRange(id, minzoom, maxzoom);
  }
}
function createLayer(map, id, props) {
  if (map.style && map.style._loaded && (!("source" in props) || map.getSource(props.source))) {
    const options = { ...props, id };
    delete options.beforeId;
    map.addLayer(options, props.beforeId);
  }
}
var layerCounter = 0;
function Layer(props) {
  const map = (0, import_react13.useContext)(MapContext).map.getMap();
  const propsRef = (0, import_react13.useRef)(props);
  const [, setStyleLoaded] = (0, import_react13.useState)(0);
  const id = (0, import_react13.useMemo)(() => props.id || `jsx-layer-${layerCounter++}`, []);
  (0, import_react13.useEffect)(() => {
    if (map) {
      const forceUpdate = () => setStyleLoaded((version) => version + 1);
      map.on("styledata", forceUpdate);
      forceUpdate();
      return () => {
        map.off("styledata", forceUpdate);
        if (map.style && map.style._loaded && map.getLayer(id)) {
          map.removeLayer(id);
        }
      };
    }
    return void 0;
  }, [map]);
  const layer = map && map.style && map.getLayer(id);
  if (layer) {
    try {
      updateLayer(map, id, props, propsRef.current);
    } catch (error) {
      console.warn(error);
    }
  } else {
    createLayer(map, id, props);
  }
  propsRef.current = props;
  return null;
}
//# sourceMappingURL=mapbox.cjs.map