@kalyx/react 0.4.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +132 -3
- package/README.md +6 -1
- package/dist/index.cjs +460 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +257 -5
- package/dist/index.d.ts +257 -5
- package/dist/index.js +458 -71
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -21,10 +21,23 @@ function useDatePickerContext(componentName) {
|
|
|
21
21
|
}
|
|
22
22
|
return context;
|
|
23
23
|
}
|
|
24
|
+
function useChangeEffect(value, callback) {
|
|
25
|
+
const callbackRef = react.useRef(callback);
|
|
26
|
+
callbackRef.current = callback;
|
|
27
|
+
const prevRef = react.useRef(value);
|
|
28
|
+
react.useEffect(() => {
|
|
29
|
+
if (prevRef.current !== value) {
|
|
30
|
+
prevRef.current = value;
|
|
31
|
+
callbackRef.current?.(value);
|
|
32
|
+
}
|
|
33
|
+
}, [value]);
|
|
34
|
+
}
|
|
24
35
|
function DatePickerRoot({
|
|
25
36
|
value: controlledValue,
|
|
26
37
|
defaultValue,
|
|
27
38
|
onChange,
|
|
39
|
+
onOpenChange,
|
|
40
|
+
onCalendarNavigate,
|
|
28
41
|
disabled = false,
|
|
29
42
|
readOnly = false,
|
|
30
43
|
weekStartsOn = 0,
|
|
@@ -49,6 +62,9 @@ function DatePickerRoot({
|
|
|
49
62
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
50
63
|
currentValue ?? adapter.today(displayTimezone)
|
|
51
64
|
);
|
|
65
|
+
useChangeEffect(isOpen, onOpenChange);
|
|
66
|
+
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
67
|
+
useChangeEffect(viewMonthStart, onCalendarNavigate);
|
|
52
68
|
const mergedLabels = react.useMemo(
|
|
53
69
|
() => ({ ...core.DEFAULT_DATEPICKER_LABELS, ...labelsProp }),
|
|
54
70
|
[labelsProp]
|
|
@@ -286,10 +302,15 @@ var DatePickerTrigger = react.forwardRef(
|
|
|
286
302
|
);
|
|
287
303
|
}
|
|
288
304
|
);
|
|
289
|
-
function usePopover({
|
|
305
|
+
function usePopover({
|
|
306
|
+
isOpen,
|
|
307
|
+
close,
|
|
308
|
+
referenceRef,
|
|
309
|
+
placement = "bottom-start"
|
|
310
|
+
}) {
|
|
290
311
|
const floatingRef = react.useRef(null);
|
|
291
312
|
const previousFocusRef = react.useRef(null);
|
|
292
|
-
const { refs, floatingStyles } = react$1.useFloating({
|
|
313
|
+
const { refs, floatingStyles, isPositioned } = react$1.useFloating({
|
|
293
314
|
open: isOpen,
|
|
294
315
|
placement,
|
|
295
316
|
middleware: [react$1.offset(4), react$1.flip(), react$1.shift({ padding: 8 })],
|
|
@@ -339,21 +360,28 @@ function usePopover({ isOpen, close, referenceRef, placement = "bottom-start" })
|
|
|
339
360
|
document.addEventListener("keydown", handleKeyDown);
|
|
340
361
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
341
362
|
}, [isOpen, close]);
|
|
342
|
-
const setFloatingRef = (
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
363
|
+
const setFloatingRef = react.useCallback(
|
|
364
|
+
(node) => {
|
|
365
|
+
floatingRef.current = node;
|
|
366
|
+
refs.setFloating(node);
|
|
367
|
+
if (node && referenceRef.current) {
|
|
368
|
+
refs.setReference(referenceRef.current);
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
[refs, referenceRef]
|
|
372
|
+
);
|
|
373
|
+
return { floatingStyles, setFloatingRef, isPositioned };
|
|
347
374
|
}
|
|
348
375
|
function DatePickerPopover({ children, ...props }) {
|
|
349
376
|
const ctx = useDatePickerContext("DatePicker.Popover");
|
|
350
377
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
351
|
-
const { floatingStyles, setFloatingRef } = usePopover({
|
|
378
|
+
const { floatingStyles, setFloatingRef, isPositioned } = usePopover({
|
|
352
379
|
isOpen: ctx.isOpen,
|
|
353
380
|
close: ctx.close,
|
|
354
381
|
referenceRef: ctx.referenceRef
|
|
355
382
|
});
|
|
356
383
|
if (!ctx.isOpen) return null;
|
|
384
|
+
const { style: userStyle, ...rest } = props;
|
|
357
385
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
358
386
|
"div",
|
|
359
387
|
{
|
|
@@ -362,8 +390,12 @@ function DatePickerPopover({ children, ...props }) {
|
|
|
362
390
|
role: "dialog",
|
|
363
391
|
"aria-label": ctx.labels.popoverLabel,
|
|
364
392
|
"aria-modal": "false",
|
|
365
|
-
|
|
366
|
-
|
|
393
|
+
...rest,
|
|
394
|
+
style: {
|
|
395
|
+
...userStyle,
|
|
396
|
+
...floatingStyles,
|
|
397
|
+
visibility: isPositioned ? void 0 : "hidden"
|
|
398
|
+
},
|
|
367
399
|
children
|
|
368
400
|
}
|
|
369
401
|
);
|
|
@@ -386,7 +418,11 @@ var srOnly = {
|
|
|
386
418
|
whiteSpace: "nowrap",
|
|
387
419
|
border: 0
|
|
388
420
|
};
|
|
389
|
-
function DatePickerCalendar({
|
|
421
|
+
function DatePickerCalendar({
|
|
422
|
+
classNames,
|
|
423
|
+
onTitleClick,
|
|
424
|
+
...props
|
|
425
|
+
}) {
|
|
390
426
|
const ctx = useDatePickerContext("DatePicker.Calendar");
|
|
391
427
|
const gridRef = react.useRef(null);
|
|
392
428
|
const [announcement, setAnnouncement] = react.useState("");
|
|
@@ -404,9 +440,7 @@ function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
|
404
440
|
const title = core.formatMonthYear(year, month, locale);
|
|
405
441
|
react.useEffect(() => {
|
|
406
442
|
if (!ctx.isOpen || !gridRef.current) return;
|
|
407
|
-
const focusedButton = gridRef.current.querySelector(
|
|
408
|
-
'[data-focused="true"]'
|
|
409
|
-
);
|
|
443
|
+
const focusedButton = gridRef.current.querySelector('[data-focused="true"]');
|
|
410
444
|
focusedButton?.focus({ preventScroll: true });
|
|
411
445
|
}, [focusedDate, ctx.isOpen]);
|
|
412
446
|
const navigateMonth = react.useCallback(
|
|
@@ -629,15 +663,7 @@ function DatePickerMonthGrid({
|
|
|
629
663
|
children: "<"
|
|
630
664
|
}
|
|
631
665
|
),
|
|
632
|
-
onTitleClick ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
633
|
-
"button",
|
|
634
|
-
{
|
|
635
|
-
type: "button",
|
|
636
|
-
className: classNames?.title,
|
|
637
|
-
onClick: onTitleClick,
|
|
638
|
-
children: currentYear
|
|
639
|
-
}
|
|
640
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: classNames?.title, children: currentYear }),
|
|
666
|
+
onTitleClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: classNames?.title, onClick: onTitleClick, children: currentYear }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: classNames?.title, children: currentYear }),
|
|
641
667
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
642
668
|
"button",
|
|
643
669
|
{
|
|
@@ -682,11 +708,7 @@ function DatePickerMonthGrid({
|
|
|
682
708
|
)
|
|
683
709
|
] });
|
|
684
710
|
}
|
|
685
|
-
function DatePickerYearGrid({
|
|
686
|
-
classNames,
|
|
687
|
-
onSelect,
|
|
688
|
-
...props
|
|
689
|
-
}) {
|
|
711
|
+
function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
690
712
|
const ctx = useDatePickerContext("DatePicker.YearGrid");
|
|
691
713
|
const { adapter, viewMonth } = ctx;
|
|
692
714
|
const currentYear = adapter.getYear(viewMonth);
|
|
@@ -778,6 +800,82 @@ function DatePickerYearGrid({
|
|
|
778
800
|
)
|
|
779
801
|
] });
|
|
780
802
|
}
|
|
803
|
+
function DatePickerPresets({ classNames, children, ...props }) {
|
|
804
|
+
const ctx = useDatePickerContext("DatePicker.Presets");
|
|
805
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "group", "aria-label": ctx.labels.popoverLabel, className: classNames?.root, ...props, children });
|
|
806
|
+
}
|
|
807
|
+
function resolveDatePreset(key, today, adapter) {
|
|
808
|
+
switch (key) {
|
|
809
|
+
case "today":
|
|
810
|
+
return today;
|
|
811
|
+
case "tomorrow":
|
|
812
|
+
return adapter.addDays(today, 1);
|
|
813
|
+
case "yesterday":
|
|
814
|
+
return adapter.addDays(today, -1);
|
|
815
|
+
case "startOfMonth":
|
|
816
|
+
return adapter.startOfMonth(today);
|
|
817
|
+
case "endOfMonth":
|
|
818
|
+
return adapter.startOfDay(adapter.endOfMonth(today));
|
|
819
|
+
case "startOfYear": {
|
|
820
|
+
const currentMonth = adapter.getMonth(today);
|
|
821
|
+
return adapter.startOfMonth(adapter.addMonths(today, -currentMonth));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
function DatePickerPreset({
|
|
826
|
+
value: presetKey,
|
|
827
|
+
date: directDate,
|
|
828
|
+
children,
|
|
829
|
+
onClick,
|
|
830
|
+
...props
|
|
831
|
+
}) {
|
|
832
|
+
const ctx = useDatePickerContext("DatePicker.Preset");
|
|
833
|
+
const handleClick = react.useCallback(
|
|
834
|
+
(e) => {
|
|
835
|
+
if (ctx.isDisabled || ctx.isReadOnly) return;
|
|
836
|
+
let resolved;
|
|
837
|
+
if (directDate) {
|
|
838
|
+
resolved = directDate;
|
|
839
|
+
} else if (presetKey) {
|
|
840
|
+
resolved = resolveDatePreset(
|
|
841
|
+
presetKey,
|
|
842
|
+
ctx.adapter.today(ctx.displayTimezone),
|
|
843
|
+
ctx.adapter
|
|
844
|
+
);
|
|
845
|
+
} else {
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
ctx.selectDate(resolved);
|
|
849
|
+
onClick?.(e);
|
|
850
|
+
},
|
|
851
|
+
[ctx, presetKey, directDate, onClick]
|
|
852
|
+
);
|
|
853
|
+
const isActive = (() => {
|
|
854
|
+
if (!ctx.value) return false;
|
|
855
|
+
let target;
|
|
856
|
+
if (directDate) {
|
|
857
|
+
target = directDate;
|
|
858
|
+
} else if (presetKey) {
|
|
859
|
+
target = resolveDatePreset(presetKey, ctx.adapter.today(ctx.displayTimezone), ctx.adapter);
|
|
860
|
+
} else {
|
|
861
|
+
return false;
|
|
862
|
+
}
|
|
863
|
+
return ctx.adapter.isSameDay(ctx.value, target, ctx.displayTimezone);
|
|
864
|
+
})();
|
|
865
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
866
|
+
"button",
|
|
867
|
+
{
|
|
868
|
+
type: "button",
|
|
869
|
+
role: "option",
|
|
870
|
+
"aria-selected": isActive,
|
|
871
|
+
"data-active": isActive || void 0,
|
|
872
|
+
disabled: ctx.isDisabled,
|
|
873
|
+
onClick: handleClick,
|
|
874
|
+
...props,
|
|
875
|
+
children
|
|
876
|
+
}
|
|
877
|
+
);
|
|
878
|
+
}
|
|
781
879
|
|
|
782
880
|
// src/components/DatePicker/index.ts
|
|
783
881
|
var DatePicker = Object.assign(DatePickerRoot, {
|
|
@@ -786,7 +884,9 @@ var DatePicker = Object.assign(DatePickerRoot, {
|
|
|
786
884
|
Popover: DatePickerPopover,
|
|
787
885
|
Calendar: DatePickerCalendar,
|
|
788
886
|
MonthGrid: DatePickerMonthGrid,
|
|
789
|
-
YearGrid: DatePickerYearGrid
|
|
887
|
+
YearGrid: DatePickerYearGrid,
|
|
888
|
+
Presets: DatePickerPresets,
|
|
889
|
+
Preset: DatePickerPreset
|
|
790
890
|
});
|
|
791
891
|
var RangePickerContext = react.createContext(null);
|
|
792
892
|
function useRangePickerContext(componentName) {
|
|
@@ -808,6 +908,8 @@ function RangePickerRoot({
|
|
|
808
908
|
value: controlledValue,
|
|
809
909
|
defaultValue,
|
|
810
910
|
onChange,
|
|
911
|
+
onOpenChange,
|
|
912
|
+
onCalendarNavigate,
|
|
811
913
|
disabled = false,
|
|
812
914
|
readOnly = false,
|
|
813
915
|
weekStartsOn = 0,
|
|
@@ -834,6 +936,9 @@ function RangePickerRoot({
|
|
|
834
936
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
835
937
|
currentValue.start ?? adapter.today(displayTimezone)
|
|
836
938
|
);
|
|
939
|
+
useChangeEffect(isOpen, onOpenChange);
|
|
940
|
+
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
941
|
+
useChangeEffect(viewMonthStart, onCalendarNavigate);
|
|
837
942
|
const mergedLabels = react.useMemo(
|
|
838
943
|
() => ({ ...core.DEFAULT_RANGEPICKER_LABELS, ...labelsProp }),
|
|
839
944
|
[labelsProp]
|
|
@@ -1018,12 +1123,13 @@ var RangePickerInput = react.forwardRef(
|
|
|
1018
1123
|
function RangePickerPopover({ children, ...props }) {
|
|
1019
1124
|
const ctx = useRangePickerContext("RangePicker.Popover");
|
|
1020
1125
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
1021
|
-
const { floatingStyles, setFloatingRef } = usePopover({
|
|
1126
|
+
const { floatingStyles, setFloatingRef, isPositioned } = usePopover({
|
|
1022
1127
|
isOpen: ctx.isOpen,
|
|
1023
1128
|
close: ctx.close,
|
|
1024
1129
|
referenceRef: ctx.referenceRef
|
|
1025
1130
|
});
|
|
1026
1131
|
if (!ctx.isOpen) return null;
|
|
1132
|
+
const { style: userStyle, ...rest } = props;
|
|
1027
1133
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1028
1134
|
"div",
|
|
1029
1135
|
{
|
|
@@ -1032,8 +1138,12 @@ function RangePickerPopover({ children, ...props }) {
|
|
|
1032
1138
|
role: "dialog",
|
|
1033
1139
|
"aria-label": ctx.labels.popoverLabel,
|
|
1034
1140
|
"aria-modal": "false",
|
|
1035
|
-
|
|
1036
|
-
|
|
1141
|
+
...rest,
|
|
1142
|
+
style: {
|
|
1143
|
+
...userStyle,
|
|
1144
|
+
...floatingStyles,
|
|
1145
|
+
visibility: isPositioned ? void 0 : "hidden"
|
|
1146
|
+
},
|
|
1037
1147
|
children
|
|
1038
1148
|
}
|
|
1039
1149
|
);
|
|
@@ -1056,7 +1166,11 @@ var srOnly2 = {
|
|
|
1056
1166
|
whiteSpace: "nowrap",
|
|
1057
1167
|
border: 0
|
|
1058
1168
|
};
|
|
1059
|
-
function RangePickerCalendar({
|
|
1169
|
+
function RangePickerCalendar({
|
|
1170
|
+
classNames,
|
|
1171
|
+
selectionMode = "range",
|
|
1172
|
+
...props
|
|
1173
|
+
}) {
|
|
1060
1174
|
const ctx = useRangePickerContext("RangePicker.Calendar");
|
|
1061
1175
|
const gridRef = react.useRef(null);
|
|
1062
1176
|
const [announcement, setAnnouncement] = react.useState("");
|
|
@@ -1086,9 +1200,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1086
1200
|
const title = core.formatMonthYear(year, month, locale);
|
|
1087
1201
|
react.useEffect(() => {
|
|
1088
1202
|
if (!ctx.isOpen || !gridRef.current) return;
|
|
1089
|
-
const focusedButton = gridRef.current.querySelector(
|
|
1090
|
-
'[data-focused="true"]'
|
|
1091
|
-
);
|
|
1203
|
+
const focusedButton = gridRef.current.querySelector('[data-focused="true"]');
|
|
1092
1204
|
focusedButton?.focus({ preventScroll: true });
|
|
1093
1205
|
}, [focusedDate, ctx.isOpen]);
|
|
1094
1206
|
const navigateMonth = react.useCallback(
|
|
@@ -1102,21 +1214,39 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1102
1214
|
},
|
|
1103
1215
|
[adapter, viewMonth, ctx, locale]
|
|
1104
1216
|
);
|
|
1217
|
+
const commitDay = react.useCallback(
|
|
1218
|
+
(iso) => {
|
|
1219
|
+
if (selectionMode === "week") {
|
|
1220
|
+
const weekStart = adapter.startOfWeek(iso, weekStartsOn);
|
|
1221
|
+
const weekEnd = adapter.startOfDay(adapter.endOfWeek(iso, weekStartsOn));
|
|
1222
|
+
const range = { start: weekStart, end: weekEnd };
|
|
1223
|
+
ctx.setRange(range);
|
|
1224
|
+
ctx.close();
|
|
1225
|
+
setAnnouncement(
|
|
1226
|
+
`${safeFormatFullDate2(weekStart, locale)} \u2013 ${safeFormatFullDate2(weekEnd, locale)}`
|
|
1227
|
+
);
|
|
1228
|
+
} else {
|
|
1229
|
+
ctx.selectDate(iso);
|
|
1230
|
+
setAnnouncement(safeFormatFullDate2(iso, locale));
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
[selectionMode, adapter, weekStartsOn, ctx, locale]
|
|
1234
|
+
);
|
|
1105
1235
|
const handleDayClick = react.useCallback(
|
|
1106
1236
|
(day) => {
|
|
1107
1237
|
if (day.isDisabled) return;
|
|
1108
|
-
|
|
1109
|
-
setAnnouncement(safeFormatFullDate2(day.isoString, locale));
|
|
1238
|
+
commitDay(day.isoString);
|
|
1110
1239
|
},
|
|
1111
|
-
[
|
|
1240
|
+
[commitDay]
|
|
1112
1241
|
);
|
|
1113
1242
|
const handleDayMouseEnter = react.useCallback(
|
|
1114
1243
|
(day) => {
|
|
1244
|
+
if (selectionMode === "week") return;
|
|
1115
1245
|
if (selectingTarget === "end" && value.start && !day.isDisabled) {
|
|
1116
1246
|
ctx.setHoverDate(day.isoString);
|
|
1117
1247
|
}
|
|
1118
1248
|
},
|
|
1119
|
-
[selectingTarget, value.start, ctx]
|
|
1249
|
+
[selectionMode, selectingTarget, value.start, ctx]
|
|
1120
1250
|
);
|
|
1121
1251
|
const handleMouseLeave = react.useCallback(() => {
|
|
1122
1252
|
ctx.setHoverDate(null);
|
|
@@ -1153,7 +1283,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1153
1283
|
case " ":
|
|
1154
1284
|
e.preventDefault();
|
|
1155
1285
|
if (!core.isDateDisabled(focusedDate, disabled, adapter)) {
|
|
1156
|
-
|
|
1286
|
+
commitDay(focusedDate);
|
|
1157
1287
|
}
|
|
1158
1288
|
return;
|
|
1159
1289
|
case "Escape":
|
|
@@ -1168,12 +1298,23 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1168
1298
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
1169
1299
|
ctx.setViewMonth(newFocused);
|
|
1170
1300
|
}
|
|
1171
|
-
if (selectingTarget === "end" && value.start) {
|
|
1301
|
+
if (selectionMode === "range" && selectingTarget === "end" && value.start) {
|
|
1172
1302
|
ctx.setHoverDate(newFocused);
|
|
1173
1303
|
}
|
|
1174
1304
|
}
|
|
1175
1305
|
},
|
|
1176
|
-
[
|
|
1306
|
+
[
|
|
1307
|
+
adapter,
|
|
1308
|
+
focusedDate,
|
|
1309
|
+
viewMonth,
|
|
1310
|
+
weekStartsOn,
|
|
1311
|
+
disabled,
|
|
1312
|
+
ctx,
|
|
1313
|
+
selectionMode,
|
|
1314
|
+
selectingTarget,
|
|
1315
|
+
value.start,
|
|
1316
|
+
commitDay
|
|
1317
|
+
]
|
|
1177
1318
|
);
|
|
1178
1319
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, onMouseLeave: handleMouseLeave, children: [
|
|
1179
1320
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
@@ -1230,7 +1371,7 @@ function RangePickerCalendar({ classNames, ...props }) {
|
|
|
1230
1371
|
day.isDisabled && classNames?.dayDisabled,
|
|
1231
1372
|
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
1232
1373
|
].filter(Boolean).join(" ") || void 0;
|
|
1233
|
-
const isSelected = day.isRangeStart || day.isRangeEnd;
|
|
1374
|
+
const isSelected = selectionMode === "week" ? day.isRangeStart || day.isRangeEnd || day.isInRange : day.isRangeStart || day.isRangeEnd;
|
|
1234
1375
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1235
1376
|
"td",
|
|
1236
1377
|
{
|
|
@@ -1310,9 +1451,7 @@ function resolvePreset(key, today, adapter) {
|
|
|
1310
1451
|
}
|
|
1311
1452
|
case "thisYear": {
|
|
1312
1453
|
const currentMonth = new Date(today).getUTCMonth();
|
|
1313
|
-
const yearStart = adapter.startOfMonth(
|
|
1314
|
-
adapter.addMonths(today, -currentMonth)
|
|
1315
|
-
);
|
|
1454
|
+
const yearStart = adapter.startOfMonth(adapter.addMonths(today, -currentMonth));
|
|
1316
1455
|
return { start: yearStart, end: today };
|
|
1317
1456
|
}
|
|
1318
1457
|
}
|
|
@@ -1448,7 +1587,19 @@ function TimePickerRoot({
|
|
|
1448
1587
|
pickerId,
|
|
1449
1588
|
labels: mergedLabels
|
|
1450
1589
|
}),
|
|
1451
|
-
[
|
|
1590
|
+
[
|
|
1591
|
+
currentValue,
|
|
1592
|
+
setTime,
|
|
1593
|
+
format,
|
|
1594
|
+
step,
|
|
1595
|
+
withSeconds,
|
|
1596
|
+
displayTimezone,
|
|
1597
|
+
disabled,
|
|
1598
|
+
readOnly,
|
|
1599
|
+
currentTime,
|
|
1600
|
+
pickerId,
|
|
1601
|
+
mergedLabels
|
|
1602
|
+
]
|
|
1452
1603
|
);
|
|
1453
1604
|
return /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: contextValue, children });
|
|
1454
1605
|
}
|
|
@@ -1465,12 +1616,9 @@ var TimePickerInput = react.forwardRef(
|
|
|
1465
1616
|
}
|
|
1466
1617
|
setInputText(null);
|
|
1467
1618
|
}, [inputText, ctx]);
|
|
1468
|
-
const handleChange = react.useCallback(
|
|
1469
|
-
(e)
|
|
1470
|
-
|
|
1471
|
-
},
|
|
1472
|
-
[]
|
|
1473
|
-
);
|
|
1619
|
+
const handleChange = react.useCallback((e) => {
|
|
1620
|
+
setInputText(e.target.value);
|
|
1621
|
+
}, []);
|
|
1474
1622
|
const handleBlur = react.useCallback(
|
|
1475
1623
|
(e) => {
|
|
1476
1624
|
commitInput();
|
|
@@ -1543,9 +1691,7 @@ function useListboxNavigation({
|
|
|
1543
1691
|
onSelect(target);
|
|
1544
1692
|
cancelAnimationFrame(rafIdRef.current);
|
|
1545
1693
|
rafIdRef.current = requestAnimationFrame(() => {
|
|
1546
|
-
const next = listRef.current?.querySelector(
|
|
1547
|
-
'[data-selected="true"]'
|
|
1548
|
-
);
|
|
1694
|
+
const next = listRef.current?.querySelector('[data-selected="true"]');
|
|
1549
1695
|
next?.focus();
|
|
1550
1696
|
});
|
|
1551
1697
|
}
|
|
@@ -1682,10 +1828,19 @@ function TimePickerAmPmToggle({ classNames, ...props }) {
|
|
|
1682
1828
|
}
|
|
1683
1829
|
);
|
|
1684
1830
|
};
|
|
1685
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1831
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1832
|
+
"div",
|
|
1833
|
+
{
|
|
1834
|
+
role: "radiogroup",
|
|
1835
|
+
"aria-label": ctx.labels.amPmToggle,
|
|
1836
|
+
className: classNames?.root,
|
|
1837
|
+
...props,
|
|
1838
|
+
children: [
|
|
1839
|
+
renderButton("AM"),
|
|
1840
|
+
renderButton("PM")
|
|
1841
|
+
]
|
|
1842
|
+
}
|
|
1843
|
+
);
|
|
1689
1844
|
}
|
|
1690
1845
|
|
|
1691
1846
|
// src/components/TimePicker/index.ts
|
|
@@ -1702,6 +1857,8 @@ function DateTimePickerRoot({
|
|
|
1702
1857
|
value: controlledValue,
|
|
1703
1858
|
defaultValue,
|
|
1704
1859
|
onChange,
|
|
1860
|
+
onOpenChange,
|
|
1861
|
+
onCalendarNavigate,
|
|
1705
1862
|
format = "24h",
|
|
1706
1863
|
step = 1,
|
|
1707
1864
|
disabled = false,
|
|
@@ -1736,6 +1893,9 @@ function DateTimePickerRoot({
|
|
|
1736
1893
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
1737
1894
|
currentValue ?? adapter.today(displayTimezone)
|
|
1738
1895
|
);
|
|
1896
|
+
useChangeEffect(isOpen, onOpenChange);
|
|
1897
|
+
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
1898
|
+
useChangeEffect(viewMonthStart, onCalendarNavigate);
|
|
1739
1899
|
const isDisabled = typeof disabled === "boolean" ? disabled : false;
|
|
1740
1900
|
const disabledRules = react.useMemo(
|
|
1741
1901
|
() => Array.isArray(disabled) ? disabled : [],
|
|
@@ -1850,7 +2010,18 @@ function DateTimePickerRoot({
|
|
|
1850
2010
|
pickerId,
|
|
1851
2011
|
labels: mergedTimeLabels
|
|
1852
2012
|
}),
|
|
1853
|
-
[
|
|
2013
|
+
[
|
|
2014
|
+
currentValue,
|
|
2015
|
+
setTime,
|
|
2016
|
+
format,
|
|
2017
|
+
step,
|
|
2018
|
+
displayTimezone,
|
|
2019
|
+
isDisabled,
|
|
2020
|
+
readOnly,
|
|
2021
|
+
currentTime,
|
|
2022
|
+
pickerId,
|
|
2023
|
+
mergedTimeLabels
|
|
2024
|
+
]
|
|
1854
2025
|
);
|
|
1855
2026
|
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerContext.Provider, { value: dateContext, children: /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: timeContext, children }) });
|
|
1856
2027
|
}
|
|
@@ -1925,6 +2096,228 @@ var DateTimePicker = Object.assign(DateTimePickerRoot, {
|
|
|
1925
2096
|
MinuteList: TimePickerMinuteList,
|
|
1926
2097
|
AmPmToggle: TimePickerAmPmToggle
|
|
1927
2098
|
});
|
|
2099
|
+
function MonthPickerRoot(props) {
|
|
2100
|
+
const displayFormat = props.displayFormat ?? "yyyy-MM";
|
|
2101
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerRoot, { ...props, displayFormat });
|
|
2102
|
+
}
|
|
2103
|
+
function MonthPickerGrid({ classNames, ...props }) {
|
|
2104
|
+
const ctx = useDatePickerContext("MonthPicker.Grid");
|
|
2105
|
+
const { adapter, viewMonth, locale, value, displayTimezone, labels } = ctx;
|
|
2106
|
+
const currentYear = adapter.getYear(viewMonth);
|
|
2107
|
+
const [valueYear, valueMonthZeroBased] = react.useMemo(() => {
|
|
2108
|
+
if (!value) return [null, null];
|
|
2109
|
+
try {
|
|
2110
|
+
const [y, m] = adapter.format(value, "yyyy-MM", displayTimezone).split("-").map(Number);
|
|
2111
|
+
return [y, m - 1];
|
|
2112
|
+
} catch {
|
|
2113
|
+
return [null, null];
|
|
2114
|
+
}
|
|
2115
|
+
}, [value, adapter, displayTimezone]);
|
|
2116
|
+
const today = adapter.today(displayTimezone);
|
|
2117
|
+
const todayYear = adapter.getYear(today);
|
|
2118
|
+
const todayMonth = adapter.getMonth(today);
|
|
2119
|
+
const navigateYear = react.useCallback(
|
|
2120
|
+
(direction) => {
|
|
2121
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
2122
|
+
},
|
|
2123
|
+
[adapter, viewMonth, ctx]
|
|
2124
|
+
);
|
|
2125
|
+
const handleMonthSelect = react.useCallback(
|
|
2126
|
+
(monthIndex) => {
|
|
2127
|
+
const target = new Date(Date.UTC(currentYear, monthIndex, 1)).toISOString();
|
|
2128
|
+
ctx.selectDate(target);
|
|
2129
|
+
},
|
|
2130
|
+
[currentYear, ctx]
|
|
2131
|
+
);
|
|
2132
|
+
const months = Array.from({ length: 12 }, (_, i) => ({
|
|
2133
|
+
index: i,
|
|
2134
|
+
name: core.getMonthName(i, locale),
|
|
2135
|
+
isSelected: valueYear === currentYear && valueMonthZeroBased === i,
|
|
2136
|
+
isCurrent: todayYear === currentYear && todayMonth === i
|
|
2137
|
+
}));
|
|
2138
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
2139
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
2140
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2141
|
+
"button",
|
|
2142
|
+
{
|
|
2143
|
+
type: "button",
|
|
2144
|
+
className: classNames?.navButton,
|
|
2145
|
+
onClick: () => navigateYear(-1),
|
|
2146
|
+
"aria-label": labels.prevYear,
|
|
2147
|
+
children: "<"
|
|
2148
|
+
}
|
|
2149
|
+
),
|
|
2150
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: classNames?.title, children: currentYear }),
|
|
2151
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2152
|
+
"button",
|
|
2153
|
+
{
|
|
2154
|
+
type: "button",
|
|
2155
|
+
className: classNames?.navButton,
|
|
2156
|
+
onClick: () => navigateYear(1),
|
|
2157
|
+
"aria-label": labels.nextYear,
|
|
2158
|
+
children: ">"
|
|
2159
|
+
}
|
|
2160
|
+
)
|
|
2161
|
+
] }),
|
|
2162
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "grid", "aria-label": `${currentYear} months`, className: classNames?.grid, children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2163
|
+
"div",
|
|
2164
|
+
{
|
|
2165
|
+
role: "row",
|
|
2166
|
+
className: classNames?.gridRow,
|
|
2167
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2168
|
+
children: months.slice(rowIndex * 3, rowIndex * 3 + 3).map((m) => {
|
|
2169
|
+
const monthClass = [
|
|
2170
|
+
classNames?.month,
|
|
2171
|
+
m.isSelected && classNames?.monthSelected,
|
|
2172
|
+
m.isCurrent && classNames?.monthCurrent
|
|
2173
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2174
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2175
|
+
"button",
|
|
2176
|
+
{
|
|
2177
|
+
type: "button",
|
|
2178
|
+
role: "gridcell",
|
|
2179
|
+
"aria-selected": m.isSelected || void 0,
|
|
2180
|
+
"aria-current": m.isCurrent ? "date" : void 0,
|
|
2181
|
+
"data-selected": m.isSelected || void 0,
|
|
2182
|
+
"data-current": m.isCurrent || void 0,
|
|
2183
|
+
className: monthClass,
|
|
2184
|
+
onClick: () => handleMonthSelect(m.index),
|
|
2185
|
+
children: m.name
|
|
2186
|
+
},
|
|
2187
|
+
m.index
|
|
2188
|
+
);
|
|
2189
|
+
})
|
|
2190
|
+
},
|
|
2191
|
+
rowIndex
|
|
2192
|
+
)) })
|
|
2193
|
+
] });
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
// src/components/MonthPicker/index.ts
|
|
2197
|
+
var MonthPicker = Object.assign(MonthPickerRoot, {
|
|
2198
|
+
Input: DatePickerInput,
|
|
2199
|
+
Trigger: DatePickerTrigger,
|
|
2200
|
+
Popover: DatePickerPopover,
|
|
2201
|
+
Grid: MonthPickerGrid
|
|
2202
|
+
});
|
|
2203
|
+
function YearPickerRoot(props) {
|
|
2204
|
+
const displayFormat = props.displayFormat ?? "yyyy";
|
|
2205
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerRoot, { ...props, displayFormat });
|
|
2206
|
+
}
|
|
2207
|
+
function YearPickerGrid({ classNames, ...props }) {
|
|
2208
|
+
const ctx = useDatePickerContext("YearPicker.Grid");
|
|
2209
|
+
const { adapter, viewMonth, value, displayTimezone, labels } = ctx;
|
|
2210
|
+
const currentYear = adapter.getYear(viewMonth);
|
|
2211
|
+
const decadeStart = currentYear - currentYear % 12;
|
|
2212
|
+
const valueYear = react.useMemo(() => {
|
|
2213
|
+
if (!value) return null;
|
|
2214
|
+
try {
|
|
2215
|
+
return Number(adapter.format(value, "yyyy", displayTimezone));
|
|
2216
|
+
} catch {
|
|
2217
|
+
return null;
|
|
2218
|
+
}
|
|
2219
|
+
}, [value, adapter, displayTimezone]);
|
|
2220
|
+
const todayYear = adapter.getYear(adapter.today(displayTimezone));
|
|
2221
|
+
const navigateDecade = react.useCallback(
|
|
2222
|
+
(direction) => {
|
|
2223
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
2224
|
+
},
|
|
2225
|
+
[adapter, viewMonth, ctx]
|
|
2226
|
+
);
|
|
2227
|
+
const handleYearSelect = react.useCallback(
|
|
2228
|
+
(year) => {
|
|
2229
|
+
const target = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2230
|
+
ctx.selectDate(target);
|
|
2231
|
+
},
|
|
2232
|
+
[ctx]
|
|
2233
|
+
);
|
|
2234
|
+
const years = Array.from({ length: 12 }, (_, i) => {
|
|
2235
|
+
const year = decadeStart + i;
|
|
2236
|
+
return {
|
|
2237
|
+
value: year,
|
|
2238
|
+
isSelected: year === valueYear,
|
|
2239
|
+
isCurrent: year === todayYear
|
|
2240
|
+
};
|
|
2241
|
+
});
|
|
2242
|
+
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
2243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
2244
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
2245
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2246
|
+
"button",
|
|
2247
|
+
{
|
|
2248
|
+
type: "button",
|
|
2249
|
+
className: classNames?.navButton,
|
|
2250
|
+
onClick: () => navigateDecade(-1),
|
|
2251
|
+
"aria-label": labels.prevDecade,
|
|
2252
|
+
children: "<"
|
|
2253
|
+
}
|
|
2254
|
+
),
|
|
2255
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: classNames?.title, children: rangeLabel }),
|
|
2256
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2257
|
+
"button",
|
|
2258
|
+
{
|
|
2259
|
+
type: "button",
|
|
2260
|
+
className: classNames?.navButton,
|
|
2261
|
+
onClick: () => navigateDecade(1),
|
|
2262
|
+
"aria-label": labels.nextDecade,
|
|
2263
|
+
children: ">"
|
|
2264
|
+
}
|
|
2265
|
+
)
|
|
2266
|
+
] }),
|
|
2267
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "grid", "aria-label": rangeLabel, className: classNames?.grid, children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2268
|
+
"div",
|
|
2269
|
+
{
|
|
2270
|
+
role: "row",
|
|
2271
|
+
className: classNames?.gridRow,
|
|
2272
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2273
|
+
children: years.slice(rowIndex * 3, rowIndex * 3 + 3).map((y) => {
|
|
2274
|
+
const yearClass = [
|
|
2275
|
+
classNames?.year,
|
|
2276
|
+
y.isSelected && classNames?.yearSelected,
|
|
2277
|
+
y.isCurrent && classNames?.yearCurrent
|
|
2278
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2279
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2280
|
+
"button",
|
|
2281
|
+
{
|
|
2282
|
+
type: "button",
|
|
2283
|
+
role: "gridcell",
|
|
2284
|
+
"aria-selected": y.isSelected || void 0,
|
|
2285
|
+
"aria-current": y.isCurrent ? "date" : void 0,
|
|
2286
|
+
"data-selected": y.isSelected || void 0,
|
|
2287
|
+
"data-current": y.isCurrent || void 0,
|
|
2288
|
+
className: yearClass,
|
|
2289
|
+
onClick: () => handleYearSelect(y.value),
|
|
2290
|
+
children: y.value
|
|
2291
|
+
},
|
|
2292
|
+
y.value
|
|
2293
|
+
);
|
|
2294
|
+
})
|
|
2295
|
+
},
|
|
2296
|
+
rowIndex
|
|
2297
|
+
)) })
|
|
2298
|
+
] });
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
// src/components/YearPicker/index.ts
|
|
2302
|
+
var YearPicker = Object.assign(YearPickerRoot, {
|
|
2303
|
+
Input: DatePickerInput,
|
|
2304
|
+
Trigger: DatePickerTrigger,
|
|
2305
|
+
Popover: DatePickerPopover,
|
|
2306
|
+
Grid: YearPickerGrid
|
|
2307
|
+
});
|
|
2308
|
+
function WeekPickerRoot(props) {
|
|
2309
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RangePickerRoot, { ...props });
|
|
2310
|
+
}
|
|
2311
|
+
function WeekPickerCalendar(props) {
|
|
2312
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RangePickerCalendar, { ...props, selectionMode: "week" });
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
// src/components/WeekPicker/index.ts
|
|
2316
|
+
var WeekPicker = Object.assign(WeekPickerRoot, {
|
|
2317
|
+
Input: RangePickerInput,
|
|
2318
|
+
Popover: RangePickerPopover,
|
|
2319
|
+
Calendar: WeekPickerCalendar
|
|
2320
|
+
});
|
|
1928
2321
|
function useDatePicker(options = {}) {
|
|
1929
2322
|
const {
|
|
1930
2323
|
value: controlledValue,
|
|
@@ -2164,14 +2557,8 @@ function useTimePicker(options = {}) {
|
|
|
2164
2557
|
},
|
|
2165
2558
|
[format, period, setTime]
|
|
2166
2559
|
);
|
|
2167
|
-
const setMinute = react.useCallback(
|
|
2168
|
-
|
|
2169
|
-
[setTime]
|
|
2170
|
-
);
|
|
2171
|
-
const setSecond = react.useCallback(
|
|
2172
|
-
(second) => setTime({ seconds: second }),
|
|
2173
|
-
[setTime]
|
|
2174
|
-
);
|
|
2560
|
+
const setMinute = react.useCallback((minute) => setTime({ minutes: minute }), [setTime]);
|
|
2561
|
+
const setSecond = react.useCallback((second) => setTime({ seconds: second }), [setTime]);
|
|
2175
2562
|
const setPeriod = react.useCallback(
|
|
2176
2563
|
(newPeriod) => {
|
|
2177
2564
|
if (format !== "12h") return;
|
|
@@ -2203,8 +2590,11 @@ Object.defineProperty(exports, "DateFnsAdapter", {
|
|
|
2203
2590
|
});
|
|
2204
2591
|
exports.DatePicker = DatePicker;
|
|
2205
2592
|
exports.DateTimePicker = DateTimePicker;
|
|
2593
|
+
exports.MonthPicker = MonthPicker;
|
|
2206
2594
|
exports.RangePicker = RangePicker;
|
|
2207
2595
|
exports.TimePicker = TimePicker;
|
|
2596
|
+
exports.WeekPicker = WeekPicker;
|
|
2597
|
+
exports.YearPicker = YearPicker;
|
|
2208
2598
|
exports.useDatePicker = useDatePicker;
|
|
2209
2599
|
exports.useRangePicker = useRangePicker;
|
|
2210
2600
|
exports.useTimePicker = useTimePicker;
|