UNPKG

11.5 kBPlain TextView Raw
1/* eslint-disable @typescript-eslint/ban-types */
2import type { CSSProperties } from "react";
3
4import { UI, DayFlag, SelectionState } from "../UI.js";
5import * as components from "../components/custom-components.js";
6import {
7 formatCaption,
8 formatDay,
9 formatMonthCaption,
10 formatMonthDropdown,
11 formatWeekdayName,
12 formatWeekNumber,
13 formatYearCaption,
14 formatYearDropdown
15} from "../formatters/index.js";
16import {
17 labelDayButton,
18 labelNav,
19 labelGrid,
20 labelGridcell,
21 labelMonthDropdown,
22 labelNext,
23 labelPrevious,
24 labelWeekday,
25 labelWeekNumber,
26 labelWeekNumberHeader,
27 labelYearDropdown
28} from "../labels/index.js";
29import { dateLib } from "../lib/index.js";
30
31/**
32 * Selection modes supported by DayPicker.
33 *
34 * - `single`: use DayPicker to select single days.
35 * - `multiple`: allow selecting multiple days.
36 * - `range`: use DayPicker to select a range of days.
37 *
38 * @see https://daypicker.dev/docs/selection-modes
39 */
40export type Mode = "single" | "multiple" | "range";
41
42/**
43 * The components that can be changed using the `components` prop.
44 *
45 * @see https://daypicker.dev/guides/custom-components
46 */
47export type CustomComponents = {
48 /** Render any button element in DayPicker. */
49 Button: typeof components.Button;
50 /** Render the chevron icon used in the navigation buttons and dropdowns. */
51 Chevron: typeof components.Chevron;
52 /** Render the caption label of the month grid. */
53 CaptionLabel: typeof components.CaptionLabel;
54 /** Render the day cell in the month grid. */
55 Day: typeof components.Day;
56 /** Render the button containing the day in the day cell. */
57 DayButton: typeof components.DayButton;
58 /** Render the dropdown element to select years and months. */
59 Dropdown: typeof components.Dropdown;
60 /** Render the container of the dropdowns. */
61 DropdownNav: typeof components.DropdownNav;
62 /** Render the footer element announced by screen readers. */
63 Footer: typeof components.Footer;
64 /** Render the container of the MonthGrid. */
65 Month: typeof components.Month;
66 /** Render the caption of the month grid. */
67 MonthCaption: typeof components.MonthCaption;
68 /** Render the grid of days in a month. */
69 MonthGrid: typeof components.MonthGrid;
70 /** Wrapper of the month grids. */
71 Months: typeof components.Months;
72 /** Render the navigation element with the next and previous buttons. */
73 Nav: typeof components.Nav;
74 /** Render the `<option>` HTML element in the dropdown. */
75 Option: typeof components.Option;
76 /** Render the root element of the calendar. */
77 Root: typeof components.Root;
78 /** Render the select element in the dropdowns. */
79 Select: typeof components.Select;
80 /** Render the weeks section in the month grid. */
81 Weeks: typeof components.Weeks;
82 /** Render the week rows. */
83 Week: typeof components.Week;
84 /** Render the weekday name in the header. */
85 Weekday: typeof components.Weekday;
86 /** Render the row containing the week days. */
87 Weekdays: typeof components.Weekdays;
88 /** Render the cell with the number of the week. */
89 WeekNumber: typeof components.WeekNumber;
90 /** Render the header of the week number column. */
91 WeekNumberHeader: typeof components.WeekNumberHeader;
92};
93
94/** @private */
95export type DateLib = typeof dateLib;
96
97/** Represent a map of formatters used to render localized content. */
98export type Formatters = {
99 /** Format the caption of a month grid. */
100 formatCaption: typeof formatCaption;
101 /** @deprecated Use {@link Formatters.formatCaption} instead. */
102 formatMonthCaption: typeof formatMonthCaption;
103 /** Format the label in the month dropdown. */
104 formatMonthDropdown: typeof formatMonthDropdown;
105 /** @deprecated Use {@link Formatters.formatYearDropdown} instead. */
106 formatYearCaption: typeof formatYearCaption;
107 /** Format the label in the year dropdown. */
108 formatYearDropdown: typeof formatYearDropdown;
109 /** Format the day in the day cell. */
110 formatDay: typeof formatDay;
111 /** Format the week number. */
112 formatWeekNumber: typeof formatWeekNumber;
113 /** Format the week day name in the header. */
114 formatWeekdayName: typeof formatWeekdayName;
115};
116
117/** Map of functions to translate ARIA labels for the relative elements. */
118export type Labels = {
119 /** The label for the navigation toolbar. */
120 labelNav: typeof labelNav;
121 /** The label for the month grid. */
122 labelGrid: typeof labelGrid;
123 /** The label for the gridcell, when the calendar is not interactive. */
124 labelGridcell: typeof labelGridcell;
125 /** The label for the month dropdown. */
126 labelMonthDropdown: typeof labelMonthDropdown;
127 /** The label for the year dropdown. */
128 labelYearDropdown: typeof labelYearDropdown;
129 /** The label for the "next month" button. */
130 labelNext: typeof labelNext;
131 /** The label for the "previous month" button. */
132 labelPrevious: typeof labelPrevious;
133 /** The label for the day button.. */
134 labelDayButton: typeof labelDayButton;
135 /** @deprecated Use {@link labelDayButton} instead. */
136 labelDay: typeof labelDayButton;
137 /** The label for the weekday. */
138 labelWeekday: typeof labelWeekday;
139 /** The label for the week number. */
140 labelWeekNumber: typeof labelWeekNumber;
141 /**
142 * Return the label for the column of the week number.
143 *
144 * @since 9.0.0
145 */
146 labelWeekNumberHeader: typeof labelWeekNumberHeader;
147};
148
149/**
150 * A value or a function that matches a specific day.
151 *
152 * @example
153 * // will always match the day
154 * const booleanMatcher: Matcher = true;
155 *
156 * // will match the today's date
157 * const dateMatcher: Matcher = new Date();
158 *
159 * // will match the days in the array
160 * const arrayMatcher: Matcher = [
161 * new Date(2019, 1, 2),
162 * new Date(2019, 1, 4)
163 * ];
164 *
165 * // will match days after the 2nd of February 2019
166 * const afterMatcher: DateAfter = { after: new Date(2019, 1, 2) };
167 *
168 * // will match days before the 2nd of February 2019 }
169 * const beforeMatcher: DateBefore = { before: new Date(2019, 1, 2) };
170 *
171 * // will match Sundays
172 * const dayOfWeekMatcher: DayOfWeek = {
173 * dayOfWeek: 0
174 * };
175 *
176 * // will match the included days, except the two dates
177 * const intervalMatcher: DateInterval = {
178 * after: new Date(2019, 1, 2),
179 * before: new Date(2019, 1, 5)
180 * };
181 *
182 * // will match the included days, including the two dates
183 * const rangeMatcher: DateRange = {
184 * from: new Date(2019, 1, 2),
185 * to: new Date(2019, 1, 5)
186 * };
187 *
188 * // will match when the function return true
189 * const functionMatcher: Matcher = (day: Date) => {
190 * return day.getMonth() === 2; // match when month is March
191 * };
192 */
193export type Matcher =
194 | boolean
195 | ((date: Date) => boolean)
196 | Date
197 | Date[]
198 | DateRange
199 | DateBefore
200 | DateAfter
201 | DateInterval
202 | DayOfWeek;
203
204/**
205 * Match a day falling after the specified date, with the date not included.
206 *
207 * @example
208 * // Match days after the 2nd of February 2019
209 * const matcher: DateAfter = { after: new Date(2019, 1, 2) };
210 */
211export type DateAfter = { after: Date };
212
213/**
214 * Match a day falling before the specified date, with the date not included.
215 *
216 * @example
217 * // Match days before the 2nd of February 2019
218 * const matcher: DateBefore = { before: new Date(2019, 1, 2) };
219 */
220export type DateBefore = { before: Date };
221
222/**
223 * An interval of dates. Differently from {@link DateRange}, the range ends here
224 * are not included.
225 *
226 * @example
227 * // Match the days between the 2nd and the 5th of February 2019
228 * const matcher: DateInterval = {
229 * after: new Date(2019, 1, 2),
230 * before: new Date(2019, 1, 5)
231 * };
232 */
233export type DateInterval = { before: Date; after: Date };
234
235/**
236 * A range of dates. The range can be open. Differently from
237 * {@link DateInterval}, the range ends here are included.
238 *
239 * @example
240 * // Match the days between the 2nd and the 5th of February 2019
241 * const matcher: DateRange = {
242 * from: new Date(2019, 1, 2),
243 * to: new Date(2019, 1, 5)
244 * };
245 */
246export type DateRange = { from: Date | undefined; to?: Date | undefined };
247
248/**
249 * Match dates being one of the specified days of the week (`0-6`, where `0` is
250 * Sunday).
251 *
252 * @example
253 * // Match Sundays
254 * const matcher: DayOfWeek = { dayOfWeek: 0 };
255 * // Match weekends
256 * const matcher: DayOfWeek = { dayOfWeek: [0, 6] };
257 */
258export type DayOfWeek = { dayOfWeek: number | number[] };
259
260/**
261 * The event handler triggered when clicking or interacting with a day.
262 *
263 * @template EventType - The event type that triggered the event (e.g.
264 * `React.MouseEvent`, `React.KeyboardEvent`, etc.).
265 * @param date - The date that has triggered the event.
266 * @param modifiers - The modifiers belonging to the date.
267 * @param e - The DOM event that triggered the event.
268 */
269export type DayEventHandler<EventType> = (
270 date: Date,
271 modifiers: Modifiers,
272 e: EventType
273) => void;
274
275/**
276 * The event handler when a month is changed in the calendar.
277 *
278 * ```tsx
279 * <DayPicker onMonthChange={(month) => console.log(month)} />
280 * ```
281 *
282 * @see https://daypicker.dev/docs/navigation
283 */
284export type MonthChangeEventHandler = (month: Date) => void;
285
286/**
287 * The CSS classnames to use for the {@link UI} elements, the
288 * {@link SelectionState} and the {@link DayFlag}.
289 *
290 * @example
291 * const classNames: ClassNames = {
292 * [UI.Root]: "root",
293 * [UI.Outside]: "outside",
294 * [UI.Nav]: "nav"
295 * // etc.
296 * };
297 */
298export type ClassNames = {
299 [key in UI | SelectionState | DayFlag]: string;
300};
301
302/**
303 * The CSS styles to use for the {@link UI} elements, the {@link SelectionState}
304 * and the {@link DayFlag}.
305 */
306export type Styles = {
307 [key in UI | SelectionState | DayFlag]: CSSProperties | undefined;
308};
309
310/**
311 * The modifiers that are matching a day in the calendar.
312 *
313 * @example
314 * const modifiers: Modifiers = {
315 * today: false, // the day is not today
316 * selected: true, // the day is selected
317 * weekend: false // the day is not in the weekend
318 * // etc
319 * };
320 */
321export type Modifiers = Record<string, boolean>;
322
323/**
324 * The style to apply to each day element matching a modifier.
325 *
326 * @example
327 * const modifiersStyles: ModifiersStyles = {
328 * today: { color: "red" },
329 * selected: { backgroundColor: "blue" },
330 * weekend: { color: "green" }
331 * };
332 */
333export type ModifiersStyles = Record<string, CSSProperties>;
334
335/**
336 * The classnames to assign to each day element matching a modifier.
337 *
338 * @example
339 * const modifiersClassNames: ModifiersClassNames = {
340 * today: "today", // Use the "today" class for the today's day
341 * selected: "highlight", // Use the "highlight" class for the selected day
342 * weekend: "weekend" // Use the "weekend" class for the weekend days
343 * };
344 */
345export type ModifiersClassNames = Record<string, string>;
346
347/**
348 * The props that have been deprecated since version 9.0.0.
349 *
350 * @private
351 * @since 9.0.0
352 * @see https://daypicker.dev/upgrading
353 */
354export type V9DeprecatedProps =
355 /** Use `hidden` prop instead. */
356 | "fromDate"
357 /** Use `hidden` prop instead. */
358 | "toDate"
359 /** Use `startMonth` instead. */
360 | "fromMonth"
361 /** Use `endMonth` instead. */
362 | "toMonth"
363 /** Use `startMonth` instead. */
364 | "fromYear"
365 /** Use `endMonth` instead. */
366 | "toYear";
367
368/** The direction to move the focus relative to the current focused date. */
369export type MoveFocusDir = "after" | "before";
370
371/** The temporal unit to move the focus by. */
372export type MoveFocusBy =
373 | "day"
374 | "week"
375 | "startOfWeek"
376 | "endOfWeek"
377 | "month"
378 | "year";