Skip to content

feat: Add Calendar multi-select, week/day views, weeksInMonth, month/year pickers, and unavailable anchor date#9948

Open
devongovett wants to merge 11 commits intomainfrom
calendar-features
Open

feat: Add Calendar multi-select, week/day views, weeksInMonth, month/year pickers, and unavailable anchor date#9948
devongovett wants to merge 11 commits intomainfrom
calendar-features

Conversation

@devongovett
Copy link
Copy Markdown
Member

@devongovett devongovett commented Apr 18, 2026

Closes #4789, closes #9171, closes #4652, closes #7809, closes #3311, closes #6677

This PR adds several new features to Calendar and RangeCalendar:

  1. Support for selectionMode="multiple" in Calendar. Just like Select and ComboBox, when this prop is set, the value and onChange props accept an array of dates instead of a single date.
  2. A new CalendarHeading component. This handles formatting the heading with an offset from the start of the visible range, for example, in multi-month calendars. Before this had to be implemented manually.
  3. New CalendarMonthPicker and CalendarYearPicker components. These format a list of month and year names and provide them to a render prop, so you can easily render a Select or another component to let users quickly jump to a specific month or year.
  4. A weeksInMonth prop which overrides the locale default number of weeks to display in a month. This can be set to a fixed value like 6 weeks to avoid layout shifts when navigating between months. Like firstDayOfWeek, this must be handled carefully to avoid unexpected behavior in various locales.
  5. Adds anchorDate as an argument to isDateUnavailable in RangeCalendar. This lets you change the available dates based on the first date the user picks, e.g. limit to a certain number of days.

[ButtonContext, {...buttonProps, isPressed: state.isOpen}],
[LabelContext, {...labelProps, ref: labelRef, elementType: 'span'}],
[CalendarContext, calendarProps],
[CalendarContext, calendarProps as any],
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contexts don't support generics so CalendarContext is defined as having either single or multiple selection. The calendarProps returned by useDatePicker only supports single selection, so the onChange props technically conflict, but this can never happen. I'm not sure of a better solution...

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 18, 2026

} else if (Array.isArray(state.value)) {
let dates = state.value.map(date => dateFormatter.format(date.toDate(state.timeZone)));
let formatted = listFormatter.format(dates);
return stringFormatter.format('selectedDateDescription', {date: formatted});
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this means that for multi-select calendars, every time you select a date the screen reader reads off all selected dates. That could get kinda verbose if you had a lot selected. We do read off the entire range in this case though so I followed that. If we want to change it to only read the latest one, we'll need a new translation for the deselect case.

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 18, 2026

@devongovett devongovett changed the title feat: Add Calendar multi-select, week/day views, weeksInMonth, and month/year pickers feat: Add Calendar multi-select, week/day views, weeksInMonth, month/year pickers, and unavailable anchor date Apr 18, 2026
@rspbot
Copy link
Copy Markdown

rspbot commented Apr 18, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 18, 2026

## API Changes

react-aria-components

/react-aria-components:Calendar

-Calendar <T extends DateValue> {
+Calendar <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
-  children?: ChildrenOrFunction<CalendarRenderProps>
-  className?: ClassNameOrFunction<CalendarRenderProps> = 'react-aria-Calendar'
+  children?: ChildrenOrFunction<CalendarRenderProps<CalendarSelectionMode>>
+  className?: ClassNameOrFunction<CalendarRenderProps<CalendarSelectionMode>> = 'react-aria-Calendar'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CalendarRenderProps>
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CalendarRenderProps<CalendarSelectionMode>>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   slot?: string | null
-  style?: StyleOrFunction<CalendarRenderProps>
-  value?: DateValue | null
+  style?: StyleOrFunction<CalendarRenderProps<CalendarSelectionMode>>
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

/react-aria-components:RangeCalendar

 RangeCalendar <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   children?: ChildrenOrFunction<RangeCalendarRenderProps>
   className?: ClassNameOrFunction<RangeCalendarRenderProps> = 'react-aria-RangeCalendar'
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, RangeCalendarRenderProps>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   slot?: string | null
   style?: StyleOrFunction<RangeCalendarRenderProps>
   value?: RangeValue<DateValue> | null
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

/react-aria-components:DateRangePicker

 DateRangePicker <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   children?: ChildrenOrFunction<DateRangePickerRenderProps>
   className?: ClassNameOrFunction<DateRangePickerRenderProps> = 'react-aria-DateRangePicker'
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   endName?: string
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, DateRangePickerRenderProps>
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldForceLeadingZeros?: boolean
   slot?: string | null
   startName?: string
   style?: StyleOrFunction<DateRangePickerRenderProps>
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

/react-aria-components:Heading

 Heading extends HTMLAttributes {
-  level?: number
+  className?: string = 'react-aria-Heading'
+  level?: number = 3
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
 }

/react-aria-components:CalendarProps

-CalendarProps <T extends DateValue> {
+CalendarProps <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
-  children?: ChildrenOrFunction<CalendarRenderProps>
-  className?: ClassNameOrFunction<CalendarRenderProps> = 'react-aria-Calendar'
+  children?: ChildrenOrFunction<CalendarRenderProps<CalendarSelectionMode>>
+  className?: ClassNameOrFunction<CalendarRenderProps<CalendarSelectionMode>> = 'react-aria-Calendar'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CalendarRenderProps>
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CalendarRenderProps<CalendarSelectionMode>>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   slot?: string | null
-  style?: StyleOrFunction<CalendarRenderProps>
-  value?: DateValue | null
+  style?: StyleOrFunction<CalendarRenderProps<CalendarSelectionMode>>
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

/react-aria-components:CalendarRenderProps

-CalendarRenderProps {
+CalendarRenderProps <M extends CalendarSelectionMode = 'single'> {
   isDisabled: boolean
   isInvalid: boolean
-  state: CalendarState
+  state: CalendarState<CalendarSelectionMode>
 }

/react-aria-components:RangeCalendarProps

 RangeCalendarProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   children?: ChildrenOrFunction<RangeCalendarRenderProps>
   className?: ClassNameOrFunction<RangeCalendarRenderProps> = 'react-aria-RangeCalendar'
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, RangeCalendarRenderProps>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   slot?: string | null
   style?: StyleOrFunction<RangeCalendarRenderProps>
   value?: RangeValue<DateValue> | null
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

/react-aria-components:DateRangePickerProps

 DateRangePickerProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   children?: ChildrenOrFunction<DateRangePickerRenderProps>
   className?: ClassNameOrFunction<DateRangePickerRenderProps> = 'react-aria-DateRangePicker'
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   endName?: string
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, DateRangePickerRenderProps>
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldForceLeadingZeros?: boolean
   slot?: string | null
   startName?: string
   style?: StyleOrFunction<DateRangePickerRenderProps>
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

/react-aria-components:HeadingProps

 HeadingProps {
-  level?: number
+  className?: string = 'react-aria-Heading'
+  level?: number = 3
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
 }

/react-aria-components:CalendarState

-CalendarState {
+CalendarState <M extends CalendarSelectionMode = 'single'> {
   focusNextDay: () => void
   focusNextPage: () => void
   focusNextRow: () => void
   focusNextSection: (boolean) => void
   focusPreviousDay: () => void
   focusPreviousPage: () => void
   focusPreviousRow: () => void
   focusPreviousSection: (boolean) => void
   focusSectionEnd: () => void
   focusSectionStart: () => void
   focusedDate: CalendarDate
   getDatesInWeek: (number, CalendarDate) => Array<CalendarDate | null>
+  getWeeksInMonth: (CalendarDate) => number
   isCellDisabled: (CalendarDate) => boolean
   isCellFocused: (CalendarDate) => boolean
   isCellUnavailable: (CalendarDate) => boolean
   isDisabled: boolean
   isFocused: boolean
   isInvalid: (CalendarDate) => boolean
   isNextVisibleRangeInvalid: () => boolean
   isPreviousVisibleRangeInvalid: () => boolean
   isReadOnly: boolean
   isSelected: (CalendarDate) => boolean
   isValueInvalid: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   selectDate: (CalendarDate) => void
   selectFocusedDate: () => void
+  selectionMode: CalendarSelectionMode
   setFocused: (boolean) => void
   setFocusedDate: (CalendarDate) => void
-  setValue: (CalendarDate | null) => void
+  setValue: (CalendarValueType<CalendarDate | null, CalendarSelectionMode>) => void
   timeZone: string
-  value: CalendarDate | null
+  value: CalendarValueType<CalendarDate | null, CalendarSelectionMode>
+  visibleDuration: DateDuration
   visibleRange: RangeValue<CalendarDate>
 }

/react-aria-components:RangeCalendarState

 RangeCalendarState <T extends DateValue = DateValue> {
   anchorDate: CalendarDate | null
   clearSelection: () => void
+  commitSelection: () => void
+  focusNearestAvailableDate: (CalendarDate) => void
   focusNextDay: () => void
   focusNextPage: () => void
   focusNextRow: () => void
   focusNextSection: (boolean) => void
   focusPreviousDay: () => void
   focusPreviousPage: () => void
   focusPreviousRow: () => void
   focusPreviousSection: (boolean) => void
   focusSectionEnd: () => void
   focusSectionStart: () => void
   focusedDate: CalendarDate
   getDatesInWeek: (number, CalendarDate) => Array<CalendarDate | null>
+  getWeeksInMonth: (CalendarDate) => number
   highlightDate: (CalendarDate) => void
   highlightedRange: RangeValue<CalendarDate> | null
   isCellDisabled: (CalendarDate) => boolean
   isCellFocused: (CalendarDate) => boolean
   isCellUnavailable: (CalendarDate) => boolean
   isDisabled: boolean
   isDragging: boolean
   isFocused: boolean
   isInvalid: (CalendarDate) => boolean
   isNextVisibleRangeInvalid: () => boolean
   isPreviousVisibleRangeInvalid: () => boolean
   isReadOnly: boolean
   isSelected: (CalendarDate) => boolean
   isValueInvalid: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   selectDate: (CalendarDate) => void
   selectFocusedDate: () => void
   setAnchorDate: (CalendarDate | null) => void
   setDragging: (boolean) => void
   setFocused: (boolean) => void
   setFocusedDate: (CalendarDate) => void
   setValue: (RangeValue<DateValue> | null) => void
   timeZone: string
   value: RangeValue<DateValue> | null
+  visibleDuration: DateDuration
   visibleRange: RangeValue<CalendarDate>
 }

/react-aria-components:CalendarMonthPicker

+CalendarMonthPicker {
+  children: (CalendarMonthPickerAria) => JSX.Element
+  format?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow'
+}

/react-aria-components:CalendarYearPicker

+CalendarYearPicker {
+  children: (CalendarYearPickerAria) => JSX.Element
+  format?: CalendarYearPickerFormatOptions
+  visibleYears?: number = 20
+}

/react-aria-components:CalendarHeading

+CalendarHeading {
+  className?: string = 'react-aria-CalendarHeading'
+  format?: CalendarHeadingFormatOptions
+  level?: number = 3
+  offset?: DateDuration = 0
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+}

/react-aria-components:CalendarMonthPickerProps

+CalendarMonthPickerProps {
+  children: (CalendarMonthPickerAria) => JSX.Element
+  format?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow'
+}

/react-aria-components:CalendarYearPickerProps

+CalendarYearPickerProps {
+  children: (CalendarYearPickerAria) => JSX.Element
+  format?: CalendarYearPickerFormatOptions
+  visibleYears?: number = 20
+}

/react-aria-components:CalendarHeadingProps

+CalendarHeadingProps {
+  className?: string = 'react-aria-CalendarHeading'
+  format?: CalendarHeadingFormatOptions
+  level?: number = 3
+  offset?: DateDuration = 0
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+}

@react-aria/calendar

/@react-aria/calendar:useCalendar

-useCalendar <T extends DateValue> {
+useCalendar <M extends CalendarSelectionMode = 'single', T extends DateValue> {
-  props: AriaCalendarProps<T>
-  state: CalendarState
+  props: AriaCalendarProps<T, M>
+  state: CalendarState<M>
   returnVal: undefined
 }

/@react-aria/calendar:useCalendarGrid

 useCalendarGrid {
   props: AriaCalendarGridProps
-  state: CalendarState | RangeCalendarState
+  state: CalendarState<CalendarSelectionMode> | RangeCalendarState
   returnVal: undefined
 }

/@react-aria/calendar:useCalendarCell

 useCalendarCell {
   props: AriaCalendarCellProps
-  state: CalendarState | RangeCalendarState
+  state: CalendarState<CalendarSelectionMode> | RangeCalendarState
   ref: RefObject<HTMLElement | null>
   returnVal: undefined
 }

/@react-aria/calendar:AriaCalendarProps

-AriaCalendarProps <T extends DateValue> {
+AriaCalendarProps <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
-  value?: DateValue | null
+  selectionMode?: CalendarSelectionMode = "single"
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
+  weeksInMonth?: number
 }

/@react-aria/calendar:AriaRangeCalendarProps

 AriaRangeCalendarProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   value?: RangeValue<DateValue> | null
+  weeksInMonth?: number
 }

/@react-aria/calendar:CalendarProps

-CalendarProps <T extends DateValue> {
+CalendarProps <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
-  value?: DateValue | null
+  selectionMode?: CalendarSelectionMode = "single"
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
+  weeksInMonth?: number
 }

/@react-aria/calendar:RangeCalendarProps

 RangeCalendarProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   value?: RangeValue<DateValue> | null
+  weeksInMonth?: number
 }

@react-aria/datepicker

/@react-aria/datepicker:AriaDateRangePickerProps

 AriaDateRangePickerProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   label?: ReactNode
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldForceLeadingZeros?: boolean
   startName?: string
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'aria' | 'native' = 'aria'
   value?: RangeValue<DateValue> | null
 }

@react-spectrum/calendar

/@react-spectrum/calendar:Calendar

 Calendar <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   bottom?: Responsive<DimensionValue>
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   end?: Responsive<DimensionValue>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   focusedValue?: DateValue | null
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isHidden?: Responsive<boolean>
   isInvalid?: boolean
   isReadOnly?: boolean = false
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
-  value?: DateValue | null
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleMonths?: number = 1
+  weeksInMonth?: number
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/calendar:RangeCalendar

 RangeCalendar <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   bottom?: Responsive<DimensionValue>
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   end?: Responsive<DimensionValue>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   focusedValue?: DateValue | null
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isHidden?: Responsive<boolean>
   isInvalid?: boolean
   isReadOnly?: boolean = false
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   value?: RangeValue<DateValue> | null
   visibleMonths?: number = 1
+  weeksInMonth?: number
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/calendar:SpectrumCalendarProps

 SpectrumCalendarProps <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   bottom?: Responsive<DimensionValue>
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   end?: Responsive<DimensionValue>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   focusedValue?: DateValue | null
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isHidden?: Responsive<boolean>
   isInvalid?: boolean
   isReadOnly?: boolean = false
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
-  value?: DateValue | null
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleMonths?: number = 1
+  weeksInMonth?: number
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/calendar:SpectrumRangeCalendarProps

 SpectrumRangeCalendarProps <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   bottom?: Responsive<DimensionValue>
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   end?: Responsive<DimensionValue>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   focusedValue?: DateValue | null
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isHidden?: Responsive<boolean>
   isInvalid?: boolean
   isReadOnly?: boolean = false
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   value?: RangeValue<DateValue> | null
   visibleMonths?: number = 1
+  weeksInMonth?: number
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/datepicker

/@react-spectrum/datepicker:DateRangePicker

 DateRangePicker <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   bottom?: Responsive<DimensionValue>
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   end?: Responsive<DimensionValue>
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   form?: string
   granularity?: Granularity
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isHidden?: Responsive<boolean>
   isOpen?: boolean
   isQuiet?: boolean = false
   isRequired?: boolean
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   showFormatHelpText?: boolean = false
   start?: Responsive<DimensionValue>
   startName?: string
   top?: Responsive<DimensionValue>
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'aria' | 'native' = 'aria'
   validationState?: ValidationState
   value?: RangeValue<DateValue> | null
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/datepicker:SpectrumDateRangePickerProps

 SpectrumDateRangePickerProps <T extends DateValue> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   bottom?: Responsive<DimensionValue>
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   end?: Responsive<DimensionValue>
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   form?: string
   granularity?: Granularity
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isHidden?: Responsive<boolean>
   isOpen?: boolean
   isQuiet?: boolean = false
   isRequired?: boolean
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minValue?: DateValue | null
   minWidth?: Responsive<DimensionValue>
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   order?: Responsive<number>
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   showFormatHelpText?: boolean = false
   start?: Responsive<DimensionValue>
   startName?: string
   top?: Responsive<DimensionValue>
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'aria' | 'native' = 'aria'
   validationState?: ValidationState
   value?: RangeValue<DateValue> | null
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/s2

/@react-spectrum/s2:Calendar

-Calendar <T extends DateValue> {
+Calendar <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   slot?: string | null
   styles?: StylesProp
-  value?: DateValue | null
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleMonths?: number = 1
 }

/@react-spectrum/s2:DateRangePicker

 DateRangePicker <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   startName?: string
   styles?: StylesProp
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

/@react-spectrum/s2:RangeCalendar

 RangeCalendar <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   slot?: string | null
   styles?: StylesProp
   value?: RangeValue<DateValue> | null
   visibleMonths?: number = 1
 }

/@react-spectrum/s2:CalendarProps

-CalendarProps <T extends DateValue> {
+CalendarProps <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  selectionMode?: CalendarSelectionMode = "single"
   slot?: string | null
   styles?: StylesProp
-  value?: DateValue | null
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleMonths?: number = 1
 }

/@react-spectrum/s2:DateRangePickerProps

 DateRangePickerProps <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   startName?: string
   styles?: StylesProp
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

/@react-spectrum/s2:RangeCalendarProps

 RangeCalendarProps <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean = false
   commitBehavior?: 'clear' | 'reset' | 'select' = 'select'
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   id?: string
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   slot?: string | null
   styles?: StylesProp
   value?: RangeValue<DateValue> | null
   visibleMonths?: number = 1
 }

@react-stately/calendar

/@react-stately/calendar:useCalendarState

-useCalendarState <T extends DateValue = DateValue> {
+useCalendarState <M extends CalendarSelectionMode = 'single', T extends DateValue = DateValue> {
-  props: CalendarStateOptions<T>
+  props: CalendarStateOptions<T, M>
   returnVal: undefined
 }

/@react-stately/calendar:CalendarProps

-CalendarProps <T extends DateValue> {
+CalendarProps <M extends CalendarSelectionMode = 'single', T extends DateValue> {
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
-  value?: DateValue | null
+  selectionMode?: CalendarSelectionMode = "single"
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
+  weeksInMonth?: number
 }

/@react-stately/calendar:CalendarStateOptions

-CalendarStateOptions <T extends DateValue = DateValue> {
+CalendarStateOptions <M extends CalendarSelectionMode = 'single', T extends DateValue = DateValue> {
   autoFocus?: boolean = false
   createCalendar: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
-  defaultValue?: DateValue | null
+  defaultValue?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   locale: string
   maxValue?: DateValue | null
   minValue?: DateValue | null
-  onChange?: (MappedDateValue<DateValue>) => void
+  onChange?: (CalendarValueType<MappedDateValue<DateValue>, CalendarSelectionMode>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
-  value?: DateValue | null
+  selectionMode?: CalendarSelectionMode = "single"
+  value?: CalendarValueType<DateValue | null, CalendarSelectionMode>
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

/@react-stately/calendar:CalendarPropsBase

 CalendarPropsBase {
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
-  isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
+  weeksInMonth?: number
 }

/@react-stately/calendar:CalendarState

-CalendarState {
+CalendarState <M extends CalendarSelectionMode = 'single'> {
   focusNextDay: () => void
   focusNextPage: () => void
   focusNextRow: () => void
   focusNextSection: (boolean) => void
   focusPreviousDay: () => void
   focusPreviousPage: () => void
   focusPreviousRow: () => void
   focusPreviousSection: (boolean) => void
   focusSectionEnd: () => void
   focusSectionStart: () => void
   focusedDate: CalendarDate
   getDatesInWeek: (number, CalendarDate) => Array<CalendarDate | null>
+  getWeeksInMonth: (CalendarDate) => number
   isCellDisabled: (CalendarDate) => boolean
   isCellFocused: (CalendarDate) => boolean
   isCellUnavailable: (CalendarDate) => boolean
   isDisabled: boolean
   isFocused: boolean
   isInvalid: (CalendarDate) => boolean
   isNextVisibleRangeInvalid: () => boolean
   isPreviousVisibleRangeInvalid: () => boolean
   isReadOnly: boolean
   isSelected: (CalendarDate) => boolean
   isValueInvalid: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   selectDate: (CalendarDate) => void
   selectFocusedDate: () => void
+  selectionMode: CalendarSelectionMode
   setFocused: (boolean) => void
   setFocusedDate: (CalendarDate) => void
-  setValue: (CalendarDate | null) => void
+  setValue: (CalendarValueType<CalendarDate | null, CalendarSelectionMode>) => void
   timeZone: string
-  value: CalendarDate | null
+  value: CalendarValueType<CalendarDate | null, CalendarSelectionMode>
+  visibleDuration: DateDuration
   visibleRange: RangeValue<CalendarDate>
 }

/@react-stately/calendar:RangeCalendarProps

 RangeCalendarProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   autoFocus?: boolean = false
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   value?: RangeValue<DateValue> | null
+  weeksInMonth?: number
 }

/@react-stately/calendar:RangeCalendarState

 RangeCalendarState <T extends DateValue = DateValue> {
   anchorDate: CalendarDate | null
   clearSelection: () => void
+  commitSelection: () => void
+  focusNearestAvailableDate: (CalendarDate) => void
   focusNextDay: () => void
   focusNextPage: () => void
   focusNextRow: () => void
   focusNextSection: (boolean) => void
   focusPreviousDay: () => void
   focusPreviousPage: () => void
   focusPreviousRow: () => void
   focusPreviousSection: (boolean) => void
   focusSectionEnd: () => void
   focusSectionStart: () => void
   focusedDate: CalendarDate
   getDatesInWeek: (number, CalendarDate) => Array<CalendarDate | null>
+  getWeeksInMonth: (CalendarDate) => number
   highlightDate: (CalendarDate) => void
   highlightedRange: RangeValue<CalendarDate> | null
   isCellDisabled: (CalendarDate) => boolean
   isCellFocused: (CalendarDate) => boolean
   isCellUnavailable: (CalendarDate) => boolean
   isDisabled: boolean
   isDragging: boolean
   isFocused: boolean
   isInvalid: (CalendarDate) => boolean
   isNextVisibleRangeInvalid: () => boolean
   isPreviousVisibleRangeInvalid: () => boolean
   isReadOnly: boolean
   isSelected: (CalendarDate) => boolean
   isValueInvalid: boolean
   maxValue?: DateValue | null
   minValue?: DateValue | null
   selectDate: (CalendarDate) => void
   selectFocusedDate: () => void
   setAnchorDate: (CalendarDate | null) => void
   setDragging: (boolean) => void
   setFocused: (boolean) => void
   setFocusedDate: (CalendarDate) => void
   setValue: (RangeValue<DateValue> | null) => void
   timeZone: string
   value: RangeValue<DateValue> | null
+  visibleDuration: DateDuration
   visibleRange: RangeValue<CalendarDate>
 }

/@react-stately/calendar:RangeCalendarStateOptions

 RangeCalendarStateOptions <T extends DateValue = DateValue> {
   allowsNonContiguousRanges?: boolean
   autoFocus?: boolean = false
   createCalendar: (CalendarIdentifier) => Calendar
   defaultFocusedValue?: DateValue | null
   defaultValue?: RangeValue<DateValue> | null
   errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   focusedValue?: DateValue | null
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean = false
   isInvalid?: boolean
   isReadOnly?: boolean = false
   locale: string
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onChange?: (RangeValue<MappedDateValue<DateValue>>) => void
   onFocusChange?: (CalendarDate) => void
   pageBehavior?: PageBehavior = visible
   selectionAlignment?: 'start' | 'center' | 'end' = 'center'
   value?: RangeValue<DateValue> | null
   visibleDuration?: DateDuration = {months: 1}
+  weeksInMonth?: number
 }

@react-stately/datepicker

/@react-stately/datepicker:DateRangePickerStateOptions

 DateRangePickerStateOptions <T extends DateValue = DateValue> {
   allowsNonContiguousRanges?: boolean
   autoFocus?: boolean
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   label?: ReactNode
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldForceLeadingZeros?: boolean
   startName?: string
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'aria' | 'native' = 'aria'
   value?: RangeValue<DateValue> | null
 }

/@react-stately/datepicker:DateRangePickerProps

 DateRangePickerProps <T extends DateValue> {
   allowsNonContiguousRanges?: boolean
   autoFocus?: boolean
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
   errorMessage?: ReactNode | (ValidationResult) => ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   granularity?: Granularity
   hideTimeZone?: boolean = false
   hourCycle?: number | number
-  isDateUnavailable?: (DateValue) => boolean
+  isDateUnavailable?: (DateValue, CalendarDate | null) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   label?: ReactNode
   maxValue?: DateValue | null
   minValue?: DateValue | null
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldForceLeadingZeros?: boolean
   startName?: string
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'aria' | 'native' = 'aria'
   value?: RangeValue<DateValue> | null
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment