UNPKG

react-datepicker-lite

Version:

A lightweight, accessible, and customizable React date picker component with TypeScript support

981 lines (980 loc) 30.7 kB
import { jsxs, jsx } from "react/jsx-runtime"; import React, { forwardRef, useState, useCallback, useMemo, useRef, useEffect } from "react"; class NativeDateAdapter { format(date, format) { if (!this.isValid(date)) { return ""; } try { const monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; const monthNamesShort = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; const dayNames = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; const dayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; let result = format; const formatMap = { EEEE: dayNames[date.getDay()] || "", EEE: dayNamesShort[date.getDay()] || "", MMMM: monthNames[date.getMonth()] || "", MMM: monthNamesShort[date.getMonth()] || "", yyyy: date.getFullYear().toString(), YYYY: date.getFullYear().toString(), MM: (date.getMonth() + 1).toString().padStart(2, "0"), dd: date.getDate().toString().padStart(2, "0"), DD: date.getDate().toString().padStart(2, "0"), HH: date.getHours().toString().padStart(2, "0"), mm: date.getMinutes().toString().padStart(2, "0"), ss: date.getSeconds().toString().padStart(2, "0"), YY: date.getFullYear().toString().slice(-2), M: (date.getMonth() + 1).toString(), D: date.getDate().toString(), H: date.getHours().toString(), m: date.getMinutes().toString(), s: date.getSeconds().toString() }; const patterns = [ "EEEE", "EEE", "MMMM", "MMM", "yyyy", "YYYY", "MM", "dd", "DD", "HH", "mm", "ss", "YY", "M", "D", "H", "m", "s" ]; for (const pattern of patterns) { const value = formatMap[pattern]; if (value !== void 0) { if (pattern.length === 1) { result = result.replace(new RegExp(`\\b${pattern}\\b`, "g"), value); } else { result = result.replace(new RegExp(pattern, "g"), value); } } } return result; } catch { return ""; } } parse(dateString, format) { if (!dateString) { return null; } try { if (format === "MM/dd/yyyy") { const match = dateString.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/); if (match && match[1] && match[2] && match[3]) { const month = parseInt(match[1]); const day = parseInt(match[2]); const year = parseInt(match[3]); if (month < 1 || month > 12 || day < 1 || day > 31 || year < 1) { return null; } const date = new Date(year, month - 1, day); if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) { return date; } return null; } } else if (format === "dd/MM/yyyy") { const match = dateString.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/); if (match && match[1] && match[2] && match[3]) { const day = parseInt(match[1]); const month = parseInt(match[2]); const year = parseInt(match[3]); const date = new Date(year, month - 1, day); if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) { return date; } } } else if (format === "yyyy-MM-dd") { const match = dateString.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/); if (match && match[1] && match[2] && match[3]) { const year = parseInt(match[1]); const month = parseInt(match[2]); const day = parseInt(match[3]); const date = new Date(year, month - 1, day); if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) { return date; } } } else if (format === "MMM dd, yyyy") { const monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; const match = dateString.match( /^([A-Za-z]{3})\s+(\d{1,2}),\s+(\d{4})$/ ); if (match && match[1] && match[2] && match[3]) { const monthStr = match[1]; const day = parseInt(match[2]); const year = parseInt(match[3]); const monthIndex = monthNames.indexOf(monthStr); if (monthIndex !== -1) { const date = new Date(year, monthIndex, day); if (date.getFullYear() === year && date.getMonth() === monthIndex && date.getDate() === day) { return date; } } } } const parsed = new Date(dateString); return this.isValid(parsed) ? parsed : null; } catch { return null; } } isValid(date) { return date instanceof Date && !isNaN(date.getTime()); } addDays(date, days) { const result = new Date(date); result.setDate(result.getDate() + days); return result; } addMonths(date, months) { const result = new Date(date); const _originalDay = result.getDate(); result.setMonth(result.getMonth() + months); if (result.getDate() !== _originalDay) { result.setDate(0); } return result; } addYears(date, years) { const result = new Date(date); const originalMonth = result.getMonth(); result.setFullYear(result.getFullYear() + years); if (result.getMonth() !== originalMonth) { result.setDate(0); } return result; } startOfDay(date) { const result = new Date(date); result.setHours(0, 0, 0, 0); return result; } startOfMonth(date) { const result = new Date(date); result.setDate(1); result.setHours(0, 0, 0, 0); return result; } startOfYear(date) { const result = new Date(date); result.setMonth(0, 1); result.setHours(0, 0, 0, 0); return result; } endOfDay(date) { const result = new Date(date); result.setHours(23, 59, 59, 999); return result; } endOfMonth(date) { const result = new Date(date); result.setMonth(result.getMonth() + 1, 0); result.setHours(23, 59, 59, 999); return result; } endOfYear(date) { const result = new Date(date); result.setMonth(11, 31); result.setHours(23, 59, 59, 999); return result; } isSameDay(date1, date2) { if (!this.isValid(date1) || !this.isValid(date2)) { return false; } return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate(); } isSameMonth(date1, date2) { if (!this.isValid(date1) || !this.isValid(date2)) { return false; } return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth(); } isSameYear(date1, date2) { if (!this.isValid(date1) || !this.isValid(date2)) { return false; } return date1.getFullYear() === date2.getFullYear(); } isAfter(date1, date2) { if (!this.isValid(date1) || !this.isValid(date2)) { return false; } return date1.getTime() > date2.getTime(); } isBefore(date1, date2) { if (!this.isValid(date1) || !this.isValid(date2)) { return false; } return date1.getTime() < date2.getTime(); } getDay(date) { return date.getDay(); } getMonth(date) { return date.getMonth(); } getYear(date) { return date.getFullYear(); } getDaysInMonth(date) { return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); } today() { return /* @__PURE__ */ new Date(); } } const nativeDateAdapter = new NativeDateAdapter(); const enUS = { code: "en-US", name: "English (US)", months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], monthsShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], weekdays: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], weekdaysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], weekdaysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], firstDayOfWeek: 0, // Sunday rtl: false, dateFormat: "MM/DD/YYYY", timeFormat: "HH:mm", dateTimeFormat: "MM/DD/YYYY HH:mm" }; const defaultLocale = enUS; function getLocale(_code) { return defaultLocale; } const DateInput = forwardRef( ({ value, defaultValue, onChange, dateAdapter = nativeDateAdapter, format, placeholder = "Select date", disabled = false, readOnly = false, autoFocus = false, className = "", locale = defaultLocale, minDate: _minDate, maxDate: _maxDate, disabledDates: _disabledDates, onFocus, onBlur, onKeyDown, onCalendarToggle, isCalendarOpen = false, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, id, ...rest }, ref) => { const [inputValue, setInputValue] = useState(() => { if (value && dateAdapter.isValid(value)) { return dateAdapter.format(value, format || locale.dateFormat); } if (defaultValue && dateAdapter.isValid(defaultValue)) { return dateAdapter.format(defaultValue, format || locale.dateFormat); } return ""; }); const [isFocused, setIsFocused] = useState(false); const handleInputChange = useCallback( (event) => { const newValue = event.target.value; setInputValue(newValue); if (newValue === "") { onChange == null ? void 0 : onChange(null); return; } const parsedDate = dateAdapter.parse( newValue, format || locale.dateFormat ); if (parsedDate && dateAdapter.isValid(parsedDate)) { onChange == null ? void 0 : onChange(parsedDate); } }, [dateAdapter, format, locale.dateFormat, onChange] ); const handleFocus = useCallback( (event) => { setIsFocused(true); onFocus == null ? void 0 : onFocus(event); onCalendarToggle == null ? void 0 : onCalendarToggle(true); }, [onFocus, onCalendarToggle] ); const handleBlur = useCallback( (event) => { setIsFocused(false); onBlur == null ? void 0 : onBlur(event); if (inputValue && value && dateAdapter.isValid(value)) { const formattedValue = dateAdapter.format( value, format || locale.dateFormat ); setInputValue(formattedValue); } }, [onBlur, inputValue, value, dateAdapter, format, locale.dateFormat] ); const handleKeyDown = useCallback( (event) => { onKeyDown == null ? void 0 : onKeyDown(event); if (event.key === "Escape") { onCalendarToggle == null ? void 0 : onCalendarToggle(false); } else if (event.key === "Enter" || event.key === "ArrowDown") { event.preventDefault(); onCalendarToggle == null ? void 0 : onCalendarToggle(true); } }, [onKeyDown, onCalendarToggle] ); React.useEffect(() => { if (value && dateAdapter.isValid(value)) { const formattedValue = dateAdapter.format( value, format || locale.dateFormat ); setInputValue(formattedValue); } else if (value === null || value === void 0) { setInputValue(""); } }, [value, dateAdapter, format, locale.dateFormat]); const inputClassName = [ "rdl-date-input", isFocused && "rdl-date-input--focused", disabled && "rdl-date-input--disabled", readOnly && "rdl-date-input--readonly", isCalendarOpen && "rdl-date-input--calendar-open", className ].filter(Boolean).join(" "); return /* @__PURE__ */ jsxs("div", { className: "rdl-date-input-wrapper", children: [ /* @__PURE__ */ jsx( "input", { ref, type: "text", value: inputValue, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, placeholder, disabled, readOnly, autoFocus, className: inputClassName, "aria-label": ariaLabel || "Date input", "aria-describedby": ariaDescribedBy, "aria-expanded": isCalendarOpen, "aria-haspopup": "dialog", "aria-controls": isCalendarOpen ? `${id || "datepicker"}-calendar` : void 0, role: "combobox", id, ...rest } ), /* @__PURE__ */ jsx( "button", { type: "button", className: "rdl-date-input-toggle", onClick: () => onCalendarToggle == null ? void 0 : onCalendarToggle(!isCalendarOpen), disabled, "aria-label": "Open calendar", tabIndex: -1, children: /* @__PURE__ */ jsx( "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM2 2a1 1 0 0 0-1 1v1h14V3a1 1 0 0 0-1-1H2zM1 5v9a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V5H1z" }) } ) } ) ] }); } ); DateInput.displayName = "DateInput"; const Calendar = ({ currentDate, onCurrentDateChange, selectedDate, selectedRange, onDateSelect, dateAdapter = nativeDateAdapter, minDate, maxDate, disabledDates, locale = defaultLocale, showWeekNumbers = false, className = "", isRangeSelection = false, rangeHoverDate, onRangeHover }) => { const calendarDays = useMemo(() => { const startOfMonth = dateAdapter.startOfMonth(currentDate); const startOfCalendar = dateAdapter.addDays( startOfMonth, -((dateAdapter.getDay(startOfMonth) - locale.firstDayOfWeek + 7) % 7) ); const endOfCalendar = dateAdapter.addDays(startOfCalendar, 41); const days = []; let current = startOfCalendar; while (dateAdapter.isBefore(current, endOfCalendar)) { const isToday = dateAdapter.isSameDay(current, dateAdapter.today()); const isSelected = selectedDate ? dateAdapter.isSameDay(current, selectedDate) : false; const isOutsideMonth = !dateAdapter.isSameMonth(current, currentDate); const isWeekend = dateAdapter.getDay(current) === 0 || dateAdapter.getDay(current) === 6; let isDisabled = false; if (minDate && dateAdapter.isBefore(current, dateAdapter.startOfDay(minDate))) { isDisabled = true; } if (maxDate && dateAdapter.isAfter(current, dateAdapter.startOfDay(maxDate))) { isDisabled = true; } if (disabledDates && !isDisabled) { if (Array.isArray(disabledDates)) { isDisabled = disabledDates.some( (disabledDate) => dateAdapter.isSameDay(current, disabledDate) ); } else { isDisabled = disabledDates(current); } } let isInRange = false; let isRangeStart = false; let isRangeEnd = false; if (isRangeSelection && selectedRange) { const { start, end } = selectedRange; if (start && end) { isInRange = (dateAdapter.isAfter(current, start) || dateAdapter.isSameDay(current, start)) && (dateAdapter.isBefore(current, end) || dateAdapter.isSameDay(current, end)); isRangeStart = dateAdapter.isSameDay(current, start); isRangeEnd = dateAdapter.isSameDay(current, end); } else if (start && rangeHoverDate) { const rangeStart = dateAdapter.isBefore(start, rangeHoverDate) ? start : rangeHoverDate; const rangeEnd = dateAdapter.isAfter(start, rangeHoverDate) ? start : rangeHoverDate; isInRange = (dateAdapter.isAfter(current, rangeStart) || dateAdapter.isSameDay(current, rangeStart)) && (dateAdapter.isBefore(current, rangeEnd) || dateAdapter.isSameDay(current, rangeEnd)); } } days.push({ date: current, isToday, isSelected, isInRange, isRangeStart, isRangeEnd, isDisabled, isOutsideMonth, isWeekend }); current = dateAdapter.addDays(current, 1); } return days; }, [ currentDate, selectedDate, selectedRange, dateAdapter, locale.firstDayOfWeek, minDate, maxDate, disabledDates, isRangeSelection, rangeHoverDate ]); const handlePreviousMonth = useCallback(() => { onCurrentDateChange(dateAdapter.addMonths(currentDate, -1)); }, [currentDate, dateAdapter, onCurrentDateChange]); const handleNextMonth = useCallback(() => { onCurrentDateChange(dateAdapter.addMonths(currentDate, 1)); }, [currentDate, dateAdapter, onCurrentDateChange]); const handleDateClick = useCallback( (day) => { if (day.isDisabled) return; onDateSelect(day.date); }, [onDateSelect] ); const handleDateHover = useCallback( (day) => { if (isRangeSelection && onRangeHover && !day.isDisabled) { onRangeHover(day.date); } }, [isRangeSelection, onRangeHover] ); const handleDateMouseLeave = useCallback(() => { if (isRangeSelection && onRangeHover) { onRangeHover(null); } }, [isRangeSelection, onRangeHover]); const handleHeaderClick = useCallback( (event) => { if (event.shiftKey) { onCurrentDateChange(dateAdapter.addYears(currentDate, -1)); } else { onCurrentDateChange(dateAdapter.addYears(currentDate, 1)); } }, [currentDate, dateAdapter, onCurrentDateChange] ); const handleKeyDown = useCallback( (event, day) => { if (day.isDisabled) return; const currentIndex = calendarDays.findIndex( (d) => dateAdapter.isSameDay(d.date, day.date) ); let newIndex = currentIndex; switch (event.key) { case "Enter": case " ": event.preventDefault(); onDateSelect(day.date); break; case "ArrowRight": event.preventDefault(); newIndex = Math.min(currentIndex + 1, calendarDays.length - 1); break; case "ArrowLeft": event.preventDefault(); newIndex = Math.max(currentIndex - 1, 0); break; case "ArrowDown": event.preventDefault(); newIndex = Math.min(currentIndex + 7, calendarDays.length - 1); break; case "ArrowUp": event.preventDefault(); newIndex = Math.max(currentIndex - 7, 0); break; case "Home": event.preventDefault(); newIndex = currentIndex - currentIndex % 7; break; case "End": event.preventDefault(); newIndex = currentIndex + (6 - currentIndex % 7); break; case "PageUp": event.preventDefault(); onCurrentDateChange(dateAdapter.addMonths(currentDate, -1)); break; case "PageDown": event.preventDefault(); onCurrentDateChange(dateAdapter.addMonths(currentDate, 1)); break; default: return; } if (newIndex !== currentIndex && newIndex >= 0 && newIndex < calendarDays.length) { const newDay = calendarDays[newIndex]; if (newDay && !newDay.isDisabled) { const buttons = document.querySelectorAll(".rdl-calendar-day"); const targetButton = buttons[newIndex]; if (targetButton) { targetButton.focus(); } } } }, [calendarDays, dateAdapter, onDateSelect, onCurrentDateChange, currentDate] ); const weekdays = useMemo(() => { const days = []; for (let i = 0; i < 7; i++) { const dayIndex = (locale.firstDayOfWeek + i) % 7; days.push(locale.weekdaysMin[dayIndex]); } return days; }, [locale]); const calendarClassName = [ "rdl-calendar", showWeekNumbers && "rdl-calendar--with-week-numbers", isRangeSelection && "rdl-calendar--range-selection", className ].filter(Boolean).join(" "); return /* @__PURE__ */ jsxs("div", { className: calendarClassName, children: [ /* @__PURE__ */ jsxs("div", { className: "rdl-calendar-header", children: [ /* @__PURE__ */ jsx( "button", { type: "button", className: "rdl-calendar-nav rdl-calendar-nav--prev", onClick: handlePreviousMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z" }) }) } ), /* @__PURE__ */ jsxs( "button", { type: "button", className: "rdl-calendar-title", onClick: handleHeaderClick, "aria-label": `${locale.months[dateAdapter.getMonth(currentDate)]} ${dateAdapter.getYear(currentDate)}, click to navigate years`, children: [ /* @__PURE__ */ jsx("span", { className: "rdl-calendar-month", children: locale.months[dateAdapter.getMonth(currentDate)] }), /* @__PURE__ */ jsx("span", { className: "rdl-calendar-year", children: dateAdapter.getYear(currentDate) }) ] } ), /* @__PURE__ */ jsx( "button", { type: "button", className: "rdl-calendar-nav rdl-calendar-nav--next", onClick: handleNextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z" }) }) } ) ] }), /* @__PURE__ */ jsxs( "div", { className: "rdl-calendar-grid", role: "grid", "aria-label": `Calendar for ${locale.months[dateAdapter.getMonth(currentDate)]} ${dateAdapter.getYear(currentDate)}`, children: [ /* @__PURE__ */ jsxs("div", { className: "rdl-calendar-weekdays", role: "row", children: [ showWeekNumbers && /* @__PURE__ */ jsx( "div", { className: "rdl-calendar-weekday rdl-calendar-week-number-header", role: "columnheader", children: "Wk" } ), weekdays.map((weekday, index) => /* @__PURE__ */ jsx( "div", { className: "rdl-calendar-weekday", role: "columnheader", children: weekday }, index )) ] }), /* @__PURE__ */ jsx("div", { className: "rdl-calendar-days", children: Array.from({ length: 6 }, (_, weekIndex) => /* @__PURE__ */ jsxs("div", { className: "rdl-calendar-week", role: "row", children: [ showWeekNumbers && /* @__PURE__ */ jsx("div", { className: "rdl-calendar-week-number", role: "rowheader", children: weekIndex + 1 }), calendarDays.slice(weekIndex * 7, (weekIndex + 1) * 7).map((day, dayIndex) => { const dayClassName = [ "rdl-calendar-day", day.isToday && "rdl-calendar-day--today", day.isSelected && "rdl-calendar-day--selected", day.isInRange && "rdl-calendar-day--in-range", day.isRangeStart && "rdl-calendar-day--range-start", day.isRangeEnd && "rdl-calendar-day--range-end", day.isDisabled && "rdl-calendar-day--disabled", day.isOutsideMonth && "rdl-calendar-day--outside-month", day.isWeekend && "rdl-calendar-day--weekend" ].filter(Boolean).join(" "); return /* @__PURE__ */ jsx("div", { role: "gridcell", children: /* @__PURE__ */ jsx( "button", { type: "button", className: dayClassName, onClick: () => handleDateClick(day), onMouseEnter: () => handleDateHover(day), onMouseLeave: handleDateMouseLeave, onKeyDown: (e) => handleKeyDown(e, day), disabled: day.isDisabled, "aria-label": dateAdapter.format( day.date, locale.dateFormat ), "aria-pressed": day.isSelected, "aria-disabled": day.isDisabled, tabIndex: day.isSelected ? 0 : -1, children: dateAdapter.format(day.date, "D") } ) }, dayIndex); }) ] }, weekIndex)) }) ] } ) ] }); }; const DatePicker = ({ value, defaultValue, onChange, dateAdapter = nativeDateAdapter, format, placeholder, disabled = false, readOnly = false, autoFocus = false, className = "", locale = defaultLocale, minDate, maxDate, disabledDates, showWeekNumbers = false, showToday = true, closeOnSelect = true, onFocus, onBlur, onKeyDown, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, id }) => { const [isOpen, setIsOpen] = useState(false); const [currentDate, setCurrentDate] = useState(() => { if (value && dateAdapter.isValid(value)) { return value; } if (defaultValue && dateAdapter.isValid(defaultValue)) { return defaultValue; } return dateAdapter.today(); }); const containerRef = useRef(null); const inputRef = useRef(null); const [internalValue, setInternalValue] = useState( () => defaultValue || null ); const currentValue = value !== void 0 ? value : internalValue; const isControlled = value !== void 0; const handleDateChange = useCallback( (newDate) => { if (value === void 0) { setInternalValue(newDate); } onChange == null ? void 0 : onChange(newDate); }, [value, onChange] ); const handleCalendarToggle = useCallback( (open) => { if (disabled || readOnly) return; setIsOpen(open); }, [disabled, readOnly] ); const handleDateSelect = useCallback( (selectedDate) => { handleDateChange(selectedDate); setCurrentDate(selectedDate); if (closeOnSelect) { setIsOpen(false); requestAnimationFrame(() => { var _a; (_a = inputRef.current) == null ? void 0 : _a.focus(); }); } }, [handleDateChange, closeOnSelect] ); const handleCurrentDateChange = useCallback((newCurrentDate) => { setCurrentDate(newCurrentDate); }, []); useEffect(() => { const handleClickOutside = (event) => { if (containerRef.current && !containerRef.current.contains(event.target)) { setIsOpen(false); } }; if (isOpen) { document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; } return void 0; }, [isOpen]); const handleKeyDown = useCallback( (event) => { onKeyDown == null ? void 0 : onKeyDown(event); if (event.key === "Escape" && isOpen) { setIsOpen(false); event.preventDefault(); } }, [onKeyDown, isOpen] ); useEffect(() => { if (currentValue && dateAdapter.isValid(currentValue)) { setCurrentDate(currentValue); } }, [currentValue, dateAdapter]); const pickerClassName = [ "rdl-date-picker", isOpen && "rdl-date-picker--open", disabled && "rdl-date-picker--disabled", className ].filter(Boolean).join(" "); const dateInputProps = { ref: inputRef, onChange: handleDateChange, dateAdapter, disabled, readOnly, autoFocus, locale, onCalendarToggle: handleCalendarToggle, isCalendarOpen: isOpen, onKeyDown: handleKeyDown, ...placeholder && { placeholder }, ...format && { format }, ...minDate !== void 0 && { minDate }, ...maxDate !== void 0 && { maxDate }, ...disabledDates && { disabledDates }, ...onFocus && { onFocus }, ...onBlur && { onBlur }, ...ariaLabel && { "aria-label": ariaLabel }, ...ariaDescribedBy && { "aria-describedby": ariaDescribedBy }, ...id && { id } }; if (isControlled) { dateInputProps.value = value; } else { dateInputProps.value = internalValue; } const calendarProps = { currentDate, onCurrentDateChange: handleCurrentDateChange, selectedDate: currentValue, onDateSelect: handleDateSelect, dateAdapter, locale, showWeekNumbers, ...minDate !== void 0 && { minDate }, ...maxDate !== void 0 && { maxDate }, ...disabledDates && { disabledDates } }; return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: pickerClassName, children: [ /* @__PURE__ */ jsx(DateInput, { ...dateInputProps }), isOpen && /* @__PURE__ */ jsxs("div", { className: "rdl-date-picker-dropdown", children: [ /* @__PURE__ */ jsx(Calendar, { ...calendarProps }), showToday && /* @__PURE__ */ jsx("div", { className: "rdl-date-picker-footer", children: /* @__PURE__ */ jsx( "button", { type: "button", className: "rdl-date-picker-today-button", onClick: () => handleDateSelect(dateAdapter.today()), children: "Today" } ) }) ] }) ] }); }; const version = "1.0.2"; export { Calendar, DateInput, DatePicker, NativeDateAdapter, defaultLocale, enUS, getLocale, nativeDateAdapter, version }; //# sourceMappingURL=index.esm.js.map