11import React , { useState } from 'react'
2- import { func , instanceOf , object , objectOf , oneOf , string } from 'prop-types'
3- import { isSameDay , isAfter , isBefore , startOfMonth , startOfDay } from 'date-fns'
4- import { isSelectable , mergeModifiers , setTime } from './utils'
2+ import { func , instanceOf , number , object , objectOf , oneOf , string } from 'prop-types'
3+ import { differenceInDays , isSameDay , isAfter , isBefore , startOfMonth , startOfDay } from 'date-fns'
4+ import { isRangeLengthValid , isSelectable , mergeModifiers , setTime } from './utils'
55import { START_DATE , END_DATE } from './constants'
66import useControllableState from './useControllableState'
77import Calendar from './Calendar'
@@ -18,12 +18,18 @@ export default function DateRangePickerCalendar({
1818 onMonthChange,
1919 minimumDate,
2020 maximumDate,
21+ minimumLength,
22+ maximumLength,
2123 modifiers : receivedModifiers ,
2224 modifiersClassNames,
2325 weekdayFormat
2426} ) {
2527 const [ hoveredDate , setHoveredDate ] = useState ( )
26- const [ month , setMonth ] = useControllableState ( receivedMonth , onMonthChange , startOfMonth ( startDate || endDate || new Date ( ) ) )
28+ const [ month , setMonth ] = useControllableState (
29+ receivedMonth ,
30+ onMonthChange ,
31+ startOfMonth ( startDate || endDate || new Date ( ) )
32+ )
2733
2834 const displayedStartDate =
2935 focus === START_DATE && ! startDate && endDate && hoveredDate && ! isSameDay ( hoveredDate , endDate )
@@ -47,46 +53,53 @@ export default function DateRangePickerCalendar({
4753 isMiddleDate ( date ) ||
4854 isEndDate ( date ) ||
4955 isSameDay ( date , startDate ) ||
50- isSameDay ( date , endDate )
51- ) ,
56+ isSameDay ( date , endDate ) ) ,
5257 selectedStart : isStartDate ,
5358 selectedMiddle : isMiddleDate ,
5459 selectedEnd : isEndDate ,
55- disabled : date => ( focus === START_DATE && isEndDate ( date ) ) || ( focus === END_DATE && isStartDate ( date ) )
60+ disabled : date =>
61+ ( focus === START_DATE &&
62+ endDate &&
63+ ( ( differenceInDays ( endDate , date ) < minimumLength && ( ! startDate || ! isAfter ( date , endDate ) ) ) ||
64+ ( ! startDate && maximumLength && differenceInDays ( endDate , date ) > maximumLength ) ) ) ||
65+ ( focus === END_DATE &&
66+ startDate &&
67+ ( ( differenceInDays ( date , startDate ) < minimumLength && ( ! endDate || ! isBefore ( date , startDate ) ) ) ||
68+ ( ! endDate && maximumLength && differenceInDays ( date , startDate ) > maximumLength ) ) )
5669 } ,
5770 receivedModifiers
5871 )
5972
6073 const handleSelectDate = date => {
6174 if ( focus === START_DATE ) {
62- if ( endDate && ! isAfter ( endDate , date ) ) {
75+ const invalidEndDate =
76+ endDate && ! isRangeLengthValid ( { startDate : date , endDate } , { minimumLength, maximumLength } )
77+
78+ if ( invalidEndDate ) {
6379 onEndDateChange ( null )
6480 }
6581
6682 onStartDateChange ( startDate ? setTime ( date , startDate ) : date )
6783 onFocusChange ( END_DATE )
6884 } else if ( focus === END_DATE ) {
69- const invalidStartDate = startDate && ! isBefore ( startDate , date )
85+ const invalidStartDate =
86+ startDate && ! isRangeLengthValid ( { startDate, endDate : date } , { minimumLength, maximumLength } )
7087
7188 if ( invalidStartDate ) {
7289 onStartDateChange ( null )
7390 }
7491
7592 onEndDateChange ( endDate ? setTime ( date , endDate ) : date )
76- onFocusChange ( invalidStartDate ? START_DATE : null )
93+ onFocusChange ( invalidStartDate || ! startDate ? START_DATE : null )
7794 }
7895 }
7996
80- const handleHoverDate = date => {
81- setHoveredDate ( date )
82- }
83-
8497 return (
8598 < Calendar
8699 locale = { locale }
87100 month = { month }
88101 onMonthChange = { setMonth }
89- onDayHover = { handleHoverDate }
102+ onDayHover = { setHoveredDate }
90103 onDayClick = { handleSelectDate }
91104 minimumDate = { minimumDate }
92105 maximumDate = { maximumDate }
@@ -109,6 +122,8 @@ DateRangePickerCalendar.propTypes = {
109122 onMonthChange : func ,
110123 minimumDate : instanceOf ( Date ) ,
111124 maximumDate : instanceOf ( Date ) ,
125+ minimumLength : number ,
126+ maximumLength : number ,
112127 modifiers : objectOf ( func ) ,
113128 modifiersClassNames : objectOf ( string ) ,
114129 weekdayFormat : string
@@ -117,5 +132,7 @@ DateRangePickerCalendar.propTypes = {
117132DateRangePickerCalendar . defaultProps = {
118133 onStartDateChange : ( ) => { } ,
119134 onEndDateChange : ( ) => { } ,
120- onFocusChange : ( ) => { }
135+ onFocusChange : ( ) => { } ,
136+ minimumLength : 0 ,
137+ maximumLength : null
121138}
0 commit comments