Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
import type { DayPickerProps } from "./types/index.js";
/**
* Renders the DayPicker calendar component.
*
* @param initialProps - The props for the DayPicker component.
* @returns The rendered DayPicker component.
* @group DayPicker
* @see https://daypicker.dev
*/
export declare function DayPicker(initialProps: DayPickerProps): React.JSX.Element;
+328
View File
@@ -0,0 +1,328 @@
import React, { useCallback, useMemo, useRef } from "react";
import { DateLib, defaultLocale } from "./classes/DateLib.js";
import { createGetModifiers } from "./helpers/createGetModifiers.js";
import { getClassNamesForModifiers } from "./helpers/getClassNamesForModifiers.js";
import { getComponents } from "./helpers/getComponents.js";
import { getDataAttributes } from "./helpers/getDataAttributes.js";
import { getDefaultClassNames } from "./helpers/getDefaultClassNames.js";
import { getFormatters } from "./helpers/getFormatters.js";
import { getLabels } from "./helpers/getLabels.js";
import { getMonthOptions } from "./helpers/getMonthOptions.js";
import { getStyleForModifiers } from "./helpers/getStyleForModifiers.js";
import { getWeekdays } from "./helpers/getWeekdays.js";
import { getYearOptions } from "./helpers/getYearOptions.js";
import { createNoonOverrides } from "./noonDateLib.js";
import { DayFlag, SelectionState, UI } from "./UI.js";
import { useAnimation } from "./useAnimation.js";
import { useCalendar } from "./useCalendar.js";
import { dayPickerContext } from "./useDayPicker.js";
import { useFocus } from "./useFocus.js";
import { useSelection } from "./useSelection.js";
import { convertMatchersToTimeZone } from "./utils/convertMatchersToTimeZone.js";
import { rangeIncludesDate } from "./utils/rangeIncludesDate.js";
import { toTimeZone } from "./utils/toTimeZone.js";
import { isDateRange } from "./utils/typeguards.js";
/**
* Renders the DayPicker calendar component.
*
* @param initialProps - The props for the DayPicker component.
* @returns The rendered DayPicker component.
* @group DayPicker
* @see https://daypicker.dev
*/
export function DayPicker(initialProps) {
let props = initialProps;
const timeZone = props.timeZone;
if (timeZone) {
props = {
...initialProps,
timeZone,
};
if (props.today) {
props.today = toTimeZone(props.today, timeZone);
}
if (props.month) {
props.month = toTimeZone(props.month, timeZone);
}
if (props.defaultMonth) {
props.defaultMonth = toTimeZone(props.defaultMonth, timeZone);
}
if (props.startMonth) {
props.startMonth = toTimeZone(props.startMonth, timeZone);
}
if (props.endMonth) {
props.endMonth = toTimeZone(props.endMonth, timeZone);
}
if (props.mode === "single" && props.selected) {
props.selected = toTimeZone(props.selected, timeZone);
}
else if (props.mode === "multiple" && props.selected) {
props.selected = props.selected?.map((date) => toTimeZone(date, timeZone));
}
else if (props.mode === "range" && props.selected) {
props.selected = {
from: props.selected.from
? toTimeZone(props.selected.from, timeZone)
: props.selected.from,
to: props.selected.to
? toTimeZone(props.selected.to, timeZone)
: props.selected.to,
};
}
if (props.disabled !== undefined) {
props.disabled = convertMatchersToTimeZone(props.disabled, timeZone);
}
if (props.hidden !== undefined) {
props.hidden = convertMatchersToTimeZone(props.hidden, timeZone);
}
if (props.modifiers) {
const nextModifiers = {};
Object.keys(props.modifiers).forEach((key) => {
nextModifiers[key] = convertMatchersToTimeZone(props.modifiers?.[key], timeZone);
});
props.modifiers = nextModifiers;
}
}
const { components, formatters, labels, dateLib, locale, classNames } = useMemo(() => {
const locale = { ...defaultLocale, ...props.locale };
const weekStartsOn = props.broadcastCalendar ? 1 : props.weekStartsOn;
const noonOverrides = props.noonSafe && props.timeZone
? createNoonOverrides(props.timeZone, {
weekStartsOn,
locale,
})
: undefined;
const overrides = props.dateLib && noonOverrides
? { ...noonOverrides, ...props.dateLib }
: (props.dateLib ?? noonOverrides);
const dateLib = new DateLib({
locale,
weekStartsOn,
firstWeekContainsDate: props.firstWeekContainsDate,
useAdditionalWeekYearTokens: props.useAdditionalWeekYearTokens,
useAdditionalDayOfYearTokens: props.useAdditionalDayOfYearTokens,
timeZone: props.timeZone,
numerals: props.numerals,
}, overrides);
return {
dateLib,
components: getComponents(props.components),
formatters: getFormatters(props.formatters),
labels: getLabels(props.labels, dateLib.options),
locale,
classNames: { ...getDefaultClassNames(), ...props.classNames },
};
}, [
props.locale,
props.broadcastCalendar,
props.weekStartsOn,
props.firstWeekContainsDate,
props.useAdditionalWeekYearTokens,
props.useAdditionalDayOfYearTokens,
props.timeZone,
props.numerals,
props.dateLib,
props.noonSafe,
props.components,
props.formatters,
props.labels,
props.classNames,
]);
if (!props.today) {
props = { ...props, today: dateLib.today() };
}
const { captionLayout, mode, navLayout, numberOfMonths = 1, onDayBlur, onDayClick, onDayFocus, onDayKeyDown, onDayMouseEnter, onDayMouseLeave, onNextClick, onPrevClick, showWeekNumber, styles, } = props;
const { formatCaption, formatDay, formatMonthDropdown, formatWeekNumber, formatWeekNumberHeader, formatWeekdayName, formatYearDropdown, } = formatters;
const calendar = useCalendar(props, dateLib);
const { days, months, navStart, navEnd, previousMonth, nextMonth, goToMonth, } = calendar;
const getModifiers = createGetModifiers(days, props, navStart, navEnd, dateLib);
const { isSelected, select, selected: selectedValue, } = useSelection(props, dateLib) ?? {};
const { blur, focused, isFocusTarget, moveFocus, setFocused } = useFocus(props, calendar, getModifiers, isSelected ?? (() => false), dateLib);
const { labelDayButton, labelGridcell, labelGrid, labelMonthDropdown, labelNav, labelPrevious, labelNext, labelWeekday, labelWeekNumber, labelWeekNumberHeader, labelYearDropdown, } = labels;
const weekdays = useMemo(() => getWeekdays(dateLib, props.ISOWeek, props.broadcastCalendar, props.today), [dateLib, props.ISOWeek, props.broadcastCalendar, props.today]);
const isInteractive = mode !== undefined || onDayClick !== undefined;
const handlePreviousClick = useCallback(() => {
if (!previousMonth)
return;
goToMonth(previousMonth);
onPrevClick?.(previousMonth);
}, [previousMonth, goToMonth, onPrevClick]);
const handleNextClick = useCallback(() => {
if (!nextMonth)
return;
goToMonth(nextMonth);
onNextClick?.(nextMonth);
}, [goToMonth, nextMonth, onNextClick]);
const handleDayClick = useCallback((day, m) => (e) => {
e.preventDefault();
e.stopPropagation();
setFocused(day);
if (m.disabled) {
return;
}
select?.(day.date, m, e);
onDayClick?.(day.date, m, e);
}, [select, onDayClick, setFocused]);
const handleDayFocus = useCallback((day, m) => (e) => {
setFocused(day);
onDayFocus?.(day.date, m, e);
}, [onDayFocus, setFocused]);
const handleDayBlur = useCallback((day, m) => (e) => {
blur();
onDayBlur?.(day.date, m, e);
}, [blur, onDayBlur]);
const handleDayKeyDown = useCallback((day, modifiers) => (e) => {
const keyMap = {
ArrowLeft: [
e.shiftKey ? "month" : "day",
props.dir === "rtl" ? "after" : "before",
],
ArrowRight: [
e.shiftKey ? "month" : "day",
props.dir === "rtl" ? "before" : "after",
],
ArrowDown: [e.shiftKey ? "year" : "week", "after"],
ArrowUp: [e.shiftKey ? "year" : "week", "before"],
PageUp: [e.shiftKey ? "year" : "month", "before"],
PageDown: [e.shiftKey ? "year" : "month", "after"],
Home: ["startOfWeek", "before"],
End: ["endOfWeek", "after"],
};
if (keyMap[e.key]) {
e.preventDefault();
e.stopPropagation();
const [moveBy, moveDir] = keyMap[e.key];
moveFocus(moveBy, moveDir);
}
onDayKeyDown?.(day.date, modifiers, e);
}, [moveFocus, onDayKeyDown, props.dir]);
const handleDayMouseEnter = useCallback((day, modifiers) => (e) => {
onDayMouseEnter?.(day.date, modifiers, e);
}, [onDayMouseEnter]);
const handleDayMouseLeave = useCallback((day, modifiers) => (e) => {
onDayMouseLeave?.(day.date, modifiers, e);
}, [onDayMouseLeave]);
const handleMonthChange = useCallback((date) => (e) => {
const selectedMonth = Number(e.target.value);
const month = dateLib.setMonth(dateLib.startOfMonth(date), selectedMonth);
goToMonth(month);
}, [dateLib, goToMonth]);
const handleYearChange = useCallback((date) => (e) => {
const selectedYear = Number(e.target.value);
const month = dateLib.setYear(dateLib.startOfMonth(date), selectedYear);
goToMonth(month);
}, [dateLib, goToMonth]);
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 = getDataAttributes(props);
const rootElRef = useRef(null);
useAnimation(rootElRef, Boolean(props.animate), {
classNames,
months,
focused,
dateLib,
});
const contextValue = {
dayPickerProps: props,
selected: selectedValue,
select: select,
isSelected,
months,
nextMonth,
previousMonth,
goToMonth,
getModifiers,
components,
classNames,
styles,
labels,
formatters,
};
return (React.createElement(dayPickerContext.Provider, { value: contextValue },
React.createElement(components.Root, { rootRef: props.animate ? rootElRef : undefined, className: className, style: style, dir: props.dir, id: props.id, lang: props.lang, nonce: props.nonce, title: props.title, role: props.role, "aria-label": props["aria-label"], "aria-labelledby": props["aria-labelledby"], ...dataAttributes },
React.createElement(components.Months, { className: classNames[UI.Months], style: styles?.[UI.Months] },
!props.hideNavigation && !navLayout && (React.createElement(components.Nav, { "data-animated-nav": props.animate ? "true" : undefined, className: classNames[UI.Nav], style: styles?.[UI.Nav], "aria-label": labelNav(), onPreviousClick: handlePreviousClick, onNextClick: handleNextClick, previousMonth: previousMonth, nextMonth: nextMonth })),
months.map((calendarMonth, displayIndex) => {
return (React.createElement(components.Month, { "data-animated-month": props.animate ? "true" : undefined, className: classNames[UI.Month], style: styles?.[UI.Month],
// biome-ignore lint/suspicious/noArrayIndexKey: breaks animation
key: displayIndex, displayIndex: displayIndex, calendarMonth: calendarMonth },
navLayout === "around" &&
!props.hideNavigation &&
displayIndex === 0 && (React.createElement(components.PreviousMonthButton, { type: "button", className: classNames[UI.PreviousMonthButton], tabIndex: previousMonth ? undefined : -1, "aria-disabled": previousMonth ? undefined : true, "aria-label": labelPrevious(previousMonth), onClick: handlePreviousClick, "data-animated-button": props.animate ? "true" : undefined },
React.createElement(components.Chevron, { disabled: previousMonth ? undefined : true, className: classNames[UI.Chevron], orientation: props.dir === "rtl" ? "right" : "left" }))),
React.createElement(components.MonthCaption, { "data-animated-caption": props.animate ? "true" : undefined, className: classNames[UI.MonthCaption], style: styles?.[UI.MonthCaption], calendarMonth: calendarMonth, displayIndex: displayIndex }, captionLayout?.startsWith("dropdown") ? (React.createElement(components.DropdownNav, { className: classNames[UI.Dropdowns], style: styles?.[UI.Dropdowns] },
(() => {
const monthControl = captionLayout === "dropdown" ||
captionLayout === "dropdown-months" ? (React.createElement(components.MonthsDropdown, { key: "month", className: classNames[UI.MonthsDropdown], "aria-label": labelMonthDropdown(), classNames: classNames, components: components, disabled: Boolean(props.disableNavigation), onChange: handleMonthChange(calendarMonth.date), options: getMonthOptions(calendarMonth.date, navStart, navEnd, formatters, dateLib), style: styles?.[UI.Dropdown], value: dateLib.getMonth(calendarMonth.date) })) : (React.createElement("span", { key: "month" }, formatMonthDropdown(calendarMonth.date, dateLib)));
const yearControl = captionLayout === "dropdown" ||
captionLayout === "dropdown-years" ? (React.createElement(components.YearsDropdown, { key: "year", className: classNames[UI.YearsDropdown], "aria-label": labelYearDropdown(dateLib.options), classNames: classNames, components: components, disabled: Boolean(props.disableNavigation), onChange: handleYearChange(calendarMonth.date), options: getYearOptions(navStart, navEnd, formatters, dateLib, Boolean(props.reverseYears)), style: styles?.[UI.Dropdown], value: dateLib.getYear(calendarMonth.date) })) : (React.createElement("span", { key: "year" }, formatYearDropdown(calendarMonth.date, dateLib)));
const controls = dateLib.getMonthYearOrder() === "year-first"
? [yearControl, monthControl]
: [monthControl, yearControl];
return controls;
})(),
React.createElement("span", { role: "status", "aria-live": "polite", style: {
border: 0,
clip: "rect(0 0 0 0)",
height: "1px",
margin: "-1px",
overflow: "hidden",
padding: 0,
position: "absolute",
width: "1px",
whiteSpace: "nowrap",
wordWrap: "normal",
} }, formatCaption(calendarMonth.date, dateLib.options, dateLib)))) : (React.createElement(components.CaptionLabel, { className: classNames[UI.CaptionLabel], role: "status", "aria-live": "polite" }, formatCaption(calendarMonth.date, dateLib.options, dateLib)))),
navLayout === "around" &&
!props.hideNavigation &&
displayIndex === numberOfMonths - 1 && (React.createElement(components.NextMonthButton, { type: "button", className: classNames[UI.NextMonthButton], tabIndex: nextMonth ? undefined : -1, "aria-disabled": nextMonth ? undefined : true, "aria-label": labelNext(nextMonth), onClick: handleNextClick, "data-animated-button": props.animate ? "true" : undefined },
React.createElement(components.Chevron, { disabled: nextMonth ? undefined : true, className: classNames[UI.Chevron], orientation: props.dir === "rtl" ? "left" : "right" }))),
displayIndex === numberOfMonths - 1 &&
navLayout === "after" &&
!props.hideNavigation && (React.createElement(components.Nav, { "data-animated-nav": props.animate ? "true" : undefined, className: classNames[UI.Nav], style: styles?.[UI.Nav], "aria-label": labelNav(), onPreviousClick: handlePreviousClick, onNextClick: handleNextClick, previousMonth: previousMonth, nextMonth: nextMonth })),
React.createElement(components.MonthGrid, { role: "grid", "aria-multiselectable": mode === "multiple" || mode === "range", "aria-label": labelGrid(calendarMonth.date, dateLib.options, dateLib) ||
undefined, className: classNames[UI.MonthGrid], style: styles?.[UI.MonthGrid] },
!props.hideWeekdays && (React.createElement(components.Weekdays, { "data-animated-weekdays": props.animate ? "true" : undefined, className: classNames[UI.Weekdays], style: styles?.[UI.Weekdays] },
showWeekNumber && (React.createElement(components.WeekNumberHeader, { "aria-label": labelWeekNumberHeader(dateLib.options), className: classNames[UI.WeekNumberHeader], style: styles?.[UI.WeekNumberHeader], scope: "col" }, formatWeekNumberHeader())),
weekdays.map((weekday) => (React.createElement(components.Weekday, { "aria-label": labelWeekday(weekday, dateLib.options, dateLib), className: classNames[UI.Weekday], key: String(weekday), style: styles?.[UI.Weekday], scope: "col" }, formatWeekdayName(weekday, dateLib.options, dateLib)))))),
React.createElement(components.Weeks, { "data-animated-weeks": props.animate ? "true" : undefined, className: classNames[UI.Weeks], style: styles?.[UI.Weeks] }, calendarMonth.weeks.map((week) => {
return (React.createElement(components.Week, { className: classNames[UI.Week], key: week.weekNumber, style: styles?.[UI.Week], week: week },
showWeekNumber && (React.createElement(components.WeekNumber, { week: week, style: styles?.[UI.WeekNumber], "aria-label": labelWeekNumber(week.weekNumber, {
locale,
}), className: classNames[UI.WeekNumber], scope: "row", role: "rowheader" }, formatWeekNumber(week.weekNumber, dateLib))),
week.days.map((day) => {
const { date } = day;
const modifiers = getModifiers(day);
modifiers[DayFlag.focused] =
!modifiers.hidden &&
Boolean(focused?.isEqualTo(day));
modifiers[SelectionState.selected] =
isSelected?.(date) || modifiers.selected;
if (isDateRange(selectedValue)) {
// add range modifiers
const { from, to } = selectedValue;
modifiers[SelectionState.range_start] = Boolean(from && to && dateLib.isSameDay(date, from));
modifiers[SelectionState.range_end] = Boolean(from && to && dateLib.isSameDay(date, to));
modifiers[SelectionState.range_middle] =
rangeIncludesDate(selectedValue, date, true, dateLib);
}
const style = getStyleForModifiers(modifiers, styles, props.modifiersStyles);
const className = getClassNamesForModifiers(modifiers, classNames, props.modifiersClassNames);
const ariaLabel = !isInteractive && !modifiers.hidden
? labelGridcell(date, modifiers, dateLib.options, dateLib)
: undefined;
return (React.createElement(components.Day, { key: `${day.isoDate}_${day.displayMonthId}`, day: day, modifiers: modifiers, className: className.join(" "), style: style, role: "gridcell", "aria-selected": modifiers.selected || undefined, "aria-label": ariaLabel, "data-day": day.isoDate, "data-month": day.outside ? day.dateMonthId : undefined, "data-selected": modifiers.selected || undefined, "data-disabled": modifiers.disabled || undefined, "data-hidden": modifiers.hidden || undefined, "data-outside": day.outside || undefined, "data-focused": modifiers.focused || undefined, "data-today": modifiers.today || undefined }, !modifiers.hidden && isInteractive ? (React.createElement(components.DayButton, { className: classNames[UI.DayButton], style: styles?.[UI.DayButton], type: "button", day: day, modifiers: modifiers, disabled: (!modifiers.focused &&
modifiers.disabled) ||
undefined, "aria-disabled": (modifiers.focused &&
modifiers.disabled) ||
undefined, tabIndex: isFocusTarget(day) ? 0 : -1, "aria-label": labelDayButton(date, modifiers, dateLib.options, dateLib), onClick: handleDayClick(day, modifiers), onBlur: handleDayBlur(day, modifiers), onFocus: handleDayFocus(day, modifiers), onKeyDown: handleDayKeyDown(day, modifiers), onMouseEnter: handleDayMouseEnter(day, modifiers), onMouseLeave: handleDayMouseLeave(day, modifiers) }, formatDay(date, dateLib.options, dateLib))) : (!modifiers.hidden &&
formatDay(day.date, dateLib.options, dateLib))));
})));
})))));
})),
props.footer && (React.createElement(components.Footer, { className: classNames[UI.Footer], style: styles?.[UI.Footer], role: "status", "aria-live": "polite" }, props.footer)))));
}
+346
View File
@@ -0,0 +1,346 @@
import type { CSSProperties } from "react";
/**
* Enum representing the UI elements composing DayPicker. These elements are
* mapped to {@link CustomComponents}, {@link ClassNames}, and {@link Styles}.
*
* Some elements are extended by flags and modifiers.
*/
export declare enum UI {
/** The root component displaying the months and the navigation bar. */
Root = "root",
/** The Chevron SVG element used by navigation buttons and dropdowns. */
Chevron = "chevron",
/**
* The grid cell with the day's date. Extended by {@link DayFlag} and
* {@link SelectionState}.
*/
Day = "day",
/** 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). */
Dropdowns = "dropdowns",
/** The dropdown element to select for years and months. */
Dropdown = "dropdown",
/** The container element of the dropdown. */
DropdownRoot = "dropdown_root",
/** The root element of the footer. */
Footer = "footer",
/** The month grid. */
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 month grid. */
Month = "month",
/** The container of the displayed months. */
Months = "months",
/** The navigation bar with the previous and next buttons. */
Nav = "nav",
/**
* The next month button in the navigation. *
*
* @since 9.1.0
*/
NextMonthButton = "button_next",
/**
* The previous month button in the navigation.
*
* @since 9.1.0
*/
PreviousMonthButton = "button_previous",
/** The row containing the week. */
Week = "week",
/** The group of row weeks in a month (`tbody`). */
Weeks = "weeks",
/** The column header with the weekday. */
Weekday = "weekday",
/** The row grouping the weekdays in the column headers. */
Weekdays = "weekdays",
/** The cell containing the week number. */
WeekNumber = "week_number",
/** The cell header of the week numbers column. */
WeekNumberHeader = "week_number_header",
/** The dropdown with the years. */
YearsDropdown = "years_dropdown"
}
/** Enum representing flags for the {@link UI.Day} element. */
export declare enum DayFlag {
/** The day is disabled. */
disabled = "disabled",
/** The day is hidden. */
hidden = "hidden",
/** The day is outside the current month. */
outside = "outside",
/** The day is focused. */
focused = "focused",
/** The day is today. */
today = "today"
}
/**
* Enum representing selection states that can be applied to the {@link UI.Day}
* element in selection mode.
*/
export declare enum SelectionState {
/** The day is at the end of a selected range. */
range_end = "range_end",
/** The day is at the middle of a selected range. */
range_middle = "range_middle",
/** The day is at the start of a selected range. */
range_start = "range_start",
/** The day is selected. */
selected = "selected"
}
/**
* Enum representing different animation states for transitioning between
* months.
*/
export declare enum Animation {
/** The entering weeks when they appear before the exiting month. */
weeks_before_enter = "weeks_before_enter",
/** The exiting weeks when they disappear before the entering month. */
weeks_before_exit = "weeks_before_exit",
/** The entering weeks when they appear after the exiting month. */
weeks_after_enter = "weeks_after_enter",
/** The exiting weeks when they disappear after the entering month. */
weeks_after_exit = "weeks_after_exit",
/** The entering caption when it appears after the exiting month. */
caption_after_enter = "caption_after_enter",
/** The exiting caption when it disappears after the entering month. */
caption_after_exit = "caption_after_exit",
/** The entering caption when it appears before the exiting month. */
caption_before_enter = "caption_before_enter",
/** The exiting caption when it disappears before the entering month. */
caption_before_exit = "caption_before_exit"
}
/**
* Deprecated UI elements and flags from previous versions of DayPicker.
*
* These elements are kept for backward compatibility and to assist in
* transitioning to the new {@link UI} elements.
*
* @deprecated
* @since 9.0.1
* @template T - The type of the deprecated UI element (e.g., CSS class or
* style).
* @see https://daypicker.dev/upgrading
* @see https://daypicker.dev/docs/styling
*/
export type DeprecatedUI<T extends CSSProperties | string> = {
/**
* This element was applied to the style of any button in DayPicker and it is
* replaced by {@link UI.PreviousMonthButton} and {@link UI.NextMonthButton}.
*
* @deprecated
*/
button: T;
/**
* This element was resetting the style of any button in DayPicker and it is
* replaced by {@link UI.PreviousMonthButton} and {@link UI.NextMonthButton}.
*
* @deprecated
*/
button_reset: T;
/**
* This element has been renamed to {@link UI.MonthCaption}.
*
* @deprecated
*/
caption: T;
/**
* This element has been removed. Captions are styled via
* {@link UI.MonthCaption}.
*
* @deprecated
*/
caption_between: T;
/**
* This element has been renamed to {@link UI.Dropdowns}.
*
* @deprecated
*/
caption_dropdowns: T;
/**
* This element has been removed. Captions are styled via
* {@link UI.MonthCaption}.
*
* @deprecated
*/
caption_end: T;
/**
* This element has been removed.
*
* @deprecated
*/
caption_start: T;
/**
* This element has been renamed to {@link UI.Day}.
*
* @deprecated
*/
cell: T;
/**
* This element has been renamed to {@link DayFlag.disabled}.
*
* @deprecated
*/
day_disabled: T;
/**
* This element has been renamed to {@link DayFlag.hidden}.
*
* @deprecated
*/
day_hidden: T;
/**
* This element has been renamed to {@link DayFlag.outside}.
*
* @deprecated
*/
day_outside: T;
/**
* This element has been renamed to {@link SelectionState.range_end}.
*
* @deprecated
*/
day_range_end: T;
/**
* This element has been renamed to {@link SelectionState.range_middle}.
*
* @deprecated
*/
day_range_middle: T;
/**
* This element has been renamed to {@link SelectionState.range_start}.
*
* @deprecated
*/
day_range_start: T;
/**
* This element has been renamed to {@link SelectionState.selected}.
*
* @deprecated
*/
day_selected: T;
/**
* This element has been renamed to {@link DayFlag.today}.
*
* @deprecated
*/
day_today: T;
/**
* This element has been removed. The dropdown icon is now {@link UI.Chevron}
* inside a {@link UI.CaptionLabel}.
*
* @deprecated
*/
dropdown_icon: T;
/**
* This element has been renamed to {@link UI.MonthsDropdown}.
*
* @deprecated
*/
dropdown_month: T;
/**
* This element has been renamed to {@link UI.YearsDropdown}.
*
* @deprecated
*/
dropdown_year: T;
/**
* This element has been removed.
*
* @deprecated
*/
head: T;
/**
* This element has been renamed to {@link UI.Weekday}.
*
* @deprecated
*/
head_cell: T;
/**
* This element has been renamed to {@link UI.Weekdays}.
*
* @deprecated
*/
head_row: T;
/**
* This flag has been removed. Use `data-multiple-months` in your CSS
* selectors.
*
* @deprecated
*/
multiple_months: T;
/**
* This element has been removed. To style the navigation buttons, use
* {@link UI.PreviousMonthButton} and {@link UI.NextMonthButton}.
*
* @deprecated
*/
nav_button: T;
/**
* This element has been renamed to {@link UI.NextMonthButton}.
*
* @deprecated
*/
nav_button_next: T;
/**
* This element has been renamed to {@link UI.PreviousMonthButton}.
*
* @deprecated
*/
nav_button_previous: T;
/**
* This element has been removed. The dropdown icon is now {@link UI.Chevron}
* inside a {@link UI.NextMonthButton} or a {@link UI.PreviousMonthButton}.
*
* @deprecated
*/
nav_icon: T;
/**
* This element has been renamed to {@link UI.Week}.
*
* @deprecated
*/
row: T;
/**
* This element has been renamed to {@link UI.MonthGrid}.
*
* @deprecated
*/
table: T;
/**
* This element has been renamed to {@link UI.Weeks}.
*
* @deprecated
*/
tbody: T;
/**
* This element has been removed. The {@link UI.Footer} is now a single element
* below the months.
*
* @deprecated
*/
tfoot: T;
/**
* This flag has been removed. There are no "visually hidden" elements in
* DayPicker 9.
*
* @deprecated
*/
vhidden: T;
/**
* This element has been renamed. Use {@link UI.WeekNumber} instead.
*
* @deprecated
*/
weeknumber: T;
/**
* This flag has been removed. Use `data-week-numbers` in your CSS.
*
* @deprecated
*/
with_weeknumber: T;
};
+120
View File
@@ -0,0 +1,120 @@
/**
* Enum representing the UI elements composing DayPicker. These elements are
* mapped to {@link CustomComponents}, {@link ClassNames}, and {@link Styles}.
*
* Some elements are extended by flags and modifiers.
*/
export var UI;
(function (UI) {
/** The root component displaying the months and the navigation bar. */
UI["Root"] = "root";
/** The Chevron SVG element used by navigation buttons and dropdowns. */
UI["Chevron"] = "chevron";
/**
* The grid cell with the day's date. Extended by {@link DayFlag} and
* {@link SelectionState}.
*/
UI["Day"] = "day";
/** The button containing the formatted day's date, inside the grid cell. */
UI["DayButton"] = "day_button";
/** The caption label of the month (when not showing the dropdown navigation). */
UI["CaptionLabel"] = "caption_label";
/** The container of the dropdown navigation (when enabled). */
UI["Dropdowns"] = "dropdowns";
/** The dropdown element to select for years and months. */
UI["Dropdown"] = "dropdown";
/** The container element of the dropdown. */
UI["DropdownRoot"] = "dropdown_root";
/** The root element of the footer. */
UI["Footer"] = "footer";
/** The month grid. */
UI["MonthGrid"] = "month_grid";
/** Contains the dropdown navigation or the caption label. */
UI["MonthCaption"] = "month_caption";
/** The dropdown with the months. */
UI["MonthsDropdown"] = "months_dropdown";
/** Wrapper of the month grid. */
UI["Month"] = "month";
/** The container of the displayed months. */
UI["Months"] = "months";
/** The navigation bar with the previous and next buttons. */
UI["Nav"] = "nav";
/**
* The next month button in the navigation. *
*
* @since 9.1.0
*/
UI["NextMonthButton"] = "button_next";
/**
* The previous month button in the navigation.
*
* @since 9.1.0
*/
UI["PreviousMonthButton"] = "button_previous";
/** The row containing the week. */
UI["Week"] = "week";
/** The group of row weeks in a month (`tbody`). */
UI["Weeks"] = "weeks";
/** The column header with the weekday. */
UI["Weekday"] = "weekday";
/** The row grouping the weekdays in the column headers. */
UI["Weekdays"] = "weekdays";
/** The cell containing the week number. */
UI["WeekNumber"] = "week_number";
/** The cell header of the week numbers column. */
UI["WeekNumberHeader"] = "week_number_header";
/** The dropdown with the years. */
UI["YearsDropdown"] = "years_dropdown";
})(UI || (UI = {}));
/** Enum representing flags for the {@link UI.Day} element. */
export var DayFlag;
(function (DayFlag) {
/** The day is disabled. */
DayFlag["disabled"] = "disabled";
/** The day is hidden. */
DayFlag["hidden"] = "hidden";
/** The day is outside the current month. */
DayFlag["outside"] = "outside";
/** The day is focused. */
DayFlag["focused"] = "focused";
/** The day is today. */
DayFlag["today"] = "today";
})(DayFlag || (DayFlag = {}));
/**
* Enum representing selection states that can be applied to the {@link UI.Day}
* element in selection mode.
*/
export var SelectionState;
(function (SelectionState) {
/** The day is at the end of a selected range. */
SelectionState["range_end"] = "range_end";
/** The day is at the middle of a selected range. */
SelectionState["range_middle"] = "range_middle";
/** The day is at the start of a selected range. */
SelectionState["range_start"] = "range_start";
/** The day is selected. */
SelectionState["selected"] = "selected";
})(SelectionState || (SelectionState = {}));
/**
* Enum representing different animation states for transitioning between
* months.
*/
export var Animation;
(function (Animation) {
/** The entering weeks when they appear before the exiting month. */
Animation["weeks_before_enter"] = "weeks_before_enter";
/** The exiting weeks when they disappear before the entering month. */
Animation["weeks_before_exit"] = "weeks_before_exit";
/** The entering weeks when they appear after the exiting month. */
Animation["weeks_after_enter"] = "weeks_after_enter";
/** The exiting weeks when they disappear after the entering month. */
Animation["weeks_after_exit"] = "weeks_after_exit";
/** The entering caption when it appears after the exiting month. */
Animation["caption_after_enter"] = "caption_after_enter";
/** The exiting caption when it disappears after the entering month. */
Animation["caption_after_exit"] = "caption_after_exit";
/** The entering caption when it appears before the exiting month. */
Animation["caption_before_enter"] = "caption_before_enter";
/** The exiting caption when it disappears before the entering month. */
Animation["caption_before_exit"] = "caption_before_exit";
})(Animation || (Animation = {}));
+26
View File
@@ -0,0 +1,26 @@
import type { Locale } from "date-fns";
import React from "react";
import { DateLib, type DateLibOptions } from "../index.js";
import type { DayPickerProps } from "../types/props.js";
export declare const th: import("../index.js").DayPickerLocale;
export declare const enUS: import("../index.js").DayPickerLocale;
/**
* Render the Buddhist (Thai) calendar.
*
* Months/weeks are Gregorian; displayed year is Buddhist Era (BE = CE + 543).
* Thai digits are used by default.
*
* Defaults:
*
* - `locale`: `th`
* - `dir`: `ltr`
* - `numerals`: `thai`
*/
export declare function DayPicker(props: DayPickerProps & {
locale?: Locale;
dir?: DayPickerProps["dir"];
numerals?: DayPickerProps["numerals"];
dateLib?: DayPickerProps["dateLib"];
}): React.JSX.Element;
/** Returns the date library used in the Buddhist calendar. */
export declare const getDateLib: (options?: DateLibOptions) => DateLib;
+40
View File
@@ -0,0 +1,40 @@
import React from "react";
import { DateLib, DayPicker as DayPickerComponent, } from "../index.js";
import { enUS as enUSLocale } from "../locale/en-US.js";
import { th as thLocale } from "../locale/th.js";
import { format as originalBuddhistFormat } from "./lib/format.js";
// Adapter to match DateLib's format signature without using `any`.
const buddhistFormat = (date, formatStr, options) => {
return originalBuddhistFormat(date, formatStr, options);
};
export const th = thLocale;
export const enUS = enUSLocale;
/**
* Render the Buddhist (Thai) calendar.
*
* Months/weeks are Gregorian; displayed year is Buddhist Era (BE = CE + 543).
* Thai digits are used by default.
*
* Defaults:
*
* - `locale`: `th`
* - `dir`: `ltr`
* - `numerals`: `thai`
*/
export function DayPicker(props) {
const dateLib = getDateLib({
locale: props.locale ?? th,
weekStartsOn: props.broadcastCalendar ? 1 : props.weekStartsOn,
firstWeekContainsDate: props.firstWeekContainsDate,
useAdditionalWeekYearTokens: props.useAdditionalWeekYearTokens,
useAdditionalDayOfYearTokens: props.useAdditionalDayOfYearTokens,
timeZone: props.timeZone,
});
return (React.createElement(DayPickerComponent, { ...props, locale: props.locale ?? th, numerals: props.numerals ?? "thai", dir: props.dir ?? "ltr", dateLib: dateLib }));
}
/** Returns the date library used in the Buddhist calendar. */
export const getDateLib = (options) => {
return new DateLib(options, {
format: buddhistFormat,
});
};
+3
View File
@@ -0,0 +1,3 @@
import type { DateLibOptions } from "../../classes/DateLib.js";
/** Format override adding +543 to year tokens for Buddhist Era (BE). */
export declare function format(date: Date, formatStr: string, options?: DateLibOptions): string;
+27
View File
@@ -0,0 +1,27 @@
import { format as dfFormat } from "date-fns";
/** Format override adding +543 to year tokens for Buddhist Era (BE). */
export function format(date, formatStr, options) {
const beYear = date.getFullYear() + 543;
switch (formatStr) {
case "LLLL y":
case "LLLL yyyy":
return `${dfFormat(date, "LLLL", options)} ${beYear}`;
case "LLLL":
return dfFormat(date, "LLLL", options);
case "yyyy":
return String(beYear).padStart(4, "0");
case "y":
return String(beYear);
case "yyyy-MM":
return `${beYear}-${dfFormat(date, "MM", options)}`;
case "yyyy-MM-dd":
return `${beYear}-${dfFormat(date, "MM", options)}-${dfFormat(date, "dd", options)}`;
case "PPP":
case "PPPP": {
const raw = dfFormat(date, formatStr, options);
return raw.replace(/(.*)(\d{4})(?!.*\d)/, (_m, pre) => `${pre}${beYear}`);
}
default:
return dfFormat(date, formatStr, options);
}
}
+60
View File
@@ -0,0 +1,60 @@
import { type DateLib } from "./DateLib.js";
/**
* Represents a day displayed in the calendar.
*
* In DayPicker, a `CalendarDay` is a wrapper around a `Date` object that
* provides additional information about the day, such as whether it belongs to
* the displayed month.
*/
export declare class CalendarDay {
constructor(date: Date, displayMonth: Date, dateLib?: DateLib);
/**
* Utility functions for manipulating dates.
*
* @private
*/
readonly dateLib: DateLib;
/**
* Indicates whether the day does not belong to the displayed month.
*
* If `outside` is `true`, use `displayMonth` to determine the month to which
* the day belongs.
*/
readonly outside: boolean;
/**
* The month that is currently displayed in the calendar.
*
* This property is useful for determining if the day belongs to the same
* month as the displayed month, especially when `showOutsideDays` is
* enabled.
*/
readonly displayMonth: Date;
/** The date represented by this day. */
readonly date: Date;
/**
* Stable `yyyy-MM-dd` representation for reuse in keys/data attrs.
*
* @since V9.11.2
*/
readonly isoDate: string;
/**
* Stable `yyyy-MM` representation of the displayed month.
*
* @since V9.11.2
*/
readonly displayMonthId: string;
/**
* Stable `yyyy-MM` representation of the date's actual month.
*
* @since V9.11.2
*/
readonly dateMonthId: string;
/**
* Checks if this day is equal to another `CalendarDay`, considering both the
* date and the displayed month.
*
* @param day The `CalendarDay` to compare with.
* @returns `true` if the days are equal, otherwise `false`.
*/
isEqualTo(day: CalendarDay): boolean;
}
+30
View File
@@ -0,0 +1,30 @@
import { defaultDateLib } from "./DateLib.js";
/**
* Represents a day displayed in the calendar.
*
* In DayPicker, a `CalendarDay` is a wrapper around a `Date` object that
* provides additional information about the day, such as whether it belongs to
* the displayed month.
*/
export class CalendarDay {
constructor(date, displayMonth, dateLib = defaultDateLib) {
this.date = date;
this.displayMonth = displayMonth;
this.outside = Boolean(displayMonth && !dateLib.isSameMonth(date, displayMonth));
this.dateLib = dateLib;
this.isoDate = dateLib.format(date, "yyyy-MM-dd");
this.displayMonthId = dateLib.format(displayMonth, "yyyy-MM");
this.dateMonthId = dateLib.format(date, "yyyy-MM");
}
/**
* Checks if this day is equal to another `CalendarDay`, considering both the
* date and the displayed month.
*
* @param day The `CalendarDay` to compare with.
* @returns `true` if the days are equal, otherwise `false`.
*/
isEqualTo(day) {
return (this.dateLib.isSameDay(day.date, this.date) &&
this.dateLib.isSameMonth(day.displayMonth, this.displayMonth));
}
}
+14
View File
@@ -0,0 +1,14 @@
import type { CalendarWeek } from "./CalendarWeek.js";
/**
* Represents a month in a calendar year.
*
* A `CalendarMonth` contains the weeks within the month and the date of the
* month.
*/
export declare class CalendarMonth {
constructor(month: Date, weeks: CalendarWeek[]);
/** The date representing the first day of the month. */
date: Date;
/** The weeks that belong to this month. */
weeks: CalendarWeek[];
}
+12
View File
@@ -0,0 +1,12 @@
/**
* Represents a month in a calendar year.
*
* A `CalendarMonth` contains the weeks within the month and the date of the
* month.
*/
export class CalendarMonth {
constructor(month, weeks) {
this.date = month;
this.weeks = weeks;
}
}
+13
View File
@@ -0,0 +1,13 @@
import type { CalendarDay } from "./CalendarDay.js";
/**
* Represents a week in a calendar month.
*
* A `CalendarWeek` contains the days within the week and the week number.
*/
export declare class CalendarWeek {
constructor(weekNumber: number, days: CalendarDay[]);
/** The number of the week within the year. */
weekNumber: number;
/** The days that belong to this week. */
days: CalendarDay[];
}
+11
View File
@@ -0,0 +1,11 @@
/**
* Represents a week in a calendar month.
*
* A `CalendarWeek` contains the days within the week and the week number.
*/
export class CalendarWeek {
constructor(weekNumber, days) {
this.days = days;
this.weekNumber = weekNumber;
}
}
+407
View File
@@ -0,0 +1,407 @@
import type { FormatOptions as DateFnsFormatOptions, EndOfWeekOptions, GetMonthOptions, GetWeekOptions, GetYearOptions, Interval, StartOfWeekOptions } from "date-fns";
import type { Locale as DateFnsLocale } from "date-fns/locale";
import type { Labels, Numerals } from "../types/shared.js";
export type { Month as DateFnsMonth } from "date-fns";
/**
* Translations for DayPicker-specific labels.
*
* @since V9.12.0
*/
export type DayPickerLocaleLabels = {
[K in keyof Labels]?: string | Labels[K];
};
/**
* Locale type used by DayPicker.
*
* @since V9.12.0
*/
export interface DayPickerLocale extends DateFnsLocale {
/** Localized DayPicker-specific labels. */
labels?: DayPickerLocaleLabels;
}
export type Locale = DayPickerLocale;
/**
* @ignore
* @deprecated Use {@link DateLibOptions} instead.
*/
export type FormatOptions = DateLibOptions;
/**
* @ignore
* @deprecated Use {@link DateLibOptions} instead.
*/
export type LabelOptions = DateLibOptions;
/** Indicates the preferred ordering of month and year for localized labels. */
export type MonthYearOrder = "month-first" | "year-first";
/**
* The options for the `DateLib` class.
*
* Extends `date-fns` [format](https://date-fns.org/docs/format),
* [startOfWeek](https://date-fns.org/docs/startOfWeek) and
* [endOfWeek](https://date-fns.org/docs/endOfWeek) options.
*
* @since 9.2.0
*/
export interface DateLibOptions extends DateFnsFormatOptions, StartOfWeekOptions, EndOfWeekOptions {
/** A constructor for the `Date` object. */
Date?: typeof Date;
/** A locale to use for formatting dates. */
locale?: DayPickerLocale;
/**
* A time zone to use for dates.
*
* @since 9.5.0
*/
timeZone?: string;
/**
* The numbering system to use for formatting numbers.
*
* @since 9.5.0
*/
numerals?: Numerals;
}
/**
* A wrapper class around [date-fns](http://date-fns.org) that provides utility
* methods for date manipulation and formatting.
*
* @since 9.2.0
* @example
* const dateLib = new DateLib({ locale: es });
* const newDate = dateLib.addDays(new Date(), 5);
*/
export declare class DateLib {
/** The options for configuring the date library. */
readonly options: DateLibOptions;
/** Overrides for the default date library functions. */
readonly overrides?: Partial<typeof DateLib.prototype>;
/**
* Creates an instance of `DateLib`.
*
* @param options Configuration options for the date library.
* @param overrides Custom overrides for the date library functions.
*/
constructor(options?: DateLibOptions, overrides?: Partial<typeof DateLib.prototype>);
/**
* Generates a mapping of Arabic digits (0-9) to the target numbering system
* digits.
*
* @since 9.5.0
* @returns A record mapping Arabic digits to the target numerals.
*/
private getDigitMap;
/**
* Replaces Arabic digits in a string with the target numbering system digits.
*
* @since 9.5.0
* @param input The string containing Arabic digits.
* @returns The string with digits replaced.
*/
private replaceDigits;
/**
* Formats a number using the configured numbering system.
*
* @since 9.5.0
* @param value The number to format.
* @returns The formatted number as a string.
*/
formatNumber(value: number | string): string;
/**
* Returns the preferred ordering for month and year labels for the current
* locale.
*/
getMonthYearOrder(): MonthYearOrder;
/**
* Formats the month/year pair respecting locale conventions.
*
* @since 9.11.0
*/
formatMonthYear(date: Date): string;
private static readonly yearFirstLocales;
/**
* Reference to the built-in Date constructor.
*
* @deprecated Use `newDate()` or `today()`.
*/
Date: typeof Date;
/**
* Creates a new `Date` object representing today's date.
*
* @since 9.5.0
* @returns A `Date` object for today's date.
*/
today: () => Date;
/**
* Creates a new `Date` object with the specified year, month, and day.
*
* @since 9.5.0
* @param year The year.
* @param monthIndex The month (0-11).
* @param date The day of the month.
* @returns A new `Date` object.
*/
newDate: (year: number, monthIndex: number, date: number) => Date;
/**
* Adds the specified number of days to the given date.
*
* @param date The date to add days to.
* @param amount The number of days to add.
* @returns The new date with the days added.
*/
addDays: (date: Date, amount: number) => Date;
/**
* Adds the specified number of months to the given date.
*
* @param date The date to add months to.
* @param amount The number of months to add.
* @returns The new date with the months added.
*/
addMonths: (date: Date, amount: number) => Date;
/**
* Adds the specified number of weeks to the given date.
*
* @param date The date to add weeks to.
* @param amount The number of weeks to add.
* @returns The new date with the weeks added.
*/
addWeeks: (date: Date, amount: number) => Date;
/**
* Adds the specified number of years to the given date.
*
* @param date The date to add years to.
* @param amount The number of years to add.
* @returns The new date with the years added.
*/
addYears: (date: Date, amount: number) => Date;
/**
* Returns the number of calendar days between the given dates.
*
* @param dateLeft The later date.
* @param dateRight The earlier date.
* @returns The number of calendar days between the dates.
*/
differenceInCalendarDays: (dateLeft: Date, dateRight: Date) => number;
/**
* Returns the number of calendar months between the given dates.
*
* @param dateLeft The later date.
* @param dateRight The earlier date.
* @returns The number of calendar months between the dates.
*/
differenceInCalendarMonths: (dateLeft: Date, dateRight: Date) => number;
/**
* Returns the months between the given dates.
*
* @param interval The interval to get the months for.
*/
eachMonthOfInterval: (interval: Interval) => Date[];
/**
* Returns the years between the given dates.
*
* @since 9.11.1
* @param interval The interval to get the years for.
* @returns The array of years in the interval.
*/
eachYearOfInterval: (interval: Interval) => Date[];
/**
* Returns the end of the broadcast week for the given date.
*
* @param date The original date.
* @returns The end of the broadcast week.
*/
endOfBroadcastWeek: (date: Date) => Date;
/**
* Returns the end of the ISO week for the given date.
*
* @param date The original date.
* @returns The end of the ISO week.
*/
endOfISOWeek: (date: Date) => Date;
/**
* Returns the end of the month for the given date.
*
* @param date The original date.
* @returns The end of the month.
*/
endOfMonth: (date: Date) => Date;
/**
* Returns the end of the week for the given date.
*
* @param date The original date.
* @returns The end of the week.
*/
endOfWeek: (date: Date, options?: EndOfWeekOptions<Date>) => Date;
/**
* Returns the end of the year for the given date.
*
* @param date The original date.
* @returns The end of the year.
*/
endOfYear: (date: Date) => Date;
/**
* Formats the given date using the specified format string.
*
* @param date The date to format.
* @param formatStr The format string.
* @returns The formatted date string.
*/
format: (date: Date, formatStr: string, _options?: DateFnsFormatOptions) => string;
/**
* Returns the ISO week number for the given date.
*
* @param date The date to get the ISO week number for.
* @returns The ISO week number.
*/
getISOWeek: (date: Date) => number;
/**
* Returns the month of the given date.
*
* @param date The date to get the month for.
* @returns The month.
*/
getMonth: (date: Date, _options?: GetMonthOptions) => number;
/**
* Returns the year of the given date.
*
* @param date The date to get the year for.
* @returns The year.
*/
getYear: (date: Date, _options?: GetYearOptions) => number;
/**
* Returns the local week number for the given date.
*
* @param date The date to get the week number for.
* @returns The week number.
*/
getWeek: (date: Date, _options?: GetWeekOptions) => number;
/**
* Checks if the first date is after the second date.
*
* @param date The date to compare.
* @param dateToCompare The date to compare with.
* @returns True if the first date is after the second date.
*/
isAfter: (date: Date, dateToCompare: Date) => boolean;
/**
* Checks if the first date is before the second date.
*
* @param date The date to compare.
* @param dateToCompare The date to compare with.
* @returns True if the first date is before the second date.
*/
isBefore: (date: Date, dateToCompare: Date) => boolean;
/**
* Checks if the given value is a Date object.
*
* @param value The value to check.
* @returns True if the value is a Date object.
*/
isDate: (value: unknown) => value is Date;
/**
* Checks if the given dates are on the same day.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are on the same day.
*/
isSameDay: (dateLeft: Date, dateRight: Date) => boolean;
/**
* Checks if the given dates are in the same month.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are in the same month.
*/
isSameMonth: (dateLeft: Date, dateRight: Date) => boolean;
/**
* Checks if the given dates are in the same year.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are in the same year.
*/
isSameYear: (dateLeft: Date, dateRight: Date) => boolean;
/**
* Returns the latest date in the given array of dates.
*
* @param dates The array of dates to compare.
* @returns The latest date.
*/
max: (dates: Date[]) => Date;
/**
* Returns the earliest date in the given array of dates.
*
* @param dates The array of dates to compare.
* @returns The earliest date.
*/
min: (dates: Date[]) => Date;
/**
* Sets the month of the given date.
*
* @param date The date to set the month on.
* @param month The month to set (0-11).
* @returns The new date with the month set.
*/
setMonth: (date: Date, month: number) => Date;
/**
* Sets the year of the given date.
*
* @param date The date to set the year on.
* @param year The year to set.
* @returns The new date with the year set.
*/
setYear: (date: Date, year: number) => Date;
/**
* Returns the start of the broadcast week for the given date.
*
* @param date The original date.
* @returns The start of the broadcast week.
*/
startOfBroadcastWeek: (date: Date, _dateLib: DateLib) => Date;
/**
* Returns the start of the day for the given date.
*
* @param date The original date.
* @returns The start of the day.
*/
startOfDay: (date: Date) => Date;
/**
* Returns the start of the ISO week for the given date.
*
* @param date The original date.
* @returns The start of the ISO week.
*/
startOfISOWeek: (date: Date) => Date;
/**
* Returns the start of the month for the given date.
*
* @param date The original date.
* @returns The start of the month.
*/
startOfMonth: (date: Date) => Date;
/**
* Returns the start of the week for the given date.
*
* @param date The original date.
* @returns The start of the week.
*/
startOfWeek: (date: Date, _options?: StartOfWeekOptions) => Date;
/**
* Returns the start of the year for the given date.
*
* @param date The original date.
* @returns The start of the year.
*/
startOfYear: (date: Date) => Date;
}
/** The default locale (English). */
export { enUS as defaultLocale } from "../locale/en-US.js";
/**
* The default date library with English locale.
*
* @since 9.2.0
*/
export declare const defaultDateLib: DateLib;
/**
* @ignore
* @deprecated Use `defaultDateLib`.
*/
export declare const dateLib: DateLib;
+576
View File
@@ -0,0 +1,576 @@
import { TZDate } from "@date-fns/tz";
import { addDays, addMonths, addWeeks, addYears, differenceInCalendarDays, differenceInCalendarMonths, eachMonthOfInterval, eachYearOfInterval, endOfISOWeek, endOfMonth, endOfWeek, endOfYear, format, getISOWeek, getMonth, getWeek, getYear, isAfter, isBefore, isDate, isSameDay, isSameMonth, isSameYear, max, min, setMonth, setYear, startOfDay, startOfISOWeek, startOfMonth, startOfWeek, startOfYear, } from "date-fns";
import { endOfBroadcastWeek } from "../helpers/endOfBroadcastWeek.js";
import { startOfBroadcastWeek } from "../helpers/startOfBroadcastWeek.js";
import { enUS } from "../locale/en-US.js";
/**
* A wrapper class around [date-fns](http://date-fns.org) that provides utility
* methods for date manipulation and formatting.
*
* @since 9.2.0
* @example
* const dateLib = new DateLib({ locale: es });
* const newDate = dateLib.addDays(new Date(), 5);
*/
export class DateLib {
/**
* Creates an instance of `DateLib`.
*
* @param options Configuration options for the date library.
* @param overrides Custom overrides for the date library functions.
*/
constructor(options, overrides) {
/**
* Reference to the built-in Date constructor.
*
* @deprecated Use `newDate()` or `today()`.
*/
this.Date = Date;
/**
* Creates a new `Date` object representing today's date.
*
* @since 9.5.0
* @returns A `Date` object for today's date.
*/
this.today = () => {
if (this.overrides?.today) {
return this.overrides.today();
}
if (this.options.timeZone) {
return TZDate.tz(this.options.timeZone);
}
return new this.Date();
};
/**
* Creates a new `Date` object with the specified year, month, and day.
*
* @since 9.5.0
* @param year The year.
* @param monthIndex The month (0-11).
* @param date The day of the month.
* @returns A new `Date` object.
*/
this.newDate = (year, monthIndex, date) => {
if (this.overrides?.newDate) {
return this.overrides.newDate(year, monthIndex, date);
}
if (this.options.timeZone) {
return new TZDate(year, monthIndex, date, this.options.timeZone);
}
return new Date(year, monthIndex, date);
};
/**
* Adds the specified number of days to the given date.
*
* @param date The date to add days to.
* @param amount The number of days to add.
* @returns The new date with the days added.
*/
this.addDays = (date, amount) => {
return this.overrides?.addDays
? this.overrides.addDays(date, amount)
: addDays(date, amount);
};
/**
* Adds the specified number of months to the given date.
*
* @param date The date to add months to.
* @param amount The number of months to add.
* @returns The new date with the months added.
*/
this.addMonths = (date, amount) => {
return this.overrides?.addMonths
? this.overrides.addMonths(date, amount)
: addMonths(date, amount);
};
/**
* Adds the specified number of weeks to the given date.
*
* @param date The date to add weeks to.
* @param amount The number of weeks to add.
* @returns The new date with the weeks added.
*/
this.addWeeks = (date, amount) => {
return this.overrides?.addWeeks
? this.overrides.addWeeks(date, amount)
: addWeeks(date, amount);
};
/**
* Adds the specified number of years to the given date.
*
* @param date The date to add years to.
* @param amount The number of years to add.
* @returns The new date with the years added.
*/
this.addYears = (date, amount) => {
return this.overrides?.addYears
? this.overrides.addYears(date, amount)
: addYears(date, amount);
};
/**
* Returns the number of calendar days between the given dates.
*
* @param dateLeft The later date.
* @param dateRight The earlier date.
* @returns The number of calendar days between the dates.
*/
this.differenceInCalendarDays = (dateLeft, dateRight) => {
return this.overrides?.differenceInCalendarDays
? this.overrides.differenceInCalendarDays(dateLeft, dateRight)
: differenceInCalendarDays(dateLeft, dateRight);
};
/**
* Returns the number of calendar months between the given dates.
*
* @param dateLeft The later date.
* @param dateRight The earlier date.
* @returns The number of calendar months between the dates.
*/
this.differenceInCalendarMonths = (dateLeft, dateRight) => {
return this.overrides?.differenceInCalendarMonths
? this.overrides.differenceInCalendarMonths(dateLeft, dateRight)
: differenceInCalendarMonths(dateLeft, dateRight);
};
/**
* Returns the months between the given dates.
*
* @param interval The interval to get the months for.
*/
this.eachMonthOfInterval = (interval) => {
return this.overrides?.eachMonthOfInterval
? this.overrides.eachMonthOfInterval(interval)
: eachMonthOfInterval(interval);
};
/**
* Returns the years between the given dates.
*
* @since 9.11.1
* @param interval The interval to get the years for.
* @returns The array of years in the interval.
*/
this.eachYearOfInterval = (interval) => {
const years = this.overrides?.eachYearOfInterval
? this.overrides.eachYearOfInterval(interval)
: eachYearOfInterval(interval);
// Remove duplicates that may happen across DST transitions (e.g., "America/Sao_Paulo")
// See https://github.com/date-fns/tz/issues/72
const uniqueYears = new Set(years.map((d) => this.getYear(d)));
if (uniqueYears.size === years.length) {
// No duplicates, return as is
return years;
}
// Rebuild the array to ensure one date per year
const yearsArray = [];
uniqueYears.forEach((y) => {
yearsArray.push(new Date(y, 0, 1));
});
return yearsArray;
};
/**
* Returns the end of the broadcast week for the given date.
*
* @param date The original date.
* @returns The end of the broadcast week.
*/
this.endOfBroadcastWeek = (date) => {
return this.overrides?.endOfBroadcastWeek
? this.overrides.endOfBroadcastWeek(date)
: endOfBroadcastWeek(date, this);
};
/**
* Returns the end of the ISO week for the given date.
*
* @param date The original date.
* @returns The end of the ISO week.
*/
this.endOfISOWeek = (date) => {
return this.overrides?.endOfISOWeek
? this.overrides.endOfISOWeek(date)
: endOfISOWeek(date);
};
/**
* Returns the end of the month for the given date.
*
* @param date The original date.
* @returns The end of the month.
*/
this.endOfMonth = (date) => {
return this.overrides?.endOfMonth
? this.overrides.endOfMonth(date)
: endOfMonth(date);
};
/**
* Returns the end of the week for the given date.
*
* @param date The original date.
* @returns The end of the week.
*/
this.endOfWeek = (date, options) => {
return this.overrides?.endOfWeek
? this.overrides.endOfWeek(date, options)
: endOfWeek(date, this.options);
};
/**
* Returns the end of the year for the given date.
*
* @param date The original date.
* @returns The end of the year.
*/
this.endOfYear = (date) => {
return this.overrides?.endOfYear
? this.overrides.endOfYear(date)
: endOfYear(date);
};
/**
* Formats the given date using the specified format string.
*
* @param date The date to format.
* @param formatStr The format string.
* @returns The formatted date string.
*/
this.format = (date, formatStr, _options) => {
const formatted = this.overrides?.format
? this.overrides.format(date, formatStr, this.options)
: format(date, formatStr, this.options);
if (this.options.numerals && this.options.numerals !== "latn") {
return this.replaceDigits(formatted);
}
return formatted;
};
/**
* Returns the ISO week number for the given date.
*
* @param date The date to get the ISO week number for.
* @returns The ISO week number.
*/
this.getISOWeek = (date) => {
return this.overrides?.getISOWeek
? this.overrides.getISOWeek(date)
: getISOWeek(date);
};
/**
* Returns the month of the given date.
*
* @param date The date to get the month for.
* @returns The month.
*/
this.getMonth = (date, _options) => {
return this.overrides?.getMonth
? this.overrides.getMonth(date, this.options)
: getMonth(date, this.options);
};
/**
* Returns the year of the given date.
*
* @param date The date to get the year for.
* @returns The year.
*/
this.getYear = (date, _options) => {
return this.overrides?.getYear
? this.overrides.getYear(date, this.options)
: getYear(date, this.options);
};
/**
* Returns the local week number for the given date.
*
* @param date The date to get the week number for.
* @returns The week number.
*/
this.getWeek = (date, _options) => {
return this.overrides?.getWeek
? this.overrides.getWeek(date, this.options)
: getWeek(date, this.options);
};
/**
* Checks if the first date is after the second date.
*
* @param date The date to compare.
* @param dateToCompare The date to compare with.
* @returns True if the first date is after the second date.
*/
this.isAfter = (date, dateToCompare) => {
return this.overrides?.isAfter
? this.overrides.isAfter(date, dateToCompare)
: isAfter(date, dateToCompare);
};
/**
* Checks if the first date is before the second date.
*
* @param date The date to compare.
* @param dateToCompare The date to compare with.
* @returns True if the first date is before the second date.
*/
this.isBefore = (date, dateToCompare) => {
return this.overrides?.isBefore
? this.overrides.isBefore(date, dateToCompare)
: isBefore(date, dateToCompare);
};
/**
* Checks if the given value is a Date object.
*
* @param value The value to check.
* @returns True if the value is a Date object.
*/
this.isDate = (value) => {
return this.overrides?.isDate
? this.overrides.isDate(value)
: isDate(value);
};
/**
* Checks if the given dates are on the same day.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are on the same day.
*/
this.isSameDay = (dateLeft, dateRight) => {
return this.overrides?.isSameDay
? this.overrides.isSameDay(dateLeft, dateRight)
: isSameDay(dateLeft, dateRight);
};
/**
* Checks if the given dates are in the same month.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are in the same month.
*/
this.isSameMonth = (dateLeft, dateRight) => {
return this.overrides?.isSameMonth
? this.overrides.isSameMonth(dateLeft, dateRight)
: isSameMonth(dateLeft, dateRight);
};
/**
* Checks if the given dates are in the same year.
*
* @param dateLeft The first date to compare.
* @param dateRight The second date to compare.
* @returns True if the dates are in the same year.
*/
this.isSameYear = (dateLeft, dateRight) => {
return this.overrides?.isSameYear
? this.overrides.isSameYear(dateLeft, dateRight)
: isSameYear(dateLeft, dateRight);
};
/**
* Returns the latest date in the given array of dates.
*
* @param dates The array of dates to compare.
* @returns The latest date.
*/
this.max = (dates) => {
return this.overrides?.max ? this.overrides.max(dates) : max(dates);
};
/**
* Returns the earliest date in the given array of dates.
*
* @param dates The array of dates to compare.
* @returns The earliest date.
*/
this.min = (dates) => {
return this.overrides?.min ? this.overrides.min(dates) : min(dates);
};
/**
* Sets the month of the given date.
*
* @param date The date to set the month on.
* @param month The month to set (0-11).
* @returns The new date with the month set.
*/
this.setMonth = (date, month) => {
return this.overrides?.setMonth
? this.overrides.setMonth(date, month)
: setMonth(date, month);
};
/**
* Sets the year of the given date.
*
* @param date The date to set the year on.
* @param year The year to set.
* @returns The new date with the year set.
*/
this.setYear = (date, year) => {
return this.overrides?.setYear
? this.overrides.setYear(date, year)
: setYear(date, year);
};
/**
* Returns the start of the broadcast week for the given date.
*
* @param date The original date.
* @returns The start of the broadcast week.
*/
this.startOfBroadcastWeek = (date, _dateLib) => {
return this.overrides?.startOfBroadcastWeek
? this.overrides.startOfBroadcastWeek(date, this)
: startOfBroadcastWeek(date, this);
};
/**
* Returns the start of the day for the given date.
*
* @param date The original date.
* @returns The start of the day.
*/
this.startOfDay = (date) => {
return this.overrides?.startOfDay
? this.overrides.startOfDay(date)
: startOfDay(date);
};
/**
* Returns the start of the ISO week for the given date.
*
* @param date The original date.
* @returns The start of the ISO week.
*/
this.startOfISOWeek = (date) => {
return this.overrides?.startOfISOWeek
? this.overrides.startOfISOWeek(date)
: startOfISOWeek(date);
};
/**
* Returns the start of the month for the given date.
*
* @param date The original date.
* @returns The start of the month.
*/
this.startOfMonth = (date) => {
return this.overrides?.startOfMonth
? this.overrides.startOfMonth(date)
: startOfMonth(date);
};
/**
* Returns the start of the week for the given date.
*
* @param date The original date.
* @returns The start of the week.
*/
this.startOfWeek = (date, _options) => {
return this.overrides?.startOfWeek
? this.overrides.startOfWeek(date, this.options)
: startOfWeek(date, this.options);
};
/**
* Returns the start of the year for the given date.
*
* @param date The original date.
* @returns The start of the year.
*/
this.startOfYear = (date) => {
return this.overrides?.startOfYear
? this.overrides.startOfYear(date)
: startOfYear(date);
};
this.options = { locale: enUS, ...options };
this.overrides = overrides;
}
/**
* Generates a mapping of Arabic digits (0-9) to the target numbering system
* digits.
*
* @since 9.5.0
* @returns A record mapping Arabic digits to the target numerals.
*/
getDigitMap() {
const { numerals = "latn" } = this.options;
// Use Intl.NumberFormat to create a formatter with the specified numbering system
const formatter = new Intl.NumberFormat("en-US", {
numberingSystem: numerals,
});
// Map Arabic digits (0-9) to the target numerals
const digitMap = {};
for (let i = 0; i < 10; i++) {
digitMap[i.toString()] = formatter.format(i);
}
return digitMap;
}
/**
* Replaces Arabic digits in a string with the target numbering system digits.
*
* @since 9.5.0
* @param input The string containing Arabic digits.
* @returns The string with digits replaced.
*/
replaceDigits(input) {
const digitMap = this.getDigitMap();
return input.replace(/\d/g, (digit) => digitMap[digit] || digit);
}
/**
* Formats a number using the configured numbering system.
*
* @since 9.5.0
* @param value The number to format.
* @returns The formatted number as a string.
*/
formatNumber(value) {
return this.replaceDigits(value.toString());
}
/**
* Returns the preferred ordering for month and year labels for the current
* locale.
*/
getMonthYearOrder() {
const code = this.options.locale?.code;
if (!code) {
return "month-first";
}
return DateLib.yearFirstLocales.has(code) ? "year-first" : "month-first";
}
/**
* Formats the month/year pair respecting locale conventions.
*
* @since 9.11.0
*/
formatMonthYear(date) {
const { locale, timeZone, numerals } = this.options;
const localeCode = locale?.code;
if (localeCode && DateLib.yearFirstLocales.has(localeCode)) {
try {
const intl = new Intl.DateTimeFormat(localeCode, {
month: "long",
year: "numeric",
timeZone,
numberingSystem: numerals,
});
const formatted = intl.format(date);
return formatted;
}
catch {
// Fallback to date-fns formatting below.
}
}
const pattern = this.getMonthYearOrder() === "year-first" ? "y LLLL" : "LLLL y";
return this.format(date, pattern);
}
}
DateLib.yearFirstLocales = new Set([
"eu",
"hu",
"ja",
"ja-Hira",
"ja-JP",
"ko",
"ko-KR",
"lt",
"lt-LT",
"lv",
"lv-LV",
"mn",
"mn-MN",
"zh",
"zh-CN",
"zh-HK",
"zh-TW",
]);
/** The default locale (English). */
export { enUS as defaultLocale } from "../locale/en-US.js";
/**
* The default date library with English locale.
*
* @since 9.2.0
*/
export const defaultDateLib = new DateLib();
/**
* @ignore
* @deprecated Use `defaultDateLib`.
*/
export const dateLib = defaultDateLib;
+4
View File
@@ -0,0 +1,4 @@
export * from "./CalendarDay.js";
export * from "./CalendarMonth.js";
export * from "./CalendarWeek.js";
export * from "./DateLib.js";
+4
View File
@@ -0,0 +1,4 @@
export * from "./CalendarDay.js";
export * from "./CalendarMonth.js";
export * from "./CalendarWeek.js";
export * from "./DateLib.js";
+9
View File
@@ -0,0 +1,9 @@
import React, { type ButtonHTMLAttributes } from "react";
/**
* Render the button elements in the calendar.
*
* @private
* @deprecated Use `PreviousMonthButton` or `@link NextMonthButton` instead.
*/
export declare function Button(props: ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
export type ButtonProps = Parameters<typeof Button>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the button elements in the calendar.
*
* @private
* @deprecated Use `PreviousMonthButton` or `@link NextMonthButton` instead.
*/
export function Button(props) {
return React.createElement("button", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render the label in the month caption.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function CaptionLabel(props: HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
export type CaptionLabelProps = Parameters<typeof CaptionLabel>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the label in the month caption.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function CaptionLabel(props) {
return React.createElement("span", { ...props });
}
+21
View File
@@ -0,0 +1,21 @@
import React from "react";
/**
* Render the chevron icon used in the navigation buttons and dropdowns.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Chevron(props: {
className?: string;
/**
* The size of the chevron.
*
* @defaultValue 24
*/
size?: number;
/** Set to `true` to disable the chevron. */
disabled?: boolean;
/** The orientation of the chevron. */
orientation?: "up" | "down" | "left" | "right";
}): React.JSX.Element;
export type ChevronProps = Parameters<typeof Chevron>[0];
+17
View File
@@ -0,0 +1,17 @@
import React from "react";
/**
* Render the chevron icon used in the navigation buttons and dropdowns.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Chevron(props) {
const { size = 24, orientation = "left", className } = props;
return (
// biome-ignore lint/a11y/noSvgWithoutTitle: handled by the parent component
React.createElement("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24" },
orientation === "up" && (React.createElement("polygon", { points: "6.77 17 12.5 11.43 18.24 17 20 15.28 12.5 8 5 15.28" })),
orientation === "down" && (React.createElement("polygon", { points: "6.77 8 12.5 13.57 18.24 8 20 9.72 12.5 17 5 9.72" })),
orientation === "left" && (React.createElement("polygon", { points: "16 18.112 9.81111111 12 16 5.87733333 14.0888889 4 6 12 14.0888889 20" })),
orientation === "right" && (React.createElement("polygon", { points: "8 18.112 14.18888889 12 8 5.87733333 9.91111111 4 18 12 9.91111111 20" }))));
}
+20
View File
@@ -0,0 +1,20 @@
import React, { type HTMLAttributes } from "react";
import type { CalendarDay } from "../classes/index.js";
import type { Modifiers } from "../types/index.js";
/**
* Render a grid cell for a specific day in the calendar.
*
* Handles interaction and focus for the day. If you only need to change the
* content of the day cell, consider swapping the `DayButton` component
* instead.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Day(props: {
/** The day to render. */
day: CalendarDay;
/** The modifiers to apply to the day. */
modifiers: Modifiers;
} & HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type DayProps = Parameters<typeof Day>[0];
+15
View File
@@ -0,0 +1,15 @@
import React from "react";
/**
* Render a grid cell for a specific day in the calendar.
*
* Handles interaction and focus for the day. If you only need to change the
* content of the day cell, consider swapping the `DayButton` component
* instead.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Day(props) {
const { day, modifiers, ...tdProps } = props;
return React.createElement("td", { ...tdProps });
}
+16
View File
@@ -0,0 +1,16 @@
import React, { type ButtonHTMLAttributes } from "react";
import type { CalendarDay } from "../classes/index.js";
import type { Modifiers } from "../types/index.js";
/**
* Render a button for a specific day in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function DayButton(props: {
/** The day to render. */
day: CalendarDay;
/** The modifiers to apply to the day. */
modifiers: Modifiers;
} & ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
export type DayButtonProps = Parameters<typeof DayButton>[0];
+16
View File
@@ -0,0 +1,16 @@
import React from "react";
/**
* Render a button for a specific day in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function DayButton(props) {
const { day, modifiers, ...buttonProps } = props;
const ref = React.useRef(null);
React.useEffect(() => {
if (modifiers.focused)
ref.current?.focus();
}, [modifiers.focused]);
return React.createElement("button", { ref: ref, ...buttonProps });
}
+32
View File
@@ -0,0 +1,32 @@
import React, { type SelectHTMLAttributes } from "react";
import type { ClassNames, CustomComponents } from "../types/index.js";
/** An option to use in the dropdown. Maps to the `<option>` HTML element. */
export type DropdownOption = {
/** The value of the option. */
value: number;
/** The label of the option. */
label: string;
/** Whether the dropdown option is disabled (e.g., out of the calendar range). */
disabled: boolean;
};
/**
* Render a dropdown component for navigation in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Dropdown(props: {
/**
* @deprecated Use {@link useDayPicker} hook to get the list of internal
* components.
*/
components: CustomComponents;
/**
* @deprecated Use {@link useDayPicker} hook to get the list of internal
* class names.
*/
classNames: ClassNames;
/** The options to display in the dropdown. */
options?: DropdownOption[] | undefined;
} & Omit<SelectHTMLAttributes<HTMLSelectElement>, "children">): React.JSX.Element;
export type DropdownProps = Parameters<typeof Dropdown>[0];
+18
View File
@@ -0,0 +1,18 @@
import React from "react";
import { UI } from "../UI.js";
/**
* Render a dropdown component for navigation in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Dropdown(props) {
const { options, className, components, classNames, ...selectProps } = props;
const cssClassSelect = [classNames[UI.Dropdown], className].join(" ");
const selectedOption = options?.find(({ value }) => value === selectProps.value);
return (React.createElement("span", { "data-disabled": selectProps.disabled, className: classNames[UI.DropdownRoot] },
React.createElement(components.Select, { className: cssClassSelect, ...selectProps }, options?.map(({ value, label, disabled }) => (React.createElement(components.Option, { key: value, value: value, disabled: disabled }, label)))),
React.createElement("span", { className: classNames[UI.CaptionLabel], "aria-hidden": true },
selectedOption?.label,
React.createElement(components.Chevron, { orientation: "down", size: 18, className: classNames[UI.Chevron] }))));
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render the navigation dropdowns for the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function DropdownNav(props: HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type DropdownNavProps = Parameters<typeof DropdownNav>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the navigation dropdowns for the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function DropdownNav(props) {
return React.createElement("div", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render the footer of the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Footer(props: HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type FooterProps = Parameters<typeof Footer>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the footer of the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Footer(props) {
return React.createElement("div", { ...props });
}
+16
View File
@@ -0,0 +1,16 @@
import React, { type HTMLAttributes } from "react";
import type { CalendarMonth } from "../classes/CalendarMonth.js";
/**
* Render the grid with the weekday header row and the weeks for a specific
* month.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Month(props: {
/** The month to display in the grid. */
calendarMonth: CalendarMonth;
/** The index of the month being displayed. */
displayIndex: number;
} & HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type MonthProps = Parameters<typeof Month>[0];
+12
View File
@@ -0,0 +1,12 @@
import React from "react";
/**
* Render the grid with the weekday header row and the weeks for a specific
* month.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Month(props) {
const { calendarMonth, displayIndex, ...divProps } = props;
return React.createElement("div", { ...divProps }, props.children);
}
+15
View File
@@ -0,0 +1,15 @@
import React, { type HTMLAttributes } from "react";
import type { CalendarMonth } from "../classes/index.js";
/**
* Render the caption for a month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function MonthCaption(props: {
/** The month to display in the caption. */
calendarMonth: CalendarMonth;
/** The index of the month being displayed. */
displayIndex: number;
} & HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type MonthCaptionProps = Parameters<typeof MonthCaption>[0];
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
/**
* Render the caption for a month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function MonthCaption(props) {
const { calendarMonth, displayIndex, ...divProps } = props;
return React.createElement("div", { ...divProps });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type TableHTMLAttributes } from "react";
/**
* Render the grid of days for a specific month.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function MonthGrid(props: TableHTMLAttributes<HTMLTableElement>): React.JSX.Element;
export type MonthGridProps = Parameters<typeof MonthGrid>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the grid of days for a specific month.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function MonthGrid(props) {
return React.createElement("table", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render a container wrapping the month grids.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Months(props: HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type MonthsProps = Parameters<typeof Months>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render a container wrapping the month grids.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Months(props) {
return React.createElement("div", { ...props });
}
@@ -0,0 +1,9 @@
import React from "react";
import type { DropdownProps } from "./Dropdown.js";
/**
* Render a dropdown to navigate between months in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function MonthsDropdown(props: DropdownProps): React.JSX.Element;
+12
View File
@@ -0,0 +1,12 @@
import React from "react";
import { useDayPicker } from "../useDayPicker.js";
/**
* Render a dropdown to navigate between months in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function MonthsDropdown(props) {
const { components } = useDayPicker();
return React.createElement(components.Dropdown, { ...props });
}
+18
View File
@@ -0,0 +1,18 @@
import React, { type HTMLAttributes, type MouseEventHandler } from "react";
/**
* Render the navigation toolbar with buttons to navigate between months.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Nav(props: {
/** Handler for the previous month button click. */
onPreviousClick?: MouseEventHandler<HTMLButtonElement>;
/** Handler for the next month button click. */
onNextClick?: MouseEventHandler<HTMLButtonElement>;
/** The date of the previous month, if available. */
previousMonth?: Date | undefined;
/** The date of the next month, if available. */
nextMonth?: Date | undefined;
} & HTMLAttributes<HTMLElement>): React.JSX.Element;
export type NavProps = Parameters<typeof Nav>[0];
+28
View File
@@ -0,0 +1,28 @@
import React, { useCallback, } from "react";
import { UI } from "../UI.js";
import { useDayPicker } from "../useDayPicker.js";
/**
* Render the navigation toolbar with buttons to navigate between months.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Nav(props) {
const { onPreviousClick, onNextClick, previousMonth, nextMonth, ...navProps } = props;
const { components, classNames, labels: { labelPrevious, labelNext }, } = useDayPicker();
const handleNextClick = useCallback((e) => {
if (nextMonth) {
onNextClick?.(e);
}
}, [nextMonth, onNextClick]);
const handlePreviousClick = useCallback((e) => {
if (previousMonth) {
onPreviousClick?.(e);
}
}, [previousMonth, onPreviousClick]);
return (React.createElement("nav", { ...navProps },
React.createElement(components.PreviousMonthButton, { type: "button", className: classNames[UI.PreviousMonthButton], tabIndex: previousMonth ? undefined : -1, "aria-disabled": previousMonth ? undefined : true, "aria-label": labelPrevious(previousMonth), onClick: handlePreviousClick },
React.createElement(components.Chevron, { disabled: previousMonth ? undefined : true, className: classNames[UI.Chevron], orientation: "left" })),
React.createElement(components.NextMonthButton, { type: "button", className: classNames[UI.NextMonthButton], tabIndex: nextMonth ? undefined : -1, "aria-disabled": nextMonth ? undefined : true, "aria-label": labelNext(nextMonth), onClick: handleNextClick },
React.createElement(components.Chevron, { disabled: nextMonth ? undefined : true, orientation: "right", className: classNames[UI.Chevron] }))));
}
@@ -0,0 +1,9 @@
import React, { type ButtonHTMLAttributes } from "react";
/**
* Render the button to navigate to the next month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function NextMonthButton(props: ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
export type NextMonthButtonProps = Parameters<typeof NextMonthButton>[0];
+12
View File
@@ -0,0 +1,12 @@
import React from "react";
import { useDayPicker } from "../useDayPicker.js";
/**
* Render the button to navigate to the next month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function NextMonthButton(props) {
const { components } = useDayPicker();
return React.createElement(components.Button, { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type OptionHTMLAttributes } from "react";
/**
* Render an `option` element.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Option(props: OptionHTMLAttributes<HTMLOptionElement>): React.JSX.Element;
export type OptionProps = Parameters<typeof Option>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render an `option` element.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Option(props) {
return React.createElement("option", { ...props });
}
@@ -0,0 +1,9 @@
import React, { type ButtonHTMLAttributes } from "react";
/**
* Render the button to navigate to the previous month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function PreviousMonthButton(props: ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
export type PreviousMonthButtonProps = Parameters<typeof PreviousMonthButton>[0];
@@ -0,0 +1,12 @@
import React from "react";
import { useDayPicker } from "../useDayPicker.js";
/**
* Render the button to navigate to the previous month in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function PreviousMonthButton(props) {
const { components } = useDayPicker();
return React.createElement(components.Button, { ...props });
}
+12
View File
@@ -0,0 +1,12 @@
import React, { type HTMLAttributes, type Ref } from "react";
/**
* Render the root element of the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Root(props: {
/** Ref for the root element, used when `animate` is `true`. */
rootRef?: Ref<HTMLDivElement>;
} & HTMLAttributes<HTMLDivElement>): React.JSX.Element;
export type RootProps = Parameters<typeof Root>[0];
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
/**
* Render the root element of the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Root(props) {
const { rootRef, ...rest } = props;
return React.createElement("div", { ...rest, ref: rootRef });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type SelectHTMLAttributes } from "react";
/**
* Render a `select` element.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Select(props: SelectHTMLAttributes<HTMLSelectElement>): React.JSX.Element;
export type SelectProps = Parameters<typeof Select>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render a `select` element.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Select(props) {
return React.createElement("select", { ...props });
}
+13
View File
@@ -0,0 +1,13 @@
import React, { type HTMLAttributes } from "react";
import type { CalendarWeek } from "../classes/index.js";
/**
* Render a table row representing a week in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Week(props: {
/** The week to render. */
week: CalendarWeek;
} & HTMLAttributes<HTMLTableRowElement>): React.JSX.Element;
export type WeekProps = Parameters<typeof Week>[0];
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
/**
* Render a table row representing a week in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Week(props) {
const { week, ...trProps } = props;
return React.createElement("tr", { ...trProps });
}
+13
View File
@@ -0,0 +1,13 @@
import React, { type ThHTMLAttributes } from "react";
import type { CalendarWeek } from "../classes/index.js";
/**
* Render a table cell displaying the number of the week.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function WeekNumber(props: {
/** The week to display. */
week: CalendarWeek;
} & ThHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
export type WeekNumberProps = Parameters<typeof WeekNumber>[0];
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
/**
* Render a table cell displaying the number of the week.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function WeekNumber(props) {
const { week, ...thProps } = props;
return React.createElement("th", { ...thProps });
}
@@ -0,0 +1,9 @@
import React, { type ThHTMLAttributes } from "react";
/**
* Render the header cell for the week numbers column.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function WeekNumberHeader(props: ThHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
export type WeekNumberHeaderProps = Parameters<typeof WeekNumberHeader>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the header cell for the week numbers column.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function WeekNumberHeader(props) {
return React.createElement("th", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type ThHTMLAttributes } from "react";
/**
* Render a table header cell with the name of a weekday (e.g., "Mo", "Tu").
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Weekday(props: ThHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
export type WeekdayProps = Parameters<typeof Weekday>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render a table header cell with the name of a weekday (e.g., "Mo", "Tu").
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Weekday(props) {
return React.createElement("th", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render the table row containing the weekday names.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Weekdays(props: HTMLAttributes<HTMLTableRowElement>): React.JSX.Element;
export type WeekdaysProps = Parameters<typeof Weekdays>[0];
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
/**
* Render the table row containing the weekday names.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Weekdays(props) {
return (React.createElement("thead", { "aria-hidden": true },
React.createElement("tr", { ...props })));
}
+9
View File
@@ -0,0 +1,9 @@
import React, { type HTMLAttributes } from "react";
/**
* Render the container for the weeks in the month grid.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function Weeks(props: HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
export type WeeksProps = Parameters<typeof Weeks>[0];
+10
View File
@@ -0,0 +1,10 @@
import React from "react";
/**
* Render the container for the weeks in the month grid.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function Weeks(props) {
return React.createElement("tbody", { ...props });
}
+9
View File
@@ -0,0 +1,9 @@
import React from "react";
import type { DropdownProps } from "./Dropdown.js";
/**
* Render a dropdown to navigate between years in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export declare function YearsDropdown(props: DropdownProps): React.JSX.Element;
+12
View File
@@ -0,0 +1,12 @@
import React from "react";
import { useDayPicker } from "../useDayPicker.js";
/**
* Render a dropdown to navigate between years in the calendar.
*
* @group Components
* @see https://daypicker.dev/guides/custom-components
*/
export function YearsDropdown(props) {
const { components } = useDayPicker();
return React.createElement(components.Dropdown, { ...props });
}
@@ -0,0 +1,26 @@
export * from "./Button.js";
export * from "./CaptionLabel.js";
export * from "./Chevron.js";
export * from "./Day.js";
export * from "./DayButton.js";
export * from "./Dropdown.js";
export * from "./DropdownNav.js";
export * from "./Footer.js";
export * from "./Month.js";
export * from "./MonthCaption.js";
export * from "./MonthGrid.js";
export * from "./Months.js";
export * from "./MonthsDropdown.js";
export * from "./Nav.js";
export * from "./NextMonthButton.js";
export * from "./Option.js";
export * from "./PreviousMonthButton.js";
export * from "./Root.js";
export * from "./Select.js";
export * from "./Week.js";
export * from "./Weekday.js";
export * from "./Weekdays.js";
export * from "./WeekNumber.js";
export * from "./WeekNumberHeader.js";
export * from "./Weeks.js";
export * from "./YearsDropdown.js";
+26
View File
@@ -0,0 +1,26 @@
export * from "./Button.js";
export * from "./CaptionLabel.js";
export * from "./Chevron.js";
export * from "./Day.js";
export * from "./DayButton.js";
export * from "./Dropdown.js";
export * from "./DropdownNav.js";
export * from "./Footer.js";
export * from "./Month.js";
export * from "./MonthCaption.js";
export * from "./MonthGrid.js";
export * from "./Months.js";
export * from "./MonthsDropdown.js";
export * from "./Nav.js";
export * from "./NextMonthButton.js";
export * from "./Option.js";
export * from "./PreviousMonthButton.js";
export * from "./Root.js";
export * from "./Select.js";
export * from "./Week.js";
export * from "./Weekday.js";
export * from "./Weekdays.js";
export * from "./WeekNumber.js";
export * from "./WeekNumberHeader.js";
export * from "./Weeks.js";
export * from "./YearsDropdown.js";
+44
View File
@@ -0,0 +1,44 @@
import type { Locale } from "date-fns";
import React from "react";
import { DateLib, type DateLibOptions } from "../index.js";
import type { DayPickerProps } from "../types/props.js";
/**
* Render the Ethiopic calendar.
*
* Defaults:
*
* - `locale`: `am-ET` (Amharic) via an Intl-backed date-fns locale
* - `numerals`: `geez` (Ethiopic digits)
*
* Notes:
*
* - Weekday names are taken from `Intl.DateTimeFormat(locale.code)`.
* - Month names are Amharic by default; they switch to Latin transliteration when
* `locale.code` starts with `en` or when `numerals` is `latn`.
* - Time tokens like `hh:mm a` are formatted via `Intl.DateTimeFormat` using the
* provided `locale`.
*
* @see https://daypicker.dev/docs/localization#ethiopic-calendar
*/
export declare function DayPicker(props: DayPickerProps & {
/**
* The locale to use in the calendar.
*
* @default `am-ET`
*/
locale?: Locale;
/**
* The numeral system to use when formatting dates.
*
* - `latn`: Latin (Western Arabic)
* - `geez`: Ge'ez (Ethiopic numerals)
*
* @defaultValue `geez` (Ethiopic numerals)
* @see https://daypicker.dev/docs/translation#numeral-systems
*/
numerals?: DayPickerProps["numerals"];
}): React.JSX.Element;
/** Returns the date library used in the calendar. */
export declare const getDateLib: (options?: DateLibOptions) => DateLib;
export { amET } from "../locale/am-ET.js";
export { enUS } from "../locale/en-US.js";
+34
View File
@@ -0,0 +1,34 @@
import React from "react";
import { DateLib, DayPicker as DayPickerComponent, } from "../index.js";
import amET from "../locale/am-ET.js";
import * as ethiopicDateLib from "./lib/index.js";
/**
* Render the Ethiopic calendar.
*
* Defaults:
*
* - `locale`: `am-ET` (Amharic) via an Intl-backed date-fns locale
* - `numerals`: `geez` (Ethiopic digits)
*
* Notes:
*
* - Weekday names are taken from `Intl.DateTimeFormat(locale.code)`.
* - Month names are Amharic by default; they switch to Latin transliteration when
* `locale.code` starts with `en` or when `numerals` is `latn`.
* - Time tokens like `hh:mm a` are formatted via `Intl.DateTimeFormat` using the
* provided `locale`.
*
* @see https://daypicker.dev/docs/localization#ethiopic-calendar
*/
export function DayPicker(props) {
return (React.createElement(DayPickerComponent, { ...props, locale: props.locale ?? amET, numerals: props.numerals ?? "geez",
// Pass overrides, not a DateLib instance
dateLib: ethiopicDateLib }));
}
/** Returns the date library used in the calendar. */
export const getDateLib = (options) => {
return new DateLib(options, ethiopicDateLib);
};
// Export a minimal Amharic (Ethiopia) date-fns locale that uses Intl
export { amET } from "../locale/am-ET.js";
export { enUS } from "../locale/en-US.js";
+9
View File
@@ -0,0 +1,9 @@
/**
* Adds the specified number of months to the given Ethiopian date. Handles
* month overflow and year boundaries correctly.
*
* @param date - The starting gregorian date
* @param amount - The number of months to add (can be negative)
* @returns A new gregorian date with the months added
*/
export declare function addMonths(date: Date, amount: number): Date;
+24
View File
@@ -0,0 +1,24 @@
import { daysInMonth } from "../utils/daysInMonth.js";
import { toEthiopicDate, toGregorianDate } from "../utils/index.js";
/**
* Adds the specified number of months to the given Ethiopian date. Handles
* month overflow and year boundaries correctly.
*
* @param date - The starting gregorian date
* @param amount - The number of months to add (can be negative)
* @returns A new gregorian date with the months added
*/
export function addMonths(date, amount) {
const { year, month, day } = toEthiopicDate(date);
let newMonth = month + amount;
const yearAdjustment = Math.floor((newMonth - 1) / 13);
newMonth = ((newMonth - 1) % 13) + 1;
if (newMonth < 1) {
newMonth += 13;
}
const newYear = year + yearAdjustment;
// Adjust day if it exceeds the month length
const monthLength = daysInMonth(newMonth, newYear);
const newDay = Math.min(day, monthLength);
return toGregorianDate({ year: newYear, month: newMonth, day: newDay });
}
+9
View File
@@ -0,0 +1,9 @@
/**
* Adds the specified number of years to the given Ethiopian date. Handles leap
* year transitions for Pagume month.
*
* @param date - The starting gregorian date
* @param amount - The number of years to add (can be negative)
* @returns A new gregorian date with the years added
*/
export declare function addYears(date: Date, amount: number): Date;
+23
View File
@@ -0,0 +1,23 @@
import { isEthiopicLeapYear, toEthiopicDate, toGregorianDate, } from "../utils/index.js";
/**
* Adds the specified number of years to the given Ethiopian date. Handles leap
* year transitions for Pagume month.
*
* @param date - The starting gregorian date
* @param amount - The number of years to add (can be negative)
* @returns A new gregorian date with the years added
*/
export function addYears(date, amount) {
const etDate = toEthiopicDate(date);
const day = isEthiopicLeapYear(etDate.year) &&
etDate.month === 13 &&
etDate.day === 6 &&
amount % 4 !== 0
? 5
: etDate.day;
return toGregorianDate({
month: etDate.month,
day: day,
year: etDate.year + amount,
});
}
@@ -0,0 +1,8 @@
/**
* Difference in calendar months
*
* @param {Date} dateLeft - The later date
* @param {Date} dateRight - The earlier date
* @returns {number} The number of calendar months between the two dates
*/
export declare function differenceInCalendarMonths(dateLeft: Date, dateRight: Date): number;
@@ -0,0 +1,14 @@
import { toEthiopicDate } from "../utils/index.js";
/**
* Difference in calendar months
*
* @param {Date} dateLeft - The later date
* @param {Date} dateRight - The earlier date
* @returns {number} The number of calendar months between the two dates
*/
export function differenceInCalendarMonths(dateLeft, dateRight) {
const ethiopicLeft = toEthiopicDate(dateLeft);
const ethiopicRight = toEthiopicDate(dateRight);
return ((ethiopicLeft.year - ethiopicRight.year) * 13 +
(ethiopicLeft.month - ethiopicRight.month));
}
@@ -0,0 +1,11 @@
import type { Interval } from "date-fns";
/**
* Each month of an interval
*
* @param {Object} interval - The interval object
* @param {Date} interval.start - The start date of the interval
* @param {Date} interval.end - The end date of the interval
* @returns {Date[]} An array of dates representing the start of each month in
* the interval
*/
export declare function eachMonthOfInterval(interval: Interval): Date[];
@@ -0,0 +1,27 @@
import { toEthiopicDate, toGregorianDate } from "../utils/index.js";
/**
* Each month of an interval
*
* @param {Object} interval - The interval object
* @param {Date} interval.start - The start date of the interval
* @param {Date} interval.end - The end date of the interval
* @returns {Date[]} An array of dates representing the start of each month in
* the interval
*/
export function eachMonthOfInterval(interval) {
const start = toEthiopicDate(new Date(interval.start));
const end = toEthiopicDate(new Date(interval.end));
const dates = [];
let currentYear = start.year;
let currentMonth = start.month;
while (currentYear < end.year ||
(currentYear === end.year && currentMonth <= end.month)) {
dates.push(toGregorianDate({ year: currentYear, month: currentMonth, day: 1 }));
currentMonth++;
if (currentMonth > 13) {
currentMonth = 1;
currentYear++;
}
}
return dates;
}
@@ -0,0 +1,7 @@
import type { Interval } from "date-fns";
/**
* Returns the start of each Ethiopic year included in the given interval.
*
* @param interval The interval whose years should be returned.
*/
export declare function eachYearOfInterval(interval: Interval): Date[];
@@ -0,0 +1,18 @@
import { toEthiopicDate, toGregorianDate } from "../utils/index.js";
/**
* Returns the start of each Ethiopic year included in the given interval.
*
* @param interval The interval whose years should be returned.
*/
export function eachYearOfInterval(interval) {
const start = toEthiopicDate(new Date(interval.start));
const end = toEthiopicDate(new Date(interval.end));
if (end.year < start.year) {
return [];
}
const years = [];
for (let year = start.year; year <= end.year; year += 1) {
years.push(toGregorianDate({ year, month: 1, day: 1 }));
}
return years;
}
+8
View File
@@ -0,0 +1,8 @@
/**
* Returns the last day of the Ethiopian month for the given date.
*
* @param date - The gregorian date to get the end of month for
* @returns A new gregorian date representing the last day of the Ethiopian
* month
*/
export declare function endOfMonth(date: Date): Date;
+14
View File
@@ -0,0 +1,14 @@
import { daysInMonth } from "../utils/daysInMonth.js";
import { toEthiopicDate, toGregorianDate } from "../utils/index.js";
/**
* Returns the last day of the Ethiopian month for the given date.
*
* @param date - The gregorian date to get the end of month for
* @returns A new gregorian date representing the last day of the Ethiopian
* month
*/
export function endOfMonth(date) {
const { year, month } = toEthiopicDate(date);
const day = daysInMonth(month, year);
return toGregorianDate({ year, month, day: day });
}
+9
View File
@@ -0,0 +1,9 @@
import { type EndOfWeekOptions } from "date-fns";
/**
* End of week
*
* @param {Date} date - The original date
* @param {EndOfWeekOptions} [options] - The options object
* @returns {Date} The end of the week
*/
export declare function endOfWeek(date: Date, options?: EndOfWeekOptions): Date;
+13
View File
@@ -0,0 +1,13 @@
import { endOfWeek as endOfWeekFns } from "date-fns";
/**
* End of week
*
* @param {Date} date - The original date
* @param {EndOfWeekOptions} [options] - The options object
* @returns {Date} The end of the week
*/
export function endOfWeek(date, options) {
const weekStartsOn = options?.weekStartsOn ?? 0; // Default to Monday (1)
const endOfWeek = endOfWeekFns(date, { weekStartsOn });
return endOfWeek;
}
+7
View File
@@ -0,0 +1,7 @@
/**
* End of year
*
* @param {Date} date - The original date
* @returns {Date} The end of the year
*/
export declare function endOfYear(date: Date): Date;
+12
View File
@@ -0,0 +1,12 @@
import { isEthiopicLeapYear, toEthiopicDate, toGregorianDate, } from "../utils/index.js";
/**
* End of year
*
* @param {Date} date - The original date
* @returns {Date} The end of the year
*/
export function endOfYear(date) {
const { year } = toEthiopicDate(date);
const day = isEthiopicLeapYear(year) ? 6 : 5;
return toGregorianDate({ year, month: 13, day });
}
+22
View File
@@ -0,0 +1,22 @@
import type { FormatOptions as DateFnsFormatOptions } from "date-fns";
/** Options for formatting dates in the Ethiopian calendar */
export type FormatOptions = DateFnsFormatOptions;
/**
* Format an Ethiopic calendar date using a subset of date-fns tokens.
*
* Behavior specifics for Ethiopic mode:
*
* - Weekday names ("cccc", "cccccc") come from `Intl.DateTimeFormat` using
* `options.locale?.code` (default: `am-ET`). Narrow form is a single letter.
* - Month names ("LLLL") are Amharic by default and switch to Latin
* transliteration when the locale code starts with `en` or when
* `options.numerals === 'latn'`.
* - Time parts such as `hh:mm a` are delegated to `Intl.DateTimeFormat` with the
* given locale.
* - Digits are converted to Ethiopic (Geez) when `options.numerals === 'geez'`.
*/
export declare function format(date: Date, formatStr: string, options?: DateFnsFormatOptions): string;
export declare const ethMonths: string[];
export declare const ethMonthsLatin: string[];
export declare const shortDays: string[];
export declare const longDays: string[];
+131
View File
@@ -0,0 +1,131 @@
import { toEthiopicDate } from "../utils/index.js";
import { formatNumber } from "./formatNumber.js";
function getEtDayName(day, short = true, localeCode = "am-ET") {
try {
const dtf = new Intl.DateTimeFormat(localeCode, {
// Ethiopic calendar expects single-letter for "cccccc" -> use narrow
weekday: short ? "narrow" : "long",
});
return dtf.format(day);
}
catch {
const dayOfWeek = day.getDay();
return short ? shortDays[dayOfWeek] : longDays[dayOfWeek];
}
}
function getEtMonthName(m, latin = false) {
if (m > 0 && m <= 13) {
return latin ? ethMonthsLatin[m - 1] : ethMonths[m - 1];
}
return "";
}
function formatEthiopianDate(dateObj, formatStr, numerals, localeCode) {
const etDate = dateObj ? toEthiopicDate(dateObj) : undefined;
if (!etDate)
return "";
const useLatin = (localeCode?.startsWith("en") ?? false) || numerals === "latn";
const yearTokenMatch = formatStr.match(/^(\s*)(y+)(\s*)$/);
if (yearTokenMatch) {
const [, leading = "", yearToken, trailing = ""] = yearTokenMatch;
const year = etDate.year.toString();
let formattedYear;
if (yearToken.length === 1) {
formattedYear = year;
}
else if (yearToken.length === 2) {
formattedYear = year.slice(-2).padStart(2, "0");
}
else {
formattedYear = year.padStart(yearToken.length, "0");
}
return `${leading}${formattedYear}${trailing}`;
}
switch (formatStr) {
case "LLLL yyyy":
case "LLLL y":
return `${getEtMonthName(etDate.month, useLatin)} ${etDate.year}`;
case "LLLL":
return getEtMonthName(etDate.month, useLatin);
case "yyyy-MM-dd":
return `${etDate.year}-${etDate.month
.toString()
.padStart(2, "0")}-${etDate.day.toString().padStart(2, "0")}`;
case "yyyy-MM":
return `${etDate.year}-${etDate.month.toString().padStart(2, "0")}`;
case "d":
return etDate.day.toString();
case "PPP":
return ` ${getEtMonthName(etDate.month, useLatin)} ${etDate.day}, ${etDate.year}`;
case "PPPP":
if (!dateObj)
return "";
return `${getEtDayName(dateObj, false, localeCode)}, ${getEtMonthName(etDate.month, useLatin)} ${etDate.day}, ${etDate.year}`;
case "cccc":
return dateObj ? getEtDayName(dateObj, false, localeCode) : "";
case "cccccc":
return dateObj ? getEtDayName(dateObj, true, localeCode) : "";
default:
return `${etDate.day}/${etDate.month}/${etDate.year}`;
}
}
/**
* Format an Ethiopic calendar date using a subset of date-fns tokens.
*
* Behavior specifics for Ethiopic mode:
*
* - Weekday names ("cccc", "cccccc") come from `Intl.DateTimeFormat` using
* `options.locale?.code` (default: `am-ET`). Narrow form is a single letter.
* - Month names ("LLLL") are Amharic by default and switch to Latin
* transliteration when the locale code starts with `en` or when
* `options.numerals === 'latn'`.
* - Time parts such as `hh:mm a` are delegated to `Intl.DateTimeFormat` with the
* given locale.
* - Digits are converted to Ethiopic (Geez) when `options.numerals === 'geez'`.
*/
export function format(date, formatStr, options) {
const extendedOptions = options;
if (formatStr.includes("hh:mm") || formatStr.includes("a")) {
return new Intl.DateTimeFormat(extendedOptions?.locale?.code ?? "en-US", {
hour: "numeric",
minute: "numeric",
hour12: formatStr.includes("a"),
}).format(date);
}
const formatted = formatEthiopianDate(date, formatStr, extendedOptions?.numerals, extendedOptions?.locale?.code ?? "am-ET");
if (extendedOptions?.numerals && extendedOptions.numerals === "geez") {
return formatted.replace(/\d+/g, (match) => formatNumber(parseInt(match, 10), "geez"));
}
return formatted;
}
export const ethMonths = [
"መስከረም",
"ጥቅምት",
"ህዳር",
"ታህሳስ",
"ጥር",
"የካቲት",
"መጋቢት",
"ሚያዚያ",
"ግንቦት",
"ሰኔ",
"ሐምሌ",
"ነሀሴ",
"ጳጉሜ",
];
export const ethMonthsLatin = [
"Meskerem",
"Tikimt",
"Hidar",
"Tahsas",
"Tir",
"Yekatit",
"Megabit",
"Miyazya",
"Ginbot",
"Sene",
"Hamle",
"Nehase",
"Pagumen",
];
export const shortDays = ["እ", "ሰ", "ማ", "ረ", "ሐ", "ዓ", "ቅ"];
export const longDays = ["እሁድ", "ሰኞ", "ማክሰኞ", "ረቡዕ", "ሐሙስ", "ዓርብ", "ቅዳሜ"];
+19
View File
@@ -0,0 +1,19 @@
/**
* Formats a number using either Latin or Ethiopic (Geez) numerals
*
* @example
* ```ts
* formatNumber(123) // '123'
* formatNumber(123, 'geez') // '፻፳፫'
* formatNumber(2023, 'geez') // '፳፻፳፫'
* ```;
*
* @param value - The number to format
* @param numerals - The numeral system to use:
*
* - 'latn': Latin numerals (1, 2, 3...)
* - 'geez': Ethiopic numerals (፩, ፪, ፫...)
*
* @returns The formatted number string
*/
export declare function formatNumber(value: number, numerals?: string): string;
+29
View File
@@ -0,0 +1,29 @@
import { toGeezNumerals } from "../utils/toGeezNumerals.js";
/**
* Formats a number using either Latin or Ethiopic (Geez) numerals
*
* @example
* ```ts
* formatNumber(123) // '123'
* formatNumber(123, 'geez') // '፻፳፫'
* formatNumber(2023, 'geez') // '፳፻፳፫'
* ```;
*
* @param value - The number to format
* @param numerals - The numeral system to use:
*
* - 'latn': Latin numerals (1, 2, 3...)
* - 'geez': Ethiopic numerals (፩, ፪, ፫...)
*
* @returns The formatted number string
*/
export function formatNumber(value, numerals = "latn") {
if (numerals === "geez") {
return toGeezNumerals(value);
}
// Use Intl.NumberFormat for other numeral systems
const formatter = new Intl.NumberFormat("en-US", {
numberingSystem: numerals,
});
return formatter.format(value);
}
+7
View File
@@ -0,0 +1,7 @@
/**
* Get month
*
* @param {Date} date - The original date
* @returns {number} The zero-based month index
*/
export declare function getMonth(date: Date): number;
+11
View File
@@ -0,0 +1,11 @@
import { toEthiopicDate } from "../utils/index.js";
/**
* Get month
*
* @param {Date} date - The original date
* @returns {number} The zero-based month index
*/
export function getMonth(date) {
const { month } = toEthiopicDate(date);
return month - 1; // Return zero-based month index
}
+9
View File
@@ -0,0 +1,9 @@
import { type GetWeekOptions } from "date-fns";
/**
* Get week number for Ethiopian calendar
*
* @param {Date} date - The original date
* @param {GetWeekOptions} [options] - The options object
* @returns {number} The week number
*/
export declare function getWeek(date: Date, options?: GetWeekOptions): number;
+41
View File
@@ -0,0 +1,41 @@
import { differenceInDays, getWeek as getWeekFns, } from "date-fns";
import { toEthiopicDate, toGregorianDate } from "../utils/index.js";
import { startOfWeek } from "./startOfWeek.js";
/**
* Get week number for Ethiopian calendar
*
* @param {Date} date - The original date
* @param {GetWeekOptions} [options] - The options object
* @returns {number} The week number
*/
export function getWeek(date, options) {
const weekStartsOn = options?.weekStartsOn ?? 1; // Default to Monday (1)
const etDate = toEthiopicDate(date);
const currentWeekStart = startOfWeek(date, { weekStartsOn });
// Get the first day of the current year
const firstDayOfYear = toGregorianDate({
year: etDate.year,
month: 1,
day: 1,
});
const firstWeekStart = startOfWeek(firstDayOfYear, { weekStartsOn });
// If date is before the first week of its year
if (date < firstWeekStart) {
return getWeekFns(date, { weekStartsOn, firstWeekContainsDate: 1 });
}
// If date falls into the first week of the NEXT Ethiopic year, return 1
const nextYearFirstDay = toGregorianDate({
year: etDate.year + 1,
month: 1,
day: 1,
});
const nextYearFirstWeekStart = startOfWeek(nextYearFirstDay, {
weekStartsOn,
});
if (date >= nextYearFirstWeekStart) {
return 1;
}
// Calculate week number based on days since first week
const daysSinceFirstWeek = differenceInDays(currentWeekStart, firstWeekStart);
return Math.floor(daysSinceFirstWeek / 7) + 1;
}
+7
View File
@@ -0,0 +1,7 @@
/**
* Get year
*
* @param {Date} date - The original date
* @returns {number} The year
*/
export declare function getYear(date: Date): number;
+11
View File
@@ -0,0 +1,11 @@
import { toEthiopicDate } from "../utils/index.js";
/**
* Get year
*
* @param {Date} date - The original date
* @returns {number} The year
*/
export function getYear(date) {
const { year } = toEthiopicDate(date);
return year;
}

Some files were not shown because too many files have changed in this diff Show More