Source: bemap-maplibre/bemap-maplibre-v5/bemap-map-maplibre-polygon.js

/**
 * BeNomad BeMap JavaScript API - MapLibre v5 - Polygon
 */

bemap.MapLibreMap.prototype.addPolygon = function(polygon, options) {
  if (!polygon || !bemap.inheritsof(polygon, bemap.Polygon)) return this;

  var opts = options || {};
  this._addOwnToProperties(polygon);

  var id = polygon._bemapId;
  polygon._maplibreSourceId = id + '-src';
  polygon._maplibreFillLayerId = id + '-fill';
  polygon._maplibreLineLayerId = id + '-line';

  var coords = [];
  var bemapCoords = polygon.getCoordinates();
  for (var i = 0; i < bemapCoords.length; i++) {
    coords.push([bemapCoords[i].getLon(), bemapCoords[i].getLat()]);
  }
  if (coords.length > 0 && (coords[0][0] !== coords[coords.length-1][0] || coords[0][1] !== coords[coords.length-1][1])) {
    coords.push(coords[0]);
  }

  var fillColor = 'rgba(0,0,0,0.3)', borderColor = 'rgba(0,0,0,1)', borderWidth = 2;
  if (polygon.style) {
    if (polygon.style.fillColor) fillColor = this._colorToRgba(polygon.style.fillColor);
    if (polygon.style.borderColor) borderColor = this._colorToRgba(polygon.style.borderColor);
    if (polygon.style.borderWidth) borderWidth = polygon.style.borderWidth;
  }

  var props = { _bemapId: polygon._bemapId };
  if (polygon.properties) { for (var k in polygon.properties) { props[k] = polygon.properties[k]; } }

  var geojson = {
    type: 'Feature',
    geometry: { type: 'Polygon', coordinates: [coords] },
    properties: props
  };

  this._geoJsonData[polygon._maplibreSourceId] = geojson;
  var _this = this;
  var addToMap = function() {
    if (!_this.native.getSource(polygon._maplibreSourceId)) {
      _this.native.addSource(polygon._maplibreSourceId, { type: 'geojson', data: geojson });
      _this.native.addLayer({
        id: polygon._maplibreFillLayerId, type: 'fill', source: polygon._maplibreSourceId,
        paint: { 'fill-color': fillColor, 'fill-opacity': 0.5 }
      });
      _this.native.addLayer({
        id: polygon._maplibreLineLayerId, type: 'line', source: polygon._maplibreSourceId,
        paint: { 'line-color': borderColor, 'line-width': borderWidth }
      });
      _this._geoJsonLayerIds.push(polygon._maplibreFillLayerId);
      _this._geoJsonLayerIds.push(polygon._maplibreLineLayerId);
    }
  };

  // Same robust scheduling as addPolyline (re-adds on every style-ready, incl.
  // after the charte setStyle) instead of the once-only `on('load')` that left
  // a polygon added before the charte load off the new style (PMT-38).
  this._enqueueStyleOp(polygon._maplibreFillLayerId, addToMap);

  polygon.native = { sourceId: polygon._maplibreSourceId };
  if (polygon.map === null) polygon.map = this;

  var l = opts.layer && bemap.inheritsof(opts.layer, bemap.Layer) ? opts.layer : this.getLayerByName(bemap.Map.DEFAULT_LAYER.POLYGON);
  if (polygon.layer === null) polygon.layer = l;
  if (l && l.native && l.native.geoJsonIds) {
    l.native.geoJsonIds.push(polygon._maplibreFillLayerId);
    l.native.geoJsonIds.push(polygon._maplibreLineLayerId);
  }
  if (l && l.native && l.native.features) l.native.features.push(polygon);

  return this;
};

bemap.MapLibreMap.prototype.removePolygon = function(polygon) {
  if (polygon && polygon.native) {
    // Clean up edit handlers
    if (polygon._insertHandler && polygon._insertLayerId) {
      try { this.native.off('click', polygon._insertLayerId, polygon._insertHandler); } catch(e) {}
      polygon._insertHandler = null;
    }
    if (polygon._vertexMarkers) {
      for (var vi = 0; vi < polygon._vertexMarkers.length; vi++) {
        try { polygon._vertexMarkers[vi].remove(); } catch(e) {}
      }
      polygon._vertexMarkers = null;
    }
    try {
      if (this.native.getLayer(polygon._maplibreFillLayerId)) this.native.removeLayer(polygon._maplibreFillLayerId);
      if (this.native.getLayer(polygon._maplibreLineLayerId)) this.native.removeLayer(polygon._maplibreLineLayerId);
      if (this.native.getSource(polygon._maplibreSourceId)) this.native.removeSource(polygon._maplibreSourceId);
      var idx1 = this._geoJsonLayerIds.indexOf(polygon._maplibreFillLayerId);
      if (idx1 > -1) this._geoJsonLayerIds.splice(idx1, 1);
      var idx2 = this._geoJsonLayerIds.indexOf(polygon._maplibreLineLayerId);
      if (idx2 > -1) this._geoJsonLayerIds.splice(idx2, 1);
    } catch(e) {}
    if (polygon._bemapId) delete this._featureRegistry[polygon._bemapId];
    if (polygon._maplibreSourceId) delete this._geoJsonData[polygon._maplibreSourceId];
    polygon.map = null;
    polygon.layer = null;
  }
  return this;
};

bemap.MapLibreMap.prototype.updatePolygonCoordinates = function(polygon) {};

bemap.MapLibreMap.prototype.draggablePolygon = function(polygon, callback, options) {
  return this._draggableFeature(polygon, callback, options, { singleFeature: true });
};

bemap.MapLibreMap.prototype.draggablePolygons = function(callback, options) {
  return this._draggableFeature(null, callback, options, { polygons: true });
};