diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index cbb3c60a62..1e6c1a969a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,8 +7,7 @@ assignees: "gpbl" ## Description Please provide a detailed description of the issue. Include any relevant context or steps to reproduce the problem. - -Fork this CodeSandbox: https://codesandbox.io/p/sandbox/react-day-picker-v8-eg8mw and add to it the code to reproduce the issue. +ssue. ## Expected Behavior @@ -41,3 +40,7 @@ If applicable, add screenshots or GIFs to help explain your problem. - Version [e.g. 22]: - Operating System [e.g. iOS, Windows]: - Other relevant information: + +## Checklist + +- [ ] I included a [CodeSandbox](https://codesandbox.io/p/sandbox/react-day-picker-v8-eg8mw) link that helps maintainer to replicate the bug diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..c04a04909f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,38 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "typescript", + "tsconfig": "tsconfig-esm.json", + "option": "watch", + "problemMatcher": ["$tsc-watch"], + "group": "build", + "label": "tsc: watch - tsconfig-esm.json", + "runOptions": { + "runOn": "folderOpen" + } + }, + { + "type": "typescript", + "tsconfig": "tsconfig-cjs.json", + "option": "watch", + "problemMatcher": ["$tsc-watch"], + "group": "build", + "label": "tsc: watch - tsconfig-cjs.json", + "runOptions": { + "runOn": "folderOpen" + } + }, + { + "type": "npm", + "script": "typecheck-watch", + "group": "build", + "problemMatcher": [], + "label": "npm: typecheck-watch", + "detail": "tsc --project ./tsconfig.json --noEmit --watch", + "runOptions": { + "runOn": "folderOpen" + } + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6f01ea09..158e61b3da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,6 @@ This release includes important updates related to accessibility, styles and per #### At a glance - Enhanced accessibility to better comply with [WCAG21](https://www.w3.org/TR/WCAG21/) recommendations. -- New HTML output using `div` grids instead of tables. - Simplified styles and selectors with new CSS variables. - Added support for UTC dates. - Improved selection logic for range mode. diff --git a/README.md b/README.md index 29867b45c1..20b6f36b1d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ import { DayPicker } from "react-day-picker"; import "react-day-picker/dist/style.css"; function MyDatePicker() { - const [selected, setSelected] = useState(); + const [selected, setSelected] = useState(); return ; } ``` diff --git a/examples/AccessibleDatePicker.tsx b/examples/AccessibleDatePicker.tsx index 1f911972ca..f2c282cd2f 100644 --- a/examples/AccessibleDatePicker.tsx +++ b/examples/AccessibleDatePicker.tsx @@ -6,28 +6,22 @@ import { DayPicker } from "react-day-picker"; export function AccessibleDatePicker() { const [meetingDate, setMeetingDate] = useState(undefined); return ( -
-

Meeting Date

- "Select a date for the meeting", - labelDay: (date, modifiers) => { - return modifiers.selected - ? `Selected Meeting Date: ${format(date, "PPP")}` - : ""; - } - }} - footer={ -

- {meetingDate - ? `Meeting date is set to ${format(meetingDate, "PPPP")}` - : "Please pick a date for the meeting."} -

+ { + return modifiers.selected + ? `Selected Meeting Date: ${format(date, "PPP")}` + : ""; } - /> -
+ }} + footer={ + meetingDate + ? `Meeting date is set to ${format(meetingDate, "PPPP")}` + : "Please pick a date for the meeting." + } + /> ); } diff --git a/examples/AutoFocus.tsx b/examples/AutoFocus.tsx new file mode 100644 index 0000000000..82aad429ea --- /dev/null +++ b/examples/AutoFocus.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +import { DayPicker } from "react-day-picker"; + +/** Test for the next focus day to not cause an infinite recursion. */ +export function AutoFocus() { + return ( +
+ +
+ ); +} diff --git a/examples/ContainerAttributes.tsx b/examples/ContainerAttributes.tsx index 2e844d720b..02f69afa91 100644 --- a/examples/ContainerAttributes.tsx +++ b/examples/ContainerAttributes.tsx @@ -11,7 +11,6 @@ export function ContainerAttributes() { nonce="foo_nonce" title="foo_title" lang="it" - mode="multiple" /> ); } diff --git a/examples/Controlled.tsx b/examples/Controlled.tsx index fb64c63365..b814373024 100644 --- a/examples/Controlled.tsx +++ b/examples/Controlled.tsx @@ -8,9 +8,11 @@ export function Controlled() { const nextMonth = addMonths(new Date(), 1); const [month, setMonth] = React.useState(nextMonth); - const footer = ( + return (
+
); - - return ; } diff --git a/examples/CustomCaption.tsx b/examples/CustomCaption.tsx index 103e872665..c10813a2b2 100644 --- a/examples/CustomCaption.tsx +++ b/examples/CustomCaption.tsx @@ -4,33 +4,38 @@ import { format } from "date-fns"; import { type MonthCaptionProps, DayPicker, - useCalendar + useDayPicker } from "react-day-picker"; function CustomMonthCaption(props: MonthCaptionProps) { - const { goToMonth, nextMonth, previousMonth } = useCalendar(); + const { goToMonth, nextMonth, previousMonth } = useDayPicker(); return ( -

- {format(props.month.date, "MMM yyy")} - - -

+ <> +

{format(props.calendarMonth.date, "MMM yyy")}

+
+ + +
+ ); } export function CustomCaption() { return ( + {props.day.date.getDate() === 19 ? `🎉` : props.children} + + ); +} + +export function CustomDayButton() { + return ; +} diff --git a/examples/CustomDayDate.test.tsx b/examples/CustomDayDate.test.tsx index 39c9b28c5b..a9d0eaca1b 100644 --- a/examples/CustomDayDate.test.tsx +++ b/examples/CustomDayDate.test.tsx @@ -2,13 +2,13 @@ import React from "react"; import { render, screen } from "@/test/render"; -import { CustomDayDate } from "./CustomDayDate"; +import { CustomDayButton } from "./CustomDayButton"; beforeAll(() => jest.setSystemTime(new Date(2021, 10, 25))); afterAll(() => jest.useRealTimers()); beforeEach(() => { - render(); + render(); }); test("should render the emoji", () => { diff --git a/examples/CustomDayDate.tsx b/examples/CustomDayDate.tsx deleted file mode 100644 index 9c0b830c97..0000000000 --- a/examples/CustomDayDate.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; - -import { DayPicker, type DayDateProps } from "react-day-picker"; - -function HighlightDay(props: DayDateProps) { - return ( - - {props.day.date.getDate() === 19 ? `🎉` : props.formattedDate} - - ); -} - -export function CustomDayDate() { - return ; -} diff --git a/examples/CustomMultiple.test.tsx b/examples/CustomMultiple.test.tsx index 368af9bde8..e2be39024d 100644 --- a/examples/CustomMultiple.test.tsx +++ b/examples/CustomMultiple.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render, screen } from "@/test/render"; import { user } from "@/test/user"; @@ -18,10 +18,10 @@ beforeEach(() => { describe("when a day is clicked", () => { const day1 = new Date(2021, 10, 1); beforeEach(async () => { - await user.click(gridcell(day1)); + await user.click(dateButton(day1)); }); test("should appear as selected", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); test("should update the footer", () => { expect(screen.getByText("You selected 1 days.")).toBeInTheDocument(); @@ -29,13 +29,13 @@ describe("when a day is clicked", () => { describe("when a second day is clicked", () => { const day2 = new Date(2021, 10, 2); beforeEach(async () => { - await user.click(gridcell(day2)); + await user.click(dateButton(day2)); }); test("the first day should appear as selected", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); test("the second day should appear as selected", () => { - expect(gridcell(day2)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day2, true)).toHaveAttribute("aria-selected", "true"); }); test("should update the footer", () => { expect(screen.getByText("You selected 2 days.")).toBeInTheDocument(); diff --git a/examples/CustomSingle.test.tsx b/examples/CustomSingle.test.tsx index 07a21d23dd..dda3704ca9 100644 --- a/examples/CustomSingle.test.tsx +++ b/examples/CustomSingle.test.tsx @@ -1,15 +1,12 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render, screen } from "@/test/render"; import { user } from "@/test/user"; import { CustomSingle } from "./CustomSingle"; -const today = new Date(2021, 10, 25); - -beforeAll(() => jest.setSystemTime(today)); -afterAll(() => jest.useRealTimers()); +const today = new Date(); beforeEach(() => { render(); @@ -17,22 +14,25 @@ beforeEach(() => { describe("when a day is clicked", () => { beforeEach(async () => { - await user.click(gridcell(today)); + await user.click(dateButton(today)); }); - test("should appear as selected", () => { - expect(gridcell(today)).toHaveAttribute("aria-selected", "true"); + test("the gridcell should appear as selected", () => { + expect(gridcell(today, true)).toHaveAttribute("aria-selected", "true"); }); test("should update the footer", () => { expect( - screen.getByText("You selected Thu Nov 25 2021") + screen.getByText("You selected " + today.toDateString()) ).toBeInTheDocument(); }); describe("when clicking the day again", () => { beforeEach(async () => { - await user.click(gridcell(today)); + await user.click(dateButton(today)); }); test("should not appear as selected", () => { - expect(gridcell(today)).not.toHaveAttribute("aria-selected", "true"); + expect(gridcell(today, true)).not.toHaveAttribute( + "aria-selected", + "true" + ); }); test("should update the footer", () => { expect( diff --git a/examples/CustomWeek.test.tsx b/examples/CustomWeek.test.tsx index 38b688f07b..2afab45f23 100644 --- a/examples/CustomWeek.test.tsx +++ b/examples/CustomWeek.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -17,17 +17,17 @@ beforeEach(() => { describe("when a day is clicked", () => { beforeEach(async () => { - await user.click(gridcell(today)); + await user.click(dateButton(today)); }); test("the whole week should appear selected", () => { const week = [ - gridcell(new Date(2021, 10, 21)), - gridcell(new Date(2021, 10, 22)), - gridcell(new Date(2021, 10, 23)), - gridcell(new Date(2021, 10, 24)), - gridcell(new Date(2021, 10, 25)), - gridcell(new Date(2021, 10, 26)), - gridcell(new Date(2021, 10, 27)) + gridcell(new Date(2021, 10, 21), true), + gridcell(new Date(2021, 10, 22), true), + gridcell(new Date(2021, 10, 23), true), + gridcell(new Date(2021, 10, 24), true), + gridcell(new Date(2021, 10, 25), true), + gridcell(new Date(2021, 10, 26), true), + gridcell(new Date(2021, 10, 27), true) ]; week.forEach((day) => { expect(day).toHaveAttribute("aria-selected", "true"); @@ -35,17 +35,17 @@ describe("when a day is clicked", () => { }); describe("when clicking the day again", () => { beforeEach(async () => { - await user.click(gridcell(today)); + await user.click(dateButton(today)); }); test("the whole week should not be selected", () => { const week = [ - gridcell(new Date(2021, 10, 21)), - gridcell(new Date(2021, 10, 22)), - gridcell(new Date(2021, 10, 23)), - gridcell(new Date(2021, 10, 24)), - gridcell(new Date(2021, 10, 25)), - gridcell(new Date(2021, 10, 26)), - gridcell(new Date(2021, 10, 27)) + dateButton(new Date(2021, 10, 21)), + dateButton(new Date(2021, 10, 22)), + dateButton(new Date(2021, 10, 23)), + dateButton(new Date(2021, 10, 24)), + dateButton(new Date(2021, 10, 25)), + dateButton(new Date(2021, 10, 26)), + dateButton(new Date(2021, 10, 27)) ]; week.forEach((day) => { expect(day).not.toHaveAttribute("aria-selected", "true"); diff --git a/examples/CustomWeek.tsx b/examples/CustomWeek.tsx index df56e80058..f49cbff2f7 100644 --- a/examples/CustomWeek.tsx +++ b/examples/CustomWeek.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; -import { endOfWeek, isSameWeek, startOfWeek } from "date-fns"; +import { endOfWeek, startOfWeek } from "date-fns"; import { DateRange, DayPicker } from "react-day-picker"; /** Select the whole week when the day is clicked. */ @@ -23,23 +23,10 @@ export function CustomWeek() { to: endOfWeek(day) }); }} - onWeekNumberClick={(weekNumber, dates) => { - if (selectedWeek?.from && isSameWeek(dates[0], selectedWeek.from)) { - setSelectedWeek(undefined); // clear the selection if the week is already selected - return; - } - setSelectedWeek({ - from: startOfWeek(dates[0]), - to: endOfWeek(dates[dates.length - 1]) - }); - }} footer={ - selectedWeek && ( -

- Week from {selectedWeek?.from?.toLocaleDateString()} to - {selectedWeek?.to?.toLocaleDateString()} -

- ) + selectedWeek && + `Week from ${selectedWeek?.from?.toLocaleDateString()} to + {selectedWeek?.to?.toLocaleDateString()}` } /> ); diff --git a/examples/Dialog.tsx b/examples/Dialog.tsx index a535e965ec..ee7213e6c5 100644 --- a/examples/Dialog.tsx +++ b/examples/Dialog.tsx @@ -23,22 +23,16 @@ export function Dialog() { // Function to toggle the dialog visibility const toggleDialog = () => setIsDialogOpen(!isDialogOpen); - // Hook to handle the body scroll behavior and focus trapping. + // Hook to handle the body scroll behavior and focus trapping. You may want to + // use your own trapping library as the body.style overflow will break the + // scroll position. useEffect(() => { - const handleBodyScroll = (isOpen: boolean) => { - document.body.style.overflow = isOpen ? "hidden" : ""; - }; if (!dialogRef.current) return; if (isDialogOpen) { - handleBodyScroll(true); dialogRef.current.showModal(); } else { - handleBodyScroll(false); dialogRef.current.close(); } - return () => { - handleBodyScroll(false); - }; }, [isDialogOpen]); /** @@ -108,20 +102,21 @@ export function Dialog() { aria-labelledby={headerId} onClose={() => setIsDialogOpen(false)} > - - {selectedDate !== undefined && ( + {isDialogOpen && ( + Selected: {selectedDate.toDateString()} - )} -

- } - /> + ) + } + /> + )} ); diff --git a/examples/Disabled.test.tsx b/examples/Disabled.test.tsx index 27bdffb01e..126ce5695b 100644 --- a/examples/Disabled.test.tsx +++ b/examples/Disabled.test.tsx @@ -1,13 +1,12 @@ import React from "react"; -import { app, grid, gridcell } from "@/test/elements"; -import { act, render, screen } from "@/test/render"; +import { app, grid } from "@/test/elements"; +import { render, screen } from "@/test/render"; import { user } from "@/test/user"; import { Disabled } from "./Disabled"; const today = new Date(2022, 5, 10); -const firstOfMonth = new Date(2022, 5, 1); beforeAll(() => jest.setSystemTime(today)); afterAll(() => jest.useRealTimers()); @@ -18,7 +17,7 @@ beforeEach(() => { ); - return act(() => gridcell(firstOfMonth).focus()); + // return act(() => dateButton(firstOfMonth).focus()); }); test("should not display the previous button", () => { diff --git a/examples/FocusRecursive.test.tsx b/examples/FocusRecursive.test.tsx index 5f34413fa0..d1c3dabddb 100644 --- a/examples/FocusRecursive.test.tsx +++ b/examples/FocusRecursive.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { activeElement, gridcell } from "@/test/elements"; +import { activeElement, dateButton } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -20,5 +20,5 @@ test("the first selected day should have focus", async () => { await user.type(activeElement(), "{arrowdown}"); await user.type(activeElement(), "{arrowdown}"); await user.type(activeElement(), "{arrowdown}"); - expect(gridcell(new Date(2022, 5, 22))).toHaveFocus(); + expect(dateButton(new Date(2022, 5, 22))).toHaveFocus(); }); diff --git a/examples/Footer.tsx b/examples/Footer.tsx index ae9270d037..99a45629f7 100644 --- a/examples/Footer.tsx +++ b/examples/Footer.tsx @@ -10,11 +10,9 @@ export function Footer() { selected={selected} onSelect={setSelected} footer={ - selected ? ( -

You picked {selected.toLocaleDateString()}.

- ) : ( -

Please pick a date.

- ) + selected + ? `You picked ${selected.toLocaleDateString()}.` + : "Please pick a date." } /> ); diff --git a/examples/Formatters.tsx b/examples/Formatters.tsx index eb983b56d6..6e82605785 100644 --- a/examples/Formatters.tsx +++ b/examples/Formatters.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { FormatOptions, format } from "date-fns"; -import { DayPicker } from "react-day-picker"; +import { format } from "date-fns"; +import { DayPicker, FormatOptions } from "react-day-picker"; const seasonEmoji: Record = { winter: "⛄️", diff --git a/examples/Input.test.tsx b/examples/Input.test.tsx index a0f638198c..99e40077ce 100644 --- a/examples/Input.test.tsx +++ b/examples/Input.test.tsx @@ -29,7 +29,6 @@ test("updates the calendar when a date is typed in", async () => { render(); const testDate = new Date(2022, 11, 31); // Dec 31, 2022 await user.type(textbox(), format(testDate, "MM/dd/yyyy")); - expect( screen.getByText(`Selected: ${testDate.toDateString()}`) ).toBeInTheDocument(); diff --git a/examples/Input.tsx b/examples/Input.tsx index 76257b954c..cc8b08852e 100644 --- a/examples/Input.tsx +++ b/examples/Input.tsx @@ -68,11 +68,7 @@ export function Input() { mode="single" selected={selectedDate} onSelect={handleDayPickerSelect} - footer={ -

- Selected: {selectedDate?.toDateString()} -

- } + footer={`Selected: ${selectedDate?.toDateString()}`} /> diff --git a/examples/InputRange.tsx b/examples/InputRange.tsx index bbb6542063..a8e7979cb7 100644 --- a/examples/InputRange.tsx +++ b/examples/InputRange.tsx @@ -56,27 +56,27 @@ export function InputRange() { }; return ( - - - {" – "} - - - } - /> +
+ +
+ + {" – "} + +
+
); } diff --git a/examples/InputTime.tsx b/examples/InputTime.tsx index 62eefc40c4..73aabd63d5 100644 --- a/examples/InputTime.tsx +++ b/examples/InputTime.tsx @@ -1,5 +1,6 @@ import React, { ChangeEventHandler, useState } from "react"; +import { setHours, setMinutes } from "date-fns"; import { DayPicker } from "react-day-picker"; export function InputTime() { @@ -13,13 +14,7 @@ export function InputTime() { return; } const [hours, minutes] = time.split(":").map((str) => parseInt(str, 10)); - const newSelectedDate = new Date( - selected.getFullYear(), - selected.getMonth(), - selected.getDate(), - hours, - minutes - ); + const newSelectedDate = setHours(setMinutes(selected, minutes), hours); setSelected(newSelectedDate); setTimeValue(time); }; @@ -43,27 +38,19 @@ export function InputTime() { }; return ( - <> +
+
+ +
-

- Pick a time:{" "} - -

-

- Selected date: {selected ? selected.toLocaleString() : "none"} -

- - } + footer={`Selected date: ${selected ? selected.toLocaleString() : "none"}`} /> - +
); } diff --git a/examples/Keyboard.test.tsx b/examples/Keyboard.test.tsx index 4ef643d0a1..286b98d200 100644 --- a/examples/Keyboard.test.tsx +++ b/examples/Keyboard.test.tsx @@ -14,11 +14,11 @@ import { import { grid, nextButton, - gridcell, + dateButton, activeElement, previousButton } from "@/test/elements"; -import { renderApp } from "@/test/renderApp"; +import { render } from "@/test/render"; import { user } from "@/test/user"; import { Keyboard } from "./Keyboard"; @@ -30,7 +30,7 @@ afterAll(() => jest.useRealTimers()); describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { beforeEach(() => { - renderApp(); + render(); }); describe("when clicking the previous month button", () => { beforeEach(() => user.click(previousButton())); @@ -59,22 +59,22 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { const startOfWeekDay = startOfWeek(day); const endOfWeekDay = endOfWeek(day); - beforeEach(() => act(() => gridcell(day).focus())); + beforeEach(() => act(() => dateButton(day).focus())); test("the day button should be focused", () => { - expect(activeElement()).toBe(gridcell(day)); + expect(activeElement()).toBe(dateButton(day)); }); describe("when the Arrow Left is pressed", () => { beforeEach(() => user.type(activeElement(), "{arrowleft}")); if (dir === "rtl") { test("should focus the next day", () => { - expect(gridcell(nextDay)).toHaveFocus(); + expect(dateButton(nextDay)).toHaveFocus(); }); } else { test("should display the previous month", () => { expect(grid("May 2022")).toBeInTheDocument(); }); test("should focus the previous day", () => { - expect(gridcell(prevDay)).toHaveFocus(); + expect(dateButton(prevDay)).toHaveFocus(); }); } }); @@ -85,11 +85,11 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("May 2022")).toBeInTheDocument(); }); test("should focus the previous day", () => { - expect(gridcell(prevDay)).toHaveFocus(); + expect(dateButton(prevDay)).toHaveFocus(); }); } else { test("should focus the next day", () => { - expect(gridcell(nextDay)).toHaveFocus(); + expect(dateButton(nextDay)).toHaveFocus(); }); } }); @@ -99,7 +99,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("May 2022")).toBeInTheDocument(); }); test("should focus the day in the previous week", () => { - expect(gridcell(prevWeekDay)).toHaveFocus(); + expect(dateButton(prevWeekDay)).toHaveFocus(); }); }); describe("when the Arrow Down is pressed", () => { @@ -108,7 +108,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("June 2022")).toBeInTheDocument(); }); test("should focus the day in the next week", () => { - expect(gridcell(nextWeekDay)).toHaveFocus(); + expect(dateButton(nextWeekDay)).toHaveFocus(); }); }); describe("when Page Up is pressed", () => { @@ -119,7 +119,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("May 2022")).toBeInTheDocument(); }); it("should focus the day in the previous month", () => { - expect(gridcell(prevMonth)).toHaveFocus(); + expect(dateButton(prevMonth)).toHaveFocus(); }); }); describe("when Page Down is pressed", () => { @@ -128,7 +128,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("July 2022")).toBeInTheDocument(); }); it("should focus the day in the next month", () => { - expect(gridcell(nextMonth)).toHaveFocus(); + expect(dateButton(nextMonth)).toHaveFocus(); }); }); describe("when Shift + Page Up is pressed", () => { @@ -137,7 +137,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("June 2021")).toBeInTheDocument(); }); it("should focus the day in the previous year", () => { - expect(gridcell(prevYear)).toHaveFocus(); + expect(dateButton(prevYear)).toHaveFocus(); }); }); describe("when Shift + Page Down is pressed", () => { @@ -148,19 +148,19 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("June 2023")).toBeInTheDocument(); }); it("should focus the day in the next yeaer", () => { - expect(gridcell(nextYear)).toHaveFocus(); + expect(dateButton(nextYear)).toHaveFocus(); }); }); describe("when Home is pressed", () => { beforeEach(() => user.type(activeElement(), "{home}")); it("should focus the start of the week", () => { - expect(gridcell(startOfWeekDay)).toHaveFocus(); + expect(dateButton(startOfWeekDay)).toHaveFocus(); }); }); describe("when End is pressed", () => { beforeEach(() => user.type(activeElement(), "{end}")); it("should focus the end of the week", () => { - expect(gridcell(endOfWeekDay)).toHaveFocus(); + expect(dateButton(endOfWeekDay)).toHaveFocus(); }); }); }); @@ -171,13 +171,13 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { const prevDay = addDays(day, -1); beforeEach(() => { - return act(() => gridcell(day).focus()); + return act(() => dateButton(day).focus()); }); describe("when the Arrow Right is pressed", () => { beforeEach(() => user.type(activeElement(), "{arrowright}")); if (dir === "rtl") { test("should focus the previous day", () => { - expect(gridcell(prevDay)).toHaveFocus(); + expect(dateButton(prevDay)).toHaveFocus(); }); } else { test("should display the next month", () => { @@ -185,7 +185,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { }); test("should focus the next day", () => { const nextDay = addDays(day, 1); - expect(gridcell(nextDay)).toHaveFocus(); + expect(dateButton(nextDay)).toHaveFocus(); }); } }); @@ -196,7 +196,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { expect(grid("July 2022")).toBeInTheDocument(); }); test("should focus the next day", () => { - expect(gridcell(nextDay)).toHaveFocus(); + expect(dateButton(nextDay)).toHaveFocus(); }); } else { test("should display the same month", () => { @@ -204,7 +204,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { }); test("should focus the previous day", () => { const prevDay = addDays(day, -1); - expect(gridcell(prevDay)).toHaveFocus(); + expect(dateButton(prevDay)).toHaveFocus(); }); } }); @@ -215,7 +215,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { }); test("should focus the day in the previous week", () => { const prevDay = addWeeks(day, -1); - expect(gridcell(prevDay)).toHaveFocus(); + expect(dateButton(prevDay)).toHaveFocus(); }); }); describe("when the Arrow Down is pressed", () => { @@ -225,7 +225,7 @@ describe.each(["ltr", "rtl"])("when text direction is %s", (dir: string) => { }); test("should focus the day in the next week", () => { const nextDay = addWeeks(day, 1); - expect(gridcell(nextDay)).toHaveFocus(); + expect(dateButton(nextDay)).toHaveFocus(); }); }); }); @@ -237,20 +237,20 @@ describe("when week is set to start on a Monday", () => { const endOfWeekDay = endOfWeek(day, { weekStartsOn: 1 }); beforeEach(() => { - renderApp(); - act(() => gridcell(day).focus()); + render(); + act(() => dateButton(day).focus()); }); describe("when Home is pressed", () => { beforeEach(() => user.type(activeElement(), "{home}")); it("should focus the start of the week being Monday", () => { - expect(gridcell(startOfWeekDay)).toHaveFocus(); + expect(dateButton(startOfWeekDay)).toHaveFocus(); }); }); describe("when End is pressed", () => { beforeEach(() => user.type(activeElement(), "{end}")); it("should focus the end of the week being Sunday", () => { - expect(gridcell(endOfWeekDay)).toHaveFocus(); + expect(dateButton(endOfWeekDay)).toHaveFocus(); }); }); }); diff --git a/examples/ModifiersCustom.test.tsx b/examples/ModifiersCustom.test.tsx index 9dcfe5438e..f442fdfba5 100644 --- a/examples/ModifiersCustom.test.tsx +++ b/examples/ModifiersCustom.test.tsx @@ -12,10 +12,10 @@ beforeEach(() => { test.each([new Date(2024, 5, 8), new Date(2024, 5, 9), new Date(2021, 5, 10)])( "%s should have the booked style", (day) => { - expect(gridcell(day)).toHaveClass("booked"); + expect(gridcell(day, true)).toHaveClass("booked"); } ); test.each([new Date(2024, 5, 1)])("%s should have the booked style", (day) => { - expect(gridcell(day)).not.toHaveClass("booked"); + expect(gridcell(day, true)).not.toHaveClass("booked"); }); diff --git a/examples/ModifiersDisabled.test.tsx b/examples/ModifiersDisabled.test.tsx index d39ac31a86..ecd5c3705c 100644 --- a/examples/ModifiersDisabled.test.tsx +++ b/examples/ModifiersDisabled.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton } from "@/test/elements"; import { render } from "@/test/render"; import { ModifiersDisabled } from "./ModifiersDisabled"; @@ -13,5 +13,5 @@ const days = [ test.each(days)("the day %s should be disabled", (day) => { render(); - expect(gridcell(day)).toHaveAttribute("aria-disabled", "true"); + expect(dateButton(day)).toBeDisabled(); }); diff --git a/examples/ModifiersStyle.test.tsx b/examples/ModifiersStyle.test.tsx index 2579307e18..20214757b8 100644 --- a/examples/ModifiersStyle.test.tsx +++ b/examples/ModifiersStyle.test.tsx @@ -20,5 +20,5 @@ const style = { color: "lightgreen" }; test.each(days)("The day %s should have the proper inline style", (day) => { - expect(gridcell(day)).toHaveStyle(style); + expect(gridcell(day, true)).toHaveStyle(style); }); diff --git a/examples/ModifiersToday.test.tsx b/examples/ModifiersToday.test.tsx index 253ace059b..938bcef79f 100644 --- a/examples/ModifiersToday.test.tsx +++ b/examples/ModifiersToday.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { addDays } from "date-fns"; -import { gridcell, app } from "@/test/elements"; +import { dateButton, app, gridcell } from "@/test/elements"; import { renderApp } from "@/test/renderApp"; import { user } from "@/test/user"; @@ -19,7 +19,7 @@ beforeEach(() => { describe("when rendering a month that contains today", () => { test("it should add the default class name for today", () => { - expect(gridcell(today)).toHaveClass("rdp-today"); + expect(gridcell(today, true)).toHaveClass("rdp-today"); }); test('it should have exactly one ".day_today" class', () => { const todays = app().querySelectorAll(".rdp-today"); @@ -29,7 +29,7 @@ describe("when rendering a month that contains today", () => { describe("when the today date is clicked", () => { beforeEach(async () => { - await user.click(gridcell(today)); + await user.click(dateButton(today)); }); test("should update the footer", () => { expect(app()).toHaveTextContent("You clicked the today’s date"); @@ -38,8 +38,8 @@ describe("when the today date is clicked", () => { describe("when another date is clicked", () => { const date = addDays(today, 1); - beforeEach(async () => user.click(gridcell(date))); + beforeEach(async () => user.click(dateButton(date))); test("should update the footer", () => { - expect(app()).toHaveTextContent("Try clicking the today’s date."); + expect(app()).toHaveTextContent("This is not the today’s date."); }); }); diff --git a/examples/ModifiersToday.tsx b/examples/ModifiersToday.tsx index c69badf3b3..2d1a86bb91 100644 --- a/examples/ModifiersToday.tsx +++ b/examples/ModifiersToday.tsx @@ -1,16 +1,19 @@ import React, { useState } from "react"; -import { DayMouseEventHandler, DayPicker } from "react-day-picker"; +import { DayEventHandler, DayPicker } from "react-day-picker"; export function ModifiersToday() { - const initialFooter =

Try clicking the today’s date.

; + const initialFooter = "Try clicking the today’s date."; const [footer, setFooter] = useState(initialFooter); - const handleDayClick: DayMouseEventHandler = (day, modifiers) => { + const handleDayClick: DayEventHandler = ( + day, + modifiers + ) => { if (modifiers.today) { - setFooter(

You clicked the today’s date.

); + setFooter("You clicked the today’s date."); } else { - setFooter(initialFooter); + setFooter("This is not the today’s date."); } }; return ; diff --git a/examples/Multiple.test.tsx b/examples/Multiple.test.tsx index 9a4a5aa99e..2d57b29fee 100644 --- a/examples/Multiple.test.tsx +++ b/examples/Multiple.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -18,29 +18,29 @@ beforeEach(() => { describe("when a day is clicked", () => { const day1 = new Date(2021, 10, 1); beforeEach(async () => { - await user.click(gridcell(day1)); + await user.click(dateButton(day1)); }); test("should appear as selected", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); describe("when the same day is clicked again", () => { beforeEach(async () => { - await user.click(gridcell(day1)); + await user.click(dateButton(day1)); }); test("should appear as not selected", () => { - expect(gridcell(day1)).not.toHaveAttribute("aria-selected"); + expect(gridcell(day1, true)).not.toHaveAttribute("aria-selected"); }); }); describe("when a second day is clicked", () => { const day2 = new Date(2021, 10, 2); beforeEach(async () => { - await user.click(gridcell(day2)); + await user.click(dateButton(day2)); }); test("the first day should appear as selected", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); test("the second day should appear as selected", () => { - expect(gridcell(day2)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day2, true)).toHaveAttribute("aria-selected", "true"); }); }); }); diff --git a/examples/MultipleMinMax.test.tsx b/examples/MultipleMinMax.test.tsx index 40fcb5dcd6..a1dfe10f42 100644 --- a/examples/MultipleMinMax.test.tsx +++ b/examples/MultipleMinMax.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { addDays } from "date-fns"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -27,30 +27,36 @@ beforeEach(() => { describe("when a day is clicked", () => { beforeEach(async () => { - await user.click(gridcell(days[0])); + await user.click(dateButton(days[0])); }); test("should appear as selected", () => { - expect(gridcell(days[0])).toHaveAttribute("aria-selected", "true"); + expect(gridcell(days[0], true)).toHaveAttribute("aria-selected", "true"); }); describe("when a second day is clicked", () => { beforeEach(async () => { - await user.click(gridcell(days[1])); + await user.click(dateButton(days[1])); }); test("the first day should appear as selected", () => { - expect(gridcell(days[0])).toHaveAttribute("aria-selected", "true"); + expect(gridcell(days[0], true)).toHaveAttribute("aria-selected", "true"); }); test("the second day should appear as selected", () => { - expect(gridcell(days[1])).toHaveAttribute("aria-selected", "true"); + expect(gridcell(days[1], true)).toHaveAttribute("aria-selected", "true"); }); describe("when clicked again", () => { beforeEach(async () => { - await user.click(gridcell(days[1])); + await user.click(dateButton(days[1])); }); test("the first day should still appear as selected", () => { - expect(gridcell(days[0])).toHaveAttribute("aria-selected", "true"); + expect(gridcell(days[0], true)).toHaveAttribute( + "aria-selected", + "true" + ); }); test("the second day should still appear as selected", () => { - expect(gridcell(days[1])).toHaveAttribute("aria-selected", "true"); + expect(gridcell(days[1], true)).toHaveAttribute( + "aria-selected", + "true" + ); }); }); }); @@ -58,17 +64,17 @@ describe("when a day is clicked", () => { describe("when the first 5 days are clicked", () => { beforeEach(async () => { - await user.click(gridcell(days[0])); - await user.click(gridcell(days[1])); - await user.click(gridcell(days[2])); - await user.click(gridcell(days[3])); - await user.click(gridcell(days[4])); + await user.click(dateButton(days[0])); + await user.click(dateButton(days[1])); + await user.click(dateButton(days[2])); + await user.click(dateButton(days[3])); + await user.click(dateButton(days[4])); }); test.each(days)("the %s day should appear as selected", (day) => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); test("the sixth day should not appear as selected", () => { const day6 = addDays(today, 5); - expect(gridcell(day6)).not.toHaveAttribute("aria-selected"); + expect(gridcell(day6, true)).not.toHaveAttribute("aria-selected"); }); }); diff --git a/examples/MultipleMonthsId.test.tsx b/examples/MultipleMonthsId.test.tsx deleted file mode 100644 index 4c20436a59..0000000000 --- a/examples/MultipleMonthsId.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; - -import { grid } from "@/test/elements"; -import { render } from "@/test/render"; - -import { MultipleMonthsId } from "./MultipleMonthsId"; - -const today = new Date(2021, 10, 25); - -beforeAll(() => jest.setSystemTime(today)); -afterAll(() => jest.useRealTimers()); - -test("the table ids should include the display index", () => { - render(); - expect(grid("November 2021")).toHaveAttribute( - "id", - "calendar_example-grid-0" - ); - expect(grid("December 2021")).toHaveAttribute( - "id", - "calendar_example-grid-1" - ); -}); diff --git a/examples/MultipleMonthsId.tsx b/examples/MultipleMonthsId.tsx deleted file mode 100644 index 65ceceaf17..0000000000 --- a/examples/MultipleMonthsId.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -import { DayPicker } from "react-day-picker"; - -export function MultipleMonthsId() { - return ; -} diff --git a/examples/None.tsx b/examples/None.tsx deleted file mode 100644 index ec60f8c7b6..0000000000 --- a/examples/None.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -import { DayPicker } from "react-day-picker"; - -export function None() { - return ; -} diff --git a/examples/NumberingSystem.test.tsx b/examples/NumberingSystem.test.tsx index 63f34c4619..a8c78b4c38 100644 --- a/examples/NumberingSystem.test.tsx +++ b/examples/NumberingSystem.test.tsx @@ -1,6 +1,5 @@ import React from "react"; -import { grid } from "@/test/elements"; import { render, screen } from "@/test/render"; import { NumberingSystem } from "./NumberingSystem"; @@ -14,9 +13,6 @@ beforeEach(() => { render(); }); -test("should localize the year", () => { - expect(grid("نوفمبر ٢٬٠٢١")).toBeInTheDocument(); -}); test("should localize the days", () => { expect(screen.getByText("أحد")).toBeInTheDocument(); }); diff --git a/examples/NumberingSystem.tsx b/examples/NumberingSystem.tsx index 4251096847..109ab57580 100644 --- a/examples/NumberingSystem.tsx +++ b/examples/NumberingSystem.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { FormatOptions, format } from "date-fns"; +import { format } from "date-fns"; import { arSA } from "date-fns/locale"; -import { DayPicker } from "react-day-picker"; +import { DayPicker, FormatOptions } from "react-day-picker"; const NU_LOCALE = "ar-u-nu-arab"; diff --git a/examples/OutsideDays.test.tsx b/examples/OutsideDays.test.tsx index 48cf8c0491..dd6abea27e 100644 --- a/examples/OutsideDays.test.tsx +++ b/examples/OutsideDays.test.tsx @@ -1,6 +1,7 @@ import React from "react"; -import { render, screen } from "@/test/render"; +import { gridcell } from "@/test/elements"; +import { render } from "@/test/render"; import { OutsideDays } from "./OutsideDays"; @@ -15,7 +16,6 @@ beforeEach(() => { describe("when displaying a month with outside days", () => { test("should display the outside day", () => { - // TODO: verify this test actually works - expect(screen.getByRole("gridcell", { name: "31" })).toBeInTheDocument(); + expect(gridcell(new Date(2021, 9, 31))).toBeInTheDocument(); }); }); diff --git a/examples/OutsideDays.tsx b/examples/OutsideDays.tsx index abc7021c69..b68860026e 100644 --- a/examples/OutsideDays.tsx +++ b/examples/OutsideDays.tsx @@ -3,5 +3,5 @@ import React from "react"; import { DayPicker } from "react-day-picker"; export function OutsideDays() { - return ; + return ; } diff --git a/examples/Range.test.tsx b/examples/Range.test.tsx index ff175ae887..40e3e50316 100644 --- a/examples/Range.test.tsx +++ b/examples/Range.test.tsx @@ -2,20 +2,21 @@ import React from "react"; import { addDays } from "date-fns"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render, screen } from "@/test/render"; import { user } from "@/test/user"; import { Range } from "./Range"; -const pastMonth = new Date(2020, 10, 15); +const defaultMonth = new Date(2020, 5, 15); + let container: HTMLElement; const days = [ - pastMonth, - addDays(pastMonth, 1), - addDays(pastMonth, 2), - addDays(pastMonth, 3), - addDays(pastMonth, 4) + defaultMonth, + addDays(defaultMonth, 1), + addDays(defaultMonth, 2), + addDays(defaultMonth, 3), + addDays(defaultMonth, 4) ]; beforeEach(() => (container = render().container)); @@ -24,33 +25,33 @@ test("should match the snapshot", () => { expect(container).toMatchSnapshot(); }); test.each(days)("%s should be selected", (day) => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); describe("when a day in the range is clicked", () => { const day = days[2]; - beforeEach(async () => user.click(gridcell(day))); + beforeEach(async () => user.click(dateButton(day))); test.each([days[0], days[1], day])("%s should be selected", (day) => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); test.each([days[3], days[4]])("%s should not be selected", (day) => { - expect(gridcell(day)).not.toHaveAttribute("aria-selected"); + expect(gridcell(day, true)).not.toHaveAttribute("aria-selected"); }); describe("when the day is clicked again", () => { const day = days[2]; - beforeEach(async () => user.click(gridcell(day))); + beforeEach(async () => user.click(dateButton(day))); test("only one day should be selected", () => { - expect(getAllSelectedDays()).toHaveLength(1); + expect(getAllSelected()).toHaveLength(1); }); test("only a day in the range should be selected", () => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); describe("when a day in the range is clicked again", () => { const day = days[2]; - beforeEach(async () => user.click(gridcell(day))); + beforeEach(async () => user.click(dateButton(day))); test("no day should be selected", () => { - expect(getAllSelectedDays()).toHaveLength(0); + expect(getAllSelected()).toHaveLength(0); }); test("should match the snapshot", () => { expect(container).toMatchSnapshot(); @@ -59,10 +60,10 @@ describe("when a day in the range is clicked", () => { }); }); -function getAllSelectedDays() { - const buttons = screen.getAllByRole("gridcell"); +function getAllSelected() { + const gridcells = screen.getAllByRole("gridcell"); - return Array.from(buttons).filter( - (button) => button.getAttribute("aria-selected") === "true" + return Array.from(gridcells).filter( + (gridcell) => gridcell.getAttribute("aria-selected") === "true" ); } diff --git a/examples/Range.tsx b/examples/Range.tsx index 4dc59b97ea..d56ef15254 100644 --- a/examples/Range.tsx +++ b/examples/Range.tsx @@ -12,16 +12,12 @@ export function Range() { }; const [range, setRange] = useState(defaultSelected); - let footer =

Please pick the first day.

; + let footer = `Please pick the first day.`; if (range?.from) { if (!range.to) { - footer =

{format(range.from, "PPP")}

; + footer = format(range.from, "PPP"); } else if (range.to) { - footer = ( -

- {format(range.from, "PPP")}–{format(range.to, "PPP")} -

- ); + footer = `${format(range.from, "PPP")}–${format(range.to, "PPP")}`; } } diff --git a/examples/RangeMinMax.test.tsx b/examples/RangeMinMax.test.tsx index c290111326..abf2d750f7 100644 --- a/examples/RangeMinMax.test.tsx +++ b/examples/RangeMinMax.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { addDays } from "date-fns"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -13,40 +13,43 @@ beforeEach(() => render()); describe("when a day is clicked", () => { const firstDay = new Date(2022, 8, 13); beforeEach(async () => { - await user.click(gridcell(firstDay)); + await user.click(dateButton(firstDay)); }); test("should be selected", () => { - expect(gridcell(firstDay)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(firstDay, true)).toHaveAttribute("aria-selected", "true"); }); describe("when the day before min is clicked", () => { const dayAfter = addDays(firstDay, 1); beforeEach(async () => { - await user.click(gridcell(dayAfter)); + await user.click(dateButton(dayAfter)); }); test("the first day should not be selected", () => { - expect(gridcell(firstDay)).not.toHaveAttribute("aria-selected", "true"); + expect(gridcell(firstDay, true)).not.toHaveAttribute( + "aria-selected", + "true" + ); }); test("the day after should be selected", () => { - expect(gridcell(dayAfter)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(dayAfter, true)).toHaveAttribute("aria-selected", "true"); }); }); describe("when the day after min is clicked", () => { const dayAfter = addDays(firstDay, 4); beforeEach(async () => { - await user.click(gridcell(dayAfter)); + await user.click(dateButton(dayAfter)); }); test("a range should be selected", () => { - expect(gridcell(firstDay)).toHaveAttribute("aria-selected", "true"); - expect(gridcell(addDays(firstDay, 1))).toHaveAttribute( + expect(gridcell(firstDay, true)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(addDays(firstDay, 1), true)).toHaveAttribute( "aria-selected", "true" ); - expect(gridcell(addDays(firstDay, 2))).toHaveAttribute( + expect(gridcell(addDays(firstDay, 2), true)).toHaveAttribute( "aria-selected", "true" ); - expect(gridcell(addDays(firstDay, 3))).toHaveAttribute( + expect(gridcell(addDays(firstDay, 3), true)).toHaveAttribute( "aria-selected", "true" ); diff --git a/examples/RangeMinMax.tsx b/examples/RangeMinMax.tsx index a750cce99e..5e8b8edc20 100644 --- a/examples/RangeMinMax.tsx +++ b/examples/RangeMinMax.tsx @@ -6,16 +6,12 @@ import { DateRange, DayPicker } from "react-day-picker"; export function RangeMinMax() { const [range, setRange] = useState(); - let footer =

Please pick the first day.

; + let footer = `Please pick the first day.`; if (range?.from) { if (!range.to) { - footer =

{format(range.from, "PPP")}

; + footer = format(range.from, "PPP"); } else if (range.to) { - footer = ( -

- {format(range.from, "PPP")}–{format(range.to, "PPP")} -

- ); + footer = `${format(range.from, "PPP")}–${format(range.to, "PPP")}`; } } diff --git a/examples/RangeShiftKey.test.tsx b/examples/RangeShiftKey.test.tsx index 1c22a565d9..6883c3bad6 100644 --- a/examples/RangeShiftKey.test.tsx +++ b/examples/RangeShiftKey.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -11,34 +11,34 @@ const today = new Date(2021, 10, 25); beforeAll(() => jest.setSystemTime(today)); afterAll(() => jest.useRealTimers()); -beforeEach(() => render().container); +beforeEach(() => render()); describe("when displaying November 2021", () => { describe("when clicking on the 11th", () => { const day1 = new Date(2021, 10, 11); - beforeEach(async () => user.click(gridcell(day1))); + beforeEach(async () => user.click(dateButton(day1))); test("the 11th day should have aria-selected true", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); describe("when clicking on the 13th", () => { const day2 = new Date(2021, 10, 13); - beforeEach(async () => user.click(gridcell(day2))); + beforeEach(async () => user.click(dateButton(day2))); test("the 11th day should still have aria-selected true", () => { - expect(gridcell(day1)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day1, true)).toHaveAttribute("aria-selected", "true"); }); test("the 13th day not should not have aria-selected", () => { - expect(gridcell(day2)).not.toHaveAttribute("aria-selected"); + expect(gridcell(day2, true)).not.toHaveAttribute("aria-selected"); }); }); describe("when pressing the Shift key", () => { const day2 = new Date(2021, 10, 13); beforeEach(async () => { user.keyboard("{Shift>}"); - await user.click(gridcell(day2)); + await user.click(dateButton(day2)); }); test("the 13th day should have aria-selected true", () => { - expect(gridcell(day2)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day2, true)).toHaveAttribute("aria-selected", "true"); }); }); }); diff --git a/examples/RangeShiftKey.tsx b/examples/RangeShiftKey.tsx index e79d47058d..53084e219d 100644 --- a/examples/RangeShiftKey.tsx +++ b/examples/RangeShiftKey.tsx @@ -3,16 +3,15 @@ import React, { MouseEventHandler } from "react"; import { isSameDay } from "date-fns"; import { DateRange, + DayButtonProps, DayPicker, - useRange, - type DayProps + useDayPicker } from "react-day-picker"; -function DayWithShiftKey(props: DayProps) { - const { selected } = useRange(); - const onClick = props.rootProps?.onClick; +function DayWithShiftKey(props: DayButtonProps) { + const { selected } = useDayPicker({ mode: "range" }); - const handleClick: MouseEventHandler = (e) => { + const handleClick: MouseEventHandler = (e) => { if ( selected?.from && !selected.to && @@ -21,12 +20,12 @@ function DayWithShiftKey(props: DayProps) { ) { return; } - onClick?.(e); + props.onClick?.(e); }; return ( -
+
+ ); } @@ -35,21 +34,19 @@ export function RangeShiftKey() { from: undefined }); - let footer =

Please pick a day.

; + let footer = "Please pick a day."; if (range?.from && !range?.to) { - footer =

Press Shift to choose more days.

; + footer = "Press Shift to choose more days."; } else if (range?.to) { - footer = ( -

- {range?.from?.toLocaleDateString()}—{range.to.toLocaleDateString()}. -

- ); + const formattedFrom = range.from?.toDateString(); + const formattedTo = range.to.toDateString(); + footer = `You selected the days between ${formattedFrom} and ${formattedTo}`; } return ( { describe("when a day is clicked", () => { const day = new Date(2021, 10, 1); beforeEach(async () => { - await user.click(gridcell(day)); + await user.click(dateButton(day)); }); test("should appear as selected", () => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); - expect(gridcell(day)).toHaveFocus(); - expect(gridcell(day)).toHaveClass("rdp-selected"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); + expect(dateButton(day)).toHaveFocus(); + expect(gridcell(day, true)).toHaveClass("rdp-selected"); }); describe("when the day is clicked again", () => { beforeEach(async () => { - await user.click(gridcell(day)); + await user.click(dateButton(day)); }); test("should not appear as selected", () => { - expect(gridcell(day)).not.toHaveAttribute("aria-selected"); - expect(gridcell(day)).not.toHaveClass("rdp-selected"); + expect(gridcell(day, true)).not.toHaveAttribute("aria-selected"); }); }); }); diff --git a/examples/SingleRequired.test.tsx b/examples/SingleRequired.test.tsx index eb9f8fae1e..fd3def454c 100644 --- a/examples/SingleRequired.test.tsx +++ b/examples/SingleRequired.test.tsx @@ -1,29 +1,29 @@ import React from "react"; -import { gridcell } from "@/test/elements"; -import { renderApp } from "@/test/renderApp"; +import { dateButton, gridcell } from "@/test/elements"; +import { render } from "@/test/render"; import { user } from "@/test/user"; import { SingleRequired } from "./SingleRequired"; beforeEach(() => { - renderApp(); + render(); }); describe("when a day is clicked", () => { const day = new Date(); beforeEach(async () => { - await user.click(gridcell(day)); + await user.click(dateButton(day)); }); test("should appear as selected", () => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); describe("when the day is clicked again", () => { beforeEach(async () => { - await user.click(gridcell(day)); + await user.click(dateButton(day)); }); test("should appear as selected", () => { - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); }); }); diff --git a/examples/Start.test.tsx b/examples/Start.test.tsx index c58e29fa0e..636484c504 100644 --- a/examples/Start.test.tsx +++ b/examples/Start.test.tsx @@ -1,6 +1,11 @@ import React from "react"; -import { nextButton, gridcell, previousButton } from "@/test/elements"; +import { + nextButton, + dateButton, + previousButton, + gridcell +} from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -31,7 +36,7 @@ const day = new Date(2021, 10, 1); describe("when a day is clicked", () => { test("should appear as selected", async () => { - await user.click(gridcell(day)); - expect(gridcell(day)).toHaveAttribute("aria-selected", "true"); + await user.click(dateButton(day)); + expect(gridcell(day, true)).toHaveAttribute("aria-selected", "true"); }); }); diff --git a/examples/Start.tsx b/examples/Start.tsx index 19eb39c41e..f9fbc62007 100644 --- a/examples/Start.tsx +++ b/examples/Start.tsx @@ -5,9 +5,5 @@ import { DayPicker } from "react-day-picker"; export function Start() { const [selected, setSelected] = useState(); - return ( -
- -
- ); + return ; } diff --git a/examples/TailwindCSS.tsx b/examples/TailwindCSS.tsx index 6672676414..48fed9c607 100644 --- a/examples/TailwindCSS.tsx +++ b/examples/TailwindCSS.tsx @@ -21,7 +21,7 @@ export function TailwindCSS() { classNames={{ today: `border-amber-500`, selected: `bg-amber-500 border-amber-500 text-white`, - calendar: `${defaultClassNames.calendar} bg-white shadow-lg p-5`, + root: `${defaultClassNames.root} bg-white shadow-lg p-5`, chevron: `${defaultClassNames.chevron} fill-amber-500` }} /> diff --git a/examples/TestCase2047.test.tsx b/examples/TestCase2047.test.tsx index f2911e2530..1c9094a6c0 100644 --- a/examples/TestCase2047.test.tsx +++ b/examples/TestCase2047.test.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { gridcell } from "@/test/elements"; +import { dateButton, gridcell } from "@/test/elements"; import { render } from "@/test/render"; import { user } from "@/test/user"; @@ -11,14 +11,18 @@ beforeEach(async () => { }); test("disabled date is not selected", () => { - expect(gridcell(new Date(2024, 5, 10))).not.toHaveAttribute("aria-selected"); + expect(gridcell(new Date(2024, 5, 10), true)).not.toHaveAttribute( + "aria-selected" + ); }); describe("when the calendar is focused", () => { beforeEach(async () => { - await user.click(gridcell(new Date(2024, 5, 10))); + await user.click(dateButton(new Date(2024, 5, 10))); }); test("the disabled day should not have focused modifier", () => { - expect(gridcell(new Date(2024, 5, 10))).not.toHaveClass("rdp-focused"); + expect(gridcell(new Date(2024, 5, 10), true)).not.toHaveClass( + "rdp-focused" + ); }); }); diff --git a/examples/Weeknumber.test.tsx b/examples/Weeknumber.test.tsx index c1ffeebc91..abe7de8117 100644 --- a/examples/Weeknumber.test.tsx +++ b/examples/Weeknumber.test.tsx @@ -1,7 +1,6 @@ import React from "react"; import { render, screen } from "@/test/render"; -import { user } from "@/test/user"; import { Weeknumber } from "./Weeknumber"; @@ -22,14 +21,4 @@ describe("when displaying November 2021", () => { test("should display the 45th week number", () => { expect(getWeekButton(45)).toBeInTheDocument(); }); - describe("when the week button is clicked", () => { - beforeEach(async () => { - return user.click(getWeekButton(45)); - }); - test("should update the footer", () => { - expect( - screen.getByText("You clicked the week n. 45.") - ).toBeInTheDocument(); - }); - }); }); diff --git a/examples/Weeknumber.tsx b/examples/Weeknumber.tsx index e91b939efa..2989346b7a 100644 --- a/examples/Weeknumber.tsx +++ b/examples/Weeknumber.tsx @@ -1,19 +1,7 @@ -import React, { useState } from "react"; +import React from "react"; import { DayPicker } from "react-day-picker"; export function Weeknumber() { - const [weekNumber, setWeekNumber] = useState(); - - const footer = weekNumber - ? `You clicked the week n. ${weekNumber}.` - : "Try clicking a week number."; - - return ( - - ); + return ; } diff --git a/examples/WeeknumberCustom.tsx b/examples/WeeknumberCustom.tsx index 6430d355cb..065c3e96eb 100644 --- a/examples/WeeknumberCustom.tsx +++ b/examples/WeeknumberCustom.tsx @@ -1,17 +1,23 @@ +/* eslint-disable no-console */ import React from "react"; import { addMonths } from "date-fns"; -import { DayPicker } from "react-day-picker"; +import { DayPicker, WeekNumberProps } from "react-day-picker"; const today = new Date(2021, 0, 1); export function WeeknumberCustom() { return ( ( + + + + ) + }} labels={{ labelWeekNumber: (weekNumber: number) => `W${weekNumber}` }} diff --git a/examples/__snapshots__/Range.test.tsx.snap b/examples/__snapshots__/Range.test.tsx.snap index d9bb2bfeab..dbec639685 100644 --- a/examples/__snapshots__/Range.test.tsx.snap +++ b/examples/__snapshots__/Range.test.tsx.snap @@ -3,13 +3,16 @@ exports[`should match the snapshot 1`] = `
-
-
- - Su - - - Mo - - - Tu - - - We - - - Th - - - Fr - - + - Sa - -
-
+ Su + + + Mo + + + Tu + + + We + + + Th + + + Fr + + + Sa + + + + -
- -
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
+ + - 5 - -
-
+ + - 6 - -
-
-
+ + + -
- 7 - -
-
+ + - 8 - -
-
+ + - 9 - -
-
+ + - 10 - -
-
+ + - 11 - -
-
+ + - 12 - -
-
+ + - 13 - -
-
-
+ + + -
- 14 - -
-
+ + - 15 - -
-
+ + - 16 - -
-
+ + - 17 - -
-
+ + - 18 - -
-
+ + - 19 - -
-
+ + - 20 - -
-
-
+ + + -
- 21 - -
-
+ + - 22 - -
-
+ + - 23 - -
-
+ + - 24 - -
-
+ + - 25 - -
-
+ + - 26 - -
-
+ + - 27 - -
-
-
+ + + -
- 28 - -
-
+ + - 29 - -
-
+ + - 30 - -
-
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
-
-
+ + + + +
@@ -654,13 +645,16 @@ exports[`should match the snapshot 1`] = ` exports[`when a day in the range is clicked when the day is clicked again when a day in the range is clicked again should match the snapshot 1`] = `
-
-
- - Su - - - Mo - - - Tu - - - We - - - Th - - - Fr - - + - Sa - -
-
+ Su + + + Mo + + + Tu + + + We + + + Th + + + Fr + + + Sa + + + + -
- -
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
+ + - 5 - -
-
+ + - 6 - -
-
-
+ + + -
- 7 - -
-
+ + - 8 - -
-
+ + - 9 - -
-
+ + - 10 - -
-
+ + - 11 - -
-
+ + - 12 - -
-
+ + - 13 - -
-
-
+ + + -
- 14 - -
-
+ + - 15 - -
-
+ + - 16 - -
-
+ + - 17 - -
-
+ + - 18 - -
-
+ + - 19 - -
-
+ + - 20 - -
-
-
+ + + -
- 21 - -
-
+ + - 22 - -
-
+ + - 23 - -
-
+ + - 24 - -
-
+ + - 25 - -
-
+ + - 26 - -
-
+ + - 27 - -
-
-
+ + + -
- 28 - -
-
+ + - 29 - -
-
+ + - 30 - -
-
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
-
-
+ + + + +
diff --git a/examples/__snapshots__/StylingCssModules.test.tsx.snap b/examples/__snapshots__/StylingCssModules.test.tsx.snap index e797fe97d0..61284e82e9 100644 --- a/examples/__snapshots__/StylingCssModules.test.tsx.snap +++ b/examples/__snapshots__/StylingCssModules.test.tsx.snap @@ -5,13 +5,15 @@ exports[`should match the snapshot 1`] = ` role="application" >
-
-
- - Su - - - Mo - - - Tu - - - We - - - Th - - - Fr - - + - Sa - -
-
+ Su + + + Mo + + + Tu + + + We + + + Th + + + Fr + + + Sa + + + + -
- -
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
+ + - 5 - -
-
+ + - 6 - -
-
-
+ + + -
- 7 - -
-
+ + - 8 - -
-
+ + - 9 - -
-
+ + - 10 - -
-
+ + - 11 - -
-
+ + - 12 - -
-
+ + - 13 - -
-
-
+ + + -
- 14 - -
-
+ + - 15 - -
-
+ + - 16 - -
-
+ + - 17 - -
-
+ + - 18 - -
-
+ + - 19 - -
-
+ + - 20 - -
-
-
+ + + -
- 21 - -
-
+ + - 22 - -
-
+ + - 23 - -
-
+ + - 24 - -
-
+ + - 25 - -
-
+ + - 26 - -
-
+ + - 27 - -
-
-
+ + + -
- 28 - -
-
+ + - 29 - -
-
+ + - 30 - -
-
+ + - 1 - -
-
+ + - 2 - -
-
+ + - 3 - -
-
+ + - 4 - -
-
-
-
+ + + + +
diff --git a/examples/index.ts b/examples/index.ts index 07755f3685..34d9be9cc4 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -4,7 +4,7 @@ export * from "./Controlled"; export * from "./CssModules"; export * from "./CssVariables"; export * from "./CustomCaption"; -export * from "./CustomDayDate"; +export * from "./CustomDayButton"; export * from "./CustomMultiple"; export * from "./CustomSingle"; export * from "./CustomWeek"; @@ -15,6 +15,7 @@ export * from "./DisableNavigation"; export * from "./Dropdown"; export * from "./DropdownMultipleMonths"; export * from "./Fixedweeks"; +export * from "./AutoFocus"; export * from "./FocusRecursive"; export * from "./Footer"; export * from "./Formatters"; @@ -36,9 +37,7 @@ export * from "./ModifiersToday"; export * from "./Multiple"; export * from "./MultipleMinMax"; export * from "./MultipleMonths"; -export * from "./MultipleMonthsId"; export * from "./MultipleMonthsPaged"; -export * from "./None"; export * from "./NumberingSystem"; export * from "./OutsideDays"; export * from "./Range"; diff --git a/package.json b/package.json index e6f284dbeb..356d71d68b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-day-picker", - "version": "9.0.0-rc.2", + "version": "9.0.0-rc.4", "description": "Customizable Date Picker for React", "author": "Giampaolo Bellavite ", "homepage": "http://daypicker.dev", @@ -98,10 +98,10 @@ }, "scripts": { "prepublish": "pnpm build", - "build": "pnpm build:cjs && pnpm build:esm", + "build": "pnpm build:cjs && pnpm build:esm && pnpm build:css", "build:cjs": "tsc --project tsconfig-cjs.json", "build:esm": "tsc --project tsconfig-esm.json", - "build:css": "tcm src", + "build:css": "./scripts/build-css.sh ./src/style.css ./src/style.module.css", "lint": "eslint .", "test": "jest", "test-watch": "jest --watch", @@ -121,17 +121,17 @@ "devDependencies": { "@date-fns/utc": "^1.2.0", "@jest/types": "^29.6.3", - "@testing-library/dom": "^10.1.0", + "@testing-library/dom": "^10.3.1", "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jest": "^29.5.12", - "@types/node": "^20.14.2", + "@types/node": "^20.14.10", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.16.0", "date-fns-jalali": "3.6.0-1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49c6585eee..84df851472 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,17 +19,17 @@ importers: specifier: ^29.6.3 version: 29.6.3 '@testing-library/dom': - specifier: ^10.1.0 - version: 10.2.0 + specifier: ^10.3.1 + version: 10.3.1 '@testing-library/jest-dom': specifier: ^6.4.5 - version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3))) + version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))) '@testing-library/react': specifier: ^16.0.0 - version: 16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 16.0.0(@testing-library/dom@10.3.1)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/user-event': specifier: ^14.5.2 - version: 14.5.2(@testing-library/dom@10.2.0) + version: 14.5.2(@testing-library/dom@10.3.1) '@trivago/prettier-plugin-sort-imports': specifier: ^4.3.0 version: 4.3.0(prettier@3.3.2) @@ -37,8 +37,8 @@ importers: specifier: ^29.5.12 version: 29.5.12 '@types/node': - specifier: ^20.14.2 - version: 20.14.9 + specifier: ^20.14.10 + version: 20.14.10 '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -46,11 +46,11 @@ importers: specifier: ^18.3.0 version: 18.3.0 '@typescript-eslint/eslint-plugin': - specifier: ^7.13.1 - version: 7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + specifier: ^7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: ^7.12.0 - version: 7.14.1(eslint@8.57.0)(typescript@5.5.3) + specifier: ^7.16.0 + version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) date-fns-jalali: specifier: 3.6.0-1 version: 3.6.0-1 @@ -62,13 +62,13 @@ importers: version: 9.1.0(eslint@8.57.0) eslint-import-resolver-typescript: specifier: ^3.6.1 - version: 3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + version: 3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jest: specifier: ^28.6.0 - version: 28.6.0(@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3) + version: 28.6.0(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3) eslint-plugin-prettier: specifier: ^5.1.3 version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) @@ -86,7 +86,7 @@ importers: version: 6.2.2(eslint@8.57.0)(typescript@5.5.3) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + version: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -110,10 +110,10 @@ importers: version: 18.3.1(react@18.3.1) ts-jest: specifier: ^29.1.4 - version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3) + version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) + version: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) tslib: specifier: ^2.6.2 version: 2.6.3 @@ -133,7 +133,7 @@ importers: specifier: ^18.3.1 version: 18.3.1 react-day-picker: - specifier: workspace:9.0.0-rc.2 + specifier: workspace:* version: link:.. react-dom: specifier: ^18.3.1 @@ -146,14 +146,14 @@ importers: specifier: ^18.3.0 version: 18.3.0 '@typescript-eslint/eslint-plugin': - specifier: ^7.13.1 - version: 7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + specifier: ^7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: ^7.13.1 - version: 7.14.1(eslint@8.57.0)(typescript@5.5.3) + specifier: ^7.16.0 + version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) '@vitejs/plugin-react': specifier: ^4.3.1 - version: 4.3.1(vite@5.3.1(@types/node@20.14.9)(terser@5.31.1)) + version: 4.3.1(vite@5.3.3(@types/node@20.14.10)(terser@5.31.1)) eslint: specifier: ^8.57.0 version: 8.57.0 @@ -167,8 +167,8 @@ importers: specifier: ^5.5.3 version: 5.5.3 vite: - specifier: ^5.3.1 - version: 5.3.1(@types/node@20.14.9)(terser@5.31.1) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.10)(terser@5.31.1) website: dependencies: @@ -206,7 +206,7 @@ importers: specifier: workspace:^ version: link:.. react-day-picker-v8: - specifier: npm:react-day-picker@8 + specifier: npm:react-day-picker@8.10.1 version: react-day-picker@8.10.1(date-fns@3.6.0)(react@18.3.1) react-dom: specifier: ^18.3.1 @@ -225,8 +225,8 @@ importers: specifier: 3.4.0 version: 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) docusaurus-plugin-typedoc: - specifier: ^1.0.1 - version: 1.0.1(typedoc-plugin-markdown@4.1.0(typedoc@0.26.3(typescript@5.5.3))) + specifier: ^1.0.2 + version: 1.0.2(typedoc-plugin-markdown@4.1.2(typedoc@0.26.3(typescript@5.5.3))) identity-obj-proxy: specifier: ^3.0.0 version: 3.0.0 @@ -235,10 +235,10 @@ importers: version: 0.26.3(typescript@5.5.3) typedoc-plugin-frontmatter: specifier: ^1.0.0 - version: 1.0.0(typedoc-plugin-markdown@4.1.0(typedoc@0.26.3(typescript@5.5.3))) + version: 1.0.0(typedoc-plugin-markdown@4.1.2(typedoc@0.26.3(typescript@5.5.3))) typedoc-plugin-markdown: - specifier: ^4.1.0 - version: 4.1.0(typedoc@0.26.3(typescript@5.5.3)) + specifier: ^4.1.2 + version: 4.1.2(typedoc@0.26.3(typescript@5.5.3)) typescript: specifier: ~5.5.3 version: 5.5.3 @@ -1700,8 +1700,8 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - '@testing-library/dom@10.2.0': - resolution: {integrity: sha512-CytIvb6tVOADRngTHGWNxH8LPgO/3hi/BdCEHOf7Qd2GvZVClhVP0Wo/QHzWhpki49Bk0b4VT6xpt3fx8HTSIw==} + '@testing-library/dom@10.3.1': + resolution: {integrity: sha512-q/WL+vlXMpC0uXDyfsMtc1rmotzLV8Y0gq6q1gfrrDjQeHoeLrqHbxdPvPNAh1i+xuJl7+BezywcXArz7vLqKQ==} engines: {node: '>=18'} '@testing-library/jest-dom@6.4.6': @@ -1892,6 +1892,9 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + '@types/node@20.14.10': + resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} + '@types/node@20.14.9': resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} @@ -1976,8 +1979,8 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.14.1': - resolution: {integrity: sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==} + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -1987,8 +1990,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.14.1': - resolution: {integrity: sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==} + '@typescript-eslint/parser@7.16.0': + resolution: {integrity: sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -2005,8 +2008,16 @@ packages: resolution: {integrity: sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.14.1': - resolution: {integrity: sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==} + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/scope-manager@7.16.0': + resolution: {integrity: sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -2023,6 +2034,14 @@ packages: resolution: {integrity: sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/types@7.16.0': + resolution: {integrity: sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==} + engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2041,6 +2060,24 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/typescript-estree@7.16.0': + resolution: {integrity: sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2053,6 +2090,12 @@ packages: peerDependencies: eslint: ^8.56.0 + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2061,6 +2104,14 @@ packages: resolution: {integrity: sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/visitor-keys@7.16.0': + resolution: {integrity: sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==} + engines: {node: ^18.18.0 || >=20.0.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -3014,8 +3065,8 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} - docusaurus-plugin-typedoc@1.0.1: - resolution: {integrity: sha512-q3e/XHmnMNdP361/0SMBbCQyr7oUwbSs5QMhu1BkEUvM45oKG7i1qxcKKabOefFDVDW9cmbBISWxB8XZGJAVFg==} + docusaurus-plugin-typedoc@1.0.2: + resolution: {integrity: sha512-V7ZOjsFVByfVuhIIFSVJCWKBQzIHLxl3W+sLVDUqMo/fwPZrHFFD0WropfPdZ7MR7AA697+0BeUWMEpLyO/QPw==} peerDependencies: typedoc-plugin-markdown: '>=4.0.0' @@ -5309,6 +5360,10 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -6242,8 +6297,8 @@ packages: peerDependencies: typedoc-plugin-markdown: '>=4.0.0' - typedoc-plugin-markdown@4.1.0: - resolution: {integrity: sha512-sUiEJVaa6+MOFShRy14j1OP/VXC5OLyHNecJ2nKeGuBy2M3YiMatSLoIiddFAqVptSuILJTZiJzCBIY6yzAVyg==} + typedoc-plugin-markdown@4.1.2: + resolution: {integrity: sha512-jZt8jmQLbmg9jmFQyfJrjLf6ljRwJ5fKMeqmFr0oPXmeX5ZRYYtCe6y/058vDESE/R+TwEvNua6SuG43UBbszw==} engines: {node: '>= 18'} peerDependencies: typedoc: 0.26.x @@ -6403,8 +6458,8 @@ packages: vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - vite@5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} + vite@5.3.3: + resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -7791,9 +7846,9 @@ snapshots: '@docusaurus/cssnano-preset@3.4.0': dependencies: - cssnano-preset-advanced: 6.1.2(postcss@8.4.38) - postcss: 8.4.38 - postcss-sort-media-queries: 5.2.0(postcss@8.4.38) + cssnano-preset-advanced: 6.1.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-sort-media-queries: 5.2.0(postcss@8.4.39) tslib: 2.6.3 '@docusaurus/logger@3.4.0': @@ -8174,7 +8229,7 @@ snapshots: infima: 0.2.0-alpha.43 lodash: 4.17.21 nprogress: 0.2.0 - postcss: 8.4.38 + postcss: 8.4.39 prism-react-renderer: 2.3.1(react@18.3.1) prismjs: 1.29.0 react: 18.3.1 @@ -8489,27 +8544,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -8534,7 +8589,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -8552,7 +8607,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -8574,7 +8629,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -8644,7 +8699,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -8914,7 +8969,7 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@testing-library/dom@10.2.0': + '@testing-library/dom@10.3.1': dependencies: '@babel/code-frame': 7.24.7 '@babel/runtime': 7.24.7 @@ -8925,7 +8980,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))': + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.7 @@ -8938,21 +8993,21 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) - '@testing-library/react@16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react@16.0.0(@testing-library/dom@10.3.1)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@testing-library/dom': 10.2.0 + '@testing-library/dom': 10.3.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.3 '@types/react-dom': 18.3.0 - '@testing-library/user-event@14.5.2(@testing-library/dom@10.2.0)': + '@testing-library/user-event@14.5.2(@testing-library/dom@10.3.1)': dependencies: - '@testing-library/dom': 10.2.0 + '@testing-library/dom': 10.3.1 '@tootallnate/once@2.0.0': {} @@ -9061,7 +9116,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/gtag.js@0.0.12': {} @@ -9098,7 +9153,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -9122,6 +9177,10 @@ snapshots: '@types/node@17.0.45': {} + '@types/node@20.14.10': + dependencies: + undici-types: 5.26.5 + '@types/node@20.14.9': dependencies: undici-types: 5.26.5 @@ -9205,7 +9264,7 @@ snapshots: '@types/webpack@3.8.27': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/tapable': 0.2.9 '@types/uglify-js': 3.17.5 source-map: 0.6.1 @@ -9220,14 +9279,14 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.1 - '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.5.3) - '@typescript-eslint/scope-manager': 7.14.1 - '@typescript-eslint/type-utils': 7.14.1(eslint@8.57.0)(typescript@5.5.3) - '@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.3) - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/parser': 7.16.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -9238,12 +9297,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3)': + '@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.14.1 - '@typescript-eslint/types': 7.14.1 - '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.3) - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/scope-manager': 7.16.0 + '@typescript-eslint/types': 7.16.0 + '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.16.0 debug: 4.3.5 eslint: 8.57.0 optionalDependencies: @@ -9261,10 +9320,20 @@ snapshots: '@typescript-eslint/types': 7.14.1 '@typescript-eslint/visitor-keys': 7.14.1 - '@typescript-eslint/type-utils@7.14.1(eslint@8.57.0)(typescript@5.5.3)': + '@typescript-eslint/scope-manager@7.15.0': dependencies: - '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.3) - '@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + + '@typescript-eslint/scope-manager@7.16.0': + dependencies: + '@typescript-eslint/types': 7.16.0 + '@typescript-eslint/visitor-keys': 7.16.0 + + '@typescript-eslint/type-utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) debug: 4.3.5 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.3) @@ -9277,6 +9346,10 @@ snapshots: '@typescript-eslint/types@7.14.1': {} + '@typescript-eslint/types@7.15.0': {} + + '@typescript-eslint/types@7.16.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.3)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -9306,6 +9379,36 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)': + dependencies: + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@7.16.0(typescript@5.5.3)': + dependencies: + '@typescript-eslint/types': 7.16.0 + '@typescript-eslint/visitor-keys': 7.16.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) @@ -9332,6 +9435,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -9342,16 +9456,26 @@ snapshots: '@typescript-eslint/types': 7.14.1 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@7.15.0': + dependencies: + '@typescript-eslint/types': 7.15.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@7.16.0': + dependencies: + '@typescript-eslint/types': 7.16.0 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react@4.3.1(vite@5.3.1(@types/node@20.14.9)(terser@5.31.1))': + '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.10)(terser@5.31.1))': dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.7) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.3.1(@types/node@20.14.9)(terser@5.31.1) + vite: 5.3.3(@types/node@20.14.10)(terser@5.31.1) transitivePeerDependencies: - supports-color @@ -9663,6 +9787,16 @@ snapshots: postcss: 8.4.38 postcss-value-parser: 4.2.0 + autoprefixer@10.4.19(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + caniuse-lite: 1.0.30001636 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.1 + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -10115,13 +10249,13 @@ snapshots: optionalDependencies: typescript: 5.5.3 - create-jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + create-jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -10146,14 +10280,18 @@ snapshots: dependencies: postcss: 8.4.38 + css-declaration-sorter@7.2.0(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + css-loader@6.11.0(webpack@5.92.1): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.39) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.39) + postcss-modules-scope: 3.2.0(postcss@8.4.39) + postcss-modules-values: 4.0.0(postcss@8.4.39) postcss-value-parser: 4.2.0 semver: 7.6.2 optionalDependencies: @@ -10162,9 +10300,9 @@ snapshots: css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.92.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 - cssnano: 6.1.2(postcss@8.4.38) + cssnano: 6.1.2(postcss@8.4.39) jest-worker: 29.7.0 - postcss: 8.4.38 + postcss: 8.4.39 schema-utils: 4.2.0 serialize-javascript: 6.0.2 webpack: 5.92.1 @@ -10210,16 +10348,16 @@ snapshots: cssesc@3.0.0: {} - cssnano-preset-advanced@6.1.2(postcss@8.4.38): + cssnano-preset-advanced@6.1.2(postcss@8.4.39): dependencies: - autoprefixer: 10.4.19(postcss@8.4.38) + autoprefixer: 10.4.19(postcss@8.4.39) browserslist: 4.23.1 - cssnano-preset-default: 6.1.2(postcss@8.4.38) - postcss: 8.4.38 - postcss-discard-unused: 6.0.5(postcss@8.4.38) - postcss-merge-idents: 6.0.3(postcss@8.4.38) - postcss-reduce-idents: 6.0.3(postcss@8.4.38) - postcss-zindex: 6.0.2(postcss@8.4.38) + cssnano-preset-default: 6.1.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-discard-unused: 6.0.5(postcss@8.4.39) + postcss-merge-idents: 6.0.3(postcss@8.4.39) + postcss-reduce-idents: 6.0.3(postcss@8.4.39) + postcss-zindex: 6.0.2(postcss@8.4.39) cssnano-preset-default@6.1.2(postcss@8.4.38): dependencies: @@ -10255,16 +10393,60 @@ snapshots: postcss-svgo: 6.0.3(postcss@8.4.38) postcss-unique-selectors: 6.0.4(postcss@8.4.38) + cssnano-preset-default@6.1.2(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + css-declaration-sorter: 7.2.0(postcss@8.4.39) + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-calc: 9.0.1(postcss@8.4.39) + postcss-colormin: 6.1.0(postcss@8.4.39) + postcss-convert-values: 6.1.0(postcss@8.4.39) + postcss-discard-comments: 6.0.2(postcss@8.4.39) + postcss-discard-duplicates: 6.0.3(postcss@8.4.39) + postcss-discard-empty: 6.0.3(postcss@8.4.39) + postcss-discard-overridden: 6.0.2(postcss@8.4.39) + postcss-merge-longhand: 6.0.5(postcss@8.4.39) + postcss-merge-rules: 6.1.1(postcss@8.4.39) + postcss-minify-font-values: 6.1.0(postcss@8.4.39) + postcss-minify-gradients: 6.0.3(postcss@8.4.39) + postcss-minify-params: 6.1.0(postcss@8.4.39) + postcss-minify-selectors: 6.0.4(postcss@8.4.39) + postcss-normalize-charset: 6.0.2(postcss@8.4.39) + postcss-normalize-display-values: 6.0.2(postcss@8.4.39) + postcss-normalize-positions: 6.0.2(postcss@8.4.39) + postcss-normalize-repeat-style: 6.0.2(postcss@8.4.39) + postcss-normalize-string: 6.0.2(postcss@8.4.39) + postcss-normalize-timing-functions: 6.0.2(postcss@8.4.39) + postcss-normalize-unicode: 6.1.0(postcss@8.4.39) + postcss-normalize-url: 6.0.2(postcss@8.4.39) + postcss-normalize-whitespace: 6.0.2(postcss@8.4.39) + postcss-ordered-values: 6.0.2(postcss@8.4.39) + postcss-reduce-initial: 6.1.0(postcss@8.4.39) + postcss-reduce-transforms: 6.0.2(postcss@8.4.39) + postcss-svgo: 6.0.3(postcss@8.4.39) + postcss-unique-selectors: 6.0.4(postcss@8.4.39) + cssnano-utils@4.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 + cssnano-utils@4.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + cssnano@6.1.2(postcss@8.4.38): dependencies: cssnano-preset-default: 6.1.2(postcss@8.4.38) lilconfig: 3.1.2 postcss: 8.4.38 + cssnano@6.1.2(postcss@8.4.39): + dependencies: + cssnano-preset-default: 6.1.2(postcss@8.4.39) + lilconfig: 3.1.2 + postcss: 8.4.39 + csso@5.0.5: dependencies: css-tree: 2.2.1 @@ -10428,9 +10610,9 @@ snapshots: dependencies: esutils: 2.0.3 - docusaurus-plugin-typedoc@1.0.1(typedoc-plugin-markdown@4.1.0(typedoc@0.26.3(typescript@5.5.3))): + docusaurus-plugin-typedoc@1.0.2(typedoc-plugin-markdown@4.1.2(typedoc@0.26.3(typescript@5.5.3))): dependencies: - typedoc-plugin-markdown: 4.1.0(typedoc@0.26.3(typescript@5.5.3)) + typedoc-plugin-markdown: 4.1.2(typedoc@0.26.3(typescript@5.5.3)) dom-accessibility-api@0.5.16: {} @@ -10676,13 +10858,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.5 enhanced-resolve: 5.17.0 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.14.0 @@ -10693,18 +10875,18 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.16.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -10714,7 +10896,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.14.0 is-glob: 4.0.3 @@ -10725,19 +10907,19 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.16.0(eslint@8.57.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@28.6.0(@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3): + eslint-plugin-jest@28.6.0(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3): dependencies: '@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + '@typescript-eslint/eslint-plugin': 7.15.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) transitivePeerDependencies: - supports-color - typescript @@ -11552,9 +11734,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.38): + icss-utils@5.1.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 identity-obj-proxy@3.0.0: dependencies: @@ -11854,7 +12036,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -11874,16 +12056,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest-cli@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + create-jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -11893,7 +12075,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest-config@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: '@babel/core': 7.24.7 '@jest/test-sequencer': 29.7.0 @@ -11918,8 +12100,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.9 - ts-node: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) + '@types/node': 20.14.10 + ts-node: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -11949,7 +12131,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -11963,7 +12145,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -11973,7 +12155,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.9 + '@types/node': 20.14.10 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -12012,7 +12194,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -12047,7 +12229,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -12075,7 +12257,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -12121,7 +12303,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -12140,7 +12322,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -12160,12 +12342,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-cli: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -13205,6 +13387,12 @@ snapshots: postcss-selector-parser: 6.1.0 postcss-value-parser: 4.2.0 + postcss-calc@9.0.1(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-selector-parser: 6.1.0 + postcss-value-parser: 4.2.0 + postcss-colormin@6.1.0(postcss@8.4.38): dependencies: browserslist: 4.23.1 @@ -13213,31 +13401,61 @@ snapshots: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-colormin@6.1.0(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-convert-values@6.1.0(postcss@8.4.38): dependencies: browserslist: 4.23.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-convert-values@6.1.0(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-discard-comments@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 + postcss-discard-comments@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-discard-duplicates@6.0.3(postcss@8.4.38): dependencies: postcss: 8.4.38 + postcss-discard-duplicates@6.0.3(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-discard-empty@6.0.3(postcss@8.4.38): dependencies: postcss: 8.4.38 + postcss-discard-empty@6.0.3(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-discard-overridden@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 - postcss-discard-unused@6.0.5(postcss@8.4.38): + postcss-discard-overridden@6.0.2(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 + + postcss-discard-unused@6.0.5(postcss@8.4.39): + dependencies: + postcss: 8.4.39 postcss-selector-parser: 6.1.0 postcss-loader@7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.92.1): @@ -13250,10 +13468,10 @@ snapshots: transitivePeerDependencies: - typescript - postcss-merge-idents@6.0.3(postcss@8.4.38): + postcss-merge-idents@6.0.3(postcss@8.4.39): dependencies: - cssnano-utils: 4.0.2(postcss@8.4.38) - postcss: 8.4.38 + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 postcss-value-parser: 4.2.0 postcss-merge-longhand@6.0.5(postcss@8.4.38): @@ -13262,6 +13480,12 @@ snapshots: postcss-value-parser: 4.2.0 stylehacks: 6.1.1(postcss@8.4.38) + postcss-merge-longhand@6.0.5(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + stylehacks: 6.1.1(postcss@8.4.39) + postcss-merge-rules@6.1.1(postcss@8.4.38): dependencies: browserslist: 4.23.1 @@ -13270,11 +13494,24 @@ snapshots: postcss: 8.4.38 postcss-selector-parser: 6.1.0 + postcss-merge-rules@6.1.1(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + caniuse-api: 3.0.0 + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-selector-parser: 6.1.0 + postcss-minify-font-values@6.1.0(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-minify-font-values@6.1.0(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-minify-gradients@6.0.3(postcss@8.4.38): dependencies: colord: 2.9.3 @@ -13282,6 +13519,13 @@ snapshots: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-minify-gradients@6.0.3(postcss@8.4.39): + dependencies: + colord: 2.9.3 + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-minify-params@6.1.0(postcss@8.4.38): dependencies: browserslist: 4.23.1 @@ -13289,86 +13533,149 @@ snapshots: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-minify-params@6.1.0(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-minify-selectors@6.0.4(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-selector-parser: 6.1.0 - postcss-modules-extract-imports@3.1.0(postcss@8.4.38): + postcss-minify-selectors@6.0.4(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 + postcss-selector-parser: 6.1.0 - postcss-modules-local-by-default@4.0.5(postcss@8.4.38): + postcss-modules-extract-imports@3.1.0(postcss@8.4.39): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 + postcss: 8.4.39 + + postcss-modules-local-by-default@4.0.5(postcss@8.4.39): + dependencies: + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 postcss-selector-parser: 6.1.0 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.38): + postcss-modules-scope@3.2.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 postcss-selector-parser: 6.1.0 - postcss-modules-values@4.0.0(postcss@8.4.38): + postcss-modules-values@4.0.0(postcss@8.4.39): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 postcss-normalize-charset@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 + postcss-normalize-charset@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-normalize-display-values@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-display-values@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-positions@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-positions@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-repeat-style@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-repeat-style@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-string@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-string@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-timing-functions@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-timing-functions@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-unicode@6.1.0(postcss@8.4.38): dependencies: browserslist: 4.23.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-unicode@6.1.0(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-url@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-url@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-normalize-whitespace@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-normalize-whitespace@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-ordered-values@6.0.2(postcss@8.4.38): dependencies: cssnano-utils: 4.0.2(postcss@8.4.38) postcss: 8.4.38 postcss-value-parser: 4.2.0 - postcss-reduce-idents@6.0.3(postcss@8.4.38): + postcss-ordered-values@6.0.2(postcss@8.4.39): dependencies: - postcss: 8.4.38 + cssnano-utils: 4.0.2(postcss@8.4.39) + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + + postcss-reduce-idents@6.0.3(postcss@8.4.39): + dependencies: + postcss: 8.4.39 postcss-value-parser: 4.2.0 postcss-reduce-initial@6.1.0(postcss@8.4.38): @@ -13377,19 +13684,30 @@ snapshots: caniuse-api: 3.0.0 postcss: 8.4.38 + postcss-reduce-initial@6.1.0(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + caniuse-api: 3.0.0 + postcss: 8.4.39 + postcss-reduce-transforms@6.0.2(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 + postcss-reduce-transforms@6.0.2(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + postcss-selector-parser@6.1.0: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-sort-media-queries@5.2.0(postcss@8.4.38): + postcss-sort-media-queries@5.2.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 sort-css-media-queries: 2.2.0 postcss-svgo@6.0.3(postcss@8.4.38): @@ -13398,16 +13716,27 @@ snapshots: postcss-value-parser: 4.2.0 svgo: 3.3.2 + postcss-svgo@6.0.3(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-value-parser: 4.2.0 + svgo: 3.3.2 + postcss-unique-selectors@6.0.4(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-selector-parser: 6.1.0 + postcss-unique-selectors@6.0.4(postcss@8.4.39): + dependencies: + postcss: 8.4.39 + postcss-selector-parser: 6.1.0 + postcss-value-parser@4.2.0: {} - postcss-zindex@6.0.2(postcss@8.4.38): + postcss-zindex@6.0.2(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 postcss@8.4.38: dependencies: @@ -13415,6 +13744,12 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 + postcss@8.4.39: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -13909,7 +14244,7 @@ snapshots: dependencies: escalade: 3.1.2 picocolors: 1.0.1 - postcss: 8.4.38 + postcss: 8.4.39 strip-json-comments: 3.1.1 run-parallel@1.2.0: @@ -14302,6 +14637,12 @@ snapshots: postcss: 8.4.38 postcss-selector-parser: 6.1.0 + stylehacks@6.1.1(postcss@8.4.39): + dependencies: + browserslist: 4.23.1 + postcss: 8.4.39 + postcss-selector-parser: 6.1.0 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -14404,11 +14745,11 @@ snapshots: dependencies: typescript: 5.5.3 - ts-jest@29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3): + ts-jest@29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -14422,14 +14763,14 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3): + ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 acorn: 8.12.0 acorn-walk: 8.3.3 arg: 4.1.3 @@ -14511,12 +14852,12 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typedoc-plugin-frontmatter@1.0.0(typedoc-plugin-markdown@4.1.0(typedoc@0.26.3(typescript@5.5.3))): + typedoc-plugin-frontmatter@1.0.0(typedoc-plugin-markdown@4.1.2(typedoc@0.26.3(typescript@5.5.3))): dependencies: - typedoc-plugin-markdown: 4.1.0(typedoc@0.26.3(typescript@5.5.3)) + typedoc-plugin-markdown: 4.1.2(typedoc@0.26.3(typescript@5.5.3)) yaml: 2.4.5 - typedoc-plugin-markdown@4.1.0(typedoc@0.26.3(typescript@5.5.3)): + typedoc-plugin-markdown@4.1.2(typedoc@0.26.3(typescript@5.5.3)): dependencies: typedoc: 0.26.3(typescript@5.5.3) @@ -14694,13 +15035,13 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite@5.3.1(@types/node@20.14.9)(terser@5.31.1): + vite@5.3.3(@types/node@20.14.10)(terser@5.31.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.38 + postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 fsevents: 2.3.3 terser: 5.31.1 diff --git a/scripts/build-css.sh b/scripts/build-css.sh new file mode 100755 index 0000000000..9cf40f8858 --- /dev/null +++ b/scripts/build-css.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Check if the correct number of arguments are provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 input_css_file output_css_file" + exit 1 +fi + +INPUT_FILE=$1 +OUTPUT_FILE=$2 + +# Check if the input file exists +if [ ! -f "$INPUT_FILE" ]; then + echo "Input file not found!" + exit 1 +fi + +# Read the input file, remove all occurrences of '.rdp-', and write to the output file +sed 's/\.rdp-/\./g' "$INPUT_FILE" > "$OUTPUT_FILE" diff --git a/src/DayPicker.test.tsx b/src/DayPicker.test.tsx index 4b55b1e35f..df83a9868d 100644 --- a/src/DayPicker.test.tsx +++ b/src/DayPicker.test.tsx @@ -1,10 +1,110 @@ import React from "react"; import { render, screen } from "@testing-library/react"; +import { startOfMonth } from "date-fns"; + +import { + activeElement, + dateButton, + grid, + nav, + previousButton +} from "@/test/elements"; +import { user } from "@/test/user"; import { DayPicker } from "./DayPicker"; +import { MonthProps } from "./components/Month"; +import { MonthsProps } from "./components/Months"; + +const testId = "test"; +const dayPicker = () => screen.getByTestId(testId); test("should render a date picker component", () => { - render(); - expect(screen.getByTestId("test")).toBeInTheDocument(); + render(); + expect(dayPicker()).toBeInTheDocument(); +}); + +it("should render the navigation and month grids", () => { + render(); + + expect(nav()).toBeInTheDocument(); + expect(grid()).toBeInTheDocument(); +}); + +it("should apply classnames and style according to props", () => { + render( + + ); + + expect(dayPicker()).toHaveClass("rdp-root"); + expect(dayPicker()).toHaveClass("custom-class"); + expect(dayPicker()).toHaveStyle({ color: "red" }); +}); + +it("should use custom components", () => { + render( +
Custom Navigation
, + Month: (props: MonthProps) =>
Custom Month
, + Months: (props: MonthsProps) => ( +
+ Custom Months
{props.children}
+
+ ), + Footer: () =>
Custom Footer
+ }} + footer="Footer" + /> + ); + + expect(dayPicker()).toHaveTextContent("Custom Navigation"); + expect(dayPicker()).toHaveTextContent("Custom Months"); + expect(dayPicker()).toHaveTextContent("Custom Month"); + expect(dayPicker()).toHaveTextContent("Custom Footer"); +}); + +describe("when the date picker is focused", () => { + test("focus the previous button", async () => { + render(); + await user.tab(); + expect(activeElement()).toBe(previousButton()); + }); + + test("on RTL, focus the previous button", async () => { + render(); + await user.tab(); + expect(activeElement()).toBe(previousButton()); + }); +}); + +describe("when the grid is focused", () => { + const today = new Date(); + + beforeAll(() => jest.setSystemTime(today)); + afterAll(() => jest.useRealTimers()); + + test("should focus the today's date", async () => { + render(); + await user.tab(); + await user.tab(); + await user.tab(); + expect(activeElement()).toBe(dateButton(today)); + }); + describe("when the today’s date is disabled", () => { + test("should focus the first day of the month", async () => { + render(); + await user.tab(); + await user.tab(); + await user.tab(); + expect(activeElement()).toBe(dateButton(startOfMonth(today))); + }); + }); }); diff --git a/src/DayPicker.tsx b/src/DayPicker.tsx index fd6ecc8d03..bf88b01515 100644 --- a/src/DayPicker.tsx +++ b/src/DayPicker.tsx @@ -1,8 +1,32 @@ -import React from "react"; +import React, { useCallback, useMemo } from "react"; +import type { + ChangeEventHandler, + MouseEvent, + FocusEvent, + KeyboardEvent +} from "react"; -import { Calendar } from "./components/Calendar.js"; -import { ContextProviders } from "./contexts/providers.js"; -import type { DayPickerProps } from "./types/index.js"; +import { UI, DayFlag, SelectionState } from "./UI.js"; +import type { CalendarDay } from "./classes/CalendarDay.js"; +import { getClassNamesForModifiers } from "./helpers/getClassNamesForModifiers.js"; +import { getComponents } from "./helpers/getComponents.js"; +import { getDataAttributes } from "./helpers/getDataAttributes.js"; +import { getDateLib } from "./helpers/getDateLib.js"; +import { getDefaultClassNames } from "./helpers/getDefaultClassNames.js"; +import { getDropdownMonths } from "./helpers/getDropdownMonths.js"; +import { getDropdownYears } from "./helpers/getDropdownYears.js"; +import { getFormatters } from "./helpers/getFormatters.js"; +import { getStyleForModifiers } from "./helpers/getStyleForModifiers.js"; +import { getWeekdays } from "./helpers/getWeekdays.js"; +import * as defaultLabels from "./labels/index.js"; +import { FormatOptions, LabelOptions } from "./lib/dateLib.js"; +import { UseRange } from "./selection/useRange.js"; +import type { DayPickerProps, Modifiers } from "./types/index.js"; +import { useCalendar } from "./useCalendar.js"; +import { dayPickerContext } from "./useDayPicker.js"; +import { useFocus } from "./useFocus.js"; +import { useModifiers } from "./useModifiers.js"; +import { useSelection } from "./useSelection.js"; /** * Render the date picker calendar. @@ -11,9 +35,608 @@ import type { DayPickerProps } from "./types/index.js"; * @see http://daypicker.dev */ export function DayPicker(props: DayPickerProps) { + const reactId = React.useId(); + const id = props.id ?? reactId; + + const { components, formatters, labels, dateLib, classNames } = useMemo( + () => ({ + dateLib: getDateLib(props.dateLib), + components: getComponents(props.components), + formatters: getFormatters(props.formatters), + labels: { ...defaultLabels, ...props.labels }, + classNames: { ...getDefaultClassNames(), ...props.classNames } + }), + [ + props.classNames, + props.components, + props.dateLib, + props.formatters, + props.labels + ] + ); + + const numberOfMonths = props.numberOfMonths ?? 1; + + const calendar = useCalendar(props, dateLib); + + const modifiers = useModifiers(props, calendar, dateLib); + const selection = useSelection(props, dateLib); + const focus = useFocus(props, calendar, modifiers, selection, dateLib); + + const { previousMonth, nextMonth, goToPreviousMonth, goToNextMonth } = + calendar; + const { isSelected, handleSelect } = selection; + const { + isFocusTarget, + focused: focusedDay, + setFocused, + blur, + focusDayBefore, + focusDayAfter, + focusWeekBefore, + focusWeekAfter, + focusMonthBefore, + focusMonthAfter, + focusYearBefore, + focusYearAfter, + focusStartOfWeek, + focusEndOfWeek + } = focus; + + const { + captionLayout, + dir, + locale, + ISOWeek, + mode, + modifiersClassNames, + modifiersStyles, + onDayBlur, + onDayClick, + onDayFocus, + onDayKeyDown, + onPrevClick, + onNextClick, + showWeekNumber, + styles, + weekStartsOn, + firstWeekContainsDate, + useAdditionalWeekYearTokens, + useAdditionalDayOfYearTokens + } = props; + + const { + formatCaption, + formatDay, + formatMonthDropdown, + formatWeekNumber, + formatWeekNumberHeader, + formatWeekdayName, + formatYearDropdown + } = formatters; + + const { + labelDayButton, + labelGridcell, + labelGrid, + labelMonthDropdown, + labelNav, + labelNext, + labelPrevious, + labelWeekday, + labelWeekNumber, + labelWeekNumberHeader, + labelYearDropdown + } = labels; + + const weekdays = useMemo( + () => getWeekdays(locale, weekStartsOn, ISOWeek, dateLib), + [ISOWeek, dateLib, locale, weekStartsOn] + ); + + const isInteractive = mode !== undefined || onDayClick !== undefined; + + const handlePreviousClick = useCallback(() => { + if (!previousMonth) return; + goToPreviousMonth(); + onPrevClick?.(previousMonth); + }, [goToPreviousMonth, onPrevClick, previousMonth]); + + const handleNextClick = useCallback(() => { + if (!nextMonth) return; + goToNextMonth(); + onNextClick?.(nextMonth); + }, [goToNextMonth, nextMonth, onNextClick]); + + const handleDayClick = useCallback( + (day: CalendarDay, m: Modifiers) => { + return (e: MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + handleSelect(day.date, m, e); + setFocused(day); + onDayClick?.(day.date, m, e); + }; + }, + [handleSelect, onDayClick, setFocused] + ); + + const handleDayFocus = useCallback( + (day: CalendarDay, m: Modifiers) => { + return (e: FocusEvent) => { + setFocused(day); + onDayFocus?.(day.date, m, e); + }; + }, + [onDayFocus, setFocused] + ); + + const handleDayBlur = useCallback( + (day: CalendarDay, m: Modifiers) => { + return (e: FocusEvent) => { + blur(); + onDayBlur?.(day.date, m, e); + }; + }, + [blur, onDayBlur] + ); + + const handleDayKeyDown = useCallback( + (day: CalendarDay, modifiers: Modifiers) => { + return (e: KeyboardEvent) => { + switch (e.key) { + case "ArrowLeft": + e.preventDefault(); + e.stopPropagation(); + dir === "rtl" ? focusDayAfter() : focusDayBefore(); + break; + case "ArrowRight": + e.preventDefault(); + e.stopPropagation(); + dir === "rtl" ? focusDayBefore() : focusDayAfter(); + break; + case "ArrowDown": + e.preventDefault(); + e.stopPropagation(); + focusWeekAfter(); + break; + case "ArrowUp": + e.preventDefault(); + e.stopPropagation(); + focusWeekBefore(); + break; + case " ": + case "Enter": + e.preventDefault(); + e.stopPropagation(); + selection?.handleSelect(day.date, modifiers, e); + break; + case "PageUp": + e.preventDefault(); + e.stopPropagation(); + e.shiftKey ? focusYearBefore() : focusMonthBefore(); + break; + case "PageDown": + e.preventDefault(); + e.stopPropagation(); + e.shiftKey ? focusYearAfter() : focusMonthAfter(); + break; + case "Home": + e.preventDefault(); + e.stopPropagation(); + focusStartOfWeek(); + break; + case "End": + e.preventDefault(); + e.stopPropagation(); + focusEndOfWeek(); + break; + } + onDayKeyDown?.(day.date, modifiers, e); + }; + }, + [ + dir, + focusDayAfter, + focusDayBefore, + focusEndOfWeek, + focusMonthAfter, + focusMonthBefore, + focusStartOfWeek, + focusWeekAfter, + focusWeekBefore, + focusYearAfter, + focusYearBefore, + onDayKeyDown, + selection + ] + ); + + const formatOptions: FormatOptions = { + locale, + weekStartsOn, + firstWeekContainsDate, + useAdditionalWeekYearTokens, + useAdditionalDayOfYearTokens + }; + + const labelOptions: LabelOptions = formatOptions; + + const { className, style } = useMemo( + () => ({ + className: [classNames[UI.Root], props.className] + .filter(Boolean) + .join(" "), + style: { ...styles?.[UI.Root], ...props.style } + }), + [classNames, props.className, props.style, styles] + ); + + const dataAttributes = useMemo(() => getDataAttributes(props), [props]); return ( - - - + + 1 || undefined} + data-week-numbers={showWeekNumber || undefined} + {...dataAttributes} + > + + {!props.hideNavigation && ( + + + + + + + + + )} + {calendar.months.map((calendarMonth, displayIndex) => { + const captionId = `${id}-caption-${displayIndex}`; + + const handleMonthChange: ChangeEventHandler = ( + e + ) => { + const selectedMonth = Number( + (e.target as HTMLSelectElement).value + ); + const month = dateLib.setMonth( + dateLib.startOfMonth(calendarMonth.date), + selectedMonth + ); + calendar.goToMonth(month); + }; + + const handleYearChange: ChangeEventHandler = ( + e + ) => { + const month = dateLib.setYear( + dateLib.startOfMonth(calendarMonth.date), + Number(e.target.value) + ); + calendar.goToMonth(month); + }; + + const dropdownMonths = getDropdownMonths( + calendarMonth.date, + calendar.navigationStartMonth, + calendar.navigationEndMonth, + formatters, + locale, + dateLib + ); + const dropdownYears = getDropdownYears( + calendar.months[0].date, + calendar.navigationStartMonth, + calendar.navigationEndMonth, + formatters, + dateLib + ); + + return ( + + + {captionLayout?.startsWith("dropdown") ? ( + + {captionLayout === "dropdown" || + captionLayout === "dropdown-months" ? ( + + ) : ( + + {formatMonthDropdown(calendarMonth.date.getMonth())} + + )} + {captionLayout === "dropdown" || + captionLayout === "dropdown-years" ? ( + + ) : ( + + {formatYearDropdown(calendarMonth.date.getFullYear())} + + )} + + ) : ( + + {formatCaption( + calendarMonth.date, + formatOptions, + dateLib + )} + + )} + + + + + {calendarMonth.weeks.map((week, weekIndex) => { + return ( + + {showWeekNumber && ( + + {formatWeekNumber(week.weekNumber)} + + )} + {week.days.map((day: CalendarDay) => { + const { date } = day; + const dayModifiers = modifiers.getModifiers(day); + const focused = focusedDay?.isEqualTo(day); + + if (!dayModifiers.hidden && focused) + dayModifiers[DayFlag.focused] = true; + + const selected = isSelected(date); + + dayModifiers[SelectionState.selected] = + !dayModifiers.disabled && selected; + + if (!dayModifiers.disabled && mode === "range") { + const range = selection as UseRange; + dayModifiers[SelectionState.range_start] = + range.isRangeStart(date); + dayModifiers[SelectionState.range_end] = + range.isRangeEnd(date); + dayModifiers[SelectionState.range_middle] = + range.isRangeMiddle(date); + } + + const style = { + ...getStyleForModifiers( + dayModifiers, + modifiersStyles + ), + ...styles?.[UI.Day] + }; + + const className = [ + classNames[UI.Day], + ...getClassNamesForModifiers( + dayModifiers, + classNames, + modifiersClassNames + ) + ]; + + const ariaLabel = !isInteractive + ? labelGridcell( + date, + dayModifiers, + labelOptions, + dateLib + ) + : undefined; + + const dataAttributes = { + "data-day": dateLib.format(date, "yyyy-MM-dd"), + "data-month": day.outside + ? dateLib.format(date, "yyyy-MM") + : undefined + }; + return ( + + {isInteractive ? ( + + {formatDay(date, formatOptions, dateLib)} + + ) : ( + formatDay(day.date, formatOptions, dateLib) + )} + + ); + })} + + ); + })} + + + + ); + })} + + {props.footer && ( + + {props.footer} + + )} + + ); } diff --git a/src/UI.ts b/src/UI.ts index eabddd2dbe..27ebd4875b 100644 --- a/src/UI.ts +++ b/src/UI.ts @@ -10,13 +10,10 @@ import type { CustomComponents, ClassNames, Styles } from "./types/index.js"; export enum UI { /** The previous button in the navigation. */ ButtonPrevious = "button_previous", - /** The next button the navigation */ + /** The next button the navigation. */ ButtonNext = "button_next", - /** - * The calendar element: the root component displaying the months and the - * navigation bar. Extended by {@link CalendarFlag}. - */ - Calendar = "calendar", + /** The root component displaying the months and the navigation bar. */ + Root = "root", /** The Chevron SVG element used by navigation buttons and dropdowns. */ Chevron = "chevron", /** @@ -24,8 +21,8 @@ export enum UI { * {@link SelectionFlag}. */ Day = "day", - /** The element containing the formatted day's date, inside the grid cell. */ - DayDate = "day_date", + /** The button containing the formatted day's date, inside the grid cell. */ + DayButton = "day_button", /** The caption label of the month (when not showing the dropdown navigation). */ CaptionLabel = "caption_label", /** The container of the dropdown navigation (when enabled). */ @@ -37,16 +34,16 @@ export enum UI { /** The root element of the footer. */ Footer = "footer", /** The month grid. */ - Month = "month", + MonthGrid = "month_grid", /** Contains the dropdown navigation or the caption label. */ MonthCaption = "month_caption", /** The dropdown with the months. */ MonthsDropdown = "months_dropdown", - /** Wrapper of the {@link} grid. */ - MonthWrapper = "month_wrapper", + /** Wrapper of the month grid. */ + Month = "month", /** The container of the displayed months. */ Months = "months", - /** The navigation bar with the previous and next buttons */ + /** The navigation bar with the previous and next buttons. */ Nav = "nav", /** The row containing the week. */ Week = "week", @@ -56,25 +53,22 @@ export enum UI { Weekday = "weekday", /** The row grouping the weekdays in the column headers. */ Weekdays = "weekdays", - /** - * The row header containing the week number. Extended by - * {@link WeekNumberFlag}. - */ + /** The row header containing the week number. */ WeekNumber = "week_number", + /** The row header containing the week number. */ + WeekNumberHeader = "week_number_header", /** The dropdown with the years. */ YearsDropdown = "years_dropdown" } /** The flags for the {@link UI.Day}. */ export enum DayFlag { - /** The day is disabled */ + /** The day is disabled. */ disabled = "disabled", - /** The day is hidden */ + /** The day is hidden. */ hidden = "hidden", - /** The day is outside the current month */ + /** The day is outside the current month. */ outside = "outside", - /** The day is focusable. */ - focusable = "focusable", /** The day is focused. */ focused = "focused", /** The day is today. */ @@ -95,28 +89,3 @@ export enum SelectionState { /** The day is selected. */ selected = "selected" } - -/** Flags that can be applied to the {@link UI.Calendar} element. */ -export enum CalendarFlag { - /** Assigned when the week numbers are show. */ - has_week_numbers = "has_week_numbers", - /** Assigned when the weekdays are hidden. */ - no_weekdays = "no_weekdays", - /** Assigned when the calendar has multiple months. */ - has_multiple_months = "has_multiple_months" -} - -/** Flags that can be applied to the {@link UI.Chevron} element. */ -export enum ChevronFlag { - /** Assigned when the week numbers are show. */ - disabled = "chevron_disabled" -} - -/** Flags that can be applied to the {@link UI.WeekNumber} element. */ -export enum WeekNumberFlag { - /** - * Assigned when the week number is interactive, i.e. has an - * `onWeekNumberClick` event attached to it. - */ - week_number_interactive = "week_number_interactive" -} diff --git a/src/classes/CalendarDay.ts b/src/classes/CalendarDay.ts index 7a4ba57910..d889d46c6f 100644 --- a/src/classes/CalendarDay.ts +++ b/src/classes/CalendarDay.ts @@ -20,9 +20,17 @@ export class CalendarDay { displayMonth && !dateLib.isSameMonth(date, displayMonth) ); this.dateLib = dateLib; + const { format } = dateLib; + this.uid = + format(date, "yyyyMMdd") + + (this.outside ? `-` + format(displayMonth, "yyyyMMdd") : ""); } - /** The utility functions to manipulate dates. */ + /** + * The utility functions to manipulate dates. + * + * @private + */ readonly dateLib: DateLib; /** @@ -45,6 +53,9 @@ export class CalendarDay { /** The date represented by this day. */ readonly date: Date; + /** A unique identifier for the day. */ + readonly uid: string; + /** * Check if the day is the same as the given day: considering if it is in the * same display month. diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 05ca2e41d1..0a9707f6c0 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,4 +1,4 @@ -import React, { type ButtonHTMLAttributes } from "react"; +import React from "react"; /** * Render the button elements in the calendar. @@ -6,9 +6,9 @@ import React, { type ButtonHTMLAttributes } from "react"; * Use the `components` prop to swap this component with a custom one. * * @group Components - * @see https://daypicker.dev/advanced-guides/custom-components + * @see https://daypicker.dev/next/guides/custom-components */ -export function Button(props: ButtonHTMLAttributes) { +export function Button(props: JSX.IntrinsicElements["button"]) { return