@opengeoweb/time-series 14.0.1 → 14.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js
CHANGED
|
@@ -4,7 +4,7 @@ import React__default, { useState, useMemo, useEffect, useCallback, memo } from
|
|
|
4
4
|
import { useDispatch, useSelector } from 'react-redux';
|
|
5
5
|
import { mapUtils, selectorMemoizationOptions, genericSelectors, uiSelectors, uiTypes, uiActions, useSetupDialog, mapSelectors, mapListener, serviceListener, layersListener, syncGroupsListener, genericListener, openlayersListener, uiReducer, syncGroupsReducer, layerReducer, serviceReducer, mapReducer, loadingIndicatorActions, syncGroupsActions, genericActions, mapActions, layerActions } from '@opengeoweb/store';
|
|
6
6
|
import { snackbarActions, snackbarTypes, snackbarListener, snackbarReducer } from '@opengeoweb/snackbar';
|
|
7
|
-
import { dateUtils, CustomTooltip, CustomToggleButton, TooltipSelect, CustomIconButton, CustomAccordion, ToolContainerDraggable, SearchHighlight, SearchField, ToggleMenu, CustomDialog, AlertBanner, useConfirmationDialog, SwitchButton } from '@opengeoweb/shared';
|
|
7
|
+
import { dateUtils, CustomTooltip, CustomToggleButton, TooltipSelect, CustomIconButton, CustomAccordion, ToolContainerDraggable, SearchHighlight, SearchField, ToggleMenu, CustomDialog, AlertBanner, useConfirmationDialog, SwitchButton, useResizeObserver } from '@opengeoweb/shared';
|
|
8
8
|
import { MenuItem, useTheme, LinearProgress, Grid, Box, Typography, ClickAwayListener, Input, Collapse, ListItem, ListItemButton, ListItemText, List, Button, InputAdornment, Card, styled, Stack, Tooltip, ListItemIcon, Checkbox } from '@mui/material';
|
|
9
9
|
import { isString, trim, trimStart, compact, chain, groupBy, sortBy, uniqBy, isEqual } from 'lodash';
|
|
10
10
|
import { ReactSortable } from 'react-sortablejs';
|
|
@@ -42,6 +42,9 @@ var en = {
|
|
|
42
42
|
"timeseries-show": "Show",
|
|
43
43
|
"timeseries-hide": "Hide",
|
|
44
44
|
"timeseries-collection": "Collection",
|
|
45
|
+
"timeseries-collection-id": "Collection ID",
|
|
46
|
+
"timeseries-collection-title": "Collection title",
|
|
47
|
+
"timeseries-collection-description": "Collection description",
|
|
45
48
|
"timeseries-parameter": "Parameter",
|
|
46
49
|
"timeseries-parameter-info": "Timeseries parameter info",
|
|
47
50
|
"timeseries-style": "Style",
|
|
@@ -371,6 +374,9 @@ var nl = {
|
|
|
371
374
|
"timeseries-show": "Tonen",
|
|
372
375
|
"timeseries-hide": "Verbergen",
|
|
373
376
|
"timeseries-collection": "Collectie",
|
|
377
|
+
"timeseries-collection-id": "Collectie ID",
|
|
378
|
+
"timeseries-collection-title": "Collectie titel",
|
|
379
|
+
"timeseries-collection-description": "Collectie beschrijving",
|
|
374
380
|
"timeseries-parameter": "Parameter",
|
|
375
381
|
"timeseries-parameter-info": "Tijdreeksen parameter info",
|
|
376
382
|
"timeseries-style": "Stijl",
|
|
@@ -1009,15 +1015,20 @@ var constructParameterObject = function constructParameterObject(serviceId, coll
|
|
|
1009
1015
|
});
|
|
1010
1016
|
};
|
|
1011
1017
|
var getCollectionDetails = function getCollectionDetails(service, collection, instances) {
|
|
1012
|
-
var _collection$extent2;
|
|
1018
|
+
var _collection$extent$cu, _collection$extent2, _collection$data_quer, _collection$extent3;
|
|
1013
1019
|
return Object.assign({
|
|
1014
1020
|
serviceId: service.id,
|
|
1015
1021
|
serviceName: service.name || service.id,
|
|
1016
|
-
collectionId: collection.id
|
|
1022
|
+
collectionId: collection.id
|
|
1023
|
+
}, collection.title !== undefined ? {
|
|
1024
|
+
collectionTitle: collection.title
|
|
1025
|
+
} : {}, collection.description !== undefined ? {
|
|
1026
|
+
collectionDescription: collection.description
|
|
1027
|
+
} : {}, {
|
|
1017
1028
|
parameters: constructParameterObject(service.id, collection.id, collection.parameter_names),
|
|
1018
|
-
customDimensions: ((_collection$extent2 = collection.extent) == null ? void 0 : _collection$extent2.custom)
|
|
1019
|
-
dataQueries: collection.data_queries
|
|
1020
|
-
extent: collection.extent
|
|
1029
|
+
customDimensions: (_collection$extent$cu = (_collection$extent2 = collection.extent) == null ? void 0 : _collection$extent2.custom) != null ? _collection$extent$cu : [],
|
|
1030
|
+
dataQueries: (_collection$data_quer = collection.data_queries) != null ? _collection$data_quer : {},
|
|
1031
|
+
extent: (_collection$extent3 = collection.extent) != null ? _collection$extent3 : {}
|
|
1021
1032
|
}, {});
|
|
1022
1033
|
};
|
|
1023
1034
|
var getServiceCollectionDetails = function getServiceCollectionDetails(service, collections) {
|
|
@@ -1028,9 +1039,9 @@ var getServiceCollectionDetails = function getServiceCollectionDetails(service,
|
|
|
1028
1039
|
}
|
|
1029
1040
|
// Only use parameters from collections that support /locations or /position
|
|
1030
1041
|
for (var _iterator = _createForOfIteratorHelperLoose(collections), _step; !(_step = _iterator()).done;) {
|
|
1031
|
-
var _collection$
|
|
1042
|
+
var _collection$data_quer2, _collection$data_quer3;
|
|
1032
1043
|
var collection = _step.value;
|
|
1033
|
-
if ((_collection$
|
|
1044
|
+
if ((_collection$data_quer2 = collection.data_queries) != null && _collection$data_quer2.locations || (_collection$data_quer3 = collection.data_queries) != null && _collection$data_quer3.position) {
|
|
1034
1045
|
collectionsParameters.push(getCollectionDetails(service, collection));
|
|
1035
1046
|
}
|
|
1036
1047
|
}
|
|
@@ -1063,15 +1074,16 @@ var clipEdrInterval = function clipEdrInterval(interval, maxHoursBefore,
|
|
|
1063
1074
|
maxHoursAfter,
|
|
1064
1075
|
// 10 days to the future
|
|
1065
1076
|
date) {
|
|
1077
|
+
var _dateUtils$isoStringT, _dateUtils$isoStringT2;
|
|
1066
1078
|
if (date === void 0) {
|
|
1067
1079
|
date = Date.now();
|
|
1068
1080
|
}
|
|
1069
1081
|
var startTimeFromEdr = (interval == null ? void 0 : interval.length) && interval[0];
|
|
1070
1082
|
var endTimeFromEdr = (interval == null ? void 0 : interval.length) && interval[1];
|
|
1071
|
-
var startDate = (dateUtils.isoStringToDate(String(startTimeFromEdr), false)
|
|
1072
|
-
var endDate = (dateUtils.isoStringToDate(String(endTimeFromEdr), false)
|
|
1073
|
-
var clippedStartDate = new Date(Math.max(startDate
|
|
1074
|
-
var clippedEndDate = new Date(Math.min(endDate
|
|
1083
|
+
var startDate = ((_dateUtils$isoStringT = dateUtils.isoStringToDate(String(startTimeFromEdr), false)) != null ? _dateUtils$isoStringT : dateUtils.getNowUtc()).getTime();
|
|
1084
|
+
var endDate = ((_dateUtils$isoStringT2 = dateUtils.isoStringToDate(String(endTimeFromEdr), false)) != null ? _dateUtils$isoStringT2 : dateUtils.getNowUtc()).getTime();
|
|
1085
|
+
var clippedStartDate = new Date(Math.max(startDate != null ? startDate : date, date - maxHoursBefore * HOUR_IN_MILLISECONDS));
|
|
1086
|
+
var clippedEndDate = new Date(Math.min(endDate != null ? endDate : date, date + maxHoursAfter * HOUR_IN_MILLISECONDS));
|
|
1075
1087
|
// Round the dates to minutes to make caching more likely.
|
|
1076
1088
|
clippedStartDate.setMilliseconds(0);
|
|
1077
1089
|
clippedStartDate.setSeconds(0);
|
|
@@ -1084,8 +1096,8 @@ date) {
|
|
|
1084
1096
|
// 1 day to past, 10 days to future
|
|
1085
1097
|
var clipInterval = [1 * 24, 10 * 24];
|
|
1086
1098
|
var constructTimeInterval = function constructTimeInterval(collection, instance, parameter) {
|
|
1087
|
-
var _instance$extent2, _collection$
|
|
1088
|
-
var interval = ((_instance$extent2 = instance.extent) == null || (_instance$extent2 = _instance$extent2.temporal) == null ? void 0 : _instance$extent2.interval[0])
|
|
1099
|
+
var _instance$extent$temp, _instance$extent2, _collection$extent4;
|
|
1100
|
+
var interval = (_instance$extent$temp = (_instance$extent2 = instance.extent) == null || (_instance$extent2 = _instance$extent2.temporal) == null ? void 0 : _instance$extent2.interval[0]) != null ? _instance$extent$temp : collection == null || (_collection$extent4 = collection.extent) == null || (_collection$extent4 = _collection$extent4.temporal) == null ? void 0 : _collection$extent4.interval[0];
|
|
1089
1101
|
var _clipEdrInterval = clipEdrInterval(interval, clipInterval[0], clipInterval[1]),
|
|
1090
1102
|
start = _clipEdrInterval[0],
|
|
1091
1103
|
end = _clipEdrInterval[1];
|
|
@@ -1103,14 +1115,14 @@ var EARTH_RADIUS = 6371;
|
|
|
1103
1115
|
* @returns feature nearest to the target location or null if none are within the maximum distance
|
|
1104
1116
|
*/
|
|
1105
1117
|
var findNearestPoint = function findNearestPoint(targetLocation, pointFeatures, maxDistanceKm) {
|
|
1106
|
-
var _pointFeatures$reduce;
|
|
1118
|
+
var _pointFeatures$reduce, _pointFeatures$reduce2;
|
|
1107
1119
|
if (maxDistanceKm === void 0) {
|
|
1108
1120
|
maxDistanceKm = 2;
|
|
1109
1121
|
}
|
|
1110
1122
|
if (!pointFeatures.length) {
|
|
1111
1123
|
return null;
|
|
1112
1124
|
}
|
|
1113
|
-
return (
|
|
1125
|
+
return (_pointFeatures$reduce = (_pointFeatures$reduce2 = pointFeatures.reduce(function (nearestPoint, currentFeature) {
|
|
1114
1126
|
var _getFeatureCenterPoin = getFeatureCenterPoint(currentFeature),
|
|
1115
1127
|
featureLon = _getFeatureCenterPoin[0],
|
|
1116
1128
|
featureLat = _getFeatureCenterPoin[1];
|
|
@@ -1131,7 +1143,7 @@ var findNearestPoint = function findNearestPoint(targetLocation, pointFeatures,
|
|
|
1131
1143
|
};
|
|
1132
1144
|
}
|
|
1133
1145
|
return nearestPoint;
|
|
1134
|
-
}, null)) == null ? void 0 : _pointFeatures$
|
|
1146
|
+
}, null)) == null ? void 0 : _pointFeatures$reduce2.feature) != null ? _pointFeatures$reduce : null;
|
|
1135
1147
|
};
|
|
1136
1148
|
var getFeatureCenterPoint = function getFeatureCenterPoint(feature) {
|
|
1137
1149
|
return feature.geometry.type === 'Point' ? feature.geometry.coordinates : turf.center(feature).geometry.coordinates;
|
|
@@ -4121,12 +4133,13 @@ var filterCollectionsParametersFromService = function filterCollectionsParameter
|
|
|
4121
4133
|
return filteredCollectionList;
|
|
4122
4134
|
}
|
|
4123
4135
|
var collectionContainsSearch = searchStringArray.every(function (search) {
|
|
4124
|
-
var _collection$collectio, _collection$serviceId, _collection$serviceNa;
|
|
4136
|
+
var _collection$collectio, _collection$collectio2, _collection$serviceId, _collection$serviceNa;
|
|
4125
4137
|
var searchLowercase = search.toLowerCase();
|
|
4126
4138
|
var isSearchTextInCollectionId = (_collection$collectio = collection.collectionId) == null ? void 0 : _collection$collectio.toLowerCase().includes(searchLowercase);
|
|
4139
|
+
var isSearchTextInCollectionTitle = (_collection$collectio2 = collection.collectionTitle) == null ? void 0 : _collection$collectio2.toLowerCase().includes(searchLowercase);
|
|
4127
4140
|
var isSearchTextInServiceId = (_collection$serviceId = collection.serviceId) == null ? void 0 : _collection$serviceId.toLowerCase().includes(searchLowercase);
|
|
4128
4141
|
var isSearchTextInServiceName = (_collection$serviceNa = collection.serviceName) == null ? void 0 : _collection$serviceNa.toLowerCase().includes(searchLowercase);
|
|
4129
|
-
return isSearchTextInCollectionId || isSearchTextInServiceId || isSearchTextInServiceName;
|
|
4142
|
+
return isSearchTextInCollectionId || isSearchTextInCollectionTitle || isSearchTextInServiceId || isSearchTextInServiceName;
|
|
4130
4143
|
});
|
|
4131
4144
|
// Not found in collection - search in parameters
|
|
4132
4145
|
var filteredParamters = collection.parameters.reduce(function (filteredParameterList, parameter) {
|
|
@@ -4168,6 +4181,7 @@ var fontStyling = function fontStyling(primary) {
|
|
|
4168
4181
|
lineHeight: '14px',
|
|
4169
4182
|
fontWeight: primary ? 500 : 'normal',
|
|
4170
4183
|
textOverflow: 'ellipsis',
|
|
4184
|
+
whiteSpace: 'nowrap',
|
|
4171
4185
|
overflow: 'hidden'
|
|
4172
4186
|
};
|
|
4173
4187
|
};
|
|
@@ -4274,10 +4288,11 @@ var TimeSeriesSelectList = function TimeSeriesSelectList(_ref) {
|
|
|
4274
4288
|
alignItems: 'center'
|
|
4275
4289
|
},
|
|
4276
4290
|
children: [jsxs(Grid, {
|
|
4291
|
+
size: "grow",
|
|
4277
4292
|
children: [jsx(Box, {
|
|
4278
4293
|
sx: fontStyling(),
|
|
4279
4294
|
children: jsx(SearchHighlight, {
|
|
4280
|
-
text: collectionListItem.collectionId,
|
|
4295
|
+
text: collectionListItem.collectionTitle || collectionListItem.collectionId,
|
|
4281
4296
|
search: searchFilter
|
|
4282
4297
|
})
|
|
4283
4298
|
}), jsx(Box, {
|
|
@@ -4325,6 +4340,7 @@ var TimeSeriesSelectList = function TimeSeriesSelectList(_ref) {
|
|
|
4325
4340
|
' .MuiListItemText-primary': {
|
|
4326
4341
|
fontSize: '12px',
|
|
4327
4342
|
fontWeight: 500,
|
|
4343
|
+
whiteSpace: 'nowrap',
|
|
4328
4344
|
textOverflow: 'ellipsis',
|
|
4329
4345
|
overflow: 'hidden'
|
|
4330
4346
|
}
|
|
@@ -4373,6 +4389,7 @@ var TimeSeriesSelectList = function TimeSeriesSelectList(_ref) {
|
|
|
4373
4389
|
alignItems: 'center'
|
|
4374
4390
|
},
|
|
4375
4391
|
children: [jsx(Grid, {
|
|
4392
|
+
size: "grow",
|
|
4376
4393
|
children: jsx(Box, {
|
|
4377
4394
|
sx: fontStyling(),
|
|
4378
4395
|
children: jsx(SearchHighlight, {
|
|
@@ -5544,7 +5561,7 @@ var ParameterInfoDialog = function ParameterInfoDialog(_ref) {
|
|
|
5544
5561
|
onClose: onClose,
|
|
5545
5562
|
startSize: {
|
|
5546
5563
|
width: 288,
|
|
5547
|
-
height: dialogHeight
|
|
5564
|
+
height: dialogHeight != null ? dialogHeight : 650
|
|
5548
5565
|
},
|
|
5549
5566
|
startPosition: {
|
|
5550
5567
|
top: 150,
|
|
@@ -5580,8 +5597,14 @@ var ParameterInfoDialog = function ParameterInfoDialog(_ref) {
|
|
|
5580
5597
|
value: relatedService.type
|
|
5581
5598
|
})]
|
|
5582
5599
|
}), jsx(ParameterInfoText$1, {
|
|
5583
|
-
label: t('timeseries-collection'),
|
|
5600
|
+
label: t('timeseries-collection-id'),
|
|
5584
5601
|
value: currentParameterInfo.collectionId
|
|
5602
|
+
}), (collectionInformation == null ? void 0 : collectionInformation.collectionTitle) && (collectionInformation == null ? void 0 : collectionInformation.collectionTitle) !== '' && jsx(ParameterInfoText$1, {
|
|
5603
|
+
label: t('timeseries-collection-title'),
|
|
5604
|
+
value: collectionInformation == null ? void 0 : collectionInformation.collectionTitle
|
|
5605
|
+
}), (collectionInformation == null ? void 0 : collectionInformation.collectionDescription) && (collectionInformation == null ? void 0 : collectionInformation.collectionDescription) !== '' && jsx(ParameterInfoText$1, {
|
|
5606
|
+
label: t('timeseries-collection-description'),
|
|
5607
|
+
value: collectionInformation == null ? void 0 : collectionInformation.collectionDescription
|
|
5585
5608
|
}), jsx(QueryInfoElement, {
|
|
5586
5609
|
queryInformation: collectionInformation,
|
|
5587
5610
|
isLoadingCollectionInformation: isLoadingCollectionInformation
|
|
@@ -7807,7 +7830,26 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7807
7830
|
var theme = useTheme();
|
|
7808
7831
|
var _useTimeseriesTransla = useTimeseriesTranslation();
|
|
7809
7832
|
_useTimeseriesTransla.t;
|
|
7833
|
+
// Wrapper ref used for hover detection AND restoring keyboard focus after selection.
|
|
7810
7834
|
var mouseMoveRef = React__default.useRef(null);
|
|
7835
|
+
// Listen for global selection events so we can re-focus the item that was activated via keyboard.
|
|
7836
|
+
React__default.useEffect(function () {
|
|
7837
|
+
var handleSelection = function handleSelection(e) {
|
|
7838
|
+
var _custom$detail;
|
|
7839
|
+
var custom = e;
|
|
7840
|
+
if (((_custom$detail = custom.detail) == null ? void 0 : _custom$detail.location) === location && mouseMoveRef.current) {
|
|
7841
|
+
// Delay to allow parent state updates / virtualization re-render.
|
|
7842
|
+
requestAnimationFrame(function () {
|
|
7843
|
+
var _mouseMoveRef$current;
|
|
7844
|
+
(_mouseMoveRef$current = mouseMoveRef.current) == null || _mouseMoveRef$current.focus();
|
|
7845
|
+
});
|
|
7846
|
+
}
|
|
7847
|
+
};
|
|
7848
|
+
window.addEventListener('location-list-selection', handleSelection);
|
|
7849
|
+
return function () {
|
|
7850
|
+
window.removeEventListener('location-list-selection', handleSelection);
|
|
7851
|
+
};
|
|
7852
|
+
}, [location]);
|
|
7811
7853
|
var textContainerRef = React__default.useRef(null);
|
|
7812
7854
|
var _React$useState = React__default.useState(false),
|
|
7813
7855
|
isHovering = _React$useState[0],
|
|
@@ -7843,6 +7885,23 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7843
7885
|
setTextContainerWidth(textContainerRef.current.clientWidth);
|
|
7844
7886
|
}
|
|
7845
7887
|
}, [textContainerRef]);
|
|
7888
|
+
// If selection state changes and this item is now the selected one, ensure it regains focus.
|
|
7889
|
+
React__default.useEffect(function () {
|
|
7890
|
+
if (selectedLocation === location && mouseMoveRef.current) {
|
|
7891
|
+
// If focus already on this item, do nothing.
|
|
7892
|
+
if (mouseMoveRef.current === document.activeElement) {
|
|
7893
|
+
return;
|
|
7894
|
+
}
|
|
7895
|
+
// If focus is outside the list item, re-focus after render settles.
|
|
7896
|
+
// Use double rAF for virtualization/layout stability.
|
|
7897
|
+
requestAnimationFrame(function () {
|
|
7898
|
+
requestAnimationFrame(function () {
|
|
7899
|
+
var _mouseMoveRef$current2;
|
|
7900
|
+
(_mouseMoveRef$current2 = mouseMoveRef.current) == null || _mouseMoveRef$current2.focus();
|
|
7901
|
+
});
|
|
7902
|
+
});
|
|
7903
|
+
}
|
|
7904
|
+
}, [selectedLocation, location]);
|
|
7846
7905
|
return jsx(OverflowTooltip, {
|
|
7847
7906
|
text: location,
|
|
7848
7907
|
textContainerWidth: textContainerWidth,
|
|
@@ -7852,6 +7911,29 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7852
7911
|
onMouseLeave: handleMouseLeave,
|
|
7853
7912
|
onFocus: handleMouseEnter,
|
|
7854
7913
|
onBlur: handleMouseLeave,
|
|
7914
|
+
tabIndex: 0,
|
|
7915
|
+
role: "option",
|
|
7916
|
+
"aria-selected": selectedLocation === location,
|
|
7917
|
+
onKeyDown: function onKeyDown(e) {
|
|
7918
|
+
if (isDisabled) {
|
|
7919
|
+
return;
|
|
7920
|
+
}
|
|
7921
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
7922
|
+
e.preventDefault();
|
|
7923
|
+
handleChange(location);
|
|
7924
|
+
// Dispatch custom event to remove focus styling from outer list container
|
|
7925
|
+
window.dispatchEvent(new CustomEvent('location-list-selection', {
|
|
7926
|
+
detail: {
|
|
7927
|
+
location: location
|
|
7928
|
+
}
|
|
7929
|
+
}));
|
|
7930
|
+
// Explicitly retain focus immediately (backup before effect runs)
|
|
7931
|
+
requestAnimationFrame(function () {
|
|
7932
|
+
var _mouseMoveRef$current3;
|
|
7933
|
+
(_mouseMoveRef$current3 = mouseMoveRef.current) == null || _mouseMoveRef$current3.focus();
|
|
7934
|
+
});
|
|
7935
|
+
}
|
|
7936
|
+
},
|
|
7855
7937
|
children: jsxs(ListItem, Object.assign({
|
|
7856
7938
|
"data-testid": "locationDropdownListItem",
|
|
7857
7939
|
role: "listitem"
|
|
@@ -7886,7 +7968,19 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7886
7968
|
backgroundColor: 'transparent'
|
|
7887
7969
|
}
|
|
7888
7970
|
},
|
|
7889
|
-
disabled: isDisabled
|
|
7971
|
+
disabled: isDisabled,
|
|
7972
|
+
// Remove from tab order so row wrapper is the single focus target
|
|
7973
|
+
tabIndex: -1,
|
|
7974
|
+
onChange: function onChange() {
|
|
7975
|
+
if (!isDisabled) {
|
|
7976
|
+
handleChange(location);
|
|
7977
|
+
window.dispatchEvent(new CustomEvent('location-list-selection', {
|
|
7978
|
+
detail: {
|
|
7979
|
+
location: location
|
|
7980
|
+
}
|
|
7981
|
+
}));
|
|
7982
|
+
}
|
|
7983
|
+
}
|
|
7890
7984
|
})
|
|
7891
7985
|
}), jsx(Typography, {
|
|
7892
7986
|
ref: textContainerRef,
|
|
@@ -7926,6 +8020,121 @@ var renderRow = function renderRow(features, handleChange, selectedLocation, isD
|
|
|
7926
8020
|
};
|
|
7927
8021
|
};
|
|
7928
8022
|
|
|
8023
|
+
var FocusableListOuter = /*#__PURE__*/React.forwardRef(function (props, ref) {
|
|
8024
|
+
// Track last interaction modality to conditionally show focus ring only for keyboard navigation.
|
|
8025
|
+
var lastInteractionWasKeyboard = React.useRef(false);
|
|
8026
|
+
React.useEffect(function () {
|
|
8027
|
+
var handleKey = function handleKey(e) {
|
|
8028
|
+
// Ignore modifier-only keys; any navigation key sets keyboard modality.
|
|
8029
|
+
if (e.key) {
|
|
8030
|
+
lastInteractionWasKeyboard.current = true;
|
|
8031
|
+
}
|
|
8032
|
+
};
|
|
8033
|
+
var handlePointer = function handlePointer() {
|
|
8034
|
+
lastInteractionWasKeyboard.current = false;
|
|
8035
|
+
};
|
|
8036
|
+
window.addEventListener('keydown', handleKey, {
|
|
8037
|
+
capture: true
|
|
8038
|
+
});
|
|
8039
|
+
window.addEventListener('mousedown', handlePointer, {
|
|
8040
|
+
capture: true
|
|
8041
|
+
});
|
|
8042
|
+
window.addEventListener('pointerdown', handlePointer, {
|
|
8043
|
+
capture: true
|
|
8044
|
+
});
|
|
8045
|
+
window.addEventListener('touchstart', handlePointer, {
|
|
8046
|
+
capture: true
|
|
8047
|
+
});
|
|
8048
|
+
// Listen for custom selection event to remove focus styling after keyboard activation.
|
|
8049
|
+
var handleSelection = function handleSelection() {
|
|
8050
|
+
setIsFocusVisible(false);
|
|
8051
|
+
};
|
|
8052
|
+
window.addEventListener('location-list-selection', handleSelection);
|
|
8053
|
+
return function () {
|
|
8054
|
+
window.removeEventListener('keydown', handleKey, {
|
|
8055
|
+
capture: true
|
|
8056
|
+
});
|
|
8057
|
+
window.removeEventListener('mousedown', handlePointer, {
|
|
8058
|
+
capture: true
|
|
8059
|
+
});
|
|
8060
|
+
window.removeEventListener('pointerdown', handlePointer, {
|
|
8061
|
+
capture: true
|
|
8062
|
+
});
|
|
8063
|
+
window.removeEventListener('touchstart', handlePointer, {
|
|
8064
|
+
capture: true
|
|
8065
|
+
});
|
|
8066
|
+
window.removeEventListener('location-list-selection', handleSelection);
|
|
8067
|
+
};
|
|
8068
|
+
}, []);
|
|
8069
|
+
var handleKeyDown = function handleKeyDown(e) {
|
|
8070
|
+
var el = ref && typeof ref === 'object' && 'current' in ref ? ref.current : null;
|
|
8071
|
+
if (!el) {
|
|
8072
|
+
return;
|
|
8073
|
+
}
|
|
8074
|
+
var lineHeight = 40; // matches itemSize
|
|
8075
|
+
var pageHeight = el.clientHeight;
|
|
8076
|
+
switch (e.key) {
|
|
8077
|
+
case 'ArrowDown':
|
|
8078
|
+
e.preventDefault();
|
|
8079
|
+
el.scrollTop += lineHeight;
|
|
8080
|
+
break;
|
|
8081
|
+
case 'ArrowUp':
|
|
8082
|
+
e.preventDefault();
|
|
8083
|
+
el.scrollTop -= lineHeight;
|
|
8084
|
+
break;
|
|
8085
|
+
case 'PageDown':
|
|
8086
|
+
e.preventDefault();
|
|
8087
|
+
el.scrollTop += pageHeight;
|
|
8088
|
+
break;
|
|
8089
|
+
case 'PageUp':
|
|
8090
|
+
e.preventDefault();
|
|
8091
|
+
el.scrollTop -= pageHeight;
|
|
8092
|
+
break;
|
|
8093
|
+
case 'Home':
|
|
8094
|
+
e.preventDefault();
|
|
8095
|
+
el.scrollTop = 0;
|
|
8096
|
+
break;
|
|
8097
|
+
case 'End':
|
|
8098
|
+
e.preventDefault();
|
|
8099
|
+
el.scrollTop = el.scrollHeight;
|
|
8100
|
+
break;
|
|
8101
|
+
}
|
|
8102
|
+
};
|
|
8103
|
+
// merge any existing style prop with our outline override
|
|
8104
|
+
var mergedStyle = Object.assign({}, props.style, {
|
|
8105
|
+
outline: 'none',
|
|
8106
|
+
transition: 'box-shadow 120ms ease, background-color 120ms ease'
|
|
8107
|
+
});
|
|
8108
|
+
var _React$useState = React.useState(false),
|
|
8109
|
+
isFocusVisible = _React$useState[0],
|
|
8110
|
+
setIsFocusVisible = _React$useState[1];
|
|
8111
|
+
var onFocus = function onFocus() {
|
|
8112
|
+
if (lastInteractionWasKeyboard.current) {
|
|
8113
|
+
setIsFocusVisible(true);
|
|
8114
|
+
}
|
|
8115
|
+
};
|
|
8116
|
+
var onBlur = function onBlur() {
|
|
8117
|
+
return setIsFocusVisible(false);
|
|
8118
|
+
};
|
|
8119
|
+
if (isFocusVisible) {
|
|
8120
|
+
mergedStyle.boxShadow = '0 0 0 2px var(--focus-ring-color, #1976d2)';
|
|
8121
|
+
mergedStyle.backgroundColor = 'rgba(25,118,210,0.06)';
|
|
8122
|
+
}
|
|
8123
|
+
return jsx("div", Object.assign({}, props, {
|
|
8124
|
+
ref: ref,
|
|
8125
|
+
tabIndex: 0,
|
|
8126
|
+
role: "listbox",
|
|
8127
|
+
"aria-label": "Locations list",
|
|
8128
|
+
onKeyDown: handleKeyDown,
|
|
8129
|
+
onFocus: onFocus,
|
|
8130
|
+
onBlur: onBlur,
|
|
8131
|
+
// Remove focus styling immediately on mouse interaction
|
|
8132
|
+
onMouseDown: function onMouseDown() {
|
|
8133
|
+
setIsFocusVisible(false);
|
|
8134
|
+
},
|
|
8135
|
+
style: mergedStyle
|
|
8136
|
+
}));
|
|
8137
|
+
});
|
|
7929
8138
|
var LocationDropdown = function LocationDropdown(_ref) {
|
|
7930
8139
|
var _combinedSelectedLoca;
|
|
7931
8140
|
var geoJson = _ref.geoJson,
|
|
@@ -7933,10 +8142,11 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
7933
8142
|
handleChange = _ref.handleChange,
|
|
7934
8143
|
selectedLocation = _ref.selectedLocation,
|
|
7935
8144
|
_ref$isDisabled = _ref.isDisabled,
|
|
7936
|
-
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
8145
|
+
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
|
|
8146
|
+
defaultExpanded = _ref.defaultExpanded;
|
|
8147
|
+
var _React$useState2 = React.useState(''),
|
|
8148
|
+
searchTerm = _React$useState2[0],
|
|
8149
|
+
setSearchTerm = _React$useState2[1];
|
|
7940
8150
|
var combinedSelectedLocation = geoJson == null ? void 0 : geoJson.features.find(function (feature) {
|
|
7941
8151
|
var _feature$properties;
|
|
7942
8152
|
return selectedLocation === ((_feature$properties = feature.properties) == null ? void 0 : _feature$properties.name);
|
|
@@ -7955,8 +8165,11 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
7955
8165
|
});
|
|
7956
8166
|
});
|
|
7957
8167
|
}, [searchTerm, splitGeoJson]);
|
|
8168
|
+
var listContainerRef = React.useRef(null);
|
|
8169
|
+
var heightObserver = useResizeObserver(listContainerRef, filteredResults);
|
|
7958
8170
|
return jsx(Box, {
|
|
7959
8171
|
"data-testid": "locationDropdownContainer",
|
|
8172
|
+
ref: listContainerRef,
|
|
7960
8173
|
sx: {
|
|
7961
8174
|
width: '100%',
|
|
7962
8175
|
height: '100%',
|
|
@@ -8000,16 +8213,17 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
8000
8213
|
title: collectionName,
|
|
8001
8214
|
title2: serviceName,
|
|
8002
8215
|
amountOfItems: collectionGeoJson.features.length || 0,
|
|
8003
|
-
defaultExpanded: false,
|
|
8216
|
+
defaultExpanded: defaultExpanded || false,
|
|
8004
8217
|
sx: {
|
|
8005
8218
|
mx: 1,
|
|
8006
8219
|
mb: 1
|
|
8007
8220
|
},
|
|
8008
8221
|
children: jsx(FixedSizeList, {
|
|
8009
|
-
height:
|
|
8222
|
+
height: heightObserver,
|
|
8010
8223
|
width: "100%",
|
|
8011
8224
|
itemSize: 40,
|
|
8012
8225
|
itemCount: collectionGeoJson.features.length,
|
|
8226
|
+
outerElementType: FocusableListOuter,
|
|
8013
8227
|
children: renderRow(collectionGeoJson.features, handleChange, collectionSelectedLocation == null || (_collectionSelectedLo = collectionSelectedLocation.properties) == null ? void 0 : _collectionSelectedLo.name, isDisabled)
|
|
8014
8228
|
})
|
|
8015
8229
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/time-series",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.2.1",
|
|
4
4
|
"description": "GeoWeb time-series library for the opengeoweb project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -9,26 +9,26 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"immer": "^10.0.3",
|
|
12
|
-
"@opengeoweb/shared": "14.
|
|
12
|
+
"@opengeoweb/shared": "14.2.1",
|
|
13
13
|
"@reduxjs/toolkit": "^2.6.1",
|
|
14
14
|
"react-redux": "^9.2.0",
|
|
15
|
-
"@opengeoweb/webmap": "14.
|
|
16
|
-
"@opengeoweb/webmap-react": "14.
|
|
15
|
+
"@opengeoweb/webmap": "14.2.1",
|
|
16
|
+
"@opengeoweb/webmap-react": "14.2.1",
|
|
17
17
|
"lodash": "^4.17.21",
|
|
18
|
-
"@opengeoweb/api": "14.
|
|
19
|
-
"@opengeoweb/theme": "14.
|
|
20
|
-
"@opengeoweb/store": "14.
|
|
18
|
+
"@opengeoweb/api": "14.2.1",
|
|
19
|
+
"@opengeoweb/theme": "14.2.1",
|
|
20
|
+
"@opengeoweb/store": "14.2.1",
|
|
21
21
|
"echarts-for-react": "^3.0.2",
|
|
22
22
|
"echarts": "^5.4.3",
|
|
23
23
|
"react-sortablejs": "^6.1.4",
|
|
24
|
-
"@opengeoweb/snackbar": "14.
|
|
24
|
+
"@opengeoweb/snackbar": "14.2.1",
|
|
25
25
|
"react-window": "^1.8.10",
|
|
26
26
|
"react-virtualized-auto-sizer": "^1.0.21",
|
|
27
27
|
"msw": "^2.7.3",
|
|
28
28
|
"i18next": "^25.0.1",
|
|
29
29
|
"react-i18next": "^15.1.1",
|
|
30
|
-
"@opengeoweb/core": "14.
|
|
31
|
-
"@opengeoweb/form-fields": "14.
|
|
30
|
+
"@opengeoweb/core": "14.2.1",
|
|
31
|
+
"@opengeoweb/form-fields": "14.2.1",
|
|
32
32
|
"@mui/material": "^7.0.1",
|
|
33
33
|
"react-hook-form": "^7.61.1",
|
|
34
34
|
"uuid": "^10.0.0",
|
|
@@ -6,4 +6,6 @@ type Story = StoryObj<typeof LocationDropdown>;
|
|
|
6
6
|
export declare const Component: Story;
|
|
7
7
|
export declare const ComponentDark: Story;
|
|
8
8
|
export declare const LocationDropdownDemoLight: Story;
|
|
9
|
+
export declare const LocationDropdownExpandedDemoLight: Story;
|
|
9
10
|
export declare const LocationDropdownDemoDark: Story;
|
|
11
|
+
export declare const LocationDropdownExpandedDemoDark: Story;
|
|
@@ -3,6 +3,8 @@ import { ServiceFilterChipsObjectEntities } from '../../store/types';
|
|
|
3
3
|
import { CustomDimension, EDRDataQueriesObject, EDRExtentObject, SelectParameter } from '../TimeSeries/types';
|
|
4
4
|
export interface TimeseriesCollectionDetail {
|
|
5
5
|
collectionId: string;
|
|
6
|
+
collectionTitle?: string;
|
|
7
|
+
collectionDescription?: string;
|
|
6
8
|
serviceId: string;
|
|
7
9
|
serviceName: string;
|
|
8
10
|
parameters: SelectParameter[];
|