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