diff --git a/src/month.tsx b/src/month.tsx index c4e3a5a76..41498ea85 100644 --- a/src/month.tsx +++ b/src/month.tsx @@ -843,8 +843,12 @@ export default class Month extends Component { return "-1"; } const preSelectedMonth = getMonth(this.props.preSelection); + const { isDisabled: isPreSelectedMonthDisabled } = + this.isMonthDisabledForLabelDate(preSelectedMonth); + const tabIndex = - !this.props.disabledKeyboardNavigation && m === preSelectedMonth + m === preSelectedMonth && + !(isPreSelectedMonthDisabled || this.props.disabledKeyboardNavigation) ? "0" : "-1"; @@ -856,8 +860,14 @@ export default class Month extends Component { return "-1"; } const preSelectedQuarter = getQuarter(this.props.preSelection); + const isCurrentQuarterDisabled = isQuarterDisabled( + this.props.day, + this.props, + ); + const tabIndex = - !this.props.disabledKeyboardNavigation && q === preSelectedQuarter + q === preSelectedQuarter && + !(isCurrentQuarterDisabled || this.props.disabledKeyboardNavigation) ? "0" : "-1"; diff --git a/src/test/month_test.test.tsx b/src/test/month_test.test.tsx index 7c0d3bd36..22bc184aa 100644 --- a/src/test/month_test.test.tsx +++ b/src/test/month_test.test.tsx @@ -28,7 +28,7 @@ import { import Month from "../month"; import { runAxe } from "./run_axe"; -import { getKey, range } from "./test_utils"; +import { getKey, range, openDateInput, gotoNextView } from "./test_utils"; import type { RenderResult } from "@testing-library/react"; @@ -2525,4 +2525,85 @@ describe("Month", () => { ).toBeNull(); }); }); + + describe("Auto-Focus", () => { + it("should auto-focus on the same selected month when navigating to the next/previous year", () => { + const date = newDate("2024-06-01"); + const selectedMonth = date.getMonth(); + + const { container } = render( + , + ); + + openDateInput(container); + gotoNextView(container); + + const preSelectedDateElement = container.querySelector( + `.react-datepicker__month-text.react-datepicker__month-${selectedMonth}`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0"); + }); + + it("shouldn't auto-focus on the same selected month when navigating to the next/previous year if the corresponding month is disabled", () => { + const date = newDate("2024-06-01"); + const selectedMonth = date.getMonth(); + const excludeDate = newDate(`2025-0${selectedMonth + 1}-01`); + + const { container } = render( + , + ); + + openDateInput(container); + gotoNextView(container); + + const preSelectedDateElement = container.querySelector( + `.react-datepicker__month-text.react-datepicker__month-${selectedMonth}`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1"); + }); + + it("should auto-focus on the same selected quarter when navigating to the next/previous year", () => { + const date = newDate("2024-06-01"); + + const { container } = render( + , + ); + + openDateInput(container); + const selectedQuarterValue = getQuarter(date); + gotoNextView(container); + + const preSelectedDateElement = container.querySelector( + `.react-datepicker__quarter-text.react-datepicker__quarter-${selectedQuarterValue}`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0"); + }); + + it("shouldn't auto-focus on the same selected quarter when navigating to the next/previous year if the corresponding quarter date is disabled", () => { + const date = newDate("2024-06-01"); + const selectedMonth = date.getMonth(); + const excludeDate = newDate(`2025-0${selectedMonth + 1}-01`); + + const { container } = render( + , + ); + + openDateInput(container); + const selectedQuarterValue = getQuarter(date); + gotoNextView(container); + + const preSelectedDateElement = container.querySelector( + `.react-datepicker__quarter-text.react-datepicker__quarter-${selectedQuarterValue}`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1"); + }); + }); }); diff --git a/src/test/test_utils.ts b/src/test/test_utils.ts index 2d3662370..72cf1fbb9 100644 --- a/src/test/test_utils.ts +++ b/src/test/test_utils.ts @@ -1,3 +1,5 @@ +import { fireEvent } from "@testing-library/react"; + import { KeyType } from "../date_utils"; interface KeyEvent { @@ -65,3 +67,16 @@ export const range = (from: number, to: number): number[] => { } return list; }; + +export const openDateInput = (container: Element) => { + const dateInput = container.querySelector("input")!; + fireEvent.focus(dateInput); +}; + +export const gotoNextView = (container: Element) => { + const calendar = container.querySelector(".react-datepicker")!; + const nextButton = calendar.querySelector( + ".react-datepicker__navigation--next", + )!; + fireEvent.click(nextButton); +}; diff --git a/src/test/year_picker_test.test.tsx b/src/test/year_picker_test.test.tsx index a1a802646..abfe3e27d 100644 --- a/src/test/year_picker_test.test.tsx +++ b/src/test/year_picker_test.test.tsx @@ -14,7 +14,15 @@ import { import DatePicker from "../index"; import Year from "../year"; -import { getKey } from "./test_utils"; +import { getKey, gotoNextView, openDateInput } from "./test_utils"; + +const getYearOffset = (calendar: Element, date: Date): number => { + const dateNode = calendar.querySelector( + `.react-datepicker__year-text.react-datepicker__year-${date.getFullYear()}`, + )!; + const yearPicker = calendar.querySelector(".react-datepicker__year-wrapper")!; + return Array.from(yearPicker.children).indexOf(dateNode); +}; describe("YearPicker", () => { it("should show year picker component when showYearPicker prop is present", () => { @@ -872,4 +880,41 @@ describe("YearPicker", () => { container.querySelector(`.react-datepicker__year-${date.getFullYear()}`), ).not.toBeNull(); }); + + describe("Auto-Focus", () => { + it("should auto-focus on the same year offset in the next/previous view when navigating", () => { + const date = newDate("2024-06-01"); + const { container } = render( + , + ); + openDateInput(container); + const calendar = container.querySelector(".react-datepicker")!; + const selectedElementOffset = getYearOffset(calendar, date); + gotoNextView(container); + const preSelectedDateElement = container.querySelector( + `.react-datepicker__year-wrapper :nth-child(${selectedElementOffset + 1}).react-datepicker__year-text`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0"); + }); + it("shouldn't auto-focus on the same year offset in the next/previous view when navigating if the year in the corresponding offset is disabled", () => { + const date = newDate("2024-06-01"); + const excludeDate = newDate("2036-05-01"); // 2036 is in the same 8th offset like 2024 + const { container } = render( + , + ); + openDateInput(container); + const calendar = container.querySelector(".react-datepicker")!; + const selectedElementOffset = getYearOffset(calendar, date); + gotoNextView(container); + const preSelectedDateElement = container.querySelector( + `.react-datepicker__year-wrapper :nth-child(${selectedElementOffset + 1}).react-datepicker__year-${excludeDate.getFullYear()}`, + )!; + expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1"); + }); + }); }); diff --git a/src/year.tsx b/src/year.tsx index a382691c2..bb8c36a96 100644 --- a/src/year.tsx +++ b/src/year.tsx @@ -402,8 +402,9 @@ export default class Year extends Component { return "-1"; } const preSelected = getYear(this.props.preSelection); + const isPreSelectedYearDisabled = isYearDisabled(y, this.props); - return y === preSelected ? "0" : "-1"; + return y === preSelected && !isPreSelectedYearDisabled ? "0" : "-1"; }; getYearContainerClassNames = () => {