aur-openlayers 0.0.2 → 1.0.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.
@@ -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
  }
@@ -728,7 +804,7 @@ class InteractionManager {
728
804
  return;
729
805
  }
730
806
  const id = entry.descriptor.feature.id(item.model);
731
- entry.api.mutate(id, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, geometry), 'modify');
807
+ entry.api.mutate(id, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, geometry), { reason: 'modify' });
732
808
  });
733
809
  });
734
810
  if (modify.onEnd) {
@@ -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) {
@@ -993,7 +1069,7 @@ class InteractionManager {
993
1069
  }
994
1070
  const translated = geometry.clone();
995
1071
  translated.translate(delta[0], delta[1]);
996
- this.runInteractionMutation(() => entry.api.mutate(active.targetKey, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, translated), 'translate'));
1072
+ this.runInteractionMutation(() => entry.api.mutate(active.targetKey, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, translated), { reason: 'translate' }));
997
1073
  if (translate.onChange) {
998
1074
  const translateEvent = this.createTranslateEvent(event, active.startCoordinate, 'translating', [resolved]);
999
1075
  active.lastHandled = this.isHandled(translate.onChange({ item: resolved, ctx: this.ctx, event: translateEvent }));
@@ -1015,7 +1091,7 @@ class InteractionManager {
1015
1091
  return;
1016
1092
  }
1017
1093
  const nextGeometry = geometry.clone();
1018
- this.runInteractionMutation(() => entry.api.mutate(active.targetKey, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, nextGeometry), 'modify'));
1094
+ this.runInteractionMutation(() => entry.api.mutate(active.targetKey, (prev) => entry.descriptor.feature.geometry.applyGeometryToModel(prev, nextGeometry), { reason: 'modify' }));
1019
1095
  if (modify.onChange) {
1020
1096
  const modifyEvent = this.createModifyEvent(event, 'modifying', [resolved]);
1021
1097
  active.lastHandled = this.isHandled(modify.onChange({ item: resolved, ctx: this.ctx, event: modifyEvent }));
@@ -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);
@@ -1313,15 +1398,9 @@ class InteractionManager {
1313
1398
  return handled;
1314
1399
  }
1315
1400
  processClick(entry, click, items, event) {
1316
- if (items.length === 0) {
1317
- return false;
1318
- }
1319
1401
  return this.isHandled(click.onClick({ items, ctx: this.ctx, event }));
1320
1402
  }
1321
1403
  processDoubleClick(entry, doubleClick, items, event) {
1322
- if (items.length === 0) {
1323
- return false;
1324
- }
1325
1404
  return this.isHandled(doubleClick.onDoubleClick({ items, ctx: this.ctx, event }));
1326
1405
  }
1327
1406
  itemsToMap(entry, items) {
@@ -1587,16 +1666,24 @@ class VectorLayerBase {
1587
1666
  registry = new FeatureRegistry();
1588
1667
  scheduleInvalidate;
1589
1668
  ctx;
1669
+ layerId;
1590
1670
  changeHandlers = new Set();
1671
+ collectionHandlers = new Set();
1672
+ models = [];
1591
1673
  constructor(options) {
1592
1674
  this.descriptor = options.descriptor.feature;
1593
1675
  this.layer = options.layer;
1594
1676
  this.source = options.source;
1595
1677
  this.ctx = options.ctx;
1596
1678
  this.scheduleInvalidate = options.scheduleInvalidate;
1679
+ this.layerId = options.descriptor.id;
1597
1680
  }
1598
1681
  setModels(models) {
1599
- this.setModelsInternal(models);
1682
+ this.assertUniqueIds(models);
1683
+ this.applyModelsUpdate({
1684
+ nextModels: models,
1685
+ reason: 'set',
1686
+ });
1600
1687
  }
1601
1688
  invalidate() {
1602
1689
  this.scheduleInvalidate();
@@ -1612,7 +1699,7 @@ class VectorLayerBase {
1612
1699
  getModelByFeature(feature) {
1613
1700
  return this.registry.getModelByFeature(feature);
1614
1701
  }
1615
- mutate(id, update, reason = 'mutate') {
1702
+ mutate(id, update, opts) {
1616
1703
  const prev = this.registry.getModel(id);
1617
1704
  if (!prev) {
1618
1705
  return;
@@ -1621,13 +1708,18 @@ class VectorLayerBase {
1621
1708
  if (next === prev) {
1622
1709
  return;
1623
1710
  }
1711
+ const reason = opts?.reason ?? 'mutate';
1624
1712
  this.registry.updateModel(id, next);
1713
+ this.replaceModelSnapshot(id, next);
1625
1714
  this.syncFeatureFromModel(next);
1626
1715
  this.scheduleInvalidate();
1627
- this.emitModelChanges([{ prev, next, reason }]);
1716
+ if (!opts?.silent) {
1717
+ this.emitModelChanges([{ prev, next, reason }]);
1718
+ }
1628
1719
  }
1629
- mutateMany(ids, update, reason = 'mutate') {
1720
+ mutateMany(ids, update, opts) {
1630
1721
  const changes = [];
1722
+ const reason = opts?.reason ?? 'mutate';
1631
1723
  ids.forEach((id) => {
1632
1724
  const prev = this.registry.getModel(id);
1633
1725
  if (!prev) {
@@ -1638,6 +1730,7 @@ class VectorLayerBase {
1638
1730
  return;
1639
1731
  }
1640
1732
  this.registry.updateModel(id, next);
1733
+ this.replaceModelSnapshot(id, next);
1641
1734
  this.syncFeatureFromModel(next);
1642
1735
  changes.push({ prev, next, reason });
1643
1736
  });
@@ -1645,12 +1738,74 @@ class VectorLayerBase {
1645
1738
  return;
1646
1739
  }
1647
1740
  this.scheduleInvalidate();
1648
- this.emitModelChanges(changes);
1741
+ if (!opts?.silent) {
1742
+ this.emitModelChanges(changes);
1743
+ }
1649
1744
  }
1650
1745
  onModelsChanged(cb) {
1651
1746
  this.changeHandlers.add(cb);
1652
1747
  return () => this.changeHandlers.delete(cb);
1653
1748
  }
1749
+ onModelsCollectionChanged(cb) {
1750
+ this.collectionHandlers.add(cb);
1751
+ return () => this.collectionHandlers.delete(cb);
1752
+ }
1753
+ addModel(model) {
1754
+ this.addModels([model]);
1755
+ }
1756
+ addModels(models) {
1757
+ if (models.length === 0) {
1758
+ return;
1759
+ }
1760
+ const existingIds = new Set(this.models.map((item) => this.descriptor.id(item)));
1761
+ const batchIds = new Set();
1762
+ for (const model of models) {
1763
+ const id = this.descriptor.id(model);
1764
+ if (existingIds.has(id) || batchIds.has(id)) {
1765
+ this.throwDuplicateId(id);
1766
+ }
1767
+ batchIds.add(id);
1768
+ }
1769
+ this.applyModelsUpdate({
1770
+ nextModels: [...this.models, ...models],
1771
+ reason: 'add',
1772
+ added: models,
1773
+ });
1774
+ }
1775
+ removeModelsById(ids) {
1776
+ if (ids.length === 0 || this.models.length === 0) {
1777
+ return 0;
1778
+ }
1779
+ const idSet = new Set(ids);
1780
+ const removed = [];
1781
+ const nextModels = this.models.filter((model) => {
1782
+ const id = this.descriptor.id(model);
1783
+ if (idSet.has(id)) {
1784
+ removed.push(model);
1785
+ return false;
1786
+ }
1787
+ return true;
1788
+ });
1789
+ if (removed.length === 0) {
1790
+ return 0;
1791
+ }
1792
+ this.applyModelsUpdate({
1793
+ nextModels,
1794
+ reason: 'remove',
1795
+ removed,
1796
+ });
1797
+ return removed.length;
1798
+ }
1799
+ clear() {
1800
+ if (this.models.length === 0) {
1801
+ return;
1802
+ }
1803
+ this.applyModelsUpdate({
1804
+ nextModels: [],
1805
+ reason: 'clear',
1806
+ removed: [...this.models],
1807
+ });
1808
+ }
1654
1809
  /** Fit view to all features on the layer. No-op if extent is empty. */
1655
1810
  centerOnAllModels(opts) {
1656
1811
  const current = this.getCenterOnAllModelsSource();
@@ -1714,19 +1869,10 @@ class VectorLayerBase {
1714
1869
  return this.registry.getFeature(id) != null;
1715
1870
  }
1716
1871
  getAllModels() {
1717
- const out = [];
1718
- this.registry.forEachId((id) => {
1719
- const model = this.registry.getModel(id);
1720
- if (model !== undefined) {
1721
- out.push(model);
1722
- }
1723
- });
1724
- return out;
1872
+ return [...this.models];
1725
1873
  }
1726
1874
  getAllModelIds() {
1727
- const out = [];
1728
- this.registry.forEachId((id) => out.push(id));
1729
- return out;
1875
+ return this.models.map((model) => this.descriptor.id(model));
1730
1876
  }
1731
1877
  setFeatureStates(ids, states) {
1732
1878
  const targetIds = Array.isArray(ids) ? ids : [ids];
@@ -1783,6 +1929,43 @@ class VectorLayerBase {
1783
1929
  }
1784
1930
  this.changeHandlers.forEach((handler) => handler(changes));
1785
1931
  }
1932
+ emitCollectionChange(event) {
1933
+ this.collectionHandlers.forEach((handler) => handler(event));
1934
+ }
1935
+ assertUniqueIds(models) {
1936
+ const ids = new Set();
1937
+ for (const model of models) {
1938
+ const id = this.descriptor.id(model);
1939
+ if (ids.has(id)) {
1940
+ this.throwDuplicateId(id);
1941
+ }
1942
+ ids.add(id);
1943
+ }
1944
+ }
1945
+ throwDuplicateId(id) {
1946
+ throw new DuplicateModelIdError(id, this.layerId);
1947
+ }
1948
+ applyModelsUpdate(args) {
1949
+ const prevSnapshot = [...this.models];
1950
+ const internalNext = [...args.nextModels];
1951
+ this.models = internalNext;
1952
+ this.setModelsInternal(this.models);
1953
+ const nextSnapshot = [...internalNext];
1954
+ this.emitCollectionChange({
1955
+ prev: prevSnapshot,
1956
+ next: nextSnapshot,
1957
+ reason: args.reason,
1958
+ added: args.added ? [...args.added] : undefined,
1959
+ removed: args.removed ? [...args.removed] : undefined,
1960
+ });
1961
+ }
1962
+ replaceModelSnapshot(id, model) {
1963
+ const index = this.models.findIndex((item) => this.descriptor.id(item) === id);
1964
+ if (index === -1) {
1965
+ return;
1966
+ }
1967
+ this.models[index] = model;
1968
+ }
1786
1969
  }
1787
1970
 
1788
1971
  class ClusteredVectorLayer extends VectorLayerBase {
@@ -2114,5 +2297,5 @@ class LayerManager {
2114
2297
  * Generated bundle index. Do not edit.
2115
2298
  */
2116
2299
 
2117
- export { LayerManager, LibComponent, LibService };
2300
+ export { DuplicateModelIdError, LayerManager, LibComponent, LibService };
2118
2301
  //# sourceMappingURL=aur-openlayers.mjs.map