@opengeoweb/core 20.1.0 → 20.2.0-nightly-20261021

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
@@ -7530,6 +7530,31 @@ var LocationSearch = function LocationSearch(_ref) {
7530
7530
  document.removeEventListener('keydown', handleKeyDown);
7531
7531
  };
7532
7532
  }, [dropdownOpen, isOpen]);
7533
+ // Always pass groupBy/renderGroup, and only group when the input is empty.
7534
+ // MUI keeps rendering the last open options while the popup closes, so
7535
+ // toggling groupBy in between makes it read flat options as groups and crash.
7536
+ var groupProps = {
7537
+ groupBy: function groupBy(option) {
7538
+ return debouncedInputValue.trim() === '' && 'groupHeader' in option && typeof option.groupHeader === 'string' ? option.groupHeader : '';
7539
+ },
7540
+ renderGroup: function renderGroup(params) {
7541
+ return jsxs(React.Fragment, {
7542
+ children: [params.group ? jsx(ListSubheader, {
7543
+ disableSticky: true,
7544
+ sx: {
7545
+ color: theme.palette.primary.main,
7546
+ fontWeight: 400,
7547
+ fontSize: '16px',
7548
+ py: 1,
7549
+ my: 0,
7550
+ minHeight: '26px',
7551
+ lineHeight: 1
7552
+ },
7553
+ children: params.group
7554
+ }) : null, Array.isArray(params.children) ? params.children : [params.children]]
7555
+ }, params.key);
7556
+ }
7557
+ };
7533
7558
  return isOpen && mapId ? jsxs(Box, {
7534
7559
  sx: {
7535
7560
  display: 'flex',
@@ -7593,28 +7618,7 @@ var LocationSearch = function LocationSearch(_ref) {
7593
7618
  paddingTop: '20px'
7594
7619
  }
7595
7620
  }
7596
- }, debouncedInputValue.trim() === '' ? {
7597
- groupBy: function groupBy(option) {
7598
- return 'groupHeader' in option && typeof option.groupHeader === 'string' ? option.groupHeader : '';
7599
- },
7600
- renderGroup: function renderGroup(params) {
7601
- return jsxs(React.Fragment, {
7602
- children: [jsx(ListSubheader, {
7603
- disableSticky: true,
7604
- sx: {
7605
- color: theme.palette.primary.main,
7606
- fontWeight: 400,
7607
- fontSize: '16px',
7608
- py: 1,
7609
- my: 0,
7610
- minHeight: '26px',
7611
- lineHeight: 1
7612
- },
7613
- children: params.group
7614
- }), Array.isArray(params.children) ? params.children : [params.children]]
7615
- }, params.key);
7616
- }
7617
- } : {}, {
7621
+ }, groupProps, {
7618
7622
  /* eslint-disable @typescript-eslint/no-explicit-any */
7619
7623
  clearIcon: null,
7620
7624
  inputValue: inputValue,
@@ -8359,18 +8363,35 @@ var OlMapViewLayerConnect = function OlMapViewLayerConnect(layerProps) {
8359
8363
  }), "layer-" + (layer == null ? void 0 : layer.id));
8360
8364
  };
8361
8365
 
8366
+ // OpenLayers counterpart of layerUtils.isHiddenFeature
8367
+ var isHiddenOlFeature = function isHiddenOlFeature(feature) {
8368
+ return feature.get('isHidden') === true;
8369
+ };
8370
+ var hideHiddenFeatures = function hideHiddenFeatures(style) {
8371
+ return function (feature, resolution) {
8372
+ if (isHiddenOlFeature(feature)) {
8373
+ return undefined;
8374
+ }
8375
+ return typeof style === 'function' ? style(feature, resolution) : style;
8376
+ };
8377
+ };
8362
8378
  /** Escape drops a multi selection only. A sole selection is kept, matching the
8363
- * plain click behaviour, and edit mode keeps its own Escape handling. */
8364
- var shouldDeselectAllOnEscape = function shouldDeselectAllOnEscape(selectedFeatureCount, isInEditMode, hasRegisteredDrawTool) {
8365
- return hasRegisteredDrawTool && !isInEditMode && selectedFeatureCount > 1;
8379
+ * plain click behaviour, unless the drawing tool is open. Edit mode keeps the
8380
+ * map's own Escape handling, after which onDrawEscape drops the selection. */
8381
+ var shouldDeselectAllOnEscape = function shouldDeselectAllOnEscape(selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, isDrawToolOpen) {
8382
+ if (isDrawToolOpen === void 0) {
8383
+ isDrawToolOpen = false;
8384
+ }
8385
+ return hasRegisteredDrawTool && !isInEditMode && selectedFeatureCount > (isDrawToolOpen ? 0 : 1);
8366
8386
  };
8367
8387
  var useDeselectAllOnEscape = function useDeselectAllOnEscape(_ref) {
8368
8388
  var selectedFeatureCount = _ref.selectedFeatureCount,
8369
8389
  isInEditMode = _ref.isInEditMode,
8370
8390
  hasRegisteredDrawTool = _ref.hasRegisteredDrawTool,
8391
+ isDrawToolOpen = _ref.isDrawToolOpen,
8371
8392
  onDeselectAll = _ref.onDeselectAll;
8372
8393
  React.useEffect(function () {
8373
- if (!shouldDeselectAllOnEscape(selectedFeatureCount, isInEditMode, hasRegisteredDrawTool)) {
8394
+ if (!shouldDeselectAllOnEscape(selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, isDrawToolOpen)) {
8374
8395
  return undefined;
8375
8396
  }
8376
8397
  var onKeyDown = function onKeyDown(event) {
@@ -8383,7 +8404,7 @@ var useDeselectAllOnEscape = function useDeselectAllOnEscape(_ref) {
8383
8404
  return function () {
8384
8405
  return window.removeEventListener('keydown', onKeyDown);
8385
8406
  };
8386
- }, [selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, onDeselectAll]);
8407
+ }, [selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, isDrawToolOpen, onDeselectAll]);
8387
8408
  };
8388
8409
  var shouldClearSelectionOnEmptyClick = function shouldClearSelectionOnEmptyClick(activeDrawToolId, hasRegisteredDrawTool) {
8389
8410
  return !activeDrawToolId && hasRegisteredDrawTool;
@@ -8418,9 +8439,7 @@ var findFeatureIndexByKey = function findFeatureIndexByKey(geojson, feature) {
8418
8439
  if (key === undefined || !geojson) {
8419
8440
  return -1;
8420
8441
  }
8421
- return geojson.features.findIndex(function (feat) {
8422
- return layerUtils.getFeatureSelectionKey(feat) === key;
8423
- });
8442
+ return layerUtils.findFeatureIndexById(geojson, key);
8424
8443
  };
8425
8444
  var getMovableSelectedFeatureIds = function getMovableSelectedFeatureIds(geojson, selectedFeatureIds) {
8426
8445
  if (!(geojson != null && geojson.features.length) || !(selectedFeatureIds != null && selectedFeatureIds.length)) {
@@ -8467,10 +8486,14 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8467
8486
  var dispatch = useDispatch();
8468
8487
  var activeDrawToolId = useSelector(drawingToolSelectors.getActiveDrawToolId);
8469
8488
  var hasRegisteredDrawTool = useSelector(function (state) {
8470
- return drawingToolSelectors.selectAllDrawingTools(state).some(function (tool) {
8471
- return tool.geoJSONLayerId === layerId;
8472
- });
8489
+ return drawingToolSelectors.getHasDrawToolForLayer(state, layerId);
8490
+ });
8491
+ var isDrawToolOpen = useSelector(function (state) {
8492
+ return drawingToolSelectors.getIsDrawToolOpenForLayer(state, layerId);
8473
8493
  });
8494
+ var layerStyle = React.useMemo(function () {
8495
+ return isDrawToolOpen ? hideHiddenFeatures(style) : style;
8496
+ }, [isDrawToolOpen, style]);
8474
8497
  var activeDrawMode = useSelector(function (store) {
8475
8498
  return drawingToolSelectors.getActiveDrawMode(store, activeDrawToolId);
8476
8499
  });
@@ -8535,7 +8558,7 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8535
8558
  });
8536
8559
  }, [layer.geojson, layer.hoveredFeatureIds, layer.originalId, layer.selectedFeatureIds, usesIdSelection]);
8537
8560
  var clearSelection = React.useCallback(function () {
8538
- if (!shouldClearSelectionOnEmptyClick(activeDrawToolId, hasRegisteredDrawTool)) {
8561
+ if (!shouldClearSelectionOnEmptyClick(drawingToolSelectors.getActiveDrawToolId(store.getState()), hasRegisteredDrawTool)) {
8539
8562
  return;
8540
8563
  }
8541
8564
  dispatch(layerActions.setSelectedFeatures({
@@ -8547,7 +8570,13 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8547
8570
  isInEditMode: false,
8548
8571
  drawMode: ''
8549
8572
  }));
8550
- }, [activeDrawToolId, hasRegisteredDrawTool, dispatch, layerId]);
8573
+ }, [store, hasRegisteredDrawTool, dispatch, layerId]);
8574
+ var onDrawEscape = React.useCallback(function () {
8575
+ // the map already ended its own edit or draw mode for this Escape
8576
+ if (document.activeElement === document.body && drawingToolSelectors.getIsDrawToolOpenForLayer(store.getState(), layerId)) {
8577
+ clearSelection();
8578
+ }
8579
+ }, [store, layerId, clearSelection]);
8551
8580
  var onFeatureClick = React.useCallback(function (feature, isShiftClick) {
8552
8581
  var _clickedFeature$prope;
8553
8582
  if (!feature.length) {
@@ -8599,7 +8628,9 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8599
8628
  if (!((_layer$geojson3 = layer.geojson) != null && _layer$geojson3.features.length)) {
8600
8629
  return;
8601
8630
  }
8602
- var boxSelectedIndices = features.map(function (feature) {
8631
+ var boxSelectedIndices = features.filter(function (feature) {
8632
+ return !(isDrawToolOpen && isHiddenOlFeature(feature));
8633
+ }).map(function (feature) {
8603
8634
  return findFeatureIndexByKey(layer.geojson, feature);
8604
8635
  }).filter(function (idx) {
8605
8636
  return idx !== -1;
@@ -8628,7 +8659,7 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8628
8659
  drawMode: ''
8629
8660
  }));
8630
8661
  }
8631
- }, [dispatch, layer.geojson, layer.selectedFeatureIds, layerId]);
8662
+ }, [dispatch, layer.geojson, layer.selectedFeatureIds, layerId, isDrawToolOpen]);
8632
8663
  var boxSelectConfig = React.useMemo(function () {
8633
8664
  return usesIdSelection && !layer.isInEditMode ? {
8634
8665
  onBoxSelect: onBoxSelect,
@@ -8652,6 +8683,7 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8652
8683
  selectedFeatureCount: selectedFeatureIndices.length,
8653
8684
  isInEditMode: layer.isInEditMode,
8654
8685
  hasRegisteredDrawTool: hasRegisteredDrawTool,
8686
+ isDrawToolOpen: isDrawToolOpen,
8655
8687
  onDeselectAll: clearSelection
8656
8688
  });
8657
8689
  var movableSelectedFeatureIds = React.useMemo(function () {
@@ -8727,7 +8759,7 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8727
8759
  modifyFeatures: modifyFeaturesConfig,
8728
8760
  moveFeatures: moveFeaturesConfig,
8729
8761
  opacity: layer.opacity,
8730
- style: style,
8762
+ style: layerStyle,
8731
8763
  visible: layer.enabled,
8732
8764
  zIndex: zIndex
8733
8765
  }), jsx(OpenLayersMapDraw, {
@@ -8736,12 +8768,13 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref3
8736
8768
  exitDrawModeCallback: exitFeatureDrawMode,
8737
8769
  geojson: layer.geojson,
8738
8770
  isInEditMode: layer.isInEditMode || false,
8771
+ onEscape: onDrawEscape,
8739
8772
  onNoFeatureClick: onNoFeatureClick,
8740
8773
  onViewOnlyFeatureClick: onViewOnlyFeatureClick,
8741
8774
  selectedFeatureIndex: activeFeatureIndex,
8742
8775
  selectedFeatureIndices: selectedFeatureIndices,
8743
8776
  updateGeojson: updateFeature,
8744
- viewOnlyStyle: style
8777
+ viewOnlyStyle: layerStyle
8745
8778
  })]
8746
8779
  });
8747
8780
  };
@@ -10490,6 +10523,7 @@ var useUpdateTimeSpan = function useUpdateTimeSpan(mapId, myOnSetTimeSliderSpan)
10490
10523
  var activeLayerTimeDimension = useSelector(function (store) {
10491
10524
  return layerSelectors.getLayerTimeDimension(store, autoTimeStepLayerId);
10492
10525
  });
10526
+ var hasActiveLayerTimeDimension = Boolean(activeLayerTimeDimension);
10493
10527
  var timeSliderWidth = useSelector(function (store) {
10494
10528
  return mapSelectors.getMapTimeSliderWidth(store, mapId);
10495
10529
  });
@@ -10508,6 +10542,24 @@ var useUpdateTimeSpan = function useUpdateTimeSpan(mapId, myOnSetTimeSliderSpan)
10508
10542
  var isAnimating = useSelector(function (store) {
10509
10543
  return mapSelectors.isAnimating(store, mapId);
10510
10544
  });
10545
+ var _React$useState = React.useState(function () {
10546
+ return Math.floor(Date.now() / 1000);
10547
+ }),
10548
+ now = _React$useState[0],
10549
+ setNow = _React$useState[1];
10550
+ var updateNow = React.useCallback(function () {
10551
+ setNow(Math.floor(Date.now() / 1000));
10552
+ }, []);
10553
+ React.useEffect(function () {
10554
+ if (!isTimeSpanAuto || !autoTimeStepLayerId || !hasActiveLayerTimeDimension) {
10555
+ return undefined;
10556
+ }
10557
+ updateNow();
10558
+ var intervalId = window.setInterval(updateNow, 60 * 1000);
10559
+ return function () {
10560
+ return window.clearInterval(intervalId);
10561
+ };
10562
+ }, [autoTimeStepLayerId, hasActiveLayerTimeDimension, isTimeSpanAuto, updateNow]);
10511
10563
  var updateTimeSliderSpan = React.useCallback(function (spanInSeconds, newCenterTime) {
10512
10564
  // Do not dispatch actions if values are the same
10513
10565
  if (spanInSeconds !== undefined && newCenterTime !== undefined && (currentTimeSpan !== spanInSeconds || centerTime !== newCenterTime)) {
@@ -10515,14 +10567,28 @@ var useUpdateTimeSpan = function useUpdateTimeSpan(mapId, myOnSetTimeSliderSpan)
10515
10567
  }
10516
10568
  }, [centerTime, currentTimeSpan, myOnSetTimeSliderSpan]);
10517
10569
  React.useEffect(function () {
10570
+ if (isTimeSpanAuto && isAnimating) {
10571
+ return;
10572
+ }
10518
10573
  if (isTimeSpanAuto && autoTimeStepLayerId && activeLayerTimeDimension && !isAnimating) {
10519
10574
  var _getTimeBounds = getTimeBounds([activeLayerTimeDimension]),
10520
10575
  startTime = _getTimeBounds.startTime,
10521
10576
  endTime = _getTimeBounds.endTime;
10522
- var minimumStartTime = selectedTime - 24 * 3600;
10523
- var slicedStartTime = startTime < minimumStartTime ? minimumStartTime : startTime;
10524
- var spanInSeconds = endTime - slicedStartTime;
10525
- var newCenterTime = (slicedStartTime + endTime) / 2;
10577
+ var oneDayInSeconds = 24 * 3600;
10578
+ var slicedStartTime;
10579
+ var slicedEndTime;
10580
+ if (now < startTime) {
10581
+ slicedStartTime = now;
10582
+ slicedEndTime = now + oneDayInSeconds;
10583
+ } else if (now > endTime) {
10584
+ slicedStartTime = now - oneDayInSeconds;
10585
+ slicedEndTime = now;
10586
+ } else {
10587
+ slicedStartTime = Math.max(startTime, now - oneDayInSeconds);
10588
+ slicedEndTime = now;
10589
+ }
10590
+ var spanInSeconds = slicedEndTime - slicedStartTime;
10591
+ var newCenterTime = (slicedStartTime + slicedEndTime) / 2;
10526
10592
  updateTimeSliderSpan(spanInSeconds, newCenterTime);
10527
10593
  } else {
10528
10594
  var _spanInSeconds = currentTimeSpan || defaultTimeSpan;
@@ -10530,7 +10596,7 @@ var useUpdateTimeSpan = function useUpdateTimeSpan(mapId, myOnSetTimeSliderSpan)
10530
10596
  updateTimeSliderSpan(_spanInSeconds, _newCenterTime);
10531
10597
  }
10532
10598
  // eslint-disable-next-line react-hooks/exhaustive-deps
10533
- }, [autoTimeStepLayerId, isTimeSpanAuto, mapId, activeLayerTimeDimension == null ? void 0 : activeLayerTimeDimension.name]);
10599
+ }, [autoTimeStepLayerId, isAnimating, isTimeSpanAuto, mapId, activeLayerTimeDimension == null ? void 0 : activeLayerTimeDimension.name, now]);
10534
10600
  };
10535
10601
  var timeToIso = function timeToIso(selectedTime) {
10536
10602
  return handleDateUtilsISOString(dateUtils.fromUnix(selectedTime).toISOString());
@@ -10604,9 +10670,9 @@ var TimeSliderConnect = function TimeSliderConnect(_ref) {
10604
10670
  useUpdateTimestep(mapId);
10605
10671
  useUpdateTimeSpan(mapId, onSetTimeSliderSpan);
10606
10672
  // Local state for unfiltered selected time
10607
- var _React$useState = React.useState(selectedTime),
10608
- unfilteredSelectedTime = _React$useState[0],
10609
- setUnfilteredSelectedTime = _React$useState[1];
10673
+ var _React$useState2 = React.useState(selectedTime),
10674
+ unfilteredSelectedTime = _React$useState2[0],
10675
+ setUnfilteredSelectedTime = _React$useState2[1];
10610
10676
  // Store unfilteredSelectedTime in a ref for callbacks
10611
10677
  var unfilteredSelectedTimeRef = React.useRef(unfilteredSelectedTime);
10612
10678
  React.useEffect(function () {
@@ -1,20 +1,23 @@
1
1
  import type { Feature } from 'ol';
2
- import type { StyleLike } from 'ol/style/Style';
2
+ import type { StyleFunction, StyleLike } from 'ol/style/Style';
3
3
  import React from 'react';
4
4
  import type { layerTypes } from '@opengeoweb/store';
5
5
  import type { HoverSelect } from '@opengeoweb/webmap-react';
6
6
  import { getAffectedIndices } from '@opengeoweb/webmap-react';
7
7
  export { getAffectedIndices };
8
+ export declare const hideHiddenFeatures: (style: StyleLike) => StyleFunction;
8
9
  /** Escape drops a multi selection only. A sole selection is kept, matching the
9
- * plain click behaviour, and edit mode keeps its own Escape handling. */
10
- export declare const shouldDeselectAllOnEscape: (selectedFeatureCount: number, isInEditMode: boolean | undefined, hasRegisteredDrawTool: boolean) => boolean;
10
+ * plain click behaviour, unless the drawing tool is open. Edit mode keeps the
11
+ * map's own Escape handling, after which onDrawEscape drops the selection. */
12
+ export declare const shouldDeselectAllOnEscape: (selectedFeatureCount: number, isInEditMode: boolean | undefined, hasRegisteredDrawTool: boolean, isDrawToolOpen?: boolean) => boolean;
11
13
  interface DeselectAllOnEscapeOptions {
12
14
  selectedFeatureCount: number;
13
15
  isInEditMode: boolean | undefined;
14
16
  hasRegisteredDrawTool: boolean;
17
+ isDrawToolOpen?: boolean;
15
18
  onDeselectAll: () => void;
16
19
  }
17
- export declare const useDeselectAllOnEscape: ({ selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, onDeselectAll, }: DeselectAllOnEscapeOptions) => void;
20
+ export declare const useDeselectAllOnEscape: ({ selectedFeatureCount, isInEditMode, hasRegisteredDrawTool, isDrawToolOpen, onDeselectAll, }: DeselectAllOnEscapeOptions) => void;
18
21
  export declare const shouldClearSelectionOnEmptyClick: (activeDrawToolId: string | undefined, hasRegisteredDrawTool: boolean) => boolean;
19
22
  export declare const isSketchInProgress: (isInEditMode: boolean | undefined, drawMode: string | undefined, activeFeature: GeoJSON.Feature | undefined) => boolean;
20
23
  /** Soundings and time series set their own highlight, so they must stay out of this. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeoweb/core",
3
- "version": "20.1.0",
3
+ "version": "20.2.0-nightly-20261021",
4
4
  "description": "GeoWeb Core library for the opengeoweb project",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,28 +20,28 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "@opengeoweb/shared": "20.1.0",
23
+ "@opengeoweb/shared": "20.2.0-nightly-20261021",
24
24
  "react-redux": "^9.2.0",
25
- "@opengeoweb/store": "20.1.0",
26
- "@opengeoweb/time-slider": "20.1.0",
25
+ "@opengeoweb/store": "20.2.0-nightly-20261021",
26
+ "@opengeoweb/time-slider": "20.2.0-nightly-20261021",
27
27
  "@reduxjs/toolkit": "^2.6.1",
28
- "@opengeoweb/webmap-react": "20.1.0",
29
- "@opengeoweb/webmap": "20.1.0",
30
- "@opengeoweb/theme": "20.1.0",
31
- "@opengeoweb/layer-select": "20.1.0",
28
+ "@opengeoweb/webmap-react": "20.2.0-nightly-20261021",
29
+ "@opengeoweb/webmap": "20.2.0-nightly-20261021",
30
+ "@opengeoweb/theme": "20.2.0-nightly-20261021",
31
+ "@opengeoweb/layer-select": "20.2.0-nightly-20261021",
32
32
  "lodash": "^4.18.1",
33
33
  "ol": "^10.4.0",
34
34
  "react-sortablejs": "^6.1.4",
35
35
  "sortablejs": "^1.15.1",
36
36
  "@mui/system": "^9.0.1",
37
- "@opengeoweb/snackbar": "20.1.0",
37
+ "@opengeoweb/snackbar": "20.2.0-nightly-20261021",
38
38
  "react-draggable": "^4.4.6",
39
39
  "i18next": "^25.0.1",
40
40
  "react-i18next": "^15.1.1",
41
41
  "dompurify": "^3.4.13",
42
42
  "@mui/material": "^9.0.1",
43
43
  "@tanstack/react-query": "^5.85.5",
44
- "@opengeoweb/api": "20.1.0",
44
+ "@opengeoweb/api": "20.2.0-nightly-20261021",
45
45
  "@types/geojson": "^7946.0.14",
46
46
  "@turf/turf": "^7.2.0",
47
47
  "proj4": "^2.15.0",