@opengeoweb/store 20.0.1 → 20.1.0-nightly-20261017

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.
package/dist/index.esm.js CHANGED
@@ -3,9 +3,9 @@ import { isEqual, mergeWith, merge, isEmpty, compact } from 'lodash';
3
3
  import { webmapUtils, parseISO8601IntervalToDateInterval, LayerType, handleDateUtilsISOString, webmapTestSettings, WMLayer, getWMLayerById, WMInvalidDateValues, isProjectionSupported, queryWMSLayers } from '@opengeoweb/webmap';
4
4
  export { LayerType } from '@opengeoweb/webmap';
5
5
  import { dateUtils, PROJECTION, defaultDelay, useDebounce } from '@opengeoweb/shared';
6
- import { secondsPerPxFromCanvasWidth, defaultTimeSpan, defaultSecondsPerPx, defaultAnimationDelayAtStart, defaultTimeStep, MAX_ANIMATION_STEPS, AnimationLengthMode, defaultExactSelections, withDraggedRange, anchorInstantFor, roundWithTimeStep, resolveAnimationRange, isValidAnimationLength, defaultOffsetSelections, isAnchoredMode, getAnimationLengthFromRange, withModeSelections, getSpeedDelay, isWithinAnimationStepLimit } from '@opengeoweb/time-slider';
6
+ import { secondsPerPxFromCanvasWidth, defaultTimeSpan, defaultSecondsPerPx, defaultAnimationDelayAtStart, defaultTimeStep, MAX_ANIMATION_STEPS, AnimationLengthMode, defaultExactSelections, withDraggedRange, roundWithTimeStep, isValidAnimationLength, isWithinAnimationStepLimit, settingRange, isAnchoredMode, resolveAnimationRange, defaultOffsetSelections, getAnimationLengthFromRange, withModeSelections, getSpeedDelay } from '@opengeoweb/time-slider';
7
7
  import { produce } from 'immer';
8
- import { getLastEmptyFeatureIndex, getGeoJson, moveFeature, createInterSections, defaultLayers, fetchStacCatalogRoot, stacCatalogCollectionToLayerProps, fetchStacCatalogCollections, emptyGeoJSON, defaultIntersectionStyleProperties, addSelectionTypeToGeoJSON, getFeatureCollection } from '@opengeoweb/webmap-react';
8
+ import { getLastEmptyFeatureIndex, getGeoJson, moveFeature, createInterSections, defaultLayers, fetchStacCatalogRoot, defaultEdrStyles, normalizeEDRLabel, fetchEDRJson, stacCatalogCollectionToLayerProps, fetchStacCatalogCollections, emptyGeoJSON, defaultIntersectionStyleProperties, addSelectionTypeToGeoJSON, getFeatureCollection } from '@opengeoweb/webmap-react';
9
9
  export { defaultLayers } from '@opengeoweb/webmap-react';
10
10
  import { v4 } from 'uuid';
11
11
  import React, { useEffect, useRef, useCallback } from 'react';
@@ -351,6 +351,9 @@ function _setPrototypeOf(t, e) {
351
351
  function _slicedToArray(r, e) {
352
352
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
353
353
  }
354
+ function _toArray(r) {
355
+ return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest();
356
+ }
354
357
  function _toConsumableArray(r) {
355
358
  return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
356
359
  }
@@ -1069,6 +1072,25 @@ var generateAnimationList = function generateAnimationList(unixAnimationStart, u
1069
1072
  });
1070
1073
  return animationList;
1071
1074
  };
1075
+ /**
1076
+ * Returns the adjacent time (unix seconds) in a comma separated list of time values,
1077
+ * or undefined when the values are empty, contain ISO8601 intervals or there is no adjacent time.
1078
+ */
1079
+ var getAdjacentTimeValue = function getAdjacentTimeValue(timeValues, currentUnix, isForwardStep) {
1080
+ if (!timeValues || timeValues.includes('/')) {
1081
+ return undefined;
1082
+ }
1083
+ var unixTimes = timeValues.split(',').map(function (timeValue) {
1084
+ return dateUtils.unix(dateUtils.utc(timeValue.trim()));
1085
+ }).filter(Number.isFinite).sort(function (first, second) {
1086
+ return first - second;
1087
+ });
1088
+ return isForwardStep ? unixTimes.find(function (time) {
1089
+ return time > currentUnix;
1090
+ }) : unixTimes.filter(function (time) {
1091
+ return time < currentUnix;
1092
+ }).pop();
1093
+ };
1072
1094
  /**
1073
1095
  * Parses the time dimension values string to an array of ISO8601 intervals
1074
1096
  * @param timeInterval
@@ -1114,6 +1136,7 @@ var utils$2 = /*#__PURE__*/Object.freeze({
1114
1136
  dateFormat: dateFormat,
1115
1137
  findMapIdFromLayerId: findMapIdFromLayerId,
1116
1138
  generateAnimationList: generateAnimationList,
1139
+ getAdjacentTimeValue: getAdjacentTimeValue,
1117
1140
  getAnimationDuration: getAnimationDuration,
1118
1141
  getDraftMapById: getDraftMapById,
1119
1142
  getSpeedFactor: getSpeedFactor,
@@ -1298,6 +1321,9 @@ var trimTrailingSlashes = function trimTrailingSlashes(url) {
1298
1321
  var getSTACServiceRootUrl = function getSTACServiceRootUrl(serviceUrl) {
1299
1322
  return trimTrailingSlashes(serviceUrl).replace(/\/collections\/[^/]+$/, '');
1300
1323
  };
1324
+ var getEDRServiceRootUrl = function getEDRServiceRootUrl(serviceUrl) {
1325
+ return trimTrailingSlashes(serviceUrl).replace(/\/collections\/[^/]+$/, '');
1326
+ };
1301
1327
  var getTrailingSlashVariant = function getTrailingSlashVariant(url) {
1302
1328
  return url.endsWith('/') ? url.slice(0, -1) : "".concat(url, "/");
1303
1329
  };
@@ -1561,6 +1587,7 @@ var utils$1 = /*#__PURE__*/Object.freeze({
1561
1587
  filterCurrentValueFromDimensions: filterCurrentValueFromDimensions,
1562
1588
  filterNonTimeDimensions: filterNonTimeDimensions,
1563
1589
  generateFeatureId: generateFeatureId,
1590
+ getEDRServiceRootUrl: getEDRServiceRootUrl,
1564
1591
  getFeatureSelectionKey: getFeatureSelectionKey,
1565
1592
  getSTACServiceRootUrl: getSTACServiceRootUrl,
1566
1593
  getSelectedFeatureIndexByIds: getSelectedFeatureIndexByIds,
@@ -2454,7 +2481,11 @@ var exactSelectionsFrom = function exactSelectionsFrom(animationLength, animatio
2454
2481
  };
2455
2482
  /** A moved edge edits the selected mode; a map without a mode gains an exact one. */
2456
2483
  var animationLengthForMovedEdge = function animationLengthForMovedEdge(map, movedEdge, referenceTime) {
2457
- return map.animationLength ? withDraggedRange(map.animationLength, movedEdge, anchorInstantFor(map.animationLength, referenceTime)) : {
2484
+ var _map$timeStep;
2485
+ return map.animationLength ? withDraggedRange(map.animationLength, movedEdge, {
2486
+ referenceTime: referenceTime,
2487
+ timeStep: (_map$timeStep = map.timeStep) !== null && _map$timeStep !== void 0 ? _map$timeStep : defaultTimeStep
2488
+ }) : {
2458
2489
  mode: AnimationLengthMode.Exact,
2459
2490
  exact: exactSelectionsFrom(map.animationLength, map.animationStartTime, map.animationEndTime)
2460
2491
  };
@@ -3179,6 +3210,7 @@ var slice$6 = createSlice({
3179
3210
  draft.byId[mapId].baseLayers = [];
3180
3211
  draft.byId[mapId].mapLayers = [];
3181
3212
  draft.byId[mapId].overLayers = [];
3213
+ draft.byId[mapId].featureLayers = [];
3182
3214
  draft.byId[mapId].isAutoUpdating = false;
3183
3215
  draft.byId[mapId].isAnimating = false;
3184
3216
  draft.byId[mapId].isTimeSliderVisible = true;
@@ -5188,6 +5220,15 @@ var useSyncgroupTimeState = function useSyncgroupTimeState(panelId) {
5188
5220
  var layerStore = function layerStore(store) {
5189
5221
  return store === null || store === void 0 ? void 0 : store.layers;
5190
5222
  };
5223
+ var getCollectionServiceRootUrl = function getCollectionServiceRootUrl(layerType, serviceUrl) {
5224
+ if (layerType === LayerType.edrFeatureLayer) {
5225
+ return getEDRServiceRootUrl(serviceUrl);
5226
+ }
5227
+ if (layerType === LayerType.stacGeoTIFFLayer) {
5228
+ return getSTACServiceRootUrl(serviceUrl);
5229
+ }
5230
+ return undefined;
5231
+ };
5191
5232
  /**
5192
5233
  * Gets a layer from the layers part of the store by its Id
5193
5234
  *
@@ -5460,7 +5501,8 @@ var getLayerService = createSelector(getLayerById, function (layer) {
5460
5501
  var getLayerServiceName = createSelector(function (store) {
5461
5502
  return store;
5462
5503
  }, getLayerById, getLayerService, function (store, layer, service) {
5463
- var layerService = getServiceByUrl(store, service) || ((layer === null || layer === void 0 ? void 0 : layer.layerType) === LayerType.stacGeoTIFFLayer ? getServiceByUrl(store, getSTACServiceRootUrl(service)) || getServiceByUrl(store, getTrailingSlashVariant(getSTACServiceRootUrl(service))) : undefined);
5504
+ var serviceRootUrl = getCollectionServiceRootUrl(layer === null || layer === void 0 ? void 0 : layer.layerType, service);
5505
+ var layerService = getServiceByUrl(store, service) || (serviceRootUrl ? getServiceByUrl(store, serviceRootUrl) || getServiceByUrl(store, getTrailingSlashVariant(serviceRootUrl)) : undefined);
5464
5506
  return layerService !== null && layerService !== void 0 && layerService.name ? layerService === null || layerService === void 0 ? void 0 : layerService.name : '';
5465
5507
  }, selectorMemoizationOptions);
5466
5508
  /**
@@ -5718,8 +5760,9 @@ var getIsLayerMissing = createSelector(function (store) {
5718
5760
  if (type === LayerType.featureLayer || type === LayerType.stacGeoTIFFLayer) {
5719
5761
  return false;
5720
5762
  }
5721
- var layer = getLayerFromService(store, service, name);
5722
- return !layer || status === LayerStatus.error;
5763
+ var serviceRootUrl = getCollectionServiceRootUrl(type, service);
5764
+ var serviceLayer = getLayerFromService(store, service, name) || (serviceRootUrl ? getLayerFromService(store, serviceRootUrl, name) || getLayerFromService(store, getTrailingSlashVariant(serviceRootUrl), name) : undefined);
5765
+ return !serviceLayer || status === LayerStatus.error;
5723
5766
  }, selectorMemoizationOptions);
5724
5767
  var getIsLayerSelectable = createSelector(getLayerById, function (layer) {
5725
5768
  return Boolean(layer === null || layer === void 0 ? void 0 : layer.isSelectable);
@@ -7478,6 +7521,15 @@ var getAnimationRange = createSelector(getLayersById, getAutoTimeStepLayerId, ge
7478
7521
  animationEndTime: animationEndTime
7479
7522
  };
7480
7523
  }, selectorMemoizationOptions);
7524
+ var getAnimationAnchorInputs = createSelector(getLayersById, getAutoTimeStepLayerId, getMapTimeStep, function (layers, autoTimeStepLayerId, timeStep) {
7525
+ var _layers$autoTimeStepL3;
7526
+ return {
7527
+ referenceTime: autoTimeStepLayerId && (layers === null || layers === void 0 || (_layers$autoTimeStepL3 = layers[autoTimeStepLayerId]) === null || _layers$autoTimeStepL3 === void 0 || (_layers$autoTimeStepL3 = _layers$autoTimeStepL3.dimensions) === null || _layers$autoTimeStepL3 === void 0 || (_layers$autoTimeStepL3 = _layers$autoTimeStepL3.find(function (dimension) {
7528
+ return dimension.name === 'reference_time';
7529
+ })) === null || _layers$autoTimeStepL3 === void 0 ? void 0 : _layers$autoTimeStepL3.currentValue) || undefined,
7530
+ timeStep: timeStep
7531
+ };
7532
+ }, selectorMemoizationOptions);
7481
7533
  /**
7482
7534
  * Gets intialViewMapPreset from webmap state
7483
7535
  *
@@ -7527,6 +7579,7 @@ var selectors$1 = /*#__PURE__*/Object.freeze({
7527
7579
  getAllMapIds: getAllMapIds,
7528
7580
  getAllMapsByIds: getAllMapsByIds,
7529
7581
  getAllUniqueDimensions: getAllUniqueDimensions,
7582
+ getAnimationAnchorInputs: getAnimationAnchorInputs,
7530
7583
  getAnimationEndTime: getAnimationEndTime,
7531
7584
  getAnimationLength: getAnimationLength,
7532
7585
  getAnimationList: getAnimationList,
@@ -8110,7 +8163,7 @@ genericListener.startListening({
8110
8163
  payload = _ref2.payload, type = _ref2.type;
8111
8164
  listenerApi.cancelActiveListeners();
8112
8165
  sourceId = payload.mapId;
8113
- if (!(type === mapActions.setAnimationLength.type && payload.skipSync)) {
8166
+ if (!((type === mapActions.setAnimationLength.type || type === mapActions.refreshAnimationRange.type) && payload.skipSync)) {
8114
8167
  _context2.n = 1;
8115
8168
  break;
8116
8169
  }
@@ -8397,6 +8450,64 @@ genericListener.startListening({
8397
8450
  }()
8398
8451
  });
8399
8452
 
8453
+ var ANIMATION_CLOCK_INTERVAL = 1000 * 60;
8454
+ /** Auto is left out: its selector derives the range from the leading layer. */
8455
+ var resolveMapAnimationRange = function resolveMapAnimationRange(state, mapId) {
8456
+ var animationLength = getAnimationLength(state, mapId);
8457
+ if (!animationLength || animationLength.mode === AnimationLengthMode.Auto) {
8458
+ return undefined;
8459
+ }
8460
+ var anchorInputs = getAnimationAnchorInputs(state, mapId);
8461
+ var isUsableRange = isValidAnimationLength(animationLength, anchorInputs) && isWithinAnimationStepLimit(animationLength, getMapTimeStep(state, mapId), anchorInputs);
8462
+ return isUsableRange ? settingRange(animationLength, anchorInputs) : undefined;
8463
+ };
8464
+ var isSameInstant = function isSameInstant(time, storedTime) {
8465
+ return !!storedTime && dateUtils.utc(time).getTime() === dateUtils.utc(storedTime).getTime();
8466
+ };
8467
+ var isStoredRange = function isStoredRange(state, mapId, _ref) {
8468
+ var animationStartTime = _ref.animationStartTime,
8469
+ animationEndTime = _ref.animationEndTime;
8470
+ return isSameInstant(animationStartTime, getAnimationStartTime(state, mapId)) && isSameInstant(animationEndTime, getAnimationEndTime(state, mapId));
8471
+ };
8472
+ var reconcileAnimationRange = function reconcileAnimationRange(mapId, listenerApi) {
8473
+ var skipSync = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
8474
+ var range = resolveMapAnimationRange(listenerApi.getState(), mapId);
8475
+ if (range && !isStoredRange(listenerApi.getState(), mapId, range)) {
8476
+ listenerApi.dispatch(mapActions.refreshAnimationRange(_objectSpread2(_objectSpread2({
8477
+ mapId: mapId
8478
+ }, range), skipSync && {
8479
+ skipSync: skipSync
8480
+ })));
8481
+ }
8482
+ };
8483
+ var mapIdOfLeadingLayer = function mapIdOfLeadingLayer(state, layerId) {
8484
+ var _layerSelectors$getLa;
8485
+ var mapId = (_layerSelectors$getLa = getLayerById(state, layerId)) === null || _layerSelectors$getLa === void 0 ? void 0 : _layerSelectors$getLa.mapId;
8486
+ return mapId && getAutoTimeStepLayerId(state, mapId) === layerId ? mapId : undefined;
8487
+ };
8488
+ var mapIdToReconcile = function mapIdToReconcile(action, state) {
8489
+ if (layerActions.onUpdateLayerInformation.match(action)) {
8490
+ var _action$payload$layer;
8491
+ return mapIdOfLeadingLayer(state, (_action$payload$layer = action.payload.layerDimensions) === null || _action$payload$layer === void 0 ? void 0 : _action$payload$layer.layerId);
8492
+ }
8493
+ if (layerActions.layerChangeDimension.match(action)) {
8494
+ return action.payload.dimension.name === 'reference_time' ? mapIdOfLeadingLayer(state, action.payload.layerId) : undefined;
8495
+ }
8496
+ return action.payload.mapId;
8497
+ };
8498
+ var isSyncSkippedBy = function isSyncSkippedBy(action) {
8499
+ return mapActions.setAnimationLength.match(action) && !!action.payload.skipSync;
8500
+ };
8501
+ var hasAnchoredAnimationLength = function hasAnchoredAnimationLength(state, mapId) {
8502
+ var _getAnimationLength;
8503
+ return isAnchoredMode((_getAnimationLength = getAnimationLength(state, mapId)) === null || _getAnimationLength === void 0 ? void 0 : _getAnimationLength.mode);
8504
+ };
8505
+ var endsAnimationClockOf = function endsAnimationClockOf(mapId) {
8506
+ return function (action) {
8507
+ return (mapActions.setAnimationLength.match(action) || mapActions.unregisterMap.match(action)) && action.payload.mapId === mapId;
8508
+ };
8509
+ };
8510
+
8400
8511
  /* A map with all the timerIds and their current step */
8401
8512
  var stepMap = new Map();
8402
8513
  /* A map with a list of timers and their dwell */
@@ -8679,6 +8790,7 @@ mapListener.startListening({
8679
8790
  effect: function effect(_ref2, listenerApi) {
8680
8791
  var payload = _ref2.payload;
8681
8792
  try {
8793
+ var _state$layers;
8682
8794
  var layerDimensions = payload.layerDimensions;
8683
8795
  if (!layerDimensions) {
8684
8796
  return;
@@ -8692,21 +8804,10 @@ mapListener.startListening({
8692
8804
  var newTimeDimension = dimensions.find(function (dimension) {
8693
8805
  return dimension.name === 'time';
8694
8806
  });
8695
- var hasReferenceTimeDimension = dimensions.some(function (dimension) {
8696
- return dimension.name === 'reference_time';
8697
- });
8698
8807
  var mapId = layer.mapId;
8699
8808
  if (!mapId) {
8700
8809
  return;
8701
8810
  }
8702
- if (hasReferenceTimeDimension) {
8703
- var _layerSelectors$getLa, _layerSelectors$getLa2;
8704
- var previousReferenceTime = (_layerSelectors$getLa = getLayerDimension(listenerApi.getOriginalState(), layerId, 'reference_time')) === null || _layerSelectors$getLa === void 0 ? void 0 : _layerSelectors$getLa.currentValue;
8705
- var referenceTime = (_layerSelectors$getLa2 = getLayerDimension(listenerApi.getState(), layerId, 'reference_time')) === null || _layerSelectors$getLa2 === void 0 ? void 0 : _layerSelectors$getLa2.currentValue;
8706
- if (referenceTime && referenceTime !== previousReferenceTime) {
8707
- updateReferenceTimeAnimationRange(mapId, layerId, referenceTime, listenerApi);
8708
- }
8709
- }
8710
8811
  listenerApi.dispatch(mapActions.mapUpdateAllMapDimensions({
8711
8812
  mapId: mapId,
8712
8813
  dimensions: getMapDimensionsFromLayers(listenerApi.getState(), mapId),
@@ -8765,6 +8866,37 @@ mapListener.startListening({
8765
8866
  }
8766
8867
  updateAnimation(mapId, incomingMaxTime, listenerApi);
8767
8868
  }
8869
+ var state = listenerApi.getState();
8870
+ // Metadata updates affect all layers with the same name and service;
8871
+ // resolve each layer's time against its own map's selected time.
8872
+ Object.values(((_state$layers = state.layers) === null || _state$layers === void 0 ? void 0 : _state$layers.byId) || {}).forEach(function (updatedLayer) {
8873
+ var _updatedLayer$dimensi;
8874
+ if (!(updatedLayer !== null && updatedLayer !== void 0 && updatedLayer.id) || !updatedLayer.mapId || updatedLayer.name !== layer.name || updatedLayer.service !== layer.service) {
8875
+ return;
8876
+ }
8877
+ var wmLayer = webmapUtils.getWMLayerById(updatedLayer.id);
8878
+ var wmTimeDimension = wmLayer === null || wmLayer === void 0 ? void 0 : wmLayer.getDimension('time');
8879
+ var mapTime = getMapDimension(state, updatedLayer.mapId, 'time');
8880
+ var timeDimension = (_updatedLayer$dimensi = updatedLayer.dimensions) === null || _updatedLayer$dimensi === void 0 ? void 0 : _updatedLayer$dimensi.find(function (dimension) {
8881
+ return dimension.name === 'time';
8882
+ });
8883
+ if ((wmLayer === null || wmLayer === void 0 ? void 0 : wmLayer.layerType) !== LayerType.mapLayer || !(wmTimeDimension !== null && wmTimeDimension !== void 0 && wmTimeDimension.linked) || !(mapTime !== null && mapTime !== void 0 && mapTime.currentValue) || !timeDimension) {
8884
+ return;
8885
+ }
8886
+ var currentValue = wmTimeDimension.getClosestValue(mapTime.currentValue, true);
8887
+ if (WMInvalidDateValues.has(currentValue) || currentValue === timeDimension.currentValue) {
8888
+ return;
8889
+ }
8890
+ listenerApi.dispatch(layerActions.layerSetDimensions({
8891
+ layerId: updatedLayer.id,
8892
+ origin: LayerActionOrigin.updateLayerInformationListener,
8893
+ dimensions: updatedLayer.dimensions.map(function (dimension) {
8894
+ return dimension.name === 'time' ? _objectSpread2(_objectSpread2({}, dimension), {}, {
8895
+ currentValue: currentValue
8896
+ }) : _objectSpread2({}, dimension);
8897
+ })
8898
+ }));
8899
+ });
8768
8900
  } catch (error) {
8769
8901
  console.warn(error);
8770
8902
  }
@@ -8810,17 +8942,38 @@ var updateAnimation = function updateAnimation(mapId, maxValue, listenerApi) {
8810
8942
  }));
8811
8943
  });
8812
8944
  };
8945
+ // Returns the maps among the given sync targets, in the order the sync groups dialog lists them
8946
+ var getMapIdsInSyncListOrder = function getMapIdsInSyncListOrder(state, targetIds) {
8947
+ var _getSynchronizationGr, _getSynchronizationGr2;
8948
+ var sourceIds = Object.keys((_getSynchronizationGr = (_getSynchronizationGr2 = getSynchronizationGroupState(state)) === null || _getSynchronizationGr2 === void 0 ? void 0 : _getSynchronizationGr2.sources.byId) !== null && _getSynchronizationGr !== void 0 ? _getSynchronizationGr : {});
8949
+ var orderedTargetIds = [].concat(_toConsumableArray(sourceIds.filter(function (sourceId) {
8950
+ return targetIds.includes(sourceId);
8951
+ })), _toConsumableArray(targetIds.filter(function (targetId) {
8952
+ return !sourceIds.includes(targetId);
8953
+ })));
8954
+ return orderedTargetIds.filter(function (targetId) {
8955
+ return getMapById(state, targetId);
8956
+ });
8957
+ };
8958
+ var isHigherSyncedMapAutoUpdating = function isHigherSyncedMapAutoUpdating(state, mapId) {
8959
+ var syncedMapIds = getMapIdsInSyncListOrder(state, getSyncedMapIdsForTimeslider(state));
8960
+ var mapIndex = syncedMapIds.indexOf(mapId);
8961
+ return syncedMapIds.slice(0, Math.max(mapIndex, 0)).some(function (syncedMapId) {
8962
+ return isAutoUpdating(state, syncedMapId);
8963
+ });
8964
+ };
8813
8965
  mapListener.startListening({
8814
8966
  actionCreator: mapActions.toggleAutoUpdate,
8815
8967
  effect: function () {
8816
8968
  var _effect = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(_ref3, listenerApi) {
8817
- var payload, shouldAutoUpdate, mapId, autoUpdateLayerId, timeDimension, syncedMapIds, payloads;
8969
+ var payload, shouldAutoUpdate, mapId, origin, syncedMapIds, autoUpdateLayerId, timeDimension, payloads;
8818
8970
  return _regenerator().w(function (_context) {
8819
8971
  while (1) switch (_context.n) {
8820
8972
  case 0:
8821
8973
  payload = _ref3.payload;
8822
8974
  listenerApi.cancelActiveListeners();
8823
- shouldAutoUpdate = payload.shouldAutoUpdate, mapId = payload.mapId;
8975
+ // origin is passed on so that the presets of all affected maps get marked as changed
8976
+ shouldAutoUpdate = payload.shouldAutoUpdate, mapId = payload.mapId, origin = payload.origin;
8824
8977
  if (shouldAutoUpdate) {
8825
8978
  _context.n = 1;
8826
8979
  break;
@@ -8828,9 +8981,9 @@ mapListener.startListening({
8828
8981
  return _context.a(2);
8829
8982
  case 1:
8830
8983
  try {
8984
+ syncedMapIds = getSyncedMapIdsForTimeslider(listenerApi.getState());
8831
8985
  autoUpdateLayerId = getAutoUpdateLayerId(listenerApi.getState(), mapId);
8832
- timeDimension = getLayerTimeDimension(listenerApi.getState(), autoUpdateLayerId);
8833
- syncedMapIds = getSyncedMapIdsForTimeslider(listenerApi.getState()); // go to end of active layer
8986
+ timeDimension = getLayerTimeDimension(listenerApi.getState(), autoUpdateLayerId); // go to end of active layer
8834
8987
  if (timeDimension !== null && timeDimension !== void 0 && timeDimension.maxValue && autoUpdateLayerId) {
8835
8988
  listenerApi.dispatch(layerActions.layerChangeDimension({
8836
8989
  layerId: autoUpdateLayerId,
@@ -8856,10 +9009,11 @@ mapListener.startListening({
8856
9009
  }
8857
9010
  // Toggle autoupdate off for synced timesliders
8858
9011
  payloads = syncedMapIds.reduce(function (syncedMapIdList, syncedMapId) {
8859
- if (syncedMapId !== mapId) {
9012
+ if (syncedMapId !== mapId && isAutoUpdating(listenerApi.getState(), syncedMapId)) {
8860
9013
  return syncedMapIdList.concat({
8861
9014
  mapId: syncedMapId,
8862
- shouldAutoUpdate: false
9015
+ shouldAutoUpdate: false,
9016
+ origin: origin
8863
9017
  });
8864
9018
  }
8865
9019
  return syncedMapIdList;
@@ -8884,9 +9038,35 @@ mapListener.startListening({
8884
9038
  }()
8885
9039
  });
8886
9040
  mapListener.startListening({
8887
- actionCreator: mapActions.mapStartAnimation,
9041
+ actionCreator: genericActions.syncGroupAddTarget,
9042
+ // When maps that auto update are synced, only the top one in the sync list keeps auto update
8888
9043
  effect: function effect(_ref4, listenerApi) {
8889
9044
  var payload = _ref4.payload;
9045
+ var state = listenerApi.getState();
9046
+ var group = getSynchronizationGroup(state, payload.groupId);
9047
+ if ((group === null || group === void 0 ? void 0 : group.type) !== SYNCGROUPS_TYPE_SETTIME) {
9048
+ return;
9049
+ }
9050
+ var _getMapIdsInSyncListO = getMapIdsInSyncListOrder(state, group.targets.allIds).filter(function (syncedMapId) {
9051
+ return isAutoUpdating(state, syncedMapId);
9052
+ }),
9053
+ _getMapIdsInSyncListO2 = _toArray(_getMapIdsInSyncListO),
9054
+ lowerAutoUpdatingMapIds = _arrayLikeToArray(_getMapIdsInSyncListO2).slice(1);
9055
+ // mark the presets of affected maps as changed when the user synced the maps
9056
+ var origin = payload.origin === 'user' ? MapActionOrigin.map : undefined;
9057
+ lowerAutoUpdatingMapIds.forEach(function (lowerMapId) {
9058
+ return listenerApi.dispatch(mapActions.toggleAutoUpdate({
9059
+ mapId: lowerMapId,
9060
+ shouldAutoUpdate: false,
9061
+ origin: origin
9062
+ }));
9063
+ });
9064
+ }
9065
+ });
9066
+ mapListener.startListening({
9067
+ actionCreator: mapActions.mapStartAnimation,
9068
+ effect: function effect(_ref5, listenerApi) {
9069
+ var payload = _ref5.payload;
8890
9070
  var mapId = payload.mapId,
8891
9071
  initialTime = payload.initialTime;
8892
9072
  // Check if the mapId is part of a syncgroup
@@ -8915,8 +9095,8 @@ mapListener.startListening({
8915
9095
  });
8916
9096
  mapListener.startListening({
8917
9097
  actionCreator: mapActions.mapStopAnimation,
8918
- effect: function effect(_ref5, listenerApi) {
8919
- var mapId = _ref5.payload.mapId;
9098
+ effect: function effect(_ref6, listenerApi) {
9099
+ var mapId = _ref6.payload.mapId;
8920
9100
  // Check if the mapId is part of a syncgroup
8921
9101
  var syncedMapIds = getSyncedMapIdsForTimeslider(listenerApi.getState());
8922
9102
  var isSyncedMap = syncedMapIds.includes(mapId);
@@ -8959,12 +9139,12 @@ var handleBaseLayers = function handleBaseLayers(mapId, baseLayers, listenerApi)
8959
9139
  mapListener.startListening({
8960
9140
  actionCreator: mapActions.setMapPreset,
8961
9141
  effect: function () {
8962
- var _effect2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(_ref6, listenerApi) {
8963
- var payload, mapId, initialProps, mapPreset, _mapPreset$dimensions, layers, activeLayerId, autoTimeStepLayerId, autoUpdateLayerId, proj, shouldAutoUpdate, shouldAnimate, animationPayload, toggleTimestepAuto, showTimeSlider, displayMapPin, shouldShowZoomControls, shouldShowLegend, legendPosition, legendSize, shouldShowDockedLayerManager, shouldShowDataExplorer, dockedLayerManagerSize, dockedLayerManagerPosition, dockedLayerManagerDimensions, timeSliderSpan, toggleTimeSpanAuto, defaultOverlayer, isClockVisible, isClockOptionsMenuVisible, clockPosition, clockSize, initialZoomToLayerId, _filterLayers, mapLayers, baseLayers, overLayers, pendingInitialZoomToLayerId, _newLayerIds$layers$f, _newLayerIds$layers$f2, autoTimeStepLayerIdNew, autoUpdateLayerIdNew, onlyActiveLayerIdIsSet, newLayerIds, newAutoTimeStepLayerId, newAutoUpdateLayerId, _newLayerIds$layers$i, initialZoomLayerIndex, customLayers, customBaseLayer, customOverLayer, baseLayersWithDefaultLayer, overLayersWithDefaultLayer, allBaseLayers, _overlayersFromStore$, overlayersFromStore, foundOverlayerId, checkIsprojectionSupported, layerId, animationDuration, animationLengthSetting, animationEndTime, shouldEndtimeOverride, interval, timeAlreadySet, mode, endTimeFromPreset, endTime, startTime, hasNoAnimationDetails, defaultAnimationLengthSetting, effectiveAnimationLengthSetting, animationLength, animationStartTime, _autoTimeStepLayerId, layerRefTimeDimension, referenceTimeFromLayer, anchorTime, resolvedRange, shouldOpenLegend, dockedLayerManagerType, _t;
9142
+ var _effect2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(_ref7, listenerApi) {
9143
+ var payload, mapId, initialProps, mapPreset, _mapPreset$dimensions, layers, activeLayerId, autoTimeStepLayerId, autoUpdateLayerId, proj, shouldAutoUpdate, shouldAnimate, animationPayload, toggleTimestepAuto, showTimeSlider, displayMapPin, shouldShowZoomControls, shouldShowLegend, legendPosition, legendSize, shouldShowDockedLayerManager, shouldShowDataExplorer, dockedLayerManagerSize, dockedLayerManagerPosition, dockedLayerManagerDimensions, timeSliderSpan, toggleTimeSpanAuto, defaultOverlayer, isClockVisible, isClockOptionsMenuVisible, clockPosition, clockSize, initialZoomToLayerId, _filterLayers, mapLayers, baseLayers, overLayers, pendingInitialZoomToLayerId, _newLayerIds$layers$f, _newLayerIds$layers$f2, autoTimeStepLayerIdNew, autoUpdateLayerIdNew, onlyActiveLayerIdIsSet, newLayerIds, newAutoTimeStepLayerId, newAutoUpdateLayerId, _newLayerIds$layers$i, initialZoomLayerIndex, customLayers, customBaseLayer, customOverLayer, baseLayersWithDefaultLayer, overLayersWithDefaultLayer, allBaseLayers, _overlayersFromStore$, overlayersFromStore, foundOverlayerId, checkIsprojectionSupported, layerId, animationDuration, animationLengthSetting, animationEndTime, shouldEndtimeOverride, interval, timeAlreadySet, mode, endTimeFromPreset, endTime, startTime, hasNoAnimationDetails, defaultAnimationLengthSetting, effectiveAnimationLengthSetting, animationLength, animationStartTime, anchorInputs, resolvedRange, shouldOpenLegend, dockedLayerManagerType, _t;
8964
9144
  return _regenerator().w(function (_context2) {
8965
9145
  while (1) switch (_context2.p = _context2.n) {
8966
9146
  case 0:
8967
- payload = _ref6.payload;
9147
+ payload = _ref7.payload;
8968
9148
  _context2.p = 1;
8969
9149
  mapId = payload.mapId, initialProps = payload.initialProps;
8970
9150
  mapPreset = initialProps.mapPreset;
@@ -9081,10 +9261,10 @@ mapListener.startListening({
9081
9261
  }));
9082
9262
  }
9083
9263
  if (shouldAutoUpdate !== undefined && !animationEndTime) {
9084
- // auto update
9264
+ // auto update, unless a synced map higher in the sync list already auto updates
9085
9265
  listenerApi.dispatch(mapActions.toggleAutoUpdate({
9086
9266
  mapId: mapId,
9087
- shouldAutoUpdate: shouldAutoUpdate
9267
+ shouldAutoUpdate: shouldAutoUpdate && !isHigherSyncedMapAutoUpdating(listenerApi.getState(), mapId)
9088
9268
  }));
9089
9269
  }
9090
9270
  if (showTimeSlider !== undefined) {
@@ -9261,11 +9441,8 @@ mapListener.startListening({
9261
9441
  }));
9262
9442
  }
9263
9443
  } else {
9264
- _autoTimeStepLayerId = getAutoTimeStepLayerId(listenerApi.getState(), mapId);
9265
- layerRefTimeDimension = getLayerDimension(listenerApi.getState(), _autoTimeStepLayerId, 'reference_time');
9266
- referenceTimeFromLayer = (layerRefTimeDimension === null || layerRefTimeDimension === void 0 ? void 0 : layerRefTimeDimension.currentValue) || undefined;
9267
- anchorTime = dateUtils.utc(referenceTimeFromLayer);
9268
- resolvedRange = isAnchoredMode(animationLength.mode) && isValidAnimationLength(animationLength, anchorTime) ? resolveAnimationRange(animationLength, anchorTime) : undefined;
9444
+ anchorInputs = getAnimationAnchorInputs(listenerApi.getState(), mapId);
9445
+ resolvedRange = isAnchoredMode(animationLength.mode) && isValidAnimationLength(animationLength, anchorInputs) ? resolveAnimationRange(animationLength, anchorInputs) : undefined;
9269
9446
  listenerApi.dispatch(mapActions.setAnimationLength(_objectSpread2(_objectSpread2({
9270
9447
  mapId: mapId,
9271
9448
  animationLength: animationLength
@@ -9380,55 +9557,35 @@ mapListener.startListening({
9380
9557
  return effect;
9381
9558
  }()
9382
9559
  });
9383
- /**
9384
- * Re-resolving on a short interval keeps a range that follows the clock correct without
9385
- * tracking what it depends on: Now slides every tick, a recurring period only rolls at
9386
- * midnight UTC, and a tick that resolves an unchanged range leaves the state untouched.
9387
- */
9388
- var ANIMATION_RANGE_REFRESH_INTERVAL = 1000 * 60 * 5;
9389
- /* Newest loop per map wins; older loops see a stale token and exit. */
9390
- var animationRangeRefreshTokens = new Map();
9391
9560
  mapListener.startListening({
9392
9561
  actionCreator: mapActions.setAnimationLength,
9393
9562
  effect: function () {
9394
- var _effect3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(_ref7, listenerApi) {
9395
- var payload, mapId, refreshToken, isNewestRefreshLoop, getRefreshableAnimationLength, animationLength;
9563
+ var _effect3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(_ref8, listenerApi) {
9564
+ var payload, mapId, endingAction;
9396
9565
  return _regenerator().w(function (_context3) {
9397
9566
  while (1) switch (_context3.n) {
9398
9567
  case 0:
9399
- payload = _ref7.payload;
9568
+ payload = _ref8.payload;
9400
9569
  mapId = payload.mapId;
9401
9570
  if (isAnimating(listenerApi.getState(), mapId)) {
9402
9571
  setStep(mapId, -1);
9403
9572
  }
9404
- refreshToken = Symbol(mapId);
9405
- animationRangeRefreshTokens.set(mapId, refreshToken);
9406
- isNewestRefreshLoop = function isNewestRefreshLoop() {
9407
- return animationRangeRefreshTokens.get(mapId) === refreshToken;
9408
- };
9409
- getRefreshableAnimationLength = function getRefreshableAnimationLength() {
9410
- var animationLength = getAnimationLength(listenerApi.getState(), mapId);
9411
- var timeStep = getMapTimeStep(listenerApi.getState(), mapId);
9412
- return isAnchoredMode(animationLength === null || animationLength === void 0 ? void 0 : animationLength.mode) && animationLength && isValidAnimationLength(animationLength) && isWithinAnimationStepLimit(animationLength, timeStep) ? animationLength : undefined;
9413
- };
9414
9573
  case 1:
9415
- if (!(isNewestRefreshLoop() && getRefreshableAnimationLength())) {
9574
+ if (!hasAnchoredAnimationLength(listenerApi.getState(), mapId)) {
9416
9575
  _context3.n = 4;
9417
9576
  break;
9418
9577
  }
9419
9578
  _context3.n = 2;
9420
- return listenerApi.delay(ANIMATION_RANGE_REFRESH_INTERVAL);
9579
+ return listenerApi.take(endsAnimationClockOf(mapId), ANIMATION_CLOCK_INTERVAL);
9421
9580
  case 2:
9422
- animationLength = getRefreshableAnimationLength();
9423
- if (!(!isNewestRefreshLoop() || !animationLength)) {
9581
+ endingAction = _context3.v;
9582
+ if (!endingAction) {
9424
9583
  _context3.n = 3;
9425
9584
  break;
9426
9585
  }
9427
9586
  return _context3.a(2);
9428
9587
  case 3:
9429
- listenerApi.dispatch(mapActions.refreshAnimationRange(_objectSpread2({
9430
- mapId: mapId
9431
- }, resolveAnimationRange(animationLength))));
9588
+ reconcileAnimationRange(mapId, listenerApi);
9432
9589
  _context3.n = 1;
9433
9590
  break;
9434
9591
  case 4:
@@ -9444,31 +9601,30 @@ mapListener.startListening({
9444
9601
  });
9445
9602
  mapListener.startListening({
9446
9603
  actionCreator: mapActions.setAnimationStartTime,
9447
- effect: function effect(_ref8, listenerApi) {
9448
- var payload = _ref8.payload;
9604
+ effect: function effect(_ref9, listenerApi) {
9605
+ var payload = _ref9.payload;
9449
9606
  preserveAnimationStep(payload.mapId, listenerApi);
9450
9607
  }
9451
9608
  });
9452
9609
  mapListener.startListening({
9453
9610
  actionCreator: mapActions.setAnimationEndTime,
9454
- effect: function effect(_ref9, listenerApi) {
9455
- var payload = _ref9.payload;
9611
+ effect: function effect(_ref0, listenerApi) {
9612
+ var payload = _ref0.payload;
9456
9613
  preserveAnimationStep(payload.mapId, listenerApi);
9457
9614
  }
9458
9615
  });
9459
9616
  mapListener.startListening({
9460
9617
  actionCreator: mapActions.refreshAnimationRange,
9461
- effect: function effect(_ref0, listenerApi) {
9462
- var payload = _ref0.payload;
9618
+ effect: function effect(_ref1, listenerApi) {
9619
+ var payload = _ref1.payload;
9463
9620
  preserveAnimationStep(payload.mapId, listenerApi);
9464
9621
  }
9465
9622
  });
9466
9623
  mapListener.startListening({
9467
9624
  actionCreator: mapActions.unregisterMap,
9468
- effect: function effect(_ref1, listenerApi) {
9469
- var payload = _ref1.payload;
9625
+ effect: function effect(_ref10, listenerApi) {
9626
+ var payload = _ref10.payload;
9470
9627
  var mapId = payload.mapId;
9471
- animationRangeRefreshTokens["delete"](mapId);
9472
9628
  var layerList = getLayersByMapId(listenerApi.getState(), mapId);
9473
9629
  metronome.unregister(mapId);
9474
9630
  layerList.map(function (layer) {
@@ -9485,8 +9641,8 @@ mapListener.startListening({
9485
9641
  });
9486
9642
  mapListener.startListening({
9487
9643
  actionCreator: mapActions.setStepBackwardOrForward,
9488
- effect: function effect(_ref10, listenerApi) {
9489
- var payload = _ref10.payload;
9644
+ effect: function effect(_ref11, listenerApi) {
9645
+ var payload = _ref11.payload;
9490
9646
  var mapId = payload.mapId,
9491
9647
  isForwardStep = payload.isForwardStep;
9492
9648
  // timeStep is stored in minutes
@@ -9499,6 +9655,11 @@ mapListener.startListening({
9499
9655
  var hasValidDataStartTime = Number.isFinite(dataStartTime) && dataStartTime > 0 && dataStartTime < 2147483647;
9500
9656
  var hasValidDataEndTime = Number.isFinite(dataEndTime) && dataEndTime > 0;
9501
9657
  if (dateUtils.isValid(currentTime)) {
9658
+ var _layerSelectors$getLa;
9659
+ var state = listenerApi.getState();
9660
+ var autoTimeStepLayerId = getAutoTimeStepLayerId(state, mapId);
9661
+ var autoTimeStepValues = isTimestepAuto(state, mapId) && autoTimeStepLayerId ? (_layerSelectors$getLa = getLayerTimeDimension(state, autoTimeStepLayerId)) === null || _layerSelectors$getLa === void 0 ? void 0 : _layerSelectors$getLa.values : undefined;
9662
+ var isIrregularTimeList = !!autoTimeStepValues && !autoTimeStepValues.includes('/');
9502
9663
  var makeForwardStep = function makeForwardStep() {
9503
9664
  // timeStep is in minutes, convert to seconds
9504
9665
  var timeStepInSeconds = timeStep * 60;
@@ -9520,7 +9681,17 @@ mapListener.startListening({
9520
9681
  var newTime = hasValidDataStartTime ? Math.max(roundedTime, dataStartTime) : roundedTime;
9521
9682
  return dateUtils.fromUnix(newTime).toISOString();
9522
9683
  };
9523
- var selectedTimeString = isForwardStep ? makeForwardStep() : makeBackwardStep();
9684
+ var adjacentTime = isIrregularTimeList ? getAdjacentTimeValue(autoTimeStepValues, currentTime, !!isForwardStep) : undefined;
9685
+ if (isIrregularTimeList && adjacentTime === undefined) {
9686
+ return;
9687
+ }
9688
+ var getSelectedTimeString = function getSelectedTimeString() {
9689
+ if (adjacentTime !== undefined) {
9690
+ return dateUtils.fromUnix(adjacentTime).toISOString();
9691
+ }
9692
+ return isForwardStep ? makeForwardStep() : makeBackwardStep();
9693
+ };
9694
+ var selectedTimeString = getSelectedTimeString();
9524
9695
  var isMapAnimating = isAnimating(listenerApi.getState(), mapId);
9525
9696
  if (isMapAnimating) {
9526
9697
  listenerApi.dispatch(mapActions.mapStopAnimation({
@@ -9538,32 +9709,6 @@ mapListener.startListening({
9538
9709
  }
9539
9710
  }
9540
9711
  });
9541
- var updateReferenceTimeAnimationRange = function updateReferenceTimeAnimationRange(mapId, layerId, referenceTime, listenerApi) {
9542
- var animationLength = getAnimationLength(listenerApi.getState(), mapId);
9543
- var autoTimeStepLayerId = getAutoTimeStepLayerId(listenerApi.getState(), mapId);
9544
- if (autoTimeStepLayerId !== layerId || (animationLength === null || animationLength === void 0 ? void 0 : animationLength.mode) !== AnimationLengthMode.ReferenceTime) {
9545
- return;
9546
- }
9547
- var anchorTime = dateUtils.utc(referenceTime);
9548
- var resolvedRange = resolveAnimationRange(animationLength, anchorTime);
9549
- listenerApi.dispatch(mapActions.setAnimationLength(_objectSpread2({
9550
- mapId: mapId,
9551
- animationLength: animationLength
9552
- }, resolvedRange)));
9553
- };
9554
- mapListener.startListening({
9555
- actionCreator: layerActions.layerChangeDimension,
9556
- effect: function effect(_ref11, listenerApi) {
9557
- var payload = _ref11.payload;
9558
- var mapId = payload.mapId,
9559
- layerId = payload.layerId,
9560
- dimension = payload.dimension;
9561
- if (!mapId || dimension.name !== 'reference_time') {
9562
- return;
9563
- }
9564
- updateReferenceTimeAnimationRange(mapId, layerId, dimension.currentValue, listenerApi);
9565
- }
9566
- });
9567
9712
  var updateAnimationMode = function updateAnimationMode(mapId, listenerApi) {
9568
9713
  var _autoTimeStepLayer$di;
9569
9714
  var previousAutoTimeStepLayerId = getAutoTimeStepLayerId(listenerApi.getOriginalState(), mapId);
@@ -9580,7 +9725,9 @@ var updateAnimationMode = function updateAnimationMode(mapId, listenerApi) {
9580
9725
  listenerApi.dispatch(mapActions.setAnimationLength(_objectSpread2({
9581
9726
  mapId: mapId,
9582
9727
  animationLength: animationLength
9583
- }, resolveAnimationRange(animationLength, dateUtils.utc(referenceTimeDimension.currentValue)))));
9728
+ }, resolveAnimationRange(animationLength, {
9729
+ referenceTime: referenceTimeDimension.currentValue
9730
+ }))));
9584
9731
  return;
9585
9732
  }
9586
9733
  var nextAnimationLength = autoTimeStepLayerId ? {
@@ -9589,7 +9736,8 @@ var updateAnimationMode = function updateAnimationMode(mapId, listenerApi) {
9589
9736
  mode: AnimationLengthMode.Now,
9590
9737
  now: defaultOffsetSelections
9591
9738
  };
9592
- var resolvedRange = nextAnimationLength.mode === AnimationLengthMode.Now && isValidAnimationLength(nextAnimationLength) ? resolveAnimationRange(nextAnimationLength) : undefined;
9739
+ var anchorInputs = getAnimationAnchorInputs(listenerApi.getState(), mapId);
9740
+ var resolvedRange = nextAnimationLength.mode === AnimationLengthMode.Now && isValidAnimationLength(nextAnimationLength, anchorInputs) ? resolveAnimationRange(nextAnimationLength, anchorInputs) : undefined;
9593
9741
  listenerApi.dispatch(mapActions.setAnimationLength(_objectSpread2({
9594
9742
  mapId: mapId,
9595
9743
  animationLength: nextAnimationLength
@@ -9609,6 +9757,16 @@ mapListener.startListening({
9609
9757
  updateAnimationMode(mapId, listenerApi);
9610
9758
  }
9611
9759
  });
9760
+ /* Last, so the range is resolved after the listeners above have settled the setting. */
9761
+ mapListener.startListening({
9762
+ matcher: isAnyOf(mapActions.setAnimationLength, mapActions.setTimeStep, mapActions.setAutoLayerId, mapActions.setAutoTimestepLayerId, layerActions.layerDelete, layerActions.onUpdateLayerInformation, layerActions.layerChangeDimension),
9763
+ effect: function effect(action, listenerApi) {
9764
+ var mapId = mapIdToReconcile(action, listenerApi.getState());
9765
+ if (mapId) {
9766
+ reconcileAnimationRange(mapId, listenerApi, isSyncSkippedBy(action));
9767
+ }
9768
+ }
9769
+ });
9612
9770
 
9613
9771
  var copyView = function copyView(view) {
9614
9772
  return new View({
@@ -9815,21 +9973,59 @@ var fetchSTACLayers = /*#__PURE__*/function () {
9815
9973
  return _ref.apply(this, arguments);
9816
9974
  };
9817
9975
  }();
9976
+ var fetchEDRLayers = /*#__PURE__*/function () {
9977
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(serviceUrl) {
9978
+ var _data$collections;
9979
+ var baseUrl, data;
9980
+ return _regenerator().w(function (_context2) {
9981
+ while (1) switch (_context2.n) {
9982
+ case 0:
9983
+ baseUrl = serviceUrl.endsWith('/') ? serviceUrl.slice(0, -1) : serviceUrl;
9984
+ _context2.n = 1;
9985
+ return fetchEDRJson("".concat(baseUrl, "/collections"));
9986
+ case 1:
9987
+ data = _context2.v;
9988
+ return _context2.a(2, ((_data$collections = data.collections) !== null && _data$collections !== void 0 ? _data$collections : []).flatMap(function (collection) {
9989
+ var _collection$parameter;
9990
+ return Object.entries((_collection$parameter = collection.parameter_names) !== null && _collection$parameter !== void 0 ? _collection$parameter : {}).map(function (_ref3) {
9991
+ var _parameter$label, _ref5, _collection$path, _collection$title, _parameter$observedPr, _parameter$label2;
9992
+ var _ref4 = _slicedToArray(_ref3, 2),
9993
+ parameterId = _ref4[0],
9994
+ parameter = _ref4[1];
9995
+ return {
9996
+ name: parameterId,
9997
+ title: (_parameter$label = parameter.label) !== null && _parameter$label !== void 0 ? _parameter$label : parameterId,
9998
+ leaf: true,
9999
+ path: [].concat(_toConsumableArray((_ref5 = (_collection$path = collection.path) !== null && _collection$path !== void 0 ? _collection$path : collection.groups) !== null && _ref5 !== void 0 ? _ref5 : collection.group ? [collection.group] : []), [(_collection$title = collection.title) !== null && _collection$title !== void 0 ? _collection$title : collection.id]),
10000
+ keywords: (_parameter$observedPr = parameter.observedProperty) !== null && _parameter$observedPr !== void 0 && _parameter$observedPr.label ? [normalizeEDRLabel(parameter.observedProperty.label, (_parameter$label2 = parameter.label) !== null && _parameter$label2 !== void 0 ? _parameter$label2 : parameterId)] : [],
10001
+ edrCollectionId: collection.id,
10002
+ edrParameter: parameter,
10003
+ styles: defaultEdrStyles
10004
+ };
10005
+ });
10006
+ }));
10007
+ }
10008
+ }, _callee2);
10009
+ }));
10010
+ return function fetchEDRLayers(_x2) {
10011
+ return _ref2.apply(this, arguments);
10012
+ };
10013
+ }();
9818
10014
  var dispatchServiceLayers = function dispatchServiceLayers(service, layers, listenerApi) {
9819
10015
  listenerApi.dispatch(serviceActions.serviceSetLayers(_objectSpread2(_objectSpread2({}, service), {}, {
9820
10016
  layers: layers
9821
10017
  })));
9822
10018
  };
9823
10019
  var fetchSTACService = /*#__PURE__*/function () {
9824
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(service, listenerApi) {
10020
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(service, listenerApi) {
9825
10021
  var _yield$Promise$all, _yield$Promise$all2, root, layers;
9826
- return _regenerator().w(function (_context2) {
9827
- while (1) switch (_context2.n) {
10022
+ return _regenerator().w(function (_context3) {
10023
+ while (1) switch (_context3.n) {
9828
10024
  case 0:
9829
- _context2.n = 1;
10025
+ _context3.n = 1;
9830
10026
  return Promise.all([fetchStacCatalogRoot(service.serviceUrl), fetchSTACLayers(service.serviceUrl)]);
9831
10027
  case 1:
9832
- _yield$Promise$all = _context2.v;
10028
+ _yield$Promise$all = _context3.v;
9833
10029
  _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
9834
10030
  root = _yield$Promise$all2[0];
9835
10031
  layers = _yield$Promise$all2[1];
@@ -9839,117 +10035,139 @@ var fetchSTACService = /*#__PURE__*/function () {
9839
10035
  type: 'STAC'
9840
10036
  }), layers, listenerApi);
9841
10037
  case 2:
9842
- return _context2.a(2);
10038
+ return _context3.a(2);
9843
10039
  }
9844
- }, _callee2);
10040
+ }, _callee3);
9845
10041
  }));
9846
- return function fetchSTACService(_x2, _x3) {
9847
- return _ref2.apply(this, arguments);
10042
+ return function fetchSTACService(_x3, _x4) {
10043
+ return _ref6.apply(this, arguments);
9848
10044
  };
9849
10045
  }();
9850
10046
  var fetchService = /*#__PURE__*/function () {
9851
- var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(service, listenerApi) {
9852
- var layers, _t;
9853
- return _regenerator().w(function (_context3) {
9854
- while (1) switch (_context3.p = _context3.n) {
10047
+ var _ref7 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(service, listenerApi) {
10048
+ var layers, _layers, _t, _t2;
10049
+ return _regenerator().w(function (_context4) {
10050
+ while (1) switch (_context4.p = _context4.n) {
9855
10051
  case 0:
9856
- if (!(service.type === 'STAC')) {
9857
- _context3.n = 2;
10052
+ if (!(service.type === 'EDR')) {
10053
+ _context4.n = 5;
9858
10054
  break;
9859
10055
  }
9860
- _context3.n = 1;
9861
- return fetchSTACService(service, listenerApi);
9862
- case 1:
9863
- return _context3.a(2);
10056
+ _context4.p = 1;
10057
+ _context4.n = 2;
10058
+ return fetchEDRLayers(service.serviceUrl);
9864
10059
  case 2:
9865
- _context3.p = 2;
9866
- _context3.n = 3;
9867
- return queryWMSLayers(service.serviceUrl);
9868
- case 3:
9869
- layers = _context3.v;
10060
+ layers = _context4.v;
9870
10061
  dispatchServiceLayers(service, layers, listenerApi);
9871
- _context3.n = 5;
10062
+ _context4.n = 4;
9872
10063
  break;
9873
- case 4:
9874
- _context3.p = 4;
9875
- _t = _context3.v;
10064
+ case 3:
10065
+ _context4.p = 3;
10066
+ _t = _context4.v;
9876
10067
  if (_t instanceof Error) {
9877
10068
  console.warn(_t.message);
9878
10069
  }
10070
+ dispatchServiceLayers(service, [], listenerApi);
10071
+ case 4:
10072
+ return _context4.a(2);
9879
10073
  case 5:
9880
- return _context3.a(2);
10074
+ if (!(service.type === 'STAC')) {
10075
+ _context4.n = 7;
10076
+ break;
10077
+ }
10078
+ _context4.n = 6;
10079
+ return fetchSTACService(service, listenerApi);
10080
+ case 6:
10081
+ return _context4.a(2);
10082
+ case 7:
10083
+ _context4.p = 7;
10084
+ _context4.n = 8;
10085
+ return queryWMSLayers(service.serviceUrl);
10086
+ case 8:
10087
+ _layers = _context4.v;
10088
+ dispatchServiceLayers(service, _layers, listenerApi);
10089
+ _context4.n = 10;
10090
+ break;
10091
+ case 9:
10092
+ _context4.p = 9;
10093
+ _t2 = _context4.v;
10094
+ if (_t2 instanceof Error) {
10095
+ console.warn(_t2.message);
10096
+ }
10097
+ case 10:
10098
+ return _context4.a(2);
9881
10099
  }
9882
- }, _callee3, null, [[2, 4]]);
10100
+ }, _callee4, null, [[7, 9], [1, 3]]);
9883
10101
  }));
9884
- return function fetchService(_x4, _x5) {
9885
- return _ref3.apply(this, arguments);
10102
+ return function fetchService(_x5, _x6) {
10103
+ return _ref7.apply(this, arguments);
9886
10104
  };
9887
10105
  }();
9888
10106
  var fetchInitialServices = /*#__PURE__*/function () {
9889
- var _ref4 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(payload, listenerApi) {
9890
- var _t2;
9891
- return _regenerator().w(function (_context5) {
9892
- while (1) switch (_context5.p = _context5.n) {
10107
+ var _ref8 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(payload, listenerApi) {
10108
+ var _t3;
10109
+ return _regenerator().w(function (_context6) {
10110
+ while (1) switch (_context6.p = _context6.n) {
9893
10111
  case 0:
9894
10112
  if (payload !== null && payload !== void 0 && payload.services) {
9895
- _context5.n = 1;
10113
+ _context6.n = 1;
9896
10114
  break;
9897
10115
  }
9898
- return _context5.a(2);
10116
+ return _context6.a(2);
9899
10117
  case 1:
9900
- _context5.p = 1;
9901
- _context5.n = 2;
10118
+ _context6.p = 1;
10119
+ _context6.n = 2;
9902
10120
  return Promise.all(payload.services.map(/*#__PURE__*/function () {
9903
- var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref5) {
10121
+ var _ref0 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(_ref9) {
9904
10122
  var url, service;
9905
- return _regenerator().w(function (_context4) {
9906
- while (1) switch (_context4.n) {
10123
+ return _regenerator().w(function (_context5) {
10124
+ while (1) switch (_context5.n) {
9907
10125
  case 0:
9908
- url = _ref5.url, service = _objectWithoutProperties(_ref5, _excluded);
9909
- return _context4.a(2, fetchService(_objectSpread2(_objectSpread2({}, service), {}, {
10126
+ url = _ref9.url, service = _objectWithoutProperties(_ref9, _excluded);
10127
+ return _context5.a(2, fetchService(_objectSpread2(_objectSpread2({}, service), {}, {
9910
10128
  serviceUrl: url
9911
10129
  }), listenerApi));
9912
10130
  }
9913
- }, _callee4);
10131
+ }, _callee5);
9914
10132
  }));
9915
- return function (_x8) {
9916
- return _ref6.apply(this, arguments);
10133
+ return function (_x9) {
10134
+ return _ref0.apply(this, arguments);
9917
10135
  };
9918
10136
  }()));
9919
10137
  case 2:
9920
- _context5.n = 4;
10138
+ _context6.n = 4;
9921
10139
  break;
9922
10140
  case 3:
9923
- _context5.p = 3;
9924
- _t2 = _context5.v;
9925
- console.warn(_t2);
10141
+ _context6.p = 3;
10142
+ _t3 = _context6.v;
10143
+ console.warn(_t3);
9926
10144
  case 4:
9927
- return _context5.a(2);
10145
+ return _context6.a(2);
9928
10146
  }
9929
- }, _callee5, null, [[1, 3]]);
10147
+ }, _callee6, null, [[1, 3]]);
9930
10148
  }));
9931
- return function fetchInitialServices(_x6, _x7) {
9932
- return _ref4.apply(this, arguments);
10149
+ return function fetchInitialServices(_x7, _x8) {
10150
+ return _ref8.apply(this, arguments);
9933
10151
  };
9934
10152
  }();
9935
10153
  serviceListener.startListening({
9936
10154
  actionCreator: serviceActions.fetchInitialServices,
9937
10155
  effect: function () {
9938
- var _effect = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(_ref7, listenerApi) {
10156
+ var _effect = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(_ref1, listenerApi) {
9939
10157
  var payload;
9940
- return _regenerator().w(function (_context6) {
9941
- while (1) switch (_context6.n) {
10158
+ return _regenerator().w(function (_context7) {
10159
+ while (1) switch (_context7.n) {
9942
10160
  case 0:
9943
- payload = _ref7.payload;
10161
+ payload = _ref1.payload;
9944
10162
  listenerApi.cancelActiveListeners();
9945
- _context6.n = 1;
10163
+ _context7.n = 1;
9946
10164
  return fetchInitialServices(payload, listenerApi);
9947
10165
  case 1:
9948
- return _context6.a(2);
10166
+ return _context7.a(2);
9949
10167
  }
9950
- }, _callee6);
10168
+ }, _callee7);
9951
10169
  }));
9952
- function effect(_x9, _x0) {
10170
+ function effect(_x0, _x1) {
9953
10171
  return _effect.apply(this, arguments);
9954
10172
  }
9955
10173
  return effect;
@@ -4,6 +4,7 @@ import type { Dimension, ReduxLayer } from '../types';
4
4
  import type { LayerState } from './types';
5
5
  export declare const trimTrailingSlashes: (url: string) => string;
6
6
  export declare const getSTACServiceRootUrl: (serviceUrl: string) => string;
7
+ export declare const getEDRServiceRootUrl: (serviceUrl: string) => string;
7
8
  export declare const getTrailingSlashVariant: (url: string) => string;
8
9
  /**
9
10
  * Generates a unique id for a geoJSON feature. Feature ids need to be stable
@@ -0,0 +1,10 @@
1
+ import type { ListenerEffectAPI, ThunkDispatch, UnknownAction } from '@reduxjs/toolkit';
2
+ import type { WebMapStateModuleState } from '../types';
3
+ type MapListenerApi = ListenerEffectAPI<WebMapStateModuleState, ThunkDispatch<WebMapStateModuleState, unknown, UnknownAction>, unknown>;
4
+ export declare const ANIMATION_CLOCK_INTERVAL: number;
5
+ export declare const reconcileAnimationRange: (mapId: string, listenerApi: MapListenerApi, skipSync?: boolean) => void;
6
+ export declare const mapIdToReconcile: (action: UnknownAction, state: WebMapStateModuleState) => string | undefined;
7
+ export declare const isSyncSkippedBy: (action: UnknownAction) => boolean;
8
+ export declare const hasAnchoredAnimationLength: (state: WebMapStateModuleState, mapId: string) => boolean;
9
+ export declare const endsAnimationClockOf: (mapId: string) => (action: UnknownAction) => boolean;
10
+ export {};
@@ -14,6 +14,7 @@ export declare const mapUtils: {
14
14
  getSpeedFactor: (speedDelay: number) => import("libs/time-slider/dist").SpeedFactorType;
15
15
  getAnimationDuration: (animationEndTime: string | undefined, animationStartTime: string | undefined) => number;
16
16
  generateAnimationList: (unixAnimationStart: number, unixAnimationEnd: number, timeValues: string | undefined, animationInterval?: number) => mapTypes.WebMapAnimationList;
17
+ getAdjacentTimeValue: (timeValues: string | undefined, currentUnix: number, isForwardStep: boolean) => number | undefined;
17
18
  parseTimeDimToISO8601Interval: (timeInterval: string | undefined) => mapTypes.ISO8601Interval[];
18
19
  produceTimeSliderTimeSpan: (draft: import("immer").Draft<mapTypes.WebMapState>, mapId: string, timeSliderSpan: number) => void;
19
20
  };
@@ -1,4 +1,4 @@
1
- import type { AnimationLengthSetting } from '@opengeoweb/time-slider';
1
+ import type { AnimationAnchorInputs, AnimationLengthSetting } from '@opengeoweb/time-slider';
2
2
  import type { Bbox, ClockPosition, ClockSize, LegendPosition, LegendSize, MapPreset, WebMap, WebMapState } from './types';
3
3
  import type { CoreAppStore } from '../../types';
4
4
  import { uiTypes } from '../../ui';
@@ -3514,6 +3514,87 @@ export declare const getAnimationRange: ((state: CoreAppStore, mapId: string) =>
3514
3514
  argsMemoize: typeof import("reselect").weakMapMemoize;
3515
3515
  memoize: typeof import("reselect").weakMapMemoize;
3516
3516
  };
3517
+ export declare const getAnimationAnchorInputs: ((state: CoreAppStore, mapId: string) => AnimationAnchorInputs) & {
3518
+ clearCache: () => void;
3519
+ resultsCount: () => number;
3520
+ resetResultsCount: () => void;
3521
+ } & {
3522
+ resultFunc: (resultFuncArgs_0: Record<string, ReduxLayer> | null, resultFuncArgs_1: string | undefined, resultFuncArgs_2: number) => AnimationAnchorInputs;
3523
+ memoizedResultFunc: ((resultFuncArgs_0: Record<string, ReduxLayer> | null, resultFuncArgs_1: string | undefined, resultFuncArgs_2: number) => AnimationAnchorInputs) & {
3524
+ clearCache: () => void;
3525
+ resultsCount: () => number;
3526
+ resetResultsCount: () => void;
3527
+ };
3528
+ lastResult: () => AnimationAnchorInputs;
3529
+ dependencies: [((state: CoreAppStore) => Record<string, ReduxLayer> | null) & {
3530
+ clearCache: () => void;
3531
+ resultsCount: () => number;
3532
+ resetResultsCount: () => void;
3533
+ } & {
3534
+ resultFunc: (resultFuncArgs_0: import("../types").LayerState | undefined) => Record<string, ReduxLayer> | null;
3535
+ memoizedResultFunc: ((resultFuncArgs_0: import("../types").LayerState | undefined) => Record<string, ReduxLayer> | null) & {
3536
+ clearCache: () => void;
3537
+ resultsCount: () => number;
3538
+ resetResultsCount: () => void;
3539
+ };
3540
+ lastResult: () => Record<string, ReduxLayer> | null;
3541
+ dependencies: [(store: CoreAppStore) => import("../types").LayerState | undefined];
3542
+ recomputations: () => number;
3543
+ resetRecomputations: () => void;
3544
+ dependencyRecomputations: () => number;
3545
+ resetDependencyRecomputations: () => void;
3546
+ } & {
3547
+ argsMemoize: typeof import("reselect").weakMapMemoize;
3548
+ memoize: typeof import("reselect").weakMapMemoize;
3549
+ }, ((state: CoreAppStore, mapId: string) => string | undefined) & {
3550
+ clearCache: () => void;
3551
+ resultsCount: () => number;
3552
+ resetResultsCount: () => void;
3553
+ } & {
3554
+ resultFunc: (resultFuncArgs_0: WebMap | undefined) => string | undefined;
3555
+ memoizedResultFunc: ((resultFuncArgs_0: WebMap | undefined) => string | undefined) & {
3556
+ clearCache: () => void;
3557
+ resultsCount: () => number;
3558
+ resetResultsCount: () => void;
3559
+ };
3560
+ lastResult: () => string | undefined;
3561
+ dependencies: [(store: CoreAppStore, mapId: string) => WebMap | undefined];
3562
+ recomputations: () => number;
3563
+ resetRecomputations: () => void;
3564
+ dependencyRecomputations: () => number;
3565
+ resetDependencyRecomputations: () => void;
3566
+ } & {
3567
+ argsMemoize: typeof import("reselect").weakMapMemoize;
3568
+ memoize: typeof import("reselect").weakMapMemoize;
3569
+ }, ((state: CoreAppStore, mapId: string) => number) & {
3570
+ clearCache: () => void;
3571
+ resultsCount: () => number;
3572
+ resetResultsCount: () => void;
3573
+ } & {
3574
+ resultFunc: (resultFuncArgs_0: WebMap | undefined) => number;
3575
+ memoizedResultFunc: ((resultFuncArgs_0: WebMap | undefined) => number) & {
3576
+ clearCache: () => void;
3577
+ resultsCount: () => number;
3578
+ resetResultsCount: () => void;
3579
+ };
3580
+ lastResult: () => number;
3581
+ dependencies: [(store: CoreAppStore, mapId: string) => WebMap | undefined];
3582
+ recomputations: () => number;
3583
+ resetRecomputations: () => void;
3584
+ dependencyRecomputations: () => number;
3585
+ resetDependencyRecomputations: () => void;
3586
+ } & {
3587
+ argsMemoize: typeof import("reselect").weakMapMemoize;
3588
+ memoize: typeof import("reselect").weakMapMemoize;
3589
+ }];
3590
+ recomputations: () => number;
3591
+ resetRecomputations: () => void;
3592
+ dependencyRecomputations: () => number;
3593
+ resetDependencyRecomputations: () => void;
3594
+ } & {
3595
+ argsMemoize: typeof import("reselect").weakMapMemoize;
3596
+ memoize: typeof import("reselect").weakMapMemoize;
3597
+ };
3517
3598
  /**
3518
3599
  * Gets intialViewMapPreset from webmap state
3519
3600
  *
@@ -233,6 +233,7 @@ export interface RefreshAnimationRangePayload {
233
233
  mapId: string;
234
234
  animationStartTime: string;
235
235
  animationEndTime: string;
236
+ skipSync?: boolean;
236
237
  }
237
238
  export interface ToggleTimeSliderHoverPayload {
238
239
  mapId: string;
@@ -78,6 +78,11 @@ export declare const getAnimationDuration: (animationEndTime: string | undefined
78
78
  * @returns WebMapAnimationList with time points
79
79
  */
80
80
  export declare const generateAnimationList: (unixAnimationStart: number, unixAnimationEnd: number, timeValues: string | undefined, animationInterval?: number) => WebMapAnimationList;
81
+ /**
82
+ * Returns the adjacent time (unix seconds) in a comma separated list of time values,
83
+ * or undefined when the values are empty, contain ISO8601 intervals or there is no adjacent time.
84
+ */
85
+ export declare const getAdjacentTimeValue: (timeValues: string | undefined, currentUnix: number, isForwardStep: boolean) => number | undefined;
81
86
  /**
82
87
  * Parses the time dimension values string to an array of ISO8601 intervals
83
88
  * @param timeInterval
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeoweb/store",
3
- "version": "20.0.1",
3
+ "version": "20.1.0-nightly-20261017",
4
4
  "description": "GeoWeb Store library for the opengeoweb project",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,15 +20,15 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "@opengeoweb/shared": "20.0.1",
23
+ "@opengeoweb/shared": "20.1.0-nightly-20261017",
24
24
  "react-redux": "^9.2.0",
25
25
  "@reduxjs/toolkit": "^2.6.1",
26
- "@opengeoweb/webmap-react": "20.0.1",
27
- "@opengeoweb/webmap": "20.0.1",
26
+ "@opengeoweb/webmap-react": "20.1.0-nightly-20261017",
27
+ "@opengeoweb/webmap": "20.1.0-nightly-20261017",
28
28
  "immer": "^10.0.3",
29
29
  "lodash": "^4.18.1",
30
- "@opengeoweb/metronome": "20.0.1",
31
- "@opengeoweb/time-slider": "20.0.1",
30
+ "@opengeoweb/metronome": "20.1.0-nightly-20261017",
31
+ "@opengeoweb/time-slider": "20.1.0-nightly-20261017",
32
32
  "ol": "^10.4.0",
33
33
  "@turf/turf": "^7.2.0",
34
34
  "@types/geojson": "^7946.0.14",