@kalyx/react 1.0.0-rc.3 → 1.0.0-rc.5
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 +86 -0
- package/README.md +2 -2
- package/dist/index.cjs +355 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +355 -143
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -685,6 +685,86 @@ function DatePickerCalendar({
|
|
|
685
685
|
/* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: srOnly, children: announcement })
|
|
686
686
|
] });
|
|
687
687
|
}
|
|
688
|
+
function isRangeFullyDisabled(start, end, rules, adapter) {
|
|
689
|
+
for (const rule of rules) {
|
|
690
|
+
if ("before" in rule && adapter.isBefore(end, rule.before)) return true;
|
|
691
|
+
if ("after" in rule && adapter.isAfter(start, rule.after)) return true;
|
|
692
|
+
}
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
695
|
+
function useGridState(opts) {
|
|
696
|
+
const { initialIndex, disabledFlags, onSelect, onPageUp, onPageDown, onEscape } = opts;
|
|
697
|
+
const gridRef = useRef(null);
|
|
698
|
+
const [focusedIndex, setFocusedIndex] = useState(initialIndex);
|
|
699
|
+
const handleKeyDown = (e) => {
|
|
700
|
+
let next = null;
|
|
701
|
+
let step = 1;
|
|
702
|
+
switch (e.key) {
|
|
703
|
+
case "ArrowLeft":
|
|
704
|
+
next = Math.max(0, focusedIndex - 1);
|
|
705
|
+
step = -1;
|
|
706
|
+
break;
|
|
707
|
+
case "ArrowRight":
|
|
708
|
+
next = Math.min(11, focusedIndex + 1);
|
|
709
|
+
break;
|
|
710
|
+
case "ArrowUp":
|
|
711
|
+
next = Math.max(0, focusedIndex - 3);
|
|
712
|
+
step = -1;
|
|
713
|
+
break;
|
|
714
|
+
case "ArrowDown":
|
|
715
|
+
next = Math.min(11, focusedIndex + 3);
|
|
716
|
+
break;
|
|
717
|
+
case "Home":
|
|
718
|
+
next = focusedIndex - focusedIndex % 3;
|
|
719
|
+
step = -1;
|
|
720
|
+
break;
|
|
721
|
+
case "End":
|
|
722
|
+
next = focusedIndex - focusedIndex % 3 + 2;
|
|
723
|
+
break;
|
|
724
|
+
case "PageUp":
|
|
725
|
+
e.preventDefault();
|
|
726
|
+
onPageUp();
|
|
727
|
+
return;
|
|
728
|
+
case "PageDown":
|
|
729
|
+
e.preventDefault();
|
|
730
|
+
onPageDown();
|
|
731
|
+
return;
|
|
732
|
+
case "Enter":
|
|
733
|
+
case " ":
|
|
734
|
+
e.preventDefault();
|
|
735
|
+
onSelect(focusedIndex);
|
|
736
|
+
return;
|
|
737
|
+
case "Escape":
|
|
738
|
+
onEscape();
|
|
739
|
+
return;
|
|
740
|
+
default:
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
if (next === null) return;
|
|
744
|
+
e.preventDefault();
|
|
745
|
+
if (disabledFlags) {
|
|
746
|
+
let attempts = 0;
|
|
747
|
+
while (next >= 0 && next < 12 && disabledFlags[next] && attempts < 12) {
|
|
748
|
+
next += step;
|
|
749
|
+
attempts++;
|
|
750
|
+
}
|
|
751
|
+
if (next < 0 || next >= 12 || disabledFlags[next]) return;
|
|
752
|
+
}
|
|
753
|
+
if (next !== focusedIndex) setFocusedIndex(next);
|
|
754
|
+
};
|
|
755
|
+
useEffect(() => {
|
|
756
|
+
if (!disabledFlags || !disabledFlags[focusedIndex]) return;
|
|
757
|
+
const firstEnabled = disabledFlags.findIndex((d) => !d);
|
|
758
|
+
if (firstEnabled !== -1 && firstEnabled !== focusedIndex) {
|
|
759
|
+
setFocusedIndex(firstEnabled);
|
|
760
|
+
}
|
|
761
|
+
}, [disabledFlags, focusedIndex]);
|
|
762
|
+
useEffect(() => {
|
|
763
|
+
const btn = gridRef.current?.querySelector('[data-focused="true"]');
|
|
764
|
+
btn?.focus({ preventScroll: true });
|
|
765
|
+
}, [focusedIndex]);
|
|
766
|
+
return { gridRef, focusedIndex, handleKeyDown };
|
|
767
|
+
}
|
|
688
768
|
function DatePickerMonthGrid({
|
|
689
769
|
classNames,
|
|
690
770
|
onSelect,
|
|
@@ -692,15 +772,18 @@ function DatePickerMonthGrid({
|
|
|
692
772
|
...props
|
|
693
773
|
}) {
|
|
694
774
|
const ctx = useDatePickerContext("DatePicker.MonthGrid");
|
|
695
|
-
const { adapter, viewMonth, locale } = ctx;
|
|
775
|
+
const { adapter, viewMonth, locale, displayTimezone } = ctx;
|
|
696
776
|
const currentYear = adapter.getYear(viewMonth);
|
|
697
777
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
698
|
-
const
|
|
699
|
-
|
|
778
|
+
const [today, setToday] = useState(null);
|
|
779
|
+
useEffect(() => {
|
|
780
|
+
setToday(adapter.today(displayTimezone));
|
|
781
|
+
}, [adapter, displayTimezone]);
|
|
782
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
783
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
700
784
|
const navigateYear = useCallback(
|
|
701
785
|
(direction) => {
|
|
702
|
-
|
|
703
|
-
ctx.setViewMonth(newDate);
|
|
786
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
704
787
|
},
|
|
705
788
|
[adapter, viewMonth, ctx]
|
|
706
789
|
);
|
|
@@ -713,12 +796,13 @@ function DatePickerMonthGrid({
|
|
|
713
796
|
},
|
|
714
797
|
[currentYear, ctx, onSelect]
|
|
715
798
|
);
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
799
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
800
|
+
initialIndex: currentMonth,
|
|
801
|
+
onSelect: handleMonthSelect,
|
|
802
|
+
onPageUp: () => navigateYear(-1),
|
|
803
|
+
onPageDown: () => navigateYear(1),
|
|
804
|
+
onEscape: ctx.close
|
|
805
|
+
});
|
|
722
806
|
return /* @__PURE__ */ jsxs("div", { className: classNames?.root, ...props, children: [
|
|
723
807
|
/* @__PURE__ */ jsxs("div", { className: classNames?.header, children: [
|
|
724
808
|
/* @__PURE__ */ jsx(
|
|
@@ -746,30 +830,37 @@ function DatePickerMonthGrid({
|
|
|
746
830
|
/* @__PURE__ */ jsx(
|
|
747
831
|
"div",
|
|
748
832
|
{
|
|
833
|
+
ref: gridRef,
|
|
749
834
|
role: "grid",
|
|
750
835
|
"aria-label": `${currentYear} months`,
|
|
751
836
|
className: classNames?.grid,
|
|
752
837
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
753
|
-
|
|
754
|
-
|
|
838
|
+
onKeyDown: handleKeyDown,
|
|
839
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
840
|
+
const isSelected = i === currentMonth;
|
|
841
|
+
const isCurrent = i === todayMonth && currentYear === todayYear;
|
|
842
|
+
const isFocused = i === focusedIndex;
|
|
843
|
+
const cls = [
|
|
755
844
|
classNames?.month,
|
|
756
|
-
|
|
757
|
-
|
|
845
|
+
isSelected && classNames?.monthSelected,
|
|
846
|
+
isCurrent && classNames?.monthCurrent
|
|
758
847
|
].filter(Boolean).join(" ") || void 0;
|
|
759
848
|
return /* @__PURE__ */ jsx(
|
|
760
849
|
"button",
|
|
761
850
|
{
|
|
762
851
|
type: "button",
|
|
763
852
|
role: "gridcell",
|
|
764
|
-
|
|
765
|
-
"aria-
|
|
766
|
-
"
|
|
767
|
-
"data-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
853
|
+
tabIndex: isFocused ? 0 : -1,
|
|
854
|
+
"aria-selected": isSelected || void 0,
|
|
855
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
856
|
+
"data-selected": isSelected || void 0,
|
|
857
|
+
"data-current": isCurrent || void 0,
|
|
858
|
+
"data-focused": isFocused || void 0,
|
|
859
|
+
className: cls,
|
|
860
|
+
onClick: () => handleMonthSelect(i),
|
|
861
|
+
children: getMonthName(i, locale)
|
|
771
862
|
},
|
|
772
|
-
|
|
863
|
+
i
|
|
773
864
|
);
|
|
774
865
|
})
|
|
775
866
|
}
|
|
@@ -778,38 +869,38 @@ function DatePickerMonthGrid({
|
|
|
778
869
|
}
|
|
779
870
|
function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
780
871
|
const ctx = useDatePickerContext("DatePicker.YearGrid");
|
|
781
|
-
const { adapter, viewMonth } = ctx;
|
|
872
|
+
const { adapter, viewMonth, displayTimezone } = ctx;
|
|
782
873
|
const currentYear = adapter.getYear(viewMonth);
|
|
783
|
-
const
|
|
874
|
+
const [today, setToday] = useState(null);
|
|
875
|
+
useEffect(() => {
|
|
876
|
+
setToday(adapter.today(displayTimezone));
|
|
877
|
+
}, [adapter, displayTimezone]);
|
|
878
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
784
879
|
const decadeStart = currentYear - currentYear % 12;
|
|
785
880
|
const navigateDecade = useCallback(
|
|
786
881
|
(direction) => {
|
|
787
|
-
|
|
788
|
-
ctx.setViewMonth(newDate);
|
|
882
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
789
883
|
},
|
|
790
884
|
[adapter, viewMonth, ctx]
|
|
791
885
|
);
|
|
792
886
|
const handleYearSelect = useCallback(
|
|
793
|
-
(
|
|
887
|
+
(indexInDecade) => {
|
|
888
|
+
const year = decadeStart + indexInDecade;
|
|
794
889
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
795
890
|
const target = new Date(Date.UTC(year, currentMonth, 1)).toISOString();
|
|
796
891
|
ctx.setViewMonth(target);
|
|
797
892
|
ctx.setFocusedDate(target);
|
|
798
893
|
onSelect?.();
|
|
799
894
|
},
|
|
800
|
-
[adapter, viewMonth, ctx, onSelect]
|
|
801
|
-
);
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
};
|
|
810
|
-
}),
|
|
811
|
-
[decadeStart, currentYear, todayYear]
|
|
812
|
-
);
|
|
895
|
+
[adapter, viewMonth, ctx, onSelect, decadeStart]
|
|
896
|
+
);
|
|
897
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
898
|
+
initialIndex: currentYear - decadeStart,
|
|
899
|
+
onSelect: handleYearSelect,
|
|
900
|
+
onPageUp: () => navigateDecade(-1),
|
|
901
|
+
onPageDown: () => navigateDecade(1),
|
|
902
|
+
onEscape: ctx.close
|
|
903
|
+
});
|
|
813
904
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
814
905
|
return /* @__PURE__ */ jsxs("div", { className: classNames?.root, ...props, children: [
|
|
815
906
|
/* @__PURE__ */ jsxs("div", { className: classNames?.header, children: [
|
|
@@ -838,30 +929,38 @@ function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
|
838
929
|
/* @__PURE__ */ jsx(
|
|
839
930
|
"div",
|
|
840
931
|
{
|
|
932
|
+
ref: gridRef,
|
|
841
933
|
role: "grid",
|
|
842
934
|
"aria-label": rangeLabel,
|
|
843
935
|
className: classNames?.grid,
|
|
844
936
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
845
|
-
|
|
846
|
-
|
|
937
|
+
onKeyDown: handleKeyDown,
|
|
938
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
939
|
+
const year = decadeStart + i;
|
|
940
|
+
const isSelected = year === currentYear;
|
|
941
|
+
const isCurrent = year === todayYear;
|
|
942
|
+
const isFocused = i === focusedIndex;
|
|
943
|
+
const cls = [
|
|
847
944
|
classNames?.year,
|
|
848
|
-
|
|
849
|
-
|
|
945
|
+
isSelected && classNames?.yearSelected,
|
|
946
|
+
isCurrent && classNames?.yearCurrent
|
|
850
947
|
].filter(Boolean).join(" ") || void 0;
|
|
851
948
|
return /* @__PURE__ */ jsx(
|
|
852
949
|
"button",
|
|
853
950
|
{
|
|
854
951
|
type: "button",
|
|
855
952
|
role: "gridcell",
|
|
856
|
-
|
|
857
|
-
"aria-
|
|
858
|
-
"
|
|
859
|
-
"data-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
953
|
+
tabIndex: isFocused ? 0 : -1,
|
|
954
|
+
"aria-selected": isSelected || void 0,
|
|
955
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
956
|
+
"data-selected": isSelected || void 0,
|
|
957
|
+
"data-current": isCurrent || void 0,
|
|
958
|
+
"data-focused": isFocused || void 0,
|
|
959
|
+
className: cls,
|
|
960
|
+
onClick: () => handleYearSelect(i),
|
|
961
|
+
children: year
|
|
863
962
|
},
|
|
864
|
-
|
|
963
|
+
i
|
|
865
964
|
);
|
|
866
965
|
})
|
|
867
966
|
}
|
|
@@ -934,8 +1033,7 @@ function DatePickerPreset({
|
|
|
934
1033
|
"button",
|
|
935
1034
|
{
|
|
936
1035
|
type: "button",
|
|
937
|
-
|
|
938
|
-
"aria-selected": isActive,
|
|
1036
|
+
"aria-pressed": isActive,
|
|
939
1037
|
"data-active": isActive || void 0,
|
|
940
1038
|
disabled: ctx.isDisabled,
|
|
941
1039
|
onClick: handleClick,
|
|
@@ -1427,7 +1525,6 @@ function RangePickerCalendar({
|
|
|
1427
1525
|
ref: gridRef,
|
|
1428
1526
|
role: "grid",
|
|
1429
1527
|
"aria-label": title,
|
|
1430
|
-
"aria-multiselectable": "true",
|
|
1431
1528
|
"aria-rowcount": weeks.length + 1,
|
|
1432
1529
|
"aria-colcount": 7,
|
|
1433
1530
|
className: classNames?.grid,
|
|
@@ -1591,8 +1688,7 @@ function RangePickerPreset({
|
|
|
1591
1688
|
"button",
|
|
1592
1689
|
{
|
|
1593
1690
|
type: "button",
|
|
1594
|
-
|
|
1595
|
-
"aria-selected": isActive,
|
|
1691
|
+
"aria-pressed": isActive,
|
|
1596
1692
|
"data-active": isActive || void 0,
|
|
1597
1693
|
disabled: ctx.isDisabled,
|
|
1598
1694
|
onClick: handleClick,
|
|
@@ -1896,29 +1992,70 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1896
1992
|
}
|
|
1897
1993
|
function TimePickerAmPmToggle({ classNames, ...props }) {
|
|
1898
1994
|
const ctx = useTimePickerContext("TimePicker.AmPmToggle");
|
|
1899
|
-
|
|
1900
|
-
const
|
|
1995
|
+
const amRef = useRef(null);
|
|
1996
|
+
const pmRef = useRef(null);
|
|
1901
1997
|
const setPeriod = useCallback(
|
|
1902
1998
|
(newPeriod) => {
|
|
1903
1999
|
if (ctx.isDisabled || ctx.isReadOnly) return;
|
|
2000
|
+
const { hours12 } = to12Hour(ctx.currentTime.hours);
|
|
1904
2001
|
const newHours24 = to24Hour(hours12, newPeriod);
|
|
1905
2002
|
ctx.setTime({ hours: newHours24 });
|
|
1906
2003
|
},
|
|
1907
|
-
[
|
|
2004
|
+
[ctx]
|
|
1908
2005
|
);
|
|
2006
|
+
if (ctx.format !== "12h") return null;
|
|
2007
|
+
const { period } = to12Hour(ctx.currentTime.hours);
|
|
2008
|
+
const focusOther = (target) => {
|
|
2009
|
+
(target === "AM" ? amRef : pmRef).current?.focus();
|
|
2010
|
+
};
|
|
2011
|
+
const handleKeyDown = (e, target) => {
|
|
2012
|
+
switch (e.key) {
|
|
2013
|
+
case "ArrowRight":
|
|
2014
|
+
case "ArrowDown":
|
|
2015
|
+
case "ArrowLeft":
|
|
2016
|
+
case "ArrowUp": {
|
|
2017
|
+
e.preventDefault();
|
|
2018
|
+
const next = target === "AM" ? "PM" : "AM";
|
|
2019
|
+
setPeriod(next);
|
|
2020
|
+
focusOther(next);
|
|
2021
|
+
break;
|
|
2022
|
+
}
|
|
2023
|
+
case "Home": {
|
|
2024
|
+
e.preventDefault();
|
|
2025
|
+
setPeriod("AM");
|
|
2026
|
+
focusOther("AM");
|
|
2027
|
+
break;
|
|
2028
|
+
}
|
|
2029
|
+
case "End": {
|
|
2030
|
+
e.preventDefault();
|
|
2031
|
+
setPeriod("PM");
|
|
2032
|
+
focusOther("PM");
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
case " ":
|
|
2036
|
+
case "Enter": {
|
|
2037
|
+
e.preventDefault();
|
|
2038
|
+
setPeriod(target);
|
|
2039
|
+
break;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
1909
2043
|
const renderButton = (target) => {
|
|
1910
2044
|
const isSelected = period === target;
|
|
1911
2045
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1912
2046
|
return /* @__PURE__ */ jsx(
|
|
1913
2047
|
"button",
|
|
1914
2048
|
{
|
|
2049
|
+
ref: target === "AM" ? amRef : pmRef,
|
|
1915
2050
|
type: "button",
|
|
1916
2051
|
role: "radio",
|
|
1917
2052
|
"aria-checked": isSelected,
|
|
2053
|
+
tabIndex: isSelected ? 0 : -1,
|
|
1918
2054
|
"data-selected": isSelected || void 0,
|
|
1919
2055
|
disabled: ctx.isDisabled,
|
|
1920
2056
|
className: optionClass,
|
|
1921
2057
|
onClick: () => setPeriod(target),
|
|
2058
|
+
onKeyDown: (e) => handleKeyDown(e, target),
|
|
1922
2059
|
children: target
|
|
1923
2060
|
}
|
|
1924
2061
|
);
|
|
@@ -2200,7 +2337,7 @@ function MonthPickerRoot(props) {
|
|
|
2200
2337
|
}
|
|
2201
2338
|
function MonthPickerGrid({ classNames, ...props }) {
|
|
2202
2339
|
const ctx = useDatePickerContext("MonthPicker.Grid");
|
|
2203
|
-
const { adapter, viewMonth, locale, value, displayTimezone, labels } = ctx;
|
|
2340
|
+
const { adapter, viewMonth, locale, value, displayTimezone, labels, disabled } = ctx;
|
|
2204
2341
|
const currentYear = adapter.getYear(viewMonth);
|
|
2205
2342
|
const [valueYear, valueMonthZeroBased] = useMemo(() => {
|
|
2206
2343
|
if (!value) return [null, null];
|
|
@@ -2211,9 +2348,19 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2211
2348
|
return [null, null];
|
|
2212
2349
|
}
|
|
2213
2350
|
}, [value, adapter, displayTimezone]);
|
|
2214
|
-
const today =
|
|
2215
|
-
|
|
2216
|
-
|
|
2351
|
+
const [today, setToday] = useState(null);
|
|
2352
|
+
useEffect(() => {
|
|
2353
|
+
setToday(adapter.today(displayTimezone));
|
|
2354
|
+
}, [adapter, displayTimezone]);
|
|
2355
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2356
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
2357
|
+
const monthDisabledFlags = useMemo(
|
|
2358
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2359
|
+
const monthStart = new Date(Date.UTC(currentYear, i, 1)).toISOString();
|
|
2360
|
+
return isRangeFullyDisabled(monthStart, adapter.endOfMonth(monthStart), disabled, adapter);
|
|
2361
|
+
}),
|
|
2362
|
+
[currentYear, disabled, adapter]
|
|
2363
|
+
);
|
|
2217
2364
|
const navigateYear = useCallback(
|
|
2218
2365
|
(direction) => {
|
|
2219
2366
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
@@ -2222,17 +2369,23 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2222
2369
|
);
|
|
2223
2370
|
const handleMonthSelect = useCallback(
|
|
2224
2371
|
(monthIndex) => {
|
|
2372
|
+
if (monthDisabledFlags[monthIndex]) return;
|
|
2225
2373
|
const target = new Date(Date.UTC(currentYear, monthIndex, 1)).toISOString();
|
|
2226
2374
|
ctx.selectDate(target);
|
|
2227
2375
|
},
|
|
2228
|
-
[currentYear, ctx]
|
|
2229
|
-
);
|
|
2230
|
-
const
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2376
|
+
[currentYear, ctx, monthDisabledFlags]
|
|
2377
|
+
);
|
|
2378
|
+
const naturalIndex = valueYear === currentYear && valueMonthZeroBased !== null ? valueMonthZeroBased : adapter.getMonth(viewMonth);
|
|
2379
|
+
const firstEnabled = monthDisabledFlags.findIndex((d) => !d);
|
|
2380
|
+
const initialIndex = monthDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2381
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2382
|
+
initialIndex,
|
|
2383
|
+
disabledFlags: monthDisabledFlags,
|
|
2384
|
+
onSelect: handleMonthSelect,
|
|
2385
|
+
onPageUp: () => navigateYear(-1),
|
|
2386
|
+
onPageDown: () => navigateYear(1),
|
|
2387
|
+
onEscape: ctx.close
|
|
2388
|
+
});
|
|
2236
2389
|
return /* @__PURE__ */ jsxs("div", { className: classNames?.root, ...props, children: [
|
|
2237
2390
|
/* @__PURE__ */ jsxs("div", { className: classNames?.header, children: [
|
|
2238
2391
|
/* @__PURE__ */ jsx(
|
|
@@ -2257,37 +2410,57 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2257
2410
|
}
|
|
2258
2411
|
)
|
|
2259
2412
|
] }),
|
|
2260
|
-
/* @__PURE__ */ jsx(
|
|
2413
|
+
/* @__PURE__ */ jsx(
|
|
2261
2414
|
"div",
|
|
2262
2415
|
{
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
"
|
|
2274
|
-
{
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2416
|
+
ref: gridRef,
|
|
2417
|
+
role: "grid",
|
|
2418
|
+
"aria-label": `${currentYear} months`,
|
|
2419
|
+
className: classNames?.grid,
|
|
2420
|
+
onKeyDown: handleKeyDown,
|
|
2421
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsx(
|
|
2422
|
+
"div",
|
|
2423
|
+
{
|
|
2424
|
+
role: "row",
|
|
2425
|
+
className: classNames?.gridRow,
|
|
2426
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2427
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2428
|
+
const i = rowIndex * 3 + col;
|
|
2429
|
+
const isSelected = valueYear === currentYear && valueMonthZeroBased === i;
|
|
2430
|
+
const isCurrent = todayYear === currentYear && todayMonth === i;
|
|
2431
|
+
const isFocused = i === focusedIndex;
|
|
2432
|
+
const isDisabled = monthDisabledFlags[i] ?? false;
|
|
2433
|
+
const cls = [
|
|
2434
|
+
classNames?.month,
|
|
2435
|
+
isSelected && classNames?.monthSelected,
|
|
2436
|
+
isCurrent && classNames?.monthCurrent,
|
|
2437
|
+
isDisabled && classNames?.monthDisabled
|
|
2438
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2439
|
+
return /* @__PURE__ */ jsx(
|
|
2440
|
+
"button",
|
|
2441
|
+
{
|
|
2442
|
+
type: "button",
|
|
2443
|
+
role: "gridcell",
|
|
2444
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2445
|
+
disabled: isDisabled,
|
|
2446
|
+
"aria-selected": isSelected || void 0,
|
|
2447
|
+
"aria-disabled": isDisabled || void 0,
|
|
2448
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2449
|
+
"data-selected": isSelected || void 0,
|
|
2450
|
+
"data-current": isCurrent || void 0,
|
|
2451
|
+
"data-focused": isFocused || void 0,
|
|
2452
|
+
className: cls,
|
|
2453
|
+
onClick: () => handleMonthSelect(i),
|
|
2454
|
+
children: getMonthName(i, locale)
|
|
2455
|
+
},
|
|
2456
|
+
i
|
|
2457
|
+
);
|
|
2458
|
+
})
|
|
2459
|
+
},
|
|
2460
|
+
rowIndex
|
|
2461
|
+
))
|
|
2462
|
+
}
|
|
2463
|
+
)
|
|
2291
2464
|
] });
|
|
2292
2465
|
}
|
|
2293
2466
|
|
|
@@ -2304,7 +2477,7 @@ function YearPickerRoot(props) {
|
|
|
2304
2477
|
}
|
|
2305
2478
|
function YearPickerGrid({ classNames, ...props }) {
|
|
2306
2479
|
const ctx = useDatePickerContext("YearPicker.Grid");
|
|
2307
|
-
const { adapter, viewMonth, value, displayTimezone, labels } = ctx;
|
|
2480
|
+
const { adapter, viewMonth, value, displayTimezone, labels, disabled } = ctx;
|
|
2308
2481
|
const currentYear = adapter.getYear(viewMonth);
|
|
2309
2482
|
const decadeStart = currentYear - currentYear % 12;
|
|
2310
2483
|
const valueYear = useMemo(() => {
|
|
@@ -2315,7 +2488,20 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2315
2488
|
return null;
|
|
2316
2489
|
}
|
|
2317
2490
|
}, [value, adapter, displayTimezone]);
|
|
2318
|
-
const
|
|
2491
|
+
const [today, setToday] = useState(null);
|
|
2492
|
+
useEffect(() => {
|
|
2493
|
+
setToday(adapter.today(displayTimezone));
|
|
2494
|
+
}, [adapter, displayTimezone]);
|
|
2495
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2496
|
+
const yearDisabledFlags = useMemo(
|
|
2497
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2498
|
+
const year = decadeStart + i;
|
|
2499
|
+
const yearStart = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2500
|
+
const yearEnd = new Date(Date.UTC(year, 11, 31, 23, 59, 59, 999)).toISOString();
|
|
2501
|
+
return isRangeFullyDisabled(yearStart, yearEnd, disabled, adapter);
|
|
2502
|
+
}),
|
|
2503
|
+
[decadeStart, disabled, adapter]
|
|
2504
|
+
);
|
|
2319
2505
|
const navigateDecade = useCallback(
|
|
2320
2506
|
(direction) => {
|
|
2321
2507
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
@@ -2323,19 +2509,24 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2323
2509
|
[adapter, viewMonth, ctx]
|
|
2324
2510
|
);
|
|
2325
2511
|
const handleYearSelect = useCallback(
|
|
2326
|
-
(
|
|
2512
|
+
(indexInDecade) => {
|
|
2513
|
+
if (yearDisabledFlags[indexInDecade]) return;
|
|
2514
|
+
const year = decadeStart + indexInDecade;
|
|
2327
2515
|
const target = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2328
2516
|
ctx.selectDate(target);
|
|
2329
2517
|
},
|
|
2330
|
-
[ctx]
|
|
2331
|
-
);
|
|
2332
|
-
const
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2518
|
+
[ctx, decadeStart, yearDisabledFlags]
|
|
2519
|
+
);
|
|
2520
|
+
const naturalIndex = valueYear !== null && valueYear >= decadeStart && valueYear <= decadeStart + 11 ? valueYear - decadeStart : currentYear - decadeStart;
|
|
2521
|
+
const firstEnabled = yearDisabledFlags.findIndex((d) => !d);
|
|
2522
|
+
const initialIndex = yearDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2523
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2524
|
+
initialIndex,
|
|
2525
|
+
disabledFlags: yearDisabledFlags,
|
|
2526
|
+
onSelect: handleYearSelect,
|
|
2527
|
+
onPageUp: () => navigateDecade(-1),
|
|
2528
|
+
onPageDown: () => navigateDecade(1),
|
|
2529
|
+
onEscape: ctx.close
|
|
2339
2530
|
});
|
|
2340
2531
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
2341
2532
|
return /* @__PURE__ */ jsxs("div", { className: classNames?.root, ...props, children: [
|
|
@@ -2362,37 +2553,58 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2362
2553
|
}
|
|
2363
2554
|
)
|
|
2364
2555
|
] }),
|
|
2365
|
-
/* @__PURE__ */ jsx(
|
|
2556
|
+
/* @__PURE__ */ jsx(
|
|
2366
2557
|
"div",
|
|
2367
2558
|
{
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
"
|
|
2379
|
-
{
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2559
|
+
ref: gridRef,
|
|
2560
|
+
role: "grid",
|
|
2561
|
+
"aria-label": rangeLabel,
|
|
2562
|
+
className: classNames?.grid,
|
|
2563
|
+
onKeyDown: handleKeyDown,
|
|
2564
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsx(
|
|
2565
|
+
"div",
|
|
2566
|
+
{
|
|
2567
|
+
role: "row",
|
|
2568
|
+
className: classNames?.gridRow,
|
|
2569
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2570
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2571
|
+
const i = rowIndex * 3 + col;
|
|
2572
|
+
const year = decadeStart + i;
|
|
2573
|
+
const isSelected = year === valueYear;
|
|
2574
|
+
const isCurrent = year === todayYear;
|
|
2575
|
+
const isFocused = i === focusedIndex;
|
|
2576
|
+
const isDisabled = yearDisabledFlags[i] ?? false;
|
|
2577
|
+
const cls = [
|
|
2578
|
+
classNames?.year,
|
|
2579
|
+
isSelected && classNames?.yearSelected,
|
|
2580
|
+
isCurrent && classNames?.yearCurrent,
|
|
2581
|
+
isDisabled && classNames?.yearDisabled
|
|
2582
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2583
|
+
return /* @__PURE__ */ jsx(
|
|
2584
|
+
"button",
|
|
2585
|
+
{
|
|
2586
|
+
type: "button",
|
|
2587
|
+
role: "gridcell",
|
|
2588
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2589
|
+
disabled: isDisabled,
|
|
2590
|
+
"aria-selected": isSelected || void 0,
|
|
2591
|
+
"aria-disabled": isDisabled || void 0,
|
|
2592
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2593
|
+
"data-selected": isSelected || void 0,
|
|
2594
|
+
"data-current": isCurrent || void 0,
|
|
2595
|
+
"data-focused": isFocused || void 0,
|
|
2596
|
+
className: cls,
|
|
2597
|
+
onClick: () => handleYearSelect(i),
|
|
2598
|
+
children: year
|
|
2599
|
+
},
|
|
2600
|
+
i
|
|
2601
|
+
);
|
|
2602
|
+
})
|
|
2603
|
+
},
|
|
2604
|
+
rowIndex
|
|
2605
|
+
))
|
|
2606
|
+
}
|
|
2607
|
+
)
|
|
2396
2608
|
] });
|
|
2397
2609
|
}
|
|
2398
2610
|
|