@kalyx/react 0.3.0 → 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 +24 -0
- package/dist/index.cjs +102 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -4
- package/dist/index.d.ts +33 -4
- package/dist/index.js +103 -63
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @kalyx/react
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 104bbf2: feat: full `displayTimezone` support across all pickers (v0.4)
|
|
8
|
+
|
|
9
|
+
All four pickers (`DatePicker`, `RangePicker`, `TimePicker`, `DateTimePicker`) and their corresponding hooks (`useDatePicker`, `useRangePicker`, `useTimePicker`) now accept a `displayTimezone` prop/option.
|
|
10
|
+
|
|
11
|
+
When set, the value stored via `onChange` is the **civil midnight of the selected day in the target timezone** (in UTC-ISO form), eliminating the classic "day off by one" bug that affects picker libraries bound to `new Date()`. Input formatting, calendar highlighting, and the time-of-day controls all follow the display timezone — including DST-aware offsets for zones like `America/New_York` and `Europe/London`.
|
|
12
|
+
|
|
13
|
+
`DateFnsAdapter` now honors the `timezone` argument on `format`, `isSameDay`, `startOfDay`, and `today` (previously declared-but-ignored). Core also exposes new helpers:
|
|
14
|
+
|
|
15
|
+
- `civilMidnightFromUtcDay(iso, tz)`
|
|
16
|
+
- `getTimeInTimezone(iso, tz)`
|
|
17
|
+
- `setTimeInTimezone(iso, partial, tz)`
|
|
18
|
+
|
|
19
|
+
No breaking changes — omitting `displayTimezone` keeps the existing UTC semantics.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [b3a8897]
|
|
24
|
+
- Updated dependencies [104bbf2]
|
|
25
|
+
- @kalyx/core@0.4.0
|
|
26
|
+
|
|
3
27
|
## 0.3.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ function DatePickerRoot({
|
|
|
30
30
|
weekStartsOn = 0,
|
|
31
31
|
displayFormat = "yyyy-MM-dd",
|
|
32
32
|
locale = "en-US",
|
|
33
|
+
displayTimezone,
|
|
33
34
|
adapter = core.DateFnsAdapter,
|
|
34
35
|
labels: labelsProp,
|
|
35
36
|
children
|
|
@@ -43,10 +44,10 @@ function DatePickerRoot({
|
|
|
43
44
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
44
45
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
45
46
|
const [viewMonth, setViewMonth] = react.useState(
|
|
46
|
-
currentValue ?? adapter.today()
|
|
47
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
47
48
|
);
|
|
48
49
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
49
|
-
currentValue ?? adapter.today()
|
|
50
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
50
51
|
);
|
|
51
52
|
const mergedLabels = react.useMemo(
|
|
52
53
|
() => ({ ...core.DEFAULT_DATEPICKER_LABELS, ...labelsProp }),
|
|
@@ -60,21 +61,22 @@ function DatePickerRoot({
|
|
|
60
61
|
const selectDate = react.useCallback(
|
|
61
62
|
(iso) => {
|
|
62
63
|
if (isDisabled || readOnly) return;
|
|
64
|
+
const normalized = iso && displayTimezone ? core.civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
63
65
|
if (!isControlled) {
|
|
64
|
-
setUncontrolledValue(
|
|
66
|
+
setUncontrolledValue(normalized);
|
|
65
67
|
}
|
|
66
|
-
onChange?.(
|
|
68
|
+
onChange?.(normalized);
|
|
67
69
|
setIsOpen(false);
|
|
68
70
|
},
|
|
69
|
-
[isControlled, isDisabled, readOnly, onChange]
|
|
71
|
+
[isControlled, isDisabled, readOnly, onChange, displayTimezone]
|
|
70
72
|
);
|
|
71
73
|
const open = react.useCallback(() => {
|
|
72
74
|
if (isDisabled || readOnly) return;
|
|
73
75
|
setIsOpen(true);
|
|
74
|
-
const target = currentValue ?? adapter.today();
|
|
76
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
75
77
|
setViewMonth(target);
|
|
76
78
|
setFocusedDate(target);
|
|
77
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
79
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
78
80
|
const close = react.useCallback(() => {
|
|
79
81
|
setIsOpen(false);
|
|
80
82
|
}, []);
|
|
@@ -103,6 +105,7 @@ function DatePickerRoot({
|
|
|
103
105
|
weekStartsOn,
|
|
104
106
|
displayFormat,
|
|
105
107
|
locale,
|
|
108
|
+
displayTimezone,
|
|
106
109
|
isDisabled,
|
|
107
110
|
isReadOnly: readOnly,
|
|
108
111
|
pickerId,
|
|
@@ -122,6 +125,7 @@ function DatePickerRoot({
|
|
|
122
125
|
weekStartsOn,
|
|
123
126
|
displayFormat,
|
|
124
127
|
locale,
|
|
128
|
+
displayTimezone,
|
|
125
129
|
isDisabled,
|
|
126
130
|
readOnly,
|
|
127
131
|
pickerId,
|
|
@@ -138,7 +142,7 @@ var DatePickerInput = react.forwardRef(
|
|
|
138
142
|
let formattedValue = "";
|
|
139
143
|
if (ctx.value) {
|
|
140
144
|
try {
|
|
141
|
-
formattedValue = ctx.adapter.format(ctx.value, displayFormat);
|
|
145
|
+
formattedValue = ctx.adapter.format(ctx.value, displayFormat, ctx.displayTimezone);
|
|
142
146
|
} catch {
|
|
143
147
|
formattedValue = ctx.value;
|
|
144
148
|
}
|
|
@@ -386,13 +390,14 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
386
390
|
const ctx = useDatePickerContext("DatePicker.Calendar");
|
|
387
391
|
const gridRef = react.useRef(null);
|
|
388
392
|
const [announcement, setAnnouncement] = react.useState("");
|
|
389
|
-
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale } = ctx;
|
|
393
|
+
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale, displayTimezone } = ctx;
|
|
390
394
|
const weekdays = core.getWeekdayNames(locale, weekStartsOn);
|
|
391
395
|
const weeks = core.getCalendarDays(viewMonth, adapter, {
|
|
392
396
|
weekStartsOn,
|
|
393
397
|
selected: ctx.value,
|
|
394
398
|
focusedDate,
|
|
395
|
-
disabled
|
|
399
|
+
disabled,
|
|
400
|
+
timezone: displayTimezone
|
|
396
401
|
});
|
|
397
402
|
const year = adapter.getYear(viewMonth);
|
|
398
403
|
const month = adapter.getMonth(viewMonth);
|
|
@@ -808,6 +813,7 @@ function RangePickerRoot({
|
|
|
808
813
|
weekStartsOn = 0,
|
|
809
814
|
displayFormat = "yyyy-MM-dd",
|
|
810
815
|
locale = "en-US",
|
|
816
|
+
displayTimezone,
|
|
811
817
|
adapter = core.DateFnsAdapter,
|
|
812
818
|
labels: labelsProp,
|
|
813
819
|
children
|
|
@@ -823,10 +829,10 @@ function RangePickerRoot({
|
|
|
823
829
|
const [selectingTarget, setSelectingTarget] = react.useState("start");
|
|
824
830
|
const [hoverDate, setHoverDate] = react.useState(null);
|
|
825
831
|
const [viewMonth, setViewMonth] = react.useState(
|
|
826
|
-
currentValue.start ?? adapter.today()
|
|
832
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
827
833
|
);
|
|
828
834
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
829
|
-
currentValue.start ?? adapter.today()
|
|
835
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
830
836
|
);
|
|
831
837
|
const mergedLabels = react.useMemo(
|
|
832
838
|
() => ({ ...core.DEFAULT_RANGEPICKER_LABELS, ...labelsProp }),
|
|
@@ -850,23 +856,24 @@ function RangePickerRoot({
|
|
|
850
856
|
const selectDate = react.useCallback(
|
|
851
857
|
(iso) => {
|
|
852
858
|
if (isDisabled || readOnly) return;
|
|
859
|
+
const normalized = displayTimezone ? core.civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
853
860
|
if (selectingTarget === "start") {
|
|
854
|
-
const newRange = { start:
|
|
861
|
+
const newRange = { start: normalized, end: null };
|
|
855
862
|
setRange(newRange);
|
|
856
863
|
setSelectingTarget("end");
|
|
857
864
|
setHoverDate(null);
|
|
858
865
|
} else {
|
|
859
866
|
const start = currentValue.start;
|
|
860
867
|
if (!start) {
|
|
861
|
-
setRange({ start:
|
|
868
|
+
setRange({ start: normalized, end: null });
|
|
862
869
|
setSelectingTarget("end");
|
|
863
870
|
return;
|
|
864
871
|
}
|
|
865
872
|
let newRange;
|
|
866
|
-
if (adapter.isBefore(
|
|
867
|
-
newRange = { start:
|
|
873
|
+
if (adapter.isBefore(normalized, start)) {
|
|
874
|
+
newRange = { start: normalized, end: start };
|
|
868
875
|
} else {
|
|
869
|
-
newRange = { start, end:
|
|
876
|
+
newRange = { start, end: normalized };
|
|
870
877
|
}
|
|
871
878
|
setRange(newRange);
|
|
872
879
|
setSelectingTarget("start");
|
|
@@ -874,18 +881,18 @@ function RangePickerRoot({
|
|
|
874
881
|
setIsOpen(false);
|
|
875
882
|
}
|
|
876
883
|
},
|
|
877
|
-
[isDisabled, readOnly, selectingTarget, currentValue.start, adapter, setRange]
|
|
884
|
+
[isDisabled, readOnly, selectingTarget, currentValue.start, adapter, setRange, displayTimezone]
|
|
878
885
|
);
|
|
879
886
|
const open = react.useCallback(() => {
|
|
880
887
|
if (isDisabled || readOnly) return;
|
|
881
888
|
setIsOpen(true);
|
|
882
|
-
const target = currentValue.start ?? adapter.today();
|
|
889
|
+
const target = currentValue.start ?? adapter.today(displayTimezone);
|
|
883
890
|
setViewMonth(target);
|
|
884
891
|
setFocusedDate(target);
|
|
885
892
|
if (currentValue.start && currentValue.end) {
|
|
886
893
|
setSelectingTarget("start");
|
|
887
894
|
}
|
|
888
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
895
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
889
896
|
const close = react.useCallback(() => {
|
|
890
897
|
setIsOpen(false);
|
|
891
898
|
setHoverDate(null);
|
|
@@ -916,6 +923,7 @@ function RangePickerRoot({
|
|
|
916
923
|
weekStartsOn,
|
|
917
924
|
displayFormat,
|
|
918
925
|
locale,
|
|
926
|
+
displayTimezone,
|
|
919
927
|
isDisabled,
|
|
920
928
|
isReadOnly: readOnly,
|
|
921
929
|
pickerId,
|
|
@@ -938,6 +946,7 @@ function RangePickerRoot({
|
|
|
938
946
|
weekStartsOn,
|
|
939
947
|
displayFormat,
|
|
940
948
|
locale,
|
|
949
|
+
displayTimezone,
|
|
941
950
|
isDisabled,
|
|
942
951
|
readOnly,
|
|
943
952
|
pickerId,
|
|
@@ -954,7 +963,7 @@ var RangePickerInput = react.forwardRef(
|
|
|
954
963
|
let displayValue = "";
|
|
955
964
|
if (value) {
|
|
956
965
|
try {
|
|
957
|
-
displayValue = ctx.adapter.format(value, displayFormat);
|
|
966
|
+
displayValue = ctx.adapter.format(value, displayFormat, ctx.displayTimezone);
|
|
958
967
|
} catch {
|
|
959
968
|
displayValue = value;
|
|
960
969
|
}
|
|
@@ -1059,7 +1068,8 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1059
1068
|
disabled,
|
|
1060
1069
|
value,
|
|
1061
1070
|
hoverDate,
|
|
1062
|
-
selectingTarget
|
|
1071
|
+
selectingTarget,
|
|
1072
|
+
displayTimezone
|
|
1063
1073
|
} = ctx;
|
|
1064
1074
|
const { locale } = ctx;
|
|
1065
1075
|
const weekdays = core.getWeekdayNames(locale, weekStartsOn);
|
|
@@ -1068,7 +1078,8 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1068
1078
|
focusedDate,
|
|
1069
1079
|
disabled,
|
|
1070
1080
|
range: value,
|
|
1071
|
-
rangeHover: hoverDate
|
|
1081
|
+
rangeHover: hoverDate,
|
|
1082
|
+
timezone: displayTimezone
|
|
1072
1083
|
});
|
|
1073
1084
|
const year = adapter.getYear(viewMonth);
|
|
1074
1085
|
const month = adapter.getMonth(viewMonth);
|
|
@@ -1391,6 +1402,7 @@ function TimePickerRoot({
|
|
|
1391
1402
|
format = "24h",
|
|
1392
1403
|
step = 1,
|
|
1393
1404
|
withSeconds = false,
|
|
1405
|
+
displayTimezone,
|
|
1394
1406
|
disabled = false,
|
|
1395
1407
|
readOnly = false,
|
|
1396
1408
|
labels: labelsProp,
|
|
@@ -1407,17 +1419,20 @@ function TimePickerRoot({
|
|
|
1407
1419
|
);
|
|
1408
1420
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1409
1421
|
const baseIso = currentValue ?? getDefaultIso();
|
|
1410
|
-
const currentTime = react.useMemo(
|
|
1422
|
+
const currentTime = react.useMemo(
|
|
1423
|
+
() => displayTimezone ? core.getTimeInTimezone(baseIso, displayTimezone) : core.getTime(baseIso),
|
|
1424
|
+
[baseIso, displayTimezone]
|
|
1425
|
+
);
|
|
1411
1426
|
const setTime = react.useCallback(
|
|
1412
1427
|
(partial) => {
|
|
1413
1428
|
if (disabled || readOnly) return;
|
|
1414
|
-
const newIso = core.setTime(baseIso, partial);
|
|
1429
|
+
const newIso = displayTimezone ? core.setTimeInTimezone(baseIso, partial, displayTimezone) : core.setTime(baseIso, partial);
|
|
1415
1430
|
if (!isControlled) {
|
|
1416
1431
|
setUncontrolledValue(newIso);
|
|
1417
1432
|
}
|
|
1418
1433
|
onChange?.(newIso);
|
|
1419
1434
|
},
|
|
1420
|
-
[disabled, readOnly, baseIso, isControlled, onChange]
|
|
1435
|
+
[disabled, readOnly, baseIso, isControlled, onChange, displayTimezone]
|
|
1421
1436
|
);
|
|
1422
1437
|
const contextValue = react.useMemo(
|
|
1423
1438
|
() => ({
|
|
@@ -1426,13 +1441,14 @@ function TimePickerRoot({
|
|
|
1426
1441
|
format,
|
|
1427
1442
|
step,
|
|
1428
1443
|
withSeconds,
|
|
1444
|
+
displayTimezone,
|
|
1429
1445
|
isDisabled: disabled,
|
|
1430
1446
|
isReadOnly: readOnly,
|
|
1431
1447
|
currentTime,
|
|
1432
1448
|
pickerId,
|
|
1433
1449
|
labels: mergedLabels
|
|
1434
1450
|
}),
|
|
1435
|
-
[currentValue, setTime, format, step, withSeconds, disabled, readOnly, currentTime, pickerId, mergedLabels]
|
|
1451
|
+
[currentValue, setTime, format, step, withSeconds, displayTimezone, disabled, readOnly, currentTime, pickerId, mergedLabels]
|
|
1436
1452
|
);
|
|
1437
1453
|
return /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: contextValue, children });
|
|
1438
1454
|
}
|
|
@@ -1693,6 +1709,7 @@ function DateTimePickerRoot({
|
|
|
1693
1709
|
weekStartsOn = 0,
|
|
1694
1710
|
displayFormat = "yyyy-MM-dd HH:mm",
|
|
1695
1711
|
locale = "en-US",
|
|
1712
|
+
displayTimezone,
|
|
1696
1713
|
adapter = core.DateFnsAdapter,
|
|
1697
1714
|
labels: labelsProp,
|
|
1698
1715
|
children
|
|
@@ -1714,10 +1731,10 @@ function DateTimePickerRoot({
|
|
|
1714
1731
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1715
1732
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
1716
1733
|
const [viewMonth, setViewMonth] = react.useState(
|
|
1717
|
-
currentValue ?? adapter.today()
|
|
1734
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1718
1735
|
);
|
|
1719
1736
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
1720
|
-
currentValue ?? adapter.today()
|
|
1737
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1721
1738
|
);
|
|
1722
1739
|
const isDisabled = typeof disabled === "boolean" ? disabled : false;
|
|
1723
1740
|
const disabledRules = react.useMemo(
|
|
@@ -1725,7 +1742,10 @@ function DateTimePickerRoot({
|
|
|
1725
1742
|
[disabled]
|
|
1726
1743
|
);
|
|
1727
1744
|
const baseIso = currentValue ?? getDefaultIso2();
|
|
1728
|
-
const currentTime = react.useMemo(
|
|
1745
|
+
const currentTime = react.useMemo(
|
|
1746
|
+
() => displayTimezone ? core.getTimeInTimezone(baseIso, displayTimezone) : core.getTime(baseIso),
|
|
1747
|
+
[baseIso, displayTimezone]
|
|
1748
|
+
);
|
|
1729
1749
|
const updateValue = react.useCallback(
|
|
1730
1750
|
(next) => {
|
|
1731
1751
|
if (isDisabled || readOnly) return;
|
|
@@ -1742,27 +1762,28 @@ function DateTimePickerRoot({
|
|
|
1742
1762
|
updateValue(null);
|
|
1743
1763
|
return;
|
|
1744
1764
|
}
|
|
1745
|
-
const
|
|
1746
|
-
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);
|
|
1747
1768
|
updateValue(merged);
|
|
1748
1769
|
},
|
|
1749
|
-
[currentValue, currentTime, updateValue]
|
|
1770
|
+
[currentValue, currentTime, updateValue, displayTimezone]
|
|
1750
1771
|
);
|
|
1751
1772
|
const setTime = react.useCallback(
|
|
1752
1773
|
(partial) => {
|
|
1753
1774
|
const base = currentValue ?? getDefaultIso2();
|
|
1754
|
-
const merged = core.setTime(base, partial);
|
|
1775
|
+
const merged = displayTimezone ? core.setTimeInTimezone(base, partial, displayTimezone) : core.setTime(base, partial);
|
|
1755
1776
|
updateValue(merged);
|
|
1756
1777
|
},
|
|
1757
|
-
[currentValue, updateValue]
|
|
1778
|
+
[currentValue, updateValue, displayTimezone]
|
|
1758
1779
|
);
|
|
1759
1780
|
const open = react.useCallback(() => {
|
|
1760
1781
|
if (isDisabled || readOnly) return;
|
|
1761
1782
|
setIsOpen(true);
|
|
1762
|
-
const target = currentValue ?? adapter.today();
|
|
1783
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
1763
1784
|
setViewMonth(target);
|
|
1764
1785
|
setFocusedDate(target);
|
|
1765
|
-
}, [isDisabled, readOnly, currentValue, adapter]);
|
|
1786
|
+
}, [isDisabled, readOnly, currentValue, adapter, displayTimezone]);
|
|
1766
1787
|
const close = react.useCallback(() => {
|
|
1767
1788
|
setIsOpen(false);
|
|
1768
1789
|
}, []);
|
|
@@ -1788,6 +1809,7 @@ function DateTimePickerRoot({
|
|
|
1788
1809
|
weekStartsOn,
|
|
1789
1810
|
displayFormat,
|
|
1790
1811
|
locale,
|
|
1812
|
+
displayTimezone,
|
|
1791
1813
|
isDisabled,
|
|
1792
1814
|
isReadOnly: readOnly,
|
|
1793
1815
|
pickerId,
|
|
@@ -1807,6 +1829,7 @@ function DateTimePickerRoot({
|
|
|
1807
1829
|
weekStartsOn,
|
|
1808
1830
|
displayFormat,
|
|
1809
1831
|
locale,
|
|
1832
|
+
displayTimezone,
|
|
1810
1833
|
isDisabled,
|
|
1811
1834
|
readOnly,
|
|
1812
1835
|
pickerId,
|
|
@@ -1820,13 +1843,14 @@ function DateTimePickerRoot({
|
|
|
1820
1843
|
format,
|
|
1821
1844
|
step,
|
|
1822
1845
|
withSeconds: false,
|
|
1846
|
+
displayTimezone,
|
|
1823
1847
|
isDisabled,
|
|
1824
1848
|
isReadOnly: readOnly,
|
|
1825
1849
|
currentTime,
|
|
1826
1850
|
pickerId,
|
|
1827
1851
|
labels: mergedTimeLabels
|
|
1828
1852
|
}),
|
|
1829
|
-
[currentValue, setTime, format, step, isDisabled, readOnly, currentTime, pickerId, mergedTimeLabels]
|
|
1853
|
+
[currentValue, setTime, format, step, displayTimezone, isDisabled, readOnly, currentTime, pickerId, mergedTimeLabels]
|
|
1830
1854
|
);
|
|
1831
1855
|
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerContext.Provider, { value: dateContext, children: /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: timeContext, children }) });
|
|
1832
1856
|
}
|
|
@@ -1836,7 +1860,9 @@ var DateTimePickerInput = react.forwardRef(
|
|
|
1836
1860
|
let displayValue = "";
|
|
1837
1861
|
if (ctx.value) {
|
|
1838
1862
|
try {
|
|
1839
|
-
|
|
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)}`;
|
|
1840
1866
|
} catch {
|
|
1841
1867
|
displayValue = ctx.value;
|
|
1842
1868
|
}
|
|
@@ -1906,7 +1932,8 @@ function useDatePicker(options = {}) {
|
|
|
1906
1932
|
onChange,
|
|
1907
1933
|
disabled = [],
|
|
1908
1934
|
weekStartsOn = 0,
|
|
1909
|
-
adapter = core.DateFnsAdapter
|
|
1935
|
+
adapter = core.DateFnsAdapter,
|
|
1936
|
+
displayTimezone
|
|
1910
1937
|
} = options;
|
|
1911
1938
|
const pickerId = react.useId();
|
|
1912
1939
|
const isControlled = react.useRef(controlledValue !== void 0).current;
|
|
@@ -1915,24 +1942,29 @@ function useDatePicker(options = {}) {
|
|
|
1915
1942
|
);
|
|
1916
1943
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1917
1944
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
1918
|
-
const [viewMonth, setViewMonth] = react.useState(
|
|
1919
|
-
|
|
1945
|
+
const [viewMonth, setViewMonth] = react.useState(
|
|
1946
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1947
|
+
);
|
|
1948
|
+
const [focusedDate, setFocusedDate] = react.useState(
|
|
1949
|
+
currentValue ?? adapter.today(displayTimezone)
|
|
1950
|
+
);
|
|
1920
1951
|
const selectDate = react.useCallback(
|
|
1921
1952
|
(iso) => {
|
|
1953
|
+
const normalized = iso && displayTimezone ? core.civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
1922
1954
|
if (!isControlled) {
|
|
1923
|
-
setUncontrolledValue(
|
|
1955
|
+
setUncontrolledValue(normalized);
|
|
1924
1956
|
}
|
|
1925
|
-
onChange?.(
|
|
1957
|
+
onChange?.(normalized);
|
|
1926
1958
|
setIsOpen(false);
|
|
1927
1959
|
},
|
|
1928
|
-
[isControlled, onChange]
|
|
1960
|
+
[isControlled, onChange, displayTimezone]
|
|
1929
1961
|
);
|
|
1930
1962
|
const open = react.useCallback(() => {
|
|
1931
1963
|
setIsOpen(true);
|
|
1932
|
-
const target = currentValue ?? adapter.today();
|
|
1964
|
+
const target = currentValue ?? adapter.today(displayTimezone);
|
|
1933
1965
|
setViewMonth(target);
|
|
1934
1966
|
setFocusedDate(target);
|
|
1935
|
-
}, [currentValue, adapter]);
|
|
1967
|
+
}, [currentValue, adapter, displayTimezone]);
|
|
1936
1968
|
const close = react.useCallback(() => {
|
|
1937
1969
|
setIsOpen(false);
|
|
1938
1970
|
}, []);
|
|
@@ -1954,7 +1986,8 @@ function useDatePicker(options = {}) {
|
|
|
1954
1986
|
weekStartsOn,
|
|
1955
1987
|
selected: currentValue,
|
|
1956
1988
|
focusedDate,
|
|
1957
|
-
disabled
|
|
1989
|
+
disabled,
|
|
1990
|
+
timezone: displayTimezone
|
|
1958
1991
|
});
|
|
1959
1992
|
return {
|
|
1960
1993
|
value: currentValue,
|
|
@@ -1982,7 +2015,8 @@ function useRangePicker(options = {}) {
|
|
|
1982
2015
|
onChange,
|
|
1983
2016
|
disabled = [],
|
|
1984
2017
|
weekStartsOn = 0,
|
|
1985
|
-
adapter = core.DateFnsAdapter
|
|
2018
|
+
adapter = core.DateFnsAdapter,
|
|
2019
|
+
displayTimezone
|
|
1986
2020
|
} = options;
|
|
1987
2021
|
const pickerId = react.useId();
|
|
1988
2022
|
const isControlled = react.useRef(controlledValue !== void 0).current;
|
|
@@ -1994,10 +2028,10 @@ function useRangePicker(options = {}) {
|
|
|
1994
2028
|
const [selectingTarget, setSelectingTarget] = react.useState("start");
|
|
1995
2029
|
const [hoverDate, setHoverDate] = react.useState(null);
|
|
1996
2030
|
const [viewMonth, setViewMonth] = react.useState(
|
|
1997
|
-
currentValue.start ?? adapter.today()
|
|
2031
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
1998
2032
|
);
|
|
1999
2033
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
2000
|
-
currentValue.start ?? adapter.today()
|
|
2034
|
+
currentValue.start ?? adapter.today(displayTimezone)
|
|
2001
2035
|
);
|
|
2002
2036
|
const setRange = react.useCallback(
|
|
2003
2037
|
(range) => {
|
|
@@ -2010,35 +2044,36 @@ function useRangePicker(options = {}) {
|
|
|
2010
2044
|
);
|
|
2011
2045
|
const selectDate = react.useCallback(
|
|
2012
2046
|
(iso) => {
|
|
2047
|
+
const normalized = displayTimezone ? core.civilMidnightFromUtcDay(iso, displayTimezone) : iso;
|
|
2013
2048
|
if (selectingTarget === "start") {
|
|
2014
|
-
setRange({ start:
|
|
2049
|
+
setRange({ start: normalized, end: null });
|
|
2015
2050
|
setSelectingTarget("end");
|
|
2016
2051
|
setHoverDate(null);
|
|
2017
2052
|
} else {
|
|
2018
2053
|
const start = currentValue.start;
|
|
2019
2054
|
if (!start) {
|
|
2020
|
-
setRange({ start:
|
|
2055
|
+
setRange({ start: normalized, end: null });
|
|
2021
2056
|
setSelectingTarget("end");
|
|
2022
2057
|
return;
|
|
2023
2058
|
}
|
|
2024
|
-
const newRange = adapter.isBefore(
|
|
2059
|
+
const newRange = adapter.isBefore(normalized, start) ? { start: normalized, end: start } : { start, end: normalized };
|
|
2025
2060
|
setRange(newRange);
|
|
2026
2061
|
setSelectingTarget("start");
|
|
2027
2062
|
setHoverDate(null);
|
|
2028
2063
|
setIsOpen(false);
|
|
2029
2064
|
}
|
|
2030
2065
|
},
|
|
2031
|
-
[selectingTarget, currentValue.start, adapter, setRange]
|
|
2066
|
+
[selectingTarget, currentValue.start, adapter, setRange, displayTimezone]
|
|
2032
2067
|
);
|
|
2033
2068
|
const open = react.useCallback(() => {
|
|
2034
2069
|
setIsOpen(true);
|
|
2035
|
-
const target = currentValue.start ?? adapter.today();
|
|
2070
|
+
const target = currentValue.start ?? adapter.today(displayTimezone);
|
|
2036
2071
|
setViewMonth(target);
|
|
2037
2072
|
setFocusedDate(target);
|
|
2038
2073
|
if (currentValue.start && currentValue.end) {
|
|
2039
2074
|
setSelectingTarget("start");
|
|
2040
2075
|
}
|
|
2041
|
-
}, [currentValue, adapter]);
|
|
2076
|
+
}, [currentValue, adapter, displayTimezone]);
|
|
2042
2077
|
const close = react.useCallback(() => {
|
|
2043
2078
|
setIsOpen(false);
|
|
2044
2079
|
setHoverDate(null);
|
|
@@ -2062,7 +2097,8 @@ function useRangePicker(options = {}) {
|
|
|
2062
2097
|
focusedDate,
|
|
2063
2098
|
disabled,
|
|
2064
2099
|
range: currentValue,
|
|
2065
|
-
rangeHover: hoverDate
|
|
2100
|
+
rangeHover: hoverDate,
|
|
2101
|
+
timezone: displayTimezone
|
|
2066
2102
|
});
|
|
2067
2103
|
return {
|
|
2068
2104
|
value: currentValue,
|
|
@@ -2095,7 +2131,8 @@ function useTimePicker(options = {}) {
|
|
|
2095
2131
|
defaultValue,
|
|
2096
2132
|
onChange,
|
|
2097
2133
|
format = "24h",
|
|
2098
|
-
step = 1
|
|
2134
|
+
step = 1,
|
|
2135
|
+
displayTimezone
|
|
2099
2136
|
} = options;
|
|
2100
2137
|
const pickerId = react.useId();
|
|
2101
2138
|
const isControlled = react.useRef(controlledValue !== void 0).current;
|
|
@@ -2104,16 +2141,19 @@ function useTimePicker(options = {}) {
|
|
|
2104
2141
|
);
|
|
2105
2142
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
2106
2143
|
const baseIso = currentValue ?? getDefaultIso3();
|
|
2107
|
-
const currentTime = react.useMemo(
|
|
2144
|
+
const currentTime = react.useMemo(
|
|
2145
|
+
() => displayTimezone ? core.getTimeInTimezone(baseIso, displayTimezone) : core.getTime(baseIso),
|
|
2146
|
+
[baseIso, displayTimezone]
|
|
2147
|
+
);
|
|
2108
2148
|
const setTime = react.useCallback(
|
|
2109
2149
|
(partial) => {
|
|
2110
|
-
const newIso = core.setTime(baseIso, partial);
|
|
2150
|
+
const newIso = displayTimezone ? core.setTimeInTimezone(baseIso, partial, displayTimezone) : core.setTime(baseIso, partial);
|
|
2111
2151
|
if (!isControlled) {
|
|
2112
2152
|
setUncontrolledValue(newIso);
|
|
2113
2153
|
}
|
|
2114
2154
|
onChange?.(newIso);
|
|
2115
2155
|
},
|
|
2116
|
-
[baseIso, isControlled, onChange]
|
|
2156
|
+
[baseIso, isControlled, onChange, displayTimezone]
|
|
2117
2157
|
);
|
|
2118
2158
|
const period = format === "12h" ? core.to12Hour(currentTime.hours).period : null;
|
|
2119
2159
|
const displayHour = format === "12h" ? core.to12Hour(currentTime.hours).hours12 : currentTime.hours;
|