@opengeoweb/time-series 14.1.0 → 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';
|
|
@@ -7830,7 +7830,26 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7830
7830
|
var theme = useTheme();
|
|
7831
7831
|
var _useTimeseriesTransla = useTimeseriesTranslation();
|
|
7832
7832
|
_useTimeseriesTransla.t;
|
|
7833
|
+
// Wrapper ref used for hover detection AND restoring keyboard focus after selection.
|
|
7833
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]);
|
|
7834
7853
|
var textContainerRef = React__default.useRef(null);
|
|
7835
7854
|
var _React$useState = React__default.useState(false),
|
|
7836
7855
|
isHovering = _React$useState[0],
|
|
@@ -7866,6 +7885,23 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7866
7885
|
setTextContainerWidth(textContainerRef.current.clientWidth);
|
|
7867
7886
|
}
|
|
7868
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]);
|
|
7869
7905
|
return jsx(OverflowTooltip, {
|
|
7870
7906
|
text: location,
|
|
7871
7907
|
textContainerWidth: textContainerWidth,
|
|
@@ -7875,6 +7911,29 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7875
7911
|
onMouseLeave: handleMouseLeave,
|
|
7876
7912
|
onFocus: handleMouseEnter,
|
|
7877
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
|
+
},
|
|
7878
7937
|
children: jsxs(ListItem, Object.assign({
|
|
7879
7938
|
"data-testid": "locationDropdownListItem",
|
|
7880
7939
|
role: "listitem"
|
|
@@ -7909,7 +7968,19 @@ var LocationListItem = function LocationListItem(_ref) {
|
|
|
7909
7968
|
backgroundColor: 'transparent'
|
|
7910
7969
|
}
|
|
7911
7970
|
},
|
|
7912
|
-
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
|
+
}
|
|
7913
7984
|
})
|
|
7914
7985
|
}), jsx(Typography, {
|
|
7915
7986
|
ref: textContainerRef,
|
|
@@ -7949,6 +8020,121 @@ var renderRow = function renderRow(features, handleChange, selectedLocation, isD
|
|
|
7949
8020
|
};
|
|
7950
8021
|
};
|
|
7951
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
|
+
});
|
|
7952
8138
|
var LocationDropdown = function LocationDropdown(_ref) {
|
|
7953
8139
|
var _combinedSelectedLoca;
|
|
7954
8140
|
var geoJson = _ref.geoJson,
|
|
@@ -7956,10 +8142,11 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
7956
8142
|
handleChange = _ref.handleChange,
|
|
7957
8143
|
selectedLocation = _ref.selectedLocation,
|
|
7958
8144
|
_ref$isDisabled = _ref.isDisabled,
|
|
7959
|
-
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
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];
|
|
7963
8150
|
var combinedSelectedLocation = geoJson == null ? void 0 : geoJson.features.find(function (feature) {
|
|
7964
8151
|
var _feature$properties;
|
|
7965
8152
|
return selectedLocation === ((_feature$properties = feature.properties) == null ? void 0 : _feature$properties.name);
|
|
@@ -7978,8 +8165,11 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
7978
8165
|
});
|
|
7979
8166
|
});
|
|
7980
8167
|
}, [searchTerm, splitGeoJson]);
|
|
8168
|
+
var listContainerRef = React.useRef(null);
|
|
8169
|
+
var heightObserver = useResizeObserver(listContainerRef, filteredResults);
|
|
7981
8170
|
return jsx(Box, {
|
|
7982
8171
|
"data-testid": "locationDropdownContainer",
|
|
8172
|
+
ref: listContainerRef,
|
|
7983
8173
|
sx: {
|
|
7984
8174
|
width: '100%',
|
|
7985
8175
|
height: '100%',
|
|
@@ -8023,16 +8213,17 @@ var LocationDropdown = function LocationDropdown(_ref) {
|
|
|
8023
8213
|
title: collectionName,
|
|
8024
8214
|
title2: serviceName,
|
|
8025
8215
|
amountOfItems: collectionGeoJson.features.length || 0,
|
|
8026
|
-
defaultExpanded: false,
|
|
8216
|
+
defaultExpanded: defaultExpanded || false,
|
|
8027
8217
|
sx: {
|
|
8028
8218
|
mx: 1,
|
|
8029
8219
|
mb: 1
|
|
8030
8220
|
},
|
|
8031
8221
|
children: jsx(FixedSizeList, {
|
|
8032
|
-
height:
|
|
8222
|
+
height: heightObserver,
|
|
8033
8223
|
width: "100%",
|
|
8034
8224
|
itemSize: 40,
|
|
8035
8225
|
itemCount: collectionGeoJson.features.length,
|
|
8226
|
+
outerElementType: FocusableListOuter,
|
|
8036
8227
|
children: renderRow(collectionGeoJson.features, handleChange, collectionSelectedLocation == null || (_collectionSelectedLo = collectionSelectedLocation.properties) == null ? void 0 : _collectionSelectedLo.name, isDisabled)
|
|
8037
8228
|
})
|
|
8038
8229
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/time-series",
|
|
3
|
-
"version": "14.1
|
|
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.1
|
|
12
|
+
"@opengeoweb/shared": "14.2.1",
|
|
13
13
|
"@reduxjs/toolkit": "^2.6.1",
|
|
14
14
|
"react-redux": "^9.2.0",
|
|
15
|
-
"@opengeoweb/webmap": "14.1
|
|
16
|
-
"@opengeoweb/webmap-react": "14.1
|
|
15
|
+
"@opengeoweb/webmap": "14.2.1",
|
|
16
|
+
"@opengeoweb/webmap-react": "14.2.1",
|
|
17
17
|
"lodash": "^4.17.21",
|
|
18
|
-
"@opengeoweb/api": "14.1
|
|
19
|
-
"@opengeoweb/theme": "14.1
|
|
20
|
-
"@opengeoweb/store": "14.1
|
|
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.1
|
|
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.1
|
|
31
|
-
"@opengeoweb/form-fields": "14.1
|
|
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;
|