import React from 'react'; import type { IsoDate } from './iso-date.js'; export type DateRangePickerSize = 'sm' | 'md' | 'lg'; /** A closed interval of calendar dates. `end` is included in the range. */ export interface DateRange { /** `YYYY-MM-DD`. */ start: IsoDate; /** `YYYY-MM-DD`, inclusive. */ end: IsoDate; } /** * A shortcut in the rail beside the calendar — "Last 7 days", "Year to date". */ export interface DateRangePreset { /** What the row reads. Also its accessible name. */ label: string; /** * The range it selects. * * A FUNCTION for anything relative to today, which is most of them. A literal * object is evaluated once, when the caller's module is first imported, so * "Last 7 days" built as a literal is seven days before whenever the tab was * opened — correct on load and increasingly wrong for a session left open * overnight. The function is re-run every time the calendar opens. */ value: DateRange | (() => DateRange); } export interface DateRangePickerProps { /** Field label. Required for a usable control — see `a11y.requires`. */ label?: React.ReactNode; /** Helper text below the field. */ description?: React.ReactNode; /** Replaces the helper text while the field is invalid — `isInvalid`, or its own bounds check. */ errorMessage?: React.ReactNode; isInvalid?: boolean; isDisabled?: boolean; isReadOnly?: boolean; isRequired?: boolean; /** Matches Input's `Size` variant: Small, Medium, Large. */ size?: DateRangePickerSize; /** * The selected range, both ends as `YYYY-MM-DD`. `null` means no range. * A half-open range is not representable on purpose — see `antiPatterns`. */ value?: DateRange | null; /** The initial range, for an uncontrolled picker. */ defaultValue?: DateRange; /** Fires with both ends, or `null` when the range is cleared. */ onChange?: (value: DateRange | null) => void; /** Earliest selectable date, `YYYY-MM-DD`. */ minValue?: IsoDate; /** Latest selectable date, `YYYY-MM-DD`. */ maxValue?: IsoDate; /** * Individual dates the calendar refuses. Receives `YYYY-MM-DD`. * * A range may not be dragged ACROSS one of these — react-aria stops the * selection at the first unavailable day, which is what makes "book a room * for these nights" correct rather than merely styled. */ isDateUnavailable?: (date: IsoDate) => boolean; /** Shortcut rows beside the calendar. Omitted, no rail is rendered. */ presets?: readonly DateRangePreset[]; /** * How many months the calendar shows at once. Two by default: a range that * crosses a month boundary is the common case, and a one-month calendar * makes the user page back and forth to see both ends of their own selection. */ visibleMonths?: 1 | 2 | 3; /** Show a Clear button under the calendar. Defaults to `true`. */ isClearable?: boolean; /** Posts `-start` and `-end` for an uncontrolled form. */ name?: string; /** Accessible label for the button that opens the calendar. */ calendarLabel?: string; clearLabel?: string; presetsLabel?: string; className?: string; wrapperClassName?: string; id?: string; } /** * DateRangePicker — two segmented date fields with one calendar between them. * * NOT TWO `DatePicker`s SIDE BY SIDE, and the difference is the whole reason * this exists. Two independent pickers cannot stop the end date being before * the start, cannot show the days between them as a band, and give the user two * calendars to reconcile by memory. `useDateRangePicker` owns both ends: the * second click completes the range in whichever order the two dates fall, the * band follows the pointer while it is being dragged out, and a range cannot be * made to run backwards. * * THE VALUE COMMITS LIVE. THERE IS NO APPLY BUTTON. * * `onChange` fires the moment the second end lands, and the calendar closes. * The reference designs this was drawn from put Clear and Apply under the grid, * which is a draft model: the popover holds a pending range and only Apply * promotes it. That was considered and rejected. Escape and an outside click * would then silently discard a selection the user watched themselves make — * and there is no way to tell those two gestures apart from "I am done". A * button labelled Apply beside a value that already applied is worse still. * * Clear stays, because clearing is a real action with no other affordance. * * BOTH ENDS OR NEITHER * * `value` has no half-open form. A range with a start and no end is a state the * calendar passes THROUGH between the two clicks; it is never a value the * caller is handed, because "everything after March" and "March to today" are * different questions and a `null` end cannot say which one was meant. A caller * who wants an open end passes a sentinel of their own choosing as `maxValue`. */ export declare function DateRangePicker({ label, description, errorMessage, isInvalid, isDisabled, isReadOnly, isRequired, size, value, defaultValue, onChange, minValue, maxValue, isDateUnavailable, presets, visibleMonths, isClearable, name, calendarLabel, clearLabel, presetsLabel, className, wrapperClassName, id, }: DateRangePickerProps): React.JSX.Element; export declare namespace DateRangePicker { var displayName: string; } //# sourceMappingURL=DateRangePicker.d.ts.map