@opengeoweb/time-slider-lite 19.1.0 → 19.1.1

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