Skip to content

Commit

Permalink
fix: enable all years available in the year select dropdown (#2614)
Browse files Browse the repository at this point in the history
* update: minor refactor

* docs: update captionLayout docs

* update: DropdownMultipleMonths example

* update: enable all displayed years in yearDropdown

* fix: DropdownMultipleMonths test and example
  • Loading branch information
rodgobbi authored Dec 8, 2024
1 parent 90ed771 commit 203fc22
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 56 deletions.
64 changes: 43 additions & 21 deletions examples/Dropdown.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,65 @@ test("should display the year dropdown", () => {
expect(yearDropdown()).toBeInTheDocument();
});

test("should disable the months out of range", () => {
expect(
within(monthDropdown()).getByRole("option", { name: "January" })
).toBeDisabled();
test("should disable the months before startMonth", () => {
const disablesMonth = [
"January",
"February",
"March",
"April",
"May",
"June"
];
for (const month of disablesMonth) {
expect(
within(monthDropdown()).getByRole("option", { name: month })
).toBeDisabled();
}
});

test("should disable the months after endMonth", async () => {
await user.selectOptions(yearDropdown(), "2025");
const disablesMonth = ["November", "December"];
for (const month of disablesMonth) {
expect(
within(monthDropdown()).getByRole("option", { name: month })
).toBeDisabled();
}
});

describe("when choosing a month", () => {
const monthName = "December";
beforeEach(async () => {
test("should display the month", async () => {
const monthName = "December";
await user.selectOptions(monthDropdown(), monthName);
});
test("should display the month", () => {
expect(grid()).toHaveAccessibleName(`${monthName} 2024`);
});
test("should disable the years out of range", () => {
expect(
within(yearDropdown()).getByRole("option", { name: "2025" })
).toBeDisabled();
});
});

describe("when choosing a year", () => {
const year = "2025";
beforeEach(async () => {
test("should display the year", async () => {
const year = "2025";
await user.selectOptions(yearDropdown(), year);
});
test("should display the year", () => {
expect(grid()).toHaveAccessibleName(`July ${year}`);
});

test("should display the first available month when selecting a month before startMonth", async () => {
await user.selectOptions(yearDropdown(), "2025");
await user.selectOptions(monthDropdown(), "January");
await user.selectOptions(yearDropdown(), "2024");
expect(grid()).toHaveAccessibleName(`July 2024`);
});

test("should display the last available month when selecting a month after endMonth", async () => {
await user.selectOptions(monthDropdown(), "December");
await user.selectOptions(yearDropdown(), "2025");
expect(grid()).toHaveAccessibleName(`October 2025`);
});
});

describe("when choosing a disabled month", () => {
const monthName = "February";
beforeEach(async () => {
test("should display the first available month", async () => {
const monthName = "February";
await user.selectOptions(monthDropdown(), monthName);
});
test("should display the first available month", () => {
expect(grid()).toHaveAccessibleName(`July 2024`);
});
});
4 changes: 2 additions & 2 deletions examples/DropdownMultipleMonths.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe("when choosing a month from the first dropdown", () => {
await user.selectOptions(firstDropDown, monthName);
});
test("should display the month in the first dropdown", () => {
expect(grid(`${monthName} 2023`)).toBeInTheDocument();
expect(grid(`${monthName} 2024`)).toBeInTheDocument();
});
});

Expand All @@ -39,6 +39,6 @@ describe("when choosing a month from the third dropdown", () => {
await user.selectOptions(thirdDropDown, newMonthName);
});
test("should display the month selected the third dropdown", () => {
expect(grid(`${newMonthName} 2023`)).toBeInTheDocument();
expect(grid(`${newMonthName} 2024`)).toBeInTheDocument();
});
});
5 changes: 3 additions & 2 deletions examples/DropdownMultipleMonths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ export function DropdownMultipleMonths() {
return (
<DayPicker
numberOfMonths={5}
defaultMonth={new Date(2024, 6)}
captionLayout="dropdown"
fromYear={2015}
toYear={2025}
startMonth={new Date(2023, 6)}
endMonth={new Date(2025, 9)}
/>
);
}
1 change: 0 additions & 1 deletion src/DayPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ export function DayPicker(props: DayPickerProps) {
);

const dropdownYears = getYearOptions(
months[0].date,
navStart,
navEnd,
formatters,
Expand Down
5 changes: 0 additions & 5 deletions src/helpers/getYearOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@ import { getFormatters } from "./getFormatters";
import { getYearOptions } from "./getYearOptions";

test("return undefined if startMonth or endMonth is not provided", () => {
const displayMonth = new Date(2022, 0, 1); // January 2022
const formatters = getFormatters({
formatYearDropdown: (year: number) => `${year}`
});
const result1 = getYearOptions(
displayMonth,
undefined,
new Date(2022, 11, 31),
formatters,
defaultDateLib
);
const result2 = getYearOptions(
displayMonth,
new Date(2022, 0, 1),
undefined,
formatters,
Expand All @@ -28,15 +25,13 @@ test("return undefined if startMonth or endMonth is not provided", () => {
});

test("return correct dropdown options", () => {
const displayMonth = new Date(2022, 0, 1); // January 2022
const startMonth = new Date(2022, 0, 1); // January 2022
const endMonth = new Date(2024, 11, 31); // December 2024
const formatters = getFormatters({
formatYearDropdown: (year: number) => `${year}`
});

const result = getYearOptions(
displayMonth,
startMonth,
endMonth,
formatters,
Expand Down
32 changes: 8 additions & 24 deletions src/helpers/getYearOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,16 @@ import type { Formatters } from "../types/index.js";

/** Return the years to show in the dropdown. */
export function getYearOptions(
displayMonth: Date,
calendarStart: Date | undefined,
calendarEnd: Date | undefined,
navStart: Date | undefined,
navEnd: Date | undefined,
formatters: Pick<Formatters, "formatYearDropdown">,
dateLib: DateLib
): DropdownOption[] | undefined {
if (!calendarStart) return undefined;
if (!calendarEnd) return undefined;
const {
startOfMonth,
startOfYear,
endOfYear,
addYears,
isBefore,
isSameYear
} = dateLib;
const month = displayMonth.getMonth();
const firstNavYear = startOfYear(calendarStart);
const lastNavYear = endOfYear(calendarEnd);
if (!navStart) return undefined;
if (!navEnd) return undefined;
const { startOfYear, endOfYear, addYears, isBefore, isSameYear } = dateLib;
const firstNavYear = startOfYear(navStart);
const lastNavYear = endOfYear(navEnd);
const years: number[] = [];

let year = firstNavYear;
Expand All @@ -32,18 +23,11 @@ export function getYearOptions(
}

return years.map((value) => {
const year = dateLib.Date
? new dateLib.Date(value, month)
: new Date(value, month);
const disabled =
(calendarStart && year < startOfMonth(calendarStart)) ||
(month && calendarEnd && year > startOfMonth(calendarEnd)) ||
false;
const label = formatters.formatYearDropdown(value);
return {
value,
label,
disabled
disabled: false
};
});
}
3 changes: 2 additions & 1 deletion src/types/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ export interface PropsBase {
* - `year`: display only the dropdown for the years
*
* **Note:** showing the dropdown will set the start/end months
* {@link fromYear} to 100 years ago, and {@link toYear} to the current year.
* {@link startMonth} to 100 years ago, and {@link endMonth} to the end of the
* current year.
*
* @see https://daypicker.dev/docs/customization#caption-layouts
*/
Expand Down

0 comments on commit 203fc22

Please sign in to comment.