1
- import React , { useState } from 'react' ;
1
+ import React , { useEffect , useState } from 'react' ;
2
2
import {
3
3
format ,
4
4
startOfMonth ,
@@ -17,25 +17,45 @@ import Footer from './components/Footer';
17
17
import ShortCuts from './components/ShortCuts' ;
18
18
import CalendarHeader from './components/CalendarHeader' ;
19
19
20
- const Calendar = ( { initialMonth1, initialMonth2, handleValueChange, closeDatePicker } ) => {
20
+ const Calendar = ( {
21
+ initialMonth1,
22
+ initialMonth2,
23
+ handleValueChange,
24
+ closeDatePicker,
25
+ showAsSingle = false ,
26
+ useRange = true ,
27
+ } ) => {
21
28
const daysOfWeek = [ 'Sun' , 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' ] ;
22
29
const [ selectedDays1 , setSelectedDays1 ] = useState ( [ ] ) ;
23
30
const [ selectedDays2 , setSelectedDays2 ] = useState ( [ ] ) ;
24
31
const [ month1 , setMonth1 ] = useState ( initialMonth1 ) ;
25
32
const [ month2 , setMonth2 ] = useState ( initialMonth2 ) ;
26
33
const [ selectedRange , setSelectedRange ] = useState ( { start : null , end : null } ) ;
27
34
35
+ useEffect ( ( ) => {
36
+ if ( ! useRange && showAsSingle ) {
37
+ setSelectedRange ( { start : new Date ( ) , end : null } ) ;
38
+ setSelectedDays1 ( ( prev ) => [ ...prev , new Date ( ) ] ) ;
39
+ }
40
+ } , [ useRange , showAsSingle ] ) ;
41
+
28
42
const handleDayClick = ( day , setSelectedDays ) => {
29
- setSelectedDays ( ( prev ) => [ ...prev , day ] ) ;
30
- if ( ! selectedRange . start ) {
43
+ if ( ! useRange ) {
44
+ const newDay = new Date ( month2 . getFullYear ( ) , month2 . getMonth ( ) , day . getDate ( ) ) ;
45
+ setSelectedDays ( ( prev ) => [ ...prev , newDay ] ) ;
46
+ setSelectedRange ( { start : newDay , end : null } ) ;
47
+ } else if ( ! selectedRange . start ) {
48
+ setSelectedDays ( ( prev ) => [ ...prev , day ] ) ;
31
49
setSelectedRange ( { start : day , end : null } ) ;
32
50
} else if ( ! selectedRange . end ) {
51
+ setSelectedDays ( ( prev ) => [ ...prev , day ] ) ;
33
52
if ( isBefore ( day , selectedRange . start ) ) {
34
53
setSelectedRange ( { start : day , end : selectedRange . start } ) ;
35
54
} else {
36
55
setSelectedRange ( { start : selectedRange . start , end : day } ) ;
37
56
}
38
57
} else {
58
+ setSelectedDays ( [ day ] ) ;
39
59
setSelectedRange ( { start : day , end : null } ) ;
40
60
}
41
61
} ;
@@ -75,13 +95,16 @@ const Calendar = ({ initialMonth1, initialMonth2, handleValueChange, closeDatePi
75
95
( selectedRange . end && isSameDay ( day , selectedRange . end ) ) || isEndOfWeek
76
96
? 'rounded-r-full'
77
97
: ''
78
- } `} >
98
+ } `}
99
+ >
79
100
< button
80
101
onClick = { ( ) => handleDayClick ( day , setSelectedDays ) }
81
102
className = { `
82
103
w-10 h-10 text-sm flex justify-center items-center
83
104
${
84
- selectedDays . includes ( day ) || isStartOrEndDay
105
+ selectedDays . includes ( day ) ||
106
+ isStartOrEndDay ||
107
+ ( showAsSingle && ! useRange && isSameDay ( day , selectedRange . start ) )
85
108
? 'bg-blue-600 dark:bg-blue-500 rounded-full text-red-50 hover:text-red-50'
86
109
: ''
87
110
}
@@ -94,7 +117,8 @@ const Calendar = ({ initialMonth1, initialMonth2, handleValueChange, closeDatePi
94
117
}
95
118
hover:border-blue-600 hover:text-blue-600 hover:rounded-full hover:border dark:hover:border-gray-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600
96
119
disabled:text-gray-300 disabled:pointer-events-none md:w-14 lg:w-16
97
- ` } >
120
+ ` }
121
+ >
98
122
{ format ( day , 'd' ) }
99
123
</ button >
100
124
</ div >
@@ -103,54 +127,46 @@ const Calendar = ({ initialMonth1, initialMonth2, handleValueChange, closeDatePi
103
127
} ;
104
128
105
129
return (
106
- < div className = 'flex flex-col items-center justify-center w-auto bg-none md:flex-row mb-10' >
107
- < div className = 'z-50 flex flex-col border border-gray-100 bg-white shadow-lg rounded-xl max-w-full min-w-[260px] md:min-w-[660px] lg:min-w-[800px]' >
130
+ < div
131
+ className = {
132
+ ! showAsSingle && useRange
133
+ ? 'flex flex-col items-center justify-center w-full bg-none md:flex-row mb-10 z-[900]'
134
+ : ''
135
+ }
136
+ >
137
+ < div
138
+ className = { `z-[900] border border-gray-100 bg-white shadow-lg rounded-xl ${
139
+ ! showAsSingle && useRange
140
+ ? 'max-w-full min-w-[260px] md:min-w-[660px] lg:min-w-[800px]'
141
+ : 'max-w-[328px] w-full min-w-40'
142
+ } `}
143
+ >
108
144
< div className = 'flex flex-col' >
109
145
< div className = 'divide-x flex flex-col md:flex-row lg:flex-row' >
110
146
{ /* shortcut section */ }
111
- < ShortCuts setSelectedRange = { setSelectedRange } />
147
+ { ! showAsSingle && useRange && < ShortCuts setSelectedRange = { setSelectedRange } /> }
112
148
113
149
{ /* calendar section one */ }
114
150
< div className = 'flex flex-col px-6 pt-5 pb-6' >
115
151
< CalendarHeader
116
- month = { format ( month1 , 'MMMM yyyy' ) }
117
- onNext = { ( ) => {
118
- const nextMonth = addMonths ( month1 , 1 ) ;
119
- if ( ! isSameMonth ( nextMonth , month2 ) ) {
120
- setMonth1 ( nextMonth ) ;
121
- }
122
- } }
123
- onPrev = { ( ) => {
124
- const prevMonth = subMonths ( month1 , 1 ) ;
125
- if ( ! isSameMonth ( prevMonth , month2 ) ) {
126
- setMonth1 ( prevMonth ) ;
127
- }
128
- } }
129
- />
130
- < div className = 'grid grid-cols-7 text-xs text-center text-gray-900 space-y-[1px]' >
131
- { daysOfWeek . map ( ( day ) => (
132
- < span
133
- key = { day }
134
- className = 'flex text-gray-600 items-center justify-center w-10 h-10 font-semibold rounded-lg' >
135
- { day }
136
- </ span >
137
- ) ) }
138
- { renderDays ( month1 , selectedDays1 , setSelectedDays1 ) }
139
- </ div >
140
- </ div >
141
- { /* calendar section two */ }
142
- < div className = 'flex flex-col px-6 pt-5 pb-6' >
143
- < CalendarHeader
144
- month = { format ( month2 , 'MMMM yyyy' ) }
152
+ month = { format ( useRange ? month1 : month2 , 'MMMM yyyy' ) }
145
153
onNext = { ( ) => {
146
- const nextMonth = addMonths ( month2 , 1 ) ;
147
- if ( ! isSameMonth ( nextMonth , month1 ) ) {
154
+ const nextMonth = addMonths ( useRange ? month1 : month2 , 1 ) ;
155
+ if ( useRange ) {
156
+ if ( ! isSameMonth ( nextMonth , month2 ) ) {
157
+ setMonth1 ( nextMonth ) ;
158
+ }
159
+ } else {
148
160
setMonth2 ( nextMonth ) ;
149
161
}
150
162
} }
151
163
onPrev = { ( ) => {
152
- const prevMonth = subMonths ( month2 , 1 ) ;
153
- if ( ! isSameMonth ( prevMonth , month1 ) ) {
164
+ const prevMonth = subMonths ( useRange ? month1 : month2 , 1 ) ;
165
+ if ( useRange ) {
166
+ if ( ! isSameMonth ( prevMonth , month2 ) ) {
167
+ setMonth1 ( prevMonth ) ;
168
+ }
169
+ } else {
154
170
setMonth2 ( prevMonth ) ;
155
171
}
156
172
} }
@@ -159,16 +175,49 @@ const Calendar = ({ initialMonth1, initialMonth2, handleValueChange, closeDatePi
159
175
{ daysOfWeek . map ( ( day ) => (
160
176
< span
161
177
key = { day }
162
- className = 'flex text-gray-600 items-center justify-center w-10 h-10 font-semibold rounded-lg' >
178
+ className = 'flex text-gray-600 items-center justify-center w-10 h-10 font-semibold rounded-lg'
179
+ >
163
180
{ day }
164
181
</ span >
165
182
) ) }
166
- { renderDays ( month2 , selectedDays2 , setSelectedDays2 ) }
183
+ { renderDays ( month1 , selectedDays1 , setSelectedDays1 , selectedRange ) }
167
184
</ div >
168
185
</ div >
186
+ { /* calendar section two */ }
187
+ { useRange && (
188
+ < div className = 'flex flex-col px-6 pt-5 pb-6' >
189
+ < CalendarHeader
190
+ month = { format ( month2 , 'MMMM yyyy' ) }
191
+ onNext = { ( ) => {
192
+ const nextMonth = addMonths ( month2 , 1 ) ;
193
+ if ( ! isSameMonth ( nextMonth , month1 ) ) {
194
+ setMonth2 ( nextMonth ) ;
195
+ }
196
+ } }
197
+ onPrev = { ( ) => {
198
+ const prevMonth = subMonths ( month2 , 1 ) ;
199
+ if ( ! isSameMonth ( prevMonth , month1 ) ) {
200
+ setMonth2 ( prevMonth ) ;
201
+ }
202
+ } }
203
+ />
204
+ < div className = 'grid grid-cols-7 text-xs text-center text-gray-900 space-y-[1px]' >
205
+ { daysOfWeek . map ( ( day ) => (
206
+ < span
207
+ key = { day }
208
+ className = 'flex text-gray-600 items-center justify-center w-10 h-10 font-semibold rounded-lg'
209
+ >
210
+ { day }
211
+ </ span >
212
+ ) ) }
213
+ { renderDays ( month2 , selectedDays2 , setSelectedDays2 ) }
214
+ </ div >
215
+ </ div >
216
+ ) }
169
217
</ div >
170
218
{ /* footer section */ }
171
219
< Footer
220
+ useRange = { useRange }
172
221
selectedRange = { selectedRange }
173
222
setSelectedRange = { setSelectedRange }
174
223
handleValueChange = { handleValueChange }
0 commit comments