UNPKG

17.7 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 var desc = Object.getOwnPropertyDescriptor(m, k);
5 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 desc = { enumerable: true, get: function() { return m[k]; } };
7 }
8 Object.defineProperty(o, k2, desc);
9}) : (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 o[k2] = m[k];
12}));
13var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 Object.defineProperty(o, "default", { enumerable: true, value: v });
15}) : function(o, v) {
16 o["default"] = v;
17});
18var __importStar = (this && this.__importStar) || function (mod) {
19 if (mod && mod.__esModule) return mod;
20 var result = {};
21 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 __setModuleDefault(result, mod);
23 return result;
24};
25Object.defineProperty(exports, "__esModule", { value: true });
26exports.DayPicker = DayPicker;
27const react_1 = __importStar(require("react"));
28const UI_js_1 = require("./UI.js");
29const getClassNamesForModifiers_js_1 = require("./helpers/getClassNamesForModifiers.js");
30const getComponents_js_1 = require("./helpers/getComponents.js");
31const getDataAttributes_js_1 = require("./helpers/getDataAttributes.js");
32const getDateLib_js_1 = require("./helpers/getDateLib.js");
33const getDefaultClassNames_js_1 = require("./helpers/getDefaultClassNames.js");
34const getFormatters_js_1 = require("./helpers/getFormatters.js");
35const getMonthOptions_js_1 = require("./helpers/getMonthOptions.js");
36const getStyleForModifiers_js_1 = require("./helpers/getStyleForModifiers.js");
37const getWeekdays_js_1 = require("./helpers/getWeekdays.js");
38const getYearOptions_js_1 = require("./helpers/getYearOptions.js");
39const defaultLabels = __importStar(require("./labels/index.js"));
40const useCalendar_js_1 = require("./useCalendar.js");
41const useDayPicker_js_1 = require("./useDayPicker.js");
42const useFocus_js_1 = require("./useFocus.js");
43const useGetModifiers_js_1 = require("./useGetModifiers.js");
44const useSelection_js_1 = require("./useSelection.js");
45const rangeIncludesDate_js_1 = require("./utils/rangeIncludesDate.js");
46const typeguards_js_1 = require("./utils/typeguards.js");
47/**
48 * Render the date picker calendar.
49 *
50 * @group DayPicker
51 * @see https://daypicker.dev
52 */
53function DayPicker(props) {
54 const { components, formatters, labels, dateLib, classNames } = (0, react_1.useMemo)(() => ({
55 dateLib: (0, getDateLib_js_1.getDateLib)(props.dateLib),
56 components: (0, getComponents_js_1.getComponents)(props.components),
57 formatters: (0, getFormatters_js_1.getFormatters)(props.formatters),
58 labels: { ...defaultLabels, ...props.labels },
59 classNames: { ...(0, getDefaultClassNames_js_1.getDefaultClassNames)(), ...props.classNames }
60 }), [
61 props.classNames,
62 props.components,
63 props.dateLib,
64 props.formatters,
65 props.labels
66 ]);
67 const { captionLayout, firstWeekContainsDate, locale, mode, onDayBlur, onDayClick, onDayFocus, onDayKeyDown, onNextClick, onPrevClick, showWeekNumber, styles, useAdditionalDayOfYearTokens, useAdditionalWeekYearTokens, weekStartsOn } = props;
68 const formatOptions = {
69 locale,
70 weekStartsOn,
71 firstWeekContainsDate,
72 useAdditionalWeekYearTokens,
73 useAdditionalDayOfYearTokens
74 };
75 const labelOptions = formatOptions;
76 const { formatCaption, formatDay, formatMonthDropdown, formatWeekNumber, formatWeekNumberHeader, formatWeekdayName, formatYearDropdown } = formatters;
77 const calendar = (0, useCalendar_js_1.useCalendar)(props, dateLib);
78 const { days, months, navStart, navEnd, previousMonth, nextMonth, goToMonth } = calendar;
79 const getModifiers = (0, useGetModifiers_js_1.useGetModifiers)(days, props, dateLib);
80 const { isSelected, select, selected: selectedValue } = (0, useSelection_js_1.useSelection)(props, dateLib) ?? {};
81 const { blur, focused, isFocusTarget, moveFocus, setFocused } = (0, useFocus_js_1.useFocus)(props, calendar, getModifiers, isSelected ?? (() => false), dateLib);
82 const { labelDayButton, labelGridcell, labelGrid, labelMonthDropdown, labelNav, labelNext, labelPrevious, labelWeekday, labelWeekNumber, labelWeekNumberHeader, labelYearDropdown } = labels;
83 const weekdays = (0, react_1.useMemo)(() => (0, getWeekdays_js_1.getWeekdays)(locale, props.weekStartsOn, props.ISOWeek, dateLib), [dateLib, locale, props.ISOWeek, props.weekStartsOn]);
84 const isInteractive = mode !== undefined || onDayClick !== undefined;
85 const handlePreviousClick = (0, react_1.useCallback)(() => {
86 if (!previousMonth)
87 return;
88 goToMonth(previousMonth);
89 onPrevClick?.(previousMonth);
90 }, [previousMonth, goToMonth, onPrevClick]);
91 const handleNextClick = (0, react_1.useCallback)(() => {
92 if (!nextMonth)
93 return;
94 goToMonth(nextMonth);
95 onNextClick?.(nextMonth);
96 }, [goToMonth, nextMonth, onNextClick]);
97 const handleDayClick = (0, react_1.useCallback)((day, m) => (e) => {
98 e.preventDefault();
99 e.stopPropagation();
100 setFocused(day);
101 select?.(day.date, m, e);
102 onDayClick?.(day.date, m, e);
103 }, [select, onDayClick, setFocused]);
104 const handleDayFocus = (0, react_1.useCallback)((day, m) => (e) => {
105 setFocused(day);
106 onDayFocus?.(day.date, m, e);
107 }, [onDayFocus, setFocused]);
108 const handleDayBlur = (0, react_1.useCallback)((day, m) => (e) => {
109 blur();
110 onDayBlur?.(day.date, m, e);
111 }, [blur, onDayBlur]);
112 const handleDayKeyDown = (0, react_1.useCallback)((day, modifiers) => (e) => {
113 const keyMap = {
114 ArrowLeft: ["day", props.dir === "rtl" ? "after" : "before"],
115 ArrowRight: ["day", props.dir === "rtl" ? "before" : "after"],
116 ArrowDown: ["week", "after"],
117 ArrowUp: ["week", "before"],
118 PageUp: [e.shiftKey ? "year" : "month", "before"],
119 PageDown: [e.shiftKey ? "year" : "month", "after"],
120 Home: ["startOfWeek", "before"],
121 End: ["endOfWeek", "after"]
122 };
123 if (keyMap[e.key]) {
124 e.preventDefault();
125 e.stopPropagation();
126 const [moveBy, moveDir] = keyMap[e.key];
127 moveFocus(moveBy, moveDir);
128 }
129 onDayKeyDown?.(day.date, modifiers, e);
130 }, [moveFocus, onDayKeyDown, props.dir]);
131 const { className, style } = (0, react_1.useMemo)(() => ({
132 className: [classNames[UI_js_1.UI.Root], props.className]
133 .filter(Boolean)
134 .join(" "),
135 style: { ...styles?.[UI_js_1.UI.Root], ...props.style }
136 }), [classNames, props.className, props.style, styles]);
137 const dataAttributes = (0, getDataAttributes_js_1.getDataAttributes)(props);
138 const contextValue = {
139 selected: selectedValue,
140 select: select,
141 isSelected,
142 months,
143 nextMonth,
144 previousMonth,
145 goToMonth,
146 getModifiers
147 };
148 return (react_1.default.createElement(useDayPicker_js_1.dayPickerContext.Provider, { value: contextValue },
149 react_1.default.createElement(components.Root, { className: className, style: style, dir: props.dir, id: props.id, lang: props.lang, nonce: props.nonce, title: props.title, ...dataAttributes },
150 react_1.default.createElement(components.Months, { className: classNames[UI_js_1.UI.Months], style: styles?.[UI_js_1.UI.Months] },
151 !props.hideNavigation && (react_1.default.createElement(components.Nav, { role: "navigation", className: classNames[UI_js_1.UI.Nav], style: styles?.[UI_js_1.UI.Nav], "aria-label": labelNav() },
152 react_1.default.createElement(components.Button, { type: "button", className: classNames[UI_js_1.UI.ButtonPrevious], tabIndex: previousMonth ? undefined : -1, disabled: previousMonth ? undefined : true, "aria-label": labelPrevious(previousMonth, labelOptions), onClick: handlePreviousClick },
153 react_1.default.createElement(components.Chevron, { disabled: previousMonth ? undefined : true, className: classNames[UI_js_1.UI.Chevron], orientation: "left" })),
154 react_1.default.createElement(components.Button, { type: "button", className: classNames[UI_js_1.UI.ButtonNext], tabIndex: nextMonth ? undefined : -1, disabled: nextMonth ? undefined : true, "aria-label": labelNext(nextMonth, labelOptions), onClick: handleNextClick },
155 react_1.default.createElement(components.Chevron, { disabled: previousMonth ? undefined : true, orientation: "right", className: classNames[UI_js_1.UI.Chevron] })))),
156 months.map((calendarMonth, displayIndex) => {
157 const handleMonthChange = (e) => {
158 const selectedMonth = Number(e.target.value);
159 const month = dateLib.setMonth(dateLib.startOfMonth(calendarMonth.date), selectedMonth);
160 goToMonth(month);
161 };
162 const handleYearChange = (e) => {
163 const month = dateLib.setYear(dateLib.startOfMonth(calendarMonth.date), Number(e.target.value));
164 goToMonth(month);
165 };
166 const dropdownMonths = (0, getMonthOptions_js_1.getMonthOptions)(calendarMonth.date, navStart, navEnd, formatters, locale, dateLib);
167 const dropdownYears = (0, getYearOptions_js_1.getYearOptions)(months[0].date, navStart, navEnd, formatters, dateLib);
168 return (react_1.default.createElement(components.Month, { className: classNames[UI_js_1.UI.Month], style: styles?.[UI_js_1.UI.Month], key: displayIndex, displayIndex: displayIndex, calendarMonth: calendarMonth },
169 react_1.default.createElement(components.MonthCaption, { className: classNames[UI_js_1.UI.MonthCaption], style: styles?.[UI_js_1.UI.MonthCaption], calendarMonth: calendarMonth, displayIndex: displayIndex }, captionLayout?.startsWith("dropdown") ? (react_1.default.createElement(components.DropdownNav, { className: classNames[UI_js_1.UI.Dropdowns], style: styles?.[UI_js_1.UI.Dropdowns] },
170 captionLayout === "dropdown" ||
171 captionLayout === "dropdown-months" ? (react_1.default.createElement(components.Dropdown, { "aria-label": labelMonthDropdown(), classNames: classNames, components: components, disabled: Boolean(props.disableNavigation), onChange: handleMonthChange, options: dropdownMonths, style: styles?.[UI_js_1.UI.Dropdown], value: calendarMonth.date.getMonth() })) : (react_1.default.createElement("span", { role: "status", "aria-live": "polite" }, formatMonthDropdown(calendarMonth.date.getMonth()))),
172 captionLayout === "dropdown" ||
173 captionLayout === "dropdown-years" ? (react_1.default.createElement(components.Dropdown, { "aria-label": labelYearDropdown(labelOptions), classNames: classNames, components: components, disabled: Boolean(props.disableNavigation), onChange: handleYearChange, options: dropdownYears, style: styles?.[UI_js_1.UI.Dropdown], value: calendarMonth.date.getFullYear() })) : (react_1.default.createElement("span", { role: "status", "aria-live": "polite" }, formatYearDropdown(calendarMonth.date.getFullYear()))))) : (react_1.default.createElement(components.CaptionLabel, { className: classNames[UI_js_1.UI.CaptionLabel], role: "status", "aria-live": "polite" }, formatCaption(calendarMonth.date, formatOptions, dateLib)))),
174 react_1.default.createElement(components.MonthGrid, { role: "grid", "aria-multiselectable": mode === "multiple" || mode === "range", "aria-label": labelGrid(calendarMonth.date, labelOptions, dateLib) ||
175 undefined, className: classNames[UI_js_1.UI.MonthGrid], style: styles?.[UI_js_1.UI.MonthGrid] },
176 !props.hideWeekdays && (react_1.default.createElement(components.Weekdays, { className: classNames[UI_js_1.UI.Weekdays], role: "row", style: styles?.[UI_js_1.UI.Weekdays] },
177 showWeekNumber && (react_1.default.createElement(components.WeekNumberHeader, { "aria-label": labelWeekNumberHeader(labelOptions), className: classNames[UI_js_1.UI.WeekNumberHeader], role: "columnheader", style: styles?.[UI_js_1.UI.WeekNumberHeader] }, formatWeekNumberHeader())),
178 weekdays.map((weekday, i) => (react_1.default.createElement(components.Weekday, { "aria-label": labelWeekday(weekday, labelOptions, dateLib), className: classNames[UI_js_1.UI.Weekday], key: i, role: "columnheader", style: styles?.[UI_js_1.UI.Weekday] }, formatWeekdayName(weekday, formatOptions, dateLib)))))),
179 react_1.default.createElement(components.Weeks, { className: classNames[UI_js_1.UI.Weeks], role: "rowgroup", style: styles?.[UI_js_1.UI.Weeks] }, calendarMonth.weeks.map((week, weekIndex) => {
180 return (react_1.default.createElement(components.Week, { className: classNames[UI_js_1.UI.Week], key: week.weekNumber, role: "row", style: styles?.[UI_js_1.UI.Week], week: week },
181 showWeekNumber && (react_1.default.createElement(components.WeekNumber, { week: week, role: "rowheader", style: styles?.[UI_js_1.UI.WeekNumber], "aria-label": labelWeekNumber(week.weekNumber, {
182 locale
183 }), className: classNames[UI_js_1.UI.WeekNumber] }, formatWeekNumber(week.weekNumber))),
184 week.days.map((day) => {
185 const { date } = day;
186 const modifiers = getModifiers(day);
187 modifiers[UI_js_1.DayFlag.focused] =
188 !modifiers.hidden &&
189 Boolean(focused?.isEqualTo(day));
190 modifiers[UI_js_1.SelectionState.selected] =
191 !modifiers.disabled &&
192 (isSelected?.(date) || modifiers.selected);
193 if ((0, typeguards_js_1.isDateRange)(selectedValue)) {
194 // add range modifiers
195 const { from, to } = selectedValue;
196 modifiers[UI_js_1.SelectionState.range_start] = Boolean(from && to && dateLib.isSameDay(date, from));
197 modifiers[UI_js_1.SelectionState.range_end] = Boolean(from && to && dateLib.isSameDay(date, to));
198 modifiers[UI_js_1.SelectionState.range_middle] =
199 (0, rangeIncludesDate_js_1.rangeIncludesDate)(selectedValue, date, true, dateLib);
200 }
201 const style = (0, getStyleForModifiers_js_1.getStyleForModifiers)(modifiers, styles, props.modifiersStyles);
202 const className = (0, getClassNamesForModifiers_js_1.getClassNamesForModifiers)(modifiers, classNames, props.modifiersClassNames);
203 const ariaLabel = !isInteractive
204 ? labelGridcell(date, modifiers, labelOptions, dateLib)
205 : undefined;
206 const dataAttributes = {
207 "data-day": dateLib.format(date, "yyyy-MM-dd"),
208 "data-month": day.outside
209 ? dateLib.format(date, "yyyy-MM")
210 : undefined
211 };
212 return (react_1.default.createElement(components.Day, { key: `${dateLib.format(date, "yyyy-MM-dd")}_${dateLib.format(day.displayMonth, "yyyy-MM")}`, day: day, modifiers: modifiers, role: "gridcell", className: className.join(" "), style: style, "aria-hidden": modifiers.hidden || undefined, "aria-selected": modifiers.selected || undefined, "aria-label": ariaLabel, ...dataAttributes }, isInteractive ? (react_1.default.createElement(components.DayButton, { className: classNames[UI_js_1.UI.DayButton], style: styles?.[UI_js_1.UI.DayButton], day: day, modifiers: modifiers, disabled: modifiers.disabled || undefined, tabIndex: isFocusTarget(day) ? 0 : -1, "aria-label": labelDayButton(date, modifiers, labelOptions, dateLib), onClick: handleDayClick(day, modifiers), onBlur: handleDayBlur(day, modifiers), onFocus: handleDayFocus(day, modifiers), onKeyDown: handleDayKeyDown(day, modifiers) }, formatDay(date, formatOptions, dateLib))) : (formatDay(day.date, formatOptions, dateLib))));
213 })));
214 })))));
215 })),
216 props.footer && (react_1.default.createElement(components.Footer, { className: classNames[UI_js_1.UI.Footer], style: styles?.[UI_js_1.UI.Footer], role: "status", "aria-live": "polite" }, props.footer)))));
217}
218//# sourceMappingURL=DayPicker.js.map
\No newline at end of file