@opengeoweb/time-slider-lite 13.0.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.
Files changed (52) hide show
  1. package/README.md +13 -0
  2. package/index.d.ts +1 -0
  3. package/index.esm.js +2559 -0
  4. package/package.json +36 -0
  5. package/src/index.d.ts +3 -0
  6. package/src/lib/components/TimeSliderLite/TimeSliderLite.d.ts +42 -0
  7. package/src/lib/components/TimeSliderLite/TimeSliderLite.spec.d.ts +1 -0
  8. package/src/lib/components/TimeSliderLite/TimeSliderLite.stories.d.ts +8 -0
  9. package/src/lib/components/TimeSliderLite/TimeSliderLiteConnect.d.ts +40 -0
  10. package/src/lib/components/TimeSliderLite/TimeSliderLiteConnect.spec.d.ts +1 -0
  11. package/src/lib/components/TimeSliderLite/TimeSliderLiteConnect.stories.d.ts +6 -0
  12. package/src/lib/components/TimeSliderLite/index.d.ts +4 -0
  13. package/src/lib/components/TimeSliderLite/timeSliderLiteUtils.d.ts +131 -0
  14. package/src/lib/components/TimeSliderLite/timeSliderLiteUtils.spec.d.ts +1 -0
  15. package/src/lib/components/TimeSliderLite/useOnToggleAnimation.d.ts +3 -0
  16. package/src/lib/components/TimeSliderLite/useOnToggleAnimation.spec.d.ts +1 -0
  17. package/src/lib/components/TimeSliderLiteBackground/TimeSliderDraggableNeedle.d.ts +25 -0
  18. package/src/lib/components/TimeSliderLiteBackground/TimeSliderDraggableNeedle.spec.d.ts +1 -0
  19. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteBackground.d.ts +24 -0
  20. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteBackground.stories.d.ts +11 -0
  21. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteBackgroundSvg.d.ts +16 -0
  22. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteBackgroundSvg.spec.d.ts +1 -0
  23. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteClickableTimeline.d.ts +14 -0
  24. package/src/lib/components/TimeSliderLiteBackground/TimeSliderLiteClickableTimeline.spec.d.ts +1 -0
  25. package/src/lib/components/TimeSliderLiteBackground/TimeSliderZeroTimestamp.d.ts +10 -0
  26. package/src/lib/components/TimeSliderLiteButtons/ControlButtonGroup/ControlButtonGroup.d.ts +8 -0
  27. package/src/lib/components/TimeSliderLiteButtons/HideButton/HideButton.d.ts +9 -0
  28. package/src/lib/components/TimeSliderLiteButtons/MenuButton/MenuButton.d.ts +9 -0
  29. package/src/lib/components/TimeSliderLiteButtons/PlayButton/PlayButton.d.ts +11 -0
  30. package/src/lib/components/TimeSliderLiteButtons/StepButton/StepButton.d.ts +11 -0
  31. package/src/lib/components/TimeSliderLiteButtons/TimeSliderLiteButtonUtils.d.ts +2 -0
  32. package/src/lib/components/TimeSliderLiteOptionsMenu/AnimationSpeedOptions/AnimationSpeedOptions.d.ts +13 -0
  33. package/src/lib/components/TimeSliderLiteOptionsMenu/AnimationSpeedOptions/AnimationSpeedOptions.spec.d.ts +1 -0
  34. package/src/lib/components/TimeSliderLiteOptionsMenu/SubmenuSelectLabel.d.ts +8 -0
  35. package/src/lib/components/TimeSliderLiteOptionsMenu/SubmenuWrapper.d.ts +8 -0
  36. package/src/lib/components/TimeSliderLiteOptionsMenu/SubmenuWrapper.spec.d.ts +1 -0
  37. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeRangeOptions/DayHourSelector.d.ts +21 -0
  38. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeRangeOptions/DayHourSelector.spec.d.ts +1 -0
  39. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeRangeOptions/TimeRangeOptions.d.ts +15 -0
  40. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeSliderLiteOptionsMenu.d.ts +24 -0
  41. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeSliderLiteOptionsMenu.spec.d.ts +1 -0
  42. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeStepOptions/TimeStepOptions.d.ts +15 -0
  43. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeStepOptions/TimeStepOptions.spec.d.ts +1 -0
  44. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeStepOptions/TimeStepSelector.d.ts +11 -0
  45. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeZoneSwitch/TimeZoneSwitch.d.ts +8 -0
  46. package/src/lib/components/TimeSliderLiteOptionsMenu/TimeZoneSwitch/TimeZoneSwitch.spec.d.ts +1 -0
  47. package/src/lib/components/TimeSliderLiteOptionsMenu/UpdateIntervalOptions/UpdateIntervalOptions.d.ts +15 -0
  48. package/src/lib/components/TimeSliderLiteOptionsMenu/UpdateIntervalOptions/UpdateIntervalOptions.spec.d.ts +1 -0
  49. package/src/lib/index.d.ts +3 -0
  50. package/src/lib/locales/i18n.d.ts +23 -0
  51. package/src/lib/locales/translations.spec.d.ts +1 -0
  52. package/src/lib/testUtils/Providers.d.ts +24 -0
package/index.esm.js ADDED
@@ -0,0 +1,2559 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { Card, Typography, IconButton, Select, MenuItem, CardContent, RadioGroup, FormControlLabel, Radio, Grid, Box, ToggleButtonGroup, ToggleButton, Divider, Tooltip, ButtonGroup, useTheme } from '@mui/material';
3
+ import { Close, ChevronDown, ChevronUp, StepForward, StepBackward, Pause, Play, Options } from '@opengeoweb/theme';
4
+ import React, { useState, useEffect, useLayoutEffect, createElement, useRef } from 'react';
5
+ import { usePrevious, safelyInitI18nForTestsAndStories } from '@opengeoweb/shared';
6
+ import { I18nextProvider, useTranslation } from 'react-i18next';
7
+ import i18n from 'i18next';
8
+ import { CORE_NAMESPACE, coreTranslations } from '@opengeoweb/core';
9
+ import { speedFactors, defaultAnimationDelayAtStart } from '@opengeoweb/time-slider';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
+ import { mapActions, mapEnums, mapSelectors, genericActions } from '@opengeoweb/store';
12
+ import { handleDateUtilsISOString } from '@opengeoweb/webmap';
13
+ import Draggable from 'react-draggable';
14
+
15
+ var en = {
16
+ common: {
17
+ "default": "Default",
18
+ custom: "Custom",
19
+ observed: "Observed",
20
+ forecast: "Forecast"
21
+ },
22
+ units: {
23
+ days: "days",
24
+ hours: "hours",
25
+ minutes: "min"
26
+ },
27
+ menu: {
28
+ title: "Animation options",
29
+ timeRange: {
30
+ title: "Time range",
31
+ description: "Time range from current time",
32
+ button: "Time range"
33
+ },
34
+ timeStep: {
35
+ title: "Time step",
36
+ button: "Time step"
37
+ },
38
+ speed: {
39
+ title: "Animation speed",
40
+ button: "Speed"
41
+ },
42
+ updateInterval: {
43
+ title: "Update interval",
44
+ button: "Update interval"
45
+ },
46
+ LT: "LT",
47
+ UTC: "UTC"
48
+ },
49
+ controlButtons: {
50
+ play: "Play",
51
+ pause: "Pause",
52
+ forward: "Forward",
53
+ backward: "Backward",
54
+ hide: "Hide",
55
+ show: "Show"
56
+ }
57
+ };
58
+ var fi = {
59
+ common: {
60
+ "default": "Oletus",
61
+ custom: "Valitse",
62
+ observed: "Havainto",
63
+ forecast: "Ennuste"
64
+ },
65
+ units: {
66
+ days: "vrk",
67
+ hours: "h",
68
+ minutes: "min"
69
+ },
70
+ menu: {
71
+ title: "Aikajana-asetukset",
72
+ timeRange: {
73
+ title: "Aikaväli",
74
+ description: "Valittu aika nykyhetkestä",
75
+ button: "Aikaväli"
76
+ },
77
+ timeStep: {
78
+ title: "Aika-askel",
79
+ button: "Aika-askel"
80
+ },
81
+ speed: {
82
+ title: "Animointinopeus",
83
+ button: "Animointinopeus"
84
+ },
85
+ updateInterval: {
86
+ title: "Päivitysväli",
87
+ button: "Päivitysväli"
88
+ },
89
+ LT: "PA",
90
+ UTC: "UTC"
91
+ },
92
+ controlButtons: {
93
+ play: "Toista",
94
+ pause: "Pysäytä",
95
+ forward: "Eteenpäin",
96
+ backward: "Taaksepäin",
97
+ hide: "Piilota aikajana",
98
+ show: "Näytä aikajana"
99
+ }
100
+ };
101
+ var translations = {
102
+ en: en,
103
+ "sv-FI": {
104
+ common: {
105
+ "default": "Standard",
106
+ custom: "Välj",
107
+ observed: "Observation",
108
+ forecast: "Prognos"
109
+ },
110
+ units: {
111
+ days: "dygn",
112
+ hours: "h",
113
+ minutes: "min"
114
+ },
115
+ menu: {
116
+ title: "Tidslinjeinställningar",
117
+ timeRange: {
118
+ title: "Tidsintervall",
119
+ description: "Vald tid från nu",
120
+ button: "Tidsintervall"
121
+ },
122
+ timeStep: {
123
+ title: "Tidssteg",
124
+ button: "Tidssteg"
125
+ },
126
+ speed: {
127
+ title: "Animationshastighet",
128
+ button: "Hastighet"
129
+ },
130
+ updateInterval: {
131
+ title: "Uppdateringsintervall",
132
+ button: "Uppdateringsintervall"
133
+ },
134
+ LT: "LT",
135
+ UTC: "UTC"
136
+ },
137
+ controlButtons: {
138
+ play: "Spela",
139
+ pause: "Paus",
140
+ forward: "Framåt",
141
+ backward: "Bakåt",
142
+ hide: "Dölj tidslinje",
143
+ show: "Visa tidslinje"
144
+ }
145
+ },
146
+ fi: fi
147
+ };
148
+
149
+ function _objectWithoutPropertiesLoose(r, e) {
150
+ if (null == r) return {};
151
+ var t = {};
152
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
153
+ if (-1 !== e.indexOf(n)) continue;
154
+ t[n] = r[n];
155
+ }
156
+ return t;
157
+ }
158
+
159
+ var _excluded$4 = ["children", "closeButtonIcon", "sx", "setSubmenu", "title"];
160
+ var SubmenuWrapper = function SubmenuWrapper(_ref) {
161
+ var children = _ref.children,
162
+ closeButtonIcon = _ref.closeButtonIcon,
163
+ sx = _ref.sx,
164
+ setSubmenu = _ref.setSubmenu,
165
+ title = _ref.title,
166
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$4);
167
+ return jsxs(Card, Object.assign({}, props, {
168
+ sx: Object.assign({
169
+ position: 'relative'
170
+ }, sx),
171
+ children: [jsx(Typography, {
172
+ sx: {
173
+ fontWeight: '500',
174
+ padding: '16px',
175
+ paddingBottom: '0px'
176
+ },
177
+ children: title
178
+ }), jsx(IconButton, {
179
+ "data-testid": "TimeSliderLite-submenuWrapper-closeButton",
180
+ size: "small",
181
+ sx: {
182
+ position: 'absolute',
183
+ top: 4,
184
+ right: 4
185
+ },
186
+ onClick: function onClick() {
187
+ return setSubmenu && setSubmenu(null);
188
+ },
189
+ children: closeButtonIcon != null ? closeButtonIcon : jsx(Close, {
190
+ "data-testid": "TimeSliderLite-submenuWrapper-defaultCloseIcon"
191
+ })
192
+ }), children]
193
+ }));
194
+ };
195
+
196
+ /* *
197
+ * Licensed under the Apache License, Version 2.0 (the "License");
198
+ * you may not use this file except in compliance with the License.
199
+ * You may obtain a copy of the License at
200
+ *
201
+ * http://www.apache.org/licenses/LICENSE-2.0
202
+ *
203
+ * Unless required by applicable law or agreed to in writing, software
204
+ * distributed under the License is distributed on an "AS IS" BASIS,
205
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
206
+ * See the License for the specific language governing permissions and
207
+ * limitations under the License.
208
+ *
209
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
210
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
211
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
212
+ * */
213
+ var DAY_TO_MILLISECOND = 24 * 60 * 60 * 1000;
214
+ var DAY_TO_SECOND = 86400;
215
+ var HOUR_TO_SECOND = 3600;
216
+ var HOUR_TO_MINUTE = 60;
217
+ var MILLISECOND_TO_DAY = 1 / 86400000;
218
+ var MILLISECOND_TO_SECOND = 1 / 1000;
219
+ var MILLISECOND_TO_MINUTE = 1 / 60000;
220
+ var MINUTE_TO_SECOND = 60;
221
+ var MINUTE_TO_MILLISECOND = 60000;
222
+ var SECOND_TO_DAY = 1 / 86400;
223
+ var SECOND_TO_HOUR = 1 / 3600;
224
+ var SECOND_TO_MILLISECOND = 1000;
225
+ var SEVEN_DAYS_IN_SECONDS = 7 * 24 * 60 * 60;
226
+ var ONE_DAY_IN_SECONDS = DAY_TO_SECOND;
227
+ /**
228
+ * Default behaviour for time slider lite to update
229
+ * - Update current time
230
+ * - Update time range
231
+ *
232
+ * Layers are updated using the native auto update functionality implemented in ReactMapView.tsx
233
+ *
234
+ * @param mapId
235
+ * @param options
236
+ */
237
+ var defaultTimeSliderLiteUpdate = function defaultTimeSliderLiteUpdate(options) {
238
+ if (document.visibilityState !== 'visible') {
239
+ return;
240
+ }
241
+ var setCurrentTime = options.setCurrentTime,
242
+ timeRange = options.timeRange,
243
+ currentTime = options.currentTime,
244
+ setTimeRange = options.setTimeRange;
245
+ var newCurrentTime = Math.floor(Date.now() * MILLISECOND_TO_SECOND);
246
+ var delta = newCurrentTime - currentTime;
247
+ // Update current time and trigger update in useDefaultTimeRange hook
248
+ setCurrentTime(currentTime + delta);
249
+ if (timeRange && setTimeRange) {
250
+ setTimeRange([timeRange[0] + delta, timeRange[1] + delta]);
251
+ }
252
+ };
253
+ /**
254
+ * Connected hook for updating time range and current time every 10 seconds
255
+ * @param updateInterval Update interval in minutes
256
+ * @param timeRange [startTime, endTime] in seconds
257
+ * @param setTimeRange Sets the time range
258
+ * @param options Options
259
+ */
260
+ var useAutoUpdate = function useAutoUpdate(timeRange, setTimeRange, options) {
261
+ var _useState = useState(Math.floor(Date.now() * MILLISECOND_TO_SECOND)),
262
+ currentTime = _useState[0],
263
+ setCurrentTime = _useState[1];
264
+ useEffect(function () {
265
+ var intervalCallback = function intervalCallback() {
266
+ var _options$handleUpdate;
267
+ return ((_options$handleUpdate = options == null ? void 0 : options.handleUpdate) != null ? _options$handleUpdate : defaultTimeSliderLiteUpdate)({
268
+ setCurrentTime: setCurrentTime,
269
+ currentTime: currentTime,
270
+ timeRange: timeRange,
271
+ setTimeRange: setTimeRange
272
+ });
273
+ };
274
+ var interval = setInterval(intervalCallback, 10 * SECOND_TO_MILLISECOND);
275
+ document.addEventListener('visibilitychange', intervalCallback);
276
+ return function () {
277
+ clearInterval(interval);
278
+ document.removeEventListener('visibilitychange', intervalCallback);
279
+ };
280
+ // eslint-disable-next-line react-hooks/exhaustive-deps
281
+ }, [timeRange, setTimeRange, options == null ? void 0 : options.handleUpdate, currentTime, setCurrentTime]);
282
+ return {
283
+ currentTime: currentTime
284
+ };
285
+ };
286
+ /**
287
+ * Reformats a date that has capitalized first letter and colon separator for time
288
+ * @param dateString Date string from Date.toLocaleDateString
289
+ * @returns Reformatted date string
290
+ */
291
+ var reformatFinnishDateString = function reformatFinnishDateString(dateString) {
292
+ var charPositionOfTimestamp = -4;
293
+ return dateString.charAt(0).toUpperCase() + dateString.slice(1, charPositionOfTimestamp) + dateString.slice(charPositionOfTimestamp).replace('.', ':');
294
+ };
295
+ /**
296
+ * Marks UTC time with Z after hh:mm or hh.mm or appends UTC to the end of the date string
297
+ * If two matches of time are found, the second one is marked
298
+ */
299
+ var shortUTCTime = function shortUTCTime(dateString) {
300
+ var timeRegex = /(\d[:.]\d{2})/g;
301
+ var match = dateString.match(timeRegex);
302
+ if (!match) {
303
+ return dateString + " UTC";
304
+ }
305
+ var first = match[0],
306
+ second = match[1];
307
+ if (second) {
308
+ var secondIndex = dateString.lastIndexOf(second);
309
+ return "" + dateString.substring(0, secondIndex) + second + "Z" + dateString.substring(secondIndex + second.length);
310
+ }
311
+ return dateString.replace(first, first + "Z");
312
+ };
313
+ var getMonthChanges = function getMonthChanges(startDate, endDate) {
314
+ var result = [];
315
+ var currentDate = new Date(startDate.getTime());
316
+ var lastDate = new Date(endDate.getTime());
317
+ currentDate.setDate(1);
318
+ currentDate.setHours(0, 0, 0, 0);
319
+ while (currentDate <= lastDate) {
320
+ result.push(currentDate.getTime() * MILLISECOND_TO_SECOND);
321
+ currentDate.setMonth(currentDate.getMonth() + 1);
322
+ }
323
+ return result;
324
+ };
325
+ var isWithinRange = function isWithinRange(time, target, range) {
326
+ return Math.abs(time - target) <= range;
327
+ };
328
+ var getSelectedTimePx = function getSelectedTimePx(startTime, endTime, selectedTime, width) {
329
+ var startDate = new Date(startTime * SECOND_TO_MILLISECOND);
330
+ var startDateX = startDate.getTime() * MILLISECOND_TO_SECOND;
331
+ var selectedTimeX = selectedTime - startDateX;
332
+ var needleX = Math.floor(selectedTimeX / (endTime - startTime) * width);
333
+ return needleX;
334
+ };
335
+ var boundedValue = function boundedValue(value, bounds) {
336
+ var min = bounds[0],
337
+ max = bounds[1];
338
+ return Math.max(min, Math.min(max, value));
339
+ };
340
+ var getSelectedTimeFromPx = function getSelectedTimeFromPx(startTime, endTime, selectedTimePx, width) {
341
+ var startDate = new Date(startTime * SECOND_TO_MILLISECOND);
342
+ var startDateX = startDate.getTime() * MILLISECOND_TO_SECOND;
343
+ var selectedTimeX = Math.floor(selectedTimePx / width * (endTime - startTime));
344
+ var selectedTime = selectedTimeX + startDateX;
345
+ return selectedTime;
346
+ };
347
+ var getNearestSelectableTime = function getNearestSelectableTime(timeStep, startTime, endTime, x, width, currentTime, disableForecast, timeZoneOffsetSeconds) {
348
+ var observedTimeStepSeconds = timeStep[0];
349
+ var forecastTimeStepSeconds = timeStep[1];
350
+ var hoveredTime = getSelectedTimeFromPx(startTime, endTime, x, width);
351
+ var lastObservedTime = floorLocalSeconds(currentTime, observedTimeStepSeconds, timeZoneOffsetSeconds);
352
+ if (disableForecast && hoveredTime >= lastObservedTime) {
353
+ return lastObservedTime;
354
+ }
355
+ var timeStepSeconds = hoveredTime >= currentTime ? forecastTimeStepSeconds : observedTimeStepSeconds;
356
+ var firstForecastTime = floorLocalSeconds(currentTime, forecastTimeStepSeconds, timeZoneOffsetSeconds) + forecastTimeStepSeconds;
357
+ var isBetweenObservedAndForecast = hoveredTime >= lastObservedTime && hoveredTime < firstForecastTime;
358
+ var roundedCurrentTime = hoveredTime >= (lastObservedTime + firstForecastTime) / 2 ? firstForecastTime : lastObservedTime;
359
+ var result = isBetweenObservedAndForecast ? roundedCurrentTime : floorLocalSeconds(hoveredTime + timeStepSeconds / 2, timeStepSeconds, timeZoneOffsetSeconds);
360
+ return result;
361
+ };
362
+ var floorLocalMinutes = function floorLocalMinutes(selectedTimeMinutes, timeStepMinutes, timeZoneOffsetMinutes) {
363
+ var localTimeZoneOffset = timeZoneOffsetMinutes != null ? timeZoneOffsetMinutes : new Date().getTimezoneOffset();
364
+ var unFlooredTimeSteps = (selectedTimeMinutes - localTimeZoneOffset) / timeStepMinutes;
365
+ return Math.floor(unFlooredTimeSteps) * timeStepMinutes + localTimeZoneOffset;
366
+ };
367
+ var floorLocalSeconds = function floorLocalSeconds(selectedTimeSeconds, timeStepSeconds, timeZoneOffsetSeconds) {
368
+ if (timeZoneOffsetSeconds === 0) {
369
+ return Math.floor(selectedTimeSeconds / timeStepSeconds) * timeStepSeconds;
370
+ }
371
+ var localTimeZoneOffset = timeZoneOffsetSeconds != null ? timeZoneOffsetSeconds : new Date().getTimezoneOffset() * 60;
372
+ var unFlooredTimeSteps = (selectedTimeSeconds - localTimeZoneOffset) / timeStepSeconds;
373
+ return Math.floor(unFlooredTimeSteps) * timeStepSeconds + localTimeZoneOffset;
374
+ };
375
+ var secondsToDaysAndHours = function secondsToDaysAndHours(seconds) {
376
+ var days = Math.floor(seconds * SECOND_TO_DAY);
377
+ var hours = Math.round(seconds % DAY_TO_SECOND * SECOND_TO_HOUR);
378
+ if (hours === 24) {
379
+ return {
380
+ days: days + 1,
381
+ hours: 0
382
+ };
383
+ }
384
+ return {
385
+ days: days,
386
+ hours: hours
387
+ };
388
+ };
389
+ var hoursAndDaysToSeconds = function hoursAndDaysToSeconds(hours, days) {
390
+ return hours * HOUR_TO_SECOND + days * DAY_TO_SECOND;
391
+ };
392
+ var TIME_SLIDER_LITE_DEFAULT_MAX_FORECAST_RANGE = 2 * SEVEN_DAYS_IN_SECONDS;
393
+ var TIME_SLIDER_LITE_DEFAULT_MAX_OBSERVED_RANGE = SEVEN_DAYS_IN_SECONDS;
394
+ /**
395
+ * Checks which layers have observed/forecasted data and returns a default time range
396
+ * @param layers layerTypes.ReduxLayer[] Map layers
397
+ * @param currentTime Current time in seconds
398
+ * @param overrideDefaultTimeRange [observedTimeRange, forecastTime] in seconds from current time
399
+ * @returns [startTime, endTime] in seconds
400
+ */
401
+ var defaultTimeRange = function defaultTimeRange(layers, currentTime, overrideDefaultTimeRange) {
402
+ if (currentTime === void 0) {
403
+ currentTime = Math.floor(Date.now() * MILLISECOND_TO_SECOND);
404
+ }
405
+ var defaultBounds = [currentTime - TIME_SLIDER_LITE_DEFAULT_MAX_OBSERVED_RANGE, currentTime + TIME_SLIDER_LITE_DEFAULT_MAX_FORECAST_RANGE];
406
+ var bounds = overrideDefaultTimeRange ? [currentTime - overrideDefaultTimeRange[0], currentTime + overrideDefaultTimeRange[1]] : defaultBounds;
407
+ var timeDimensions = [];
408
+ layers.forEach(function (layer) {
409
+ var _layer$dimensions;
410
+ var timeDimension = (_layer$dimensions = layer.dimensions) == null ? void 0 : _layer$dimensions.find(function (dimension) {
411
+ return dimension.name === 'time';
412
+ });
413
+ if (timeDimension != null && timeDimension.minValue && timeDimension != null && timeDimension.maxValue) {
414
+ timeDimensions.push(timeDimension);
415
+ }
416
+ });
417
+ if (timeDimensions.length === 0) {
418
+ return bounds;
419
+ }
420
+ var minMinValue = Math.min.apply(Math, timeDimensions.map(function (dimension) {
421
+ return new Date(dimension.minValue).valueOf() * MILLISECOND_TO_SECOND;
422
+ }));
423
+ var maxMaxValue = Math.max.apply(Math, timeDimensions.map(function (dimension) {
424
+ return new Date(dimension.maxValue).valueOf() * MILLISECOND_TO_SECOND;
425
+ }));
426
+ return [Math.max(bounds[0], minMinValue), Math.min(bounds[1], maxMaxValue)];
427
+ };
428
+ var useDefaultTimeRange = function useDefaultTimeRange(layers, updateThreshold, currentTime) {
429
+ if (currentTime === void 0) {
430
+ currentTime = Math.floor(Date.now() * MILLISECOND_TO_SECOND);
431
+ }
432
+ var _useState2 = useState([0, 0]),
433
+ _useState2$ = _useState2[0],
434
+ defaultStartTime = _useState2$[0],
435
+ defaultEndTime = _useState2$[1],
436
+ setDefaultTimeRange = _useState2[1];
437
+ var updateThresholdInMinutes = updateThreshold * MINUTE_TO_SECOND;
438
+ var updateDefaultTimeRange = function updateDefaultTimeRange() {
439
+ var newTimeRange = defaultTimeRange(layers, currentTime);
440
+ var defaultStartTimeChanged = Math.abs(newTimeRange[0] - defaultStartTime) > updateThresholdInMinutes;
441
+ var defaultEndTimeChanged = Math.abs(newTimeRange[1] - defaultEndTime) > updateThresholdInMinutes;
442
+ if (defaultStartTimeChanged || defaultEndTimeChanged) {
443
+ setDefaultTimeRange(newTimeRange);
444
+ }
445
+ };
446
+ useEffect(function () {
447
+ updateDefaultTimeRange();
448
+ // eslint-disable-next-line react-hooks/exhaustive-deps
449
+ }, [layers, currentTime]);
450
+ return [defaultStartTime, defaultEndTime];
451
+ };
452
+ var generateCustomTimeList = function generateCustomTimeList(currentTime, startTime, endTime, timeStep, timeZoneOffsetSeconds) {
453
+ var localTimeZoneOffset = timeZoneOffsetSeconds !== undefined ? timeZoneOffsetSeconds : new Date().getTimezoneOffset() * MINUTE_TO_SECOND;
454
+ var observedTimeStep = timeStep[0] * MINUTE_TO_SECOND;
455
+ var forecastTimeStep = timeStep[1] * MINUTE_TO_SECOND;
456
+ var firstObservedTimeStep = floorLocalSeconds(startTime, observedTimeStep, localTimeZoneOffset);
457
+ if (firstObservedTimeStep < startTime) {
458
+ firstObservedTimeStep += observedTimeStep;
459
+ }
460
+ var lastObservedTimeStep = floorLocalSeconds(currentTime, observedTimeStep, localTimeZoneOffset);
461
+ var truncatePassingHour = currentTime - startTime < 0;
462
+ var firstForecastTimeStep = truncatePassingHour ? floorLocalSeconds(currentTime + HOUR_TO_SECOND, HOUR_TO_SECOND, localTimeZoneOffset) - 1 : floorLocalSeconds(currentTime, forecastTimeStep, localTimeZoneOffset);
463
+ var lastForecastTimeStep = floorLocalSeconds(endTime, forecastTimeStep, localTimeZoneOffset);
464
+ var observedTimeList = [];
465
+ var forecastTimeList = [];
466
+ var time = firstObservedTimeStep;
467
+ while (time <= lastObservedTimeStep) {
468
+ var observedTimeListItem = {
469
+ name: 'time',
470
+ value: new Date(time * SECOND_TO_MILLISECOND).toISOString()
471
+ };
472
+ observedTimeList.push(observedTimeListItem);
473
+ time += observedTimeStep;
474
+ }
475
+ time = lastForecastTimeStep;
476
+ while (time > firstForecastTimeStep) {
477
+ var forecastTimeListItem = {
478
+ name: 'time',
479
+ value: new Date(time * SECOND_TO_MILLISECOND).toISOString()
480
+ };
481
+ forecastTimeList.push(forecastTimeListItem);
482
+ time -= forecastTimeStep;
483
+ }
484
+ forecastTimeList.reverse();
485
+ return [].concat(observedTimeList, forecastTimeList);
486
+ };
487
+ var TickMode;
488
+ (function (TickMode) {
489
+ TickMode[TickMode["DAY"] = 1] = "DAY";
490
+ TickMode[TickMode["HALF_A_DAY"] = 2] = "HALF_A_DAY";
491
+ TickMode[TickMode["SIX_HOURS"] = 4] = "SIX_HOURS";
492
+ TickMode[TickMode["THREE_HOURS"] = 8] = "THREE_HOURS";
493
+ TickMode[TickMode["ONE_HOUR"] = 24] = "ONE_HOUR";
494
+ TickMode[TickMode["HALF_AN_HOUR"] = 48] = "HALF_AN_HOUR";
495
+ TickMode[TickMode["FIFTEEN_MINUTES"] = 96] = "FIFTEEN_MINUTES";
496
+ })(TickMode || (TickMode = {}));
497
+ var subTicksPerDay = function subTicksPerDay(dayWidthInPixels) {
498
+ if (dayWidthInPixels < 40) {
499
+ return TickMode.DAY;
500
+ }
501
+ if (dayWidthInPixels < 75) {
502
+ return TickMode.HALF_A_DAY;
503
+ }
504
+ if (dayWidthInPixels < 400) {
505
+ return TickMode.SIX_HOURS;
506
+ }
507
+ if (dayWidthInPixels < 800) {
508
+ return TickMode.THREE_HOURS;
509
+ }
510
+ if (dayWidthInPixels < 1600) {
511
+ return TickMode.ONE_HOUR;
512
+ }
513
+ if (dayWidthInPixels < 3200) {
514
+ return TickMode.HALF_AN_HOUR;
515
+ }
516
+ return TickMode.FIFTEEN_MINUTES;
517
+ };
518
+ var maxSubTicksPerDay = function maxSubTicksPerDay(dayWidthInPixels, timeStep) {
519
+ return Math.min(subTicksPerDay(dayWidthInPixels), Math.floor(ONE_DAY_IN_SECONDS / timeStep));
520
+ };
521
+ var getRemainingHours = function getRemainingHours(maxHours, days) {
522
+ var hourDifference = maxHours && maxHours - days * 24;
523
+ var result = maxHours && hourDifference && hourDifference > 0 ? hourDifference : 0;
524
+ return result;
525
+ };
526
+ var secondsSinceLocalMidnight = function secondsSinceLocalMidnight(currentTimeInSeconds) {
527
+ return new Date(currentTimeInSeconds * 1000).getHours() * HOUR_TO_SECOND + new Date(currentTimeInSeconds * 1000).getMinutes() * MINUTE_TO_SECOND + new Date(currentTimeInSeconds * 1000).getSeconds();
528
+ };
529
+ var getTimeScaleDescription = function getTimeScaleDescription(timeScale) {
530
+ if (timeScale !== 1 && timeScale < HOUR_TO_SECOND) {
531
+ return Math.round(timeScale / MINUTE_TO_SECOND) + " minutes is ~1 second";
532
+ }
533
+ if (timeScale > 60) {
534
+ var hours = Math.floor(timeScale / HOUR_TO_SECOND);
535
+ var mins = Math.round((timeScale - hours * HOUR_TO_SECOND) / MINUTE_TO_SECOND);
536
+ return hours + " h " + mins + " min is ~1 second";
537
+ }
538
+ return 'Real-time';
539
+ };
540
+ /**
541
+ * Keeps selected time in sync with default time
542
+ * @returns True if selected time sync to default time is enabled
543
+ */
544
+ var useAutoUpdateSelectedTime = function useAutoUpdateSelectedTime(defaultTime, selectedTime, setSelectedTime) {
545
+ var defaultTimeBeforeChange = usePrevious(defaultTime);
546
+ var _useState3 = useState(defaultTime),
547
+ previousDefaultTime = _useState3[0],
548
+ setPreviousDefaultTime = _useState3[1];
549
+ useEffect(function () {
550
+ if (defaultTime !== defaultTimeBeforeChange) {
551
+ setPreviousDefaultTime(defaultTimeBeforeChange);
552
+ }
553
+ // eslint-disable-next-line react-hooks/exhaustive-deps
554
+ }, [defaultTime]);
555
+ useEffect(function () {
556
+ if (previousDefaultTime === selectedTime) {
557
+ setSelectedTime(defaultTime);
558
+ }
559
+ // eslint-disable-next-line react-hooks/exhaustive-deps
560
+ }, [previousDefaultTime]);
561
+ return defaultTime === selectedTime;
562
+ };
563
+
564
+ var timeSliderLiteUtils = /*#__PURE__*/Object.freeze({
565
+ __proto__: null,
566
+ DAY_TO_MILLISECOND: DAY_TO_MILLISECOND,
567
+ DAY_TO_SECOND: DAY_TO_SECOND,
568
+ HOUR_TO_MINUTE: HOUR_TO_MINUTE,
569
+ HOUR_TO_SECOND: HOUR_TO_SECOND,
570
+ MILLISECOND_TO_DAY: MILLISECOND_TO_DAY,
571
+ MILLISECOND_TO_MINUTE: MILLISECOND_TO_MINUTE,
572
+ MILLISECOND_TO_SECOND: MILLISECOND_TO_SECOND,
573
+ MINUTE_TO_MILLISECOND: MINUTE_TO_MILLISECOND,
574
+ MINUTE_TO_SECOND: MINUTE_TO_SECOND,
575
+ SECOND_TO_DAY: SECOND_TO_DAY,
576
+ SECOND_TO_HOUR: SECOND_TO_HOUR,
577
+ SECOND_TO_MILLISECOND: SECOND_TO_MILLISECOND,
578
+ SEVEN_DAYS_IN_SECONDS: SEVEN_DAYS_IN_SECONDS,
579
+ TIME_SLIDER_LITE_DEFAULT_MAX_FORECAST_RANGE: TIME_SLIDER_LITE_DEFAULT_MAX_FORECAST_RANGE,
580
+ TIME_SLIDER_LITE_DEFAULT_MAX_OBSERVED_RANGE: TIME_SLIDER_LITE_DEFAULT_MAX_OBSERVED_RANGE,
581
+ boundedValue: boundedValue,
582
+ defaultTimeRange: defaultTimeRange,
583
+ defaultTimeSliderLiteUpdate: defaultTimeSliderLiteUpdate,
584
+ floorLocalMinutes: floorLocalMinutes,
585
+ floorLocalSeconds: floorLocalSeconds,
586
+ generateCustomTimeList: generateCustomTimeList,
587
+ getMonthChanges: getMonthChanges,
588
+ getNearestSelectableTime: getNearestSelectableTime,
589
+ getRemainingHours: getRemainingHours,
590
+ getSelectedTimeFromPx: getSelectedTimeFromPx,
591
+ getSelectedTimePx: getSelectedTimePx,
592
+ getTimeScaleDescription: getTimeScaleDescription,
593
+ hoursAndDaysToSeconds: hoursAndDaysToSeconds,
594
+ isWithinRange: isWithinRange,
595
+ maxSubTicksPerDay: maxSubTicksPerDay,
596
+ reformatFinnishDateString: reformatFinnishDateString,
597
+ secondsSinceLocalMidnight: secondsSinceLocalMidnight,
598
+ secondsToDaysAndHours: secondsToDaysAndHours,
599
+ shortUTCTime: shortUTCTime,
600
+ subTicksPerDay: subTicksPerDay,
601
+ useAutoUpdate: useAutoUpdate,
602
+ useAutoUpdateSelectedTime: useAutoUpdateSelectedTime,
603
+ useDefaultTimeRange: useDefaultTimeRange
604
+ });
605
+
606
+ var TIME_SLIDER_LITE_NAMESPACE = 'timesliderlite';
607
+ var initTimeSliderLiteI18n = function initTimeSliderLiteI18n(language, i18nInstance) {
608
+ var i18nInst = i18nInstance != null ? i18nInstance : i18n;
609
+ safelyInitI18nForTestsAndStories(i18nInst, TIME_SLIDER_LITE_NAMESPACE, [], language);
610
+ // load all translations here that are needed for tests and stories
611
+ i18nInst.addResourceBundle('en', TIME_SLIDER_LITE_NAMESPACE, translations['en']);
612
+ i18nInst.addResourceBundle('en', CORE_NAMESPACE, coreTranslations['en']);
613
+ i18nInst.addResourceBundle('fi', TIME_SLIDER_LITE_NAMESPACE, translations['fi']);
614
+ i18nInst.addResourceBundle('fi', CORE_NAMESPACE, coreTranslations['fi']);
615
+ i18nInst.addResourceBundle('sv-FI', TIME_SLIDER_LITE_NAMESPACE, translations['sv-FI']);
616
+ };
617
+ /**
618
+ * This provider is limited to TimeSliderLite translations.
619
+ *
620
+ * If you need more translations, install i18next and react-i18next packages and create your own I18nextProvider as multiple providers are not supported.
621
+ *
622
+ * You can then import TIME_SLIDER_LITE_NAMESPACE and timeSliderLiteTranslations and use it to build your own provider.
623
+ * @language TimeSliderLiteLanguage - optional - default 'en'
624
+ * @returns I18nextProvider
625
+ */
626
+ var TimeSliderLiteI18nProvider = function TimeSliderLiteI18nProvider(_ref) {
627
+ var children = _ref.children,
628
+ language = _ref.language,
629
+ i18nInstance = _ref.i18nInstance;
630
+ initTimeSliderLiteI18n(language, i18nInstance);
631
+ return jsx(I18nextProvider, {
632
+ i18n: i18nInstance != null ? i18nInstance : i18n,
633
+ children: children
634
+ });
635
+ };
636
+ var useTimesliderLiteTranslation = function useTimesliderLiteTranslation() {
637
+ return useTranslation(TIME_SLIDER_LITE_NAMESPACE);
638
+ };
639
+
640
+ var _excluded$3 = ["dropdownButtonIcon", "value", "setValue", "defaultTimeStep", "timeStepOptions"];
641
+ var TimeStepSelector = function TimeStepSelector(_ref) {
642
+ var dropdownButtonIcon = _ref.dropdownButtonIcon,
643
+ value = _ref.value,
644
+ setValue = _ref.setValue,
645
+ defaultTimeStep = _ref.defaultTimeStep,
646
+ timeStepOptions = _ref.timeStepOptions,
647
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
648
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
649
+ t = _useTimesliderLiteTra.t;
650
+ var defaultTimeStepOptions = {
651
+ 5: "5 " + t('units.minutes'),
652
+ 15: "15 " + t('units.minutes'),
653
+ 30: "30 " + t('units.minutes'),
654
+ 60: "1 " + t('units.hours'),
655
+ 180: "3 " + t('units.hours'),
656
+ 360: "6 " + t('units.hours'),
657
+ 720: "12 " + t('units.hours')
658
+ };
659
+ var options = timeStepOptions != null ? timeStepOptions : defaultTimeStepOptions;
660
+ var allOptionsKeys = Object.keys(options);
661
+ var availableOptionKeys = allOptionsKeys.filter(function (option) {
662
+ return Number(option) >= defaultTimeStep;
663
+ });
664
+ return jsx(Select, Object.assign({}, props, {
665
+ className: "TimeSliderLite-timeStepSelect",
666
+ "data-testid": "TimeSliderLite-timeStepSelect",
667
+ inputProps: {
668
+ 'data-testid': 'TimeSliderLite-timeStepSelect-input'
669
+ },
670
+ sx: {
671
+ height: '40px',
672
+ width: '100%'
673
+ },
674
+ value: String(availableOptionKeys.includes(String(value)) ? value : availableOptionKeys[availableOptionKeys.length - 1]),
675
+ onChange: function onChange(event) {
676
+ var _event$target;
677
+ var newValue = Number(event == null || (_event$target = event.target) == null ? void 0 : _event$target.value);
678
+ setValue(newValue);
679
+ },
680
+ IconComponent: dropdownButtonIcon,
681
+ children: availableOptionKeys.map(function (option) {
682
+ return jsx(MenuItem, {
683
+ value: String(option),
684
+ children: options[option]
685
+ }, String(option));
686
+ })
687
+ }));
688
+ };
689
+
690
+ var SubmenuSelectLabel = function SubmenuSelectLabel(_ref) {
691
+ var children = _ref.children,
692
+ isDisabled = _ref.isDisabled;
693
+ return jsx(Typography, {
694
+ sx: {
695
+ opacity: isDisabled ? 0.5 : 1,
696
+ fontWeight: '400',
697
+ paddingTop: '10px'
698
+ },
699
+ children: children
700
+ });
701
+ };
702
+
703
+ var TimeStepOptions = function TimeStepOptions(_ref) {
704
+ var useTimeStep = _ref.useTimeStep,
705
+ _ref$defaultTimeStep = _ref.defaultTimeStep,
706
+ defaultTimeStep = _ref$defaultTimeStep === void 0 ? [5, 15] : _ref$defaultTimeStep,
707
+ timeStepOptions = _ref.timeStepOptions,
708
+ dropdownButtonIcon = _ref.dropdownButtonIcon;
709
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
710
+ t = _useTimesliderLiteTra.t;
711
+ var isReadOnly = useTimeStep === undefined;
712
+ var timeStep = useTimeStep == null ? void 0 : useTimeStep[0];
713
+ var setTimeStep = useTimeStep == null ? void 0 : useTimeStep[1];
714
+ var observedTimeStepProp = timeStep == null ? void 0 : timeStep[0];
715
+ var forecastTimeStepProp = timeStep == null ? void 0 : timeStep[1];
716
+ var isDefault = !useTimeStep || timeStep === null;
717
+ var defaultObservedTimeStep = defaultTimeStep[0];
718
+ var defaultForecastTimeStep = defaultTimeStep[1];
719
+ var _React$useState = React.useState(observedTimeStepProp != null ? observedTimeStepProp : defaultObservedTimeStep),
720
+ observedTimeStep = _React$useState[0],
721
+ setObservedTimeStep = _React$useState[1];
722
+ var _React$useState2 = React.useState(forecastTimeStepProp != null ? forecastTimeStepProp : defaultForecastTimeStep),
723
+ forecastTimeStep = _React$useState2[0],
724
+ setForecastTimeStep = _React$useState2[1];
725
+ useEffect(function () {
726
+ if (!isDefault && setTimeStep) {
727
+ setTimeStep([observedTimeStep, forecastTimeStep]);
728
+ }
729
+ // eslint-disable-next-line react-hooks/exhaustive-deps
730
+ }, [observedTimeStep, forecastTimeStep]);
731
+ var handleIsDefaultChange = function handleIsDefaultChange(event) {
732
+ if (event.target.value === 'default') {
733
+ setTimeStep && setTimeStep(null);
734
+ setObservedTimeStep(defaultTimeStep[0]);
735
+ setForecastTimeStep(defaultTimeStep[1]);
736
+ }
737
+ if (event.target.value === 'custom' && setTimeStep) {
738
+ setTimeStep(defaultTimeStep);
739
+ }
740
+ };
741
+ return jsxs(CardContent, {
742
+ "data-testid": "TimeSliderLite-timeStepOptions",
743
+ sx: {
744
+ paddingTop: '4px',
745
+ '& label': {
746
+ height: '36px'
747
+ },
748
+ '&:last-child': {
749
+ paddingBottom: '16px'
750
+ }
751
+ },
752
+ children: [jsxs(RadioGroup, {
753
+ defaultValue: isDefault ? 'default' : 'custom',
754
+ name: "time-range-radio-button-group",
755
+ row: true,
756
+ sx: {
757
+ marginTop: 1
758
+ },
759
+ value: isDefault ? 'default' : 'custom',
760
+ onChange: handleIsDefaultChange,
761
+ children: [jsx(FormControlLabel, {
762
+ disabled: isReadOnly,
763
+ value: "default",
764
+ control: jsx(Radio, {}),
765
+ label: t('common.default')
766
+ }), jsx(FormControlLabel, {
767
+ disabled: isReadOnly,
768
+ value: "custom",
769
+ control: jsx(Radio, {}),
770
+ label: t('common.custom')
771
+ })]
772
+ }), jsxs(Grid, {
773
+ container: true,
774
+ width: 250,
775
+ children: [jsx(Grid, {
776
+ size: {
777
+ xs: 4
778
+ },
779
+ sx: {
780
+ marginY: 1
781
+ },
782
+ children: jsx(SubmenuSelectLabel, {
783
+ isDisabled: isDefault,
784
+ children: t('common.observed')
785
+ })
786
+ }), jsx(Grid, {
787
+ size: {
788
+ xs: 8
789
+ },
790
+ paddingX: "4px",
791
+ sx: {
792
+ marginY: 1
793
+ },
794
+ children: jsx(TimeStepSelector, {
795
+ disabled: isDefault,
796
+ value: observedTimeStep,
797
+ setValue: setObservedTimeStep,
798
+ defaultTimeStep: defaultTimeStep[0],
799
+ dropdownButtonIcon: dropdownButtonIcon,
800
+ timeStepOptions: timeStepOptions
801
+ })
802
+ }), jsx(Grid, {
803
+ size: {
804
+ xs: 4
805
+ },
806
+ children: jsx(SubmenuSelectLabel, {
807
+ isDisabled: isDefault,
808
+ children: t('common.forecast')
809
+ })
810
+ }), jsx(Grid, {
811
+ size: {
812
+ xs: 8
813
+ },
814
+ paddingX: "4px",
815
+ children: jsx(TimeStepSelector, {
816
+ disabled: isDefault,
817
+ value: forecastTimeStep,
818
+ setValue: setForecastTimeStep,
819
+ defaultTimeStep: defaultTimeStep[1],
820
+ dropdownButtonIcon: dropdownButtonIcon,
821
+ timeStepOptions: timeStepOptions
822
+ })
823
+ })]
824
+ })]
825
+ });
826
+ };
827
+
828
+ var _excluded$2 = ["amountOfOptions", "dropdownButtonIcon", "itemPostFix", "value", "setValue"];
829
+ var CustomSelect = function CustomSelect(_ref) {
830
+ var amountOfOptions = _ref.amountOfOptions,
831
+ dropdownButtonIcon = _ref.dropdownButtonIcon,
832
+ itemPostFix = _ref.itemPostFix,
833
+ value = _ref.value,
834
+ setValue = _ref.setValue,
835
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$2);
836
+ var availableOptions = Array.from(Array(amountOfOptions).keys());
837
+ return jsx(Select, Object.assign({}, props, {
838
+ "data-testid": "TimeSliderLite-customSelect-" + itemPostFix,
839
+ inputProps: {
840
+ 'data-testid': "TimeSliderLite-customSelect-" + itemPostFix + "-input"
841
+ },
842
+ sx: {
843
+ height: '40px',
844
+ width: '100%'
845
+ },
846
+ value: String(availableOptions.includes(value) ? value : availableOptions[availableOptions.length - 1]),
847
+ onChange: function onChange(event) {
848
+ var _event$target;
849
+ var newValue = Number(event == null || (_event$target = event.target) == null ? void 0 : _event$target.value);
850
+ if (availableOptions.includes(newValue)) {
851
+ setValue(newValue);
852
+ }
853
+ },
854
+ autoWidth: false,
855
+ IconComponent: dropdownButtonIcon,
856
+ children: availableOptions.map(function (option) {
857
+ return jsxs(MenuItem, {
858
+ value: String(option),
859
+ children: [option, " ", itemPostFix]
860
+ }, option);
861
+ })
862
+ }));
863
+ };
864
+ var DayHourSelector = function DayHourSelector(_ref2) {
865
+ var isDisabled = _ref2.isDisabled,
866
+ dropdownButtonIcon = _ref2.dropdownButtonIcon,
867
+ label = _ref2.label,
868
+ maxHours = _ref2.maxHours,
869
+ sx = _ref2.sx,
870
+ useDays = _ref2.useDays,
871
+ useHours = _ref2.useHours;
872
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
873
+ t = _useTimesliderLiteTra.t;
874
+ var days = useDays[0],
875
+ setDays = useDays[1];
876
+ var hours = useHours[0],
877
+ setHours = useHours[1];
878
+ var remainingHours = getRemainingHours(maxHours, days);
879
+ var amountOfDayOptions = maxHours ? Math.floor(maxHours / 24) + 1 : 1;
880
+ var amountOfHourOptions = maxHours ? Math.min(24, remainingHours + 1) : 1;
881
+ return jsxs(Grid, {
882
+ container: true,
883
+ sx: sx,
884
+ children: [jsx(Grid, {
885
+ size: {
886
+ xs: 3
887
+ },
888
+ children: jsx(SubmenuSelectLabel, {
889
+ isDisabled: isDisabled || amountOfDayOptions === 1 && amountOfHourOptions === 1,
890
+ children: label
891
+ })
892
+ }), jsx(Grid, {
893
+ size: {
894
+ xs: 4.5
895
+ },
896
+ paddingX: "4px",
897
+ children: jsx(CustomSelect, {
898
+ disabled: isDisabled || amountOfDayOptions === 1,
899
+ value: days,
900
+ setValue: setDays,
901
+ itemPostFix: t('units.days'),
902
+ amountOfOptions: amountOfDayOptions,
903
+ dropdownButtonIcon: dropdownButtonIcon
904
+ })
905
+ }), jsx(Grid, {
906
+ size: {
907
+ xs: 4.5
908
+ },
909
+ paddingLeft: "4px",
910
+ children: jsx(CustomSelect, {
911
+ disabled: isDisabled || amountOfHourOptions === 1,
912
+ value: hours,
913
+ setValue: setHours,
914
+ itemPostFix: t('units.hours'),
915
+ amountOfOptions: amountOfHourOptions,
916
+ dropdownButtonIcon: dropdownButtonIcon
917
+ })
918
+ })]
919
+ });
920
+ };
921
+
922
+ var TIME_SELECTOR_MIN_WIDTH = '21em';
923
+ var TimeRangeOptions = function TimeRangeOptions(_ref) {
924
+ var _ref$currentTime = _ref.currentTime,
925
+ currentTime = _ref$currentTime === void 0 ? Date.now().valueOf() * MILLISECOND_TO_SECOND : _ref$currentTime,
926
+ useTimeRange = _ref.useTimeRange,
927
+ defaultTimeRange = _ref.defaultTimeRange,
928
+ dropdownButtonIcon = _ref.dropdownButtonIcon;
929
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
930
+ t = _useTimesliderLiteTra.t;
931
+ var isReadOnly = useTimeRange === undefined;
932
+ var isDefault = !useTimeRange || useTimeRange[0] === null;
933
+ var handleIsDefaultChange = function handleIsDefaultChange(event) {
934
+ if (event.target.value === 'default' && useTimeRange != null && useTimeRange[1]) {
935
+ useTimeRange[1](null);
936
+ }
937
+ if (event.target.value === 'custom' && useTimeRange != null && useTimeRange[1]) {
938
+ useTimeRange[1](defaultTimeRange);
939
+ }
940
+ };
941
+ var _React$useState = React.useState(0),
942
+ forecastDays = _React$useState[0],
943
+ setForecastDays = _React$useState[1];
944
+ var _React$useState2 = React.useState(0),
945
+ forecastHours = _React$useState2[0],
946
+ setForecastHours = _React$useState2[1];
947
+ var _React$useState3 = React.useState(0),
948
+ observedDays = _React$useState3[0],
949
+ setObservedDays = _React$useState3[1];
950
+ var _React$useState4 = React.useState(0),
951
+ observedHours = _React$useState4[0],
952
+ setObservedHours = _React$useState4[1];
953
+ useEffect(function () {
954
+ if (!isDefault && !isReadOnly) {
955
+ var observedSeconds = Math.min(hoursAndDaysToSeconds(observedHours, observedDays), currentTime - defaultTimeRange[0]);
956
+ var forecastSeconds = Math.min(hoursAndDaysToSeconds(forecastHours, forecastDays), defaultTimeRange[1] - currentTime);
957
+ if (useTimeRange != null && useTimeRange[1]) {
958
+ useTimeRange[1]([currentTime - observedSeconds, currentTime + forecastSeconds]);
959
+ }
960
+ }
961
+ // eslint-disable-next-line react-hooks/exhaustive-deps
962
+ }, [forecastDays, forecastHours, observedDays, observedHours]);
963
+ useLayoutEffect(function () {
964
+ if (useTimeRange) {
965
+ var timeRange = useTimeRange[0];
966
+ var _ref2 = timeRange || defaultTimeRange,
967
+ timeStart = _ref2[0],
968
+ timeEnd = _ref2[1];
969
+ var timeToEndSeconds = timeEnd - currentTime > 0 ? timeEnd - currentTime : 0;
970
+ var timeToStartSeconds = currentTime - timeStart > 0 ? currentTime - timeStart : 0;
971
+ var _secondsToDaysAndHour = secondsToDaysAndHours(timeToEndSeconds),
972
+ _forecastDays = _secondsToDaysAndHour.days,
973
+ _forecastHours = _secondsToDaysAndHour.hours;
974
+ var _secondsToDaysAndHour2 = secondsToDaysAndHours(timeToStartSeconds),
975
+ _observedDays = _secondsToDaysAndHour2.days,
976
+ _observedHours = _secondsToDaysAndHour2.hours;
977
+ setForecastDays(_forecastDays);
978
+ setForecastHours(_forecastHours);
979
+ setObservedDays(_observedDays);
980
+ setObservedHours(_observedHours);
981
+ }
982
+ // eslint-disable-next-line react-hooks/exhaustive-deps
983
+ }, [isDefault]);
984
+ var customTimeRange = (useTimeRange == null ? void 0 : useTimeRange[0]) || defaultTimeRange;
985
+ var minStartTime = Math.min(defaultTimeRange[0], customTimeRange[0]);
986
+ var observedHoursToCurrentTime = (currentTime - minStartTime) * SECOND_TO_HOUR;
987
+ var maxObservedHours = observedHoursToCurrentTime > 0 ? Math.floor(observedHoursToCurrentTime) : 0;
988
+ var maxEndTime = Math.max(defaultTimeRange[1], customTimeRange[1]);
989
+ var forecastHoursToCurrentTime = (maxEndTime - currentTime) * SECOND_TO_HOUR;
990
+ var maxForecastHours = forecastHoursToCurrentTime > 0 ? Math.floor(forecastHoursToCurrentTime) : 0;
991
+ return jsxs(CardContent, {
992
+ className: "TimeSliderLite-timeRangeOptions",
993
+ "data-testid": "TimeSliderLite-timeRangeOptions",
994
+ sx: {
995
+ paddingTop: '4px',
996
+ '& label': {
997
+ height: '36px'
998
+ },
999
+ '&:last-child': {
1000
+ paddingBottom: '16px'
1001
+ }
1002
+ },
1003
+ children: [t('menu.timeRange.description'), jsxs(RadioGroup, {
1004
+ defaultValue: isDefault ? 'default' : 'custom',
1005
+ name: "time-range-radio-button-group",
1006
+ row: true,
1007
+ sx: {
1008
+ marginTop: 1
1009
+ },
1010
+ value: isDefault ? 'default' : 'custom',
1011
+ onChange: handleIsDefaultChange,
1012
+ children: [jsx(FormControlLabel, {
1013
+ disabled: isReadOnly,
1014
+ value: "default",
1015
+ control: jsx(Radio, {}),
1016
+ label: t('common.default')
1017
+ }), jsx(FormControlLabel, {
1018
+ disabled: isReadOnly,
1019
+ value: "custom",
1020
+ control: jsx(Radio, {}),
1021
+ label: t('common.custom')
1022
+ })]
1023
+ }), jsxs(Box, {
1024
+ minWidth: TIME_SELECTOR_MIN_WIDTH,
1025
+ children: [jsx(DayHourSelector, {
1026
+ isDisabled: isDefault,
1027
+ dropdownButtonIcon: dropdownButtonIcon,
1028
+ label: t('common.observed'),
1029
+ maxHours: maxObservedHours,
1030
+ sx: {
1031
+ marginY: 1
1032
+ },
1033
+ useDays: [observedDays, setObservedDays],
1034
+ useHours: [observedHours, setObservedHours]
1035
+ }), jsx(DayHourSelector, {
1036
+ isDisabled: isDefault,
1037
+ dropdownButtonIcon: dropdownButtonIcon,
1038
+ label: t('common.forecast'),
1039
+ maxHours: maxForecastHours,
1040
+ useDays: [forecastDays, setForecastDays],
1041
+ useHours: [forecastHours, setForecastHours]
1042
+ })]
1043
+ })]
1044
+ });
1045
+ };
1046
+
1047
+ var AnimationSpeedOptions = function AnimationSpeedOptions(_ref) {
1048
+ var _useAnimationSpeed$;
1049
+ var dropdownButtonIcon = _ref.dropdownButtonIcon,
1050
+ _ref$speedOptions = _ref.speedOptions,
1051
+ speedOptions = _ref$speedOptions === void 0 ? speedFactors.sort(function (speedA, speedB) {
1052
+ return speedB - speedA;
1053
+ }) : _ref$speedOptions,
1054
+ _ref$speedOptionItemP = _ref.speedOptionItemPrefix,
1055
+ speedOptionItemPrefix = _ref$speedOptionItemP === void 0 ? 'x ' : _ref$speedOptionItemP,
1056
+ _ref$speedOptionItemP2 = _ref.speedOptionItemPostfix,
1057
+ speedOptionItemPostfix = _ref$speedOptionItemP2 === void 0 ? '' : _ref$speedOptionItemP2,
1058
+ defaultSpeedOptionPostfix = _ref.defaultSpeedOptionPostfix,
1059
+ _ref$defaultSpeedFact = _ref.defaultSpeedFactor,
1060
+ defaultSpeedFactor = _ref$defaultSpeedFact === void 0 ? speedFactors[2] : _ref$defaultSpeedFact,
1061
+ useAnimationSpeed = _ref.useAnimationSpeed;
1062
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1063
+ t = _useTimesliderLiteTra.t;
1064
+ var translatedSpeedOptionPostfix = defaultSpeedOptionPostfix != null ? defaultSpeedOptionPostfix : " (" + t('common.default').toLocaleLowerCase() + ")";
1065
+ var animationSpeed = (_useAnimationSpeed$ = useAnimationSpeed == null ? void 0 : useAnimationSpeed[0]) != null ? _useAnimationSpeed$ : defaultSpeedFactor;
1066
+ var setAnimationSpeed = useAnimationSpeed == null ? void 0 : useAnimationSpeed[1];
1067
+ var readOnly = !setAnimationSpeed || speedOptions.length < 2;
1068
+ return jsx(CardContent, {
1069
+ className: "TimeSliderLite-animationSpeedOptions",
1070
+ "data-testid": "TimeSliderLite-animationSpeedOptions",
1071
+ sx: {
1072
+ paddingTop: '12px',
1073
+ marginBottom: '-8px',
1074
+ minWidth: '200px'
1075
+ },
1076
+ children: jsx(Select, {
1077
+ disabled: readOnly,
1078
+ className: "TimeSliderLite-animationSpeedSelect",
1079
+ "data-testid": "TimeSliderLite-animationSpeedSelect",
1080
+ inputProps: {
1081
+ 'data-testid': 'TimeSliderLite-animationSpeedSelect-input'
1082
+ },
1083
+ sx: {
1084
+ height: '40px'
1085
+ },
1086
+ value: String(animationSpeed),
1087
+ onChange: function onChange(event) {
1088
+ var _event$target;
1089
+ var newValue = Number(event == null || (_event$target = event.target) == null ? void 0 : _event$target.value);
1090
+ setAnimationSpeed && setAnimationSpeed(newValue);
1091
+ },
1092
+ IconComponent: dropdownButtonIcon,
1093
+ children: speedOptions.map(function (option) {
1094
+ var postfix = option === defaultSpeedFactor ? translatedSpeedOptionPostfix : speedOptionItemPostfix;
1095
+ var label = speedOptionItemPrefix + option + postfix;
1096
+ return jsx(MenuItem, {
1097
+ value: String(option),
1098
+ children: label
1099
+ }, String(option));
1100
+ })
1101
+ })
1102
+ });
1103
+ };
1104
+
1105
+ var defaultUpdateIntervalOptions = [1, 2, 5, 10, 15, 30, 60];
1106
+ var UpdateIntervalOptions = function UpdateIntervalOptions(_ref) {
1107
+ var _useUpdateInterval$, _updateIntervalOption;
1108
+ var _ref$defaultUpdateInt = _ref.defaultUpdateInterval,
1109
+ defaultUpdateInterval = _ref$defaultUpdateInt === void 0 ? 1 : _ref$defaultUpdateInt,
1110
+ dropdownButtonIcon = _ref.dropdownButtonIcon,
1111
+ _ref$intervalOptionPr = _ref.intervalOptionPrefix,
1112
+ intervalOptionPrefix = _ref$intervalOptionPr === void 0 ? '' : _ref$intervalOptionPr,
1113
+ intervalOptionPostfix = _ref.intervalOptionPostfix,
1114
+ defaultOptionPostfix = _ref.defaultOptionPostfix,
1115
+ _ref$updateIntervalOp = _ref.updateIntervalOptions,
1116
+ updateIntervalOptions = _ref$updateIntervalOp === void 0 ? defaultUpdateIntervalOptions.sort(function (optionA, optionB) {
1117
+ return optionA - optionB;
1118
+ }) : _ref$updateIntervalOp,
1119
+ useUpdateInterval = _ref.useUpdateInterval;
1120
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1121
+ t = _useTimesliderLiteTra.t;
1122
+ var translatedIntervalOptionPostfix = intervalOptionPostfix != null ? intervalOptionPostfix : " " + t('units.minutes');
1123
+ var translatedDefaultOptionPostfix = defaultOptionPostfix != null ? defaultOptionPostfix : " " + t('units.minutes') + " (" + t('common.default').toLowerCase() + ")";
1124
+ var updateInterval = (_useUpdateInterval$ = useUpdateInterval == null ? void 0 : useUpdateInterval[0]) != null ? _useUpdateInterval$ : defaultUpdateInterval;
1125
+ var setUpdateInterval = useUpdateInterval == null ? void 0 : useUpdateInterval[1];
1126
+ var readOnly = !setUpdateInterval || updateIntervalOptions.length < 2;
1127
+ var defaultValue = (_updateIntervalOption = updateIntervalOptions.find(function (option) {
1128
+ return option === defaultUpdateInterval;
1129
+ })) != null ? _updateIntervalOption : Math.min.apply(Math, updateIntervalOptions);
1130
+ return jsx(CardContent, {
1131
+ className: "TimeSliderLite-updateIntervalOptions",
1132
+ "data-testid": "TimeSliderLite-updateIntervalOptions",
1133
+ sx: {
1134
+ paddingTop: '12px',
1135
+ marginBottom: '-8px',
1136
+ minWidth: '200px'
1137
+ },
1138
+ children: jsx(Select, {
1139
+ disabled: readOnly,
1140
+ className: "TimeSliderLite-updateIntervalSelect",
1141
+ "data-testid": "TimeSliderLite-updateIntervalSelect",
1142
+ inputProps: {
1143
+ 'data-testid': 'TimeSliderLite-updateIntervalSelect-input'
1144
+ },
1145
+ sx: {
1146
+ height: '40px'
1147
+ },
1148
+ value: String(updateInterval != null ? updateInterval : defaultValue),
1149
+ onChange: function onChange(event) {
1150
+ var _event$target;
1151
+ var newValue = Number(event == null || (_event$target = event.target) == null ? void 0 : _event$target.value);
1152
+ setUpdateInterval && setUpdateInterval(newValue === defaultValue ? null : newValue);
1153
+ },
1154
+ IconComponent: dropdownButtonIcon,
1155
+ children: updateIntervalOptions.map(function (option) {
1156
+ var label = option === defaultValue ? "" + intervalOptionPrefix + option + translatedDefaultOptionPostfix : "" + intervalOptionPrefix + option + translatedIntervalOptionPostfix;
1157
+ return jsx(MenuItem, {
1158
+ value: String(option),
1159
+ children: label
1160
+ }, String(option));
1161
+ })
1162
+ })
1163
+ });
1164
+ };
1165
+
1166
+ var availableTimeZones = ['LT', 'UTC'];
1167
+ var styles$3 = {
1168
+ root: {
1169
+ marginY: 0.5,
1170
+ marginRight: 1,
1171
+ '> button': {
1172
+ borderRadius: 10,
1173
+ height: '36px',
1174
+ textTransform: 'none'
1175
+ },
1176
+ '> button:first-of-type': {
1177
+ paddingRight: 1
1178
+ },
1179
+ '> button:last-of-type': {
1180
+ paddingLeft: 1
1181
+ }
1182
+ }
1183
+ };
1184
+ var TimeZoneSwitch = function TimeZoneSwitch(_ref) {
1185
+ var _ref$useTimeZone = _ref.useTimeZone,
1186
+ _ref$useTimeZone2 = _ref$useTimeZone === void 0 ? ['LT', undefined] : _ref$useTimeZone,
1187
+ timeZone = _ref$useTimeZone2[0],
1188
+ setTimeZone = _ref$useTimeZone2[1];
1189
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1190
+ t = _useTimesliderLiteTra.t;
1191
+ return jsx(ToggleButtonGroup, {
1192
+ disabled: !setTimeZone,
1193
+ className: "TimeSliderLite-timeZoneSwitch",
1194
+ "data-testid": "TimeSliderLite-timeZoneSwitch",
1195
+ value: timeZone != null ? timeZone : 'LT',
1196
+ exclusive: true,
1197
+ sx: styles$3.root,
1198
+ onChange: function onChange(_event, newZone) {
1199
+ if (newZone && setTimeZone) {
1200
+ setTimeZone(newZone);
1201
+ }
1202
+ },
1203
+ children: availableTimeZones.map(function (zone) {
1204
+ return jsx(ToggleButton, {
1205
+ value: zone,
1206
+ children: t("menu." + zone)
1207
+ }, zone);
1208
+ })
1209
+ });
1210
+ };
1211
+
1212
+ var styles$2 = {
1213
+ button: {
1214
+ height: '36px',
1215
+ lineHeight: '1em',
1216
+ border: 'none',
1217
+ textTransform: 'none',
1218
+ borderRadius: '2px !important',
1219
+ color: 'geowebColors.typographyAndIcons.text',
1220
+ '&.Mui-selected': {
1221
+ backgroundColor: 'geowebColors.timeSliderLite.selected.backgroundColor'
1222
+ },
1223
+ '&:disabled': {
1224
+ border: 'none'
1225
+ }
1226
+ }
1227
+ };
1228
+ // TODO: Add translations
1229
+ var SubmenuTitleTranslations;
1230
+ (function (SubmenuTitleTranslations) {
1231
+ SubmenuTitleTranslations["TIME_RANGE"] = "menu.timeRange";
1232
+ SubmenuTitleTranslations["TIME_STEP"] = "menu.timeStep";
1233
+ SubmenuTitleTranslations["SPEED"] = "menu.speed";
1234
+ SubmenuTitleTranslations["UPDATE_INTERVAL"] = "menu.updateInterval";
1235
+ })(SubmenuTitleTranslations || (SubmenuTitleTranslations = {}));
1236
+ var TimeSliderLiteOptionsMenu = function TimeSliderLiteOptionsMenu(_ref) {
1237
+ var closeButtonIcon = _ref.closeButtonIcon,
1238
+ _ref$currentTime = _ref.currentTime,
1239
+ currentTime = _ref$currentTime === void 0 ? Date.now().valueOf() * MILLISECOND_TO_SECOND : _ref$currentTime,
1240
+ defaultTimeRange = _ref.defaultTimeRange,
1241
+ defaultTimeStep = _ref.defaultTimeStep,
1242
+ defaultSpeedFactor = _ref.defaultSpeedFactor,
1243
+ defaultUpdateInterval = _ref.defaultUpdateInterval,
1244
+ dropdownButtonIcon = _ref.dropdownButtonIcon,
1245
+ menuOpen = _ref.menuOpen,
1246
+ setMenuOpen = _ref.setMenuOpen,
1247
+ speedOptionItemPostfix = _ref.speedOptionItemPostfix,
1248
+ speedOptionItemPrefix = _ref.speedOptionItemPrefix,
1249
+ speedOptions = _ref.speedOptions,
1250
+ updateIntervalOptions = _ref.updateIntervalOptions,
1251
+ subMenuSx = _ref.subMenuSx,
1252
+ sx = _ref.sx,
1253
+ _ref$TimeZoneSwitch = _ref.TimeZoneSwitch,
1254
+ TimeZoneSwitch$1 = _ref$TimeZoneSwitch === void 0 ? TimeZoneSwitch : _ref$TimeZoneSwitch,
1255
+ timeStepOptions = _ref.timeStepOptions,
1256
+ useAnimationSpeed = _ref.useAnimationSpeed,
1257
+ useTimeRange = _ref.useTimeRange,
1258
+ useTimeStep = _ref.useTimeStep,
1259
+ useTimeZone = _ref.useTimeZone,
1260
+ useUpdateInterval = _ref.useUpdateInterval;
1261
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1262
+ t = _useTimesliderLiteTra.t;
1263
+ var _React$useState = React.useState(null),
1264
+ submenu = _React$useState[0],
1265
+ setSubmenu = _React$useState[1];
1266
+ var _React$useState2 = React.useState(0),
1267
+ submenuLeft = _React$useState2[0],
1268
+ setSubmenuLeft = _React$useState2[1];
1269
+ return jsxs(Fragment, {
1270
+ children: [submenu && jsxs(SubmenuWrapper, {
1271
+ sx: Object.assign({
1272
+ left: submenuLeft,
1273
+ marginLeft: '-12px'
1274
+ }, subMenuSx),
1275
+ setSubmenu: setSubmenu,
1276
+ title: t(submenu + ".title"),
1277
+ closeButtonIcon: closeButtonIcon,
1278
+ children: [submenu === SubmenuTitleTranslations.TIME_RANGE && jsx(TimeRangeOptions, {
1279
+ currentTime: currentTime,
1280
+ useTimeRange: useTimeRange,
1281
+ defaultTimeRange: defaultTimeRange,
1282
+ dropdownButtonIcon: dropdownButtonIcon
1283
+ }), submenu === SubmenuTitleTranslations.TIME_STEP && jsx(TimeStepOptions, {
1284
+ defaultTimeStep: defaultTimeStep,
1285
+ useTimeStep: useTimeStep,
1286
+ dropdownButtonIcon: dropdownButtonIcon,
1287
+ timeStepOptions: timeStepOptions
1288
+ }), submenu === SubmenuTitleTranslations.SPEED && jsx(AnimationSpeedOptions, {
1289
+ useAnimationSpeed: useAnimationSpeed,
1290
+ dropdownButtonIcon: dropdownButtonIcon,
1291
+ speedOptionItemPostfix: speedOptionItemPostfix,
1292
+ speedOptionItemPrefix: speedOptionItemPrefix,
1293
+ speedOptions: speedOptions,
1294
+ defaultSpeedFactor: defaultSpeedFactor
1295
+ }), submenu === SubmenuTitleTranslations.UPDATE_INTERVAL && jsx(UpdateIntervalOptions, {
1296
+ defaultUpdateInterval: defaultUpdateInterval,
1297
+ dropdownButtonIcon: dropdownButtonIcon,
1298
+ updateIntervalOptions: updateIntervalOptions,
1299
+ useUpdateInterval: useUpdateInterval
1300
+ })]
1301
+ }), jsxs(Box, {
1302
+ sx: Object.assign({
1303
+ backgroundColor: 'geowebColors.background.surface',
1304
+ borderRadius: 1,
1305
+ display: 'flex',
1306
+ flexDirection: 'row',
1307
+ marginY: 1,
1308
+ visibility: menuOpen ? 'visible' : 'hidden'
1309
+ }, sx),
1310
+ children: [jsx(ToggleButtonGroup, {
1311
+ "data-testid": "TimeSliderLite-optionsMenu",
1312
+ value: submenu,
1313
+ exclusive: true,
1314
+ sx: {
1315
+ padding: 0.5,
1316
+ gap: 0.5
1317
+ },
1318
+ onChange: function onChange(event, newOption) {
1319
+ setSubmenu(newOption);
1320
+ var button = event.currentTarget;
1321
+ var buttonPosition = button.getBoundingClientRect();
1322
+ setSubmenuLeft(buttonPosition.x);
1323
+ },
1324
+ children: Object.values(SubmenuTitleTranslations).map(function (value) {
1325
+ return jsx(ToggleButton, {
1326
+ value: value,
1327
+ sx: styles$2.button,
1328
+ children: t(value + ".button")
1329
+ }, value);
1330
+ })
1331
+ }), jsx(TimeZoneSwitch$1, {
1332
+ useTimeZone: useTimeZone != null ? useTimeZone : ['LT']
1333
+ }), jsx(Divider, {
1334
+ orientation: "vertical",
1335
+ flexItem: true
1336
+ }), jsx(IconButton, {
1337
+ "data-testid": "TimeSliderLite-optionsMenu-closeButton",
1338
+ size: "small",
1339
+ sx: {
1340
+ margin: 0.5
1341
+ },
1342
+ onClick: function onClick() {
1343
+ return setMenuOpen && setMenuOpen(false);
1344
+ },
1345
+ children: closeButtonIcon != null ? closeButtonIcon : jsx(Close, {})
1346
+ })]
1347
+ })]
1348
+ });
1349
+ };
1350
+
1351
+ /* *
1352
+ * Licensed under the Apache License, Version 2.0 (the "License");
1353
+ * you may not use this file except in compliance with the License.
1354
+ * You may obtain a copy of the License at
1355
+ *
1356
+ * http://www.apache.org/licenses/LICENSE-2.0
1357
+ *
1358
+ * Unless required by applicable law or agreed to in writing, software
1359
+ * distributed under the License is distributed on an "AS IS" BASIS,
1360
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361
+ * See the License for the specific language governing permissions and
1362
+ * limitations under the License.
1363
+ *
1364
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
1365
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
1366
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
1367
+ * */
1368
+ var timeSliderLiteButtonDefaultProps = {
1369
+ sx: {
1370
+ width: '36px',
1371
+ height: '36px'
1372
+ }
1373
+ };
1374
+
1375
+ var HideButton = function HideButton(_ref) {
1376
+ var _settings$icon$hide, _settings$icon, _settings$icon$show, _settings$icon2;
1377
+ var isVisible = _ref.isVisible,
1378
+ settings = _ref.settings,
1379
+ onClick = _ref.onClick;
1380
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1381
+ t = _useTimesliderLiteTra.t;
1382
+ var hideIcon = (_settings$icon$hide = settings == null || (_settings$icon = settings.icon) == null ? void 0 : _settings$icon.hide) != null ? _settings$icon$hide : jsx(ChevronDown, {});
1383
+ var showIcon = (_settings$icon$show = settings == null || (_settings$icon2 = settings.icon) == null ? void 0 : _settings$icon2.show) != null ? _settings$icon$show : jsx(ChevronUp, {});
1384
+ return jsx(Tooltip, {
1385
+ placement: "top-end",
1386
+ title: isVisible ? t('controlButtons.hide') : t('controlButtons.show'),
1387
+ children: jsx(IconButton, Object.assign({}, timeSliderLiteButtonDefaultProps, {
1388
+ "aria-selected": !isVisible,
1389
+ onClick: onClick,
1390
+ "data-testid": "TimeSliderLite-HideButton",
1391
+ children: isVisible ? hideIcon : showIcon
1392
+ }))
1393
+ });
1394
+ };
1395
+
1396
+ var _excluded$1 = ["children", "right", "left"];
1397
+ var ControlButtonGroup = function ControlButtonGroup(_ref) {
1398
+ var children = _ref.children,
1399
+ right = _ref.right,
1400
+ left = _ref.left,
1401
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
1402
+ return jsx(ButtonGroup, Object.assign({
1403
+ orientation: "horizontal",
1404
+ fullWidth: true
1405
+ }, props, {
1406
+ sx: Object.assign({}, right && {
1407
+ borderTopLeftRadius: 0,
1408
+ borderBottomLeftRadius: 0
1409
+ }, left && {
1410
+ borderTopRightRadius: 0,
1411
+ borderBottomRightRadius: 0
1412
+ }, {
1413
+ backgroundColor: 'geowebColors.background.surface',
1414
+ height: '100%',
1415
+ alignItems: 'center',
1416
+ justifyContent: 'center',
1417
+ padding: '4px',
1418
+ gap: '2px'
1419
+ }, props.sx),
1420
+ children: children
1421
+ }));
1422
+ };
1423
+
1424
+ var OBSERVED_PADDING_DAYS = 1;
1425
+ var FORECAST_PADDING_DAYS = OBSERVED_PADDING_DAYS + 2;
1426
+ var TICK_HEIGHT = 6;
1427
+ var HOUR_LABEL_OFFSET = 1.5;
1428
+ var MONTH_LABEL_BREAKPOINT = 65;
1429
+ var HOUR_LABEL_BREAKPOINT = 800;
1430
+ var HOUR_LABEL_EVERY_THIRD_HOUR_BREAKPOINT = 1600;
1431
+ var TIME_SLIDER_LITE_PADDING_RIGHT = 1;
1432
+ var TimeSliderLiteBackgroundSvg = function TimeSliderLiteBackgroundSvg(_ref) {
1433
+ var width = _ref.width,
1434
+ height = _ref.height,
1435
+ startTime = _ref.startTime,
1436
+ endTime = _ref.endTime,
1437
+ disableForecast = _ref.disableForecast,
1438
+ _ref$currentTime = _ref.currentTime,
1439
+ currentTime = _ref$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref$currentTime,
1440
+ timeStep = _ref.timeStep,
1441
+ style = _ref.style,
1442
+ _ref$timeZone = _ref.timeZone,
1443
+ timeZone = _ref$timeZone === void 0 ? 'LT' : _ref$timeZone;
1444
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1445
+ i18n = _useTimesliderLiteTra.i18n;
1446
+ var language = i18n.language;
1447
+ var _useTheme = useTheme(),
1448
+ timeSliderLite = _useTheme.palette.geowebColors.timeSliderLite;
1449
+ if (!width) {
1450
+ return jsx("svg", {
1451
+ style: style,
1452
+ height: height
1453
+ });
1454
+ }
1455
+ // Convert start and end time from Unix timestamp to JavaScript Date object
1456
+ var startDate = new Date(startTime * SECOND_TO_MILLISECOND);
1457
+ var endDate = new Date(endTime * SECOND_TO_MILLISECOND);
1458
+ var totalDays = (endDate.getTime() - startDate.getTime()) * MILLISECOND_TO_DAY;
1459
+ var utcOffset = timeZone === 'UTC' ? new Date().getTimezoneOffset() * 60 * SECOND_TO_DAY : 0;
1460
+ var tickSpacing = width / totalDays;
1461
+ if (tickSpacing === Infinity || tickSpacing === -Infinity || isNaN(tickSpacing)) {
1462
+ return null;
1463
+ }
1464
+ var startTimeDayOffset = secondsSinceLocalMidnight(startTime) * SECOND_TO_DAY + utcOffset;
1465
+ var tickOffset = startTimeDayOffset * tickSpacing;
1466
+ var showMonthLabel = tickSpacing < MONTH_LABEL_BREAKPOINT;
1467
+ var maxTimeStep = timeStep ? Math.max.apply(Math, timeStep) : null;
1468
+ var hideHourLabels = maxTimeStep && maxTimeStep > 60 * 60 * 3;
1469
+ var showHourLabel = !hideHourLabels && tickSpacing > HOUR_LABEL_BREAKPOINT;
1470
+ var limitHourLabelsToEveryThirdHour = maxTimeStep && maxTimeStep > 60 * 60;
1471
+ var showHourLabelEveryThirdHour = limitHourLabelsToEveryThirdHour || tickSpacing < HOUR_LABEL_EVERY_THIRD_HOUR_BREAKPOINT;
1472
+ // Set up variables for date labels and background colors
1473
+ var dayLabels = [];
1474
+ var dayLabelDate = new Date(startTime * SECOND_TO_MILLISECOND - OBSERVED_PADDING_DAYS * DAY_TO_MILLISECOND);
1475
+ var lastDayLabelDate = new Date(endDate.getTime() + FORECAST_PADDING_DAYS * DAY_TO_MILLISECOND);
1476
+ while (dayLabelDate < lastDayLabelDate) {
1477
+ var dateString = dayLabelDate.toLocaleDateString(language, {
1478
+ weekday: 'short',
1479
+ month: 'numeric',
1480
+ day: 'numeric'
1481
+ });
1482
+ var label = dateString.charAt(0).toUpperCase() + dateString.slice(1);
1483
+ dayLabels.push(label);
1484
+ dayLabelDate.setDate(dayLabelDate.getDate() + 1);
1485
+ }
1486
+ var monthChanges = getMonthChanges(startDate, endDate);
1487
+ var monthLabels = showMonthLabel ? monthChanges.map(function (monthChange) {
1488
+ var x = getSelectedTimePx(startTime, endTime, monthChange, width) + 4;
1489
+ var dateString = new Date(monthChange * 1000).toLocaleDateString(language, {
1490
+ weekday: 'short',
1491
+ month: 'numeric',
1492
+ day: 'numeric'
1493
+ });
1494
+ var label = dateString.charAt(0).toUpperCase() + dateString.slice(1);
1495
+ return jsx("text", {
1496
+ x: x,
1497
+ y: 14,
1498
+ fill: timeSliderLite.timeline.fill,
1499
+ textAnchor: "left",
1500
+ fontSize: "12px",
1501
+ style: {
1502
+ userSelect: 'none'
1503
+ },
1504
+ children: label
1505
+ }, monthChange + "-month-change-text");
1506
+ }) : null;
1507
+ var currentDayIndex = (currentTime - startTime) * SECOND_TO_DAY + startTimeDayOffset + OBSERVED_PADDING_DAYS;
1508
+ var backgroundRectangles = dayLabels.map(function (label, index) {
1509
+ var observedColor = index % 2 === 0 ? timeSliderLite.timelineBackgroundObserved.fill : timeSliderLite.timelineBackgroundObservedAlternative.fill;
1510
+ var enabledForecastColor = index % 2 === 0 ? timeSliderLite.timelineBackgroundAlternative.fill : timeSliderLite.timelineBackground.fill;
1511
+ var disabledForecastColor = index % 2 === 0 ? timeSliderLite.timelineBackgroundDisabled.fill : timeSliderLite.timelineBackgroundDisabledAlternative.fill;
1512
+ var forecastColor = disableForecast ? disabledForecastColor : enabledForecastColor;
1513
+ var defaultProps = {
1514
+ x: Math.floor((index - OBSERVED_PADDING_DAYS) * tickSpacing - tickOffset),
1515
+ y: 0,
1516
+ height: height
1517
+ };
1518
+ var isObserved = index + 1 < currentDayIndex;
1519
+ var baseRectangle = /*#__PURE__*/createElement("rect", Object.assign({}, defaultProps, {
1520
+ fill: isObserved ? observedColor : forecastColor,
1521
+ width: Math.ceil(tickSpacing),
1522
+ key: label + "-color",
1523
+ "data-testid": "TimeSliderLite-BackgroundRectangle-" + (isObserved ? 'Observed' : 'Forecast')
1524
+ }));
1525
+ var localDayOffset = secondsSinceLocalMidnight(currentTime) * SECOND_TO_DAY + utcOffset;
1526
+ var isCurrentDay = index === Math.floor(currentDayIndex);
1527
+ if (isCurrentDay) {
1528
+ var partialRectangle = /*#__PURE__*/createElement("rect", Object.assign({}, defaultProps, {
1529
+ width: tickSpacing * localDayOffset,
1530
+ fill: observedColor,
1531
+ key: label + "-partial-color"
1532
+ }));
1533
+ return [baseRectangle, partialRectangle];
1534
+ }
1535
+ return baseRectangle;
1536
+ }).flat();
1537
+ var dailyLabels = !showMonthLabel ? dayLabels.map(function (label, index) {
1538
+ return jsx("text", {
1539
+ x: (index - OBSERVED_PADDING_DAYS) * tickSpacing + 8 - tickOffset,
1540
+ y: 14,
1541
+ fill: timeSliderLite.timeline.fill,
1542
+ textAnchor: "left",
1543
+ fontSize: "12px",
1544
+ style: {
1545
+ userSelect: 'none'
1546
+ },
1547
+ children: dayLabels[index]
1548
+ }, label + "-text");
1549
+ }) : null;
1550
+ var hourLabelsPerDay = 24;
1551
+ var hourLabels = showHourLabel ? dayLabels.map(function (label, index) {
1552
+ return Array.from({
1553
+ length: hourLabelsPerDay
1554
+ }, function (_, value) {
1555
+ var defaultProps = {
1556
+ x: (index - OBSERVED_PADDING_DAYS) * tickSpacing + value * (tickSpacing / hourLabelsPerDay) - tickOffset - HOUR_LABEL_OFFSET,
1557
+ y: height - 10,
1558
+ visibility: showHourLabelEveryThirdHour && value % 3 !== 0 ? 'hidden' : 'visible',
1559
+ fill: timeSliderLite.timeline.fill,
1560
+ fontSize: '12px'
1561
+ };
1562
+ return jsxs("g", {
1563
+ children: [jsx("text", Object.assign({}, defaultProps, {
1564
+ textAnchor: "end",
1565
+ style: {
1566
+ userSelect: 'none'
1567
+ },
1568
+ children: value
1569
+ })), jsx("text", Object.assign({}, defaultProps, {
1570
+ textAnchor: "start",
1571
+ style: {
1572
+ userSelect: 'none'
1573
+ },
1574
+ children: ":00"
1575
+ })), ","]
1576
+ }, label + "-" + value + "-hourLabel");
1577
+ });
1578
+ }).flat() : null;
1579
+ var tickMarks = dayLabels.map(function (label, index) {
1580
+ var defaultProps = {
1581
+ y1: height,
1582
+ y2: Math.floor(height - TICK_HEIGHT),
1583
+ stroke: timeSliderLite.timeline.stroke
1584
+ };
1585
+ var ticksPerDay = timeStep ? maxSubTicksPerDay(tickSpacing, index > currentDayIndex ? timeStep[1] : timeStep[0]) : subTicksPerDay(tickSpacing);
1586
+ var isCurrentDay = index === Math.floor(currentDayIndex);
1587
+ if (isCurrentDay && timeStep) {
1588
+ var observedTicksPerDay = maxSubTicksPerDay(tickSpacing, timeStep[0]);
1589
+ var forecastTicksPerDay = maxSubTicksPerDay(tickSpacing, timeStep[1]);
1590
+ var observedTickMarksFromStartOfDay = Array.from({
1591
+ length: Math.floor(observedTicksPerDay * (currentDayIndex - index)) + 1
1592
+ }, function (_, value) {
1593
+ return /*#__PURE__*/createElement("line", Object.assign({}, defaultProps, {
1594
+ x1: (index - OBSERVED_PADDING_DAYS) * tickSpacing + value * (tickSpacing / observedTicksPerDay) - tickOffset,
1595
+ x2: (index - OBSERVED_PADDING_DAYS) * tickSpacing + value * (tickSpacing / observedTicksPerDay) - tickOffset,
1596
+ key: label + "-" + value + "-observed-tick"
1597
+ }));
1598
+ });
1599
+ var forecastTickMarksFromEndOfDay = Array.from({
1600
+ length: Math.floor(forecastTicksPerDay * (1 - (currentDayIndex - index))) + 1
1601
+ }, function (_, value) {
1602
+ return /*#__PURE__*/createElement("line", Object.assign({}, defaultProps, {
1603
+ x1: (index + 1 - OBSERVED_PADDING_DAYS) * tickSpacing - value * (tickSpacing / forecastTicksPerDay) - tickOffset,
1604
+ x2: (index + 1 - OBSERVED_PADDING_DAYS) * tickSpacing - value * (tickSpacing / forecastTicksPerDay) - tickOffset,
1605
+ key: label + "-" + value + "-forecast-tick"
1606
+ }));
1607
+ });
1608
+ return [].concat(observedTickMarksFromStartOfDay, forecastTickMarksFromEndOfDay);
1609
+ }
1610
+ return Array.from({
1611
+ length: ticksPerDay + 1
1612
+ }, function (_, value) {
1613
+ return /*#__PURE__*/createElement("line", Object.assign({}, defaultProps, {
1614
+ x1: (index - OBSERVED_PADDING_DAYS) * tickSpacing + value * (tickSpacing / ticksPerDay) - tickOffset,
1615
+ x2: (index - OBSERVED_PADDING_DAYS) * tickSpacing + value * (tickSpacing / ticksPerDay) - tickOffset,
1616
+ key: label + "-" + value + "-tick"
1617
+ }));
1618
+ });
1619
+ }).flat();
1620
+ return jsxs("svg", {
1621
+ style: style,
1622
+ width: width + TIME_SLIDER_LITE_PADDING_RIGHT,
1623
+ height: height,
1624
+ children: [backgroundRectangles, tickMarks, monthLabels, dailyLabels, hourLabels]
1625
+ });
1626
+ };
1627
+
1628
+ var DRAG_AREA_WIDTH = 10;
1629
+ var NEEDLE_WIDTH = 5;
1630
+ var SHADOW_SPREAD = 2;
1631
+ var NeedleShadow = function NeedleShadow(_ref) {
1632
+ var x = _ref.x,
1633
+ stroke = _ref.stroke,
1634
+ height = _ref.height,
1635
+ width = _ref.width;
1636
+ return jsx("line", {
1637
+ x1: x,
1638
+ y1: height - (height - SHADOW_SPREAD / 2),
1639
+ x2: x,
1640
+ y2: height - SHADOW_SPREAD / 2,
1641
+ strokeWidth: width + SHADOW_SPREAD,
1642
+ stroke: stroke,
1643
+ strokeLinecap: "round",
1644
+ filter: "blur(0.5px)",
1645
+ "data-testid": "TimeSliderLite-NeedleShadow"
1646
+ });
1647
+ };
1648
+ var NeedleLine = function NeedleLine(_ref2) {
1649
+ var x = _ref2.x,
1650
+ stroke = _ref2.stroke,
1651
+ height = _ref2.height,
1652
+ width = _ref2.width;
1653
+ return jsx("line", {
1654
+ x1: x,
1655
+ y1: width / 2,
1656
+ x2: x,
1657
+ y2: height - width / 2,
1658
+ strokeWidth: width,
1659
+ strokeLinecap: "round",
1660
+ stroke: stroke,
1661
+ "data-testid": "TimeSliderLite-NeedleLine"
1662
+ });
1663
+ };
1664
+ var TimeSliderDraggableNeedle = function TimeSliderDraggableNeedle(_ref3) {
1665
+ var draggableLabel = _ref3.draggableLabel,
1666
+ width = _ref3.width,
1667
+ height = _ref3.height,
1668
+ _ref3$timeZone = _ref3.timeZone,
1669
+ timeZone = _ref3$timeZone === void 0 ? 'LT' : _ref3$timeZone,
1670
+ _ref3$currentTime = _ref3.currentTime,
1671
+ currentTime = _ref3$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref3$currentTime,
1672
+ currentTimeSelected = _ref3.currentTimeSelected,
1673
+ startTime = _ref3.startTime,
1674
+ endTime = _ref3.endTime,
1675
+ disableForecast = _ref3.disableForecast,
1676
+ _ref3$needleDragAreaW = _ref3.needleDragAreaWidth,
1677
+ needleDragAreaWidth = _ref3$needleDragAreaW === void 0 ? DRAG_AREA_WIDTH : _ref3$needleDragAreaW,
1678
+ needleLabelZIndex = _ref3.needleLabelZIndex,
1679
+ _ref3$needleLabelOffs = _ref3.needleLabelOffset,
1680
+ needleLabelOffset = _ref3$needleLabelOffs === void 0 ? [0, -5] : _ref3$needleLabelOffs,
1681
+ _ref3$needleWidth = _ref3.needleWidth,
1682
+ needleWidth = _ref3$needleWidth === void 0 ? NEEDLE_WIDTH : _ref3$needleWidth,
1683
+ timeStep = _ref3.timeStep,
1684
+ selectedTime = _ref3.selectedTime,
1685
+ setSelectedTime = _ref3.setSelectedTime,
1686
+ style = _ref3.style,
1687
+ onDoubleClick = _ref3.onDoubleClick;
1688
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1689
+ i18n = _useTimesliderLiteTra.i18n;
1690
+ var language = i18n.language;
1691
+ var draggableRef = useRef(null);
1692
+ var _useTheme = useTheme(),
1693
+ timeSliderLite = _useTheme.palette.geowebColors.timeSliderLite;
1694
+ var timeZoneOffset = timeZone === 'UTC' ? 0 : undefined;
1695
+ var observedTimeStepSeconds = timeStep[0];
1696
+ var forecastTimeStepSeconds = timeStep[1];
1697
+ var timeStepSeconds = selectedTime >= currentTime ? forecastTimeStepSeconds : observedTimeStepSeconds;
1698
+ var lastObservedTime = floorLocalSeconds(currentTime, observedTimeStepSeconds, timeZoneOffset);
1699
+ var firstForecastTime = floorLocalSeconds(currentTime, forecastTimeStepSeconds, timeZoneOffset) + forecastTimeStepSeconds;
1700
+ var selectedTimePx = getSelectedTimePx(startTime, endTime, selectedTime, width);
1701
+ var x = selectedTimePx > 0 ? selectedTimePx - needleDragAreaWidth / 2 : -needleDragAreaWidth / 2;
1702
+ var isBetweenObservedAndForecast = selectedTime >= lastObservedTime && selectedTime < firstForecastTime;
1703
+ var roundedSelectedTime = isBetweenObservedAndForecast ? lastObservedTime : floorLocalSeconds(selectedTime, timeStepSeconds, timeZoneOffset);
1704
+ var dateString = new Date(roundedSelectedTime * 1000).toLocaleDateString(language, {
1705
+ weekday: 'short',
1706
+ month: 'numeric',
1707
+ day: 'numeric',
1708
+ hour: 'numeric',
1709
+ minute: 'numeric',
1710
+ timeZone: timeZone === 'UTC' ? 'UTC' : undefined
1711
+ });
1712
+ var localLabel = language === 'fi' || language === 'sv-FI' ? reformatFinnishDateString(dateString) : dateString;
1713
+ var label = timeZone === 'UTC' ? shortUTCTime(localLabel) : localLabel;
1714
+ return jsx(Draggable, {
1715
+ handle: ".TimeSliderLite-DraggableNeedle",
1716
+ axis: "x",
1717
+ nodeRef: draggableRef,
1718
+ bounds: {
1719
+ left: -needleDragAreaWidth / 2,
1720
+ right: width - needleDragAreaWidth / 2
1721
+ },
1722
+ position: {
1723
+ x: x,
1724
+ y: 0
1725
+ },
1726
+ onDrag: function onDrag(_, position) {
1727
+ var positionOffsetToCompensateFlooring = 0.5;
1728
+ var needleCenterPosition = position.x + needleDragAreaWidth / 2 + positionOffsetToCompensateFlooring;
1729
+ var newSelectedTime = getSelectedTimeFromPx(startTime, endTime, needleCenterPosition, width);
1730
+ if (disableForecast && newSelectedTime >= lastObservedTime) {
1731
+ setSelectedTime(lastObservedTime);
1732
+ }
1733
+ setSelectedTime(newSelectedTime);
1734
+ },
1735
+ onStop: function onStop(_, position) {
1736
+ var positionOffsetToCompensateFlooring = 0.5;
1737
+ var needleCenterPosition = position.x + needleDragAreaWidth / 2 + positionOffsetToCompensateFlooring;
1738
+ var newSelectedTime = getSelectedTimeFromPx(startTime, endTime, needleCenterPosition, width);
1739
+ var isLastObservedTime = newSelectedTime >= lastObservedTime && newSelectedTime < firstForecastTime || newSelectedTime >= lastObservedTime && disableForecast;
1740
+ var roundedSelectedTime = isLastObservedTime ? lastObservedTime : floorLocalSeconds(newSelectedTime, timeStepSeconds, timeZoneOffset);
1741
+ setSelectedTime(roundedSelectedTime);
1742
+ },
1743
+ children: jsxs(Box, {
1744
+ className: "TimeSliderLite-DraggableNeedle",
1745
+ ref: draggableRef,
1746
+ "data-testid": "TimeSliderLite-DraggableNeedle",
1747
+ onDoubleClick: onDoubleClick,
1748
+ sx: {
1749
+ overflow: 'visible'
1750
+ },
1751
+ children: [jsxs("svg", {
1752
+ style: style,
1753
+ cursor: "ew-resize",
1754
+ width: needleDragAreaWidth,
1755
+ height: height,
1756
+ "data-testid": "TimeSliderLite-NeedleSvg",
1757
+ children: [jsx(NeedleShadow, {
1758
+ x: needleDragAreaWidth / 2,
1759
+ stroke: timeSliderLite.needleShadow.stroke,
1760
+ height: height,
1761
+ width: needleWidth
1762
+ }), jsx(NeedleLine, {
1763
+ x: needleDragAreaWidth / 2,
1764
+ stroke: currentTimeSelected ? timeSliderLite.needleDefault.stroke : timeSliderLite.needle.stroke,
1765
+ height: height,
1766
+ width: needleWidth
1767
+ })]
1768
+ }), jsxs(Box, {
1769
+ className: "TimeSliderLite-timeStamp",
1770
+ position: "absolute",
1771
+ bottom: "-1px",
1772
+ sx: {
1773
+ backgroundColor: timeSliderLite.needleLabel.backgroundColor,
1774
+ border: "1px solid " + timeSliderLite.needleLabel.borderColor,
1775
+ borderRadius: '4px',
1776
+ className: draggableLabel ? 'TimeSliderLite-DraggableNeedle' : '',
1777
+ color: timeSliderLite.needleLabel.color,
1778
+ cursor: draggableLabel ? 'ew-resize' : null,
1779
+ fontSize: '12px',
1780
+ padding: '0px 4px 0px 4px',
1781
+ pointerEvents: draggableLabel ? null : 'none',
1782
+ transform: "translate(calc(-50% + " + needleWidth + "px + " + needleLabelOffset[0] + "px), " + needleLabelOffset[1] + "px)",
1783
+ zIndex: needleLabelZIndex != null ? needleLabelZIndex : null
1784
+ },
1785
+ children: [label, jsx(Box, {
1786
+ className: "TimeSliderLite-timeStamp-tail",
1787
+ position: "absolute",
1788
+ width: "10px",
1789
+ height: "10px",
1790
+ bottom: "-4px",
1791
+ sx: {
1792
+ backgroundColor: timeSliderLite.needleLabel.backgroundColor,
1793
+ transform: 'rotate(45deg)',
1794
+ left: "calc(50% - 5px - " + needleLabelOffset[0] + "px)",
1795
+ zIndex: -1
1796
+ }
1797
+ })]
1798
+ })]
1799
+ })
1800
+ });
1801
+ };
1802
+
1803
+ var HOVER_NEEDLE_WIDTH = 1;
1804
+ var DEFAULT_OPACITY = 0.5;
1805
+ var TimeSliderClickableTimeline = function TimeSliderClickableTimeline(_ref) {
1806
+ var _ref$currentTime = _ref.currentTime,
1807
+ currentTime = _ref$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref$currentTime,
1808
+ endTime = _ref.endTime,
1809
+ disableForecast = _ref.disableForecast,
1810
+ _ref$opacity = _ref.opacity,
1811
+ opacity = _ref$opacity === void 0 ? DEFAULT_OPACITY : _ref$opacity,
1812
+ setSelectedTime = _ref.setSelectedTime,
1813
+ startTime = _ref.startTime,
1814
+ timeStep = _ref.timeStep,
1815
+ width = _ref.width,
1816
+ timeZone = _ref.timeZone;
1817
+ var _React$useState = React.useState(false),
1818
+ isShown = _React$useState[0],
1819
+ setIsShown = _React$useState[1];
1820
+ var _React$useState2 = React.useState(0),
1821
+ mouseX = _React$useState2[0],
1822
+ setMouseX = _React$useState2[1];
1823
+ var _useTheme = useTheme(),
1824
+ timeSliderLite = _useTheme.palette.geowebColors.timeSliderLite;
1825
+ var needleSuggestion = getNearestSelectableTime(timeStep, startTime, endTime, mouseX, width, currentTime, disableForecast, timeZone === 'UTC' ? 0 : undefined);
1826
+ var x = getSelectedTimePx(startTime, endTime, needleSuggestion, width);
1827
+ if (isNaN(x)) {
1828
+ return null;
1829
+ }
1830
+ return jsx("svg", {
1831
+ "data-testid": "TimeSliderLite-clickableTimeline",
1832
+ style: {
1833
+ position: 'absolute',
1834
+ width: '100%',
1835
+ height: '100%',
1836
+ cursor: 'pointer'
1837
+ },
1838
+ onClick: function onClick() {
1839
+ return setSelectedTime(needleSuggestion);
1840
+ },
1841
+ onMouseEnter: function onMouseEnter() {
1842
+ return setIsShown(true);
1843
+ },
1844
+ onMouseLeave: function onMouseLeave() {
1845
+ return setIsShown(false);
1846
+ },
1847
+ onMouseMove: function onMouseMove(event) {
1848
+ isShown && setMouseX(event.nativeEvent.offsetX);
1849
+ },
1850
+ children: jsx("line", {
1851
+ opacity: isShown ? opacity : 0,
1852
+ x1: x,
1853
+ y1: "0",
1854
+ x2: x,
1855
+ y2: "100%",
1856
+ stroke: timeSliderLite.timeline.stroke,
1857
+ strokeWidth: HOVER_NEEDLE_WIDTH,
1858
+ style: {
1859
+ transition: 'opacity 0.2s ease-in-out'
1860
+ }
1861
+ })
1862
+ });
1863
+ };
1864
+
1865
+ var styles$1 = {
1866
+ centeredBox: {
1867
+ borderRadius: '4px',
1868
+ bottom: 'calc(50% - 0.5rem - 2px)',
1869
+ left: '50%',
1870
+ padding: '0px 3px 0px 3px',
1871
+ position: 'absolute',
1872
+ transform: 'translateX(-50%)'
1873
+ }
1874
+ };
1875
+ var TimeSliderZeroTimestamp = function TimeSliderZeroTimestamp(_ref) {
1876
+ var _ref$timeZone = _ref.timeZone,
1877
+ timeZone = _ref$timeZone === void 0 ? 'LT' : _ref$timeZone,
1878
+ _ref$currentTime = _ref.currentTime,
1879
+ currentTime = _ref$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref$currentTime,
1880
+ timeStep = _ref.timeStep,
1881
+ timestampZIndex = _ref.timestampZIndex;
1882
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
1883
+ i18n = _useTimesliderLiteTra.i18n;
1884
+ var language = i18n.language;
1885
+ var _useTheme = useTheme(),
1886
+ timeSliderLite = _useTheme.palette.geowebColors.timeSliderLite;
1887
+ var observedTimeStepSeconds = timeStep[0];
1888
+ var lastObservedTime = floorLocalSeconds(currentTime, observedTimeStepSeconds);
1889
+ var dateString = new Date(lastObservedTime * 1000).toLocaleDateString(language, {
1890
+ weekday: 'short',
1891
+ month: 'numeric',
1892
+ day: 'numeric',
1893
+ hour: 'numeric',
1894
+ minute: 'numeric',
1895
+ timeZone: timeZone === 'UTC' ? 'UTC' : undefined
1896
+ });
1897
+ var localLabel = language === 'fi' || language === 'sv-FI' ? reformatFinnishDateString(dateString) : dateString;
1898
+ var label = timeZone === 'UTC' ? shortUTCTime(localLabel) : localLabel;
1899
+ return jsx(Box, {
1900
+ className: "TimeSliderLite-zeroTimeStamp",
1901
+ sx: Object.assign({}, styles$1.centeredBox, timeSliderLite.needleLabel, {
1902
+ fontSize: '13px',
1903
+ opacity: 0.6,
1904
+ pointerEvents: null,
1905
+ zIndex: timestampZIndex != null ? timestampZIndex : null
1906
+ }),
1907
+ children: label
1908
+ });
1909
+ };
1910
+
1911
+ var TimeSliderLiteBackground = function TimeSliderLiteBackground(_ref) {
1912
+ var height = _ref.height,
1913
+ draggableTimeStamp = _ref.draggableTimeStamp,
1914
+ _ref$timeZone = _ref.timeZone,
1915
+ timeZone = _ref$timeZone === void 0 ? 'LT' : _ref$timeZone,
1916
+ startTime = _ref.startTime,
1917
+ endTime = _ref.endTime,
1918
+ disableForecast = _ref.disableForecast,
1919
+ _ref$currentTime = _ref.currentTime,
1920
+ currentTime = _ref$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref$currentTime,
1921
+ currentTimeSelected = _ref.currentTimeSelected,
1922
+ mouseHoverNeedleOpacity = _ref.mouseHoverNeedleOpacity,
1923
+ needleWidth = _ref.needleWidth,
1924
+ needleDragAreaWidth = _ref.needleDragAreaWidth,
1925
+ needleLabelZIndex = _ref.needleLabelZIndex,
1926
+ needleLabelOffset = _ref.needleLabelOffset,
1927
+ timeStep = _ref.timeStep,
1928
+ selectedTime = _ref.selectedTime,
1929
+ setSelectedTime = _ref.setSelectedTime,
1930
+ resetSelectedTime = _ref.resetSelectedTime,
1931
+ zerorange = _ref.zerorange;
1932
+ var _useTheme = useTheme(),
1933
+ timeSliderLite = _useTheme.palette.geowebColors.timeSliderLite;
1934
+ var sliderAreaRef = useRef(null);
1935
+ var _React$useState = React.useState(0),
1936
+ areaWidth = _React$useState[0],
1937
+ setAreaWidth = _React$useState[1];
1938
+ var drawNeedle = selectedTime && areaWidth && startTime <= endTime;
1939
+ useLayoutEffect(function () {
1940
+ var sliderArea = sliderAreaRef.current;
1941
+ setAreaWidth(sliderArea.clientWidth - TIME_SLIDER_LITE_PADDING_RIGHT);
1942
+ var observer = new ResizeObserver(function () {
1943
+ setAreaWidth(sliderArea.clientWidth - TIME_SLIDER_LITE_PADDING_RIGHT);
1944
+ });
1945
+ observer.observe(sliderArea);
1946
+ return function () {
1947
+ observer.disconnect();
1948
+ };
1949
+ }, [sliderAreaRef]);
1950
+ return jsxs(Box, {
1951
+ ref: sliderAreaRef,
1952
+ sx: {
1953
+ position: 'relative',
1954
+ height: height + "px",
1955
+ overflow: 'visible',
1956
+ width: '100%',
1957
+ backgroundColor: timeSliderLite.timelineBackgroundObserved.fill
1958
+ },
1959
+ "data-testid": "TimeSliderLite-Background",
1960
+ children: [jsx(TimeSliderLiteBackgroundSvg, {
1961
+ style: {
1962
+ position: 'absolute',
1963
+ top: 0
1964
+ },
1965
+ timeStep: timeStep,
1966
+ width: areaWidth,
1967
+ height: height,
1968
+ startTime: startTime,
1969
+ endTime: endTime,
1970
+ disableForecast: disableForecast,
1971
+ currentTime: currentTime,
1972
+ timeZone: timeZone
1973
+ }), jsx(TimeSliderClickableTimeline, {
1974
+ currentTime: currentTime,
1975
+ opacity: mouseHoverNeedleOpacity,
1976
+ width: areaWidth,
1977
+ startTime: startTime,
1978
+ endTime: endTime,
1979
+ disableForecast: disableForecast,
1980
+ timeStep: timeStep,
1981
+ setSelectedTime: setSelectedTime,
1982
+ timeZone: timeZone
1983
+ }), drawNeedle && (!zerorange ? jsx(TimeSliderDraggableNeedle, {
1984
+ currentTimeSelected: currentTimeSelected,
1985
+ onDoubleClick: resetSelectedTime,
1986
+ needleWidth: needleWidth,
1987
+ draggableLabel: draggableTimeStamp,
1988
+ style: {
1989
+ position: 'absolute',
1990
+ top: 0
1991
+ },
1992
+ timeZone: timeZone,
1993
+ disableForecast: disableForecast,
1994
+ width: areaWidth,
1995
+ needleDragAreaWidth: needleDragAreaWidth,
1996
+ needleLabelZIndex: needleLabelZIndex,
1997
+ needleLabelOffset: needleLabelOffset,
1998
+ height: height,
1999
+ startTime: startTime,
2000
+ endTime: endTime,
2001
+ timeStep: timeStep,
2002
+ currentTime: currentTime,
2003
+ selectedTime: selectedTime,
2004
+ setSelectedTime: setSelectedTime
2005
+ }) : jsx(TimeSliderZeroTimestamp, {
2006
+ timeZone: timeZone,
2007
+ timeStep: timeStep,
2008
+ currentTime: currentTime,
2009
+ timestampZIndex: needleLabelZIndex
2010
+ }))]
2011
+ });
2012
+ };
2013
+
2014
+ var StepButton = function StepButton(_ref) {
2015
+ var _settings$icon$forwar, _settings$icon, _settings$icon$backwa, _settings$icon2;
2016
+ var forward = _ref.forward,
2017
+ isDisabled = _ref.isDisabled,
2018
+ _ref$onClick = _ref.onClick,
2019
+ onClick = _ref$onClick === void 0 ? function () {} : _ref$onClick,
2020
+ settings = _ref.settings,
2021
+ tooltipDelay = _ref.tooltipDelay;
2022
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
2023
+ t = _useTimesliderLiteTra.t;
2024
+ var forwardTitle = t('controlButtons.forward');
2025
+ var backwardTitle = t('controlButtons.backward');
2026
+ var forwardIcon = (_settings$icon$forwar = settings == null || (_settings$icon = settings.icon) == null ? void 0 : _settings$icon.forward) != null ? _settings$icon$forwar : jsx(StepForward, {
2027
+ "data-testid": "step-forward-svg-path"
2028
+ });
2029
+ var backwardIcon = (_settings$icon$backwa = settings == null || (_settings$icon2 = settings.icon) == null ? void 0 : _settings$icon2.backward) != null ? _settings$icon$backwa : jsx(StepBackward, {
2030
+ "data-testid": "step-backward-svg-path"
2031
+ });
2032
+ return jsx(Tooltip, {
2033
+ placement: "top",
2034
+ title: forward ? forwardTitle : backwardTitle,
2035
+ enterDelay: tooltipDelay,
2036
+ enterNextDelay: tooltipDelay,
2037
+ children: jsx("span", {
2038
+ children: jsx(IconButton, Object.assign({}, timeSliderLiteButtonDefaultProps, {
2039
+ disabled: isDisabled,
2040
+ "aria-label": forward ? forwardTitle : backwardTitle,
2041
+ onClick: onClick,
2042
+ "data-testid": "TimeSliderLite-StepButton" + (forward ? 'Forward' : 'Backward'),
2043
+ children: forward ? forwardIcon : backwardIcon
2044
+ }))
2045
+ })
2046
+ });
2047
+ };
2048
+
2049
+ var PlayButton = function PlayButton(_ref) {
2050
+ var _settings$icon$pause, _settings$icon, _settings$icon$play, _settings$icon2;
2051
+ var isAnimating = _ref.isAnimating,
2052
+ isDisabled = _ref.isDisabled,
2053
+ onTogglePlayButton = _ref.onTogglePlayButton,
2054
+ settings = _ref.settings,
2055
+ tooltipDelay = _ref.tooltipDelay;
2056
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
2057
+ t = _useTimesliderLiteTra.t;
2058
+ var pauseIcon = (_settings$icon$pause = settings == null || (_settings$icon = settings.icon) == null ? void 0 : _settings$icon.pause) != null ? _settings$icon$pause : jsx(Pause, {});
2059
+ var playIcon = (_settings$icon$play = settings == null || (_settings$icon2 = settings.icon) == null ? void 0 : _settings$icon2.play) != null ? _settings$icon$play : jsx(Play, {});
2060
+ return jsx(Tooltip, {
2061
+ title: isAnimating ? t('controlButtons.pause') : t('controlButtons.play'),
2062
+ placement: "top",
2063
+ enterDelay: tooltipDelay,
2064
+ enterNextDelay: tooltipDelay,
2065
+ children: jsx("span", {
2066
+ children: jsx(IconButton, Object.assign({}, timeSliderLiteButtonDefaultProps, {
2067
+ sx: Object.assign({}, isAnimating && {
2068
+ backgroundColor: 'geowebColors.timeSliderLite.selected.backgroundColor'
2069
+ }, timeSliderLiteButtonDefaultProps.sx),
2070
+ onClick: function onClick() {
2071
+ onTogglePlayButton();
2072
+ },
2073
+ disabled: isDisabled,
2074
+ "data-testid": "TimeSliderLite-PlayButton",
2075
+ children: isAnimating ? pauseIcon : playIcon
2076
+ }))
2077
+ })
2078
+ });
2079
+ };
2080
+
2081
+ var MenuButton = function MenuButton(_ref) {
2082
+ var _settings$icon;
2083
+ var menuOpen = _ref.menuOpen,
2084
+ onClick = _ref.onClick,
2085
+ settings = _ref.settings;
2086
+ var _useTimesliderLiteTra = useTimesliderLiteTranslation(),
2087
+ t = _useTimesliderLiteTra.t;
2088
+ var icon = (_settings$icon = settings == null ? void 0 : settings.icon) != null ? _settings$icon : jsx(Options, {});
2089
+ var Button = jsx(IconButton, Object.assign({}, timeSliderLiteButtonDefaultProps, {
2090
+ sx: Object.assign({}, menuOpen && {
2091
+ backgroundColor: 'geowebColors.timeSliderLite.selected.backgroundColor'
2092
+ }, timeSliderLiteButtonDefaultProps.sx),
2093
+ "aria-selected": menuOpen,
2094
+ onClick: onClick,
2095
+ "data-testid": "TimeSliderLite-MenuButton",
2096
+ children: icon
2097
+ }));
2098
+ if (menuOpen) {
2099
+ return Button;
2100
+ }
2101
+ return jsx(Tooltip, {
2102
+ placement: "top-start",
2103
+ title: t('menu.title'),
2104
+ children: Button
2105
+ });
2106
+ };
2107
+
2108
+ var TIME_SLIDER_LITE_DEFAULT_HEIGHT = 40;
2109
+ var TIME_SLIDER_LITE_DEFAULT_TIME_STEP = 5;
2110
+ var TIME_SLIDER_LITE_TOOLTIP_DELAY = 3000;
2111
+ var styles = {
2112
+ container: {
2113
+ display: 'grid',
2114
+ alignItems: 'center',
2115
+ justifyContent: 'center',
2116
+ borderRadius: '4px',
2117
+ width: '100%'
2118
+ }
2119
+ };
2120
+ var TimeSliderLite = function TimeSliderLite(_ref) {
2121
+ var controlButtons = _ref.controlButtons,
2122
+ _ref$currentTime = _ref.currentTime,
2123
+ currentTime = _ref$currentTime === void 0 ? Date.now() * MILLISECOND_TO_SECOND : _ref$currentTime,
2124
+ endTime = _ref.endTime,
2125
+ _ref$height = _ref.height,
2126
+ height = _ref$height === void 0 ? TIME_SLIDER_LITE_DEFAULT_HEIGHT : _ref$height,
2127
+ hideButton = _ref.hideButton,
2128
+ hideMenuButton = _ref.hideMenuButton,
2129
+ hideStepButtons = _ref.hideStepButtons,
2130
+ hidePlayButton = _ref.hidePlayButton,
2131
+ isAnimating = _ref.isAnimating,
2132
+ isVisible = _ref.isVisible,
2133
+ mapId = _ref.mapId,
2134
+ menuOpen = _ref.menuOpen,
2135
+ mouseHoverNeedleOpacity = _ref.mouseHoverNeedleOpacity,
2136
+ overrideAnimation = _ref.overrideAnimation,
2137
+ onToggleAnimation = _ref.onToggleAnimation,
2138
+ onToggleMenu = _ref.onToggleMenu,
2139
+ onToggleTimeSlider = _ref.onToggleTimeSlider,
2140
+ needleWidth = _ref.needleWidth,
2141
+ needleDragAreaWidth = _ref.needleDragAreaWidth,
2142
+ needleLabelZIndex = _ref.needleLabelZIndex,
2143
+ needleLabelOffset = _ref.needleLabelOffset,
2144
+ draggableTimeStamp = _ref.draggableTimeStamp,
2145
+ selectedTime = _ref.selectedTime,
2146
+ setSelectedTime = _ref.setSelectedTime,
2147
+ settings = _ref.settings,
2148
+ startTime = _ref.startTime,
2149
+ sx = _ref.sx,
2150
+ needleDisabled = _ref.needleDisabled,
2151
+ _ref$timeStep = _ref.timeStep,
2152
+ timeStep = _ref$timeStep === void 0 ? [TIME_SLIDER_LITE_DEFAULT_TIME_STEP, TIME_SLIDER_LITE_DEFAULT_TIME_STEP] : _ref$timeStep,
2153
+ _ref$timeZone = _ref.timeZone,
2154
+ timeZone = _ref$timeZone === void 0 ? 'LT' : _ref$timeZone,
2155
+ _ref$animationSpeed = _ref.animationSpeed,
2156
+ animationSpeed = _ref$animationSpeed === void 0 ? 1 : _ref$animationSpeed;
2157
+ var observedTimeStep = timeStep[0],
2158
+ forecastTimeStep = timeStep[1];
2159
+ var timeZoneOffset = timeZone === 'UTC' ? 0 : undefined;
2160
+ var _useState = useState(currentTime),
2161
+ rawSelectedTime = _useState[0],
2162
+ setRawSelectedTime = _useState[1];
2163
+ var forecastTimeStepSeconds = forecastTimeStep * MINUTE_TO_SECOND;
2164
+ var observedTimeStepSeconds = observedTimeStep * MINUTE_TO_SECOND;
2165
+ var lastObservedTime = floorLocalSeconds(currentTime, observedTimeStepSeconds, timeZoneOffset);
2166
+ var firstForecastTime = floorLocalSeconds(currentTime, forecastTimeStepSeconds, timeZoneOffset) + forecastTimeStepSeconds;
2167
+ var timeStepSeconds = rawSelectedTime >= currentTime ? forecastTimeStepSeconds : observedTimeStepSeconds;
2168
+ var roundedStartTime = floorLocalSeconds(startTime + Math.max(forecastTimeStepSeconds, observedTimeStepSeconds, HOUR_TO_SECOND), HOUR_TO_SECOND, timeZoneOffset);
2169
+ var isObservedTimeRange = endTime - currentTime < HOUR_TO_SECOND;
2170
+ var roundedEndTime = floorLocalSeconds(endTime + HOUR_TO_SECOND, HOUR_TO_SECOND, timeZoneOffset);
2171
+ var autoUpdateSelectedTime = useAutoUpdateSelectedTime(lastObservedTime, selectedTime, setRawSelectedTime);
2172
+ var runningExternalAnimation = overrideAnimation && isAnimating;
2173
+ var runningInternalAnimation = !overrideAnimation && isAnimating;
2174
+ useEffect(function () {
2175
+ if (needleDisabled && selectedTime !== lastObservedTime) {
2176
+ setRawSelectedTime(lastObservedTime);
2177
+ setSelectedTime(lastObservedTime);
2178
+ }
2179
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2180
+ }, [selectedTime, needleDisabled, lastObservedTime]);
2181
+ useEffect(function () {
2182
+ if (!runningExternalAnimation) {
2183
+ var roundedSelectedTime = floorLocalSeconds(rawSelectedTime, timeStepSeconds, timeZoneOffset);
2184
+ setSelectedTime(roundedSelectedTime);
2185
+ }
2186
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2187
+ }, [rawSelectedTime, timeStepSeconds, runningExternalAnimation]);
2188
+ useEffect(function () {
2189
+ if (runningInternalAnimation) {
2190
+ var interval = setInterval(function () {
2191
+ handleTimeStep(timeStepSeconds, true);
2192
+ }, SECOND_TO_MILLISECOND / animationSpeed);
2193
+ return function () {
2194
+ return clearInterval(interval);
2195
+ };
2196
+ }
2197
+ if (runningExternalAnimation) {
2198
+ setRawSelectedTime(selectedTime);
2199
+ }
2200
+ return function () {};
2201
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2202
+ }, [runningInternalAnimation, runningExternalAnimation, selectedTime]);
2203
+ var handleTimeStep = function handleTimeStep(stepSeconds, asAnimation) {
2204
+ var newSteppedTime = stepSeconds >= 0 ? floorLocalSeconds(rawSelectedTime, timeStepSeconds, timeZoneOffset) + stepSeconds : floorLocalSeconds(rawSelectedTime - 1, timeStepSeconds, timeZoneOffset);
2205
+ if (asAnimation && newSteppedTime > roundedEndTime + 1) {
2206
+ setRawSelectedTime(roundedStartTime);
2207
+ return;
2208
+ }
2209
+ // Handle stepping over current time
2210
+ if (newSteppedTime >= currentTime && currentTime > rawSelectedTime && !isObservedTimeRange) {
2211
+ setRawSelectedTime(firstForecastTime);
2212
+ } else if (newSteppedTime < currentTime && currentTime <= rawSelectedTime && newSteppedTime >= roundedStartTime) {
2213
+ setRawSelectedTime(lastObservedTime);
2214
+ } else {
2215
+ // Handle normal stepping
2216
+ setRawSelectedTime(boundedValue(newSteppedTime, [roundedStartTime, isObservedTimeRange ? lastObservedTime : roundedEndTime]));
2217
+ }
2218
+ if (!asAnimation && isAnimating && onToggleAnimation) {
2219
+ onToggleAnimation();
2220
+ }
2221
+ };
2222
+ var handleTimeSelect = function handleTimeSelect(value) {
2223
+ setRawSelectedTime(boundedValue(value, [roundedStartTime, roundedEndTime]));
2224
+ if (isAnimating && onToggleAnimation) {
2225
+ onToggleAnimation();
2226
+ }
2227
+ };
2228
+ // Handle time range selection
2229
+ useEffect(function () {
2230
+ var userDraggingNeedle = rawSelectedTime !== selectedTime || rawSelectedTime === roundedEndTime;
2231
+ if (!userDraggingNeedle) {
2232
+ var newRawSelectedTime = isObservedTimeRange ? lastObservedTime : roundedEndTime;
2233
+ var isValid = newRawSelectedTime >= roundedStartTime;
2234
+ setRawSelectedTime(boundedValue(selectedTime, [roundedStartTime, isValid ? newRawSelectedTime : roundedStartTime]));
2235
+ }
2236
+ if (needleDisabled) {
2237
+ setRawSelectedTime(selectedTime);
2238
+ }
2239
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2240
+ }, [startTime, endTime, needleDisabled, timeStep]);
2241
+ var tooltipDelay = menuOpen ? TIME_SLIDER_LITE_TOOLTIP_DELAY : undefined;
2242
+ return jsxs(Grid, {
2243
+ container: true,
2244
+ sx: Object.assign({}, styles.container, sx, {
2245
+ gridTemplateColumns: isVisible ? 'auto 1fr auto' : "1fr auto",
2246
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2247
+ boxShadow: isVisible ? sx == null ? void 0 : sx.boxShadow : undefined
2248
+ }),
2249
+ "data-testid": "timeSliderLite-" + mapId,
2250
+ children: [isVisible ? jsxs(Fragment, {
2251
+ children: [jsx(Grid, {
2252
+ sx: {
2253
+ height: height + "px"
2254
+ },
2255
+ children: controlButtons || jsxs(ControlButtonGroup, {
2256
+ left: true,
2257
+ children: [!hideMenuButton && jsxs(Fragment, {
2258
+ children: [jsx(MenuButton, {
2259
+ settings: settings == null ? void 0 : settings.menuButton,
2260
+ menuOpen: menuOpen,
2261
+ onClick: onToggleMenu
2262
+ }), jsx(Divider, {
2263
+ orientation: "vertical",
2264
+ sx: {
2265
+ height: height + "px",
2266
+ margin: '2px'
2267
+ }
2268
+ })]
2269
+ }), !hidePlayButton && jsx(PlayButton, {
2270
+ settings: settings == null ? void 0 : settings.playButton,
2271
+ isAnimating: isAnimating,
2272
+ onTogglePlayButton: onToggleAnimation,
2273
+ tooltipDelay: tooltipDelay,
2274
+ isDisabled: needleDisabled
2275
+ }), !hideStepButtons && jsxs(Fragment, {
2276
+ children: [jsx(StepButton, {
2277
+ settings: settings == null ? void 0 : settings.stepButton,
2278
+ onClick: function onClick() {
2279
+ return handleTimeStep(-timeStepSeconds);
2280
+ },
2281
+ tooltipDelay: tooltipDelay,
2282
+ isDisabled: needleDisabled
2283
+ }), jsx(StepButton, {
2284
+ forward: true,
2285
+ settings: settings == null ? void 0 : settings.stepButton,
2286
+ onClick: function onClick() {
2287
+ return handleTimeStep(timeStepSeconds);
2288
+ },
2289
+ tooltipDelay: tooltipDelay,
2290
+ isDisabled: needleDisabled
2291
+ })]
2292
+ })]
2293
+ })
2294
+ }), jsx(Grid, {
2295
+ children: jsx(TimeSliderLiteBackground, {
2296
+ draggableTimeStamp: draggableTimeStamp,
2297
+ currentTime: currentTime,
2298
+ currentTimeSelected: autoUpdateSelectedTime && !isAnimating,
2299
+ startTime: roundedStartTime,
2300
+ timeZone: timeZone,
2301
+ endTime: roundedEndTime,
2302
+ disableForecast: isObservedTimeRange,
2303
+ mouseHoverNeedleOpacity: mouseHoverNeedleOpacity,
2304
+ needleWidth: needleWidth,
2305
+ needleDragAreaWidth: needleDragAreaWidth,
2306
+ needleLabelZIndex: needleLabelZIndex,
2307
+ needleLabelOffset: needleLabelOffset,
2308
+ timeStep: [observedTimeStepSeconds, forecastTimeStepSeconds],
2309
+ selectedTime: runningExternalAnimation ? selectedTime : rawSelectedTime,
2310
+ setSelectedTime: handleTimeSelect,
2311
+ resetSelectedTime: function resetSelectedTime() {
2312
+ return setRawSelectedTime(lastObservedTime);
2313
+ },
2314
+ height: height,
2315
+ zerorange: needleDisabled
2316
+ })
2317
+ })]
2318
+ }) : jsx(Grid, {}), jsx(Grid, {
2319
+ sx: {
2320
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2321
+ boxShadow: isVisible ? 'none' : sx == null ? void 0 : sx.boxShadow,
2322
+ borderRadius: isVisible ? 'none' : '4px',
2323
+ height: height + "px"
2324
+ },
2325
+ children: hideButton || jsx(ControlButtonGroup, {
2326
+ className: "timeSliderLite-hideButtonGroup-" + (isVisible ? 'hide' : 'show'),
2327
+ right: isVisible,
2328
+ children: jsx(HideButton, {
2329
+ settings: settings == null ? void 0 : settings.hideButton,
2330
+ onClick: onToggleTimeSlider,
2331
+ isVisible: isVisible
2332
+ })
2333
+ })
2334
+ })]
2335
+ });
2336
+ };
2337
+
2338
+ /* *
2339
+ * Licensed under the Apache License, Version 2.0 (the "License");
2340
+ * you may not use this file except in compliance with the License.
2341
+ * You may obtain a copy of the License at
2342
+ *
2343
+ * http://www.apache.org/licenses/LICENSE-2.0
2344
+ *
2345
+ * Unless required by applicable law or agreed to in writing, software
2346
+ * distributed under the License is distributed on an "AS IS" BASIS,
2347
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2348
+ * See the License for the specific language governing permissions and
2349
+ * limitations under the License.
2350
+ *
2351
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2352
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
2353
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
2354
+ * */
2355
+ var useOnToggleAnimation = function useOnToggleAnimation(dispatch, mapId, selectedTime, timeStep, defaultTimeStep, startTime, endTime, isAnimating, timeSliderProps) {
2356
+ var startMapAnimation = function startMapAnimation() {
2357
+ var _timeStep$, _timeStep$2, _timeSliderProps$curr, _timeSliderProps$curr2;
2358
+ var observedTimeStep = (_timeStep$ = timeStep == null ? void 0 : timeStep[0]) != null ? _timeStep$ : defaultTimeStep[0];
2359
+ var forecastTimeStep = (_timeStep$2 = timeStep == null ? void 0 : timeStep[1]) != null ? _timeStep$2 : defaultTimeStep[1];
2360
+ var floorCorrectedTimeStart = floorLocalSeconds(startTime + HOUR_TO_SECOND, HOUR_TO_SECOND);
2361
+ var floorCorrectedEndTime = floorLocalSeconds(endTime + HOUR_TO_SECOND, HOUR_TO_SECOND);
2362
+ var currentTime = (_timeSliderProps$curr = timeSliderProps.currentTime) != null ? _timeSliderProps$curr : Date.now() * MILLISECOND_TO_SECOND;
2363
+ var observedOnly = floorCorrectedEndTime - currentTime < HOUR_TO_SECOND;
2364
+ var timeList = generateCustomTimeList((_timeSliderProps$curr2 = timeSliderProps.currentTime) != null ? _timeSliderProps$curr2 : Date.now() * MILLISECOND_TO_SECOND, floorCorrectedTimeStart, observedOnly ? currentTime : floorCorrectedEndTime, [observedTimeStep, forecastTimeStep], timeSliderProps.timeZone === 'UTC' ? 0 : undefined);
2365
+ dispatch(mapActions.mapStartAnimation({
2366
+ mapId: mapId,
2367
+ initialTime: new Date(selectedTime * SECOND_TO_MILLISECOND).toISOString(),
2368
+ timeList: timeList,
2369
+ origin: mapEnums.MapActionOrigin.map
2370
+ }));
2371
+ };
2372
+ var onToggleAnimation = function onToggleAnimation(forceStart) {
2373
+ if (isAnimating && !forceStart) {
2374
+ dispatch(mapActions.mapStopAnimation({
2375
+ mapId: mapId,
2376
+ origin: mapEnums.MapActionOrigin.map
2377
+ }));
2378
+ } else {
2379
+ startMapAnimation();
2380
+ }
2381
+ };
2382
+ React.useEffect(function () {
2383
+ var hasTimeRange = startTime && endTime && selectedTime;
2384
+ var isInvalidAnimation = selectedTime < startTime || selectedTime > endTime;
2385
+ if (hasTimeRange && isInvalidAnimation && isAnimating) {
2386
+ startMapAnimation();
2387
+ }
2388
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2389
+ }, [selectedTime, startTime, endTime]);
2390
+ return onToggleAnimation;
2391
+ };
2392
+
2393
+ var _excluded = ["overrideUseTimeRange", "overrideUseTimeStep", "overrideUseTimeZone", "overrideUseUpdateInterval", "overrideHandleAutoUpdate", "preTimeDimensionSelect", "sourceId", "mapId", "isAlwaysVisible", "TimeSliderLiteOptionsMenuProps"];
2394
+ var TimeSliderLiteConnect = function TimeSliderLiteConnect(_ref) {
2395
+ var _TimeSliderLiteOption, _timeSliderProps$sett, _timeSliderProps$sett2, _timeSliderProps$sett3;
2396
+ var overrideUseTimeRange = _ref.overrideUseTimeRange,
2397
+ overrideUseTimeStep = _ref.overrideUseTimeStep,
2398
+ overrideUseTimeZone = _ref.overrideUseTimeZone,
2399
+ overrideUseUpdateInterval = _ref.overrideUseUpdateInterval,
2400
+ overrideHandleAutoUpdate = _ref.overrideHandleAutoUpdate,
2401
+ _ref$preTimeDimension = _ref.preTimeDimensionSelect,
2402
+ preTimeDimensionSelect = _ref$preTimeDimension === void 0 ? function (_, selectedTime) {
2403
+ return new Date(selectedTime * SECOND_TO_MILLISECOND).toISOString();
2404
+ } : _ref$preTimeDimension,
2405
+ sourceId = _ref.sourceId,
2406
+ mapId = _ref.mapId,
2407
+ _ref$isAlwaysVisible = _ref.isAlwaysVisible,
2408
+ isAlwaysVisible = _ref$isAlwaysVisible === void 0 ? false : _ref$isAlwaysVisible,
2409
+ TimeSliderLiteOptionsMenuProps = _ref.TimeSliderLiteOptionsMenuProps,
2410
+ timeSliderProps = _objectWithoutPropertiesLoose(_ref, _excluded);
2411
+ var _React$useState = React.useState(false),
2412
+ menuOpen = _React$useState[0],
2413
+ setMenuOpen = _React$useState[1];
2414
+ var useTimeRange = React.useState(null);
2415
+ var _ref2 = overrideUseTimeRange || useTimeRange,
2416
+ timeRange = _ref2[0],
2417
+ setTimeRange = _ref2[1];
2418
+ var useTimeStep = React.useState(null);
2419
+ var _ref3 = overrideUseTimeStep || useTimeStep,
2420
+ timeStep = _ref3[0],
2421
+ setTimeStep = _ref3[1];
2422
+ var useTimeZone = React.useState('LT');
2423
+ var _ref4 = overrideUseTimeZone || useTimeZone,
2424
+ timeZone = _ref4[0],
2425
+ setTimeZone = _ref4[1];
2426
+ var useUpdateInterval = React.useState(null);
2427
+ var _ref5 = overrideUseUpdateInterval || useUpdateInterval,
2428
+ updateInterval = _ref5[0],
2429
+ setUpdateInterval = _ref5[1];
2430
+ var dispatch = useDispatch();
2431
+ var _useAutoUpdate = useAutoUpdate(timeRange, setTimeRange, Object.assign({}, TimeSliderLiteOptionsMenuProps, {
2432
+ handleUpdate: overrideHandleAutoUpdate
2433
+ })),
2434
+ currentTime = _useAutoUpdate.currentTime;
2435
+ var isTimeSliderVisible = useSelector(function (store) {
2436
+ return mapSelectors.isTimeSliderVisible(store, mapId);
2437
+ });
2438
+ var isVisible = isAlwaysVisible || isTimeSliderVisible;
2439
+ var onToggleTimeSliderVisibility = function onToggleTimeSliderVisibility() {
2440
+ dispatch(mapActions.toggleTimeSliderIsVisible({
2441
+ mapId: mapId,
2442
+ isTimeSliderVisible: !isVisible,
2443
+ origin: mapEnums.MapActionOrigin.map
2444
+ }));
2445
+ };
2446
+ var animationDelay = useSelector(function (store) {
2447
+ return mapSelectors.getMapAnimationDelay(store, mapId);
2448
+ });
2449
+ var animationSpeed = animationDelay ? SECOND_TO_MILLISECOND / animationDelay : defaultAnimationDelayAtStart;
2450
+ var handleAnimationSpeedChange = function handleAnimationSpeedChange(animationSpeed) {
2451
+ var animationDelay = SECOND_TO_MILLISECOND / animationSpeed;
2452
+ dispatch(mapActions.setAnimationDelay({
2453
+ mapId: mapId,
2454
+ animationDelay: animationDelay,
2455
+ origin: mapEnums.MapActionOrigin.map
2456
+ }));
2457
+ };
2458
+ var defaultTimeStep = (_TimeSliderLiteOption = TimeSliderLiteOptionsMenuProps == null ? void 0 : TimeSliderLiteOptionsMenuProps.defaultTimeStep) != null ? _TimeSliderLiteOption : [5, 15];
2459
+ var layers = useSelector(function (store) {
2460
+ return mapSelectors.getMapLayers(store, mapId);
2461
+ });
2462
+ var _useDefaultTimeRange = useDefaultTimeRange(layers, HOUR_TO_MINUTE, currentTime),
2463
+ defaultStartTime = _useDefaultTimeRange[0],
2464
+ defaultEndTime = _useDefaultTimeRange[1];
2465
+ var _ref6 = timeRange || [defaultStartTime, defaultEndTime],
2466
+ startTime = _ref6[0],
2467
+ endTime = _ref6[1];
2468
+ var zeroRange = isWithinRange(startTime, endTime, 30 * MINUTE_TO_SECOND);
2469
+ var isAnimating = useSelector(function (store) {
2470
+ return mapSelectors.isAnimating(store, mapId);
2471
+ });
2472
+ useEffect(function () {
2473
+ if (zeroRange) {
2474
+ dispatch(mapActions.mapStopAnimation({
2475
+ mapId: mapId
2476
+ }));
2477
+ }
2478
+ }, [dispatch, mapId, zeroRange]);
2479
+ var selectedTime = useSelector(function (store) {
2480
+ return mapSelectors.getSelectedTime(store, mapId);
2481
+ });
2482
+ var onToggleAnimation = useOnToggleAnimation(dispatch, mapId, selectedTime, timeStep, defaultTimeStep, startTime, endTime, isAnimating, Object.assign({}, timeSliderProps, {
2483
+ timeZone: timeZone
2484
+ }));
2485
+ // Restart animation if auto updated
2486
+ useEffect(function () {
2487
+ if (isAnimating) {
2488
+ onToggleAnimation(true);
2489
+ }
2490
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2491
+ }, [currentTime]);
2492
+ var handleTimeRangeChange = function handleTimeRangeChange(newTimeRange) {
2493
+ if (isAnimating && newTimeRange) {
2494
+ dispatch(mapActions.mapStopAnimation({
2495
+ mapId: mapId
2496
+ }));
2497
+ }
2498
+ setTimeRange(newTimeRange);
2499
+ };
2500
+ var handleTimeStepChange = function handleTimeStepChange(newTimeStep) {
2501
+ if (isAnimating) {
2502
+ dispatch(mapActions.mapStopAnimation({
2503
+ mapId: mapId
2504
+ }));
2505
+ }
2506
+ setTimeStep(newTimeStep);
2507
+ };
2508
+ return jsxs(Fragment, {
2509
+ children: [isVisible && menuOpen && jsx(TimeSliderLiteOptionsMenu, Object.assign({
2510
+ menuOpen: menuOpen,
2511
+ setMenuOpen: setMenuOpen,
2512
+ defaultTimeRange: [defaultStartTime, defaultEndTime],
2513
+ defaultTimeStep: defaultTimeStep,
2514
+ useTimeRange: [timeRange, handleTimeRangeChange],
2515
+ useTimeStep: [timeStep, handleTimeStepChange],
2516
+ useAnimationSpeed: [animationSpeed, handleAnimationSpeedChange],
2517
+ useUpdateInterval: [updateInterval, setUpdateInterval],
2518
+ useTimeZone: [timeZone, setTimeZone],
2519
+ closeButtonIcon: (_timeSliderProps$sett = timeSliderProps.settings) == null || (_timeSliderProps$sett = _timeSliderProps$sett.closeButton) == null ? void 0 : _timeSliderProps$sett.icon,
2520
+ dropdownButtonIcon: (_timeSliderProps$sett2 = timeSliderProps.settings) == null || (_timeSliderProps$sett2 = _timeSliderProps$sett2.dropdownButton) == null ? void 0 : _timeSliderProps$sett2.icon,
2521
+ TimeZoneSwitch: timeSliderProps == null || (_timeSliderProps$sett3 = timeSliderProps.settings) == null ? void 0 : _timeSliderProps$sett3.TimeZoneSwitch
2522
+ }, TimeSliderLiteOptionsMenuProps)), jsx(TimeSliderLite, Object.assign({
2523
+ currentTime: currentTime,
2524
+ selectedTime: selectedTime,
2525
+ timeStep: timeStep != null ? timeStep : defaultTimeStep,
2526
+ timeZone: timeZone,
2527
+ overrideAnimation: true,
2528
+ isAnimating: !!isAnimating,
2529
+ isVisible: isVisible,
2530
+ needleDisabled: zeroRange,
2531
+ mapId: mapId,
2532
+ setSelectedTime: function setSelectedTime(newSelectedTime) {
2533
+ var newDate = preTimeDimensionSelect(mapId, newSelectedTime);
2534
+ if (isAnimating) {
2535
+ dispatch(mapActions.mapStopAnimation({
2536
+ mapId: mapId
2537
+ }));
2538
+ }
2539
+ dispatch(genericActions.setTime({
2540
+ sourceId: sourceId,
2541
+ value: {
2542
+ currentTime: handleDateUtilsISOString(newDate)
2543
+ },
2544
+ origin: mapEnums.MapActionOrigin.map
2545
+ }));
2546
+ },
2547
+ menuOpen: menuOpen,
2548
+ onToggleMenu: function onToggleMenu() {
2549
+ return setMenuOpen(!menuOpen);
2550
+ },
2551
+ onToggleTimeSlider: onToggleTimeSliderVisibility,
2552
+ onToggleAnimation: onToggleAnimation,
2553
+ startTime: startTime,
2554
+ endTime: endTime
2555
+ }, timeSliderProps))]
2556
+ });
2557
+ };
2558
+
2559
+ export { TIME_SLIDER_LITE_NAMESPACE, TimeSliderLite, TimeSliderLiteConnect, TimeSliderLiteI18nProvider, TimeSliderLiteOptionsMenu, timeSliderLiteUtils as TimeSliderLiteUtils, initTimeSliderLiteI18n, translations as timeSliderLiteTranslations, translations as timesliderliteTranslations, useTimesliderLiteTranslation };