@nextgis/leaflet-map-adapter 4.0.1 → 4.1.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.
@@ -1,4 +1,4 @@
1
- /** Bundle of @nextgis/leaflet-map-adapter; version: 4.0.1; author: NextGIS */
1
+ /** Bundle of @nextgis/leaflet-map-adapter; version: 4.1.0; author: NextGIS */
2
2
  var LeafletMapAdapter = (function () {
3
3
  'use strict';
4
4
 
@@ -15371,8 +15371,14 @@ var LeafletMapAdapter = (function () {
15371
15371
  }
15372
15372
 
15373
15373
  function updateUrlParams(urlStr, params) {
15374
- const url = new URL(urlStr);
15375
- const searchParams = new URLSearchParams(url.search);
15374
+ const hashIndex = urlStr.indexOf("#");
15375
+ const hash = hashIndex === -1 ? "" : urlStr.slice(hashIndex);
15376
+ const url = hashIndex === -1 ? urlStr : urlStr.slice(0, hashIndex);
15377
+ const queryIndex = url.indexOf("?");
15378
+ const baseUrl = queryIndex === -1 ? url : url.slice(0, queryIndex);
15379
+ const searchParams = new URLSearchParams(
15380
+ queryIndex === -1 ? "" : url.slice(queryIndex + 1)
15381
+ );
15376
15382
  Object.entries(params).forEach(([key, value]) => {
15377
15383
  if (value === void 0) {
15378
15384
  searchParams.delete(key);
@@ -15382,7 +15388,7 @@ var LeafletMapAdapter = (function () {
15382
15388
  });
15383
15389
  searchParams.set("timestamp", String((/* @__PURE__ */ new Date()).getTime()));
15384
15390
  const newSearch = [...searchParams.entries()].map(([key, value]) => `${key}=${value}`).join("&");
15385
- return `${url.origin}${url.pathname}?${newSearch}`;
15391
+ return `${baseUrl}?${newSearch}${hash}`;
15386
15392
  }
15387
15393
 
15388
15394
  function boundsToArray(bounds) {
@@ -16491,15 +16497,31 @@ var LeafletMapAdapter = (function () {
16491
16497
  /**
16492
16498
  * @param {PromiseQueueOptions} options - Configuration options for the queue.
16493
16499
  */
16494
- constructor({ concurrency = 1, delay = 0 } = {}) {
16500
+ constructor({
16501
+ delay = 0,
16502
+ limit,
16503
+ timeout,
16504
+ debounce,
16505
+ concurrency = 1
16506
+ } = {}) {
16495
16507
  __publicField$4(this, "queue", []);
16508
+ __publicField$4(this, "activeRequests", []);
16496
16509
  __publicField$4(this, "concurrency");
16497
- __publicField$4(this, "activeCount", 0);
16498
16510
  __publicField$4(this, "timeoutId");
16511
+ __publicField$4(this, "resumeTimer");
16499
16512
  __publicField$4(this, "delay");
16500
- __publicField$4(this, "toAbort", []);
16501
- this.concurrency = concurrency;
16502
- this.delay = delay;
16513
+ __publicField$4(this, "timeout");
16514
+ __publicField$4(this, "paused", false);
16515
+ __publicField$4(this, "idleResolvers", []);
16516
+ __publicField$4(this, "debounce");
16517
+ this.concurrency = limit != null ? limit : concurrency;
16518
+ this.delay = debounce != null ? debounce : delay;
16519
+ this.debounce = this.delay;
16520
+ this.timeout = timeout;
16521
+ }
16522
+ setLimit(limit) {
16523
+ this.concurrency = limit;
16524
+ this._next();
16503
16525
  }
16504
16526
  /**
16505
16527
  * Adds a task to the queue, which can be either a simple asynchronous function or an array containing a function and its abort handler.
@@ -16518,7 +16540,18 @@ var LeafletMapAdapter = (function () {
16518
16540
  * ```
16519
16541
  */
16520
16542
  add(promise, abort) {
16521
- this.queue.push({ promise, abort });
16543
+ var _a, _b;
16544
+ const options = typeof abort === "function" ? { abort } : abort;
16545
+ if ((options == null ? void 0 : options.id) !== void 0) {
16546
+ this.removeById(options.id);
16547
+ }
16548
+ this.queue.push({
16549
+ id: (_a = options == null ? void 0 : options.id) != null ? _a : Math.random().toString(36).slice(2),
16550
+ promise,
16551
+ abort: options == null ? void 0 : options.abort,
16552
+ abortController: new AbortController(),
16553
+ timeout: (_b = options == null ? void 0 : options.timeout) != null ? _b : this.timeout
16554
+ });
16522
16555
  this.debouncedNext();
16523
16556
  }
16524
16557
  /**
@@ -16528,60 +16561,167 @@ var LeafletMapAdapter = (function () {
16528
16561
  * queue.abort(); // Aborts all abortable tasks in the queue.
16529
16562
  */
16530
16563
  abort() {
16531
- for (const abort of this.toAbort) {
16532
- abort();
16564
+ for (const item of [...this.queue, ...this.activeRequests]) {
16565
+ this.abortRequest(item);
16566
+ this.clearRequestTimeout(item);
16567
+ item.completed = true;
16533
16568
  }
16534
- this.toAbort = [];
16535
- this.queue = [];
16569
+ this.queue.length = 0;
16570
+ this.activeRequests.length = 0;
16536
16571
  this._clearTimeout();
16572
+ this.checkIdle();
16573
+ }
16574
+ remove(id) {
16575
+ this.removeById(id);
16576
+ }
16577
+ clearQueue() {
16578
+ for (const item of this.queue) {
16579
+ this.abortRequest(item);
16580
+ item.completed = true;
16581
+ }
16582
+ this.queue.length = 0;
16583
+ this._clearTimeout();
16584
+ this.checkIdle();
16585
+ }
16586
+ waitAll() {
16587
+ return new Promise((resolve) => {
16588
+ if (this.isIdle()) {
16589
+ resolve();
16590
+ } else {
16591
+ this.idleResolvers.push(resolve);
16592
+ }
16593
+ });
16594
+ }
16595
+ pause(pauseDuration) {
16596
+ this.paused = true;
16597
+ this._clearTimeout();
16598
+ this._clearResumeTimer();
16599
+ if (pauseDuration) {
16600
+ this.resumeTimer = setTimeout(() => this.resume(), pauseDuration);
16601
+ }
16602
+ }
16603
+ resume() {
16604
+ if (!this.paused) return;
16605
+ this.paused = false;
16606
+ this._clearResumeTimer();
16607
+ this._next();
16537
16608
  }
16538
16609
  debouncedNext() {
16610
+ if (this.paused) return;
16611
+ if (this.activeRequests.length) {
16612
+ this._next();
16613
+ return;
16614
+ }
16539
16615
  this._clearTimeout();
16540
16616
  this.timeoutId = setTimeout(() => this._next(), this.delay);
16541
16617
  }
16542
16618
  _clearTimeout() {
16543
16619
  if (this.timeoutId) {
16544
16620
  clearTimeout(this.timeoutId);
16621
+ this.timeoutId = void 0;
16622
+ }
16623
+ }
16624
+ _clearResumeTimer() {
16625
+ if (this.resumeTimer) {
16626
+ clearTimeout(this.resumeTimer);
16627
+ this.resumeTimer = void 0;
16545
16628
  }
16546
16629
  }
16547
16630
  _next() {
16548
- while (this.activeCount < this.concurrency && this.queue.length > 0) {
16549
- const { promise, abort } = this.queue.shift();
16550
- this.activeCount++;
16551
- let toAbort = abort;
16552
- let request;
16553
- const execute = promise();
16554
- if (Array.isArray(execute)) {
16555
- request = execute[0];
16556
- toAbort = execute[1];
16557
- } else {
16558
- request = execute;
16559
- }
16560
- if (toAbort) {
16561
- this.toAbort.push(toAbort);
16631
+ if (this.paused) return;
16632
+ while (this.activeRequests.length < this.concurrency && this.queue.length) {
16633
+ const item = this.queue.shift();
16634
+ if (item.abortController.signal.aborted) continue;
16635
+ this.activeRequests.push(item);
16636
+ if (item.timeout && item.timeout > 0) {
16637
+ item.timeoutId = setTimeout(() => {
16638
+ this.abortRequest(
16639
+ item,
16640
+ new DOMException("Request timed out", "TimeoutError")
16641
+ );
16642
+ this.finishRequest(item);
16643
+ }, item.timeout);
16562
16644
  }
16563
- request.finally(() => {
16564
- this.activeCount--;
16565
- if (toAbort) {
16566
- this.toAbort = this.toAbort.filter((a) => a !== toAbort);
16645
+ try {
16646
+ const execute = item.promise({ signal: item.abortController.signal });
16647
+ const request = Array.isArray(execute) ? execute[0] : execute;
16648
+ if (Array.isArray(execute)) {
16649
+ const abort = item.abort;
16650
+ item.abort = abort ? () => {
16651
+ abort();
16652
+ execute[1]();
16653
+ } : execute[1];
16567
16654
  }
16568
- this.debouncedNext();
16569
- });
16655
+ Promise.resolve(request).then(
16656
+ () => this.finishRequest(item),
16657
+ () => this.finishRequest(item)
16658
+ );
16659
+ } catch (error) {
16660
+ this.finishRequest(item);
16661
+ console.error(error);
16662
+ }
16663
+ }
16664
+ this.checkIdle();
16665
+ }
16666
+ removeById(id) {
16667
+ this.queue = this.queue.filter((item) => {
16668
+ if (item.id !== id) return true;
16669
+ this.abortRequest(item);
16670
+ item.completed = true;
16671
+ return false;
16672
+ });
16673
+ for (const item of [...this.activeRequests]) {
16674
+ if (item.id === id) {
16675
+ this.abortRequest(item);
16676
+ this.finishRequest(item);
16677
+ }
16678
+ }
16679
+ this.checkIdle();
16680
+ }
16681
+ abortRequest(item, reason) {
16682
+ var _a;
16683
+ if (!item.abortController.signal.aborted) {
16684
+ item.abortController.abort(reason);
16685
+ }
16686
+ (_a = item.abort) == null ? void 0 : _a.call(item);
16687
+ }
16688
+ clearRequestTimeout(item) {
16689
+ if (item.timeoutId) {
16690
+ clearTimeout(item.timeoutId);
16691
+ item.timeoutId = void 0;
16692
+ }
16693
+ }
16694
+ finishRequest(item) {
16695
+ if (item.completed) return;
16696
+ item.completed = true;
16697
+ this.clearRequestTimeout(item);
16698
+ this.activeRequests = this.activeRequests.filter((x) => x !== item);
16699
+ this.checkIdle();
16700
+ this._next();
16701
+ }
16702
+ isIdle() {
16703
+ return this.queue.length === 0 && this.activeRequests.length === 0;
16704
+ }
16705
+ checkIdle() {
16706
+ if (this.isIdle()) {
16707
+ this.idleResolvers.splice(0).forEach((resolve) => resolve());
16570
16708
  }
16571
16709
  }
16572
16710
  }
16573
16711
 
16574
- const imageQueue = new Queue({ concurrency: 6, delay: 200 });
16712
+ const imageQueue = new Queue({ limit: 6, debounce: 150 });
16575
16713
 
16576
16714
  var __defProp$6 = Object.defineProperty;
16577
16715
  var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16578
16716
  var __publicField$3 = (obj, key, value) => __defNormalProp$6(obj, key + "" , value);
16717
+ const transparentImage = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAIBAAA=";
16579
16718
  class ImageOverlay extends leafletSrcExports.ImageOverlay {
16580
16719
  constructor(imageUrl, bounds, options) {
16581
16720
  super(imageUrl, bounds, options);
16582
16721
  __publicField$3(this, "_aborter");
16583
16722
  }
16584
16723
  cancelLoad() {
16724
+ imageQueue.remove(leafletSrcExports.Util.stamp(this));
16585
16725
  if (this._aborter) {
16586
16726
  this._aborter();
16587
16727
  this._aborter = void 0;
@@ -16593,19 +16733,27 @@ var LeafletMapAdapter = (function () {
16593
16733
  const img = this._image;
16594
16734
  const src = img.src;
16595
16735
  img.src = "";
16596
- imageQueue.add(() => {
16597
- const [promise, abortFunc] = callAjax({
16598
- src,
16599
- headers,
16600
- request,
16601
- withCredentials
16602
- });
16603
- promise.then((imgUrl) => {
16604
- img.src = imgUrl;
16605
- });
16606
- this._aborter = abortFunc;
16607
- return promise;
16608
- });
16736
+ imageQueue.add(
16737
+ ({ signal }) => {
16738
+ const [promise, abortFunc] = callAjax({
16739
+ src,
16740
+ headers,
16741
+ request,
16742
+ withCredentials
16743
+ });
16744
+ void promise.then((imgUrl) => {
16745
+ if (!signal.aborted) img.src = imgUrl || transparentImage;
16746
+ }).catch((error) => {
16747
+ if (!signal.aborted) {
16748
+ console.error(error);
16749
+ img.src = transparentImage;
16750
+ }
16751
+ });
16752
+ this._aborter = abortFunc;
16753
+ return [promise, abortFunc];
16754
+ },
16755
+ { id: leafletSrcExports.Util.stamp(this) }
16756
+ );
16609
16757
  }
16610
16758
  }
16611
16759
 
@@ -16675,6 +16823,12 @@ var LeafletMapAdapter = (function () {
16675
16823
  map.removeLayer(this._currentOverlay);
16676
16824
  delete this._currentOverlay;
16677
16825
  }
16826
+ if (this._loadedOverlay) {
16827
+ this._loadedOverlay.cancelLoad();
16828
+ this._loadedOverlay.off("load");
16829
+ map.removeLayer(this._loadedOverlay);
16830
+ this._loadedOverlay = void 0;
16831
+ }
16678
16832
  if (this._currentUrl) {
16679
16833
  delete this._currentUrl;
16680
16834
  }
@@ -16700,6 +16854,7 @@ var LeafletMapAdapter = (function () {
16700
16854
  if (this._loadedOverlay) {
16701
16855
  this._loadedOverlay.cancelLoad();
16702
16856
  this._loadedOverlay.off("load");
16857
+ this._map.removeLayer(this._loadedOverlay);
16703
16858
  this._loadedOverlay = void 0;
16704
16859
  }
16705
16860
  const overlay = new ImageOverlay(url, bounds, {
@@ -16750,6 +16905,7 @@ var LeafletMapAdapter = (function () {
16750
16905
  if (this._currentOverlay) {
16751
16906
  this._currentOverlay.setOpacity(opacity);
16752
16907
  }
16908
+ this.fire("opacitychange", { opacity });
16753
16909
  }
16754
16910
  bringToBack() {
16755
16911
  this.options.isBack = true;