@opengeoweb/shared 9.22.0 → 9.24.0

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
@@ -1,15 +1,14 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { Box, Typography, Tooltip, IconButton, Dialog, DialogTitle, DialogContent, DialogActions, Button, CircularProgress, Alert, AlertTitle, useTheme, Drawer, Link, Avatar as Avatar$1, Paper, ClickAwayListener, MenuList, MenuItem, Grid, RadioGroup, FormControlLabel, Radio, List, ListItem, Tabs, Tab, Backdrop, Switch, Slider, ToggleButton, Menu, ListSubheader, ListItemText, ListItemIcon, Select, Accordion, AccordionSummary, AccordionDetails, FormLabel, TextField, InputAdornment } from '@mui/material';
2
+ import { Box, Typography, Tooltip, IconButton, Dialog, DialogTitle, DialogContent, DialogActions, Button, CircularProgress, Alert, AlertTitle, useTheme, Drawer, Link, Avatar as Avatar$1, Paper, ClickAwayListener, MenuList, MenuItem, Grid, RadioGroup, FormControlLabel, Radio, List, ListItem, Tabs, Tab, Backdrop, Switch, Slider, ToggleButton, Menu, ListSubheader, ListItemText, ListItemIcon, styled, Select, Accordion, AccordionSummary, AccordionDetails, FormLabel, TextField, InputAdornment, Chip, Stack, debounce as debounce$1, Checkbox, ListItemSecondaryAction } from '@mui/material';
3
3
  import { Close, Exclamation, Success, Info, ChevronRight, GeoWebLogo, HamburgerMenu, Resize, Admin, useThemeContext, DragHandle, ArrowLeft, ArrowRight, KeyOption, ArrowUp, ArrowDown, KeyCommand, Options, ChevronDown, Search, Clear, Cached } from '@opengeoweb/theme';
4
4
  import * as React from 'react';
5
5
  import React__default, { useRef, Component } from 'react';
6
6
  import i18n from 'i18next';
7
- import { useTranslation } from 'react-i18next';
7
+ import { initReactI18next, useTranslation } from 'react-i18next';
8
8
  import { throttle, escapeRegExp, debounce } from 'lodash';
9
9
  import Draggable from 'react-draggable';
10
10
  import { Resizable } from 're-resizable';
11
11
  import * as Sentry from '@sentry/react';
12
- import { styled } from '@mui/material/styles';
13
12
  import { useStore } from 'react-redux';
14
13
  import { parseISO, parse, format, isEqual, add as add$1, sub as sub$1, differenceInYears as differenceInYears$1, differenceInMonths as differenceInMonths$1, differenceInDays as differenceInDays$1, differenceInMinutes as differenceInMinutes$1, differenceInHours as differenceInHours$1, differenceInSeconds as differenceInSeconds$1, isBefore as isBefore$1, isAfter as isAfter$1, isValid as isValid$1, getUnixTime, fromUnixTime, set as set$3, getHours as getHours$1, startOfDay, addMinutes, addHours, getDay, getDayOfYear, getMonth, getWeek, getYear, isWithinInterval } from 'date-fns';
15
14
  import configureStore from 'redux-mock-store';
@@ -64,58 +63,72 @@ var en = {
64
63
  "shared-sentry-disable-both": "Enable HTML + Canvas recording",
65
64
  "shared-sentry-cors-wait": "Disabled untill with and without CORS headers fetching mechanism has been implemented",
66
65
  "shared-sentry-disclaimer": "I understand that while using canvas recording, adding a layer without correct CORS headers will cause error and make the recording to fail. A new recording without the canvas or the layer can be made after reloading the application.",
67
- "shared-clear": "Clear"
66
+ "shared-clear": "Clear",
67
+ "shared-light": "Light",
68
+ "shared-dark": "Dark",
69
+ "shared-filter-all": "All",
70
+ "shared-filter-my-presets": "My presets",
71
+ "shared-filter-system-presets": "System presets",
72
+ "shared-filter-search": "Search",
73
+ "shared-only": "ONLY"
68
74
  };
69
75
  var fi = {
70
- "shared-choose-app-mode": "ei käännetty",
71
- "shared-cheat-sheet": "ei käännetty",
72
- "shared-save": "ei käännetty",
73
- "shared-viewer": "ei käännetty",
74
- "shared-editor": "ei käännetty",
75
- "shared-reload-page": "ei käännetty",
76
- "shared-search-label": "ei käännetty",
77
- "shared-last-updated": "ei käännetty",
78
- "shared-click-to-refresh": "ei käännetty",
79
- "shared-error-occurred": "ei käännetty",
80
- "shared-confirmation-description": "ei käännetty",
81
- "shared-confirmation-cancel": "ei käännetty",
82
- "shared-confirmation-submit": "ei käännetty",
83
- "shared-close-caps": "ei käännetty",
84
- "shared-close": "ei käännetty",
85
- "shared-search": "ei käännetty",
86
- "shared-choose-selected-time": "ei käännetty",
87
- "shared-move-selected-time": "ei käännetty",
88
- "shared-move-one-step": "ei käännetty",
89
- "shared-toggle-timeslider": "ei käännetty",
90
- "shared-timeslider-scale": "ei käännetty",
91
- "shared-expand-timeslider-scale": "ei käännetty",
92
- "shared-mouseover-selected-time": "ei käännetty",
93
- "shared-mouseover-on-off": "ei käännetty",
94
- "shared-change-timestep-or-speed": "ei käännetty",
95
- "shared-return-to-current-time": "ei käännettye",
96
- "shared-change-layer-values-scrolling": "ei käännetty",
97
- "shared-change-layermanager-small": "ei käännetty",
98
- "shared-change-layermanager-medium": "ei käännetty",
99
- "shared-change-layermanager-large": "ei käännetty",
100
- "shared-shortcut-left-click": "ei käännetty",
101
- "shared-shortcut-mouse-scroll-timeslider": "ei käännetty",
102
- "shared-shortcut-hold-click": "ei käännetty",
103
- "shared-shortcut-scroll": "ei käännetty",
104
- "shared-shortcut-hover": "ei käännetty",
105
- "shared-shortcut-when-active": "ei käännetty",
106
- "shared-shortcut-home": "ei käännetty",
107
- "shared-shortcut-mouse-scroll": "ei käännetty",
108
- "shared-shortcut-or": "ei käännetty",
109
- "shared-sentry-recording": "ei käännetty",
110
- "shared-sentry-information": "ei käännetty",
111
- "shared-sentry-enable-message": "ei käännetty",
112
- "shared-sentry-disable": "ei käännetty",
113
- "shared-sentry-enable": "ei käännetty",
114
- "shared-sentry-enable-both": "ei käännetty",
115
- "shared-sentry-disable-both": "ei käännetty",
116
- "shared-sentry-cors-wait": "ei käännetty",
117
- "shared-sentry-disclaimer": "ei käännetty",
118
- "shared-clear": "ei käännetty"
76
+ "shared-choose-app-mode": "Sovelluksen väriteema",
77
+ "shared-cheat-sheet": "Lunttilappu",
78
+ "shared-save": "Tallenna",
79
+ "shared-viewer": "Katselu",
80
+ "shared-editor": "Muokkain",
81
+ "shared-reload-page": "Lataa sivu uudelleen",
82
+ "shared-search-label": "Etsi palveluista tai lisää palvelun URL-osoite",
83
+ "shared-last-updated": "Päivitetty viimeksi {{time}}",
84
+ "shared-click-to-refresh": "Napsauta päivittääksesi",
85
+ "shared-error-occurred": "Hups, virhe havaittu. Ilmoita ongelmasta eteenpäin ja lataa sivu uudelleen tarvittaessa",
86
+ "shared-confirmation-description": "Oletko varma?",
87
+ "shared-confirmation-cancel": "Palaa takaisin",
88
+ "shared-confirmation-submit": "Lähetä",
89
+ "shared-close-caps": "SULJE",
90
+ "shared-close": "Sulje",
91
+ "shared-search": "Etsi",
92
+ "shared-choose-selected-time": "Valitse valittu aika",
93
+ "shared-move-selected-time": "Liiku ajassa taaksepäin/eteenpäin",
94
+ "shared-move-one-step": "Liiku 1 askel ajassa taaksepäin/eteenpäin",
95
+ "shared-toggle-timeslider": "Kytke TimeSlider näkyville/pois näkyvistä",
96
+ "shared-timeslider-scale": "Muuta TimeSliderin näkyvää aikaväliä",
97
+ "shared-expand-timeslider-scale": "Laajenna/kutista TimeSliderin mittakaavaa (näkyvää aikaväliä)",
98
+ "shared-mouseover-selected-time": "Osoita ja liikuta hiirtä muuttaaksesi valittua aikaa",
99
+ "shared-mouseover-on-off": "Kytke hiiren vaikutus TimeSlideriin päälle/pois päältä",
100
+ "shared-change-timestep-or-speed": "Muuta aika-askelta tai animaation nopeutta",
101
+ "shared-return-to-current-time": "Palaa nykyhetkeen",
102
+ "shared-change-layer-values-scrolling": "Muuta Layer Managerin arvoja vierittämällä hiirtä",
103
+ "shared-change-layermanager-small": "Muuta Layer Managerin kokoa pieneksi",
104
+ "shared-change-layermanager-medium": "Muuta Layer Managerin kokoa keskikokoiseksi",
105
+ "shared-change-layermanager-large": "Muuta Layer Managerin kokoa suureksi",
106
+ "shared-shortcut-left-click": "Napsauta TimeSlider aikajanaa hiiren vasemmalla painikkeella",
107
+ "shared-shortcut-mouse-scroll-timeslider": "Vieritä hiiren rullaa TimeSlider aikajanana päällä",
108
+ "shared-shortcut-hold-click": "Napsauta aikajanaa hiiren vasemmalla painikkeella ja raahaa vasemmalle tai oikealle",
109
+ "shared-shortcut-scroll": "+ vieritä hiiren rullaa TimeSlider aikajanan päällä",
110
+ "shared-shortcut-hover": "Vie hiiri TimeSlider aikajanan tai ajan esittäjän päälle",
111
+ "shared-shortcut-when-active": "kun aikajana on aktiivinen",
112
+ "shared-shortcut-home": "Koti",
113
+ "shared-shortcut-mouse-scroll": "+ hiiren rulla",
114
+ "shared-shortcut-or": "tai",
115
+ "shared-sentry-recording": "Sentry Tallennus",
116
+ "shared-sentry-information": "Geoweb tallentaa tietoja sovelluksen käytöstä monitoroidakseen suorituskykyä, sekä virhetilanteita. Arkaluonteista dataa ei kerätä tai lähetetä.",
117
+ "shared-sentry-enable-message": "Ymmärrän, että laittamalla tallennuksen päälle tallennukseen liittyvää dataa lähetetään Sentryn palvelimille.",
118
+ "shared-sentry-disable": "Laita HTML tallennus pois päältä",
119
+ "shared-sentry-enable": "Laita HTML tallennus päälle",
120
+ "shared-sentry-enable-both": "Laita HTML + Canvas tallennus päälle",
121
+ "shared-sentry-disable-both": "Laita HTML + Canvas tallennus pois päältä",
122
+ "shared-sentry-cors-wait": "Ominaisuus kytketty pois päältä, kunnes sovelluksen latausprosessit tukevat CORS headerien puuttumista.",
123
+ "shared-sentry-disclaimer": "Ymmärrän, että käyttäessäni Canvas-tallennusta ja lisätessäni karttatason, jonka CORS headerit eivät ola kunnosa, sovelluksessa tapahtuu virhe, joka johtaa tallennnuksen epäonnistumiseen. Uuden tallennuksen voi tehdä ilman Canvaksen tallentamista sen jälkeen, kun sovellus on ladattu uudelleen.",
124
+ "shared-clear": "Tyhjennä",
125
+ "shared-light": "Vaalea",
126
+ "shared-dark": "Tumma",
127
+ "shared-filter-all": "Kaikki",
128
+ "shared-filter-my-presets": "Omat presetit",
129
+ "shared-filter-system-presets": "Järestelmä presetit",
130
+ "shared-filter-search": "Etsi",
131
+ "shared-only": "Pelkästään"
119
132
  };
120
133
  var no = {
121
134
  "shared-choose-app-mode": "Velg din standardmodus",
@@ -166,7 +179,14 @@ var no = {
166
179
  "shared-sentry-disable-both": "Skru på HTML + lerret-opptak",
167
180
  "shared-sentry-cors-wait": "Avskrudd inntil CORS-relaterte headere er implementert",
168
181
  "shared-sentry-disclaimer": "Jeg forstår at ved å bruke lerretopptak vil opptaket feile dersom jeg legger til et lag uten riktig CORS-headere. Ved å laste inn applikasjonen på nytt kan man starte nytt opptak uten lerret eller lag.",
169
- "shared-clear": "ikke oversatt"
182
+ "shared-clear": "Tøm",
183
+ "shared-light": "Lys",
184
+ "shared-dark": "Mørk",
185
+ "shared-filter-all": "Alle",
186
+ "shared-filter-my-presets": "Mine presets",
187
+ "shared-filter-system-presets": "System presets",
188
+ "shared-filter-search": "Søk",
189
+ "shared-only": "BARE"
170
190
  };
171
191
  var nl = {
172
192
  "shared-choose-app-mode": "Kies je standaard app-modus",
@@ -217,7 +237,14 @@ var nl = {
217
237
  "shared-sentry-disable-both": "HTML + Canvas opname starten",
218
238
  "shared-sentry-cors-wait": "Uitgeschakeld totdat het fetching mechanisme met en zonder CORS-headers is geïmplementeerd",
219
239
  "shared-sentry-disclaimer": "Ik begrijp dat bij het gebruik van canvasopnamen het toevoegen van een laag zonder de juiste CORS-headers fouten zal veroorzaken en ervoor zal zorgen dat de opname mislukt. Een nieuwe opname zonder het canvas of de laag kan worden gemaakt na het opnieuw laden van de applicatie.",
220
- "shared-clear": "Wissen"
240
+ "shared-clear": "Wissen",
241
+ "shared-light": "Licht",
242
+ "shared-dark": "Donker",
243
+ "shared-filter-all": "Alle",
244
+ "shared-filter-my-presets": "Mijn presets",
245
+ "shared-filter-system-presets": "Systeem presets",
246
+ "shared-filter-search": "Zoeken",
247
+ "shared-only": "ALLEEN"
221
248
  };
222
249
  var sharedTranslations = {
223
250
  en: en,
@@ -2223,9 +2250,35 @@ const CustomDialog = _a => {
2223
2250
  };
2224
2251
 
2225
2252
  const SHARED_NAMESPACE = 'shared';
2253
+ const initSharedI18n = () => {
2254
+ i18n.use(initReactI18next).init({
2255
+ lng: 'en',
2256
+ fallbackLng: 'en',
2257
+ ns: SHARED_NAMESPACE,
2258
+ interpolation: {
2259
+ escapeValue: false
2260
+ },
2261
+ resources: {
2262
+ en: {
2263
+ [SHARED_NAMESPACE]: sharedTranslations.en
2264
+ },
2265
+ fi: {
2266
+ [SHARED_NAMESPACE]: sharedTranslations.fi
2267
+ },
2268
+ no: {
2269
+ [SHARED_NAMESPACE]: sharedTranslations.no
2270
+ },
2271
+ nl: {
2272
+ [SHARED_NAMESPACE]: sharedTranslations.nl
2273
+ }
2274
+ }
2275
+ });
2276
+ };
2277
+ initSharedI18n();
2226
2278
  const translateKeyOutsideComponents = (key, params = undefined) => i18n.t(key, Object.assign({
2227
2279
  ns: SHARED_NAMESPACE
2228
2280
  }, params));
2281
+ const useSharedTranslation = () => useTranslation([SHARED_NAMESPACE]);
2229
2282
 
2230
2283
  const confirmStyle = {
2231
2284
  width: {
@@ -4796,13 +4849,13 @@ const MenuItemTheme = () => {
4796
4849
  control: jsx(Radio, {
4797
4850
  checked: !isDark
4798
4851
  }),
4799
- label: "Light"
4852
+ label: t('shared-light')
4800
4853
  }), jsx(FormControlLabel, {
4801
4854
  value: false,
4802
4855
  control: jsx(Radio, {
4803
4856
  checked: isDark
4804
4857
  }),
4805
- label: "Dark"
4858
+ label: t('shared-dark')
4806
4859
  })]
4807
4860
  }))
4808
4861
  }))]
@@ -5187,7 +5240,7 @@ const useHandleSizeFromOutsideComponent = ({
5187
5240
  // handle size from outside component
5188
5241
  React__default.useEffect(() => {
5189
5242
  const boundsNode = getBoundsNode();
5190
- if (boundsNode && lastSize.current.width && lastSize.current.height && (lastSize.current.width !== startSize.width || lastSize.current.height !== startSize.height) && typeof startSize.height === 'number' && typeof startSize.width === 'number') {
5243
+ if (boundsNode && lastSize.current.width && lastSize.current.height && (lastSize.current.width !== startSize.width || lastSize.current.height !== startSize.height) && typeof startSize.height === 'number' && typeof startSize.width === 'number' && nodeRef.current) {
5191
5244
  const {
5192
5245
  position: newPosition,
5193
5246
  size: newSize
@@ -5204,7 +5257,7 @@ const useHandleSizeFromOutsideComponent = ({
5204
5257
  const boundsTarget = entry[0].target;
5205
5258
  const element = nodeRef.current;
5206
5259
  const boundsBbox = boundsTarget.getBoundingClientRect();
5207
- if (boundsBbox.height === lastSize.current.height && boundsBbox.width === lastSize.current.width || !boundsBbox.height) {
5260
+ if (boundsBbox.height === lastSize.current.height && boundsBbox.width === lastSize.current.width || !boundsBbox.height || !element || !boundsBbox) {
5208
5261
  return;
5209
5262
  }
5210
5263
  const {
@@ -7732,7 +7785,7 @@ $({ target: 'RegExp', proto: true, forced: !DELEGATES_TO_EXEC }, {
7732
7785
  });
7733
7786
 
7734
7787
  const isURL = string => /^https?:\/\//.test(string);
7735
- const ClearButton = ({
7788
+ const ClearButton$1 = ({
7736
7789
  onClick
7737
7790
  }) => jsx(CustomIconButton, Object.assign({
7738
7791
  tooltipTitle: translateKeyOutsideComponents('shared-clear'),
@@ -7763,7 +7816,7 @@ const SearchFieldButton = ({
7763
7816
  marginRight: '15px'
7764
7817
  }
7765
7818
  }, {
7766
- children: jsx(ClearButton, {
7819
+ children: jsx(ClearButton$1, {
7767
7820
  onClick: () => onClickClear()
7768
7821
  })
7769
7822
  })), jsx(Button, Object.assign({
@@ -7775,7 +7828,7 @@ const SearchFieldButton = ({
7775
7828
  });
7776
7829
  }
7777
7830
  if (localSearchString) {
7778
- return jsx(ClearButton, {
7831
+ return jsx(ClearButton$1, {
7779
7832
  onClick: () => onClickClear()
7780
7833
  });
7781
7834
  }
@@ -7787,7 +7840,7 @@ const SearchFieldButton = ({
7787
7840
  }));
7788
7841
  };
7789
7842
 
7790
- const SearchField = ({
7843
+ const SearchField$1 = ({
7791
7844
  searchFilter,
7792
7845
  label,
7793
7846
  setSearchFilter,
@@ -8266,6 +8319,292 @@ CanvasComponent.defaultProps = {
8266
8319
  }
8267
8320
  };
8268
8321
 
8322
+ const FilterChip = ({
8323
+ label,
8324
+ id,
8325
+ isSelected: _isSelected = false,
8326
+ isDisabled: _isDisabled = false,
8327
+ handleClick: _handleClick = () => {},
8328
+ onAction,
8329
+ actionIcon
8330
+ }) => {
8331
+ const theme = useTheme();
8332
+ const size = actionIcon && onAction ? 'medium' : 'small';
8333
+ return jsx(Chip, {
8334
+ size: size,
8335
+ id: id,
8336
+ label: label,
8337
+ disabled: _isDisabled,
8338
+ variant: _isSelected ? 'filled' : 'outlined',
8339
+ color: _isSelected ? 'secondary' : 'default',
8340
+ sx: {
8341
+ borderColor: `${theme.palette.geowebColors.buttons.tertiary.default.borderColor}`,
8342
+ padding: '0px 4px',
8343
+ '& .MuiSvgIcon-root, .MuiChip-deleteIcon': {
8344
+ fill: _isSelected ? theme.palette.geowebColors.buttons.secondary.active.color : theme.palette.geowebColors.buttons.flat.default.color,
8345
+ color: _isSelected ? theme.palette.geowebColors.buttons.secondary.active.color : theme.palette.geowebColors.buttons.flat.default.color,
8346
+ paddingLeft: _isSelected ? 0 : '2px'
8347
+ },
8348
+ '& .MuiChip-filled': {
8349
+ border: '1px solid transparent'
8350
+ },
8351
+ '& .MuiChip-labelMedium': {
8352
+ overflow: 'visible'
8353
+ }
8354
+ },
8355
+ onClick: () => _handleClick(id),
8356
+ deleteIcon: actionIcon,
8357
+ onDelete: onAction
8358
+ });
8359
+ };
8360
+
8361
+ const FilterList = ({
8362
+ filters: _filters = [],
8363
+ onChipClick: _onChipClick = () => {},
8364
+ isAllSelected: _isAllSelected = false
8365
+ }) => {
8366
+ const {
8367
+ t
8368
+ } = useSharedTranslation();
8369
+ return jsxs(Stack, Object.assign({
8370
+ direction: "row",
8371
+ spacing: 1,
8372
+ "data-testid": "filterList",
8373
+ className: "filter-list"
8374
+ }, {
8375
+ children: [jsx(FilterChip, {
8376
+ id: "all",
8377
+ label: t('shared-filter-all'),
8378
+ isSelected: _isAllSelected,
8379
+ handleClick: key => _onChipClick(key, !_isAllSelected)
8380
+ }), _filters.map(filter => {
8381
+ return jsx(FilterChip, {
8382
+ id: filter.id,
8383
+ label: t(filter.label),
8384
+ isSelected: _isAllSelected ? false : filter.isSelected,
8385
+ isDisabled: filter.isDisabled,
8386
+ handleClick: key => {
8387
+ // If they are all isSelected ensure that if one is clicked that one will be the only one set to selected
8388
+ const selected = _isAllSelected ? true : !filter.isSelected;
8389
+ _onChipClick(key, selected);
8390
+ }
8391
+ }, filter.id);
8392
+ })]
8393
+ }));
8394
+ };
8395
+
8396
+ const DEBOUNCE_TIMEOUT = 300;
8397
+ const SearchButton = ({
8398
+ label
8399
+ }) => jsx(CustomIconButton, Object.assign({
8400
+ tooltipTitle: label,
8401
+ edge: "end",
8402
+ size: "large"
8403
+ }, {
8404
+ children: jsx(Search, {})
8405
+ }));
8406
+ const ClearButton = ({
8407
+ onClick
8408
+ }) => jsx(CustomIconButton, Object.assign({
8409
+ tooltipTitle: "Clear",
8410
+ edge: "end",
8411
+ onClick: onClick,
8412
+ size: "large"
8413
+ }, {
8414
+ children: jsx(Clear, {})
8415
+ }));
8416
+ const SearchField = ({
8417
+ valueChanged,
8418
+ value: _value = ''
8419
+ }) => {
8420
+ const [localValue, setLocalValue] = React.useState(_value);
8421
+ const {
8422
+ t
8423
+ } = useSharedTranslation();
8424
+ const label = t('shared-filter-search');
8425
+ // eslint-disable-next-line react-hooks/exhaustive-deps
8426
+ const handleValueChangeDebounced = React.useCallback(debounce$1(valueChanged, DEBOUNCE_TIMEOUT), []);
8427
+ return jsx(TextField, {
8428
+ variant: "filled",
8429
+ size: "small",
8430
+ sx: {
8431
+ '& input': {
8432
+ paddingTop: '18px'
8433
+ }
8434
+ },
8435
+ label: label,
8436
+ value: localValue,
8437
+ autoFocus: true,
8438
+ fullWidth: true,
8439
+ onChange: e => {
8440
+ handleValueChangeDebounced(e.target.value);
8441
+ setLocalValue(e.target.value);
8442
+ },
8443
+ InputProps: {
8444
+ endAdornment: jsx(InputAdornment, Object.assign({
8445
+ position: "end"
8446
+ }, {
8447
+ children: localValue ? jsx(ClearButton, {
8448
+ onClick: () => {
8449
+ setLocalValue('');
8450
+ valueChanged('');
8451
+ }
8452
+ }) : jsx(SearchButton, {
8453
+ label: label
8454
+ })
8455
+ }))
8456
+ }
8457
+ });
8458
+ };
8459
+
8460
+ const DEFAULT_FILTER_HEIGHT = 85;
8461
+ const Filter = /*#__PURE__*/React.forwardRef((_a, ref) => {
8462
+ var {
8463
+ filters,
8464
+ onClickFilterChip = () => {},
8465
+ onSearch = () => {},
8466
+ isAllSelected,
8467
+ searchQuery
8468
+ } = _a,
8469
+ props = __rest(_a, ["filters", "onClickFilterChip", "onSearch", "isAllSelected", "searchQuery"]);
8470
+ return jsx(Box, Object.assign({
8471
+ sx: Object.assign({
8472
+ marginBottom: '8px'
8473
+ }, props.sx),
8474
+ ref: ref
8475
+ }, {
8476
+ children: jsxs(Stack, Object.assign({
8477
+ spacing: 1
8478
+ }, {
8479
+ children: [jsx(SearchField, {
8480
+ value: searchQuery,
8481
+ valueChanged: onSearch
8482
+ }), jsx(FilterList, {
8483
+ filters: filters,
8484
+ onChipClick: onClickFilterChip,
8485
+ isAllSelected: isAllSelected
8486
+ })]
8487
+ }))
8488
+ }));
8489
+ });
8490
+
8491
+ const FilterListItem = ({
8492
+ filter,
8493
+ toggleFilter,
8494
+ enableOnlyOneFilter
8495
+ }) => {
8496
+ const {
8497
+ t
8498
+ } = useSharedTranslation();
8499
+ const [isHovering, setIsHovering] = React.useState(false);
8500
+ const handleMouseEnter = React.useCallback(() => {
8501
+ setIsHovering(true);
8502
+ }, []);
8503
+ const handleMouseLeave = React.useCallback(() => {
8504
+ setIsHovering(false);
8505
+ }, []);
8506
+ const selectOnlyOne = filterId => {
8507
+ enableOnlyOneFilter(filterId);
8508
+ };
8509
+ const toggleCheckbox = filterId => {
8510
+ toggleFilter([filterId]);
8511
+ };
8512
+ const mouseMoveRef = React.useRef(null);
8513
+ React.useEffect(() => {
8514
+ window.addEventListener('mousemove', checkHover, true);
8515
+ return () => {
8516
+ window.removeEventListener('mousemove', checkHover, true);
8517
+ };
8518
+ });
8519
+ const checkHover = e => {
8520
+ if (mouseMoveRef.current) {
8521
+ const mouseOver = mouseMoveRef.current.contains(e.target);
8522
+ if (!isHovering && mouseOver) {
8523
+ handleMouseEnter();
8524
+ }
8525
+ if (isHovering && !mouseOver) {
8526
+ handleMouseLeave();
8527
+ }
8528
+ }
8529
+ };
8530
+ const name = filter.amountVisible ? `${filter.name} (${filter.amountVisible})` : filter.name;
8531
+ if (filter.amountVisible !== 0) {
8532
+ return jsx("div", Object.assign({
8533
+ ref: mouseMoveRef,
8534
+ onMouseEnter: handleMouseEnter,
8535
+ onMouseLeave: handleMouseLeave,
8536
+ onFocus: handleMouseEnter,
8537
+ onBlur: handleMouseLeave
8538
+ }, {
8539
+ children: jsxs(ListItem, Object.assign({
8540
+ sx: {
8541
+ width: '100%',
8542
+ minWidth: '300px',
8543
+ padding: '0px',
8544
+ paddingLeft: '0px',
8545
+ paddingRight: '50px',
8546
+ fontSize: '12px'
8547
+ }
8548
+ }, {
8549
+ children: [jsx(ListItemIcon, Object.assign({
8550
+ sx: {
8551
+ minWidth: '42px'
8552
+ }
8553
+ }, {
8554
+ children: jsx(Checkbox, {
8555
+ inputProps: {
8556
+ 'aria-label': filter.name
8557
+ },
8558
+ color: "secondary",
8559
+ checked: filter.checked,
8560
+ onChange: () => {
8561
+ toggleCheckbox(filter.id);
8562
+ },
8563
+ sx: {
8564
+ paddingTop: '6px',
8565
+ paddingBottom: '7px',
8566
+ '&&:hover': {
8567
+ backgroundColor: 'transparent'
8568
+ }
8569
+ }
8570
+ })
8571
+ })), jsx(Typography, Object.assign({
8572
+ variant: "body2",
8573
+ sx: {
8574
+ fontSize: '16px',
8575
+ textOverflow: 'ellipsis',
8576
+ whiteSpace: 'nowrap',
8577
+ overflow: 'hidden'
8578
+ }
8579
+ }, {
8580
+ children: name
8581
+ })), isHovering ? jsx(ListItemSecondaryAction, {
8582
+ children: jsx(CustomIconButton, Object.assign({
8583
+ "aria-label": `Only ${filter.name}`,
8584
+ style: {
8585
+ backgroundColor: 'transparent',
8586
+ width: 'auto'
8587
+ },
8588
+ edge: "end",
8589
+ onClick: () => selectOnlyOne(filter.id)
8590
+ }, {
8591
+ children: jsx(Typography, Object.assign({
8592
+ sx: {
8593
+ color: 'geowebColors.buttons.primary.default.fill',
8594
+ fontSize: '14px',
8595
+ fontWeight: 500
8596
+ }
8597
+ }, {
8598
+ children: t('shared-only')
8599
+ }))
8600
+ }))
8601
+ }) : null]
8602
+ }))
8603
+ }));
8604
+ }
8605
+ return null;
8606
+ };
8607
+
8269
8608
  /* *
8270
8609
  * Licensed under the Apache License, Version 2.0 (the "License");
8271
8610
  * you may not use this file except in compliance with the License.
@@ -8397,6 +8736,7 @@ const DATE_FORMAT_YEAR = 'yyyy-MM-dd';
8397
8736
  const DATE_FORMAT_HOURS = 'HH:mm';
8398
8737
  const DATE_FORMAT_NAME_OF_DAY_MONTH = 'eee dd MMM HH:mm';
8399
8738
  const DATE_FORMAT_NAME_OF_MONTH = 'dd MMM yyyy, HH:mm';
8739
+ const DATE_FORMAT_NAME_OF_DAY = 'eee dd/MM/yyyy HH:mm';
8400
8740
 
8401
8741
  /**
8402
8742
  * Parsing date strings with geoweb dateUtils:
@@ -8932,7 +9272,7 @@ const startOfYearUTC = date => {
8932
9272
  const convertNOWFormatToUTC = timeValue => {
8933
9273
  const now = new Date();
8934
9274
  const today = startOfDay(now);
8935
- const regex = /(NOW|TODAY)([\+\-])PT(\d+)H(\d+)M/;
9275
+ const regex = /(NOW|TODAY)([+-])PT(\d+)H(\d+)M/;
8936
9276
  const matches = timeValue.match(regex);
8937
9277
  if (matches) {
8938
9278
  const base = matches[1] === 'NOW' ? now : today;
@@ -8951,7 +9291,7 @@ const convertNOWFormatToUTC = timeValue => {
8951
9291
  const convertNOWandTODAYFormatsToUTC = timeValue => {
8952
9292
  const now = new Date();
8953
9293
  const today = startOfDayUTC(now);
8954
- const regex = /(NOW|TODAY)([\+\-])PT(\d+)H(\d+)M/;
9294
+ const regex = /(NOW|TODAY)([+-])PT(\d+)H(\d+)M/;
8955
9295
  const matches = timeValue.match(regex);
8956
9296
  if (matches) {
8957
9297
  const base = matches[1] === 'NOW' ? now : today;
@@ -8984,6 +9324,7 @@ var index = /*#__PURE__*/Object.freeze({
8984
9324
  __proto__: null,
8985
9325
  DATE_FORMAT_DATEPICKER: DATE_FORMAT_DATEPICKER,
8986
9326
  DATE_FORMAT_HOURS: DATE_FORMAT_HOURS,
9327
+ DATE_FORMAT_NAME_OF_DAY: DATE_FORMAT_NAME_OF_DAY,
8987
9328
  DATE_FORMAT_NAME_OF_DAY_MONTH: DATE_FORMAT_NAME_OF_DAY_MONTH,
8988
9329
  DATE_FORMAT_NAME_OF_MONTH: DATE_FORMAT_NAME_OF_MONTH,
8989
9330
  DATE_FORMAT_UTC: DATE_FORMAT_UTC,
@@ -9125,4 +9466,4 @@ class RenderCounter {
9125
9466
  }
9126
9467
  const renderCounter = new RenderCounter();
9127
9468
 
9128
- export { AlertBanner, AlertIcon, AppHeader, AppLayout, Avatar, CanvasComponent, ConfirmationDialog, ConfirmationServiceProvider, CustomAccordion, CustomDialog, CustomIconButton, CustomSlider, CustomToggleButton, CustomTooltip, DEFAULT_ERROR_MESSAGE, DraggableComponent$1 as Draggable, ErrorBoundary, LastUpdateTime, ResizeComponent as Resizable, SHARED_NAMESPACE, SearchField, SearchFieldButton, SearchHighlight, StatusTag, SwitchButton, ToggleMenu, ToolContainer, DraggableComponent as ToolContainerDraggable, ToolFooter, ToolHeader, TooltipSelect, UserMenu, UserMenuItemCheatSheet, UserMenuItemSentryRecording, MenuItemTheme as UserMenuItemTheme, adjustPosition, calculateDialogSizeAndPosition, calculateStartSize, createMockStoreWithEggs, createMockStoreWithEggsAndMiddleware, createToolkitMockStoreWithEggs, index as dateUtils, defaultDelay, getAxiosErrorMessage, getAxiosWarningMessage, getErrorMessage, getInitials, getLastUpdateTitle, getPosition, getWarningMessage, isAxiosAuthError, isAxiosError, pollingIntervalTimeout, renderCounter, sharedTranslations, showPrompt, sliderHeaderStyle, tooltipContainerStyles, useConfirmationDialog, useControlledTooltip, useDebounce, useDialogActions, useIsMounted, useMakeSureContainerStaysInsideWindow, usePoller, usePreventBrowserClose, usePrevious, useUserMenu, withEggs };
9469
+ export { AlertBanner, AlertIcon, AppHeader, AppLayout, Avatar, CanvasComponent, ConfirmationDialog, ConfirmationServiceProvider, CustomAccordion, CustomDialog, CustomIconButton, CustomSlider, CustomToggleButton, CustomTooltip, DEBOUNCE_TIMEOUT, DEFAULT_ERROR_MESSAGE, DEFAULT_FILTER_HEIGHT, DraggableComponent$1 as Draggable, ErrorBoundary, Filter, FilterChip, FilterListItem, LastUpdateTime, ResizeComponent as Resizable, SHARED_NAMESPACE, SearchField$1 as SearchField, SearchFieldButton, SearchHighlight, StatusTag, SwitchButton, ToggleMenu, ToolContainer, DraggableComponent as ToolContainerDraggable, ToolFooter, ToolHeader, TooltipSelect, UserMenu, UserMenuItemCheatSheet, UserMenuItemSentryRecording, MenuItemTheme as UserMenuItemTheme, adjustPosition, calculateDialogSizeAndPosition, calculateStartSize, createMockStoreWithEggs, createMockStoreWithEggsAndMiddleware, createToolkitMockStoreWithEggs, index as dateUtils, defaultDelay, getAxiosErrorMessage, getAxiosWarningMessage, getErrorMessage, getInitials, getLastUpdateTitle, getPosition, getWarningMessage, isAxiosAuthError, isAxiosError, pollingIntervalTimeout, renderCounter, sharedTranslations, showPrompt, sliderHeaderStyle, tooltipContainerStyles, useConfirmationDialog, useControlledTooltip, useDebounce, useDialogActions, useIsMounted, useMakeSureContainerStaysInsideWindow, usePoller, usePreventBrowserClose, usePrevious, useUserMenu, withEggs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeoweb/shared",
3
- "version": "9.22.0",
3
+ "version": "9.24.0",
4
4
  "description": "GeoWeb shared library with shared components and utils for the opengeoweb project",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -0,0 +1,13 @@
1
+ import { BoxProps } from '@mui/material';
2
+ import * as React from 'react';
3
+ import { ListFilter } from './FilterList';
4
+ export declare const DEFAULT_FILTER_HEIGHT = 85;
5
+ interface FilterProps extends BoxProps {
6
+ filters: ListFilter[];
7
+ onClickFilterChip?: (id: string, selected: boolean) => void;
8
+ onSearch?: (value: string) => void;
9
+ isAllSelected?: boolean;
10
+ searchQuery?: string;
11
+ }
12
+ declare const Filter: React.ForwardRefExoticComponent<Omit<FilterProps, "ref"> & React.RefAttributes<HTMLElement>>;
13
+ export default Filter;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ declare const _default: {
3
+ title: string;
4
+ };
5
+ export default _default;
6
+ export declare const FilterLight: {
7
+ (): React.ReactElement;
8
+ parameters: {
9
+ zeplinLink: {
10
+ name: string;
11
+ link: string;
12
+ }[];
13
+ };
14
+ tags: string[];
15
+ };
16
+ export declare const FilterDark: {
17
+ (): React.ReactElement;
18
+ parameters: {
19
+ zeplinLink: {
20
+ name: string;
21
+ link: string;
22
+ }[];
23
+ };
24
+ tags: string[];
25
+ };
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ export interface FilterChipProps {
3
+ id: string;
4
+ label: string;
5
+ isSelected?: boolean;
6
+ isDisabled?: boolean;
7
+ handleClick?: (label: string) => void;
8
+ onAction?: React.MouseEventHandler;
9
+ actionIcon?: React.ReactElement;
10
+ }
11
+ declare const FilterChip: React.FC<FilterChipProps>;
12
+ export default FilterChip;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ export interface ListFilter {
3
+ label: string;
4
+ id: string;
5
+ type?: 'scope' | 'keyword';
6
+ isSelected?: boolean;
7
+ isDisabled?: boolean;
8
+ }
9
+ interface FilterListProps {
10
+ filters?: ListFilter[];
11
+ onChipClick?: (id: string, selected: boolean) => void;
12
+ isAllSelected?: boolean;
13
+ }
14
+ declare const FilterList: React.FC<FilterListProps>;
15
+ export default FilterList;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ export interface Filter {
3
+ id: string;
4
+ name: string;
5
+ checked?: boolean;
6
+ amountVisible?: number;
7
+ }
8
+ export interface FilterListItemProps {
9
+ filter: Filter;
10
+ toggleFilter: (filterIds: string[]) => void;
11
+ enableOnlyOneFilter: (filterId: string) => void;
12
+ }
13
+ export declare const FilterListItem: React.FC<FilterListItemProps>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ declare const _default: {
3
+ title: string;
4
+ };
5
+ export default _default;
6
+ export declare const FilterListItemLight: () => React.ReactElement;
7
+ export declare const FilterListItemDark: () => React.ReactElement;
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ export declare const DEBOUNCE_TIMEOUT = 300;
3
+ interface SearchFieldProps {
4
+ valueChanged: (value: string) => void;
5
+ value?: string;
6
+ }
7
+ declare const SearchField: React.FC<SearchFieldProps>;
8
+ export default SearchField;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export { default as Filter } from './Filter';
2
+ export { DEFAULT_FILTER_HEIGHT } from './Filter';
3
+ export type { ListFilter } from './FilterList';
4
+ export { FilterListItem } from './FilterListItem';
5
+ export type { Filter as FilterListItemFilter, FilterListItemProps, } from './FilterListItem';
6
+ export { default as FilterChip } from './FilterChip';
7
+ export type { FilterChipProps } from './FilterChip';
8
+ export { DEBOUNCE_TIMEOUT } from './SearchField';
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
- import { BaseSelectProps, SelectVariants } from '@mui/material';
3
- import { SxProps, Theme } from '@mui/material/styles';
2
+ import { BaseSelectProps, SelectVariants, SxProps, Theme } from '@mui/material';
4
3
  interface ListElement {
5
4
  value: string;
6
5
  }
@@ -23,3 +23,4 @@ export * from './SwitchButton';
23
23
  export * from './SearchField';
24
24
  export * from './LastUpdateTime';
25
25
  export * from './CanvasComponent';
26
+ export * from './Filter';
@@ -4,3 +4,4 @@ export declare const DATE_FORMAT_YEAR = "yyyy-MM-dd";
4
4
  export declare const DATE_FORMAT_HOURS = "HH:mm";
5
5
  export declare const DATE_FORMAT_NAME_OF_DAY_MONTH = "eee dd MMM HH:mm";
6
6
  export declare const DATE_FORMAT_NAME_OF_MONTH = "dd MMM yyyy, HH:mm";
7
+ export declare const DATE_FORMAT_NAME_OF_DAY = "eee dd/MM/yyyy HH:mm";
@@ -1,3 +1,7 @@
1
+ import i18n from 'i18next';
2
+ import { UseTranslationResponse } from 'react-i18next';
1
3
  export declare const SHARED_NAMESPACE = "shared";
2
4
  export declare const initSharedI18n: () => void;
3
5
  export declare const translateKeyOutsideComponents: (key: string, params?: Record<string, string | number> | undefined) => string;
6
+ export declare const useSharedTranslation: () => UseTranslationResponse<typeof SHARED_NAMESPACE, typeof i18n>;
7
+ export { i18n };