aur-openlayers 0.0.3 → 1.0.1

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.
@@ -39,6 +39,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
39
39
  ` }]
40
40
  }] });
41
41
 
42
+ /**
43
+ * Ошибка, выбрасываемая при нарушении уникальности id моделей слоя.
44
+ *
45
+ * Возникает при попытке:
46
+ * - добавить модель с уже существующим id;
47
+ * - передать в setModels массив с дублирующимися id.
48
+ */
49
+ class DuplicateModelIdError extends Error {
50
+ id;
51
+ layerId;
52
+ name = 'DuplicateModelIdError';
53
+ constructor(
54
+ /** Дублирующийся id. */
55
+ id,
56
+ /** Идентификатор слоя. */
57
+ layerId, message) {
58
+ super(message ?? `Model with id "${String(id)}" already exists on layer (${layerId}).`);
59
+ this.id = id;
60
+ this.layerId = layerId;
61
+ }
62
+ }
63
+
42
64
  class FlushScheduler {
43
65
  defaultPolicy;
44
66
  queue = new Map();
@@ -314,6 +336,54 @@ class InteractionManager {
314
336
  if (this.activeTranslates.has(entry.descriptor.id)) {
315
337
  continue;
316
338
  }
339
+ const modify = interactions?.modify;
340
+ if (modify && this.isEnabled(modify.enabled)) {
341
+ const { items: candidates } = this.hitTest({
342
+ layerId: entry.descriptor.id,
343
+ layer: entry.layer,
344
+ api: entry.api,
345
+ descriptor: entry.descriptor,
346
+ event,
347
+ hitTolerance: this.getHitTolerance(modify.hitTolerance),
348
+ });
349
+ if (candidates.length > 0) {
350
+ const modifyEvent = this.createModifyEvent(event, 'modifystart', candidates);
351
+ let target;
352
+ if (modify.pickTarget) {
353
+ target = modify.pickTarget({ candidates, ctx: this.ctx, event: modifyEvent });
354
+ }
355
+ else {
356
+ target = candidates[0];
357
+ }
358
+ if (target) {
359
+ const targetKey = entry.descriptor.feature.id(target.model);
360
+ const resolved = this.resolveTarget(entry, targetKey);
361
+ if (resolved) {
362
+ const active = {
363
+ targetKey,
364
+ lastItem: resolved,
365
+ moveThrottleMs: modify.moveThrottleMs ?? 0,
366
+ modify,
367
+ };
368
+ this.activeModifies.set(entry.descriptor.id, active);
369
+ this.lockDragPan();
370
+ if (modify.state) {
371
+ this.applyState([resolved], modify.state, true);
372
+ }
373
+ const handled = modify.onStart
374
+ ? this.isHandled(modify.onStart({ item: resolved, ctx: this.ctx, event: modifyEvent }))
375
+ : false;
376
+ active.lastHandled = handled;
377
+ if (handled && this.shouldStopPropagation(modify)) {
378
+ break;
379
+ }
380
+ }
381
+ }
382
+ }
383
+ }
384
+ if (this.activeModifies.has(entry.descriptor.id)) {
385
+ continue;
386
+ }
317
387
  }
318
388
  this.updateCursor(event);
319
389
  }
@@ -624,21 +694,27 @@ class InteractionManager {
624
694
  let needsPointerUp = false;
625
695
  this.schema.layers.forEach((descriptor) => {
626
696
  const state = this.enabledState.get(descriptor.id);
627
- if (state?.hover) {
697
+ const interactions = descriptor.feature.interactions;
698
+ const maybeHover = this.isMaybeEnabled(interactions?.hover?.enabled);
699
+ const maybeClick = this.isMaybeEnabled(interactions?.click?.enabled);
700
+ const maybeSelect = this.isMaybeEnabled(interactions?.select?.enabled);
701
+ const maybeDoubleClick = this.isMaybeEnabled(interactions?.doubleClick?.enabled);
702
+ const maybeTranslate = this.isMaybeEnabled(interactions?.translate?.enabled);
703
+ const maybeModify = this.isMaybeEnabled(interactions?.modify?.enabled);
704
+ if (state?.hover || maybeHover) {
628
705
  needsPointerMove = true;
629
706
  }
630
- if (state?.click || state?.select) {
707
+ if (state?.click || state?.select || maybeClick || maybeSelect) {
631
708
  needsSingleClick = true;
632
709
  }
633
- if (state?.doubleClick) {
710
+ if (state?.doubleClick || maybeDoubleClick) {
634
711
  needsDoubleClick = true;
635
712
  }
636
- if (state?.translate || state?.modify) {
713
+ if (state?.translate || state?.modify || maybeTranslate || maybeModify) {
637
714
  needsPointerDown = true;
638
715
  needsPointerDrag = true;
639
716
  needsPointerUp = true;
640
717
  }
641
- const interactions = descriptor.feature.interactions;
642
718
  if (interactions && this.hasCursorInteraction(interactions)) {
643
719
  needsPointerMove = true;
644
720
  }
@@ -759,7 +835,7 @@ class InteractionManager {
759
835
  interactions.translate,
760
836
  interactions.modify,
761
837
  ];
762
- return candidates.some((interaction) => interaction?.cursor && this.isEnabled(interaction.enabled));
838
+ return candidates.some((interaction) => interaction?.cursor && this.isMaybeEnabled(interaction.enabled));
763
839
  }
764
840
  toggleListener(type, enabled, handler) {
765
841
  if (enabled) {
@@ -1255,6 +1331,15 @@ class InteractionManager {
1255
1331
  }
1256
1332
  return enabled;
1257
1333
  }
1334
+ isMaybeEnabled(enabled) {
1335
+ if (enabled === undefined) {
1336
+ return true;
1337
+ }
1338
+ if (typeof enabled === 'function') {
1339
+ return true;
1340
+ }
1341
+ return enabled;
1342
+ }
1258
1343
  processHover(entry, hover, items, event) {
1259
1344
  const prev = this.hoverItems.get(entry.descriptor.id) ?? new Map();
1260
1345
  const next = this.itemsToMap(entry, items);
@@ -1279,7 +1364,13 @@ class InteractionManager {
1279
1364
  return handled;
1280
1365
  }
1281
1366
  processSelect(entry, select, items, event) {
1282
- if (items.length === 0) {
1367
+ const selectedItems = select.pickTargets
1368
+ ? select.pickTargets({ candidates: items, ctx: this.ctx, event })
1369
+ : items;
1370
+ if (!selectedItems || selectedItems.length === 0) {
1371
+ if (select.pickTargets) {
1372
+ return false;
1373
+ }
1283
1374
  const prev = this.selectedItems.get(entry.descriptor.id);
1284
1375
  this.selectedItems.set(entry.descriptor.id, new Map());
1285
1376
  if (select.onClear) {
@@ -1295,9 +1386,9 @@ class InteractionManager {
1295
1386
  return false;
1296
1387
  }
1297
1388
  const prev = this.selectedItems.get(entry.descriptor.id) ?? new Map();
1298
- const next = this.itemsToMap(entry, items);
1389
+ const next = this.itemsToMap(entry, selectedItems);
1299
1390
  const handled = select.onSelect
1300
- ? this.isHandled(select.onSelect({ items, ctx: this.ctx, event }))
1391
+ ? this.isHandled(select.onSelect({ items: selectedItems, ctx: this.ctx, event }))
1301
1392
  : false;
1302
1393
  if (select.state) {
1303
1394
  const added = Array.from(next.entries())
@@ -1313,15 +1404,9 @@ class InteractionManager {
1313
1404
  return handled;
1314
1405
  }
1315
1406
  processClick(entry, click, items, event) {
1316
- if (items.length === 0) {
1317
- return false;
1318
- }
1319
1407
  return this.isHandled(click.onClick({ items, ctx: this.ctx, event }));
1320
1408
  }
1321
1409
  processDoubleClick(entry, doubleClick, items, event) {
1322
- if (items.length === 0) {
1323
- return false;
1324
- }
1325
1410
  return this.isHandled(doubleClick.onDoubleClick({ items, ctx: this.ctx, event }));
1326
1411
  }
1327
1412
  itemsToMap(entry, items) {
@@ -1587,16 +1672,24 @@ class VectorLayerBase {
1587
1672
  registry = new FeatureRegistry();
1588
1673
  scheduleInvalidate;
1589
1674
  ctx;
1675
+ layerId;
1590
1676
  changeHandlers = new Set();
1677
+ collectionHandlers = new Set();
1678
+ models = [];
1591
1679
  constructor(options) {
1592
1680
  this.descriptor = options.descriptor.feature;
1593
1681
  this.layer = options.layer;
1594
1682
  this.source = options.source;
1595
1683
  this.ctx = options.ctx;
1596
1684
  this.scheduleInvalidate = options.scheduleInvalidate;
1685
+ this.layerId = options.descriptor.id;
1597
1686
  }
1598
1687
  setModels(models) {
1599
- this.setModelsInternal(models);
1688
+ this.assertUniqueIds(models);
1689
+ this.applyModelsUpdate({
1690
+ nextModels: models,
1691
+ reason: 'set',
1692
+ });
1600
1693
  }
1601
1694
  invalidate() {
1602
1695
  this.scheduleInvalidate();
@@ -1623,6 +1716,7 @@ class VectorLayerBase {
1623
1716
  }
1624
1717
  const reason = opts?.reason ?? 'mutate';
1625
1718
  this.registry.updateModel(id, next);
1719
+ this.replaceModelSnapshot(id, next);
1626
1720
  this.syncFeatureFromModel(next);
1627
1721
  this.scheduleInvalidate();
1628
1722
  if (!opts?.silent) {
@@ -1642,6 +1736,7 @@ class VectorLayerBase {
1642
1736
  return;
1643
1737
  }
1644
1738
  this.registry.updateModel(id, next);
1739
+ this.replaceModelSnapshot(id, next);
1645
1740
  this.syncFeatureFromModel(next);
1646
1741
  changes.push({ prev, next, reason });
1647
1742
  });
@@ -1657,6 +1752,66 @@ class VectorLayerBase {
1657
1752
  this.changeHandlers.add(cb);
1658
1753
  return () => this.changeHandlers.delete(cb);
1659
1754
  }
1755
+ onModelsCollectionChanged(cb) {
1756
+ this.collectionHandlers.add(cb);
1757
+ return () => this.collectionHandlers.delete(cb);
1758
+ }
1759
+ addModel(model) {
1760
+ this.addModels([model]);
1761
+ }
1762
+ addModels(models) {
1763
+ if (models.length === 0) {
1764
+ return;
1765
+ }
1766
+ const existingIds = new Set(this.models.map((item) => this.descriptor.id(item)));
1767
+ const batchIds = new Set();
1768
+ for (const model of models) {
1769
+ const id = this.descriptor.id(model);
1770
+ if (existingIds.has(id) || batchIds.has(id)) {
1771
+ this.throwDuplicateId(id);
1772
+ }
1773
+ batchIds.add(id);
1774
+ }
1775
+ this.applyModelsUpdate({
1776
+ nextModels: [...this.models, ...models],
1777
+ reason: 'add',
1778
+ added: models,
1779
+ });
1780
+ }
1781
+ removeModelsById(ids) {
1782
+ if (ids.length === 0 || this.models.length === 0) {
1783
+ return 0;
1784
+ }
1785
+ const idSet = new Set(ids);
1786
+ const removed = [];
1787
+ const nextModels = this.models.filter((model) => {
1788
+ const id = this.descriptor.id(model);
1789
+ if (idSet.has(id)) {
1790
+ removed.push(model);
1791
+ return false;
1792
+ }
1793
+ return true;
1794
+ });
1795
+ if (removed.length === 0) {
1796
+ return 0;
1797
+ }
1798
+ this.applyModelsUpdate({
1799
+ nextModels,
1800
+ reason: 'remove',
1801
+ removed,
1802
+ });
1803
+ return removed.length;
1804
+ }
1805
+ clear() {
1806
+ if (this.models.length === 0) {
1807
+ return;
1808
+ }
1809
+ this.applyModelsUpdate({
1810
+ nextModels: [],
1811
+ reason: 'clear',
1812
+ removed: [...this.models],
1813
+ });
1814
+ }
1660
1815
  /** Fit view to all features on the layer. No-op if extent is empty. */
1661
1816
  centerOnAllModels(opts) {
1662
1817
  const current = this.getCenterOnAllModelsSource();
@@ -1720,19 +1875,10 @@ class VectorLayerBase {
1720
1875
  return this.registry.getFeature(id) != null;
1721
1876
  }
1722
1877
  getAllModels() {
1723
- const out = [];
1724
- this.registry.forEachId((id) => {
1725
- const model = this.registry.getModel(id);
1726
- if (model !== undefined) {
1727
- out.push(model);
1728
- }
1729
- });
1730
- return out;
1878
+ return [...this.models];
1731
1879
  }
1732
1880
  getAllModelIds() {
1733
- const out = [];
1734
- this.registry.forEachId((id) => out.push(id));
1735
- return out;
1881
+ return this.models.map((model) => this.descriptor.id(model));
1736
1882
  }
1737
1883
  setFeatureStates(ids, states) {
1738
1884
  const targetIds = Array.isArray(ids) ? ids : [ids];
@@ -1745,6 +1891,9 @@ class VectorLayerBase {
1745
1891
  });
1746
1892
  this.scheduleInvalidate();
1747
1893
  }
1894
+ clearFeatureStates(ids) {
1895
+ this.setFeatureStates(ids, []);
1896
+ }
1748
1897
  setModelsInternal(models) {
1749
1898
  const nextIds = new Set();
1750
1899
  models.forEach((model) => {
@@ -1789,6 +1938,43 @@ class VectorLayerBase {
1789
1938
  }
1790
1939
  this.changeHandlers.forEach((handler) => handler(changes));
1791
1940
  }
1941
+ emitCollectionChange(event) {
1942
+ this.collectionHandlers.forEach((handler) => handler(event));
1943
+ }
1944
+ assertUniqueIds(models) {
1945
+ const ids = new Set();
1946
+ for (const model of models) {
1947
+ const id = this.descriptor.id(model);
1948
+ if (ids.has(id)) {
1949
+ this.throwDuplicateId(id);
1950
+ }
1951
+ ids.add(id);
1952
+ }
1953
+ }
1954
+ throwDuplicateId(id) {
1955
+ throw new DuplicateModelIdError(id, this.layerId);
1956
+ }
1957
+ applyModelsUpdate(args) {
1958
+ const prevSnapshot = [...this.models];
1959
+ const internalNext = [...args.nextModels];
1960
+ this.models = internalNext;
1961
+ this.setModelsInternal(this.models);
1962
+ const nextSnapshot = [...internalNext];
1963
+ this.emitCollectionChange({
1964
+ prev: prevSnapshot,
1965
+ next: nextSnapshot,
1966
+ reason: args.reason,
1967
+ added: args.added ? [...args.added] : undefined,
1968
+ removed: args.removed ? [...args.removed] : undefined,
1969
+ });
1970
+ }
1971
+ replaceModelSnapshot(id, model) {
1972
+ const index = this.models.findIndex((item) => this.descriptor.id(item) === id);
1973
+ if (index === -1) {
1974
+ return;
1975
+ }
1976
+ this.models[index] = model;
1977
+ }
1792
1978
  }
1793
1979
 
1794
1980
  class ClusteredVectorLayer extends VectorLayerBase {
@@ -2120,5 +2306,5 @@ class LayerManager {
2120
2306
  * Generated bundle index. Do not edit.
2121
2307
  */
2122
2308
 
2123
- export { LayerManager, LibComponent, LibService };
2309
+ export { DuplicateModelIdError, LayerManager, LibComponent, LibService };
2124
2310
  //# sourceMappingURL=aur-openlayers.mjs.map