diff --git a/src/DayPicker.tsx b/src/DayPicker.tsx index 6d8cdde7a..aaface07e 100644 --- a/src/DayPicker.tsx +++ b/src/DayPicker.tsx @@ -350,10 +350,7 @@ export function DayPicker(props: DayPickerProps) { /> ) : ( - {formatMonthDropdown( - calendarMonth.date.getMonth(), - locale - )} + {formatMonthDropdown(calendarMonth.date, dateLib)} )} {captionLayout === "dropdown" || @@ -371,7 +368,7 @@ export function DayPicker(props: DayPickerProps) { /> ) : ( - {formatYearDropdown(calendarMonth.date.getFullYear())} + {formatYearDropdown(calendarMonth.date, dateLib)} )} diff --git a/src/formatters/formatMonthDropdown.test.ts b/src/formatters/formatMonthDropdown.test.ts index b2613cde7..2c79e19e1 100644 --- a/src/formatters/formatMonthDropdown.test.ts +++ b/src/formatters/formatMonthDropdown.test.ts @@ -1,19 +1,19 @@ import { es } from "date-fns/locale/es"; -import { defaultLocale } from "../classes/DateLib"; +import { DateLib } from "../classes/DateLib"; import { formatMonthDropdown } from "./formatMonthDropdown"; const date = new Date(2022, 10, 21); test("should return the formatted month dropdown label", () => { - expect(formatMonthDropdown(date.getMonth(), defaultLocale)).toEqual( - "November" - ); + expect(formatMonthDropdown(date)).toEqual("November"); }); describe("when a locale is passed in", () => { test("should format using the locale", () => { - expect(formatMonthDropdown(date.getMonth(), es)).toEqual("noviembre"); + expect(formatMonthDropdown(date, new DateLib({ locale: es }))).toEqual( + "noviembre" + ); }); }); diff --git a/src/formatters/formatMonthDropdown.ts b/src/formatters/formatMonthDropdown.ts index 05f72add6..cb3b2df40 100644 --- a/src/formatters/formatMonthDropdown.ts +++ b/src/formatters/formatMonthDropdown.ts @@ -1,4 +1,4 @@ -import type { DateFnsMonth, Locale } from "../classes/DateLib.js"; +import { defaultDateLib, type DateLib } from "../classes/DateLib.js"; /** * Format the month number for the dropdown option label. @@ -8,10 +8,8 @@ import type { DateFnsMonth, Locale } from "../classes/DateLib.js"; * @see https://daypicker.dev/docs/translation#custom-formatters */ export function formatMonthDropdown( - /** The month number to format. */ - monthNumber: number, - /** The locale to use for formatting. */ - locale: Locale + month: Date, + dateLib: DateLib = defaultDateLib ): string { - return locale.localize?.month(monthNumber as DateFnsMonth); + return dateLib.format(month, "LLLL"); } diff --git a/src/formatters/formatYearDropdown.test.ts b/src/formatters/formatYearDropdown.test.ts index a4cb1765a..8b47fabe2 100644 --- a/src/formatters/formatYearDropdown.test.ts +++ b/src/formatters/formatYearDropdown.test.ts @@ -1,5 +1,7 @@ +import { defaultDateLib } from "../classes"; + import { formatYearDropdown } from "./formatYearDropdown"; test("should return the formatted weekday name", () => { - expect(formatYearDropdown(2022)).toEqual("2022"); + expect(formatYearDropdown(new Date(2022, 0), defaultDateLib)).toEqual("2022"); }); diff --git a/src/formatters/formatYearDropdown.ts b/src/formatters/formatYearDropdown.ts index 07020c27e..879497cb3 100644 --- a/src/formatters/formatYearDropdown.ts +++ b/src/formatters/formatYearDropdown.ts @@ -1,12 +1,16 @@ +import { defaultDateLib, type DateLib } from "../classes/DateLib.js"; + /** * Format the years for the dropdown option label. * - * @defaultValue `year.toString()` * @group Formatters * @see https://daypicker.dev/docs/translation#custom-formatters */ -export function formatYearDropdown(year: number): string { - return year.toString(); +export function formatYearDropdown( + year: Date, + dateLib: DateLib = defaultDateLib +): string { + return dateLib.format(year, "yyyy"); } /** diff --git a/src/helpers/getFormatters.test.ts b/src/helpers/getFormatters.test.ts index 373771aff..4672e2ee5 100644 --- a/src/helpers/getFormatters.test.ts +++ b/src/helpers/getFormatters.test.ts @@ -1,4 +1,3 @@ -import { defaultDateLib } from "../classes/DateLib"; import * as defaultFormatters from "../formatters"; import { getFormatters } from "./getFormatters"; @@ -20,12 +19,8 @@ test("merges custom formatters with default formatters", () => { test("assigns `formatMonthCaption` to `formatCaption` if `formatCaption` is not defined", () => { const result = getFormatters({ formatMonthCaption: () => "customMonth" }); - expect(result.formatCaption(new Date(), {}, defaultDateLib)).toBe( - "customMonth" - ); - expect(result.formatMonthCaption(new Date(), {}, defaultDateLib)).toBe( - "customMonth" - ); + expect(result.formatCaption(new Date(), {})).toBe("customMonth"); + expect(result.formatMonthCaption(new Date(), {})).toBe("customMonth"); }); test("does not overwrite `formatCaption` if already defined", () => { @@ -33,22 +28,14 @@ test("does not overwrite `formatCaption` if already defined", () => { formatMonthCaption: () => "customMonth", formatCaption: () => "customCaption" }); - expect(result.formatCaption(new Date(), {}, defaultDateLib)).toBe( - "customCaption" - ); - expect(result.formatMonthCaption(new Date(), {}, defaultDateLib)).toBe( - "customMonth" - ); + expect(result.formatCaption(new Date(), {})).toBe("customCaption"); + expect(result.formatMonthCaption(new Date(), {})).toBe("customMonth"); }); test("assigns `formatYearCaption` to `formatYearDropdown` if `formatYearDropdown` is not defined", () => { const result = getFormatters({ formatYearCaption: () => "customYear" }); - expect(result.formatYearDropdown(new Date(0).getFullYear())).toBe( - "customYear" - ); - expect(result.formatYearCaption(new Date(0).getFullYear())).toBe( - "customYear" - ); + expect(result.formatYearDropdown(new Date(2000, 0))).toBe("customYear"); + expect(result.formatYearCaption(new Date(2000, 0))).toBe("customYear"); }); test("does not overwrite `formatYearDropdown` if already defined", () => { @@ -56,8 +43,6 @@ test("does not overwrite `formatYearDropdown` if already defined", () => { formatYearCaption: () => "customYear", formatYearDropdown: () => "customDropdown" }); - expect(result.formatYearDropdown(new Date().getFullYear())).toBe( - "customDropdown" - ); - expect(result.formatYearCaption(new Date().getFullYear())).toBe("customYear"); + expect(result.formatYearDropdown(new Date())).toBe("customDropdown"); + expect(result.formatYearCaption(new Date())).toBe("customYear"); }); diff --git a/src/helpers/getMonthOptions.ts b/src/helpers/getMonthOptions.ts index 372f151f6..80ee7ba9d 100644 --- a/src/helpers/getMonthOptions.ts +++ b/src/helpers/getMonthOptions.ts @@ -1,4 +1,4 @@ -import { defaultLocale, type DateLib } from "../classes/DateLib.js"; +import { type DateLib } from "../classes/DateLib.js"; import { DropdownOption } from "../components/Dropdown.js"; import type { Formatters } from "../types/index.js"; @@ -12,25 +12,23 @@ export function getMonthOptions( ): DropdownOption[] | undefined { if (!navStart) return undefined; if (!navEnd) return undefined; + // const year = dateLib.getYear(displayMonth); + const { + startOfMonth, + startOfYear, + endOfYear, + eachMonthOfInterval, + getMonth + } = dateLib; - const { addMonths, startOfMonth } = dateLib; - const year = displayMonth.getFullYear(); - - const months: number[] = []; - let month = navStart; - while (months.length < 12) { - months.push(month.getMonth()); - month = addMonths(month, 1); - } - const sortedMonths = months.sort((a, b) => { - return a - b; + const months = eachMonthOfInterval({ + start: startOfYear(displayMonth), + end: endOfYear(displayMonth) }); - const options = sortedMonths.map((value) => { - const label = formatters.formatMonthDropdown( - value, - dateLib.options.locale ?? defaultLocale - ); - const month = new dateLib.Date(year, value); + + const options = months.map((month) => { + const label = formatters.formatMonthDropdown(month, dateLib); + const value = getMonth(month); const disabled = (navStart && month < startOfMonth(navStart)) || (navEnd && month > startOfMonth(navEnd)) || diff --git a/src/helpers/getYearOptions.test.ts b/src/helpers/getYearOptions.test.ts index c5473bea0..b54ff45e8 100644 --- a/src/helpers/getYearOptions.test.ts +++ b/src/helpers/getYearOptions.test.ts @@ -5,7 +5,7 @@ import { getYearOptions } from "./getYearOptions"; test("return undefined if startMonth or endMonth is not provided", () => { const formatters = getFormatters({ - formatYearDropdown: (year: number) => `${year}` + formatYearDropdown: (date: Date) => `${date.getFullYear()}` }); const result1 = getYearOptions( undefined, @@ -28,7 +28,7 @@ test("return correct dropdown options", () => { 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}` + formatYearDropdown: (date: Date) => `${date.getFullYear()}` }); const result = getYearOptions( diff --git a/src/helpers/getYearOptions.ts b/src/helpers/getYearOptions.ts index 4c88f3161..7a0f35f26 100644 --- a/src/helpers/getYearOptions.ts +++ b/src/helpers/getYearOptions.ts @@ -11,21 +11,22 @@ export function getYearOptions( ): DropdownOption[] | undefined { if (!navStart) return undefined; if (!navEnd) return undefined; - const { startOfYear, endOfYear, addYears, isBefore, isSameYear } = dateLib; + const { startOfYear, endOfYear, addYears, getYear, isBefore, isSameYear } = + dateLib; const firstNavYear = startOfYear(navStart); const lastNavYear = endOfYear(navEnd); - const years: number[] = []; + const years: Date[] = []; let year = firstNavYear; while (isBefore(year, lastNavYear) || isSameYear(year, lastNavYear)) { - years.push(year.getFullYear()); + years.push(year); year = addYears(year, 1); } - return years.map((value) => { - const label = formatters.formatYearDropdown(value); + return years.map((year) => { + const label = formatters.formatYearDropdown(year, dateLib); return { - value, + value: getYear(year), label, disabled: false };