@opengeoweb/webmap-react 19.6.0 → 19.6.1-nightly-20260913

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
@@ -1,4 +1,4 @@
1
- import { WMInvalidDateValues, getCorrectWMSDimName, WMImageStore, WMImageStoreLoadType, WMJSDimension, webmapUtils, WMLayer, LayerType, legendImageStore, WMImageEventType, getLegendGraphicURLForLayer, WEBMAP_NAMESPACE, WMProj4Defs, privateWebMapUtils, wmDetermineDimensionMode, WMDefaultStyleName, tilesettings } from '@opengeoweb/webmap';
1
+ import { WMInvalidDateValues, getCorrectWMSDimName, WMImageStore, WMImageStoreLoadType, WMJSDimension, webmapUtils, WMLayer, LayerType, legendImageStore, WMImageEventType, getLegendGraphicURLForLayer, WEBMAP_NAMESPACE, WMProj4Defs, privateWebMapUtils, wmDetermineDimensionMode, WMJSMAP_LONLAT_EPSGCODE, WMDefaultStyleName, tilesettings } from '@opengeoweb/webmap';
2
2
  export { WEBMAP_NAMESPACE, webmapTranslations } from '@opengeoweb/webmap';
3
3
  import React, { createContext, useMemo, useRef, useState, useEffect, useCallback, useContext, useLayoutEffect } from 'react';
4
4
  import { memoize, range, without, isEqual, throttle, debounce, cloneDeep } from 'lodash';
@@ -20,13 +20,15 @@ import { Point, MultiPoint, Polygon, LineString } from 'ol/geom';
20
20
  import { Style, Icon as Icon$1, Circle, Stroke, Fill, Text } from 'ol/style';
21
21
  import Box$1 from '@mui/material/Box';
22
22
  import Typography$1 from '@mui/material/Typography';
23
- import { View, Map as Map$1, Feature, Collection, Overlay } from 'ol';
24
- import { defaults, MouseWheelZoom, Draw, Modify, Translate, Snap, DragPan } from 'ol/interaction';
23
+ import { View, Map as Map$1, Collection, Feature, Overlay } from 'ol';
24
+ import { defaults, MouseWheelZoom, Draw, Modify, Translate as Translate$1, Snap, DragPan } from 'ol/interaction';
25
25
  import 'ol/ol.css';
26
26
  import { listen, unlistenByKey } from 'ol/events';
27
27
  import { unByKey } from 'ol/Observable';
28
28
  import EventType from 'ol/pointer/EventType';
29
29
  import { toLonLat, fromLonLat, transformExtent, transform } from 'ol/proj';
30
+ import { noModifierKeys, platformModifierKeyOnly, always, never } from 'ol/events/condition';
31
+ import Translate from 'ol/interaction/Translate';
30
32
  import { register } from 'ol/proj/proj4';
31
33
  import proj4 from 'proj4';
32
34
  import { lineSplit, cleanCoords, featureCollection, difference, bbox, feature, simplify, booleanPointInPolygon, intersect, polygonToLine, booleanClockwise, rewind, toWgs84, toMercator, coordEach } from '@turf/turf';
@@ -36,11 +38,10 @@ import WMTSCapabilities from 'ol/format/WMTSCapabilities';
36
38
  import TileLayer from 'ol/layer/Tile';
37
39
  import { WMTS, XYZ, TileWMS, GeoTIFF } from 'ol/source';
38
40
  import { optionsFromCapabilities } from 'ol/source/WMTS';
39
- import OlGeoJSON from 'ol/format/GeoJSON';
40
- import { platformModifierKeyOnly, always, never } from 'ol/events/condition';
41
- import DragBox from 'ol/interaction/DragBox';
41
+ import GeoJSON from 'ol/format/GeoJSON';
42
42
  import { Vector } from 'ol/layer';
43
43
  import VectorSource from 'ol/source/Vector';
44
+ import DragBox from 'ol/interaction/DragBox';
44
45
  import TileLayer$1 from 'ol/layer/WebGLTile';
45
46
  import { fromCircle } from 'ol/geom/Polygon';
46
47
  import { createBox, createRegularPolygon } from 'ol/interaction/Draw';
@@ -3846,6 +3847,101 @@ var OpenLayersMapView = function OpenLayersMapView(_ref) {
3846
3847
  });
3847
3848
  };
3848
3849
 
3850
+ var getOlFeatureKey = function getOlFeatureKey(feature) {
3851
+ var id = feature === null || feature === void 0 ? void 0 : feature.getId();
3852
+ if (id !== undefined && id !== null) {
3853
+ return String(id);
3854
+ }
3855
+ var originalId = feature === null || feature === void 0 ? void 0 : feature.get('originalId');
3856
+ return typeof originalId === 'string' ? originalId : undefined;
3857
+ };
3858
+ var isDefaultMovable = function isDefaultMovable(feature) {
3859
+ return feature.get('isSelected') === true && feature.get('isReadonly') !== true;
3860
+ };
3861
+ var createMoveFeatures = function createMoveFeatures(_ref) {
3862
+ var features = _ref.features,
3863
+ isMovable = _ref.isMovable,
3864
+ onMoveEnd = _ref.onMoveEnd,
3865
+ onMoveStart = _ref.onMoveStart;
3866
+ var movableFeatures = features.filter(isMovable);
3867
+ if (movableFeatures.length === 0) {
3868
+ return undefined;
3869
+ }
3870
+ var collection = new Collection(movableFeatures);
3871
+ var translate = new Translate({
3872
+ features: collection,
3873
+ // Cmd/Ctrl must fall through to the box select and shift to the selection toggle.
3874
+ condition: noModifierKeys,
3875
+ hitTolerance: 5
3876
+ });
3877
+ translate.on('translatestart', function () {
3878
+ onMoveStart === null || onMoveStart === void 0 || onMoveStart();
3879
+ });
3880
+ translate.on('translateend', function (event) {
3881
+ var _event$startCoordinat = _slicedToArray(event.startCoordinate, 2),
3882
+ startX = _event$startCoordinat[0],
3883
+ startY = _event$startCoordinat[1];
3884
+ var _event$coordinate = _slicedToArray(event.coordinate, 2),
3885
+ endX = _event$coordinate[0],
3886
+ endY = _event$coordinate[1];
3887
+ if (startX === endX && startY === endY) {
3888
+ onMoveEnd([]);
3889
+ return;
3890
+ }
3891
+ onMoveEnd(event.features.getArray());
3892
+ });
3893
+ return {
3894
+ translate: translate,
3895
+ dispose: function dispose() {
3896
+ return collection.clear();
3897
+ }
3898
+ };
3899
+ };
3900
+ var useMoveFeatures = function useMoveFeatures(_ref2) {
3901
+ var map = _ref2.map,
3902
+ features = _ref2.features,
3903
+ active = _ref2.active,
3904
+ isMovable = _ref2.isMovable,
3905
+ onMoveEnd = _ref2.onMoveEnd,
3906
+ onMoveStart = _ref2.onMoveStart;
3907
+ var isMovableRef = useRef(isMovable);
3908
+ var onMoveEndRef = useRef(onMoveEnd);
3909
+ var onMoveStartRef = useRef(onMoveStart);
3910
+ useEffect(function () {
3911
+ isMovableRef.current = isMovable;
3912
+ onMoveEndRef.current = onMoveEnd;
3913
+ onMoveStartRef.current = onMoveStart;
3914
+ });
3915
+ useEffect(function () {
3916
+ if (!map || !active || !features.length) {
3917
+ return function () {};
3918
+ }
3919
+ var moveFeatures = createMoveFeatures({
3920
+ features: features,
3921
+ isMovable: function isMovable(feature) {
3922
+ var _isMovableRef$current;
3923
+ return ((_isMovableRef$current = isMovableRef.current) !== null && _isMovableRef$current !== void 0 ? _isMovableRef$current : isDefaultMovable)(feature);
3924
+ },
3925
+ onMoveEnd: function onMoveEnd(movedFeatures) {
3926
+ var _onMoveEndRef$current;
3927
+ return (_onMoveEndRef$current = onMoveEndRef.current) === null || _onMoveEndRef$current === void 0 ? void 0 : _onMoveEndRef$current.call(onMoveEndRef, movedFeatures);
3928
+ },
3929
+ onMoveStart: function onMoveStart() {
3930
+ var _onMoveStartRef$curre;
3931
+ return (_onMoveStartRef$curre = onMoveStartRef.current) === null || _onMoveStartRef$curre === void 0 ? void 0 : _onMoveStartRef$curre.call(onMoveStartRef);
3932
+ }
3933
+ });
3934
+ if (!moveFeatures) {
3935
+ return function () {};
3936
+ }
3937
+ map.addInteraction(moveFeatures.translate);
3938
+ return function () {
3939
+ moveFeatures.dispose();
3940
+ map.removeInteraction(moveFeatures.translate);
3941
+ };
3942
+ }, [map, features, active]);
3943
+ };
3944
+
3849
3945
  var initializeOpenLayersProjections = function initializeOpenLayersProjections() {
3850
3946
  WMProj4Defs.forEach(function (_ref) {
3851
3947
  var _ref2 = _slicedToArray(_ref, 2),
@@ -4953,6 +5049,7 @@ var useGetWMSLayerStyleList = function useGetWMSLayerStyleList(serviceUrl, name)
4953
5049
  * @returns object with wmLayer and if set an errorMessage
4954
5050
  */
4955
5051
  var useGetWMLayerInstance = function useGetWMLayerInstance(layerFoundation) {
5052
+ var hasLayerFoundation = layerFoundation !== undefined;
4956
5053
  var id = layerFoundation === null || layerFoundation === void 0 ? void 0 : layerFoundation.id;
4957
5054
  var serviceUrl = (layerFoundation === null || layerFoundation === void 0 ? void 0 : layerFoundation.service) || '';
4958
5055
  var name = (layerFoundation === null || layerFoundation === void 0 ? void 0 : layerFoundation.name) || '';
@@ -4973,7 +5070,7 @@ var useGetWMLayerInstance = function useGetWMLayerInstance(layerFoundation) {
4973
5070
  var tmpWMLayer = webmapUtils.getWMLayerById(layerId);
4974
5071
  var layerIdChanged = id && id !== (tmpWMLayer === null || tmpWMLayer === void 0 ? void 0 : tmpWMLayer.id);
4975
5072
  var layerServiceChanged = (tmpWMLayer === null || tmpWMLayer === void 0 ? void 0 : tmpWMLayer.service) !== serviceUrl;
4976
- if (layerServiceChanged || layerIdChanged) {
5073
+ if (serviceUrl && (layerServiceChanged || layerIdChanged)) {
4977
5074
  // Make a new layer if the serviceUrl changes. (But not when the name changes)
4978
5075
  var refTimeDimensionMode = wmDetermineDimensionMode({
4979
5076
  name: name,
@@ -4991,6 +5088,9 @@ var useGetWMLayerInstance = function useGetWMLayerInstance(layerFoundation) {
4991
5088
  webmapUtils.registerWMLayer(wmLayer, layerId);
4992
5089
  }
4993
5090
  React.useEffect(function () {
5091
+ if (!hasLayerFoundation || !serviceUrl) {
5092
+ return;
5093
+ }
4994
5094
  // Set the name and parse the layer
4995
5095
  var wmLayer = webmapUtils.getWMLayerById(layerId);
4996
5096
  if (wmLayer.layerType !== layerType) {
@@ -5001,7 +5101,7 @@ var useGetWMLayerInstance = function useGetWMLayerInstance(layerFoundation) {
5001
5101
  })["finally"](function () {
5002
5102
  setLayer(wmLayer);
5003
5103
  });
5004
- }, [layerId, layerType, name, serviceUrl]);
5104
+ }, [hasLayerFoundation, layerId, layerType, name, serviceUrl]);
5005
5105
  return {
5006
5106
  wmLayer: layer,
5007
5107
  errorMessage: errorMessage
@@ -5029,7 +5129,8 @@ var useQueryWMTSGetCapabilities = function useQueryWMTSGetCapabilities(serviceUr
5029
5129
  return _queryFn2.apply(this, arguments);
5030
5130
  }
5031
5131
  return queryFn;
5032
- }()
5132
+ }(),
5133
+ enabled: serviceUrl.length > 0
5033
5134
  });
5034
5135
  };
5035
5136
 
@@ -5746,6 +5847,17 @@ var useSetIntervalWhenVisible = function useSetIntervalWhenVisible(autoUpdate, r
5746
5847
  * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
5747
5848
  * */
5748
5849
  initializeOpenLayersProjections();
5850
+ var getLayerExtentForProjection = function getLayerExtentForProjection(wmLayer, projectionCode) {
5851
+ var crs = wmLayer.getCRSByName(projectionCode);
5852
+ if (crs !== null && crs !== void 0 && crs.bbox) {
5853
+ return crs.bbox.getExtent();
5854
+ }
5855
+ var geo = wmLayer.geographicBoundingBox;
5856
+ if (geo) {
5857
+ return transformExtent([parseFloat(geo.west), parseFloat(geo.south), parseFloat(geo.east), parseFloat(geo.north)], WMJSMAP_LONLAT_EPSGCODE, projectionCode);
5858
+ }
5859
+ return undefined;
5860
+ };
5749
5861
  var useViewFromLayer = function useViewFromLayer(layerProps) {
5750
5862
  var baseView = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
5751
5863
  projection: 'EPSG:3857',
@@ -5771,11 +5883,11 @@ var useViewFromLayer = function useViewFromLayer(layerProps) {
5771
5883
  if (!wmLayer) {
5772
5884
  return;
5773
5885
  }
5774
- var layerProjectionForCode = wmLayer.getProjection(viewRef.current.getProjection().getCode());
5775
- if (!(layerProjectionForCode !== null && layerProjectionForCode !== void 0 && layerProjectionForCode.bbox)) {
5886
+ var extent = getLayerExtentForProjection(wmLayer, viewRef.current.getProjection().getCode());
5887
+ if (!extent) {
5776
5888
  return;
5777
5889
  }
5778
- viewRef.current.fit(layerProjectionForCode.bbox.getExtent());
5890
+ viewRef.current.fit(extent);
5779
5891
  }, [wmLayer]);
5780
5892
  return viewRef.current;
5781
5893
  };
@@ -5991,13 +6103,141 @@ var DefaultBaseLayers = function DefaultBaseLayers(_ref) {
5991
6103
  });
5992
6104
  };
5993
6105
 
6106
+ /* *
6107
+ * Licensed under the Apache License, Version 2.0 (the "License");
6108
+ * you may not use this file except in compliance with the License.
6109
+ * You may obtain a copy of the License at
6110
+ *
6111
+ * http://www.apache.org/licenses/LICENSE-2.0
6112
+ *
6113
+ * Unless required by applicable law or agreed to in writing, software
6114
+ * distributed under the License is distributed on an "AS IS" BASIS,
6115
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6116
+ * See the License for the specific language governing permissions and
6117
+ * limitations under the License.
6118
+ *
6119
+ * Copyright 2026 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6120
+ * Copyright 2026 - Finnish Meteorological Institute (FMI)
6121
+ * Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
6122
+ * */
6123
+ var isBoxSelectModifier = function isBoxSelectModifier(event) {
6124
+ return platformModifierKeyOnly({
6125
+ originalEvent: event
6126
+ });
6127
+ };
6128
+ var createDragBoxSelect = function createDragBoxSelect(_ref) {
6129
+ var sources = _ref.sources,
6130
+ onBoxSelect = _ref.onBoxSelect;
6131
+ var dragBox = new DragBox({
6132
+ condition: platformModifierKeyOnly
6133
+ });
6134
+ var previewedFeatures = [];
6135
+ // Preview flags are set silently, so the source needs telling or it keeps its cached frame.
6136
+ var repaint = function repaint() {
6137
+ sources.forEach(function (source) {
6138
+ return source.changed();
6139
+ });
6140
+ };
6141
+ var setPreview = function setPreview(feature, isPreviewed) {
6142
+ feature.set('boxSelectPreview', isPreviewed, true);
6143
+ };
6144
+ var clearPreview = function clearPreview() {
6145
+ if (!previewedFeatures.length) {
6146
+ return;
6147
+ }
6148
+ previewedFeatures.forEach(function (feature) {
6149
+ setPreview(feature, false);
6150
+ });
6151
+ previewedFeatures = [];
6152
+ repaint();
6153
+ };
6154
+ var getIntersectingFeatures = function getIntersectingFeatures() {
6155
+ var extent = dragBox.getGeometry().getExtent();
6156
+ return sources.flatMap(function (source) {
6157
+ return source.getFeaturesInExtent(extent).filter(function (feature) {
6158
+ var _feature$getGeometry;
6159
+ return (_feature$getGeometry = feature.getGeometry()) === null || _feature$getGeometry === void 0 ? void 0 : _feature$getGeometry.intersectsExtent(extent);
6160
+ });
6161
+ });
6162
+ };
6163
+ dragBox.on('boxstart', function () {
6164
+ clearPreview();
6165
+ });
6166
+ dragBox.on('boxdrag', function () {
6167
+ var intersectingFeatures = getIntersectingFeatures();
6168
+ var intersectingSet = new Set(intersectingFeatures);
6169
+ var previousSet = new Set(previewedFeatures);
6170
+ var hasChanges = false;
6171
+ previewedFeatures.forEach(function (feature) {
6172
+ if (!intersectingSet.has(feature)) {
6173
+ setPreview(feature, false);
6174
+ hasChanges = true;
6175
+ }
6176
+ });
6177
+ intersectingFeatures.forEach(function (feature) {
6178
+ if (!previousSet.has(feature)) {
6179
+ setPreview(feature, true);
6180
+ hasChanges = true;
6181
+ }
6182
+ });
6183
+ previewedFeatures = intersectingFeatures;
6184
+ if (hasChanges) {
6185
+ repaint();
6186
+ }
6187
+ });
6188
+ dragBox.on('boxend', function (event) {
6189
+ clearPreview();
6190
+ var selectedFeatures = getIntersectingFeatures();
6191
+ if (selectedFeatures.length > 0) {
6192
+ var originalEvent = event.mapBrowserEvent.originalEvent;
6193
+ var addToSelection = Boolean(originalEvent === null || originalEvent === void 0 ? void 0 : originalEvent.shiftKey);
6194
+ onBoxSelect(selectedFeatures, addToSelection);
6195
+ }
6196
+ });
6197
+ return {
6198
+ dragBox: dragBox,
6199
+ dispose: clearPreview
6200
+ };
6201
+ };
6202
+ var useDragBoxSelect = function useDragBoxSelect(_ref2) {
6203
+ var map = _ref2.map,
6204
+ source = _ref2.source,
6205
+ active = _ref2.active,
6206
+ onBoxSelect = _ref2.onBoxSelect;
6207
+ var onBoxSelectRef = useRef(onBoxSelect);
6208
+ useEffect(function () {
6209
+ onBoxSelectRef.current = onBoxSelect;
6210
+ });
6211
+ useEffect(function () {
6212
+ if (!map || !source || !active) {
6213
+ return function () {};
6214
+ }
6215
+ var _createDragBoxSelect = createDragBoxSelect({
6216
+ sources: [source],
6217
+ onBoxSelect: function onBoxSelect(features, addToSelection) {
6218
+ var _onBoxSelectRef$curre;
6219
+ return (_onBoxSelectRef$curre = onBoxSelectRef.current) === null || _onBoxSelectRef$curre === void 0 ? void 0 : _onBoxSelectRef$curre.call(onBoxSelectRef, features, addToSelection);
6220
+ }
6221
+ }),
6222
+ dragBox = _createDragBoxSelect.dragBox,
6223
+ dispose = _createDragBoxSelect.dispose;
6224
+ map.addInteraction(dragBox);
6225
+ return function () {
6226
+ dispose();
6227
+ map.removeInteraction(dragBox);
6228
+ };
6229
+ }, [map, source, active]);
6230
+ };
6231
+
5994
6232
  var FeatureLayer = function FeatureLayer(_ref) {
6233
+ var _moveFeatures$isMovab;
5995
6234
  var features = _ref.features,
5996
6235
  style = _ref.style,
5997
6236
  zIndex = _ref.zIndex,
5998
6237
  hoverSelect = _ref.hoverSelect,
5999
6238
  clickOnFeature = _ref.clickOnFeature,
6000
6239
  boxSelect = _ref.boxSelect,
6240
+ moveFeatures = _ref.moveFeatures,
6001
6241
  layerId = _ref.layerId,
6002
6242
  testId = _ref.testId,
6003
6243
  opacity = _ref.opacity,
@@ -6011,6 +6251,8 @@ var FeatureLayer = function FeatureLayer(_ref) {
6011
6251
  _useState2 = _slicedToArray(_useState, 2),
6012
6252
  source = _useState2[0],
6013
6253
  setSource = _useState2[1];
6254
+ var isMovingRef = useRef(false);
6255
+ var pendingFeaturesRef = useRef(undefined);
6014
6256
  var layerRef = useRef(undefined);
6015
6257
  useEffect(function () {
6016
6258
  if (!map || !visible) {
@@ -6062,21 +6304,36 @@ var FeatureLayer = function FeatureLayer(_ref) {
6062
6304
  var _layerRef$current3;
6063
6305
  (_layerRef$current3 = layerRef.current) === null || _layerRef$current3 === void 0 || _layerRef$current3.setVisible(visible);
6064
6306
  }, [visible]);
6065
- useEffect(function () {
6307
+ var syncSource = React.useCallback(function (nextFeatures) {
6066
6308
  if (!source) {
6067
6309
  return;
6068
6310
  }
6069
6311
  source.clear();
6070
- if (features && features.length > 0) {
6071
- source.addFeatures(features);
6312
+ if (nextFeatures.length > 0) {
6313
+ source.addFeatures(nextFeatures);
6314
+ }
6315
+ }, [source]);
6316
+ useEffect(function () {
6317
+ if (!source) {
6318
+ return;
6072
6319
  }
6073
- }, [source, features]);
6320
+ // Rebuilding the source mid-drag would swap the features out from under the
6321
+ // move interaction, so it is deferred until the move has finished.
6322
+ if (isMovingRef.current) {
6323
+ pendingFeaturesRef.current = features;
6324
+ return;
6325
+ }
6326
+ syncSource(features !== null && features !== void 0 ? features : []);
6327
+ }, [source, features, syncSource]);
6074
6328
  useEffect(function () {
6075
6329
  if (!map || !source || !hoverSelect || !hoverSelect.active || !visible) {
6076
6330
  return function () {};
6077
6331
  }
6078
6332
  var previousHover = [];
6079
6333
  var pointerMoveFunction = debounce(function (evt) {
6334
+ if (isMovingRef.current) {
6335
+ return;
6336
+ }
6080
6337
  var hoveredFeature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
6081
6338
  if (!layer || (layer === null || layer === void 0 ? void 0 : layer.getSource()) !== source) {
6082
6339
  return false;
@@ -6136,64 +6393,34 @@ var FeatureLayer = function FeatureLayer(_ref) {
6136
6393
  unByKey(eventKey);
6137
6394
  };
6138
6395
  }, [map, source, clickOnFeature, visible]);
6139
- var onBoxSelectRef = useRef(boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.onBoxSelect);
6140
- useEffect(function () {
6141
- onBoxSelectRef.current = boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.onBoxSelect;
6396
+ useDragBoxSelect({
6397
+ map: map,
6398
+ source: source,
6399
+ active: Boolean((boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.active) && visible),
6400
+ onBoxSelect: boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.onBoxSelect
6401
+ });
6402
+ var handleMoveStart = React.useCallback(function () {
6403
+ isMovingRef.current = true;
6404
+ }, []);
6405
+ var handleMoveEnd = React.useCallback(function (movedFeatures) {
6406
+ isMovingRef.current = false;
6407
+ var pendingFeatures = pendingFeaturesRef.current;
6408
+ pendingFeaturesRef.current = undefined;
6409
+ if (pendingFeatures) {
6410
+ syncSource(pendingFeatures);
6411
+ }
6412
+ if (movedFeatures.length > 0) {
6413
+ moveFeatures === null || moveFeatures === void 0 || moveFeatures.onMoveEnd(movedFeatures);
6414
+ }
6415
+ }, [moveFeatures, syncSource]);
6416
+ useMoveFeatures({
6417
+ map: map,
6418
+ features: features,
6419
+ active: Boolean((moveFeatures === null || moveFeatures === void 0 ? void 0 : moveFeatures.active) && visible),
6420
+ isMovable: (_moveFeatures$isMovab = moveFeatures === null || moveFeatures === void 0 ? void 0 : moveFeatures.isMovable) !== null && _moveFeatures$isMovab !== void 0 ? _moveFeatures$isMovab : isDefaultMovable,
6421
+ onMoveEnd: handleMoveEnd,
6422
+ onMoveStart: handleMoveStart
6142
6423
  });
6143
- useEffect(function () {
6144
- if (!map || !source || !(boxSelect !== null && boxSelect !== void 0 && boxSelect.active) || !visible) {
6145
- return function () {};
6146
- }
6147
- var dragBox = new DragBox({
6148
- condition: platformModifierKeyOnly
6149
- });
6150
- var previewedFeatures = [];
6151
- var clearPreview = function clearPreview() {
6152
- previewedFeatures.forEach(function (feature) {
6153
- feature.set('boxSelectPreview', false, true);
6154
- });
6155
- previewedFeatures = [];
6156
- };
6157
- dragBox.on('boxstart', function () {
6158
- clearPreview();
6159
- });
6160
- dragBox.on('boxdrag', function () {
6161
- var extent = dragBox.getGeometry().getExtent();
6162
- var intersectingFeatures = source.getFeaturesInExtent(extent).filter(function (feature) {
6163
- var _feature$getGeometry;
6164
- return (_feature$getGeometry = feature.getGeometry()) === null || _feature$getGeometry === void 0 ? void 0 : _feature$getGeometry.intersectsExtent(extent);
6165
- });
6166
- var intersectingSet = new Set(intersectingFeatures);
6167
- previewedFeatures.forEach(function (feature) {
6168
- if (!intersectingSet.has(feature)) {
6169
- feature.set('boxSelectPreview', false, true);
6170
- }
6171
- });
6172
- intersectingFeatures.forEach(function (feature) {
6173
- feature.set('boxSelectPreview', true, true);
6174
- });
6175
- previewedFeatures = intersectingFeatures;
6176
- });
6177
- dragBox.on('boxend', function (event) {
6178
- clearPreview();
6179
- var extent = dragBox.getGeometry().getExtent();
6180
- var selectedFeatures = source.getFeaturesInExtent(extent).filter(function (feature) {
6181
- var _feature$getGeometry2;
6182
- return (_feature$getGeometry2 = feature.getGeometry()) === null || _feature$getGeometry2 === void 0 ? void 0 : _feature$getGeometry2.intersectsExtent(extent);
6183
- });
6184
- if (selectedFeatures.length > 0) {
6185
- var _onBoxSelectRef$curre;
6186
- var originalEvent = event.mapBrowserEvent.originalEvent;
6187
- var addToSelection = Boolean(originalEvent === null || originalEvent === void 0 ? void 0 : originalEvent.shiftKey);
6188
- (_onBoxSelectRef$curre = onBoxSelectRef.current) === null || _onBoxSelectRef$curre === void 0 || _onBoxSelectRef$curre.call(onBoxSelectRef, selectedFeatures, addToSelection);
6189
- }
6190
- });
6191
- map.addInteraction(dragBox);
6192
- return function () {
6193
- clearPreview();
6194
- map.removeInteraction(dragBox);
6195
- };
6196
- }, [map, source, boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.active, visible]);
6197
6424
  return null;
6198
6425
  };
6199
6426
 
@@ -6214,6 +6441,7 @@ var OpenLayersFeatureLayer = function OpenLayersFeatureLayer(_ref) {
6214
6441
  hoverSelect = _ref.hoverSelect,
6215
6442
  clickOnFeature = _ref.clickOnFeature,
6216
6443
  boxSelect = _ref.boxSelect,
6444
+ moveFeatures = _ref.moveFeatures,
6217
6445
  layerId = _ref.layerId,
6218
6446
  testId = _ref.testId,
6219
6447
  opacity = _ref.opacity,
@@ -6222,6 +6450,40 @@ var OpenLayersFeatureLayer = function OpenLayersFeatureLayer(_ref) {
6222
6450
  _ref$visible = _ref.visible,
6223
6451
  visible = _ref$visible === void 0 ? true : _ref$visible;
6224
6452
  var projection = useProjection();
6453
+ var onMoveEnd = moveFeatures === null || moveFeatures === void 0 ? void 0 : moveFeatures.onMoveEnd;
6454
+ var handleMoveEnd = useCallback(function (olFeatures) {
6455
+ if (!onMoveEnd || !projection) {
6456
+ return;
6457
+ }
6458
+ var formatter = new GeoJSON({
6459
+ featureProjection: projection
6460
+ });
6461
+ var movedFeatures = olFeatures.reduce(function (acc, olFeature) {
6462
+ var featureId = getOlFeatureKey(olFeature);
6463
+ var geometry = olFeature.getGeometry();
6464
+ if (!featureId || !geometry) {
6465
+ return acc;
6466
+ }
6467
+ var geoJSONGeometry = formatter.writeGeometryObject(geometry);
6468
+ if ('coordinates' in geoJSONGeometry) {
6469
+ geoJSONGeometry.coordinates = roundCoordinates(geoJSONGeometry.coordinates);
6470
+ }
6471
+ acc.push({
6472
+ featureId: featureId,
6473
+ geometry: geoJSONGeometry
6474
+ });
6475
+ return acc;
6476
+ }, []);
6477
+ if (movedFeatures.length > 0) {
6478
+ onMoveEnd(movedFeatures);
6479
+ }
6480
+ }, [onMoveEnd, projection]);
6481
+ var moveFeaturesConfig = useMemo(function () {
6482
+ return moveFeatures ? {
6483
+ active: moveFeatures.active,
6484
+ onMoveEnd: handleMoveEnd
6485
+ } : undefined;
6486
+ }, [moveFeatures, handleMoveEnd]);
6225
6487
  var featureCollectionRef = useRef(undefined);
6226
6488
  var projectionRef = useRef(projection);
6227
6489
  var features = useRef([]);
@@ -6230,7 +6492,7 @@ var OpenLayersFeatureLayer = function OpenLayersFeatureLayer(_ref) {
6230
6492
  if (projection && featureCollection) {
6231
6493
  featureCollectionRef.current = featureCollection;
6232
6494
  projectionRef.current = projection;
6233
- var formatter = new OlGeoJSON({
6495
+ var formatter = new GeoJSON({
6234
6496
  featureProjection: projection
6235
6497
  });
6236
6498
  features.current = formatter.readFeatures(featureCollection);
@@ -6247,6 +6509,7 @@ var OpenLayersFeatureLayer = function OpenLayersFeatureLayer(_ref) {
6247
6509
  features: features.current,
6248
6510
  hoverSelect: hoverSelect,
6249
6511
  layerId: layerId,
6512
+ moveFeatures: moveFeaturesConfig,
6250
6513
  opacity: opacity,
6251
6514
  style: style,
6252
6515
  testId: testId,
@@ -9662,7 +9925,22 @@ var FEATURE_MY_LOCATION = new Style$1({
9662
9925
  ctx.restore();
9663
9926
  }
9664
9927
  });
9928
+ var SELECTED_FEATURE_COLOR = '#006CFD';
9929
+ var getBoxSelectPreviewStyle = function getBoxSelectPreviewStyle(fill) {
9930
+ return new Style$1({
9931
+ stroke: new Stroke({
9932
+ color: SELECTED_FEATURE_COLOR,
9933
+ width: 2,
9934
+ lineDash: [4, 4]
9935
+ }),
9936
+ fill: new Fill({
9937
+ color: geowebColorToOpenLayersColor(fill, 0.3)
9938
+ }),
9939
+ zIndex: 9997
9940
+ });
9941
+ };
9665
9942
  var getFeaturePointStyle = function getFeaturePointStyle(fillColor, fillOpacity) {
9943
+ var isSelected = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
9666
9944
  return new Style$1({
9667
9945
  renderer: function renderer(pixelCoordinates, state) {
9668
9946
  var ctx = state.context,
@@ -9677,10 +9955,33 @@ var getFeaturePointStyle = function getFeaturePointStyle(fillColor, fillOpacity)
9677
9955
  ctx.arc(coord[0], coord[1], 9 * pixelRatio, 0, 2 * Math.PI);
9678
9956
  ctx.fill();
9679
9957
  ctx.shadowBlur = 0;
9958
+ if (isSelected) {
9959
+ ctx.strokeStyle = SELECTED_FEATURE_COLOR;
9960
+ ctx.lineWidth = 3 * pixelRatio;
9961
+ ctx.beginPath();
9962
+ ctx.arc(coord[0], coord[1], 12 * pixelRatio, 0, 2 * Math.PI);
9963
+ ctx.stroke();
9964
+ }
9680
9965
  ctx.restore();
9681
9966
  }
9682
9967
  });
9683
9968
  };
9969
+ // For icon points; getFeaturePointStyle draws the ring for the rest.
9970
+ var SELECTED_POINT_HALO_STYLE = new Style$1({
9971
+ renderer: function renderer(pixelCoordinates, state) {
9972
+ var ctx = state.context,
9973
+ pixelRatio = state.pixelRatio;
9974
+ var coord = pixelCoordinates;
9975
+ ctx.save();
9976
+ ctx.strokeStyle = SELECTED_FEATURE_COLOR;
9977
+ ctx.lineWidth = 3 * pixelRatio;
9978
+ ctx.beginPath();
9979
+ ctx.arc(coord[0], coord[1], 16 * pixelRatio, 0, 2 * Math.PI);
9980
+ ctx.stroke();
9981
+ ctx.restore();
9982
+ },
9983
+ zIndex: 9998
9984
+ });
9684
9985
  var FEATURE_POINT_MODIFY = new Style$1({
9685
9986
  renderer: function renderer(pixelCoordinates, state) {
9686
9987
  var ctx = state.context,
@@ -10109,27 +10410,23 @@ var genericOpenLayersFeatureStyle = function genericOpenLayersFeatureStyle(featu
10109
10410
  }
10110
10411
  return undefined;
10111
10412
  }
10413
+ var isSelectedFeature = Boolean(highlightSelectedFeature || isSelected);
10414
+ var canHighlightPoint = mapFeatureClass !== MapFeatureClass.ObservationStation && mapFeatureClass !== MapFeatureClass.Plugin && selectionType !== 'fir';
10112
10415
  if (((_feature$getGeometry3 = feature.getGeometry) === null || _feature$getGeometry3 === void 0 || (_feature$getGeometry3 = _feature$getGeometry3.call(feature)) === null || _feature$getGeometry3 === void 0 ? void 0 : _feature$getGeometry3.getType()) === 'Point' && props.iconPath) {
10113
10416
  var iconStyle = customIconStyle(feature);
10417
+ var styles = [iconStyle];
10418
+ if (isSelectedFeature && canHighlightPoint) {
10419
+ styles.unshift(SELECTED_POINT_HALO_STYLE);
10420
+ }
10114
10421
  if (hoverLabelStyle) {
10115
- return [iconStyle, hoverLabelStyle];
10422
+ styles.push(hoverLabelStyle);
10116
10423
  }
10117
- return iconStyle;
10424
+ return styles.length === 1 ? iconStyle : styles;
10118
10425
  }
10119
10426
  var shouldHighlight = geometry && geometry.getType() !== 'Point' && mapFeatureClass !== MapFeatureClass.ObservationStation && mapFeatureClass !== MapFeatureClass.Plugin && selectionType !== 'fir';
10120
10427
  // Preview highlight during box-select drag
10121
10428
  if (boxSelectPreview && shouldHighlight) {
10122
- return new Style$1({
10123
- stroke: new Stroke({
10124
- color: '#006CFD',
10125
- width: 2,
10126
- lineDash: [4, 4]
10127
- }),
10128
- fill: new Fill({
10129
- color: geowebColorToOpenLayersColor(fill, 0.3)
10130
- }),
10131
- zIndex: 9997
10132
- });
10429
+ return getBoxSelectPreviewStyle(fill);
10133
10430
  }
10134
10431
  // Highlight selected features (applies to predefined areas, etc)
10135
10432
  if ((highlightSelectedFeature || isSelected) && shouldHighlight) {
@@ -10163,7 +10460,7 @@ var genericOpenLayersFeatureStyle = function genericOpenLayersFeatureStyle(featu
10163
10460
  return [].concat(_toConsumableArray(inlineFeatureStyle(feature)), [hoverLabelStyle]);
10164
10461
  }
10165
10462
  if ((!mapFeatureClass || mapFeatureClass === MapFeatureClass["default"]) && geometry && selectionType === 'point') {
10166
- return getFeaturePointStyle(fill, effectiveFillOpacity);
10463
+ return getFeaturePointStyle(fill, effectiveFillOpacity, isSelectedFeature && canHighlightPoint);
10167
10464
  }
10168
10465
  if (fill || stroke) {
10169
10466
  return inlineFeatureStyle(feature);
@@ -10792,10 +11089,12 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10792
11089
  viewOnlyStyle = _ref.viewOnlyStyle,
10793
11090
  geojson = _ref.geojson,
10794
11091
  selectedFeatureIndex = _ref.selectedFeatureIndex,
11092
+ selectedFeatureIndices = _ref.selectedFeatureIndices,
10795
11093
  exitDrawModeCallback = _ref.exitDrawModeCallback,
10796
11094
  updateGeojson = _ref.updateGeojson,
10797
11095
  onViewOnlyFeatureClick = _ref.onViewOnlyFeatureClick,
10798
- onNoFeatureClick = _ref.onNoFeatureClick;
11096
+ onNoFeatureClick = _ref.onNoFeatureClick,
11097
+ boxSelect = _ref.boxSelect;
10799
11098
  var _React$useContext = React.useContext(MapContext),
10800
11099
  map = _React$useContext.map;
10801
11100
  var projection = useProjection();
@@ -10803,10 +11102,12 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10803
11102
  var updateGeojsonRef = React.useRef(updateGeojson);
10804
11103
  var onViewOnlyFeatureClickRef = React.useRef(onViewOnlyFeatureClick);
10805
11104
  var onNoFeatureClickRef = React.useRef(onNoFeatureClick);
11105
+ var boxSelectRef = React.useRef(boxSelect);
10806
11106
  exitDrawModeCallbackRef.current = exitDrawModeCallback;
10807
11107
  updateGeojsonRef.current = updateGeojson;
10808
11108
  onViewOnlyFeatureClickRef.current = onViewOnlyFeatureClick;
10809
11109
  onNoFeatureClickRef.current = onNoFeatureClick;
11110
+ boxSelectRef.current = boxSelect;
10810
11111
  React.useEffect(function () {
10811
11112
  var _geojson$features$sel;
10812
11113
  if (!map || !isInEditMode) {
@@ -10824,10 +11125,18 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10824
11125
  var drawOperation = createDrawOperation(actualDrawMode, selectedFeature === null || selectedFeature === void 0 ? void 0 : selectedFeature.geometry.type);
10825
11126
  var drawStyle = drawStyles[actualDrawMode];
10826
11127
  var modifyStyle = modifyStyles[actualDrawMode];
10827
- var geojsonFormatter = new OlGeoJSON({
11128
+ var geojsonFormatter = new GeoJSON({
10828
11129
  featureProjection: projection
10829
11130
  });
10830
11131
  var allFeatures = geojson ? geojsonFormatter.readFeatures(geojson) : [];
11132
+ if (selectedFeatureIndices) {
11133
+ var selectedIndexSet = new Set(selectedFeatureIndices);
11134
+ allFeatures.forEach(function (feature, index) {
11135
+ var isSelected = selectedIndexSet.has(index);
11136
+ feature.set('isSelected', isSelected, true);
11137
+ feature.set('highlightSelectedFeature', isSelected, true);
11138
+ });
11139
+ }
10831
11140
  var viewOnlyFeatures = allFeatures.filter(function (_f, i) {
10832
11141
  return i !== selectedFeatureIndex;
10833
11142
  });
@@ -10844,9 +11153,16 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10844
11153
  features: editFeatureCollection
10845
11154
  });
10846
11155
  var selectedFeatureHasGeometry = selectedFeature && !isGeoJSONGeometryEmpty(selectedFeature);
11156
+ // Without this the shape being edited is the only one missing a drag box outline.
11157
+ var editStyle = function editStyle(feature, resolution) {
11158
+ if (feature.get('boxSelectPreview')) {
11159
+ return getBoxSelectPreviewStyle(feature.get('fill'));
11160
+ }
11161
+ return typeof modifyStyle === 'function' ? modifyStyle(feature, resolution) : modifyStyle;
11162
+ };
10847
11163
  var layer = new VectorLayer({
10848
11164
  source: source,
10849
- style: modifyStyle,
11165
+ style: editStyle,
10850
11166
  zIndex: 1000000
10851
11167
  });
10852
11168
  map.addLayer(layer);
@@ -10864,8 +11180,9 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10864
11180
  }
10865
11181
  });
10866
11182
  if (features.length) {
10867
- var _onViewOnlyFeatureCli;
10868
- (_onViewOnlyFeatureCli = onViewOnlyFeatureClickRef.current) === null || _onViewOnlyFeatureCli === void 0 || _onViewOnlyFeatureCli.call(onViewOnlyFeatureClickRef, features);
11183
+ var _event$originalEvent, _onViewOnlyFeatureCli;
11184
+ var isShiftClick = Boolean((_event$originalEvent = event.originalEvent) === null || _event$originalEvent === void 0 ? void 0 : _event$originalEvent.shiftKey);
11185
+ (_onViewOnlyFeatureCli = onViewOnlyFeatureClickRef.current) === null || _onViewOnlyFeatureCli === void 0 || _onViewOnlyFeatureCli.call(onViewOnlyFeatureClickRef, features, isShiftClick);
10869
11186
  } else {
10870
11187
  var _onNoFeatureClickRef$;
10871
11188
  (_onNoFeatureClickRef$ = onNoFeatureClickRef.current) === null || _onNoFeatureClickRef$ === void 0 || _onNoFeatureClickRef$.call(onNoFeatureClickRef);
@@ -10898,7 +11215,7 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
10898
11215
  return;
10899
11216
  }
10900
11217
  // GeoJsons are always treated as latlon, therefore using EPSG:4326 as transformer does not do anything except translating the object.
10901
- var geojsonFormatterNoTransform = new OlGeoJSON({
11218
+ var geojsonFormatterNoTransform = new GeoJSON({
10902
11219
  featureProjection: 'EPSG:4326'
10903
11220
  });
10904
11221
  var isLineSplit = selectedFeature.geometry.type === 'LineString';
@@ -11133,7 +11450,7 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
11133
11450
  updateFeature(evt.features.getArray()[0]);
11134
11451
  });
11135
11452
  }
11136
- var translate = new Translate({
11453
+ var translate = new Translate$1({
11137
11454
  features: editFeatureCollection
11138
11455
  });
11139
11456
  translate.on('translateend', function (evt) {
@@ -11149,6 +11466,9 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
11149
11466
  // immediately show a grabbing cursor on mousedown (before any movement).
11150
11467
  var isPointerDownNearCorner = false;
11151
11468
  var handlePointerDownNearCorner = function handlePointerDownNearCorner(event) {
11469
+ if (isBoxSelectModifier(event)) {
11470
+ return;
11471
+ }
11152
11472
  if (!isBoxOrSquare || !selectedFeatureHasGeometry) {
11153
11473
  return;
11154
11474
  }
@@ -11199,6 +11519,9 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
11199
11519
  isPointerDownNearCorner = false;
11200
11520
  };
11201
11521
  var startRotateIfOnHandle = function startRotateIfOnHandle(event) {
11522
+ if (isBoxSelectModifier(event)) {
11523
+ return;
11524
+ }
11202
11525
  if (!isBoxOrSquareRotatable || !selectedFeatureHasGeometry) {
11203
11526
  return;
11204
11527
  }
@@ -11414,14 +11737,36 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
11414
11737
  _viewport2.addEventListener('pointerup', handlePointerUpAfterCorner);
11415
11738
  }
11416
11739
  window.addEventListener('keydown', abortOnEsc);
11740
+ // Read from the prop, not the ref: `boxSelect?.active` is a dependency of this
11741
+ // effect, so toggling it adds or removes the DragBox. Only `onBoxSelect` goes
11742
+ // through the ref, to keep an inline arrow from re-running the effect.
11743
+ // Not while sketching, or the drag would both box select and dangle the sketch.
11744
+ var shouldEnableBoxSelect = (boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.active) && actualDrawMode !== DRAWMODE.SPLIT && Boolean(selectedFeatureHasGeometry);
11745
+ var disposeBoxSelect;
11746
+ if (shouldEnableBoxSelect) {
11747
+ var _createDragBoxSelect = createDragBoxSelect({
11748
+ sources: [viewOnlySource, source],
11749
+ onBoxSelect: function onBoxSelect(features, addToSelection) {
11750
+ var _boxSelectRef$current;
11751
+ return (_boxSelectRef$current = boxSelectRef.current) === null || _boxSelectRef$current === void 0 ? void 0 : _boxSelectRef$current.onBoxSelect(features, addToSelection);
11752
+ }
11753
+ }),
11754
+ dragBox = _createDragBoxSelect.dragBox,
11755
+ dispose = _createDragBoxSelect.dispose;
11756
+ // Added last so it takes priority over Translate and Modify.
11757
+ interactions.push(dragBox);
11758
+ disposeBoxSelect = dispose;
11759
+ }
11417
11760
  interactions.forEach(function (i) {
11418
11761
  return map.addInteraction(i);
11419
11762
  });
11420
11763
  return function () {
11764
+ var _disposeBoxSelect;
11421
11765
  map.getViewport().removeEventListener('dblclick', handleDoubleClickToClosePolygon);
11422
11766
  map.getViewport().removeEventListener('click', handleClickNearPolygonStartPoint);
11423
11767
  map.getViewport().removeEventListener('pointerdown', recordPointerDownPosition);
11424
11768
  window.removeEventListener('keydown', abortOnEsc);
11769
+ (_disposeBoxSelect = disposeBoxSelect) === null || _disposeBoxSelect === void 0 || _disposeBoxSelect();
11425
11770
  interactions.forEach(function (i) {
11426
11771
  return map.removeInteraction(i);
11427
11772
  });
@@ -11448,7 +11793,7 @@ var OpenLayersMapDraw = function OpenLayersMapDraw(_ref) {
11448
11793
  // re-run when parents pass inline arrows. Re-running mid-sketch would
11449
11794
  // tear down the Draw interaction and lose the in-progress polygon.
11450
11795
  // eslint-disable-next-line react-hooks/exhaustive-deps
11451
- }, [map, isInEditMode, geojson, projection, viewOnlyStyle, selectedFeatureIndex, drawMode]);
11796
+ }, [map, isInEditMode, geojson, projection, viewOnlyStyle, selectedFeatureIndex, selectedFeatureIndices, boxSelect === null || boxSelect === void 0 ? void 0 : boxSelect.active, drawMode]);
11452
11797
  return null;
11453
11798
  };
11454
11799
 
@@ -13067,6 +13412,51 @@ var endToolExampleConfig = {
13067
13412
  }
13068
13413
  };
13069
13414
 
13415
+ /* *
13416
+ * Licensed under the Apache License, Version 2.0 (the "License");
13417
+ * you may not use this file except in compliance with the License.
13418
+ * You may obtain a copy of the License at
13419
+ *
13420
+ * http://www.apache.org/licenses/LICENSE-2.0
13421
+ *
13422
+ * Unless required by applicable law or agreed to in writing, software
13423
+ * distributed under the License is distributed on an "AS IS" BASIS,
13424
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13425
+ * See the License for the specific language governing permissions and
13426
+ * limitations under the License.
13427
+ *
13428
+ * Copyright 2026 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
13429
+ * Copyright 2026 - Finnish Meteorological Institute (FMI)
13430
+ * Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
13431
+ * */
13432
+ var calculateNewSelection = function calculateNewSelection(currentSelectedIndices, clickedIndex, isShiftClick) {
13433
+ if (isShiftClick) {
13434
+ if (currentSelectedIndices.includes(clickedIndex)) {
13435
+ return currentSelectedIndices.filter(function (i) {
13436
+ return i !== clickedIndex;
13437
+ });
13438
+ }
13439
+ return [].concat(_toConsumableArray(currentSelectedIndices), [clickedIndex]);
13440
+ }
13441
+ var isSoleSelection = currentSelectedIndices.length === 1 && currentSelectedIndices[0] === clickedIndex;
13442
+ return isSoleSelection ? [] : [clickedIndex];
13443
+ };
13444
+ var getAffectedIndices = function getAffectedIndices(oldSelection, newSelection) {
13445
+ var allIndices = new Set([].concat(_toConsumableArray(oldSelection), _toConsumableArray(newSelection)));
13446
+ return Array.from(allIndices).filter(function (idx) {
13447
+ return oldSelection.includes(idx) !== newSelection.includes(idx);
13448
+ });
13449
+ };
13450
+ var shouldEnterEditMode = function shouldEnterEditMode(isReadonly, isShiftClick, newSelectionCount) {
13451
+ return !isReadonly && !isShiftClick && newSelectionCount === 1;
13452
+ };
13453
+ var shouldExitEditModeForMultiSelect = function shouldExitEditModeForMultiSelect(newSelectionCount) {
13454
+ return newSelectionCount > 1;
13455
+ };
13456
+ var calculateBoxSelection = function calculateBoxSelection(currentSelectedIndices, boxSelectedIndices, addToSelection) {
13457
+ return addToSelection ? Array.from(new Set([].concat(_toConsumableArray(currentSelectedIndices), _toConsumableArray(boxSelectedIndices)))) : boxSelectedIndices;
13458
+ };
13459
+
13070
13460
  var ClickOnMapTool = function ClickOnMapTool(_ref) {
13071
13461
  var isActive = _ref.isActive,
13072
13462
  isVisible = _ref.isVisible,
@@ -13756,4 +14146,4 @@ var getLayerUpdateInfo = function getLayerUpdateInfo(wmLayer, mapId) {
13756
14146
  return updateObject;
13757
14147
  };
13758
14148
 
13759
- export { BaseLayerType, CLASSNAME_MAP_MEASURE_TOOLTIP, ClickOnMapTool, Clock, DEFAULT_GEOJSON_STYLE_FILL_OPACITY, DRAWMODE, DefaultBaseLayers, DimensionSelectButton, DimensionSelectDialog, DimensionSelectSlider, EditModeButton as EditModeButtonField, FEATURE_DRAW_FILL_COLOR, FEATURE_DRAW_FILL_COLOR_TRANSPARENT, FEATURE_DRAW_SECONDARY_FILL_COLOR, FEATURE_DRAW_SECONDARY_STROKE_COLOR, FEATURE_DRAW_STROKE_COLOR, FEATURE_FILL, FEATURE_FILL_SELECTED, FEATURE_STROKE, FEATURE_STROKE_EDIT, FEATURE_STROKE_SELECTED, FEATURE_VERTICES_EDIT_HANDLES, FEATURE_VERTICE_HANDLE_IMAGE, FEATURE_VERTICE_IMAGE, FeatureLayer, FeatureLayers, GeoJSONTextField, IntersectionSelect, LayerInfoButton, LayerInfoDialog, LayerInfoLegend, LayerInfoList, LayerInfoText, Legend, LegendButton, LegendDialog, LegendLayout, MIN_HEIGHT, MIN_WIDTH, MapContext, MapControlButton, MapControls, MapDimensionSelect, MapFeatureClass, MapMeasure, MapTime, MapWarningProperties, NEW_FEATURE_CREATED, NEW_LINESTRING_CREATED, NEW_POINT_CREATED, OpenLayersFeatureLayer, OpenLayersGetFeatureInfo, OpenLayersLayer, OpenLayersMapDraw, OpenLayersMapView, OpenLayersZoomControl, POINTER_CLICK_TOLERANCE_PX, STAC_ASSET_STYLE_PREFIX, STAC_ITEM_PAGE_LIMIT, STAC_ITEM_SEARCH_FIELDS_CONFORMANCE, STAC_TEMPORAL_STEP_SAMPLE_LIMIT, SelectField, StoryLayoutGrid, TimeAwareEDRLocationLayer, TimeAwareGeoTIFFLayer, TimeAwareWMTSLayer, TimeContext, TimeawareImageSource, TimeawareImageSourceWMSLayer, WEBMAP_REACT_NAMESPACE, WMSLayer, WMTSLayer, XYZLayer, ZoomControls, addFeatureProperties, addGeoJSONProperties, addSelectionTypeToGeoJSON, asNewFeature, basicExampleDrawOptions, basicExampleMultipleShapeDrawOptions, basicExampleMultipleShapeWithValuesDrawOptions, catmullRomSpline, clearImageCacheForAllMaps, colorMaps, createBoxBasedOnModifiedVertex, createIconStyle, createInterSections, createOval, currentlySupportedDrawModes, defaultBox, defaultCircle, defaultDelete, defaultEdrStyles, defaultFreehandLine, defaultGeoJSONStyleProperties, defaultIntersectionStyleProperties, defaultLayers, defaultLineString, defaultLocation, defaultModes, defaultOval, defaultPoint, defaultPolygon, defaultRotatableBox, defaultSmoothLine, defaultSplit, defaultSquare, defaultTimeFormat, dimensionConfig, drawPolyStoryStyles, drawStyles, emptyGeoJSON, endToolExampleConfig, exampleIntersectionOptions, exampleIntersectionWithShapeOptions, exampleIntersections, exampleIntersectionsMultiDrawTool, featureMultiPoint, featurePoint, featurePolygon, fetchStacCatalogCollections, fetchStacCatalogRoot, fetchStacCollection, fetchStacItem, fetchStacItems, fetchStacItemsPage, fetchStacItemsWithPagination, fillOptions, firSelectionType, formatTime, generateImageFromLegend, genericOpenLayersFeatureStyle, geowebColorToOpenLayersColor, getBoxRotateHandlePoints, getDimensionIcon, getDimensionLabel, getDimensionValue, getDimensionsList, getDoubleControlToolIcon, getDrawModeIdFromSelectionType, getFeatureCollection, getFeatureExtent, getFeaturePointStyle, getFirTitle, getGeoJSONPropertyValue, getGeoJson, getIcon, getIntersectionToolIcon, getIsInsideAcceptanceTime, getLastEmptyFeatureIndex, getLayerBbox, getLayerStyles, getLayerUpdateInfo, getLegendClass, getProj4, getRendersAsStyles, getStacAssetKeyFromStyle, getStacAssetStyles, getStacCollectionStyles, getStacFrameItemsToRender, getStacItemLookupWindowForTimes, getStacItemSearchUrl, getStacItemsUrl, getTimeDimension, getToolIcon, initializeOpenLayersProjections, inlineFeatureStyle, intersectPointGeoJSONS, intersectPolygonGeoJSONS, intersectionFeatureBE, intersectionFeatureNL, isBrowserReadableGeoTIFFAsset, isClickFromDrag, isGeoJSONFeatureCreatedByTool, isGeoJSONGeometryEmpty, isGeoTIFFAsset, isPointFeatureCollection, keepIdentityOnFirstSplitFeature, labelOptions, lineString, lineStringCollection, makeFeatureStyleDisc, makeFeatureStyleLoading, makeFeatureStyleMultiParam, makeFeatureStyleMultiParamLoading, makeFeatureStyleWind, makeLegendFromColorMap, makeLegendFromStyleName, makeTimeList, makeView, marksByDimension, measureResultStyle, measureToolStyle, modifyStyles, moveFeature, multiLineStringLabelStyle, multiPolygonLabelStyle, opacityOptions, openLayersGetMapImageStore, polygonCleanDangling, polygonCleanDanglingCoords, polygonFeatureCollectionCleanDangling, precipitationMMLegendColorsWoW, projectorCache, publicLayers, publicServices, removeOverlappingLines, resolvePreferredStyleName$1 as resolvePreferredStyleName, resolveStacAssetKey, rewindGeometry, roundCoordinates, roundFeatureCoordinates, selectPreferredWMSProjection, setMapCenter, setViewFromExtent, setViewFromFeature, simpleBoxGeoJSON, simpleBoxGeoJSONWrongOrder, simpleFlightRouteLineStringGeoJSON, simpleFlightRoutePointsGeoJSON, simpleGeometryCollectionGeoJSON, simpleLineStringGeoJSON, simpleMultiPolygon, simplePointsGeojson, simplePolygonGeoJSON, simpleSmallLineStringGeoJSON, splitLine, splitPolygon, splitStyle, stacCatalogCollectionToLayerProps, stacColormapToOlStyle, stacGrayscaleOlStyle, stacNormalizedGrayscaleOlStyle, startToolExampleConfig, strokeWidthOptions, styleNameToStyleLike, temperatureLegendColorsCWK, temperatureLegendColorsWoW, textLabelStyle, textStyle, textStyleWithMargin, updateEditModeButtonsWithFir, useAnimationForLayer, useEDRGetCollectionDetails, useEDRGetParameterData, useEDRWMLayer, useGeoJSON, useGetWMLayerInstance, useGetWMSLayerStyleList, useIconStyle, useMapDrawTool, useProjection, useQueryGetWMSGetCapabilities, useQueryGetWMSLayer, useQueryGetWMSLayers, useQueryGetWMSLayersTree, useQueryGetWMSServiceInfo, useQueryWMTSGetCapabilities, useSetIntervalWhenVisible, useStacCatalogRoot, useStacCollection, useStacItems, useStacOverviewItems, useStacTemporalStepItems, useViewFromLayer, viewUtils, webmapEDRQueryOptions, webmapReactTranslations };
14149
+ export { BaseLayerType, CLASSNAME_MAP_MEASURE_TOOLTIP, ClickOnMapTool, Clock, DEFAULT_GEOJSON_STYLE_FILL_OPACITY, DRAWMODE, DefaultBaseLayers, DimensionSelectButton, DimensionSelectDialog, DimensionSelectSlider, EditModeButton as EditModeButtonField, FEATURE_DRAW_FILL_COLOR, FEATURE_DRAW_FILL_COLOR_TRANSPARENT, FEATURE_DRAW_SECONDARY_FILL_COLOR, FEATURE_DRAW_SECONDARY_STROKE_COLOR, FEATURE_DRAW_STROKE_COLOR, FEATURE_FILL, FEATURE_FILL_SELECTED, FEATURE_STROKE, FEATURE_STROKE_EDIT, FEATURE_STROKE_SELECTED, FEATURE_VERTICES_EDIT_HANDLES, FEATURE_VERTICE_HANDLE_IMAGE, FEATURE_VERTICE_IMAGE, FeatureLayer, FeatureLayers, GeoJSONTextField, IntersectionSelect, LayerInfoButton, LayerInfoDialog, LayerInfoLegend, LayerInfoList, LayerInfoText, Legend, LegendButton, LegendDialog, LegendLayout, MIN_HEIGHT, MIN_WIDTH, MapContext, MapControlButton, MapControls, MapDimensionSelect, MapFeatureClass, MapMeasure, MapTime, MapWarningProperties, NEW_FEATURE_CREATED, NEW_LINESTRING_CREATED, NEW_POINT_CREATED, OpenLayersFeatureLayer, OpenLayersGetFeatureInfo, OpenLayersLayer, OpenLayersMapDraw, OpenLayersMapView, OpenLayersZoomControl, POINTER_CLICK_TOLERANCE_PX, SELECTED_FEATURE_COLOR, SELECTED_POINT_HALO_STYLE, STAC_ASSET_STYLE_PREFIX, STAC_ITEM_PAGE_LIMIT, STAC_ITEM_SEARCH_FIELDS_CONFORMANCE, STAC_TEMPORAL_STEP_SAMPLE_LIMIT, SelectField, StoryLayoutGrid, TimeAwareEDRLocationLayer, TimeAwareGeoTIFFLayer, TimeAwareWMTSLayer, TimeContext, TimeawareImageSource, TimeawareImageSourceWMSLayer, WEBMAP_REACT_NAMESPACE, WMSLayer, WMTSLayer, XYZLayer, ZoomControls, addFeatureProperties, addGeoJSONProperties, addSelectionTypeToGeoJSON, asNewFeature, basicExampleDrawOptions, basicExampleMultipleShapeDrawOptions, basicExampleMultipleShapeWithValuesDrawOptions, calculateBoxSelection, calculateNewSelection, catmullRomSpline, clearImageCacheForAllMaps, colorMaps, createBoxBasedOnModifiedVertex, createIconStyle, createInterSections, createMoveFeatures, createOval, currentlySupportedDrawModes, defaultBox, defaultCircle, defaultDelete, defaultEdrStyles, defaultFreehandLine, defaultGeoJSONStyleProperties, defaultIntersectionStyleProperties, defaultLayers, defaultLineString, defaultLocation, defaultModes, defaultOval, defaultPoint, defaultPolygon, defaultRotatableBox, defaultSmoothLine, defaultSplit, defaultSquare, defaultTimeFormat, dimensionConfig, drawPolyStoryStyles, drawStyles, emptyGeoJSON, endToolExampleConfig, exampleIntersectionOptions, exampleIntersectionWithShapeOptions, exampleIntersections, exampleIntersectionsMultiDrawTool, featureMultiPoint, featurePoint, featurePolygon, fetchStacCatalogCollections, fetchStacCatalogRoot, fetchStacCollection, fetchStacItem, fetchStacItems, fetchStacItemsPage, fetchStacItemsWithPagination, fillOptions, firSelectionType, formatTime, generateImageFromLegend, genericOpenLayersFeatureStyle, geowebColorToOpenLayersColor, getAffectedIndices, getBoxRotateHandlePoints, getBoxSelectPreviewStyle, getDimensionIcon, getDimensionLabel, getDimensionValue, getDimensionsList, getDoubleControlToolIcon, getDrawModeIdFromSelectionType, getFeatureCollection, getFeatureExtent, getFeaturePointStyle, getFirTitle, getGeoJSONPropertyValue, getGeoJson, getIcon, getIntersectionToolIcon, getIsInsideAcceptanceTime, getLastEmptyFeatureIndex, getLayerBbox, getLayerExtentForProjection, getLayerStyles, getLayerUpdateInfo, getLegendClass, getOlFeatureKey, getProj4, getRendersAsStyles, getStacAssetKeyFromStyle, getStacAssetStyles, getStacCollectionStyles, getStacFrameItemsToRender, getStacItemLookupWindowForTimes, getStacItemSearchUrl, getStacItemsUrl, getTimeDimension, getToolIcon, initializeOpenLayersProjections, inlineFeatureStyle, intersectPointGeoJSONS, intersectPolygonGeoJSONS, intersectionFeatureBE, intersectionFeatureNL, isBrowserReadableGeoTIFFAsset, isClickFromDrag, isDefaultMovable, isGeoJSONFeatureCreatedByTool, isGeoJSONGeometryEmpty, isGeoTIFFAsset, isPointFeatureCollection, keepIdentityOnFirstSplitFeature, labelOptions, lineString, lineStringCollection, makeFeatureStyleDisc, makeFeatureStyleLoading, makeFeatureStyleMultiParam, makeFeatureStyleMultiParamLoading, makeFeatureStyleWind, makeLegendFromColorMap, makeLegendFromStyleName, makeTimeList, makeView, marksByDimension, measureResultStyle, measureToolStyle, modifyStyles, moveFeature, multiLineStringLabelStyle, multiPolygonLabelStyle, opacityOptions, openLayersGetMapImageStore, polygonCleanDangling, polygonCleanDanglingCoords, polygonFeatureCollectionCleanDangling, precipitationMMLegendColorsWoW, projectorCache, publicLayers, publicServices, removeOverlappingLines, resolvePreferredStyleName$1 as resolvePreferredStyleName, resolveStacAssetKey, rewindGeometry, roundCoordinates, roundFeatureCoordinates, selectPreferredWMSProjection, setMapCenter, setViewFromExtent, setViewFromFeature, shouldEnterEditMode, shouldExitEditModeForMultiSelect, simpleBoxGeoJSON, simpleBoxGeoJSONWrongOrder, simpleFlightRouteLineStringGeoJSON, simpleFlightRoutePointsGeoJSON, simpleGeometryCollectionGeoJSON, simpleLineStringGeoJSON, simpleMultiPolygon, simplePointsGeojson, simplePolygonGeoJSON, simpleSmallLineStringGeoJSON, splitLine, splitPolygon, splitStyle, stacCatalogCollectionToLayerProps, stacColormapToOlStyle, stacGrayscaleOlStyle, stacNormalizedGrayscaleOlStyle, startToolExampleConfig, strokeWidthOptions, styleNameToStyleLike, temperatureLegendColorsCWK, temperatureLegendColorsWoW, textLabelStyle, textStyle, textStyleWithMargin, updateEditModeButtonsWithFir, useAnimationForLayer, useEDRGetCollectionDetails, useEDRGetParameterData, useEDRWMLayer, useGeoJSON, useGetWMLayerInstance, useGetWMSLayerStyleList, useIconStyle, useMapDrawTool, useMoveFeatures, useProjection, useQueryGetWMSGetCapabilities, useQueryGetWMSLayer, useQueryGetWMSLayers, useQueryGetWMSLayersTree, useQueryGetWMSServiceInfo, useQueryWMTSGetCapabilities, useSetIntervalWhenVisible, useStacCatalogRoot, useStacCollection, useStacItems, useStacOverviewItems, useStacTemporalStepItems, useViewFromLayer, viewUtils, webmapEDRQueryOptions, webmapReactTranslations };
@@ -24,7 +24,10 @@ export declare const FEATURE_STROKE_SELECTED: Stroke;
24
24
  export declare const FEATURE_VERTICE_IMAGE: Circle;
25
25
  export declare const FEATURE_VERTICE_HANDLE_IMAGE: Circle;
26
26
  export declare const FEATURE_VERTICES_EDIT_HANDLES: Style;
27
- export declare const getFeaturePointStyle: (fillColor?: string, fillOpacity?: number) => Style;
27
+ export declare const SELECTED_FEATURE_COLOR = "#006CFD";
28
+ export declare const getBoxSelectPreviewStyle: (fill?: string) => Style;
29
+ export declare const getFeaturePointStyle: (fillColor?: string, fillOpacity?: number, isSelected?: boolean) => Style;
30
+ export declare const SELECTED_POINT_HALO_STYLE: Style;
28
31
  export declare const labelOptions: {
29
32
  font: string;
30
33
  padding: number[];
@@ -3,6 +3,7 @@ import type { Geometry } from 'ol/geom';
3
3
  import type { StyleLike } from 'ol/style/Style';
4
4
  import React from 'react';
5
5
  import type { DrawModeExitCallback, DrawModeValue } from './types';
6
+ import type { BoxSelect } from '../utils/types';
6
7
  export interface OpenLayersMapDrawProps {
7
8
  geojson: GeoJSON.FeatureCollection;
8
9
  drawMode?: DrawModeValue;
@@ -10,9 +11,12 @@ export interface OpenLayersMapDrawProps {
10
11
  exitDrawModeCallback?: (reason: DrawModeExitCallback) => void;
11
12
  isInEditMode: boolean;
12
13
  selectedFeatureIndex: number;
14
+ /** Highlight-only. The edit target stays `selectedFeatureIndex`. */
15
+ selectedFeatureIndices?: number[];
13
16
  updateGeojson?: (geoJson: GeoJSON.FeatureCollection, text: string) => void;
14
- onViewOnlyFeatureClick?: (feature: Feature<Geometry>[]) => void;
17
+ onViewOnlyFeatureClick?: (feature: Feature<Geometry>[], isShiftClick?: boolean) => void;
15
18
  onNoFeatureClick?: () => void;
19
+ boxSelect?: BoxSelect;
16
20
  }
17
21
  /**
18
22
  * Integrates with OpenLayers Draw and Modify (+Snap) interactions, to implement feature drawing
@@ -10,3 +10,4 @@ export * from './geojsonShapes';
10
10
  export * from './mapDrawUtils';
11
11
  export * from './storyComponents';
12
12
  export * from './polygonCleanDangling';
13
+ export * from './selectionUtils';
@@ -0,0 +1,5 @@
1
+ export declare const calculateNewSelection: (currentSelectedIndices: number[], clickedIndex: number, isShiftClick: boolean) => number[];
2
+ export declare const getAffectedIndices: (oldSelection: number[], newSelection: number[]) => number[];
3
+ export declare const shouldEnterEditMode: (isReadonly: boolean, isShiftClick: boolean, newSelectionCount: number) => boolean;
4
+ export declare const shouldExitEditModeForMultiSelect: (newSelectionCount: number) => boolean;
5
+ export declare const calculateBoxSelection: (currentSelectedIndices: number[], boxSelectedIndices: number[], addToSelection: boolean) => number[];
@@ -2,6 +2,7 @@ export { default as MapContext } from './context/MapContext';
2
2
  export * from './component/OpenLayersMapView';
3
3
  export * from './utils/TimeAwareImageWrapper';
4
4
  export type * from './utils/types';
5
+ export * from './utils/moveFeatures';
5
6
  export * from './utils/projections';
6
7
  export * from './utils/setMapCenter';
7
8
  export * from './utils/viewUtils';
@@ -1,6 +1,7 @@
1
1
  import type { Feature } from 'ol';
2
2
  import type { StyleLike } from 'ol/style/Style';
3
- import type { BoxSelect, ClickOnFeature, HoverSelect } from '../utils/types';
3
+ import React from 'react';
4
+ import type { BoxSelect, ClickOnFeature, HoverSelect, MoveFeatures } from '../utils/types';
4
5
  export interface FeatureLayerProps {
5
6
  features: Feature[];
6
7
  style: StyleLike;
@@ -8,6 +9,7 @@ export interface FeatureLayerProps {
8
9
  hoverSelect?: HoverSelect;
9
10
  clickOnFeature?: ClickOnFeature;
10
11
  boxSelect?: BoxSelect;
12
+ moveFeatures?: MoveFeatures;
11
13
  layerId?: string;
12
14
  testId?: string;
13
15
  opacity?: number;
@@ -1,6 +1,6 @@
1
1
  import type { FeatureCollection } from 'geojson';
2
2
  import type { StyleLike } from 'ol/style/Style';
3
- import type { BoxSelect, ClickOnFeature, HoverSelect } from '../utils/types';
3
+ import type { BoxSelect, ClickOnFeature, HoverSelect, MoveFeaturesGeoJSON } from '../utils/types';
4
4
  export interface OpenLayersFeatureLayerProps {
5
5
  featureCollection?: FeatureCollection;
6
6
  style?: StyleLike;
@@ -8,6 +8,7 @@ export interface OpenLayersFeatureLayerProps {
8
8
  hoverSelect?: HoverSelect;
9
9
  clickOnFeature?: ClickOnFeature;
10
10
  boxSelect?: BoxSelect;
11
+ moveFeatures?: MoveFeaturesGeoJSON;
11
12
  layerId?: string;
12
13
  testId?: string;
13
14
  opacity?: number;
@@ -0,0 +1,25 @@
1
+ import type { Feature, Map } from 'ol';
2
+ import DragBox from 'ol/interaction/DragBox';
3
+ import type VectorSource from 'ol/source/Vector';
4
+ export declare const isBoxSelectModifier: (event: {
5
+ altKey: boolean;
6
+ ctrlKey: boolean;
7
+ metaKey: boolean;
8
+ shiftKey: boolean;
9
+ }) => boolean;
10
+ export interface CreateDragBoxSelectOptions {
11
+ sources: VectorSource[];
12
+ onBoxSelect: (features: Feature[], addToSelection: boolean) => void;
13
+ }
14
+ export interface DragBoxSelect {
15
+ dragBox: DragBox;
16
+ dispose: () => void;
17
+ }
18
+ export declare const createDragBoxSelect: ({ sources, onBoxSelect, }: CreateDragBoxSelectOptions) => DragBoxSelect;
19
+ export interface UseDragBoxSelectOptions {
20
+ map?: Map | null;
21
+ source?: VectorSource;
22
+ active: boolean;
23
+ onBoxSelect?: (features: Feature[], addToSelection: boolean) => void;
24
+ }
25
+ export declare const useDragBoxSelect: ({ map, source, active, onBoxSelect, }: UseDragBoxSelectOptions) => void;
@@ -0,0 +1,24 @@
1
+ import type { Feature, Map } from 'ol';
2
+ import Translate from 'ol/interaction/Translate';
3
+ export declare const getOlFeatureKey: (feature?: Feature) => string | undefined;
4
+ export declare const isDefaultMovable: (feature: Feature) => boolean;
5
+ export interface CreateMoveFeaturesOptions {
6
+ features: Feature[];
7
+ isMovable: (feature: Feature) => boolean;
8
+ onMoveEnd: (features: Feature[]) => void;
9
+ onMoveStart?: () => void;
10
+ }
11
+ export interface MoveFeaturesInteraction {
12
+ translate: Translate;
13
+ dispose: () => void;
14
+ }
15
+ export declare const createMoveFeatures: ({ features, isMovable, onMoveEnd, onMoveStart, }: CreateMoveFeaturesOptions) => MoveFeaturesInteraction | undefined;
16
+ export interface UseMoveFeaturesOptions {
17
+ map?: Map | null;
18
+ features: Feature[];
19
+ active: boolean;
20
+ isMovable?: (feature: Feature) => boolean;
21
+ onMoveEnd?: (features: Feature[]) => void;
22
+ onMoveStart?: () => void;
23
+ }
24
+ export declare const useMoveFeatures: ({ map, features, active, isMovable, onMoveEnd, onMoveStart, }: UseMoveFeaturesOptions) => void;
@@ -13,6 +13,19 @@ export interface BoxSelect {
13
13
  onBoxSelect: (features: Feature[], addToSelection: boolean) => void;
14
14
  active: boolean;
15
15
  }
16
+ export interface MovedFeature {
17
+ featureId: string;
18
+ geometry: GeoJSON.Geometry;
19
+ }
20
+ export interface MoveFeatures {
21
+ onMoveEnd: (features: Feature[]) => void;
22
+ isMovable?: (feature: Feature) => boolean;
23
+ active: boolean;
24
+ }
25
+ export interface MoveFeaturesGeoJSON {
26
+ onMoveEnd: (movedFeatures: MovedFeature[]) => void;
27
+ active: boolean;
28
+ }
16
29
  export interface OnInitializeLayerProps {
17
30
  layerId: string;
18
31
  style: string;
@@ -1,6 +1,9 @@
1
1
  import { View } from 'ol';
2
+ import type { Extent } from 'ol/extent';
3
+ import type { WMLayer } from '@opengeoweb/webmap';
2
4
  import type { OpenLayersLayerProps } from '../components/OpenLayers/layers';
3
- export declare const useViewFromLayer: (layerProps: OpenLayersLayerProps, baseView?: {
5
+ export declare const getLayerExtentForProjection: (wmLayer: WMLayer, projectionCode: string) => Extent | undefined;
6
+ export declare const useViewFromLayer: (layerProps: OpenLayersLayerProps | undefined, baseView?: {
4
7
  projection: string;
5
8
  zoom: number;
6
9
  center: number[];
package/package.json CHANGED
@@ -1,51 +1,51 @@
1
1
  {
2
- "name": "@opengeoweb/webmap-react",
3
- "version": "19.6.0",
4
- "description": "GeoWeb react wrapper for webmap",
5
- "license": "Apache-2.0",
6
- "repository": {
7
- "type": "git",
8
- "url": "git@gitlab.com:opengeoweb/opengeoweb.git"
9
- },
10
- "main": "./dist/index.esm.js",
11
- "module": "./dist/index.esm.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- "./package.json": "./package.json",
15
- ".": {
16
- "@opengeoweb/source": "./src/index.ts",
17
- "types": "./dist/index.d.ts",
18
- "import": "./dist/index.esm.js",
19
- "default": "./dist/index.esm.js"
20
- }
21
- },
22
- "dependencies": {
23
- "@opengeoweb/webmap": "*",
24
- "@opengeoweb/theme": "*",
25
- "@opengeoweb/shared": "*",
26
- "lodash": "^4.18.1",
27
- "ol": "^10.4.0",
28
- "proj4": "^2.9.2",
29
- "@turf/turf": "^7.1.0",
30
- "immer": "^10.0.3",
31
- "i18next": "^25.0.1",
32
- "@mui/material": "^9.0.1",
33
- "react-i18next": "^15.1.1",
34
- "@tanstack/react-query": "^5.85.5",
35
- "@types/geojson": "^7946.0.14"
36
- },
37
- "peerDependencies": {
38
- "react": "19",
39
- "@emotion/react": "*",
40
- "@emotion/styled": "*"
41
- },
42
- "devDependencies": {
43
- "eslint-plugin-storybook": "10.3.3"
44
- },
45
- "files": [
46
- "dist",
47
- "!dist/package.json",
48
- "README.md",
49
- "package.json"
50
- ]
51
- }
2
+ "name": "@opengeoweb/webmap-react",
3
+ "version": "19.6.1-nightly-20260913",
4
+ "description": "GeoWeb react wrapper for webmap",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git@gitlab.com:opengeoweb/opengeoweb.git"
9
+ },
10
+ "main": "./dist/index.esm.js",
11
+ "module": "./dist/index.esm.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ "./package.json": "./package.json",
15
+ ".": {
16
+ "@opengeoweb/source": "./src/index.ts",
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.esm.js",
19
+ "default": "./dist/index.esm.js"
20
+ }
21
+ },
22
+ "dependencies": {
23
+ "@opengeoweb/webmap": "19.6.1-nightly-20260913",
24
+ "@opengeoweb/theme": "19.6.1-nightly-20260913",
25
+ "@opengeoweb/shared": "19.6.1-nightly-20260913",
26
+ "lodash": "^4.18.1",
27
+ "ol": "^10.4.0",
28
+ "proj4": "^2.9.2",
29
+ "@turf/turf": "^7.1.0",
30
+ "immer": "^10.0.3",
31
+ "i18next": "^25.0.1",
32
+ "@mui/material": "^9.0.1",
33
+ "react-i18next": "^15.1.1",
34
+ "@tanstack/react-query": "^5.85.5",
35
+ "@types/geojson": "^7946.0.14"
36
+ },
37
+ "peerDependencies": {
38
+ "react": "19",
39
+ "@emotion/react": "*",
40
+ "@emotion/styled": "*"
41
+ },
42
+ "devDependencies": {
43
+ "eslint-plugin-storybook": "10.3.3"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "!dist/package.json",
48
+ "README.md",
49
+ "package.json"
50
+ ]
51
+ }