@@ -27,7 +27,7 @@ import {
2727 toCalendarDate ,
2828 today
2929} from '@internationalized/date' ;
30- import { CalendarProps , DateValue } from '@react-types/calendar' ;
30+ import { CalendarProps , DateValue , MappedDateValue } from '@react-types/calendar' ;
3131import { CalendarState } from './types' ;
3232import { useControlledState } from '@react-stately/utils' ;
3333import { useMemo , useState } from 'react' ;
@@ -51,7 +51,6 @@ export interface CalendarStateOptions<T extends DateValue = DateValue> extends C
5151 /** Determines how to align the initial selection relative to the visible date range. */
5252 selectionAlignment ?: 'start' | 'center' | 'end'
5353}
54-
5554/**
5655 * Provides state management for a calendar component.
5756 * A calendar displays one or more date grids and allows users to select a single date.
@@ -71,7 +70,7 @@ export function useCalendarState<T extends DateValue = DateValue>(props: Calenda
7170 } = props ;
7271 let calendar = useMemo ( ( ) => createCalendar ( resolvedOptions . calendar ) , [ createCalendar , resolvedOptions . calendar ] ) ;
7372
74- let [ value , setControlledValue ] = useControlledState < DateValue > ( props . value , props . defaultValue , props . onChange ) ;
73+ let [ value , setControlledValue ] = useControlledState < DateValue | null , MappedDateValue < T > > ( props . value ! , props . defaultValue ?? null ! , props . onChange ) ;
7574 let calendarDateValue = useMemo ( ( ) => value ? toCalendar ( toCalendarDate ( value ) , calendar ) : null , [ value , calendar ] ) ;
7675 let timeZone = useMemo ( ( ) => value && 'timeZone' in value ? value . timeZone : resolvedOptions . timeZone , [ value , resolvedOptions . timeZone ] ) ;
7776 let focusedCalendarDate = useMemo ( ( ) => (
@@ -138,25 +137,26 @@ export function useCalendarState<T extends DateValue = DateValue>(props: Calenda
138137
139138 function setValue ( newValue : CalendarDate | null ) {
140139 if ( ! props . isDisabled && ! props . isReadOnly ) {
141- if ( newValue === null ) {
140+ let localValue = newValue ;
141+ if ( localValue === null ) {
142142 setControlledValue ( null ) ;
143143 return ;
144144 }
145- newValue = constrainValue ( newValue , minValue , maxValue ) ;
146- newValue = previousAvailableDate ( newValue , startDate , isDateUnavailable ) ;
147- if ( ! newValue ) {
145+ localValue = constrainValue ( localValue , minValue , maxValue ) ;
146+ localValue = previousAvailableDate ( localValue , startDate , isDateUnavailable ) ;
147+ if ( ! localValue ) {
148148 return ;
149149 }
150150
151151 // The display calendar should not have any effect on the emitted value.
152152 // Emit dates in the same calendar as the original value, if any, otherwise gregorian.
153- newValue = toCalendar ( newValue , value ?. calendar || new GregorianCalendar ( ) ) ;
153+ localValue = toCalendar ( localValue , value ?. calendar || new GregorianCalendar ( ) ) ;
154154
155155 // Preserve time if the input value had one.
156156 if ( value && 'hour' in value ) {
157- setControlledValue ( value . set ( newValue ) ) ;
157+ setControlledValue ( value . set ( localValue ) ) ;
158158 } else {
159- setControlledValue ( newValue ) ;
159+ setControlledValue ( localValue ) ;
160160 }
161161 }
162162 }
@@ -173,7 +173,7 @@ export function useCalendarState<T extends DateValue = DateValue>(props: Calenda
173173 return isInvalid ( calendarDateValue , minValue , maxValue ) ;
174174 } , [ calendarDateValue , isDateUnavailable , minValue , maxValue ] ) ;
175175 let isValueInvalid = props . isInvalid || props . validationState === 'invalid' || isUnavailable ;
176- let validationState : ValidationState = isValueInvalid ? 'invalid' : null ;
176+ let validationState : ValidationState | null = isValueInvalid ? 'invalid' : null ;
177177
178178 let pageDuration = useMemo ( ( ) => {
179179 if ( pageBehavior === 'visible' ) {
@@ -184,8 +184,8 @@ export function useCalendarState<T extends DateValue = DateValue>(props: Calenda
184184 } , [ pageBehavior , visibleDuration ] ) ;
185185
186186 return {
187- isDisabled : props . isDisabled ,
188- isReadOnly : props . isReadOnly ,
187+ isDisabled : props . isDisabled ?? false ,
188+ isReadOnly : props . isReadOnly ?? false ,
189189 value : calendarDateValue ,
190190 setValue,
191191 visibleRange : {
@@ -308,25 +308,25 @@ export function useCalendarState<T extends DateValue = DateValue>(props: Calenda
308308 return isFocused && focusedDate && isSameDay ( date , focusedDate ) ;
309309 } ,
310310 isCellDisabled ( date ) {
311- return props . isDisabled || date . compare ( startDate ) < 0 || date . compare ( endDate ) > 0 || this . isInvalid ( date , minValue , maxValue ) ;
311+ return props . isDisabled || date . compare ( startDate ) < 0 || date . compare ( endDate ) > 0 || this . isInvalid ( date ) ;
312312 } ,
313313 isCellUnavailable ( date ) {
314- return props . isDateUnavailable && props . isDateUnavailable ( date ) ;
314+ return props . isDateUnavailable ? props . isDateUnavailable ( date ) : false ;
315315 } ,
316316 isPreviousVisibleRangeInvalid ( ) {
317317 let prev = startDate . subtract ( { days : 1 } ) ;
318- return isSameDay ( prev , startDate ) || this . isInvalid ( prev , minValue , maxValue ) ;
318+ return isSameDay ( prev , startDate ) || this . isInvalid ( prev ) ;
319319 } ,
320320 isNextVisibleRangeInvalid ( ) {
321321 // Adding may return the same date if we reached the end of time
322322 // according to the calendar system (e.g. 9999-12-31).
323323 let next = endDate . add ( { days : 1 } ) ;
324- return isSameDay ( next , endDate ) || this . isInvalid ( next , minValue , maxValue ) ;
324+ return isSameDay ( next , endDate ) || this . isInvalid ( next ) ;
325325 } ,
326326 getDatesInWeek ( weekIndex , from = startDate ) {
327327 // let date = startOfWeek(from, locale);
328328 let date = from . add ( { weeks : weekIndex } ) ;
329- let dates = [ ] ;
329+ let dates : ( CalendarDate | null ) [ ] = [ ] ;
330330
331331 date = startOfWeek ( date , locale ) ;
332332
0 commit comments