import { useState, useEffect } from "react"; import { DayPicker } from "react-day-picker"; import type { DateRange } from "react-day-picker"; import "react-day-picker/style.css"; type BaseProps = Omit< React.ComponentProps, "mode" | "selected" | "onSelect" >; type CalendarProps = | (BaseProps & { mode: "single"; selected?: Date; onSelect?: (date: Date | undefined) => void; closeOnSelect?: boolean /** whether to request closing after selection (default true for single) */; onClose?: () => void; }) | (BaseProps & { mode: "range"; selected?: DateRange; onSelect?: (range: DateRange | undefined) => void; closeOnSelect?: boolean; // will close only when range is complete onClose?: () => void; }) | (BaseProps & { mode: "multiple"; selected?: Date[]; onSelect?: (dates: Date[] | undefined) => void; closeOnSelect?: boolean; // default false for multi onClose?: () => void; }); export function Calendar(props: CalendarProps) { const { mode, selected, onSelect, className, closeOnSelect, onClose, ...rest } = props; const [internalSelected, setInternalSelected] = useState(selected); useEffect(() => { setInternalSelected(selected); }, [selected]); const handleSelect = (value: typeof selected) => { setInternalSelected(value); // forward original callback onSelect?.(value as any); // Decide whether to request closing const shouldClose = typeof closeOnSelect !== "undefined" ? closeOnSelect : mode === "single" ? true : false; if (!shouldClose) return; // For range: only close when both from and to exist if (mode === "range") { const range = value as DateRange | undefined; if (range?.from && range?.to) { onClose?.(); } return; } // For single or multiple (when allowed), close immediately onClose?.(); }; return (
{mode === "single" && ( void} captionLayout="dropdown" // ✅ Enables month/year dropdown {...rest} /> )} {mode === "range" && ( void} {...rest} /> )} {mode === "multiple" && ( void} {...rest} /> )}
); }