Skip to content

Commit

Permalink
fix(breaking): dropdown formatters to use dateLib format (#2644)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpbl authored Dec 25, 2024
1 parent 9d5b06b commit 39b3cb1
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 69 deletions.
7 changes: 2 additions & 5 deletions src/DayPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,7 @@ export function DayPicker(props: DayPickerProps) {
/>
) : (
<span role="status" aria-live="polite">
{formatMonthDropdown(
calendarMonth.date.getMonth(),
locale
)}
{formatMonthDropdown(calendarMonth.date, dateLib)}
</span>
)}
{captionLayout === "dropdown" ||
Expand All @@ -371,7 +368,7 @@ export function DayPicker(props: DayPickerProps) {
/>
) : (
<span role="status" aria-live="polite">
{formatYearDropdown(calendarMonth.date.getFullYear())}
{formatYearDropdown(calendarMonth.date, dateLib)}
</span>
)}
</components.DropdownNav>
Expand Down
10 changes: 5 additions & 5 deletions src/formatters/formatMonthDropdown.test.ts
Original file line number Diff line number Diff line change
@@ -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"
);
});
});
10 changes: 4 additions & 6 deletions src/formatters/formatMonthDropdown.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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");
}
4 changes: 3 additions & 1 deletion src/formatters/formatYearDropdown.test.ts
Original file line number Diff line number Diff line change
@@ -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");
});
10 changes: 7 additions & 3 deletions src/formatters/formatYearDropdown.ts
Original file line number Diff line number Diff line change
@@ -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");
}

/**
Expand Down
31 changes: 8 additions & 23 deletions src/helpers/getFormatters.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { defaultDateLib } from "../classes/DateLib";
import * as defaultFormatters from "../formatters";

import { getFormatters } from "./getFormatters";
Expand All @@ -20,44 +19,30 @@ 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", () => {
const result = getFormatters({
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", () => {
const result = getFormatters({
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");
});
34 changes: 16 additions & 18 deletions src/helpers/getMonthOptions.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -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)) ||
Expand Down
4 changes: 2 additions & 2 deletions src/helpers/getYearOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(
Expand Down
13 changes: 7 additions & 6 deletions src/helpers/getYearOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down

0 comments on commit 39b3cb1

Please sign in to comment.