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