@opengeoweb/time-slider 19.6.1 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Grid, useTheme, Box, Typography, Menu, MenuItem, CardHeader, FormControl, TextField, Select, Popper, Paper, Stack, InputAdornment, ClickAwayListener } from '@mui/material';
2
+ import { Grid, useTheme, Box, Typography, Menu, MenuItem, CardHeader, InputAdornment, RadioGroup, FormControlLabel, Radio, Divider, FormHelperText, FormControl, TextField, Select, Popper, Paper, Stack, ClickAwayListener } from '@mui/material';
3
3
  import React, { useState, useRef, useEffect, useCallback, useContext, useMemo, createElement } from 'react';
4
- import { dateUtils, isTargetInteractiveInput, isDialogFocused, safelyInitI18nForTestsAndStories, CustomIconButton, CustomTooltip, CanvasComponent, renderCounter, CustomToggleButton } from '@opengeoweb/shared';
4
+ import { dateUtils, isTargetInteractiveInput, isDialogFocused, safelyInitI18nForTestsAndStories, CustomIconButton, CustomTooltip, CanvasComponent, NumberWithUnitField, DateTimePicker, renderCounter, pickerDateToUTC, CustomToggleButton } from '@opengeoweb/shared';
5
5
  import { debounce, throttle } from 'lodash';
6
- import { ChevronDown, ChevronUp, dragHandlePath, Edit, Animation, AutoUpdateActive, AutoUpdateInActive, StepForward, StepBackward, Now, Pause, Play, Speed, Clock, FastForward, Options, CalendarToday, ThemeWrapper, lightTheme, darkTheme } from '@opengeoweb/theme';
6
+ import { ChevronDown, ChevronUp, dragHandlePath, Edit, Animation, Clock, CalendarToday, AutoUpdateActive, AutoUpdateInActive, StepForward, StepBackward, Now, Pause, Play, Speed, FastForward, Options, ThemeWrapper, lightTheme, darkTheme } from '@opengeoweb/theme';
7
7
  import i18n from 'i18next';
8
8
  import { useTranslation, I18nextProvider } from 'react-i18next';
9
- import { Box as Box$1 } from '@mui/system';
10
9
  import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
11
- import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
12
10
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
11
+ import { TimePicker } from '@mui/x-date-pickers/TimePicker';
12
+ import { Box as Box$1 } from '@mui/system';
13
13
  import { PickerDay } from '@mui/x-date-pickers/PickerDay';
14
14
 
15
15
  var en = {
@@ -61,7 +61,37 @@ var en = {
61
61
  "timeslider-span": "Span",
62
62
  "timeslider-marker": "Marker",
63
63
  "timeslider-marker-placement": "Marker placement",
64
- "timeslider-marker-label": "Select date and time"
64
+ "timeslider-marker-label": "Select date and time",
65
+ "timeslider-animation-length": "Animation length",
66
+ "timeslider-animation-length-auto": "Auto",
67
+ "timeslider-animation-length-now": "Now −/+",
68
+ "timeslider-animation-length-recurring-period": "Recurring period −/+",
69
+ "timeslider-animation-length-reference-time": "Reference time −/+",
70
+ "timeslider-reference-time": "Reference time",
71
+ "timeslider-animation-length-exact": "Exact",
72
+ "timeslider-anchor-time": "Anchor Time",
73
+ "timeslider-auto-animation-length": "Auto animation length",
74
+ "timeslider-recurring-period": "Recurring period",
75
+ "timeslider-date": "Date",
76
+ "timeslider-today": "Today",
77
+ "timeslider-time": "Time",
78
+ "timeslider-start-time": "Start time",
79
+ "timeslider-end-time": "End time",
80
+ "timeslider-unit-years": "years",
81
+ "timeslider-unit-months": "months",
82
+ "timeslider-unit-weeks": "weeks",
83
+ "timeslider-unit-days": "days",
84
+ "timeslider-unit-hours": "hours",
85
+ "timeslider-unit-minutes": "minutes",
86
+ "timeslider-unit-short-years": "yr",
87
+ "timeslider-unit-short-months": "mo",
88
+ "timeslider-unit-short-weeks": "w",
89
+ "timeslider-unit-short-days": "d",
90
+ "timeslider-unit-short-hours": "h",
91
+ "timeslider-unit-short-minutes": "m",
92
+ "timeslider-start-before-end": "Start time must be before end time",
93
+ "timeslider-animation-too-many-steps": "Reduce the animation length or increase the time step",
94
+ "timeslider-start-and-end-time": "Start and end time"
65
95
  };
66
96
  var fi = {
67
97
  "timeslider-auto": "Auto",
@@ -111,7 +141,36 @@ var fi = {
111
141
  "timeslider-span": "missing-translation",
112
142
  "timeslider-marker": "Aikamerkki",
113
143
  "timeslider-marker-placement": "Aikamerkin siirto",
114
- "timeslider-marker-label": "Valitse päivämäärä ja kellonaika"
144
+ "timeslider-marker-label": "Valitse päivämäärä ja kellonaika",
145
+ "timeslider-animation-length": "Animaation pituus",
146
+ "timeslider-animation-length-auto": "Auto",
147
+ "timeslider-animation-length-now": "Nyt −/+",
148
+ "timeslider-animation-length-recurring-period": "Toistuva jakso −/+",
149
+ "timeslider-animation-length-reference-time": "Referenssiaika −/+",
150
+ "timeslider-reference-time": "Referenssiaika",
151
+ "timeslider-animation-length-exact": "Tarkka",
152
+ "timeslider-anchor-time": "Ankkuriaika",
153
+ "timeslider-auto-animation-length": "Automaattinen animaation pituus",
154
+ "timeslider-recurring-period": "Toistuva jakso",
155
+ "timeslider-date": "Päivämäärä",
156
+ "timeslider-today": "Tänään",
157
+ "timeslider-time": "Aika",
158
+ "timeslider-start-time": "Alkuaika",
159
+ "timeslider-end-time": "Loppuaika",
160
+ "timeslider-unit-years": "vuotta",
161
+ "timeslider-unit-months": "kuukautta",
162
+ "timeslider-unit-weeks": "viikkoa",
163
+ "timeslider-unit-days": "päivää",
164
+ "timeslider-unit-hours": "tuntia",
165
+ "timeslider-unit-minutes": "minuuttia",
166
+ "timeslider-unit-short-years": "v",
167
+ "timeslider-unit-short-months": "kk",
168
+ "timeslider-unit-short-weeks": "vk",
169
+ "timeslider-unit-short-days": "pv",
170
+ "timeslider-unit-short-hours": "t",
171
+ "timeslider-unit-short-minutes": "min",
172
+ "timeslider-start-before-end": "Alkuajan on oltava ennen loppuaikaa",
173
+ "timeslider-animation-too-many-steps": "Pienennä animaation pituutta tai kasvata aika-askelta"
115
174
  };
116
175
  var no = {
117
176
  "timeslider-auto": "Auto",
@@ -161,7 +220,36 @@ var no = {
161
220
  "timeslider-span": "Periode",
162
221
  "timeslider-marker": "missing translation",
163
222
  "timeslider-marker-placement": "missing translation",
164
- "timeslider-marker-label": "missing translation"
223
+ "timeslider-marker-label": "missing translation",
224
+ "timeslider-animation-length": "Animasjonslengde",
225
+ "timeslider-animation-length-auto": "Auto",
226
+ "timeslider-animation-length-now": "Nå −/+",
227
+ "timeslider-animation-length-recurring-period": "Gjentakende periode −/+",
228
+ "timeslider-animation-length-reference-time": "Referansetid −/+",
229
+ "timeslider-reference-time": "Referansetid",
230
+ "timeslider-animation-length-exact": "Eksakt",
231
+ "timeslider-anchor-time": "Ankertid",
232
+ "timeslider-auto-animation-length": "Automatisk animasjonslengde",
233
+ "timeslider-recurring-period": "Gjentakende periode",
234
+ "timeslider-date": "Dato",
235
+ "timeslider-today": "I dag",
236
+ "timeslider-time": "Tid",
237
+ "timeslider-start-time": "Starttid",
238
+ "timeslider-end-time": "Slutttid",
239
+ "timeslider-unit-years": "år",
240
+ "timeslider-unit-months": "måneder",
241
+ "timeslider-unit-weeks": "uker",
242
+ "timeslider-unit-days": "dager",
243
+ "timeslider-unit-hours": "timer",
244
+ "timeslider-unit-minutes": "minutter",
245
+ "timeslider-unit-short-years": "år",
246
+ "timeslider-unit-short-months": "mnd",
247
+ "timeslider-unit-short-weeks": "u",
248
+ "timeslider-unit-short-days": "d",
249
+ "timeslider-unit-short-hours": "t",
250
+ "timeslider-unit-short-minutes": "m",
251
+ "timeslider-start-before-end": "Starttid må være før slutttid",
252
+ "timeslider-animation-too-many-steps": "Reduser animasjonslengden eller øk tidssteget"
165
253
  };
166
254
  var nl = {
167
255
  "timeslider-auto": "Auto",
@@ -211,7 +299,37 @@ var nl = {
211
299
  "timeslider-span": "Tijdsperiode",
212
300
  "timeslider-marker": "Kies tijdstip",
213
301
  "timeslider-marker-placement": "Tijd kiezen",
214
- "timeslider-marker-label": "Selecteer datum en tijd"
302
+ "timeslider-marker-label": "Selecteer datum en tijd",
303
+ "timeslider-animation-length": "Animatielengte",
304
+ "timeslider-animation-length-auto": "Auto",
305
+ "timeslider-animation-length-now": "Nu −/+",
306
+ "timeslider-animation-length-recurring-period": "Terugkerende periode −/+",
307
+ "timeslider-animation-length-reference-time": "Referentietijd −/+",
308
+ "timeslider-reference-time": "Referentietijd",
309
+ "timeslider-animation-length-exact": "Exact",
310
+ "timeslider-anchor-time": "Ankertijd",
311
+ "timeslider-auto-animation-length": "Automatische animatielengte",
312
+ "timeslider-recurring-period": "Terugkerende periode",
313
+ "timeslider-date": "Datum",
314
+ "timeslider-today": "Vandaag",
315
+ "timeslider-time": "Tijd",
316
+ "timeslider-start-time": "Starttijd",
317
+ "timeslider-end-time": "Eindtijd",
318
+ "timeslider-unit-years": "jaren",
319
+ "timeslider-unit-months": "maanden",
320
+ "timeslider-unit-weeks": "weken",
321
+ "timeslider-unit-days": "dagen",
322
+ "timeslider-unit-hours": "uren",
323
+ "timeslider-unit-minutes": "minuten",
324
+ "timeslider-unit-short-years": "jr",
325
+ "timeslider-unit-short-months": "mnd",
326
+ "timeslider-unit-short-weeks": "w",
327
+ "timeslider-unit-short-days": "d",
328
+ "timeslider-unit-short-hours": "u",
329
+ "timeslider-unit-short-minutes": "m",
330
+ "timeslider-start-before-end": "Starttijd moet voor eindtijd liggen",
331
+ "timeslider-animation-too-many-steps": "Verklein de animatielengte of vergroot de tijdstap",
332
+ "timeslider-start-and-end-time": "Start- en eindtijd"
215
333
  };
216
334
  var timesliderTranslations = {
217
335
  en: en,
@@ -2340,6 +2458,932 @@ var AnimationLengthButton = function AnimationLengthButton(_ref) {
2340
2458
  });
2341
2459
  };
2342
2460
 
2461
+ var _modeTranslationKey;
2462
+ var AnimationLengthMode;
2463
+ (function (AnimationLengthMode) {
2464
+ AnimationLengthMode["Auto"] = "auto";
2465
+ AnimationLengthMode["Now"] = "now";
2466
+ AnimationLengthMode["RecurringPeriod"] = "recurringPeriod";
2467
+ AnimationLengthMode["ReferenceTime"] = "referenceTime";
2468
+ AnimationLengthMode["Exact"] = "exact";
2469
+ })(AnimationLengthMode || (AnimationLengthMode = {}));
2470
+ var timeUnits = ['years', 'months', 'weeks', 'days', 'hours', 'minutes'];
2471
+ var defaultStartOffset = {
2472
+ value: 0,
2473
+ unit: 'hours'
2474
+ };
2475
+ var defaultEndOffset = {
2476
+ value: 2,
2477
+ unit: 'hours'
2478
+ };
2479
+ var defaultOffsetSelections = {
2480
+ startOffset: defaultStartOffset,
2481
+ endOffset: defaultEndOffset
2482
+ };
2483
+ var unitTranslationKey = {
2484
+ years: 'timeslider-unit-years',
2485
+ months: 'timeslider-unit-months',
2486
+ weeks: 'timeslider-unit-weeks',
2487
+ days: 'timeslider-unit-days',
2488
+ hours: 'timeslider-unit-hours',
2489
+ minutes: 'timeslider-unit-minutes'
2490
+ };
2491
+ var shortUnitTranslationKey = {
2492
+ years: 'timeslider-unit-short-years',
2493
+ months: 'timeslider-unit-short-months',
2494
+ weeks: 'timeslider-unit-short-weeks',
2495
+ days: 'timeslider-unit-short-days',
2496
+ hours: 'timeslider-unit-short-hours',
2497
+ minutes: 'timeslider-unit-short-minutes'
2498
+ };
2499
+ var modeTranslationKey = (_modeTranslationKey = {}, _modeTranslationKey[AnimationLengthMode.Auto] = 'timeslider-animation-length-auto', _modeTranslationKey[AnimationLengthMode.Now] = 'timeslider-animation-length-now', _modeTranslationKey[AnimationLengthMode.RecurringPeriod] = 'timeslider-animation-length-recurring-period', _modeTranslationKey[AnimationLengthMode.ReferenceTime] = 'timeslider-animation-length-reference-time', _modeTranslationKey[AnimationLengthMode.Exact] = 'timeslider-animation-length-exact', _modeTranslationKey);
2500
+ var offsetToDuration = function offsetToDuration(_ref) {
2501
+ var _ref2;
2502
+ var value = _ref.value,
2503
+ unit = _ref.unit;
2504
+ return _ref2 = {}, _ref2[unit] = value, _ref2;
2505
+ };
2506
+ var toAnimationTime = function toAnimationTime(date) {
2507
+ return dateUtils.dateToString(date, dateUtils.DATE_FORMAT_UTC);
2508
+ };
2509
+ /* The clock in the menu offers minutes in these increments, so an anchor must land on one. */
2510
+ var ANCHOR_MINUTE_STEP = 5;
2511
+ var padded = function padded(value) {
2512
+ return String(value).padStart(2, '0');
2513
+ };
2514
+ /**
2515
+ * Reads the UTC fields directly: `dateUtils.dateToString` formats a local twin of the
2516
+ * date, which a DST gap shifts by an hour.
2517
+ */
2518
+ var toAnchorTime = function toAnchorTime(date) {
2519
+ var minutes = date.getUTCMinutes();
2520
+ return padded(date.getUTCHours()) + ":" + padded(minutes - minutes % ANCHOR_MINUTE_STEP);
2521
+ };
2522
+ /* Modes that count their offsets from an anchor instant rather than a stored range. */
2523
+ var anchoredModes = [AnimationLengthMode.Now, AnimationLengthMode.RecurringPeriod, AnimationLengthMode.ReferenceTime];
2524
+ var isAnchoredMode = function isAnchoredMode(mode) {
2525
+ return !!mode && anchoredModes.includes(mode);
2526
+ };
2527
+ /** Narrows the mode so the compiler can require an anchor time alongside it. */
2528
+ var isRecurringPeriodMode = function isRecurringPeriodMode(mode) {
2529
+ return mode === AnimationLengthMode.RecurringPeriod;
2530
+ };
2531
+ var ANCHOR_TIME_PATTERN = /^([01]\d|2[0-3]):[0-5]\d$/;
2532
+ var isValidAnchorTime = function isValidAnchorTime(anchorTime) {
2533
+ return !!anchorTime && ANCHOR_TIME_PATTERN.test(anchorTime);
2534
+ };
2535
+ var selectionsForMode = function selectionsForMode(setting) {
2536
+ if (setting.mode === AnimationLengthMode.Now) {
2537
+ return setting.now;
2538
+ }
2539
+ if (setting.mode === AnimationLengthMode.RecurringPeriod) {
2540
+ return setting.recurringPeriod;
2541
+ }
2542
+ if (setting.mode === AnimationLengthMode.ReferenceTime) {
2543
+ return setting.referenceTime;
2544
+ }
2545
+ return defaultOffsetSelections;
2546
+ };
2547
+ /** The offsets of whichever mode is selected; the modes without offsets use the defaults. */
2548
+ var activeOffsets = function activeOffsets(setting) {
2549
+ var _selectionsForMode = selectionsForMode(setting),
2550
+ startOffset = _selectionsForMode.startOffset,
2551
+ endOffset = _selectionsForMode.endOffset;
2552
+ return {
2553
+ startOffset: startOffset,
2554
+ endOffset: endOffset
2555
+ };
2556
+ };
2557
+ var defaultRecurringPeriodSelections = function defaultRecurringPeriodSelections(now) {
2558
+ if (now === void 0) {
2559
+ now = dateUtils.utc();
2560
+ }
2561
+ return Object.assign({}, defaultOffsetSelections, {
2562
+ anchorTime: toAnchorTime(now)
2563
+ });
2564
+ };
2565
+ /** Presets carry settings the compiler cannot vouch for, so the selected mode is given the slice it needs. */
2566
+ var withModeSelections = function withModeSelections(setting, now) {
2567
+ if (now === void 0) {
2568
+ now = dateUtils.utc();
2569
+ }
2570
+ if (setting.mode === AnimationLengthMode.Now) {
2571
+ return Object.assign({}, setting, {
2572
+ now: Object.assign({}, defaultOffsetSelections, setting.now)
2573
+ });
2574
+ }
2575
+ if (setting.mode === AnimationLengthMode.RecurringPeriod) {
2576
+ var merged = Object.assign({}, defaultRecurringPeriodSelections(now), setting.recurringPeriod);
2577
+ return Object.assign({}, setting, {
2578
+ recurringPeriod: isValidAnchorTime(merged.anchorTime) ? merged : Object.assign({}, merged, {
2579
+ anchorTime: toAnchorTime(now)
2580
+ })
2581
+ });
2582
+ }
2583
+ if (setting.mode === AnimationLengthMode.Exact) {
2584
+ return Object.assign({}, setting, {
2585
+ exact: Object.assign({}, defaultExactSelections(now), setting.exact)
2586
+ });
2587
+ }
2588
+ return setting;
2589
+ };
2590
+ /**
2591
+ * A recurring period anchors on its time of day within the current UTC date, so the
2592
+ * window it resolves rolls onto the next day once the clock passes midnight.
2593
+ */
2594
+ var resolveAnchorInstant = function resolveAnchorInstant(setting, now) {
2595
+ if (now === void 0) {
2596
+ now = dateUtils.utc();
2597
+ }
2598
+ if (setting.mode !== AnimationLengthMode.RecurringPeriod) {
2599
+ return now;
2600
+ }
2601
+ var _setting$recurringPer = setting.recurringPeriod.anchorTime.split(':').map(Number),
2602
+ hours = _setting$recurringPer[0],
2603
+ minutes = _setting$recurringPer[1];
2604
+ return dateUtils.set(now, {
2605
+ hours: hours,
2606
+ minutes: minutes,
2607
+ seconds: 0,
2608
+ milliseconds: 0
2609
+ });
2610
+ };
2611
+ /**
2612
+ * Offsets are signed: negative lands before the anchor, positive after. They are
2613
+ * applied as calendar durations, so "+ 1 month" lands on the same day of the next
2614
+ * month rather than a fixed number of days later.
2615
+ */
2616
+ var resolveAnimationRange = function resolveAnimationRange(setting, now) {
2617
+ if (now === void 0) {
2618
+ now = dateUtils.utc();
2619
+ }
2620
+ var _activeOffsets = activeOffsets(setting),
2621
+ startOffset = _activeOffsets.startOffset,
2622
+ endOffset = _activeOffsets.endOffset;
2623
+ var anchor = resolveAnchorInstant(setting, now);
2624
+ return {
2625
+ animationStartTime: toAnimationTime(dateUtils.add(anchor, offsetToDuration(startOffset))),
2626
+ animationEndTime: toAnimationTime(dateUtils.add(anchor, offsetToDuration(endOffset)))
2627
+ };
2628
+ };
2629
+ /** Offsets can use different units, so validity is decided on the resolved instants. */
2630
+ /** Exact names its range outright; every other mode resolves one from its offsets. */
2631
+ var settingRange = function settingRange(setting, now) {
2632
+ if (now === void 0) {
2633
+ now = dateUtils.utc();
2634
+ }
2635
+ return setting.mode === AnimationLengthMode.Exact ? setting.exact : resolveAnimationRange(setting, now);
2636
+ };
2637
+ /* Exact times are picked to the minute, so seconds must not decide validity. */
2638
+ var isValidAnimationLength = function isValidAnimationLength(setting, now) {
2639
+ if (now === void 0) {
2640
+ now = dateUtils.utc();
2641
+ }
2642
+ var _settingRange = settingRange(setting, now),
2643
+ animationStartTime = _settingRange.animationStartTime,
2644
+ animationEndTime = _settingRange.animationEndTime;
2645
+ return dateUtils.isBefore(dateUtils.utc(animationStartTime).setSeconds(0, 0), dateUtils.utc(animationEndTime).setSeconds(0, 0));
2646
+ };
2647
+ /** Frames the animation may hold; the range is expanded one entry per time step. */
2648
+ var MAX_ANIMATION_STEPS = 10000;
2649
+ /**
2650
+ * The cost of an animation is its span divided by the time step, so a wide range
2651
+ * is affordable with a coarse step and unaffordable with a fine one.
2652
+ */
2653
+ var isWithinAnimationStepLimit = function isWithinAnimationStepLimit(setting, timeStepInMinutes, now) {
2654
+ if (now === void 0) {
2655
+ now = dateUtils.utc();
2656
+ }
2657
+ if (!timeStepInMinutes) {
2658
+ return true;
2659
+ }
2660
+ var _settingRange2 = settingRange(setting, now),
2661
+ animationStartTime = _settingRange2.animationStartTime,
2662
+ animationEndTime = _settingRange2.animationEndTime;
2663
+ var spanInMinutes = dateUtils.differenceInMinutes(dateUtils.utc(animationEndTime), dateUtils.utc(animationStartTime));
2664
+ return Math.abs(spanInMinutes) / timeStepInMinutes <= MAX_ANIMATION_STEPS;
2665
+ };
2666
+ /* Shares the animation-time format, so a typed and a dragged range serialise alike. */
2667
+ var toExactAnimationTime = toAnimationTime;
2668
+ /** A day either side of now, so an exact window opens on something usable. */
2669
+ var defaultExactSelections = function defaultExactSelections(now) {
2670
+ if (now === void 0) {
2671
+ now = dateUtils.utc();
2672
+ }
2673
+ var wholeMinute = dateUtils.set(now, {
2674
+ seconds: 0,
2675
+ milliseconds: 0
2676
+ });
2677
+ return {
2678
+ animationStartTime: toExactAnimationTime(dateUtils.sub(wholeMinute, {
2679
+ days: 1
2680
+ })),
2681
+ animationEndTime: toExactAnimationTime(dateUtils.add(wholeMinute, {
2682
+ days: 1
2683
+ }))
2684
+ };
2685
+ };
2686
+ /** Starts Exact from whatever range is already on screen, falling back to the defaults. */
2687
+ var exactAnimationLengthFrom = function exactAnimationLengthFrom(_ref3, now) {
2688
+ var animationStartTime = _ref3.animationStartTime,
2689
+ animationEndTime = _ref3.animationEndTime;
2690
+ if (now === void 0) {
2691
+ now = dateUtils.utc();
2692
+ }
2693
+ return {
2694
+ mode: AnimationLengthMode.Exact,
2695
+ exact: animationStartTime && animationEndTime ? {
2696
+ animationStartTime: animationStartTime,
2697
+ animationEndTime: animationEndTime
2698
+ } : defaultExactSelections(now)
2699
+ };
2700
+ };
2701
+ var getOffsetFromTime = function getOffsetFromTime(time, anchorTime) {
2702
+ var relativeTime = dateUtils.utc(time);
2703
+ var value = dateUtils.differenceInMinutes(relativeTime, anchorTime);
2704
+ return {
2705
+ unit: 'minutes',
2706
+ value: value
2707
+ };
2708
+ };
2709
+ var getAnimationLengthFromRange = function getAnimationLengthFromRange(mode, _ref4, now) {
2710
+ var animationStartTime = _ref4.animationStartTime,
2711
+ animationEndTime = _ref4.animationEndTime;
2712
+ if (now === void 0) {
2713
+ now = dateUtils.utc();
2714
+ }
2715
+ switch (mode) {
2716
+ case AnimationLengthMode.Now:
2717
+ {
2718
+ return {
2719
+ mode: mode,
2720
+ now: {
2721
+ startOffset: getOffsetFromTime(animationStartTime, now),
2722
+ endOffset: getOffsetFromTime(animationEndTime, now)
2723
+ }
2724
+ };
2725
+ }
2726
+ case AnimationLengthMode.RecurringPeriod:
2727
+ {
2728
+ var today = dateUtils.startOfDayUTC(now);
2729
+ return {
2730
+ mode: mode,
2731
+ recurringPeriod: {
2732
+ anchorTime: '00:00',
2733
+ startOffset: getOffsetFromTime(animationStartTime, today),
2734
+ endOffset: getOffsetFromTime(animationEndTime, today)
2735
+ }
2736
+ };
2737
+ }
2738
+ case AnimationLengthMode.Exact:
2739
+ default:
2740
+ return exactAnimationLengthFrom({
2741
+ animationStartTime: animationStartTime,
2742
+ animationEndTime: animationEndTime
2743
+ });
2744
+ }
2745
+ };
2746
+
2747
+ var styles$2 = {
2748
+ openPickerButton: {
2749
+ padding: 0
2750
+ },
2751
+ /* Filled inputs offset their adornments for the label, so match that offset. */
2752
+ utc: {
2753
+ paddingTop: '16px'
2754
+ }
2755
+ };
2756
+ /**
2757
+ * Only the hours and minutes of the carrier are ever read, so its date is arbitrary —
2758
+ * but it must be a day no timezone shifts, or a DST gap swallows the anchor's hour.
2759
+ */
2760
+ var TIME_ONLY_CARRIER_DATE = '2001-01-15T00:00:00Z';
2761
+ /* The picker reads and writes a Date through its local-time getters, so the anchor rides in that frame. */
2762
+ var anchorTimeToPickerDate = function anchorTimeToPickerDate(anchorTime) {
2763
+ if (!isValidAnchorTime(anchorTime)) {
2764
+ return null;
2765
+ }
2766
+ var _anchorTime$split$map = anchorTime.split(':').map(Number),
2767
+ hours = _anchorTime$split$map[0],
2768
+ minutes = _anchorTime$split$map[1];
2769
+ var pickerDate = new Date(TIME_ONLY_CARRIER_DATE);
2770
+ pickerDate.setHours(hours, minutes, 0, 0);
2771
+ return pickerDate;
2772
+ };
2773
+ var pickerDateToAnchorTime = function pickerDateToAnchorTime(pickerDate) {
2774
+ return dateUtils.dateToString(pickerDate, dateUtils.DATE_FORMAT_HOURS, false);
2775
+ };
2776
+ var OpenPicker = function OpenPicker() {
2777
+ return jsx(Clock, {});
2778
+ };
2779
+ var AnchorTimeField = function AnchorTimeField(_ref) {
2780
+ var value = _ref.value,
2781
+ label = _ref.label,
2782
+ onChange = _ref.onChange,
2783
+ _ref$disabled = _ref.disabled,
2784
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled;
2785
+ /* Typing walks through incomplete times, so only a whole one is worth reporting. */
2786
+ var reportCompletedAnchorTime = function reportCompletedAnchorTime(pickerDate) {
2787
+ if (pickerDate && dateUtils.isValid(pickerDate)) {
2788
+ onChange(pickerDateToAnchorTime(pickerDate));
2789
+ }
2790
+ };
2791
+ return jsx(LocalizationProvider, {
2792
+ dateAdapter: AdapterDateFns,
2793
+ children: jsx(TimePicker, {
2794
+ ampm: false,
2795
+ closeOnSelect: false,
2796
+ desktopModeMediaQuery: "@media (min-width: 720px)",
2797
+ disabled: disabled,
2798
+ label: label,
2799
+ onChange: reportCompletedAnchorTime,
2800
+ slotProps: {
2801
+ actionBar: {
2802
+ actions: ['accept']
2803
+ },
2804
+ field: {
2805
+ openPickerButtonPosition: 'start'
2806
+ },
2807
+ openPickerButton: {
2808
+ size: 'small',
2809
+ sx: styles$2.openPickerButton
2810
+ },
2811
+ textField: {
2812
+ variant: 'filled',
2813
+ slotProps: {
2814
+ input: {
2815
+ endAdornment: jsx(InputAdornment, {
2816
+ position: "end",
2817
+ sx: styles$2.utc,
2818
+ children: "UTC"
2819
+ })
2820
+ }
2821
+ }
2822
+ }
2823
+ },
2824
+ slots: {
2825
+ openPickerIcon: OpenPicker
2826
+ },
2827
+ timeSteps: {
2828
+ minutes: ANCHOR_MINUTE_STEP
2829
+ },
2830
+ value: anchorTimeToPickerDate(value)
2831
+ })
2832
+ });
2833
+ };
2834
+
2835
+ var selectableModes = [AnimationLengthMode.Auto, AnimationLengthMode.Now, AnimationLengthMode.RecurringPeriod, AnimationLengthMode.ReferenceTime, AnimationLengthMode.Exact];
2836
+ var OFFSET_MAX_DIGITS = 3;
2837
+ var maxOffsetByUnit = {
2838
+ minutes: 999,
2839
+ hours: 999,
2840
+ days: 365,
2841
+ weeks: 99,
2842
+ months: 99,
2843
+ years: 99
2844
+ };
2845
+ /* One line of MuiFormHelperText: 20px line box plus its 3px top margin. */
2846
+ var RESERVED_ERROR_HEIGHT = '23px';
2847
+ /* Every row splits the panel the same way, so the fields line up in two columns. */
2848
+ var fieldRow = {
2849
+ display: 'flex',
2850
+ gap: 1,
2851
+ '& > *': {
2852
+ flex: '1 1 0'
2853
+ }
2854
+ };
2855
+ var styles$1 = {
2856
+ menu: {
2857
+ display: 'flex',
2858
+ flexDirection: 'column',
2859
+ minWidth: '260px',
2860
+ padding: '8px 12px'
2861
+ },
2862
+ sectionTitle: {
2863
+ fontSize: 12,
2864
+ fontWeight: 700,
2865
+ paddingBottom: 2
2866
+ },
2867
+ caption: {
2868
+ color: 'geowebColors.greys.accessible',
2869
+ fontSize: 11,
2870
+ paddingLeft: 0.5
2871
+ },
2872
+ radioLabel: {
2873
+ '& .MuiFormControlLabel-label': {
2874
+ fontSize: 14
2875
+ }
2876
+ },
2877
+ anchorRow: {
2878
+ alignItems: 'center',
2879
+ display: 'flex',
2880
+ gap: 1,
2881
+ paddingLeft: 0.5
2882
+ },
2883
+ anchorValue: {
2884
+ flexGrow: 1,
2885
+ fontSize: 14,
2886
+ fontWeight: 700
2887
+ },
2888
+ anchorFields: fieldRow,
2889
+ /* The top padding matches the reserved error line below, so the fields sit between equal gaps. */
2890
+ offsets: Object.assign({}, fieldRow, {
2891
+ paddingTop: RESERVED_ERROR_HEIGHT
2892
+ }),
2893
+ reservedError: {
2894
+ visibility: 'hidden'
2895
+ },
2896
+ readOnlyValue: {
2897
+ flexGrow: 1,
2898
+ fontSize: 14
2899
+ },
2900
+ exact: {
2901
+ display: 'flex',
2902
+ flexDirection: 'column'
2903
+ },
2904
+ dateTimePicker: {
2905
+ paddingBottom: 2
2906
+ },
2907
+ utc: {
2908
+ color: 'geowebColors.greys.accessible',
2909
+ fontSize: 18
2910
+ }
2911
+ };
2912
+ var AnimationLengthMenu = function AnimationLengthMenu(_ref) {
2913
+ var setting = _ref.setting,
2914
+ onChange = _ref.onChange,
2915
+ onInputChange = _ref.onInputChange,
2916
+ animationStartTime = _ref.animationStartTime,
2917
+ animationEndTime = _ref.animationEndTime,
2918
+ autoTimeStepLayerName = _ref.autoTimeStepLayerName,
2919
+ timeStep = _ref.timeStep,
2920
+ _ref$isAutoDisabled = _ref.isAutoDisabled,
2921
+ isAutoDisabled = _ref$isAutoDisabled === void 0 ? false : _ref$isAutoDisabled,
2922
+ _ref$disabled = _ref.disabled,
2923
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
2924
+ referenceTimeFromLayer = _ref.referenceTimeFromLayer;
2925
+ var _useTimesliderTransla = useTimesliderTranslation(),
2926
+ t = _useTimesliderTransla.t;
2927
+ /* Spreading the setting keeps every other mode's selections while this one changes. */
2928
+ var changeMode = function changeMode(mode) {
2929
+ if (isRecurringPeriodMode(mode)) {
2930
+ var _setting$recurringPer;
2931
+ onChange(Object.assign({}, setting, {
2932
+ mode: mode,
2933
+ recurringPeriod: (_setting$recurringPer = setting.recurringPeriod) != null ? _setting$recurringPer : defaultRecurringPeriodSelections()
2934
+ }));
2935
+ return;
2936
+ }
2937
+ if (mode === AnimationLengthMode.Now) {
2938
+ var _setting$now;
2939
+ onChange(Object.assign({}, setting, {
2940
+ mode: mode,
2941
+ now: (_setting$now = setting.now) != null ? _setting$now : defaultOffsetSelections
2942
+ }));
2943
+ return;
2944
+ }
2945
+ if (mode === AnimationLengthMode.Exact) {
2946
+ var _setting$exact;
2947
+ onChange(Object.assign({}, setting, {
2948
+ mode: mode,
2949
+ exact: (_setting$exact = setting.exact) != null ? _setting$exact : defaultExactSelections()
2950
+ }));
2951
+ return;
2952
+ }
2953
+ if (mode === AnimationLengthMode.ReferenceTime) {
2954
+ var _setting$referenceTim;
2955
+ onChange(Object.assign({}, setting, {
2956
+ mode: mode,
2957
+ referenceTime: (_setting$referenceTim = setting.referenceTime) != null ? _setting$referenceTim : defaultOffsetSelections
2958
+ }));
2959
+ return;
2960
+ }
2961
+ onChange(Object.assign({}, setting, {
2962
+ mode: mode
2963
+ }));
2964
+ };
2965
+ var _activeOffsets = activeOffsets(setting),
2966
+ startOffset = _activeOffsets.startOffset,
2967
+ endOffset = _activeOffsets.endOffset;
2968
+ var changeActiveOffsets = function changeActiveOffsets(offsets, isStep) {
2969
+ if (setting.mode === AnimationLengthMode.RecurringPeriod) {
2970
+ onChange(Object.assign({}, setting, {
2971
+ recurringPeriod: Object.assign({}, setting.recurringPeriod, offsets)
2972
+ }), isStep);
2973
+ return;
2974
+ }
2975
+ if (setting.mode === AnimationLengthMode.Now) {
2976
+ onChange(Object.assign({}, setting, {
2977
+ now: offsets
2978
+ }), isStep);
2979
+ }
2980
+ if (setting.mode === AnimationLengthMode.ReferenceTime) {
2981
+ onChange(Object.assign({}, setting, {
2982
+ referenceTime: offsets
2983
+ }), isStep);
2984
+ }
2985
+ };
2986
+ var changeAnchorTime = function changeAnchorTime(changedAnchorTime) {
2987
+ if (setting.mode !== AnimationLengthMode.RecurringPeriod) {
2988
+ return;
2989
+ }
2990
+ onChange(Object.assign({}, setting, {
2991
+ recurringPeriod: Object.assign({}, setting.recurringPeriod, {
2992
+ anchorTime: changedAnchorTime
2993
+ })
2994
+ }));
2995
+ };
2996
+ var unitOptions = timeUnits.map(function (unit) {
2997
+ return {
2998
+ value: unit,
2999
+ label: t(unitTranslationKey[unit])
3000
+ };
3001
+ });
3002
+ var asTimeOffset = function asTimeOffset(_ref2) {
3003
+ var value = _ref2.value,
3004
+ unit = _ref2.unit;
3005
+ var maxOffset = maxOffsetByUnit[unit];
3006
+ return {
3007
+ value: Math.max(-maxOffset, Math.min(maxOffset, value)),
3008
+ unit: unit
3009
+ };
3010
+ };
3011
+ /* One unit spans the whole window, so picking it on either field moves both. */
3012
+ var changeStartOffset = function changeStartOffset(offset, isStep) {
3013
+ var changed = asTimeOffset(offset);
3014
+ changeActiveOffsets({
3015
+ startOffset: changed,
3016
+ endOffset: asTimeOffset(Object.assign({}, endOffset, {
3017
+ unit: changed.unit
3018
+ }))
3019
+ }, isStep);
3020
+ };
3021
+ var changeEndOffset = function changeEndOffset(offset, isStep) {
3022
+ var changed = asTimeOffset(offset);
3023
+ changeActiveOffsets({
3024
+ startOffset: asTimeOffset(Object.assign({}, startOffset, {
3025
+ unit: changed.unit
3026
+ })),
3027
+ endOffset: changed
3028
+ }, isStep);
3029
+ };
3030
+ var resolvesOwnRange = isAnchoredMode(setting.mode);
3031
+ var hasInvertedRange = !isValidAnimationLength(setting, dateUtils.utc(referenceTimeFromLayer));
3032
+ var hasTooManySteps = resolvesOwnRange && !hasInvertedRange && !isWithinAnimationStepLimit(setting, timeStep);
3033
+ var hasRangeError = hasInvertedRange || hasTooManySteps;
3034
+ var rangeError = function () {
3035
+ if (hasInvertedRange) {
3036
+ return t('timeslider-start-before-end');
3037
+ }
3038
+ if (hasTooManySteps) {
3039
+ return t('timeslider-animation-too-many-steps');
3040
+ }
3041
+ return ' ';
3042
+ }();
3043
+ var isModeDisabled = function isModeDisabled(mode) {
3044
+ return disabled || mode === AnimationLengthMode.Auto && isAutoDisabled || mode === AnimationLengthMode.ReferenceTime && !referenceTimeFromLayer;
3045
+ };
3046
+ var describedAnimationLength = animationStartTime && animationEndTime ? minutesToDescribedDuration(dateUtils.differenceInMinutes(dateUtils.utc(animationEndTime), dateUtils.utc(animationStartTime))) : '';
3047
+ var asDisplayTime = function asDisplayTime(time) {
3048
+ return time ? "" + dateUtils.dateToString(dateUtils.utc(time), dateUtils.DATE_FORMAT_DATEPICKER, true) : '';
3049
+ };
3050
+ /* The surrounding Menu dismisses itself on Tab; keep it open so focus can reach the next field. */
3051
+ var keepMenuOpenOnTab = function keepMenuOpenOnTab(event) {
3052
+ if (event.key === 'Tab') {
3053
+ event.stopPropagation();
3054
+ }
3055
+ };
3056
+ var isSteppingExactTimeRef = React.useRef(false);
3057
+ var handleExactTimeKeyDown = function handleExactTimeKeyDown(event) {
3058
+ isSteppingExactTimeRef.current = event.key === 'ArrowUp' || event.key === 'ArrowDown';
3059
+ };
3060
+ /* Typing walks through incomplete dates, so only a whole one is worth reporting. */
3061
+ var changeExactStartTime = function changeExactStartTime(date) {
3062
+ if (setting.mode !== AnimationLengthMode.Exact || !date) {
3063
+ return;
3064
+ }
3065
+ var isStep = isSteppingExactTimeRef.current;
3066
+ isSteppingExactTimeRef.current = false;
3067
+ onChange(Object.assign({}, setting, {
3068
+ exact: Object.assign({}, setting.exact, {
3069
+ animationStartTime: toExactAnimationTime(date)
3070
+ })
3071
+ }), isStep);
3072
+ };
3073
+ var changeExactEndTime = function changeExactEndTime(date) {
3074
+ if (setting.mode !== AnimationLengthMode.Exact || !date) {
3075
+ return;
3076
+ }
3077
+ var isStep = isSteppingExactTimeRef.current;
3078
+ isSteppingExactTimeRef.current = false;
3079
+ onChange(Object.assign({}, setting, {
3080
+ exact: Object.assign({}, setting.exact, {
3081
+ animationEndTime: toExactAnimationTime(date)
3082
+ })
3083
+ }), isStep);
3084
+ };
3085
+ return jsxs(Box, {
3086
+ onKeyDown: keepMenuOpenOnTab,
3087
+ sx: styles$1.menu,
3088
+ children: [jsx(Typography, {
3089
+ sx: styles$1.sectionTitle,
3090
+ children: t('timeslider-animation-length')
3091
+ }), jsx(RadioGroup, {
3092
+ onChange: function onChange(event) {
3093
+ return changeMode(event.target.value);
3094
+ },
3095
+ value: setting.mode,
3096
+ children: selectableModes.map(function (mode) {
3097
+ return jsx(FormControlLabel, {
3098
+ control: jsx(Radio, {
3099
+ size: "small"
3100
+ }),
3101
+ disabled: isModeDisabled(mode),
3102
+ label: t(modeTranslationKey[mode]),
3103
+ sx: styles$1.radioLabel,
3104
+ value: mode
3105
+ }, mode);
3106
+ })
3107
+ }), jsx(Divider, {
3108
+ sx: {
3109
+ marginY: 1
3110
+ }
3111
+ }), setting.mode === AnimationLengthMode.Exact ? jsx(Typography, {
3112
+ sx: styles$1.sectionTitle,
3113
+ children: t('timeslider-start-and-end-time')
3114
+ }) : jsx(Typography, {
3115
+ sx: styles$1.sectionTitle,
3116
+ children: t('timeslider-anchor-time')
3117
+ }), setting.mode === AnimationLengthMode.Auto && jsxs(Box, {
3118
+ children: [jsx(Typography, {
3119
+ sx: styles$1.readOnlyValue,
3120
+ children: autoTimeStepLayerName
3121
+ }), jsx(Typography, {
3122
+ sx: styles$1.caption,
3123
+ children: t('timeslider-auto-animation-length')
3124
+ }), jsx(Typography, {
3125
+ sx: Object.assign({}, styles$1.readOnlyValue, {
3126
+ paddingLeft: 0.5
3127
+ }),
3128
+ children: describedAnimationLength
3129
+ })]
3130
+ }), resolvesOwnRange ? jsxs(Box, {
3131
+ children: [setting.mode === AnimationLengthMode.Now && jsxs(Fragment, {
3132
+ children: [jsx(Typography, {
3133
+ sx: styles$1.caption,
3134
+ children: t('timeslider-date')
3135
+ }), jsxs(Box, {
3136
+ sx: styles$1.anchorRow,
3137
+ children: [jsx(CalendarToday, {}), jsx(Typography, {
3138
+ sx: styles$1.anchorValue,
3139
+ children: t('timeslider-now')
3140
+ }), jsx(Typography, {
3141
+ sx: styles$1.utc,
3142
+ children: "UTC"
3143
+ })]
3144
+ })]
3145
+ }), setting.mode === AnimationLengthMode.RecurringPeriod && jsxs(Box, {
3146
+ sx: styles$1.anchorFields,
3147
+ children: [jsx(AnchorTimeField, {
3148
+ disabled: disabled,
3149
+ label: t('timeslider-time'),
3150
+ onChange: changeAnchorTime,
3151
+ value: setting.recurringPeriod.anchorTime
3152
+ }), jsxs(Box, {
3153
+ children: [jsx(Typography, {
3154
+ sx: styles$1.caption,
3155
+ children: t('timeslider-date')
3156
+ }), jsxs(Box, {
3157
+ sx: styles$1.anchorRow,
3158
+ children: [jsx(CalendarToday, {}), jsx(Typography, {
3159
+ sx: styles$1.anchorValue,
3160
+ children: t('timeslider-today')
3161
+ })]
3162
+ })]
3163
+ })]
3164
+ }), setting.mode === AnimationLengthMode.ReferenceTime && jsxs(Fragment, {
3165
+ children: [jsx(Typography, {
3166
+ sx: styles$1.caption,
3167
+ children: t('timeslider-reference-time')
3168
+ }), jsxs(Box, {
3169
+ sx: styles$1.anchorRow,
3170
+ children: [jsx(CalendarToday, {}), jsx(Typography, {
3171
+ sx: styles$1.readOnlyValue,
3172
+ children: asDisplayTime(referenceTimeFromLayer)
3173
+ }), jsx(Typography, {
3174
+ sx: styles$1.utc,
3175
+ children: "UTC"
3176
+ })]
3177
+ })]
3178
+ }), jsxs(Box, {
3179
+ sx: styles$1.offsets,
3180
+ children: [jsx(NumberWithUnitField, {
3181
+ disabled: disabled,
3182
+ error: hasRangeError,
3183
+ label: t('timeslider-start-time'),
3184
+ maxDigits: OFFSET_MAX_DIGITS,
3185
+ maxMagnitude: maxOffsetByUnit[startOffset.unit],
3186
+ onChange: changeStartOffset,
3187
+ onInputChange: onInputChange,
3188
+ unit: startOffset.unit,
3189
+ unitOptions: unitOptions,
3190
+ value: startOffset.value
3191
+ }), jsx(NumberWithUnitField, {
3192
+ disabled: disabled,
3193
+ error: hasRangeError,
3194
+ label: t('timeslider-end-time'),
3195
+ maxDigits: OFFSET_MAX_DIGITS,
3196
+ maxMagnitude: maxOffsetByUnit[endOffset.unit],
3197
+ onChange: changeEndOffset,
3198
+ onInputChange: onInputChange,
3199
+ unit: endOffset.unit,
3200
+ unitOptions: unitOptions,
3201
+ value: endOffset.value
3202
+ })]
3203
+ })]
3204
+ }) : null, setting.mode === AnimationLengthMode.Exact && jsxs(Box, {
3205
+ sx: styles$1.exact,
3206
+ children: [jsx(DateTimePicker, {
3207
+ label: t('timeslider-start-time'),
3208
+ onChange: changeExactStartTime,
3209
+ slotProps: {
3210
+ textField: {
3211
+ error: hasRangeError,
3212
+ onKeyDown: handleExactTimeKeyDown
3213
+ }
3214
+ },
3215
+ sx: styles$1.dateTimePicker,
3216
+ value: new Date(setting.exact.animationStartTime)
3217
+ }), jsx(DateTimePicker, {
3218
+ label: t('timeslider-end-time'),
3219
+ onChange: changeExactEndTime,
3220
+ slotProps: {
3221
+ textField: {
3222
+ error: hasRangeError,
3223
+ onKeyDown: handleExactTimeKeyDown
3224
+ }
3225
+ },
3226
+ value: new Date(setting.exact.animationEndTime)
3227
+ })]
3228
+ }), jsx(FormHelperText, {
3229
+ "data-testid": "animationLengthRangeError",
3230
+ error: true,
3231
+ sx: hasRangeError ? undefined : styles$1.reservedError,
3232
+ children: rangeError
3233
+ })]
3234
+ });
3235
+ };
3236
+
3237
+ var styles = {
3238
+ button: {
3239
+ padding: '0px',
3240
+ paddingRight: '12px',
3241
+ width: '100%!important',
3242
+ minWidth: '64px',
3243
+ justifyContent: 'space-between'
3244
+ },
3245
+ buttonLabel: {
3246
+ fontSize: 12,
3247
+ fontWeight: 400,
3248
+ textTransform: 'none'
3249
+ }
3250
+ };
3251
+ var asDisplayTime = function asDisplayTime(time) {
3252
+ return time ? dateUtils.dateToString(dateUtils.utc(time), dateUtils.DATE_FORMAT_DATEPICKER) + " UTC" : '';
3253
+ };
3254
+ var AnimationLengthPanel = function AnimationLengthPanel(_ref) {
3255
+ var setting = _ref.setting,
3256
+ onChange = _ref.onChange,
3257
+ onInputChange = _ref.onInputChange,
3258
+ animationStartTime = _ref.animationStartTime,
3259
+ animationEndTime = _ref.animationEndTime,
3260
+ autoTimeStepLayerName = _ref.autoTimeStepLayerName,
3261
+ timeStep = _ref.timeStep,
3262
+ _ref$isAutoDisabled = _ref.isAutoDisabled,
3263
+ isAutoDisabled = _ref$isAutoDisabled === void 0 ? false : _ref$isAutoDisabled,
3264
+ _ref$disabled = _ref.disabled,
3265
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
3266
+ referenceTimeFromLayer = _ref.referenceTimeFromLayer;
3267
+ var _useTimesliderTransla = useTimesliderTranslation(),
3268
+ t = _useTimesliderTransla.t;
3269
+ var _React$useState = React.useState(null),
3270
+ anchorRef = _React$useState[0],
3271
+ setAnchorRef = _React$useState[1];
3272
+ var _React$useState2 = React.useState(false),
3273
+ open = _React$useState2[0],
3274
+ setOpen = _React$useState2[1];
3275
+ var describedAnimationLength = animationStartTime && animationEndTime ? minutesToDescribedDuration(dateUtils.differenceInMinutes(dateUtils.utc(animationEndTime), dateUtils.utc(animationStartTime))) : '';
3276
+ /* Zero has no direction, so it carries no sign. */
3277
+ var asSignedOffsetLabel = function asSignedOffsetLabel(_ref2) {
3278
+ var value = _ref2.value,
3279
+ unit = _ref2.unit;
3280
+ var sign = value === 0 ? '' : (value < 0 ? '−' : '+') + " ";
3281
+ return "" + sign + Math.abs(value) + " " + t(shortUnitTranslationKey[unit]);
3282
+ };
3283
+ var _activeOffsets = activeOffsets(setting),
3284
+ startOffset = _activeOffsets.startOffset,
3285
+ endOffset = _activeOffsets.endOffset;
3286
+ var offsetsLabel = asSignedOffsetLabel(startOffset) + " / " + asSignedOffsetLabel(endOffset);
3287
+ var buttonLabel = function () {
3288
+ switch (setting.mode) {
3289
+ case AnimationLengthMode.Auto:
3290
+ return t('timeslider-auto') + " " + describedAnimationLength;
3291
+ case AnimationLengthMode.Now:
3292
+ return t('timeslider-now') + " " + offsetsLabel;
3293
+ case AnimationLengthMode.RecurringPeriod:
3294
+ return setting.recurringPeriod.anchorTime + " " + offsetsLabel;
3295
+ case AnimationLengthMode.ReferenceTime:
3296
+ return "Ref. " + offsetsLabel;
3297
+ case AnimationLengthMode.Exact:
3298
+ return t('timeslider-animation-length-exact');
3299
+ default:
3300
+ return describedAnimationLength;
3301
+ }
3302
+ }();
3303
+ /* The offsets are counted from an anchor, so the heading names which one. */
3304
+ var tooltipHeading = function () {
3305
+ switch (setting.mode) {
3306
+ case AnimationLengthMode.Now:
3307
+ return t('timeslider-now') + " - " + dateUtils.dateToString(dateUtils.utc(), dateUtils.DATE_FORMAT_HOURS);
3308
+ case AnimationLengthMode.RecurringPeriod:
3309
+ return t('timeslider-recurring-period') + " - " + setting.recurringPeriod.anchorTime;
3310
+ case AnimationLengthMode.ReferenceTime:
3311
+ return "Ref. - " + asDisplayTime(referenceTimeFromLayer);
3312
+ default:
3313
+ return t(modeTranslationKey[setting.mode]);
3314
+ }
3315
+ }();
3316
+ var tooltipTitle = jsxs(Box, {
3317
+ children: [jsx(Typography, {
3318
+ variant: "body2",
3319
+ children: tooltipHeading
3320
+ }), jsx(Typography, {
3321
+ variant: "body2",
3322
+ children: t('timeslider-start-time') + " " + asDisplayTime(animationStartTime)
3323
+ }), jsx(Typography, {
3324
+ variant: "body2",
3325
+ children: t('timeslider-end-time') + " " + asDisplayTime(animationEndTime)
3326
+ })]
3327
+ });
3328
+ return jsxs(Box, {
3329
+ onKeyDown: function onKeyDown(event) {
3330
+ event.stopPropagation();
3331
+ },
3332
+ children: [jsxs(CustomIconButton, {
3333
+ "aria-label": t('timeslider-animation-length'),
3334
+ "data-testid": "animationLengthPanelButton",
3335
+ isSelected: true,
3336
+ onClick: function onClick() {
3337
+ return setOpen(true);
3338
+ },
3339
+ ref: setAnchorRef,
3340
+ sx: styles.button,
3341
+ tooltipProps: {
3342
+ title: tooltipTitle,
3343
+ placement: 'top'
3344
+ },
3345
+ variant: "tool",
3346
+ children: [jsx(Animation, {}), jsx(Typography, {
3347
+ sx: styles.buttonLabel,
3348
+ children: buttonLabel
3349
+ })]
3350
+ }), !!anchorRef && jsx(Menu, {
3351
+ anchorEl: anchorRef,
3352
+ anchorOrigin: {
3353
+ vertical: -15,
3354
+ horizontal: 'center'
3355
+ },
3356
+ onClose: function onClose() {
3357
+ return setOpen(false);
3358
+ },
3359
+ open: open,
3360
+ slotProps: {
3361
+ backdrop: {
3362
+ sx: {
3363
+ backgroundColor: 'transparent'
3364
+ }
3365
+ }
3366
+ },
3367
+ transformOrigin: {
3368
+ vertical: 'bottom',
3369
+ horizontal: 'center'
3370
+ },
3371
+ children: jsx(AnimationLengthMenu, {
3372
+ animationEndTime: animationEndTime,
3373
+ animationStartTime: animationStartTime,
3374
+ autoTimeStepLayerName: autoTimeStepLayerName,
3375
+ disabled: disabled,
3376
+ isAutoDisabled: isAutoDisabled,
3377
+ onChange: onChange,
3378
+ onInputChange: onInputChange,
3379
+ referenceTimeFromLayer: referenceTimeFromLayer,
3380
+ setting: setting,
3381
+ timeStep: timeStep
3382
+ })
3383
+ })]
3384
+ });
3385
+ };
3386
+
2343
3387
  var AutoUpdateButton = function AutoUpdateButton(_ref) {
2344
3388
  var _ref$toggleAutoUpdate = _ref.toggleAutoUpdate,
2345
3389
  toggleAutoUpdate = _ref$toggleAutoUpdate === void 0 ? function () {} : _ref$toggleAutoUpdate,
@@ -2928,6 +3972,14 @@ var OptionsMenu = function OptionsMenu(_ref) {
2928
3972
  animationLengthBtn = _ref.animationLengthBtn;
2929
3973
  return jsxs(Fragment, {
2930
3974
  children: [jsx(Grid, {
3975
+ size: {
3976
+ xs: 'auto'
3977
+ },
3978
+ children: animationLengthBtn || jsx(AnimationLengthButton, {
3979
+ onChangeAnimationLength: function onChangeAnimationLength() {},
3980
+ toggleAnimationLengthAuto: function toggleAnimationLengthAuto() {}
3981
+ })
3982
+ }), jsx(Grid, {
2931
3983
  size: {
2932
3984
  xs: 'auto'
2933
3985
  },
@@ -2939,14 +3991,6 @@ var OptionsMenu = function OptionsMenu(_ref) {
2939
3991
  onToggleTimeSpan: function onToggleTimeSpan() {},
2940
3992
  timeSliderSpan: 0
2941
3993
  })
2942
- }), jsx(Grid, {
2943
- size: {
2944
- xs: 'auto'
2945
- },
2946
- children: animationLengthBtn || jsx(AnimationLengthButton, {
2947
- onChangeAnimationLength: function onChangeAnimationLength() {},
2948
- toggleAnimationLengthAuto: function toggleAnimationLengthAuto() {}
2949
- })
2950
3994
  }), jsx(Grid, {
2951
3995
  size: {
2952
3996
  xs: 'auto'
@@ -3238,18 +4282,6 @@ var renderTimeSliderCurrentTimeBox = function renderTimeSliderCurrentTimeBox(ctx
3238
4282
  };
3239
4283
 
3240
4284
  var _excluded = ["day", "today", "outsideCurrentMonth"];
3241
- var getTimezoneOffsetS = function getTimezoneOffsetS(value) {
3242
- return value.getTimezoneOffset() * 60;
3243
- };
3244
- var toLocalTime = function toLocalTime(dateTime) {
3245
- return dateUtils.fromUnix(dateTime + getTimezoneOffsetS(dateUtils.fromUnix(dateTime)));
3246
- };
3247
- var toUTCTime = function toUTCTime(dateTime) {
3248
- return dateUtils.unix(dateTime) - getTimezoneOffsetS(dateTime);
3249
- };
3250
- var OpenPicker = function OpenPicker() {
3251
- return jsx(CalendarToday, {});
3252
- };
3253
4285
  var enabledAndSelectedButtonStyle = {
3254
4286
  borderWidth: '6px',
3255
4287
  borderBottomStyle: 'solid',
@@ -3301,28 +4333,30 @@ var MarkerTimeSelector = function MarkerTimeSelector(_ref) {
3301
4333
  onCancel = _ref$onCancel === void 0 ? function () {} : _ref$onCancel;
3302
4334
  var _useTimesliderTransla = useTimesliderTranslation(),
3303
4335
  t = _useTimesliderTransla.t;
3304
- var _React$useState2 = React.useState(value ? toLocalTime(value) : null),
3305
- localTimeValue = _React$useState2[0],
3306
- setLocalTimeValue = _React$useState2[1];
4336
+ var _React$useState2 = React.useState(value ? dateUtils.fromUnix(value) : null),
4337
+ utcTimeValue = _React$useState2[0],
4338
+ setUtcTimeValue = _React$useState2[1];
3307
4339
  var _React$useState3 = React.useState(!dataStartTime || !dataEndTime || dataStartTime > dataEndTime),
3308
4340
  isUndefinedDateRange = _React$useState3[0],
3309
4341
  setIsUndefinedDateRange = _React$useState3[1];
3310
4342
  var isDateRangeDisabled = React.useCallback(function (date) {
3311
- if (dataStartTime === undefined || dataEndTime === undefined || dataStartTime > dataEndTime) {
4343
+ if (!date || dataStartTime === undefined || dataEndTime === undefined || dataStartTime > dataEndTime) {
3312
4344
  return true;
3313
4345
  }
3314
- var startOfFirstDay = dateUtils.fromUnix(dataStartTime);
3315
- startOfFirstDay.setHours(0, 0, 0);
3316
- var endOfLastDay = dateUtils.fromUnix(dataEndTime);
3317
- var day = dateUtils.unix(date);
3318
- return day < dateUtils.unix(startOfFirstDay) || day > dateUtils.unix(endOfLastDay);
4346
+ var asUtcDay = function asUtcDay(value) {
4347
+ return Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());
4348
+ };
4349
+ var firstDay = asUtcDay(dateUtils.fromUnix(dataStartTime));
4350
+ var lastDay = asUtcDay(dateUtils.fromUnix(dataEndTime));
4351
+ var day = asUtcDay(date);
4352
+ return day < firstDay || day > lastDay;
3319
4353
  }, [dataStartTime, dataEndTime]);
3320
- var _React$useState4 = React.useState(isDateRangeDisabled(localTimeValue)),
4354
+ var _React$useState4 = React.useState(isDateRangeDisabled(utcTimeValue)),
3321
4355
  isDisabledRange = _React$useState4[0],
3322
4356
  setIsDisabledRange = _React$useState4[1];
3323
4357
  var handleSelect = function handleSelect() {
3324
- if (localTimeValue) {
3325
- onSelect(toUTCTime(localTimeValue));
4358
+ if (utcTimeValue) {
4359
+ onSelect(dateUtils.unix(utcTimeValue));
3326
4360
  }
3327
4361
  };
3328
4362
  var handleKeyDown = function handleKeyDown(event) {
@@ -3337,16 +4371,16 @@ var MarkerTimeSelector = function MarkerTimeSelector(_ref) {
3337
4371
  };
3338
4372
  var handleDateChange = function handleDateChange(value) {
3339
4373
  if (value instanceof Date || value === null || isDisabledDateWithSomeAvailableData()) {
3340
- setLocalTimeValue(value);
4374
+ setUtcTimeValue(value);
3341
4375
  }
3342
4376
  };
3343
4377
  var AvailableDay = function AvailableDay(props) {
3344
- return AvailableDayByTimeRange(props, isDateRangeDisabled(props.day));
4378
+ return AvailableDayByTimeRange(props, isDateRangeDisabled(pickerDateToUTC(props.day)));
3345
4379
  };
3346
4380
  React.useEffect(function () {
3347
4381
  setIsUndefinedDateRange(!dataStartTime || !dataEndTime || dataStartTime > dataEndTime);
3348
- setIsDisabledRange(isDateRangeDisabled(localTimeValue));
3349
- }, [dataStartTime, dataEndTime, localTimeValue, isDateRangeDisabled]);
4382
+ setIsDisabledRange(isDateRangeDisabled(utcTimeValue));
4383
+ }, [dataStartTime, dataEndTime, utcTimeValue, isDateRangeDisabled]);
3350
4384
  return jsx(Paper, {
3351
4385
  sx: {
3352
4386
  borderRadius: '0px',
@@ -3380,59 +4414,33 @@ var MarkerTimeSelector = function MarkerTimeSelector(_ref) {
3380
4414
  },
3381
4415
  children: t('timeslider-marker')
3382
4416
  })
3383
- }), jsx(LocalizationProvider, {
3384
- dateAdapter: AdapterDateFns,
3385
- children: jsx(DateTimePicker, {
3386
- ampm: false,
3387
- autoFocus: true,
3388
- closeOnSelect: false,
3389
- desktopModeMediaQuery: "@media (min-width: 720px)",
3390
- disableIgnoringDatePartForTimeValidation: true,
3391
- format: format,
3392
- label: t('timeslider-marker-label'),
3393
- maxDateTime: isUndefinedDateRange ? undefined : toLocalTime(dataEndTime),
3394
- minDateTime: isUndefinedDateRange ? undefined : toLocalTime(dataStartTime),
3395
- onChange: handleDateChange,
3396
- onClose: handleSelect,
3397
- shouldDisableDate: isDisabledDateWithSomeAvailableData,
3398
- slotProps: {
3399
- textField: {
3400
- variant: 'filled',
3401
- endAdornment: jsx(InputAdornment, {
3402
- position: "end",
3403
- sx: {
3404
- paddingTop: '16px'
3405
- },
3406
- children: "UTC"
3407
- })
3408
- },
3409
- field: {
3410
- onKeyDownCapture: handleKeyDown,
3411
- openPickerButtonPosition: 'start'
3412
- },
3413
- openPickerButton: {
3414
- size: 'small',
3415
- sx: {
3416
- padding: 0
3417
- }
3418
- }
3419
- },
3420
- slots: {
3421
- openPickerIcon: OpenPicker,
3422
- day: AvailableDay
3423
- },
3424
- sx: {
3425
- marginTop: '8px',
3426
- marginBottom: '8px',
3427
- marginLeft: '8px',
3428
- marginRight: '8px',
3429
- borderRadius: '0px'
3430
- },
3431
- timeSteps: {
3432
- minutes: 1
3433
- },
3434
- value: localTimeValue
3435
- })
4417
+ }), jsx(DateTimePicker, {
4418
+ autoFocus: true,
4419
+ closeOnSelect: false,
4420
+ disableIgnoringDatePartForTimeValidation: true,
4421
+ format: format,
4422
+ label: t('timeslider-marker-label'),
4423
+ maxDateTime: isUndefinedDateRange ? undefined : dateUtils.fromUnix(dataEndTime),
4424
+ minDateTime: isUndefinedDateRange ? undefined : dateUtils.fromUnix(dataStartTime),
4425
+ onChange: handleDateChange,
4426
+ onClose: handleSelect,
4427
+ shouldDisableDate: isDisabledDateWithSomeAvailableData,
4428
+ slotProps: {
4429
+ field: {
4430
+ onKeyDownCapture: handleKeyDown
4431
+ }
4432
+ },
4433
+ slots: {
4434
+ day: AvailableDay
4435
+ },
4436
+ sx: {
4437
+ marginTop: '8px',
4438
+ marginBottom: '8px',
4439
+ marginLeft: '8px',
4440
+ marginRight: '8px',
4441
+ borderRadius: '0px'
4442
+ },
4443
+ value: utcTimeValue
3436
4444
  })]
3437
4445
  })
3438
4446
  });
@@ -3688,4 +4696,4 @@ var DemoWrapper = function DemoWrapper(_ref2) {
3688
4696
  });
3689
4697
  };
3690
4698
 
3691
- export { AUTO_MOVE_AREA_PADDING, AnimationLength, AnimationLengthButton, AutoUpdateButton, _BackwardForwardStepButton as BackwardForwardStepButton, ControlButtons, DRAG_AREA_WIDTH, DemoWrapper, HideSliderButton, NowButton, OptionsMenu, OptionsMenuButton, PlayButton, Scale, SpeedButton, TIME_SLIDER_LEGEND_HEIGHT, TIME_SLIDER_NAMESPACE, TimeInMinutes, TimeSlider, TimeSliderButtons, TimeSliderCurrentTimeBox, TimeSliderLegend, TimeSliderMenu, TimeSpanButton, _TimeStepButton as TimeStepButton, calculateMouseTimeAndCheckBounds, convertStringTimeToUnix, defaultAnimationDelayAtStart, defaultDelay, defaultSecondsPerPx, defaultTimeSpan, defaultTimeStep, getAutoMoveAreaWidth, getFilteredTime, getFundamentalScale, getLargestTimeUnit, getNewCenterOfFixedPointZoom, getPixelsBetweenViewportAndTimesliderOnLeft, getPositions, getScaleFromSpan, getSpeedDelay, getTimeBoxWidth, getTimeSliderLegendElement, getTimeSliderLegendId, handleSetNowEvent, isDraggingEndWithinBounds, isDraggingStartWithinBounds, isInsideAnimationArea, isLeftAnimationIconArea, isRightAnimationIconArea, isSelectedTimeIconArea, marks$1 as marks, minutesToDescribedDuration, moveRelativeToTimePoint, moveSelectedTimePx, onsetNewDateDebounced, pixelToTimestamp, roundWithTimeStep, scaleToSecondsPerPx, scalingCoefficient, secondsPerPxFromCanvasWidth, secondsPerPxToScale, secondsPerPxValues, setNextTimeStep, setPreviousTimeStep, spanToScale, speedFactors, timeBoxGeom, timeSliderLegendDefaultProps, timeSliderUtils, timeValues, timesliderTranslations, timestampToPixel, timestampToPixelEdges, useCanvasTarget };
4699
+ export { ANCHOR_MINUTE_STEP, AUTO_MOVE_AREA_PADDING, AnchorTimeField, AnimationLength, AnimationLengthButton, AnimationLengthMenu, AnimationLengthMode, AnimationLengthPanel, AutoUpdateButton, _BackwardForwardStepButton as BackwardForwardStepButton, ControlButtons, DRAG_AREA_WIDTH, DemoWrapper, HideSliderButton, MAX_ANIMATION_STEPS, NowButton, OptionsMenu, OptionsMenuButton, PlayButton, Scale, SpeedButton, TIME_SLIDER_LEGEND_HEIGHT, TIME_SLIDER_NAMESPACE, TimeInMinutes, TimeSlider, TimeSliderButtons, TimeSliderCurrentTimeBox, TimeSliderLegend, TimeSliderMenu, TimeSpanButton, _TimeStepButton as TimeStepButton, activeOffsets, anchorTimeToPickerDate, asDisplayTime, calculateMouseTimeAndCheckBounds, convertStringTimeToUnix, defaultAnimationDelayAtStart, defaultDelay, defaultEndOffset, defaultExactSelections, defaultOffsetSelections, defaultRecurringPeriodSelections, defaultSecondsPerPx, defaultStartOffset, defaultTimeSpan, defaultTimeStep, exactAnimationLengthFrom, getAnimationLengthFromRange, getAutoMoveAreaWidth, getFilteredTime, getFundamentalScale, getLargestTimeUnit, getNewCenterOfFixedPointZoom, getPixelsBetweenViewportAndTimesliderOnLeft, getPositions, getScaleFromSpan, getSpeedDelay, getTimeBoxWidth, getTimeSliderLegendElement, getTimeSliderLegendId, handleSetNowEvent, isAnchoredMode, isDraggingEndWithinBounds, isDraggingStartWithinBounds, isInsideAnimationArea, isLeftAnimationIconArea, isRecurringPeriodMode, isRightAnimationIconArea, isSelectedTimeIconArea, isValidAnchorTime, isValidAnimationLength, isWithinAnimationStepLimit, marks$1 as marks, minutesToDescribedDuration, modeTranslationKey, moveRelativeToTimePoint, moveSelectedTimePx, onsetNewDateDebounced, pickerDateToAnchorTime, pixelToTimestamp, resolveAnchorInstant, resolveAnimationRange, roundWithTimeStep, scaleToSecondsPerPx, scalingCoefficient, secondsPerPxFromCanvasWidth, secondsPerPxToScale, secondsPerPxValues, setNextTimeStep, setPreviousTimeStep, settingRange, shortUnitTranslationKey, spanToScale, speedFactors, timeBoxGeom, timeSliderLegendDefaultProps, timeSliderUtils, timeUnits, timeValues, timesliderTranslations, timestampToPixel, timestampToPixelEdges, toAnchorTime, toExactAnimationTime, unitTranslationKey, useCanvasTarget, withModeSelections };