@kalyx/react 0.2.2 → 0.4.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/CHANGELOG.md +45 -0
- package/dist/index.cjs +330 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -5
- package/dist/index.d.ts +42 -5
- package/dist/index.js +331 -269
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, forwardRef, useState, useCallback, useContext, useId, useRef, useMemo, useEffect } from 'react';
|
|
2
|
-
import { parseInputValue, formatTimeString, parseTimeString, getTime, DateFnsAdapter, getMonthName, getWeekdayNames, getCalendarDays, formatMonthYear,
|
|
2
|
+
import { parseInputValue, formatTimeString, parseTimeString, getTimeInTimezone, getTime, DateFnsAdapter, DEFAULT_DATEPICKER_LABELS, civilMidnightFromUtcDay, getMonthName, getWeekdayNames, getCalendarDays, formatMonthYear, isDateDisabled, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, setTimeInTimezone, setTime, to12Hour, to24Hour, generateMinutes, generateHours, formatFullDate } from '@kalyx/core';
|
|
3
3
|
export { DateFnsAdapter } from '@kalyx/core';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
import { useFloating, autoUpdate, offset, flip, shift } from '@floating-ui/react';
|
|
@@ -29,7 +29,9 @@ function DatePickerRoot({
|
|
|
29
29
|
weekStartsOn = 0,
|
|
30
30
|
displayFormat = "yyyy-MM-dd",
|
|
31
31
|
locale = "en-US",
|
|
32
|
+
displayTimezone,
|
|
32
33
|
adapter = DateFnsAdapter,
|
|
34
|
+
labels: labelsProp,
|
|
33
35
|
children
|
|
34
36
|
}) {
|
|
35
37
|
const pickerId = useId();
|
|
@@ -41,31 +43,39 @@ function DatePickerRoot({
|
|
|
41
43
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
42
44
|
const [isOpen, setIsOpen] = useState(false);
|
|
43
45
|
const [viewMonth, setViewMonth] = useState(
|
|
44
|
-
currentValue ?? adapter.today()
|
|
46
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
45
47
|
);
|
|
46
48
|
const [focusedDate, setFocusedDate] = useState(
|
|
47
|
-
currentValue ?? adapter.today()
|
|
49
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
50
|
+
);
|
|
51
|
+
const mergedLabels = useMemo(
|
|
52
|
+
() => ({ ...DEFAULT_DATEPICKER_LABELS, ...labelsProp }),
|
|
53
|
+
[labelsProp]
|
|
48
54
|
);
|
|
49
55
|
const isDisabled = typeof disabled === "boolean" ? disabled : false;
|
|
50
|
-
const disabledRules =
|
|
56
|
+
const disabledRules = useMemo(
|
|
57
|
+
() => Array.isArray(disabled) ? disabled : [],
|
|
58
|
+
[disabled]
|
|
59
|
+
);
|
|
51
60
|
const selectDate = useCallback(
|
|
52
61
|
(iso) => {
|
|
53
62
|
if (isDisabled || readOnly) return;
|
|
63
|
+
const normalized = iso && displayTimezone ? civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
54
64
|
if (!isControlled) {
|
|
55
|
-
setUncontrolledValue(
|
|
65
|
+
setUncontrolledValue(normalized);
|
|
56
66
|
}
|
|
57
|
-
onChange?.(
|
|
67
|
+
onChange?.(normalized);
|
|
58
68
|
setIsOpen(false);
|
|
59
69
|
},
|
|
60
|
-
[isControlled, isDisabled, readOnly, onChange]
|
|
70
|
+
[isControlled, isDisabled, readOnly, onChange, displayTimezone]
|
|
61
71
|
);
|
|
62
72
|
const open = useCallback(() => {
|
|
63
73
|
if (isDisabled || readOnly) return;
|
|
64
74
|
setIsOpen(true);
|
|
65
|
-
const target = currentValue ?? adapter.today();
|
|
75
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
66
76
|
setViewMonth(target);
|
|
67
77
|
setFocusedDate(target);
|
|
68
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
78
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
69
79
|
const close = useCallback(() => {
|
|
70
80
|
setIsOpen(false);
|
|
71
81
|
}, []);
|
|
@@ -94,9 +104,11 @@ function DatePickerRoot({
|
|
|
94
104
|
weekStartsOn,
|
|
95
105
|
displayFormat,
|
|
96
106
|
locale,
|
|
107
|
+
displayTimezone,
|
|
97
108
|
isDisabled,
|
|
98
109
|
isReadOnly: readOnly,
|
|
99
|
-
pickerId
|
|
110
|
+
pickerId,
|
|
111
|
+
labels: mergedLabels
|
|
100
112
|
}),
|
|
101
113
|
[
|
|
102
114
|
currentValue,
|
|
@@ -112,30 +124,40 @@ function DatePickerRoot({
|
|
|
112
124
|
weekStartsOn,
|
|
113
125
|
displayFormat,
|
|
114
126
|
locale,
|
|
127
|
+
displayTimezone,
|
|
115
128
|
isDisabled,
|
|
116
129
|
readOnly,
|
|
117
|
-
pickerId
|
|
130
|
+
pickerId,
|
|
131
|
+
mergedLabels
|
|
118
132
|
]
|
|
119
133
|
);
|
|
120
134
|
return /* @__PURE__ */ jsx(DatePickerContext.Provider, { value: contextValue, children });
|
|
121
135
|
}
|
|
122
136
|
var DatePickerInput = forwardRef(
|
|
123
|
-
function DatePickerInput2({ format: formatProp,
|
|
137
|
+
function DatePickerInput2({ format: formatProp, onClick, onBlur, onKeyDown, ...props }, ref) {
|
|
124
138
|
const ctx = useDatePickerContext("DatePicker.Input");
|
|
125
139
|
const displayFormat = formatProp ?? ctx.displayFormat;
|
|
126
140
|
const [inputText, setInputText] = useState(null);
|
|
127
|
-
|
|
128
|
-
|
|
141
|
+
let formattedValue = "";
|
|
142
|
+
if (ctx.value) {
|
|
143
|
+
try {
|
|
144
|
+
formattedValue = ctx.adapter.format(ctx.value, displayFormat, ctx.displayTimezone);
|
|
145
|
+
} catch {
|
|
146
|
+
formattedValue = ctx.value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const displayValue = inputText !== null ? inputText : formattedValue;
|
|
150
|
+
const handleClick = useCallback(
|
|
129
151
|
(e) => {
|
|
130
|
-
ctx.open();
|
|
131
|
-
|
|
152
|
+
if (!ctx.isOpen) ctx.open();
|
|
153
|
+
onClick?.(e);
|
|
132
154
|
},
|
|
133
|
-
[ctx,
|
|
155
|
+
[ctx, onClick]
|
|
134
156
|
);
|
|
135
157
|
const handleBlur = useCallback(
|
|
136
158
|
(e) => {
|
|
137
159
|
if (inputText !== null) {
|
|
138
|
-
const parsed = parseInputValue(inputText,
|
|
160
|
+
const parsed = parseInputValue(inputText, ctx.adapter);
|
|
139
161
|
if (parsed) {
|
|
140
162
|
ctx.selectDate(parsed);
|
|
141
163
|
}
|
|
@@ -154,7 +176,7 @@ var DatePickerInput = forwardRef(
|
|
|
154
176
|
setInputText(null);
|
|
155
177
|
return;
|
|
156
178
|
}
|
|
157
|
-
const parsed = parseInputValue(text,
|
|
179
|
+
const parsed = parseInputValue(text, ctx.adapter);
|
|
158
180
|
if (parsed) {
|
|
159
181
|
ctx.selectDate(parsed);
|
|
160
182
|
setInputText(null);
|
|
@@ -168,7 +190,7 @@ var DatePickerInput = forwardRef(
|
|
|
168
190
|
ctx.close();
|
|
169
191
|
} else if (e.key === "Enter") {
|
|
170
192
|
if (inputText !== null) {
|
|
171
|
-
const parsed = parseInputValue(inputText,
|
|
193
|
+
const parsed = parseInputValue(inputText, ctx.adapter);
|
|
172
194
|
if (parsed) {
|
|
173
195
|
ctx.selectDate(parsed);
|
|
174
196
|
setInputText(null);
|
|
@@ -202,7 +224,7 @@ var DatePickerInput = forwardRef(
|
|
|
202
224
|
disabled: ctx.isDisabled || props.disabled,
|
|
203
225
|
readOnly: ctx.isReadOnly,
|
|
204
226
|
onChange: handleChange,
|
|
205
|
-
|
|
227
|
+
onClick: handleClick,
|
|
206
228
|
onBlur: handleBlur,
|
|
207
229
|
onKeyDown: handleKeyDown,
|
|
208
230
|
...props
|
|
@@ -231,7 +253,7 @@ var DatePickerTrigger = forwardRef(
|
|
|
231
253
|
},
|
|
232
254
|
type: "button",
|
|
233
255
|
tabIndex: 0,
|
|
234
|
-
"aria-label": ctx.isOpen ?
|
|
256
|
+
"aria-label": ctx.isOpen ? ctx.labels.triggerClose : ctx.labels.triggerOpen,
|
|
235
257
|
"aria-expanded": ctx.isOpen,
|
|
236
258
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
237
259
|
disabled: ctx.isDisabled || props.disabled,
|
|
@@ -263,38 +285,39 @@ var DatePickerTrigger = forwardRef(
|
|
|
263
285
|
);
|
|
264
286
|
}
|
|
265
287
|
);
|
|
266
|
-
function
|
|
267
|
-
const ctx = useDatePickerContext("DatePicker.Popover");
|
|
268
|
-
const calendarId = `${ctx.pickerId}-calendar`;
|
|
288
|
+
function usePopover({ isOpen, close, referenceRef, placement = "bottom-start" }) {
|
|
269
289
|
const floatingRef = useRef(null);
|
|
290
|
+
const previousFocusRef = useRef(null);
|
|
270
291
|
const { refs, floatingStyles } = useFloating({
|
|
271
|
-
open:
|
|
272
|
-
placement
|
|
292
|
+
open: isOpen,
|
|
293
|
+
placement,
|
|
273
294
|
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
274
295
|
whileElementsMounted: autoUpdate
|
|
275
296
|
});
|
|
276
297
|
useEffect(() => {
|
|
277
|
-
if (
|
|
278
|
-
refs.setReference(
|
|
298
|
+
if (referenceRef.current) {
|
|
299
|
+
refs.setReference(referenceRef.current);
|
|
279
300
|
}
|
|
280
|
-
}, [
|
|
281
|
-
const previousFocusRef = useRef(null);
|
|
301
|
+
}, [referenceRef, refs, isOpen]);
|
|
282
302
|
useEffect(() => {
|
|
283
|
-
if (
|
|
303
|
+
if (isOpen) {
|
|
284
304
|
previousFocusRef.current = document.activeElement;
|
|
285
305
|
} else if (previousFocusRef.current) {
|
|
286
|
-
previousFocusRef.current
|
|
306
|
+
const el = previousFocusRef.current;
|
|
287
307
|
previousFocusRef.current = null;
|
|
308
|
+
if (el !== referenceRef.current && typeof el.focus === "function") {
|
|
309
|
+
el.focus({ preventScroll: true });
|
|
310
|
+
}
|
|
288
311
|
}
|
|
289
|
-
}, [
|
|
312
|
+
}, [isOpen, referenceRef]);
|
|
290
313
|
useEffect(() => {
|
|
291
|
-
if (!
|
|
314
|
+
if (!isOpen) return;
|
|
292
315
|
function handleClickOutside(e) {
|
|
293
316
|
const floating = floatingRef.current;
|
|
294
|
-
const reference =
|
|
317
|
+
const reference = referenceRef.current;
|
|
295
318
|
const target = e.target;
|
|
296
319
|
if (floating && !floating.contains(target) && (!reference || !reference.contains(target))) {
|
|
297
|
-
|
|
320
|
+
close();
|
|
298
321
|
}
|
|
299
322
|
}
|
|
300
323
|
const timer = setTimeout(() => {
|
|
@@ -304,28 +327,39 @@ function DatePickerPopover({ children, ...props }) {
|
|
|
304
327
|
clearTimeout(timer);
|
|
305
328
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
306
329
|
};
|
|
307
|
-
}, [
|
|
330
|
+
}, [isOpen, close, referenceRef]);
|
|
308
331
|
useEffect(() => {
|
|
309
|
-
if (!
|
|
332
|
+
if (!isOpen) return;
|
|
310
333
|
function handleKeyDown(e) {
|
|
311
334
|
if (e.key === "Escape") {
|
|
312
|
-
|
|
335
|
+
close();
|
|
313
336
|
}
|
|
314
337
|
}
|
|
315
338
|
document.addEventListener("keydown", handleKeyDown);
|
|
316
339
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
317
|
-
}, [
|
|
340
|
+
}, [isOpen, close]);
|
|
341
|
+
const setFloatingRef = (node) => {
|
|
342
|
+
floatingRef.current = node;
|
|
343
|
+
refs.setFloating(node);
|
|
344
|
+
};
|
|
345
|
+
return { floatingStyles, setFloatingRef };
|
|
346
|
+
}
|
|
347
|
+
function DatePickerPopover({ children, ...props }) {
|
|
348
|
+
const ctx = useDatePickerContext("DatePicker.Popover");
|
|
349
|
+
const calendarId = `${ctx.pickerId}-calendar`;
|
|
350
|
+
const { floatingStyles, setFloatingRef } = usePopover({
|
|
351
|
+
isOpen: ctx.isOpen,
|
|
352
|
+
close: ctx.close,
|
|
353
|
+
referenceRef: ctx.referenceRef
|
|
354
|
+
});
|
|
318
355
|
if (!ctx.isOpen) return null;
|
|
319
356
|
return /* @__PURE__ */ jsx(
|
|
320
357
|
"div",
|
|
321
358
|
{
|
|
322
|
-
ref:
|
|
323
|
-
floatingRef.current = node;
|
|
324
|
-
refs.setFloating(node);
|
|
325
|
-
},
|
|
359
|
+
ref: setFloatingRef,
|
|
326
360
|
id: calendarId,
|
|
327
361
|
role: "dialog",
|
|
328
|
-
"aria-label":
|
|
362
|
+
"aria-label": ctx.labels.popoverLabel,
|
|
329
363
|
"aria-modal": "false",
|
|
330
364
|
style: floatingStyles,
|
|
331
365
|
...props,
|
|
@@ -333,6 +367,13 @@ function DatePickerPopover({ children, ...props }) {
|
|
|
333
367
|
}
|
|
334
368
|
);
|
|
335
369
|
}
|
|
370
|
+
function safeFormatFullDate(iso, locale) {
|
|
371
|
+
try {
|
|
372
|
+
return formatFullDate(iso, locale);
|
|
373
|
+
} catch {
|
|
374
|
+
return iso;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
336
377
|
var srOnly = {
|
|
337
378
|
position: "absolute",
|
|
338
379
|
width: "1px",
|
|
@@ -348,13 +389,14 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
348
389
|
const ctx = useDatePickerContext("DatePicker.Calendar");
|
|
349
390
|
const gridRef = useRef(null);
|
|
350
391
|
const [announcement, setAnnouncement] = useState("");
|
|
351
|
-
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale } = ctx;
|
|
392
|
+
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale, displayTimezone } = ctx;
|
|
352
393
|
const weekdays = getWeekdayNames(locale, weekStartsOn);
|
|
353
394
|
const weeks = getCalendarDays(viewMonth, adapter, {
|
|
354
395
|
weekStartsOn,
|
|
355
396
|
selected: ctx.value,
|
|
356
397
|
focusedDate,
|
|
357
|
-
disabled
|
|
398
|
+
disabled,
|
|
399
|
+
timezone: displayTimezone
|
|
358
400
|
});
|
|
359
401
|
const year = adapter.getYear(viewMonth);
|
|
360
402
|
const month = adapter.getMonth(viewMonth);
|
|
@@ -364,7 +406,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
364
406
|
const focusedButton = gridRef.current.querySelector(
|
|
365
407
|
'[data-focused="true"]'
|
|
366
408
|
);
|
|
367
|
-
focusedButton?.focus();
|
|
409
|
+
focusedButton?.focus({ preventScroll: true });
|
|
368
410
|
}, [focusedDate, ctx.isOpen]);
|
|
369
411
|
const navigateMonth = useCallback(
|
|
370
412
|
(direction) => {
|
|
@@ -381,7 +423,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
381
423
|
(day) => {
|
|
382
424
|
if (day.isDisabled) return;
|
|
383
425
|
ctx.selectDate(day.isoString);
|
|
384
|
-
setAnnouncement(
|
|
426
|
+
setAnnouncement(safeFormatFullDate(day.isoString, locale));
|
|
385
427
|
},
|
|
386
428
|
[ctx, locale]
|
|
387
429
|
);
|
|
@@ -453,7 +495,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
453
495
|
type: "button",
|
|
454
496
|
className: classNames?.navButton,
|
|
455
497
|
onClick: () => navigateMonth(-1),
|
|
456
|
-
"aria-label":
|
|
498
|
+
"aria-label": ctx.labels.prevMonth,
|
|
457
499
|
children: "<"
|
|
458
500
|
}
|
|
459
501
|
),
|
|
@@ -473,7 +515,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
473
515
|
type: "button",
|
|
474
516
|
className: classNames?.navButton,
|
|
475
517
|
onClick: () => navigateMonth(1),
|
|
476
|
-
"aria-label":
|
|
518
|
+
"aria-label": ctx.labels.nextMonth,
|
|
477
519
|
children: ">"
|
|
478
520
|
}
|
|
479
521
|
)
|
|
@@ -526,7 +568,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
526
568
|
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
527
569
|
className: dayClasses,
|
|
528
570
|
onClick: () => handleDayClick(day),
|
|
529
|
-
"aria-label":
|
|
571
|
+
"aria-label": safeFormatFullDate(day.isoString, locale),
|
|
530
572
|
children: day.dayNumber
|
|
531
573
|
}
|
|
532
574
|
)
|
|
@@ -582,7 +624,7 @@ function DatePickerMonthGrid({
|
|
|
582
624
|
type: "button",
|
|
583
625
|
className: classNames?.navButton,
|
|
584
626
|
onClick: () => navigateYear(-1),
|
|
585
|
-
"aria-label":
|
|
627
|
+
"aria-label": ctx.labels.prevYear,
|
|
586
628
|
children: "<"
|
|
587
629
|
}
|
|
588
630
|
),
|
|
@@ -601,7 +643,7 @@ function DatePickerMonthGrid({
|
|
|
601
643
|
type: "button",
|
|
602
644
|
className: classNames?.navButton,
|
|
603
645
|
onClick: () => navigateYear(1),
|
|
604
|
-
"aria-label":
|
|
646
|
+
"aria-label": ctx.labels.nextYear,
|
|
605
647
|
children: ">"
|
|
606
648
|
}
|
|
607
649
|
)
|
|
@@ -686,7 +728,7 @@ function DatePickerYearGrid({
|
|
|
686
728
|
type: "button",
|
|
687
729
|
className: classNames?.navButton,
|
|
688
730
|
onClick: () => navigateDecade(-1),
|
|
689
|
-
"aria-label":
|
|
731
|
+
"aria-label": ctx.labels.prevDecade,
|
|
690
732
|
children: "<"
|
|
691
733
|
}
|
|
692
734
|
),
|
|
@@ -697,7 +739,7 @@ function DatePickerYearGrid({
|
|
|
697
739
|
type: "button",
|
|
698
740
|
className: classNames?.navButton,
|
|
699
741
|
onClick: () => navigateDecade(1),
|
|
700
|
-
"aria-label":
|
|
742
|
+
"aria-label": ctx.labels.nextDecade,
|
|
701
743
|
children: ">"
|
|
702
744
|
}
|
|
703
745
|
)
|
|
@@ -770,7 +812,9 @@ function RangePickerRoot({
|
|
|
770
812
|
weekStartsOn = 0,
|
|
771
813
|
displayFormat = "yyyy-MM-dd",
|
|
772
814
|
locale = "en-US",
|
|
815
|
+
displayTimezone,
|
|
773
816
|
adapter = DateFnsAdapter,
|
|
817
|
+
labels: labelsProp,
|
|
774
818
|
children
|
|
775
819
|
}) {
|
|
776
820
|
const pickerId = useId();
|
|
@@ -784,13 +828,20 @@ function RangePickerRoot({
|
|
|
784
828
|
const [selectingTarget, setSelectingTarget] = useState("start");
|
|
785
829
|
const [hoverDate, setHoverDate] = useState(null);
|
|
786
830
|
const [viewMonth, setViewMonth] = useState(
|
|
787
|
-
currentValue.start ?? adapter.today()
|
|
831
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
788
832
|
);
|
|
789
833
|
const [focusedDate, setFocusedDate] = useState(
|
|
790
|
-
currentValue.start ?? adapter.today()
|
|
834
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
835
|
+
);
|
|
836
|
+
const mergedLabels = useMemo(
|
|
837
|
+
() => ({ ...DEFAULT_RANGEPICKER_LABELS, ...labelsProp }),
|
|
838
|
+
[labelsProp]
|
|
791
839
|
);
|
|
792
840
|
const isDisabled = typeof disabled === "boolean" ? disabled : false;
|
|
793
|
-
const disabledRules =
|
|
841
|
+
const disabledRules = useMemo(
|
|
842
|
+
() => Array.isArray(disabled) ? disabled : [],
|
|
843
|
+
[disabled]
|
|
844
|
+
);
|
|
794
845
|
const setRange = useCallback(
|
|
795
846
|
(range) => {
|
|
796
847
|
if (isDisabled || readOnly) return;
|
|
@@ -804,23 +855,24 @@ function RangePickerRoot({
|
|
|
804
855
|
const selectDate = useCallback(
|
|
805
856
|
(iso) => {
|
|
806
857
|
if (isDisabled || readOnly) return;
|
|
858
|
+
const normalized = displayTimezone ? civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
807
859
|
if (selectingTarget === "start") {
|
|
808
|
-
const newRange = { start:
|
|
860
|
+
const newRange = { start: normalized, end: null };
|
|
809
861
|
setRange(newRange);
|
|
810
862
|
setSelectingTarget("end");
|
|
811
863
|
setHoverDate(null);
|
|
812
864
|
} else {
|
|
813
865
|
const start = currentValue.start;
|
|
814
866
|
if (!start) {
|
|
815
|
-
setRange({ start:
|
|
867
|
+
setRange({ start: normalized, end: null });
|
|
816
868
|
setSelectingTarget("end");
|
|
817
869
|
return;
|
|
818
870
|
}
|
|
819
871
|
let newRange;
|
|
820
|
-
if (adapter.isBefore(
|
|
821
|
-
newRange = { start:
|
|
872
|
+
if (adapter.isBefore(normalized, start)) {
|
|
873
|
+
newRange = { start: normalized, end: start };
|
|
822
874
|
} else {
|
|
823
|
-
newRange = { start, end:
|
|
875
|
+
newRange = { start, end: normalized };
|
|
824
876
|
}
|
|
825
877
|
setRange(newRange);
|
|
826
878
|
setSelectingTarget("start");
|
|
@@ -828,18 +880,18 @@ function RangePickerRoot({
|
|
|
828
880
|
setIsOpen(false);
|
|
829
881
|
}
|
|
830
882
|
},
|
|
831
|
-
[isDisabled, readOnly, selectingTarget, currentValue.start, adapter, setRange]
|
|
883
|
+
[isDisabled, readOnly, selectingTarget, currentValue.start, adapter, setRange, displayTimezone]
|
|
832
884
|
);
|
|
833
885
|
const open = useCallback(() => {
|
|
834
886
|
if (isDisabled || readOnly) return;
|
|
835
887
|
setIsOpen(true);
|
|
836
|
-
const target = currentValue.start ?? adapter.today();
|
|
888
|
+
const target = currentValue.start ?? adapter.today(displayTimezone);
|
|
837
889
|
setViewMonth(target);
|
|
838
890
|
setFocusedDate(target);
|
|
839
891
|
if (currentValue.start && currentValue.end) {
|
|
840
892
|
setSelectingTarget("start");
|
|
841
893
|
}
|
|
842
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
894
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
843
895
|
const close = useCallback(() => {
|
|
844
896
|
setIsOpen(false);
|
|
845
897
|
setHoverDate(null);
|
|
@@ -870,9 +922,11 @@ function RangePickerRoot({
|
|
|
870
922
|
weekStartsOn,
|
|
871
923
|
displayFormat,
|
|
872
924
|
locale,
|
|
925
|
+
displayTimezone,
|
|
873
926
|
isDisabled,
|
|
874
927
|
isReadOnly: readOnly,
|
|
875
|
-
pickerId
|
|
928
|
+
pickerId,
|
|
929
|
+
labels: mergedLabels
|
|
876
930
|
}),
|
|
877
931
|
[
|
|
878
932
|
currentValue,
|
|
@@ -891,25 +945,34 @@ function RangePickerRoot({
|
|
|
891
945
|
weekStartsOn,
|
|
892
946
|
displayFormat,
|
|
893
947
|
locale,
|
|
948
|
+
displayTimezone,
|
|
894
949
|
isDisabled,
|
|
895
950
|
readOnly,
|
|
896
|
-
pickerId
|
|
951
|
+
pickerId,
|
|
952
|
+
mergedLabels
|
|
897
953
|
]
|
|
898
954
|
);
|
|
899
955
|
return /* @__PURE__ */ jsx(RangePickerContext.Provider, { value: contextValue, children });
|
|
900
956
|
}
|
|
901
957
|
var RangePickerInput = forwardRef(
|
|
902
|
-
function RangePickerInput2({ part, format: formatProp,
|
|
958
|
+
function RangePickerInput2({ part, format: formatProp, onClick, onKeyDown, ...props }, ref) {
|
|
903
959
|
const ctx = useRangePickerContext("RangePicker.Input");
|
|
904
960
|
const displayFormat = formatProp ?? ctx.displayFormat;
|
|
905
961
|
const value = ctx.value[part];
|
|
906
|
-
|
|
907
|
-
|
|
962
|
+
let displayValue = "";
|
|
963
|
+
if (value) {
|
|
964
|
+
try {
|
|
965
|
+
displayValue = ctx.adapter.format(value, displayFormat, ctx.displayTimezone);
|
|
966
|
+
} catch {
|
|
967
|
+
displayValue = value;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
const handleClick = useCallback(
|
|
908
971
|
(e) => {
|
|
909
|
-
ctx.open();
|
|
910
|
-
|
|
972
|
+
if (!ctx.isOpen) ctx.open();
|
|
973
|
+
onClick?.(e);
|
|
911
974
|
},
|
|
912
|
-
[ctx,
|
|
975
|
+
[ctx, onClick]
|
|
913
976
|
);
|
|
914
977
|
const handleKeyDown = useCallback(
|
|
915
978
|
(e) => {
|
|
@@ -939,11 +1002,11 @@ var RangePickerInput = forwardRef(
|
|
|
939
1002
|
"aria-haspopup": "dialog",
|
|
940
1003
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
941
1004
|
"aria-autocomplete": "none",
|
|
942
|
-
"aria-label": part === "start" ?
|
|
1005
|
+
"aria-label": part === "start" ? ctx.labels.startInput : ctx.labels.endInput,
|
|
943
1006
|
autoComplete: "off",
|
|
944
1007
|
value: displayValue,
|
|
945
1008
|
disabled: ctx.isDisabled || props.disabled,
|
|
946
|
-
|
|
1009
|
+
onClick: handleClick,
|
|
947
1010
|
onKeyDown: handleKeyDown,
|
|
948
1011
|
"data-part": part,
|
|
949
1012
|
...props
|
|
@@ -954,66 +1017,19 @@ var RangePickerInput = forwardRef(
|
|
|
954
1017
|
function RangePickerPopover({ children, ...props }) {
|
|
955
1018
|
const ctx = useRangePickerContext("RangePicker.Popover");
|
|
956
1019
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
957
|
-
const
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
962
|
-
whileElementsMounted: autoUpdate
|
|
1020
|
+
const { floatingStyles, setFloatingRef } = usePopover({
|
|
1021
|
+
isOpen: ctx.isOpen,
|
|
1022
|
+
close: ctx.close,
|
|
1023
|
+
referenceRef: ctx.referenceRef
|
|
963
1024
|
});
|
|
964
|
-
useEffect(() => {
|
|
965
|
-
if (ctx.referenceRef.current) {
|
|
966
|
-
refs.setReference(ctx.referenceRef.current);
|
|
967
|
-
}
|
|
968
|
-
}, [ctx.referenceRef, refs, ctx.isOpen]);
|
|
969
|
-
const previousFocusRef = useRef(null);
|
|
970
|
-
useEffect(() => {
|
|
971
|
-
if (ctx.isOpen) {
|
|
972
|
-
previousFocusRef.current = document.activeElement;
|
|
973
|
-
} else if (previousFocusRef.current) {
|
|
974
|
-
previousFocusRef.current.focus();
|
|
975
|
-
previousFocusRef.current = null;
|
|
976
|
-
}
|
|
977
|
-
}, [ctx.isOpen]);
|
|
978
|
-
useEffect(() => {
|
|
979
|
-
if (!ctx.isOpen) return;
|
|
980
|
-
function handleClickOutside(e) {
|
|
981
|
-
const floating = floatingRef.current;
|
|
982
|
-
const reference = ctx.referenceRef.current;
|
|
983
|
-
const target = e.target;
|
|
984
|
-
if (floating && !floating.contains(target) && (!reference || !reference.contains(target))) {
|
|
985
|
-
ctx.close();
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
const timer = setTimeout(() => {
|
|
989
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
990
|
-
}, 0);
|
|
991
|
-
return () => {
|
|
992
|
-
clearTimeout(timer);
|
|
993
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
994
|
-
};
|
|
995
|
-
}, [ctx.isOpen, ctx]);
|
|
996
|
-
useEffect(() => {
|
|
997
|
-
if (!ctx.isOpen) return;
|
|
998
|
-
function handleKeyDown(e) {
|
|
999
|
-
if (e.key === "Escape") {
|
|
1000
|
-
ctx.close();
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
1004
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1005
|
-
}, [ctx.isOpen, ctx]);
|
|
1006
1025
|
if (!ctx.isOpen) return null;
|
|
1007
1026
|
return /* @__PURE__ */ jsx(
|
|
1008
1027
|
"div",
|
|
1009
1028
|
{
|
|
1010
|
-
ref:
|
|
1011
|
-
floatingRef.current = node;
|
|
1012
|
-
refs.setFloating(node);
|
|
1013
|
-
},
|
|
1029
|
+
ref: setFloatingRef,
|
|
1014
1030
|
id: calendarId,
|
|
1015
1031
|
role: "dialog",
|
|
1016
|
-
"aria-label":
|
|
1032
|
+
"aria-label": ctx.labels.popoverLabel,
|
|
1017
1033
|
"aria-modal": "false",
|
|
1018
1034
|
style: floatingStyles,
|
|
1019
1035
|
...props,
|
|
@@ -1021,6 +1037,13 @@ function RangePickerPopover({ children, ...props }) {
|
|
|
1021
1037
|
}
|
|
1022
1038
|
);
|
|
1023
1039
|
}
|
|
1040
|
+
function safeFormatFullDate2(iso, locale) {
|
|
1041
|
+
try {
|
|
1042
|
+
return formatFullDate(iso, locale);
|
|
1043
|
+
} catch {
|
|
1044
|
+
return iso;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1024
1047
|
var srOnly2 = {
|
|
1025
1048
|
position: "absolute",
|
|
1026
1049
|
width: "1px",
|
|
@@ -1044,7 +1067,8 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1044
1067
|
disabled,
|
|
1045
1068
|
value,
|
|
1046
1069
|
hoverDate,
|
|
1047
|
-
selectingTarget
|
|
1070
|
+
selectingTarget,
|
|
1071
|
+
displayTimezone
|
|
1048
1072
|
} = ctx;
|
|
1049
1073
|
const { locale } = ctx;
|
|
1050
1074
|
const weekdays = getWeekdayNames(locale, weekStartsOn);
|
|
@@ -1053,7 +1077,8 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1053
1077
|
focusedDate,
|
|
1054
1078
|
disabled,
|
|
1055
1079
|
range: value,
|
|
1056
|
-
rangeHover: hoverDate
|
|
1080
|
+
rangeHover: hoverDate,
|
|
1081
|
+
timezone: displayTimezone
|
|
1057
1082
|
});
|
|
1058
1083
|
const year = adapter.getYear(viewMonth);
|
|
1059
1084
|
const month = adapter.getMonth(viewMonth);
|
|
@@ -1063,7 +1088,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1063
1088
|
const focusedButton = gridRef.current.querySelector(
|
|
1064
1089
|
'[data-focused="true"]'
|
|
1065
1090
|
);
|
|
1066
|
-
focusedButton?.focus();
|
|
1091
|
+
focusedButton?.focus({ preventScroll: true });
|
|
1067
1092
|
}, [focusedDate, ctx.isOpen]);
|
|
1068
1093
|
const navigateMonth = useCallback(
|
|
1069
1094
|
(direction) => {
|
|
@@ -1080,7 +1105,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1080
1105
|
(day) => {
|
|
1081
1106
|
if (day.isDisabled) return;
|
|
1082
1107
|
ctx.selectDate(day.isoString);
|
|
1083
|
-
setAnnouncement(
|
|
1108
|
+
setAnnouncement(safeFormatFullDate2(day.isoString, locale));
|
|
1084
1109
|
},
|
|
1085
1110
|
[ctx, locale]
|
|
1086
1111
|
);
|
|
@@ -1157,7 +1182,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1157
1182
|
type: "button",
|
|
1158
1183
|
className: classNames?.navButton,
|
|
1159
1184
|
onClick: () => navigateMonth(-1),
|
|
1160
|
-
"aria-label":
|
|
1185
|
+
"aria-label": ctx.labels.prevMonth,
|
|
1161
1186
|
children: "<"
|
|
1162
1187
|
}
|
|
1163
1188
|
),
|
|
@@ -1168,7 +1193,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1168
1193
|
type: "button",
|
|
1169
1194
|
className: classNames?.navButton,
|
|
1170
1195
|
onClick: () => navigateMonth(1),
|
|
1171
|
-
"aria-label":
|
|
1196
|
+
"aria-label": ctx.labels.nextMonth,
|
|
1172
1197
|
children: ">"
|
|
1173
1198
|
}
|
|
1174
1199
|
)
|
|
@@ -1228,7 +1253,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1228
1253
|
className: dayClasses,
|
|
1229
1254
|
onClick: () => handleDayClick(day),
|
|
1230
1255
|
onMouseEnter: () => handleDayMouseEnter(day),
|
|
1231
|
-
"aria-label":
|
|
1256
|
+
"aria-label": safeFormatFullDate2(day.isoString, locale),
|
|
1232
1257
|
children: day.dayNumber
|
|
1233
1258
|
}
|
|
1234
1259
|
)
|
|
@@ -1243,7 +1268,8 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1243
1268
|
] });
|
|
1244
1269
|
}
|
|
1245
1270
|
function RangePickerPresets({ classNames, children, ...props }) {
|
|
1246
|
-
|
|
1271
|
+
const ctx = useRangePickerContext("RangePicker.Presets");
|
|
1272
|
+
return /* @__PURE__ */ jsx("div", { role: "group", "aria-label": ctx.labels.presetsGroup, className: classNames?.root, ...props, children });
|
|
1247
1273
|
}
|
|
1248
1274
|
function resolvePreset(key, today, adapter) {
|
|
1249
1275
|
switch (key) {
|
|
@@ -1282,8 +1308,9 @@ function resolvePreset(key, today, adapter) {
|
|
|
1282
1308
|
};
|
|
1283
1309
|
}
|
|
1284
1310
|
case "thisYear": {
|
|
1311
|
+
const currentMonth = new Date(today).getUTCMonth();
|
|
1285
1312
|
const yearStart = adapter.startOfMonth(
|
|
1286
|
-
adapter.addMonths(today, -
|
|
1313
|
+
adapter.addMonths(today, -currentMonth)
|
|
1287
1314
|
);
|
|
1288
1315
|
return { start: yearStart, end: today };
|
|
1289
1316
|
}
|
|
@@ -1365,10 +1392,7 @@ function useTimePickerContext(componentName) {
|
|
|
1365
1392
|
return context;
|
|
1366
1393
|
}
|
|
1367
1394
|
function getDefaultIso() {
|
|
1368
|
-
|
|
1369
|
-
return new Date(
|
|
1370
|
-
Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())
|
|
1371
|
-
).toISOString();
|
|
1395
|
+
return DateFnsAdapter.today();
|
|
1372
1396
|
}
|
|
1373
1397
|
function TimePickerRoot({
|
|
1374
1398
|
value: controlledValue,
|
|
@@ -1377,28 +1401,37 @@ function TimePickerRoot({
|
|
|
1377
1401
|
format = "24h",
|
|
1378
1402
|
step = 1,
|
|
1379
1403
|
withSeconds = false,
|
|
1404
|
+
displayTimezone,
|
|
1380
1405
|
disabled = false,
|
|
1381
1406
|
readOnly = false,
|
|
1407
|
+
labels: labelsProp,
|
|
1382
1408
|
children
|
|
1383
1409
|
}) {
|
|
1384
1410
|
const pickerId = useId();
|
|
1411
|
+
const mergedLabels = useMemo(
|
|
1412
|
+
() => ({ ...DEFAULT_TIMEPICKER_LABELS, ...labelsProp }),
|
|
1413
|
+
[labelsProp]
|
|
1414
|
+
);
|
|
1385
1415
|
const isControlled = useRef(controlledValue !== void 0).current;
|
|
1386
1416
|
const [uncontrolledValue, setUncontrolledValue] = useState(
|
|
1387
1417
|
defaultValue ?? null
|
|
1388
1418
|
);
|
|
1389
1419
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1390
1420
|
const baseIso = currentValue ?? getDefaultIso();
|
|
1391
|
-
const currentTime = useMemo(
|
|
1421
|
+
const currentTime = useMemo(
|
|
1422
|
+
() => displayTimezone ? getTimeInTimezone(baseIso, displayTimezone) : getTime(baseIso),
|
|
1423
|
+
[baseIso, displayTimezone]
|
|
1424
|
+
);
|
|
1392
1425
|
const setTime$1 = useCallback(
|
|
1393
1426
|
(partial) => {
|
|
1394
1427
|
if (disabled || readOnly) return;
|
|
1395
|
-
const newIso = setTime(baseIso, partial);
|
|
1428
|
+
const newIso = displayTimezone ? setTimeInTimezone(baseIso, partial, displayTimezone) : setTime(baseIso, partial);
|
|
1396
1429
|
if (!isControlled) {
|
|
1397
1430
|
setUncontrolledValue(newIso);
|
|
1398
1431
|
}
|
|
1399
1432
|
onChange?.(newIso);
|
|
1400
1433
|
},
|
|
1401
|
-
[disabled, readOnly, baseIso, isControlled, onChange]
|
|
1434
|
+
[disabled, readOnly, baseIso, isControlled, onChange, displayTimezone]
|
|
1402
1435
|
);
|
|
1403
1436
|
const contextValue = useMemo(
|
|
1404
1437
|
() => ({
|
|
@@ -1407,12 +1440,14 @@ function TimePickerRoot({
|
|
|
1407
1440
|
format,
|
|
1408
1441
|
step,
|
|
1409
1442
|
withSeconds,
|
|
1443
|
+
displayTimezone,
|
|
1410
1444
|
isDisabled: disabled,
|
|
1411
1445
|
isReadOnly: readOnly,
|
|
1412
1446
|
currentTime,
|
|
1413
|
-
pickerId
|
|
1447
|
+
pickerId,
|
|
1448
|
+
labels: mergedLabels
|
|
1414
1449
|
}),
|
|
1415
|
-
[currentValue, setTime$1, format, step, withSeconds, disabled, readOnly, currentTime, pickerId]
|
|
1450
|
+
[currentValue, setTime$1, format, step, withSeconds, displayTimezone, disabled, readOnly, currentTime, pickerId, mergedLabels]
|
|
1416
1451
|
);
|
|
1417
1452
|
return /* @__PURE__ */ jsx(TimePickerContext.Provider, { value: contextValue, children });
|
|
1418
1453
|
}
|
|
@@ -1458,7 +1493,7 @@ var TimePickerInput = forwardRef(
|
|
|
1458
1493
|
type: "text",
|
|
1459
1494
|
inputMode: "numeric",
|
|
1460
1495
|
autoComplete: "off",
|
|
1461
|
-
"aria-label":
|
|
1496
|
+
"aria-label": ctx.labels.timeInput,
|
|
1462
1497
|
placeholder: ctx.withSeconds ? "HH:MM:SS" : "HH:MM",
|
|
1463
1498
|
value: displayValue,
|
|
1464
1499
|
disabled: ctx.isDisabled || props.disabled,
|
|
@@ -1471,46 +1506,42 @@ var TimePickerInput = forwardRef(
|
|
|
1471
1506
|
);
|
|
1472
1507
|
}
|
|
1473
1508
|
);
|
|
1474
|
-
function
|
|
1475
|
-
|
|
1476
|
-
|
|
1509
|
+
function useListboxNavigation({
|
|
1510
|
+
items,
|
|
1511
|
+
onSelect,
|
|
1512
|
+
disabled = false
|
|
1513
|
+
}) {
|
|
1477
1514
|
const listRef = useRef(null);
|
|
1478
|
-
const
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
(hourDisplay) => {
|
|
1483
|
-
if (isDisabled || isReadOnly) return;
|
|
1484
|
-
const hours24 = format === "12h" && currentPeriod ? to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1485
|
-
ctx.setTime({ hours: hours24 });
|
|
1486
|
-
},
|
|
1487
|
-
[format, currentPeriod, ctx, isDisabled, isReadOnly]
|
|
1488
|
-
);
|
|
1515
|
+
const rafIdRef = useRef(0);
|
|
1516
|
+
useEffect(() => {
|
|
1517
|
+
return () => cancelAnimationFrame(rafIdRef.current);
|
|
1518
|
+
}, []);
|
|
1489
1519
|
const handleKeyDown = useCallback(
|
|
1490
|
-
(e,
|
|
1491
|
-
if (
|
|
1492
|
-
const currentIndex =
|
|
1520
|
+
(e, item) => {
|
|
1521
|
+
if (disabled) return;
|
|
1522
|
+
const currentIndex = items.indexOf(item);
|
|
1493
1523
|
let newIndex = -1;
|
|
1494
1524
|
if (e.key === "ArrowDown") {
|
|
1495
|
-
newIndex = Math.min(currentIndex + 1,
|
|
1525
|
+
newIndex = Math.min(currentIndex + 1, items.length - 1);
|
|
1496
1526
|
} else if (e.key === "ArrowUp") {
|
|
1497
1527
|
newIndex = Math.max(currentIndex - 1, 0);
|
|
1498
1528
|
} else if (e.key === "Home") {
|
|
1499
1529
|
newIndex = 0;
|
|
1500
1530
|
} else if (e.key === "End") {
|
|
1501
|
-
newIndex =
|
|
1531
|
+
newIndex = items.length - 1;
|
|
1502
1532
|
} else if (e.key === "Enter" || e.key === " ") {
|
|
1503
1533
|
e.preventDefault();
|
|
1504
|
-
|
|
1534
|
+
onSelect(item);
|
|
1505
1535
|
return;
|
|
1506
1536
|
} else {
|
|
1507
1537
|
return;
|
|
1508
1538
|
}
|
|
1509
1539
|
e.preventDefault();
|
|
1510
|
-
const
|
|
1511
|
-
if (
|
|
1512
|
-
|
|
1513
|
-
|
|
1540
|
+
const target = items[newIndex];
|
|
1541
|
+
if (target !== void 0) {
|
|
1542
|
+
onSelect(target);
|
|
1543
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
1544
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
1514
1545
|
const next = listRef.current?.querySelector(
|
|
1515
1546
|
'[data-selected="true"]'
|
|
1516
1547
|
);
|
|
@@ -1518,14 +1549,35 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1518
1549
|
});
|
|
1519
1550
|
}
|
|
1520
1551
|
},
|
|
1521
|
-
[
|
|
1552
|
+
[items, onSelect, disabled]
|
|
1553
|
+
);
|
|
1554
|
+
return { listRef, handleKeyDown };
|
|
1555
|
+
}
|
|
1556
|
+
function TimePickerHourList({ classNames, ...props }) {
|
|
1557
|
+
const ctx = useTimePickerContext("TimePicker.HourList");
|
|
1558
|
+
const { format, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1559
|
+
const hours = generateHours(format);
|
|
1560
|
+
const selectedHourDisplay = format === "12h" ? to12Hour(currentTime.hours).hours12 : currentTime.hours;
|
|
1561
|
+
const currentPeriod = format === "12h" ? to12Hour(currentTime.hours).period : null;
|
|
1562
|
+
const handleSelect = useCallback(
|
|
1563
|
+
(hourDisplay) => {
|
|
1564
|
+
if (isDisabled || isReadOnly) return;
|
|
1565
|
+
const hours24 = format === "12h" && currentPeriod ? to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1566
|
+
ctx.setTime({ hours: hours24 });
|
|
1567
|
+
},
|
|
1568
|
+
[format, currentPeriod, ctx, isDisabled, isReadOnly]
|
|
1522
1569
|
);
|
|
1570
|
+
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1571
|
+
items: hours,
|
|
1572
|
+
onSelect: handleSelect,
|
|
1573
|
+
disabled: isDisabled || isReadOnly
|
|
1574
|
+
});
|
|
1523
1575
|
return /* @__PURE__ */ jsx(
|
|
1524
1576
|
"ul",
|
|
1525
1577
|
{
|
|
1526
1578
|
ref: listRef,
|
|
1527
1579
|
role: "listbox",
|
|
1528
|
-
"aria-label":
|
|
1580
|
+
"aria-label": ctx.labels.hourList,
|
|
1529
1581
|
"aria-disabled": isDisabled || void 0,
|
|
1530
1582
|
className: classNames?.root,
|
|
1531
1583
|
...props,
|
|
@@ -1538,7 +1590,7 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1538
1590
|
role: "option",
|
|
1539
1591
|
"aria-selected": isSelected,
|
|
1540
1592
|
"aria-disabled": isDisabled || void 0,
|
|
1541
|
-
"aria-label":
|
|
1593
|
+
"aria-label": ctx.labels.hourOption(hour),
|
|
1542
1594
|
"data-selected": isSelected || void 0,
|
|
1543
1595
|
tabIndex: isSelected ? 0 : -1,
|
|
1544
1596
|
className: optionClass,
|
|
@@ -1555,7 +1607,6 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1555
1607
|
function TimePickerMinuteList({ classNames, ...props }) {
|
|
1556
1608
|
const ctx = useTimePickerContext("TimePicker.MinuteList");
|
|
1557
1609
|
const { step, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1558
|
-
const listRef = useRef(null);
|
|
1559
1610
|
const minutes = generateMinutes(step);
|
|
1560
1611
|
const handleSelect = useCallback(
|
|
1561
1612
|
(minute) => {
|
|
@@ -1564,46 +1615,17 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1564
1615
|
},
|
|
1565
1616
|
[ctx, isDisabled, isReadOnly]
|
|
1566
1617
|
);
|
|
1567
|
-
const handleKeyDown =
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
if (e.key === "ArrowDown") {
|
|
1573
|
-
newIndex = Math.min(currentIndex + 1, minutes.length - 1);
|
|
1574
|
-
} else if (e.key === "ArrowUp") {
|
|
1575
|
-
newIndex = Math.max(currentIndex - 1, 0);
|
|
1576
|
-
} else if (e.key === "Home") {
|
|
1577
|
-
newIndex = 0;
|
|
1578
|
-
} else if (e.key === "End") {
|
|
1579
|
-
newIndex = minutes.length - 1;
|
|
1580
|
-
} else if (e.key === "Enter" || e.key === " ") {
|
|
1581
|
-
e.preventDefault();
|
|
1582
|
-
handleSelect(minute);
|
|
1583
|
-
return;
|
|
1584
|
-
} else {
|
|
1585
|
-
return;
|
|
1586
|
-
}
|
|
1587
|
-
e.preventDefault();
|
|
1588
|
-
const target = minutes[newIndex];
|
|
1589
|
-
if (target !== void 0) {
|
|
1590
|
-
handleSelect(target);
|
|
1591
|
-
requestAnimationFrame(() => {
|
|
1592
|
-
const next = listRef.current?.querySelector(
|
|
1593
|
-
'[data-selected="true"]'
|
|
1594
|
-
);
|
|
1595
|
-
next?.focus();
|
|
1596
|
-
});
|
|
1597
|
-
}
|
|
1598
|
-
},
|
|
1599
|
-
[minutes, handleSelect, isDisabled, isReadOnly]
|
|
1600
|
-
);
|
|
1618
|
+
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1619
|
+
items: minutes,
|
|
1620
|
+
onSelect: handleSelect,
|
|
1621
|
+
disabled: isDisabled || isReadOnly
|
|
1622
|
+
});
|
|
1601
1623
|
return /* @__PURE__ */ jsx(
|
|
1602
1624
|
"ul",
|
|
1603
1625
|
{
|
|
1604
1626
|
ref: listRef,
|
|
1605
1627
|
role: "listbox",
|
|
1606
|
-
"aria-label":
|
|
1628
|
+
"aria-label": ctx.labels.minuteList,
|
|
1607
1629
|
"aria-disabled": isDisabled || void 0,
|
|
1608
1630
|
className: classNames?.root,
|
|
1609
1631
|
...props,
|
|
@@ -1616,7 +1638,7 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1616
1638
|
role: "option",
|
|
1617
1639
|
"aria-selected": isSelected,
|
|
1618
1640
|
"aria-disabled": isDisabled || void 0,
|
|
1619
|
-
"aria-label":
|
|
1641
|
+
"aria-label": ctx.labels.minuteOption(minute),
|
|
1620
1642
|
"data-selected": isSelected || void 0,
|
|
1621
1643
|
tabIndex: isSelected ? 0 : -1,
|
|
1622
1644
|
className: optionClass,
|
|
@@ -1659,7 +1681,7 @@ function TimePickerAmPmToggle({ classNames, ...props }) {
|
|
|
1659
1681
|
}
|
|
1660
1682
|
);
|
|
1661
1683
|
};
|
|
1662
|
-
return /* @__PURE__ */ jsxs("div", { role: "radiogroup", "aria-label":
|
|
1684
|
+
return /* @__PURE__ */ jsxs("div", { role: "radiogroup", "aria-label": ctx.labels.amPmToggle, className: classNames?.root, ...props, children: [
|
|
1663
1685
|
renderButton("AM"),
|
|
1664
1686
|
renderButton("PM")
|
|
1665
1687
|
] });
|
|
@@ -1673,10 +1695,7 @@ var TimePicker = Object.assign(TimePickerRoot, {
|
|
|
1673
1695
|
AmPmToggle: TimePickerAmPmToggle
|
|
1674
1696
|
});
|
|
1675
1697
|
function getDefaultIso2() {
|
|
1676
|
-
|
|
1677
|
-
return new Date(
|
|
1678
|
-
Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())
|
|
1679
|
-
).toISOString();
|
|
1698
|
+
return DateFnsAdapter.today();
|
|
1680
1699
|
}
|
|
1681
1700
|
function DateTimePickerRoot({
|
|
1682
1701
|
value: controlledValue,
|
|
@@ -1689,10 +1708,20 @@ function DateTimePickerRoot({
|
|
|
1689
1708
|
weekStartsOn = 0,
|
|
1690
1709
|
displayFormat = "yyyy-MM-dd HH:mm",
|
|
1691
1710
|
locale = "en-US",
|
|
1711
|
+
displayTimezone,
|
|
1692
1712
|
adapter = DateFnsAdapter,
|
|
1713
|
+
labels: labelsProp,
|
|
1693
1714
|
children
|
|
1694
1715
|
}) {
|
|
1695
1716
|
const pickerId = useId();
|
|
1717
|
+
const mergedDateLabels = useMemo(
|
|
1718
|
+
() => ({ ...DEFAULT_DATEPICKER_LABELS, ...labelsProp }),
|
|
1719
|
+
[labelsProp]
|
|
1720
|
+
);
|
|
1721
|
+
const mergedTimeLabels = useMemo(
|
|
1722
|
+
() => ({ ...DEFAULT_TIMEPICKER_LABELS, ...labelsProp }),
|
|
1723
|
+
[labelsProp]
|
|
1724
|
+
);
|
|
1696
1725
|
const isControlled = useRef(controlledValue !== void 0).current;
|
|
1697
1726
|
const referenceRef = useRef(null);
|
|
1698
1727
|
const [uncontrolledValue, setUncontrolledValue] = useState(
|
|
@@ -1701,15 +1730,21 @@ function DateTimePickerRoot({
|
|
|
1701
1730
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1702
1731
|
const [isOpen, setIsOpen] = useState(false);
|
|
1703
1732
|
const [viewMonth, setViewMonth] = useState(
|
|
1704
|
-
currentValue ?? adapter.today()
|
|
1733
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1705
1734
|
);
|
|
1706
1735
|
const [focusedDate, setFocusedDate] = useState(
|
|
1707
|
-
currentValue ?? adapter.today()
|
|
1736
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1708
1737
|
);
|
|
1709
1738
|
const isDisabled = typeof disabled === "boolean" ? disabled : false;
|
|
1710
|
-
const disabledRules =
|
|
1739
|
+
const disabledRules = useMemo(
|
|
1740
|
+
() => Array.isArray(disabled) ? disabled : [],
|
|
1741
|
+
[disabled]
|
|
1742
|
+
);
|
|
1711
1743
|
const baseIso = currentValue ?? getDefaultIso2();
|
|
1712
|
-
const currentTime = useMemo(
|
|
1744
|
+
const currentTime = useMemo(
|
|
1745
|
+
() => displayTimezone ? getTimeInTimezone(baseIso, displayTimezone) : getTime(baseIso),
|
|
1746
|
+
[baseIso, displayTimezone]
|
|
1747
|
+
);
|
|
1713
1748
|
const updateValue = useCallback(
|
|
1714
1749
|
(next) => {
|
|
1715
1750
|
if (isDisabled || readOnly) return;
|
|
@@ -1726,27 +1761,28 @@ function DateTimePickerRoot({
|
|
|
1726
1761
|
updateValue(null);
|
|
1727
1762
|
return;
|
|
1728
1763
|
}
|
|
1729
|
-
const
|
|
1730
|
-
const
|
|
1764
|
+
const normalizedDate = displayTimezone ? civilMidnightFromUtcDay(newDateIso, displayTimezone) : newDateIso;
|
|
1765
|
+
const time = currentValue ? displayTimezone ? getTimeInTimezone(currentValue, displayTimezone) : getTime(currentValue) : currentTime;
|
|
1766
|
+
const merged = displayTimezone ? setTimeInTimezone(normalizedDate, time, displayTimezone) : setTime(normalizedDate, time);
|
|
1731
1767
|
updateValue(merged);
|
|
1732
1768
|
},
|
|
1733
|
-
[currentValue, currentTime, updateValue]
|
|
1769
|
+
[currentValue, currentTime, updateValue, displayTimezone]
|
|
1734
1770
|
);
|
|
1735
1771
|
const setTime$1 = useCallback(
|
|
1736
1772
|
(partial) => {
|
|
1737
1773
|
const base = currentValue ?? getDefaultIso2();
|
|
1738
|
-
const merged = setTime(base, partial);
|
|
1774
|
+
const merged = displayTimezone ? setTimeInTimezone(base, partial, displayTimezone) : setTime(base, partial);
|
|
1739
1775
|
updateValue(merged);
|
|
1740
1776
|
},
|
|
1741
|
-
[currentValue, updateValue]
|
|
1777
|
+
[currentValue, updateValue, displayTimezone]
|
|
1742
1778
|
);
|
|
1743
1779
|
const open = useCallback(() => {
|
|
1744
1780
|
if (isDisabled || readOnly) return;
|
|
1745
1781
|
setIsOpen(true);
|
|
1746
|
-
const target = currentValue ?? adapter.today();
|
|
1782
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
1747
1783
|
setViewMonth(target);
|
|
1748
1784
|
setFocusedDate(target);
|
|
1749
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
1785
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
1750
1786
|
const close = useCallback(() => {
|
|
1751
1787
|
setIsOpen(false);
|
|
1752
1788
|
}, []);
|
|
@@ -1772,9 +1808,11 @@ function DateTimePickerRoot({
|
|
|
1772
1808
|
weekStartsOn,
|
|
1773
1809
|
displayFormat,
|
|
1774
1810
|
locale,
|
|
1811
|
+
displayTimezone,
|
|
1775
1812
|
isDisabled,
|
|
1776
1813
|
isReadOnly: readOnly,
|
|
1777
|
-
pickerId
|
|
1814
|
+
pickerId,
|
|
1815
|
+
labels: mergedDateLabels
|
|
1778
1816
|
}),
|
|
1779
1817
|
[
|
|
1780
1818
|
currentValue,
|
|
@@ -1790,9 +1828,11 @@ function DateTimePickerRoot({
|
|
|
1790
1828
|
weekStartsOn,
|
|
1791
1829
|
displayFormat,
|
|
1792
1830
|
locale,
|
|
1831
|
+
displayTimezone,
|
|
1793
1832
|
isDisabled,
|
|
1794
1833
|
readOnly,
|
|
1795
|
-
pickerId
|
|
1834
|
+
pickerId,
|
|
1835
|
+
mergedDateLabels
|
|
1796
1836
|
]
|
|
1797
1837
|
);
|
|
1798
1838
|
const timeContext = useMemo(
|
|
@@ -1802,25 +1842,36 @@ function DateTimePickerRoot({
|
|
|
1802
1842
|
format,
|
|
1803
1843
|
step,
|
|
1804
1844
|
withSeconds: false,
|
|
1845
|
+
displayTimezone,
|
|
1805
1846
|
isDisabled,
|
|
1806
1847
|
isReadOnly: readOnly,
|
|
1807
1848
|
currentTime,
|
|
1808
|
-
pickerId
|
|
1849
|
+
pickerId,
|
|
1850
|
+
labels: mergedTimeLabels
|
|
1809
1851
|
}),
|
|
1810
|
-
[currentValue, setTime$1, format, step, isDisabled, readOnly, currentTime, pickerId]
|
|
1852
|
+
[currentValue, setTime$1, format, step, displayTimezone, isDisabled, readOnly, currentTime, pickerId, mergedTimeLabels]
|
|
1811
1853
|
);
|
|
1812
1854
|
return /* @__PURE__ */ jsx(DatePickerContext.Provider, { value: dateContext, children: /* @__PURE__ */ jsx(TimePickerContext.Provider, { value: timeContext, children }) });
|
|
1813
1855
|
}
|
|
1814
1856
|
var DateTimePickerInput = forwardRef(
|
|
1815
|
-
function DateTimePickerInput2({
|
|
1857
|
+
function DateTimePickerInput2({ onClick, onKeyDown, ...props }, ref) {
|
|
1816
1858
|
const ctx = useDatePickerContext("DateTimePicker.Input");
|
|
1817
|
-
|
|
1818
|
-
|
|
1859
|
+
let displayValue = "";
|
|
1860
|
+
if (ctx.value) {
|
|
1861
|
+
try {
|
|
1862
|
+
const datePart = ctx.adapter.format(ctx.value, "yyyy-MM-dd", ctx.displayTimezone);
|
|
1863
|
+
const time = ctx.displayTimezone ? getTimeInTimezone(ctx.value, ctx.displayTimezone) : getTime(ctx.value);
|
|
1864
|
+
displayValue = `${datePart} ${formatTimeString(time)}`;
|
|
1865
|
+
} catch {
|
|
1866
|
+
displayValue = ctx.value;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
const handleClick = useCallback(
|
|
1819
1870
|
(e) => {
|
|
1820
|
-
ctx.open();
|
|
1821
|
-
|
|
1871
|
+
if (!ctx.isOpen) ctx.open();
|
|
1872
|
+
onClick?.(e);
|
|
1822
1873
|
},
|
|
1823
|
-
[ctx,
|
|
1874
|
+
[ctx, onClick]
|
|
1824
1875
|
);
|
|
1825
1876
|
const handleKeyDown = useCallback(
|
|
1826
1877
|
(e) => {
|
|
@@ -1846,7 +1897,7 @@ var DateTimePickerInput = forwardRef(
|
|
|
1846
1897
|
type: "text",
|
|
1847
1898
|
role: "combobox",
|
|
1848
1899
|
readOnly: true,
|
|
1849
|
-
"aria-label": "
|
|
1900
|
+
"aria-label": ctx.labels.dateTimeInput ?? "Date and time",
|
|
1850
1901
|
"aria-expanded": ctx.isOpen,
|
|
1851
1902
|
"aria-haspopup": "dialog",
|
|
1852
1903
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
@@ -1854,7 +1905,7 @@ var DateTimePickerInput = forwardRef(
|
|
|
1854
1905
|
autoComplete: "off",
|
|
1855
1906
|
value: displayValue,
|
|
1856
1907
|
disabled: ctx.isDisabled || props.disabled,
|
|
1857
|
-
|
|
1908
|
+
onClick: handleClick,
|
|
1858
1909
|
onKeyDown: handleKeyDown,
|
|
1859
1910
|
...props
|
|
1860
1911
|
}
|
|
@@ -1880,7 +1931,8 @@ function useDatePicker(options = {}) {
|
|
|
1880
1931
|
onChange,
|
|
1881
1932
|
disabled = [],
|
|
1882
1933
|
weekStartsOn = 0,
|
|
1883
|
-
adapter = DateFnsAdapter
|
|
1934
|
+
adapter = DateFnsAdapter,
|
|
1935
|
+
displayTimezone
|
|
1884
1936
|
} = options;
|
|
1885
1937
|
const pickerId = useId();
|
|
1886
1938
|
const isControlled = useRef(controlledValue !== void 0).current;
|
|
@@ -1889,24 +1941,29 @@ function useDatePicker(options = {}) {
|
|
|
1889
1941
|
);
|
|
1890
1942
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1891
1943
|
const [isOpen, setIsOpen] = useState(false);
|
|
1892
|
-
const [viewMonth, setViewMonth] = useState(
|
|
1893
|
-
|
|
1944
|
+
const [viewMonth, setViewMonth] = useState(
|
|
1945
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1946
|
+
);
|
|
1947
|
+
const [focusedDate, setFocusedDate] = useState(
|
|
1948
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1949
|
+
);
|
|
1894
1950
|
const selectDate = useCallback(
|
|
1895
1951
|
(iso) => {
|
|
1952
|
+
const normalized = iso && displayTimezone ? civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
1896
1953
|
if (!isControlled) {
|
|
1897
|
-
setUncontrolledValue(
|
|
1954
|
+
setUncontrolledValue(normalized);
|
|
1898
1955
|
}
|
|
1899
|
-
onChange?.(
|
|
1956
|
+
onChange?.(normalized);
|
|
1900
1957
|
setIsOpen(false);
|
|
1901
1958
|
},
|
|
1902
|
-
[isControlled, onChange]
|
|
1959
|
+
[isControlled, onChange, displayTimezone]
|
|
1903
1960
|
);
|
|
1904
1961
|
const open = useCallback(() => {
|
|
1905
1962
|
setIsOpen(true);
|
|
1906
|
-
const target = currentValue ?? adapter.today();
|
|
1963
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
1907
1964
|
setViewMonth(target);
|
|
1908
1965
|
setFocusedDate(target);
|
|
1909
|
-
}, [currentValue, adapter]);
|
|
1966
|
+
}, [currentValue, adapter, displayTimezone]);
|
|
1910
1967
|
const close = useCallback(() => {
|
|
1911
1968
|
setIsOpen(false);
|
|
1912
1969
|
}, []);
|
|
@@ -1928,7 +1985,8 @@ function useDatePicker(options = {}) {
|
|
|
1928
1985
|
weekStartsOn,
|
|
1929
1986
|
selected: currentValue,
|
|
1930
1987
|
focusedDate,
|
|
1931
|
-
disabled
|
|
1988
|
+
disabled,
|
|
1989
|
+
timezone: displayTimezone
|
|
1932
1990
|
});
|
|
1933
1991
|
return {
|
|
1934
1992
|
value: currentValue,
|
|
@@ -1956,7 +2014,8 @@ function useRangePicker(options = {}) {
|
|
|
1956
2014
|
onChange,
|
|
1957
2015
|
disabled = [],
|
|
1958
2016
|
weekStartsOn = 0,
|
|
1959
|
-
adapter = DateFnsAdapter
|
|
2017
|
+
adapter = DateFnsAdapter,
|
|
2018
|
+
displayTimezone
|
|
1960
2019
|
} = options;
|
|
1961
2020
|
const pickerId = useId();
|
|
1962
2021
|
const isControlled = useRef(controlledValue !== void 0).current;
|
|
@@ -1968,10 +2027,10 @@ function useRangePicker(options = {}) {
|
|
|
1968
2027
|
const [selectingTarget, setSelectingTarget] = useState("start");
|
|
1969
2028
|
const [hoverDate, setHoverDate] = useState(null);
|
|
1970
2029
|
const [viewMonth, setViewMonth] = useState(
|
|
1971
|
-
currentValue.start ?? adapter.today()
|
|
2030
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
1972
2031
|
);
|
|
1973
2032
|
const [focusedDate, setFocusedDate] = useState(
|
|
1974
|
-
currentValue.start ?? adapter.today()
|
|
2033
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
1975
2034
|
);
|
|
1976
2035
|
const setRange = useCallback(
|
|
1977
2036
|
(range) => {
|
|
@@ -1984,35 +2043,36 @@ function useRangePicker(options = {}) {
|
|
|
1984
2043
|
);
|
|
1985
2044
|
const selectDate = useCallback(
|
|
1986
2045
|
(iso) => {
|
|
2046
|
+
const normalized = displayTimezone ? civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
1987
2047
|
if (selectingTarget === "start") {
|
|
1988
|
-
setRange({ start:
|
|
2048
|
+
setRange({ start: normalized, end: null });
|
|
1989
2049
|
setSelectingTarget("end");
|
|
1990
2050
|
setHoverDate(null);
|
|
1991
2051
|
} else {
|
|
1992
2052
|
const start = currentValue.start;
|
|
1993
2053
|
if (!start) {
|
|
1994
|
-
setRange({ start:
|
|
2054
|
+
setRange({ start: normalized, end: null });
|
|
1995
2055
|
setSelectingTarget("end");
|
|
1996
2056
|
return;
|
|
1997
2057
|
}
|
|
1998
|
-
const newRange = adapter.isBefore(
|
|
2058
|
+
const newRange = adapter.isBefore(normalized, start) ? { start: normalized, end: start } : { start, end: normalized };
|
|
1999
2059
|
setRange(newRange);
|
|
2000
2060
|
setSelectingTarget("start");
|
|
2001
2061
|
setHoverDate(null);
|
|
2002
2062
|
setIsOpen(false);
|
|
2003
2063
|
}
|
|
2004
2064
|
},
|
|
2005
|
-
[selectingTarget, currentValue.start, adapter, setRange]
|
|
2065
|
+
[selectingTarget, currentValue.start, adapter, setRange, displayTimezone]
|
|
2006
2066
|
);
|
|
2007
2067
|
const open = useCallback(() => {
|
|
2008
2068
|
setIsOpen(true);
|
|
2009
|
-
const target = currentValue.start ?? adapter.today();
|
|
2069
|
+
const target = currentValue.start ?? adapter.today(displayTimezone);
|
|
2010
2070
|
setViewMonth(target);
|
|
2011
2071
|
setFocusedDate(target);
|
|
2012
2072
|
if (currentValue.start && currentValue.end) {
|
|
2013
2073
|
setSelectingTarget("start");
|
|
2014
2074
|
}
|
|
2015
|
-
}, [currentValue, adapter]);
|
|
2075
|
+
}, [currentValue, adapter, displayTimezone]);
|
|
2016
2076
|
const close = useCallback(() => {
|
|
2017
2077
|
setIsOpen(false);
|
|
2018
2078
|
setHoverDate(null);
|
|
@@ -2036,7 +2096,8 @@ function useRangePicker(options = {}) {
|
|
|
2036
2096
|
focusedDate,
|
|
2037
2097
|
disabled,
|
|
2038
2098
|
range: currentValue,
|
|
2039
|
-
rangeHover: hoverDate
|
|
2099
|
+
rangeHover: hoverDate,
|
|
2100
|
+
timezone: displayTimezone
|
|
2040
2101
|
});
|
|
2041
2102
|
return {
|
|
2042
2103
|
value: currentValue,
|
|
@@ -2061,10 +2122,7 @@ function useRangePicker(options = {}) {
|
|
|
2061
2122
|
};
|
|
2062
2123
|
}
|
|
2063
2124
|
function getDefaultIso3() {
|
|
2064
|
-
|
|
2065
|
-
return new Date(
|
|
2066
|
-
Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())
|
|
2067
|
-
).toISOString();
|
|
2125
|
+
return DateFnsAdapter.today();
|
|
2068
2126
|
}
|
|
2069
2127
|
function useTimePicker(options = {}) {
|
|
2070
2128
|
const {
|
|
@@ -2072,7 +2130,8 @@ function useTimePicker(options = {}) {
|
|
|
2072
2130
|
defaultValue,
|
|
2073
2131
|
onChange,
|
|
2074
2132
|
format = "24h",
|
|
2075
|
-
step = 1
|
|
2133
|
+
step = 1,
|
|
2134
|
+
displayTimezone
|
|
2076
2135
|
} = options;
|
|
2077
2136
|
const pickerId = useId();
|
|
2078
2137
|
const isControlled = useRef(controlledValue !== void 0).current;
|
|
@@ -2081,16 +2140,19 @@ function useTimePicker(options = {}) {
|
|
|
2081
2140
|
);
|
|
2082
2141
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
2083
2142
|
const baseIso = currentValue ?? getDefaultIso3();
|
|
2084
|
-
const currentTime = useMemo(
|
|
2143
|
+
const currentTime = useMemo(
|
|
2144
|
+
() => displayTimezone ? getTimeInTimezone(baseIso, displayTimezone) : getTime(baseIso),
|
|
2145
|
+
[baseIso, displayTimezone]
|
|
2146
|
+
);
|
|
2085
2147
|
const setTime$1 = useCallback(
|
|
2086
2148
|
(partial) => {
|
|
2087
|
-
const newIso = setTime(baseIso, partial);
|
|
2149
|
+
const newIso = displayTimezone ? setTimeInTimezone(baseIso, partial, displayTimezone) : setTime(baseIso, partial);
|
|
2088
2150
|
if (!isControlled) {
|
|
2089
2151
|
setUncontrolledValue(newIso);
|
|
2090
2152
|
}
|
|
2091
2153
|
onChange?.(newIso);
|
|
2092
2154
|
},
|
|
2093
|
-
[baseIso, isControlled, onChange]
|
|
2155
|
+
[baseIso, isControlled, onChange, displayTimezone]
|
|
2094
2156
|
);
|
|
2095
2157
|
const period = format === "12h" ? to12Hour(currentTime.hours).period : null;
|
|
2096
2158
|
const displayHour = format === "12h" ? to12Hour(currentTime.hours).hours12 : currentTime.hours;
|