react-day-picker 9.6.2 → 9.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/DayPicker.js +14 -2
- package/dist/cjs/DayPicker.js.map +1 -1
- package/dist/cjs/classes/DateLib.js +4 -4
- package/dist/cjs/classes/DateLib.js.map +1 -1
- package/dist/esm/DayPicker.js +14 -2
- package/dist/esm/DayPicker.js.map +1 -1
- package/dist/esm/classes/DateLib.js +1 -1
- package/dist/esm/classes/DateLib.js.map +1 -1
- package/package.json +2 -4
- package/src/.eslintignore +1 -0
- package/src/.eslintrc.cjs +27 -0
- package/src/DayPicker.test.tsx +199 -0
- package/src/DayPicker.tsx +629 -0
- package/src/UI.ts +365 -0
- package/src/classes/CalendarDay.test.ts +17 -0
- package/src/classes/CalendarDay.ts +61 -0
- package/src/classes/CalendarMonth.test.ts +28 -0
- package/src/classes/CalendarMonth.ts +15 -0
- package/src/classes/CalendarWeek.test.ts +21 -0
- package/src/classes/CalendarWeek.ts +13 -0
- package/src/classes/DateLib.ts +615 -0
- package/src/classes/index.ts +4 -0
- package/src/components/Button.tsx +13 -0
- package/src/components/CaptionLabel.tsx +13 -0
- package/src/components/Chevron.tsx +42 -0
- package/src/components/Day.tsx +28 -0
- package/src/components/DayButton.tsx +29 -0
- package/src/components/Dropdown.tsx +71 -0
- package/src/components/DropdownNav.tsx +13 -0
- package/src/components/Footer.tsx +13 -0
- package/src/components/Month.tsx +24 -0
- package/src/components/MonthCaption.tsx +23 -0
- package/src/components/MonthGrid.tsx +13 -0
- package/src/components/Months.tsx +13 -0
- package/src/components/MonthsDropdown.tsx +16 -0
- package/src/components/Nav.tsx +90 -0
- package/src/components/NextMonthButton.tsx +18 -0
- package/src/components/Option.tsx +13 -0
- package/src/components/PreviousMonthButton.tsx +20 -0
- package/src/components/Root.tsx +19 -0
- package/src/components/Select.tsx +13 -0
- package/src/components/Week.tsx +20 -0
- package/src/components/WeekNumber.tsx +21 -0
- package/src/components/WeekNumberHeader.tsx +15 -0
- package/src/components/Weekday.tsx +13 -0
- package/src/components/Weekdays.tsx +17 -0
- package/src/components/Weeks.tsx +13 -0
- package/src/components/YearsDropdown.tsx +16 -0
- package/src/components/custom-components.tsx +26 -0
- package/src/formatters/formatCaption.test.ts +27 -0
- package/src/formatters/formatCaption.ts +23 -0
- package/src/formatters/formatDay.test.ts +7 -0
- package/src/formatters/formatDay.ts +16 -0
- package/src/formatters/formatMonthDropdown.test.ts +19 -0
- package/src/formatters/formatMonthDropdown.ts +15 -0
- package/src/formatters/formatWeekNumber.test.ts +5 -0
- package/src/formatters/formatWeekNumber.ts +13 -0
- package/src/formatters/formatWeekNumberHeader.ts +10 -0
- package/src/formatters/formatWeekdayName.test.ts +15 -0
- package/src/formatters/formatWeekdayName.ts +16 -0
- package/src/formatters/formatYearDropdown.test.ts +7 -0
- package/src/formatters/formatYearDropdown.ts +21 -0
- package/src/formatters/index.ts +7 -0
- package/src/helpers/broadcastCalendar.test.ts +43 -0
- package/src/helpers/calculateFocusTarget.ts +51 -0
- package/src/helpers/endOfBroadcastWeek.test.ts +25 -0
- package/src/helpers/endOfBroadcastWeek.ts +16 -0
- package/src/helpers/getBroadcastWeeksInMonth.test.ts +23 -0
- package/src/helpers/getBroadcastWeeksInMonth.ts +31 -0
- package/src/helpers/getClassNamesForModifiers.ts +26 -0
- package/src/helpers/getComponents.ts +11 -0
- package/src/helpers/getDataAttributes.test.tsx +48 -0
- package/src/helpers/getDataAttributes.tsx +21 -0
- package/src/helpers/getDates.test.ts +190 -0
- package/src/helpers/getDates.ts +64 -0
- package/src/helpers/getDays.test.ts +30 -0
- package/src/helpers/getDays.ts +16 -0
- package/src/helpers/getDefaultClassNames.test.ts +47 -0
- package/src/helpers/getDefaultClassNames.ts +33 -0
- package/src/helpers/getDisplayMonths.test.ts +44 -0
- package/src/helpers/getDisplayMonths.ts +20 -0
- package/src/helpers/getFocusableDate.ts +59 -0
- package/src/helpers/getFormatters.test.ts +48 -0
- package/src/helpers/getFormatters.ts +19 -0
- package/src/helpers/getInitialMonth.test.ts +79 -0
- package/src/helpers/getInitialMonth.ts +41 -0
- package/src/helpers/getLabels.ts +10 -0
- package/src/helpers/getMonthOptions.test.ts +226 -0
- package/src/helpers/getMonthOptions.ts +37 -0
- package/src/helpers/getMonths.test.ts +88 -0
- package/src/helpers/getMonths.ts +90 -0
- package/src/helpers/getNavMonth.test.ts +253 -0
- package/src/helpers/getNavMonth.ts +70 -0
- package/src/helpers/getNextFocus.test.tsx +99 -0
- package/src/helpers/getNextFocus.tsx +67 -0
- package/src/helpers/getNextMonth.test.ts +101 -0
- package/src/helpers/getNextMonth.ts +45 -0
- package/src/helpers/getPossibleFocusDate.test.ts +144 -0
- package/src/helpers/getPreviousMonth.test.ts +77 -0
- package/src/helpers/getPreviousMonth.ts +40 -0
- package/src/helpers/getStyleForModifiers.test.ts +92 -0
- package/src/helpers/getStyleForModifiers.ts +21 -0
- package/src/helpers/getWeekdays.test.ts +44 -0
- package/src/helpers/getWeekdays.ts +29 -0
- package/src/helpers/getWeeks.test.ts +30 -0
- package/src/helpers/getWeeks.ts +9 -0
- package/src/helpers/getYearOptions.test.ts +46 -0
- package/src/helpers/getYearOptions.ts +34 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/startOfBroadcastWeek.test.ts +24 -0
- package/src/helpers/startOfBroadcastWeek.ts +19 -0
- package/src/helpers/useControlledValue.test.ts +45 -0
- package/src/helpers/useControlledValue.ts +33 -0
- package/src/index.ts +15 -0
- package/src/jalali.tsx +2 -0
- package/src/labels/index.ts +12 -0
- package/src/labels/labelDayButton.test.ts +41 -0
- package/src/labels/labelDayButton.ts +31 -0
- package/src/labels/labelGrid.test.ts +7 -0
- package/src/labels/labelGrid.ts +23 -0
- package/src/labels/labelGridcell.test.ts +7 -0
- package/src/labels/labelGridcell.ts +22 -0
- package/src/labels/labelMonthDropdown.test.ts +5 -0
- package/src/labels/labelMonthDropdown.ts +12 -0
- package/src/labels/labelNav.test.ts +5 -0
- package/src/labels/labelNav.ts +10 -0
- package/src/labels/labelNext.test.ts +5 -0
- package/src/labels/labelNext.ts +13 -0
- package/src/labels/labelPrevious.test.ts +5 -0
- package/src/labels/labelPrevious.ts +13 -0
- package/src/labels/labelWeekNumber.test.ts +5 -0
- package/src/labels/labelWeekNumber.ts +15 -0
- package/src/labels/labelWeekNumberHeader.test.ts +5 -0
- package/src/labels/labelWeekNumberHeader.ts +12 -0
- package/src/labels/labelWeekday.test.ts +15 -0
- package/src/labels/labelWeekday.ts +16 -0
- package/src/labels/labelYearDropdown.test.ts +5 -0
- package/src/labels/labelYearDropdown.ts +12 -0
- package/src/locale.ts +1 -0
- package/src/persian.tsx +86 -0
- package/src/selection/useMulti.test.tsx +41 -0
- package/src/selection/useMulti.tsx +74 -0
- package/src/selection/useRange.test.tsx +154 -0
- package/src/selection/useRange.tsx +73 -0
- package/src/selection/useSingle.test.tsx +38 -0
- package/src/selection/useSingle.tsx +69 -0
- package/src/types/deprecated.ts +230 -0
- package/src/types/index.ts +4 -0
- package/src/types/props.test.tsx +71 -0
- package/src/types/props.ts +675 -0
- package/src/types/selection.ts +57 -0
- package/src/types/shared.ts +442 -0
- package/src/useAnimation.test.tsx +134 -0
- package/src/useAnimation.ts +203 -0
- package/src/useCalendar.ts +178 -0
- package/src/useDayPicker.test.tsx +142 -0
- package/src/useDayPicker.ts +93 -0
- package/src/useFocus.ts +87 -0
- package/src/useGetModifiers.test.tsx +154 -0
- package/src/useGetModifiers.tsx +122 -0
- package/src/useSelection.ts +26 -0
- package/src/utc.tsx +10 -0
- package/src/utils/addToRange.test.ts +117 -0
- package/src/utils/addToRange.ts +87 -0
- package/src/utils/dateMatchModifiers.test.ts +120 -0
- package/src/utils/dateMatchModifiers.ts +88 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/rangeContainsDayOfWeek.test.ts +48 -0
- package/src/utils/rangeContainsDayOfWeek.ts +35 -0
- package/src/utils/rangeContainsModifiers.test.ts +230 -0
- package/src/utils/rangeContainsModifiers.ts +125 -0
- package/src/utils/rangeIncludesDate.test.ts +46 -0
- package/src/utils/rangeIncludesDate.ts +43 -0
- package/src/utils/rangeOverlaps.test.ts +60 -0
- package/src/utils/rangeOverlaps.ts +22 -0
- package/src/utils/typeguards.test.ts +83 -0
- package/src/utils/typeguards.ts +70 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DateLib } from "../classes/DateLib.js";
|
|
2
|
+
import { DropdownOption } from "../components/Dropdown.js";
|
|
3
|
+
import type { Formatters } from "../types/index.js";
|
|
4
|
+
|
|
5
|
+
/** Return the years to show in the dropdown. */
|
|
6
|
+
export function getYearOptions(
|
|
7
|
+
navStart: Date | undefined,
|
|
8
|
+
navEnd: Date | undefined,
|
|
9
|
+
formatters: Pick<Formatters, "formatYearDropdown">,
|
|
10
|
+
dateLib: DateLib
|
|
11
|
+
): DropdownOption[] | undefined {
|
|
12
|
+
if (!navStart) return undefined;
|
|
13
|
+
if (!navEnd) return undefined;
|
|
14
|
+
const { startOfYear, endOfYear, addYears, getYear, isBefore, isSameYear } =
|
|
15
|
+
dateLib;
|
|
16
|
+
const firstNavYear = startOfYear(navStart);
|
|
17
|
+
const lastNavYear = endOfYear(navEnd);
|
|
18
|
+
const years: Date[] = [];
|
|
19
|
+
|
|
20
|
+
let year = firstNavYear;
|
|
21
|
+
while (isBefore(year, lastNavYear) || isSameYear(year, lastNavYear)) {
|
|
22
|
+
years.push(year);
|
|
23
|
+
year = addYears(year, 1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return years.map((year) => {
|
|
27
|
+
const label = formatters.formatYearDropdown(year, dateLib);
|
|
28
|
+
return {
|
|
29
|
+
value: getYear(year),
|
|
30
|
+
label,
|
|
31
|
+
disabled: false
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defaultDateLib } from "../classes";
|
|
2
|
+
|
|
3
|
+
import { startOfBroadcastWeek } from "./startOfBroadcastWeek";
|
|
4
|
+
|
|
5
|
+
describe("startOfBroadcastWeek", () => {
|
|
6
|
+
test.each([
|
|
7
|
+
[new Date(2023, 0, 1), new Date(2022, 11, 26)], // January, Sunday
|
|
8
|
+
[new Date(2023, 1, 1), new Date(2023, 0, 30)], // February, Wednesday
|
|
9
|
+
[new Date(2023, 2, 1), new Date(2023, 1, 27)], // March, Wednesday
|
|
10
|
+
[new Date(2023, 3, 1), new Date(2023, 2, 27)], // April, Saturday
|
|
11
|
+
[new Date(2023, 4, 1), new Date(2023, 4, 1)], // May, Monday
|
|
12
|
+
[new Date(2023, 5, 1), new Date(2023, 4, 29)], // June, Thursday
|
|
13
|
+
[new Date(2023, 6, 1), new Date(2023, 5, 26)], // July, Saturday
|
|
14
|
+
[new Date(2023, 7, 1), new Date(2023, 6, 31)], // August, Tuesday
|
|
15
|
+
[new Date(2023, 8, 1), new Date(2023, 7, 28)], // September, Friday
|
|
16
|
+
[new Date(2023, 9, 1), new Date(2023, 8, 25)], // October, Sunday
|
|
17
|
+
[new Date(2023, 10, 1), new Date(2023, 9, 30)], // November, Wednesday
|
|
18
|
+
[new Date(2023, 11, 1), new Date(2023, 10, 27)] // December, Friday
|
|
19
|
+
])("startOfBroadcastWeek(%s) should return %s", (inputDate, expectedDate) => {
|
|
20
|
+
expect(startOfBroadcastWeek(inputDate, defaultDateLib)).toEqual(
|
|
21
|
+
expectedDate
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DateLib } from "../classes/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return the start date of the week in the broadcast calendar.
|
|
5
|
+
*
|
|
6
|
+
* @since 9.4.0
|
|
7
|
+
*/
|
|
8
|
+
export function startOfBroadcastWeek(date: Date, dateLib: DateLib): Date {
|
|
9
|
+
const firstOfMonth = dateLib.startOfMonth(date);
|
|
10
|
+
const dayOfWeek = firstOfMonth.getDay();
|
|
11
|
+
|
|
12
|
+
if (dayOfWeek === 1) {
|
|
13
|
+
return firstOfMonth;
|
|
14
|
+
} else if (dayOfWeek === 0) {
|
|
15
|
+
return dateLib.addDays(firstOfMonth, -1 * 6);
|
|
16
|
+
} else {
|
|
17
|
+
return dateLib.addDays(firstOfMonth, -1 * (dayOfWeek - 1));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { act, renderHook } from "@testing-library/react";
|
|
2
|
+
|
|
3
|
+
import { useControlledValue } from "./useControlledValue";
|
|
4
|
+
|
|
5
|
+
describe("when the value is controlled", () => {
|
|
6
|
+
const defaultValue: string | undefined = "foo"; // not controlled
|
|
7
|
+
const controlledValue: string | undefined = "bar"; // now controlled
|
|
8
|
+
test("should return the controlled value", () => {
|
|
9
|
+
const { result } = renderHook(() =>
|
|
10
|
+
useControlledValue<string>(defaultValue, controlledValue)
|
|
11
|
+
);
|
|
12
|
+
expect(result.current[0]).toBe(controlledValue);
|
|
13
|
+
});
|
|
14
|
+
describe("when setting a new value", () => {
|
|
15
|
+
const newValue = "taz";
|
|
16
|
+
test("should return the controlled value instead", async () => {
|
|
17
|
+
const { result } = renderHook(() =>
|
|
18
|
+
useControlledValue<string>(defaultValue, controlledValue)
|
|
19
|
+
);
|
|
20
|
+
act(() => result.current[1](newValue));
|
|
21
|
+
expect(result.current[0]).toBe(controlledValue);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("when the value is not controlled", () => {
|
|
27
|
+
const defaultValue = "foo";
|
|
28
|
+
const controlledValue = undefined;
|
|
29
|
+
test("should return the value", () => {
|
|
30
|
+
const { result } = renderHook(() =>
|
|
31
|
+
useControlledValue<string>(defaultValue, controlledValue)
|
|
32
|
+
);
|
|
33
|
+
expect(result.current[0]).toBe(defaultValue);
|
|
34
|
+
});
|
|
35
|
+
describe("when setting a new value", () => {
|
|
36
|
+
const newValue = "bar";
|
|
37
|
+
test("should return the new value", async () => {
|
|
38
|
+
const { result } = renderHook(() =>
|
|
39
|
+
useControlledValue<string>(defaultValue, controlledValue)
|
|
40
|
+
);
|
|
41
|
+
act(() => result.current[1](newValue));
|
|
42
|
+
expect(result.current[0]).toBe(newValue);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export type DispatchStateAction<T> = React.Dispatch<React.SetStateAction<T>>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A custom hook for managing both controlled and uncontrolled component states.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Uncontrolled usage
|
|
10
|
+
* const [value, setValue] = useControlledValue(0, undefined);
|
|
11
|
+
*
|
|
12
|
+
* // Controlled usage
|
|
13
|
+
* const [value, setValue] = useControlledValue(0, props.value);
|
|
14
|
+
*
|
|
15
|
+
* @template T - The type of the value.
|
|
16
|
+
* @param {T} defaultValue - The initial value for the uncontrolled state.
|
|
17
|
+
* @param {T | undefined} controlledValue - The value for the controlled state.
|
|
18
|
+
* If undefined, the component will use the uncontrolled state.
|
|
19
|
+
* @returns {[T, DispatchStateAction<T>]} - Returns a tuple where the first
|
|
20
|
+
* element is the current value (either controlled or uncontrolled) and the
|
|
21
|
+
* second element is a setter function to update the value.
|
|
22
|
+
*/
|
|
23
|
+
export function useControlledValue<T>(
|
|
24
|
+
defaultValue: T,
|
|
25
|
+
controlledValue: T | undefined
|
|
26
|
+
): [T, DispatchStateAction<T>] {
|
|
27
|
+
const [uncontrolledValue, setValue] = useState(defaultValue);
|
|
28
|
+
|
|
29
|
+
const value =
|
|
30
|
+
controlledValue === undefined ? uncontrolledValue : controlledValue;
|
|
31
|
+
|
|
32
|
+
return [value, setValue] as [T, DispatchStateAction<T>];
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./DayPicker.js";
|
|
2
|
+
export * from "./types/index.js";
|
|
3
|
+
|
|
4
|
+
export * from "./classes/index.js";
|
|
5
|
+
export * from "./components/custom-components.js";
|
|
6
|
+
|
|
7
|
+
export * from "./formatters/index.js";
|
|
8
|
+
export * from "./helpers/index.js";
|
|
9
|
+
export * from "./labels/index.js";
|
|
10
|
+
export * from "./utils/index.js";
|
|
11
|
+
export * from "./UI.js";
|
|
12
|
+
|
|
13
|
+
export * from "./useDayPicker.js";
|
|
14
|
+
|
|
15
|
+
export { TZDate } from "@date-fns/tz";
|
package/src/jalali.tsx
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./labelGrid.js";
|
|
2
|
+
export * from "./labelGridcell.js";
|
|
3
|
+
export * from "./labelDayButton.js";
|
|
4
|
+
export * from "./labelNav.js";
|
|
5
|
+
export * from "./labelGrid.js";
|
|
6
|
+
export * from "./labelMonthDropdown.js";
|
|
7
|
+
export * from "./labelNext.js";
|
|
8
|
+
export * from "./labelPrevious.js";
|
|
9
|
+
export * from "./labelWeekday.js";
|
|
10
|
+
export * from "./labelWeekNumber.js";
|
|
11
|
+
export * from "./labelWeekNumberHeader.js";
|
|
12
|
+
export * from "./labelYearDropdown.js";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { es } from "date-fns/locale/es";
|
|
2
|
+
|
|
3
|
+
import type { Modifiers } from "../types";
|
|
4
|
+
|
|
5
|
+
import { labelDayButton } from "./labelDayButton";
|
|
6
|
+
|
|
7
|
+
const day = new Date(2022, 10, 21);
|
|
8
|
+
const dayModifiers: Modifiers = {
|
|
9
|
+
disabled: false,
|
|
10
|
+
focusable: false,
|
|
11
|
+
focused: false,
|
|
12
|
+
hidden: false,
|
|
13
|
+
outside: false,
|
|
14
|
+
range_end: false,
|
|
15
|
+
range_middle: false,
|
|
16
|
+
range_start: false,
|
|
17
|
+
selected: false,
|
|
18
|
+
today: false
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe("when the day is selected", () => {
|
|
22
|
+
test("return the label", () => {
|
|
23
|
+
expect(labelDayButton(day, { ...dayModifiers, selected: true })).toEqual(
|
|
24
|
+
"Monday, November 21st, 2022, selected"
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("when the day is today", () => {
|
|
30
|
+
test("return the label", () => {
|
|
31
|
+
expect(labelDayButton(day, { ...dayModifiers, today: true })).toEqual(
|
|
32
|
+
"Today, Monday, November 21st, 2022"
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("should return the localized label", () => {
|
|
38
|
+
expect(labelDayButton(day, dayModifiers, { locale: es })).toEqual(
|
|
39
|
+
"lunes, 21 de noviembre de 2022"
|
|
40
|
+
);
|
|
41
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DateLib, type DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
import type { Modifiers } from "../types/index.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The ARIA label for the day button.
|
|
6
|
+
*
|
|
7
|
+
* Use the `modifiers` argument to add additional context to the label, e.g.
|
|
8
|
+
* when a day is selected or is today.
|
|
9
|
+
*
|
|
10
|
+
* @defaultValue The formatted date.
|
|
11
|
+
* @group Labels
|
|
12
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
13
|
+
*/
|
|
14
|
+
export function labelDayButton(
|
|
15
|
+
date: Date,
|
|
16
|
+
/** The modifiers for the day. */
|
|
17
|
+
modifiers: Modifiers,
|
|
18
|
+
options?: DateLibOptions,
|
|
19
|
+
dateLib?: DateLib
|
|
20
|
+
) {
|
|
21
|
+
let label = (dateLib ?? new DateLib(options)).format(date, "PPPP");
|
|
22
|
+
if (modifiers.today) label = `Today, ${label}`;
|
|
23
|
+
if (modifiers.selected) label = `${label}, selected`;
|
|
24
|
+
return label;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @ignore
|
|
29
|
+
* @deprecated Use `labelDayButton` instead.
|
|
30
|
+
*/
|
|
31
|
+
export const labelDay = labelDayButton;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DateLib, type DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the month grid, that will be announced when entering the
|
|
5
|
+
* grid.
|
|
6
|
+
*
|
|
7
|
+
* @defaultValue `LLLL y` (e.g. "November 2022")
|
|
8
|
+
* @group Labels
|
|
9
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
10
|
+
*/
|
|
11
|
+
export function labelGrid(
|
|
12
|
+
date: Date,
|
|
13
|
+
options?: DateLibOptions,
|
|
14
|
+
dateLib?: DateLib
|
|
15
|
+
) {
|
|
16
|
+
return (dateLib ?? new DateLib(options)).format(date, "LLLL y");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @ignore
|
|
21
|
+
* @deprecated Use {@link labelGrid} instead.
|
|
22
|
+
*/
|
|
23
|
+
export const labelCaption = labelGrid;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DateLib, type DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
import type { Modifiers } from "../types/index.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The label for the day gridcell when the calendar is not interactive.
|
|
6
|
+
*
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelGridcell(
|
|
11
|
+
date: Date,
|
|
12
|
+
/** The modifiers for the day. */
|
|
13
|
+
modifiers?: Modifiers,
|
|
14
|
+
options?: DateLibOptions,
|
|
15
|
+
dateLib?: DateLib
|
|
16
|
+
) {
|
|
17
|
+
let label = (dateLib ?? new DateLib(options)).format(date, "PPPP");
|
|
18
|
+
if (modifiers?.today) {
|
|
19
|
+
label = `Today, ${label}`;
|
|
20
|
+
}
|
|
21
|
+
return label;
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the months dropdown.
|
|
5
|
+
*
|
|
6
|
+
* @defaultValue `"Choose the Month"`
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelMonthDropdown(options?: DateLibOptions) {
|
|
11
|
+
return "Choose the Month";
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ARIA label for next month button.
|
|
3
|
+
*
|
|
4
|
+
* @defaultValue `"Go to the Next Month"`
|
|
5
|
+
* @group Labels
|
|
6
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
7
|
+
*/
|
|
8
|
+
export function labelNext(
|
|
9
|
+
/** `undefined` where there's no next month to navigate to. */
|
|
10
|
+
month: Date | undefined
|
|
11
|
+
) {
|
|
12
|
+
return "Go to the Next Month";
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ARIA label for previous month button.
|
|
3
|
+
*
|
|
4
|
+
* @defaultValue `"Go to the Previous Month"`
|
|
5
|
+
* @group Labels
|
|
6
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
7
|
+
*/
|
|
8
|
+
export function labelPrevious(
|
|
9
|
+
/** Undefined where there's no previous month to navigate to. */
|
|
10
|
+
month: Date | undefined
|
|
11
|
+
) {
|
|
12
|
+
return "Go to the Previous Month";
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the week number cell (the first cell in the row).
|
|
5
|
+
*
|
|
6
|
+
* @defaultValue `Week ${weekNumber}`
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelWeekNumber(
|
|
11
|
+
weekNumber: number,
|
|
12
|
+
options?: DateLibOptions
|
|
13
|
+
): string {
|
|
14
|
+
return `Week ${weekNumber}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the week number header element.
|
|
5
|
+
*
|
|
6
|
+
* @defaultValue `"Week Number"`
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelWeekNumberHeader(options?: DateLibOptions): string {
|
|
11
|
+
return "Week Number";
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { es } from "date-fns/locale/es";
|
|
2
|
+
|
|
3
|
+
import { labelWeekday } from "./labelWeekday";
|
|
4
|
+
|
|
5
|
+
const weekDay = new Date(2022, 10, 21);
|
|
6
|
+
|
|
7
|
+
test("should return the formatted weekday name", () => {
|
|
8
|
+
expect(labelWeekday(weekDay)).toEqual("Monday");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
describe("when a locale is passed in", () => {
|
|
12
|
+
test("should format using the locale", () => {
|
|
13
|
+
expect(labelWeekday(weekDay, { locale: es })).toEqual("lunes");
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DateLib, type DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the Weekday column header.
|
|
5
|
+
*
|
|
6
|
+
* @defaultValue `"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"`
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelWeekday(
|
|
11
|
+
date: Date,
|
|
12
|
+
options?: DateLibOptions,
|
|
13
|
+
dateLib?: DateLib
|
|
14
|
+
): string {
|
|
15
|
+
return (dateLib ?? new DateLib(options)).format(date, "cccc");
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DateLibOptions } from "../classes/DateLib.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ARIA label for the years dropdown.
|
|
5
|
+
*
|
|
6
|
+
* @defaultValue `"Choose the Year"`
|
|
7
|
+
* @group Labels
|
|
8
|
+
* @see https://daypicker.dev/docs/translation#aria-labels
|
|
9
|
+
*/
|
|
10
|
+
export function labelYearDropdown(options?: DateLibOptions) {
|
|
11
|
+
return "Choose the Year";
|
|
12
|
+
}
|
package/src/locale.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "date-fns/locale";
|
package/src/persian.tsx
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import * as dateFnsJalali from "date-fns-jalali";
|
|
4
|
+
import { Locale } from "date-fns-jalali";
|
|
5
|
+
import * as locales from "date-fns-jalali/locale";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
DateLib,
|
|
9
|
+
DateLibOptions,
|
|
10
|
+
DayPicker as DayPickerComponent
|
|
11
|
+
} from "./index.js";
|
|
12
|
+
import type { DayPickerProps } from "./types/props.js";
|
|
13
|
+
|
|
14
|
+
export const faIR = locales.faIR;
|
|
15
|
+
export const enUS = locales.enUS;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Render the Persian Calendar.
|
|
19
|
+
*
|
|
20
|
+
* @see https://daypicker.dev/docs/localization#persian-calendar
|
|
21
|
+
*/
|
|
22
|
+
export function DayPicker(
|
|
23
|
+
props: DayPickerProps & {
|
|
24
|
+
/**
|
|
25
|
+
* The locale to use in the calendar.
|
|
26
|
+
*
|
|
27
|
+
* @default `faIR`
|
|
28
|
+
*/
|
|
29
|
+
locale?: Locale;
|
|
30
|
+
/**
|
|
31
|
+
* The direction of the text in the calendar.
|
|
32
|
+
*
|
|
33
|
+
* @default `rtl`
|
|
34
|
+
*/
|
|
35
|
+
dir?: DayPickerProps["dir"];
|
|
36
|
+
/**
|
|
37
|
+
* The date library to use in the calendar.
|
|
38
|
+
*
|
|
39
|
+
* @default `jalaliDateLib` from `date-fns-jalali`
|
|
40
|
+
*/
|
|
41
|
+
dateLib?: DayPickerProps["dateLib"];
|
|
42
|
+
/**
|
|
43
|
+
* The numeral system to use when formatting dates.
|
|
44
|
+
*
|
|
45
|
+
* - `latn`: Latin (Western Arabic)
|
|
46
|
+
* - `arab`: Arabic-Indic
|
|
47
|
+
* - `arabext`: Eastern Arabic-Indic (Persian)
|
|
48
|
+
* - `deva`: Devanagari
|
|
49
|
+
* - `beng`: Bengali
|
|
50
|
+
* - `guru`: Gurmukhi
|
|
51
|
+
* - `gujr`: Gujarati
|
|
52
|
+
* - `orya`: Oriya
|
|
53
|
+
* - `tamldec`: Tamil
|
|
54
|
+
* - `telu`: Telugu
|
|
55
|
+
* - `knda`: Kannada
|
|
56
|
+
* - `mlym`: Malayalam
|
|
57
|
+
*
|
|
58
|
+
* @defaultValue `arabext` Eastern Arabic-Indic (Persian)
|
|
59
|
+
* @see https://daypicker.dev/docs/translation#numeral-systems
|
|
60
|
+
*/
|
|
61
|
+
numerals?: DayPickerProps["numerals"];
|
|
62
|
+
}
|
|
63
|
+
) {
|
|
64
|
+
const dateLib = getDateLib({
|
|
65
|
+
locale: props.locale,
|
|
66
|
+
weekStartsOn: props.broadcastCalendar ? 1 : props.weekStartsOn,
|
|
67
|
+
firstWeekContainsDate: props.firstWeekContainsDate,
|
|
68
|
+
useAdditionalWeekYearTokens: props.useAdditionalWeekYearTokens,
|
|
69
|
+
useAdditionalDayOfYearTokens: props.useAdditionalDayOfYearTokens,
|
|
70
|
+
timeZone: props.timeZone
|
|
71
|
+
});
|
|
72
|
+
return (
|
|
73
|
+
<DayPickerComponent
|
|
74
|
+
{...props}
|
|
75
|
+
locale={props.locale ?? faIR}
|
|
76
|
+
numerals={props.numerals ?? "arabext"}
|
|
77
|
+
dir={props.dir ?? "rtl"}
|
|
78
|
+
dateLib={dateLib}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Returns the date library used in the calendar. */
|
|
84
|
+
export const getDateLib = (options?: DateLibOptions) => {
|
|
85
|
+
return new DateLib(options, dateFnsJalali);
|
|
86
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { act, renderHook } from "@/test/render";
|
|
2
|
+
|
|
3
|
+
import { defaultDateLib } from "../classes/DateLib";
|
|
4
|
+
import { DayPickerProps } from "../types";
|
|
5
|
+
|
|
6
|
+
import { useMulti } from "./useMulti";
|
|
7
|
+
|
|
8
|
+
describe("useMulti", () => {
|
|
9
|
+
it("uses the selected value from props when onSelect is provided", () => {
|
|
10
|
+
const mockOnSelect = jest.fn();
|
|
11
|
+
const selectedDates = [new Date(2023, 9, 1), new Date(2023, 9, 2)];
|
|
12
|
+
const props: DayPickerProps = {
|
|
13
|
+
mode: "multiple",
|
|
14
|
+
selected: selectedDates,
|
|
15
|
+
onSelect: mockOnSelect
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const { result } = renderHook(() => useMulti(props, defaultDateLib));
|
|
19
|
+
|
|
20
|
+
expect(result.current.selected).toBe(selectedDates);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("uses the internally selected value when onSelect is not provided", () => {
|
|
24
|
+
const initialSelectedDates = [new Date(2023, 9, 1), new Date(2023, 9, 2)];
|
|
25
|
+
const props: DayPickerProps = {
|
|
26
|
+
mode: "multiple",
|
|
27
|
+
selected: initialSelectedDates
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const { result } = renderHook(() => useMulti(props, defaultDateLib));
|
|
31
|
+
|
|
32
|
+
act(() => {
|
|
33
|
+
result.current.select?.(new Date(2023, 9, 3), {}, {} as React.MouseEvent);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(result.current.selected).toEqual([
|
|
37
|
+
...initialSelectedDates,
|
|
38
|
+
new Date(2023, 9, 3)
|
|
39
|
+
]);
|
|
40
|
+
});
|
|
41
|
+
});
|