├── .gitignore ├── README.md ├── RangeDatepicker ├── Day.js ├── DayHeader.js ├── DayRow.js ├── Month.js └── index.js ├── SingleDatepicker ├── Day.js ├── DayRow.js ├── Month.js └── index.js ├── demo-datepicker.gif ├── helper └── index.js ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-range-datepicker 2 | 3 | This is my first npm package, inspired by Airbnb datepicker. 4 | 5 | ![react-native-range-datepicker in action](https://raw.githubusercontent.com/apaajabolehd/react-native-range-datepicker/master/demo-datepicker.gif) 6 | 7 | ### Install 8 | ```sh 9 | $ npm i react-native-range-datepicker --save 10 | ``` 11 | 12 | ### How to use 13 | ```jsx 14 | import DatepickerRange from 'react-native-range-datepicker'; 15 | 16 | this.setState({ startDate, untilDate })} 20 | /> 21 | ``` 22 | 23 | 24 | ### Default props RangeDatepicker 25 | ```jsx 26 | static defaultProps = { 27 | monthProps: { 28 | titleFormat: 'MMMM YYYY', 29 | titleStyle: { fontSize: 20, padding: 20 }, 30 | dayHeaderProps: {}, 31 | showDaysHeader: false, 32 | capitalizeTitle: false, 33 | }, 34 | buttonText: 'Select Date', 35 | flatListProps: {}, 36 | closeButtonText: 'Close', 37 | chosenDateTextColor: '#666', 38 | monthProps: {}, 39 | dayHeaderDividerColor: "#000000", 40 | initialMonth: '', 41 | dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 42 | dayHeaderStyle: {}, 43 | dayHeaderContainerStyle: {}, 44 | maxMonth: 12, 45 | buttonColor: 'green', 46 | buttonContainerStyle: {}, 47 | flatListProps: {}, 48 | monthProps: {}, 49 | showReset: true, 50 | showClose: true, 51 | showConfirmButton: true, 52 | showSelectedRange: true, 53 | showsVerticalScrollIndicator: false, 54 | showDaysHeader: true, 55 | ignoreMinDate: false, 56 | isHistorical: false, 57 | dayContainerOffset: 0, 58 | onClose: () => {}, 59 | onSelect: () => {}, 60 | onConfirm: () => {}, 61 | placeHolderStart: 'Start Date', 62 | placeHolderUntil: 'Until Date', 63 | selectedBackgroundColor: 'green', 64 | selectedTextColor: 'white', 65 | dayBackgroundColor: '', 66 | dayTextColor: '', 67 | pointBackgroundColor: '', 68 | pointTextColor: '', 69 | todayColor: 'green', 70 | textColor: '#000000', 71 | resetButtonText: "Reset", 72 | startDate: '', 73 | untilDate: '', 74 | minDate: '', 75 | maxDate: '', 76 | infoText: '', 77 | showSelectionInfo: true, 78 | showButton: true, 79 | infoStyle: {color: '#fff', fontSize: 13}, 80 | infoContainerStyle: {marginRight: 20, paddingHorizontal: 20, paddingVertical: 5, backgroundColor: 'green', borderRadius: 20, alignSelf: 'flex-end'} 81 | }; 82 | ``` 83 | 84 | ### Proptypes RangeDatepicker 85 | ```jsx 86 | static propTypes = { 87 | monthProps: PropTypes.shape({ 88 | titleFormat: PropTypes.string, 89 | titleStyle: PropTypes.object, 90 | }), 91 | initialMonth: PropTypes.string, 92 | dayHeadings: PropTypes.arrayOf(PropTypes.string), 93 | availableDates: PropTypes.arrayOf(PropTypes.string), 94 | maxMonth: PropTypes.number, 95 | buttonColor: PropTypes.string, 96 | buttonText: PropTypes.string, 97 | dayHeaderDividerColor: PropTypes.string, 98 | closeButtonText: PropTypes.string, 99 | chosenDateTextColor: PropTypes.string, 100 | flatListProps: PropTypes.object, 101 | dayHeaderStyle: PropTypes.object, 102 | dayHeaderContainerStyle: PropTypes.object, 103 | buttonContainerStyle: PropTypes.object, 104 | monthProps: PropTypes.object, 105 | startDate: PropTypes.string, 106 | untilDate: PropTypes.string, 107 | minDate: PropTypes.string, 108 | maxDate: PropTypes.string, 109 | showReset: PropTypes.bool, 110 | showClose: PropTypes.bool, 111 | dayContainerOffset: PropTypes.number, 112 | showConfirmButton: PropTypes.bool, 113 | showSelectedRange: PropTypes.bool, 114 | showsVerticalScrollIndicator: PropTypes.bool, 115 | ignoreMinDate: PropTypes.bool, 116 | isHistorical: PropTypes.bool, 117 | onClose: PropTypes.func, 118 | onSelect: PropTypes.func, 119 | onConfirm: PropTypes.func, 120 | placeHolderStart: PropTypes.string, 121 | placeHolderUntil: PropTypes.string, 122 | selectedBackgroundColor: PropTypes.string, 123 | resetButtonText: PropTypes.string, 124 | selectedTextColor: PropTypes.string, 125 | dayBackgroundColor: PropTypes.string, 126 | dayTextColor: PropTypes.string, 127 | pointBackgroundColor: PropTypes.string, 128 | pointTextColor: PropTypes.string, 129 | todayColor: PropTypes.string, 130 | infoText: PropTypes.string, 131 | infoStyle: PropTypes.object, 132 | showSelectionInfo: PropTypes.bool, 133 | showButton: PropTypes.bool, 134 | infoContainerStyle: PropTypes.object 135 | } 136 | 137 | ``` 138 | 139 | 140 | 141 | ```jsx 142 | import {SingleDatepicker} from 'react-native-range-datepicker'; 143 | 144 | this.setState({ date })} 146 | /> 147 | ``` 148 | 149 | ### How to set fist day of week 150 | ```js 151 | 152 | import 'moment/locale/en-gb'; 153 | moment.locale("en-gb"); 154 | 155 | ``` 156 | 157 | ### How to set days heades 158 | ```js 159 | 160 | const dayHeadings = 161 | [...Array(7).keys()] 162 | .map(day => moment().weekday(day).format('dd')) 163 | .map(_capitalize); 164 | 165 | ``` 166 | 167 | ### Default props SingleDatepicker 168 | ```jsx 169 | static defaultProps = { 170 | initialMonth: '', 171 | dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 172 | maxMonth: 12, 173 | showClose: true, 174 | onClose: () => {}, 175 | onSelect: () => {}, 176 | selectedBackgroundColor: 'green', 177 | selectedTextColor: 'white', 178 | todayColor: 'green', 179 | minDate: '', 180 | maxDate: '', 181 | infoText: '', 182 | infoStyle: {color: '#fff', fontSize: 13}, 183 | infoContainerStyle: {marginRight: 20, paddingHorizontal: 20, paddingVertical: 5, backgroundColor: 'green', borderRadius: 20, alignSelf: 'flex-end'}, 184 | }; 185 | ``` 186 | 187 | ### Proptypes SingleDatepicker 188 | ```jsx 189 | static propTypes = { 190 | initialMonth: PropTypes.string, 191 | dayHeadings: PropTypes.arrayOf(React.PropTypes.string), 192 | availableDates: PropTypes.arrayOf(React.PropTypes.string), 193 | maxMonth: PropTypes.number, 194 | minDate: PropTypes.string, 195 | maxDate: PropTypes.string, 196 | showClose: PropTypes.bool, 197 | onClose: PropTypes.func, 198 | onSelect: PropTypes.func, 199 | selectedBackgroundColor: PropTypes.string, 200 | selectedTextColor: PropTypes.string, 201 | todayColor: PropTypes.string, 202 | infoText: PropTypes.string, 203 | infoStyle: PropTypes.object, 204 | infoContainerStyle: PropTypes.object, 205 | } 206 | ``` 207 | 208 | ### Update 23/07/2019 209 | * RN 0.6 compatibility: replaced ListView by FlatList 210 | * added more flexible width based on actual container size 211 | -------------------------------------------------------------------------------- /RangeDatepicker/Day.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React, { memo } from 'react'; 3 | import { 4 | View, 5 | Text, 6 | TouchableWithoutFeedback, 7 | Dimensions, 8 | StyleSheet 9 | } from 'react-native'; 10 | import { dayJsMod } from '../helper'; 11 | 12 | const DEVICE_WIDTH = Dimensions.get('window').width; 13 | 14 | const areEqual = (prevProps, nextProps) => { 15 | if(nextProps.day.type != prevProps.day.type){ 16 | return false; 17 | } 18 | 19 | if(nextProps.onSelectDate != prevProps.onSelectDate){ 20 | return false; 21 | } 22 | 23 | return true; 24 | }; 25 | 26 | const Day = memo((props) => { 27 | const { 28 | day, 29 | dayProps, 30 | } = props; 31 | 32 | const { 33 | dayBackgroundColor, 34 | dayTextColor, 35 | pointBackgroundColor, 36 | pointTextColor, 37 | selectedBackgroundColor, 38 | selectedTextColor, 39 | dayContainerOffset = 10, 40 | } = dayProps; 41 | 42 | const side = Math.floor(DEVICE_WIDTH / 7)+2; 43 | const size = { 44 | width: side, 45 | height: side, 46 | flexDirection: 'row', 47 | justifyContent: 'center', 48 | alignItems: 'center', 49 | }; 50 | 51 | const dayWrapperStyle = { 52 | ...size, 53 | backgroundColor : 'transparent', 54 | }; 55 | 56 | const dayStyle = { 57 | width: side - dayContainerOffset, 58 | height: side - dayContainerOffset, 59 | // flex: 0, 60 | backgroundColor : dayBackgroundColor || 'transparent', 61 | position: 'relative', 62 | borderRadius: side - dayContainerOffset, 63 | }; 64 | 65 | const textDayStyle = { color: dayTextColor || 'black' }; 66 | 67 | 68 | switch(day.type) { 69 | case "single" : 70 | dayStyle.backgroundColor = pointBackgroundColor || selectedBackgroundColor; 71 | textDayStyle.color = pointTextColor || selectedTextColor; 72 | break; 73 | case "first" : 74 | dayStyle.backgroundColor = pointBackgroundColor || selectedBackgroundColor; 75 | textDayStyle.color = pointTextColor || selectedTextColor; 76 | dayWrapperStyle.backgroundColor = selectedBackgroundColor; 77 | dayWrapperStyle.borderBottomLeftRadius = side; 78 | dayWrapperStyle.borderTopLeftRadius = side; 79 | break; 80 | case "last" : 81 | dayStyle.backgroundColor = pointBackgroundColor || selectedBackgroundColor; 82 | textDayStyle.color = pointTextColor || selectedTextColor; 83 | dayWrapperStyle.backgroundColor = selectedBackgroundColor; 84 | dayWrapperStyle.borderBottomRightRadius = side; 85 | dayWrapperStyle.borderTopRightRadius = side; 86 | break; 87 | case "between" : 88 | dayStyle.backgroundColor = selectedBackgroundColor; 89 | textDayStyle.color = selectedTextColor; 90 | dayWrapperStyle.backgroundColor = selectedBackgroundColor; 91 | break; 92 | case "disabled" : 93 | case "blockout" : 94 | textDayStyle.color = '#ccc'; 95 | default: break; 96 | } 97 | 98 | if(day.date){ 99 | if(day.type == 'disabled') 100 | return ( 101 | 102 | 103 | 104 | {dayJsMod(day.date, 'YYYYMMDD').date()} 105 | {day.date == dayJsMod().format("YYYYMMDD") ? (__) : null} 106 | 107 | 108 | 109 | ); 110 | else if(day.type == 'blockout') { 111 | const strikeTop = Math.floor(DEVICE_WIDTH / -22); 112 | return ( 113 | 114 | 115 | 116 | {dayJsMod(day.date, 'YYYYMMDD').date()} 117 | 118 | __ 119 | 120 | 121 | 122 | 123 | ); 124 | } 125 | else 126 | return ( 127 | props.onSelectDate(dayJsMod(day.date, 'YYYYMMDD'))}> 128 | 129 | 130 | 131 | {dayJsMod(day.date, 'YYYYMMDD').date()} 132 | 133 | {day.date == dayJsMod().format("YYYYMMDD") ? 134 | ( 135 | __ 136 | ) 137 | : null} 138 | 139 | 140 | 141 | ); 142 | } 143 | else 144 | return ( 145 | 146 | 147 | 148 | {null} 149 | 150 | 151 | 152 | ); 153 | }, areEqual) 154 | 155 | export default Day; -------------------------------------------------------------------------------- /RangeDatepicker/DayHeader.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React from 'react'; 3 | import { 4 | Dimensions, 5 | StyleSheet, 6 | Text, 7 | View 8 | } from 'react-native'; 9 | 10 | const DEVICE_WIDTH = Dimensions.get('window').width; 11 | 12 | const DayHeader = (props) => { 13 | const { 14 | dayContainerOffset = 0, 15 | dayHeaderContainerStyle, 16 | dayHeaderStyle, 17 | dayHeadings 18 | } = props; 19 | return ( 20 | 21 | { 22 | dayHeadings.map((day, i) => { 23 | return ( 24 | 25 | {day} 26 | 27 | ); 28 | }) 29 | } 30 | 31 | ); 32 | } 33 | 34 | const styles = StyleSheet.create({ 35 | dayHeader : { 36 | flexDirection: 'row', 37 | borderBottomWidth: 1, 38 | paddingBottom: 10, 39 | paddingTop: 10, 40 | } 41 | }); 42 | 43 | export default DayHeader; -------------------------------------------------------------------------------- /RangeDatepicker/DayRow.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React from 'react'; 3 | import { 4 | View 5 | } from 'react-native'; 6 | import Day from './Day'; 7 | 8 | const DayRow = (props) => { 9 | return ( 10 | 11 | { 12 | props.days.map((day, i) => { 13 | return ( 14 | 15 | ) 16 | }) 17 | } 18 | 19 | ); 20 | } 21 | 22 | export default DayRow; -------------------------------------------------------------------------------- /RangeDatepicker/Month.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React, { memo } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import { 5 | View, 6 | Text 7 | } from 'react-native'; 8 | import DayRow from './DayRow'; 9 | import DayHeader from './DayHeader'; 10 | import { dayJsMod } from '../helper' 11 | 12 | function capitalize(str){ 13 | return str.charAt(0).toUpperCase() + str.slice(1); 14 | } 15 | 16 | const areEqual = (prevProps, nextProps) => { 17 | if(nextProps.minDate != prevProps.minDate) 18 | return false; 19 | 20 | if(nextProps.maxDate != prevProps.maxDate) 21 | return false; 22 | 23 | if(nextProps.availableDates != prevProps.availableDates) 24 | return false; 25 | 26 | if(nextProps.startDate != prevProps.startDate) 27 | return false; 28 | 29 | if(nextProps.untilDate != prevProps.untilDate) 30 | return false; 31 | 32 | return true; 33 | } 34 | 35 | const Month = memo((props) => { 36 | const { month, dayProps, titleStyle, titleFormat, capitalizeTitle, dayHeaderProps } = props; 37 | 38 | const getDayStack = (month) => { 39 | let res = []; 40 | let currMonth = dayJsMod(month).month(); //get this month 41 | let currDate = dayJsMod(month).startOf("month"); //get first day in this month 42 | 43 | let dayColumn = []; 44 | let dayRow = []; 45 | let dayObject = {}; 46 | let {startDate, untilDate, availableDates, minDate, maxDate, ignoreMinDate} = props; 47 | 48 | do{ 49 | dayColumn = []; 50 | for(let i = 0; i < 7; i++){ 51 | dayObject = { 52 | type : null, 53 | date: null 54 | }; 55 | if(i == currDate.day() && currDate.month() == currMonth) 56 | { 57 | if(minDate && minDate.format("YYYYMMDD") && currDate.format("YYYYMMDD") < minDate.format("YYYYMMDD")){ 58 | if(startDate && startDate.format('YYYYMMDD') > currDate.format("YYYYMMDD") && currDate.format("YYYYMMDD") > dayJsMod().format("YYYYMMDD") && ignoreMinDate){} 59 | else{ 60 | dayObject.type = 'disabled'; 61 | } 62 | } 63 | if(maxDate && maxDate.format("YYYYMMDD") && currDate.format("YYYYMMDD") > maxDate.format("YYYYMMDD")){ 64 | dayObject.type = 'disabled'; 65 | } 66 | if(availableDates && availableDates.indexOf(currDate.format("YYYYMMDD")) == -1){ 67 | dayObject.type = 'blockout'; 68 | } 69 | if(startDate && startDate.format('YYYYMMDD') == currDate.format('YYYYMMDD')){ 70 | if(!untilDate) 71 | dayObject.type = 'single'; 72 | else{ 73 | dayObject.type = 'first'; 74 | } 75 | } 76 | if(untilDate && untilDate.format('YYYYMMDD') == currDate.format('YYYYMMDD')){ 77 | dayObject.type = 'last'; 78 | } 79 | if((startDate && startDate.format('YYYYMMDD') < currDate.format('YYYYMMDD')) && 80 | (untilDate && untilDate.format('YYYYMMDD') > currDate.format('YYYYMMDD'))) 81 | dayObject.type = 'between'; 82 | 83 | dayObject.date = currDate.clone().format('YYYYMMDD'); 84 | dayColumn.push(dayObject); 85 | currDate = currDate.add(1, 'day'); 86 | } 87 | else{ 88 | if(startDate && untilDate && 89 | ( 90 | startDate.format('YYYYMMDD') < currDate.format('YYYYMMDD') && 91 | untilDate.format('YYYYMMDD') >= currDate.format('YYYYMMDD') 92 | ) 93 | ) 94 | dayObject.type = 'between'; 95 | 96 | dayColumn.push(dayObject); 97 | } 98 | } 99 | 100 | dayRow.push(dayColumn); 101 | } while (currDate.month() == currMonth); 102 | 103 | return dayRow; 104 | } 105 | 106 | const dayStack = getDayStack(dayJsMod(month, 'YYYYMM')); 107 | 108 | return ( 109 | 110 | 111 | {capitalizeTitle ? 112 | capitalize(dayJsMod(month, 'YYYYMM').format(titleFormat)) : 113 | dayJsMod(month, 'YYYYMM').format(titleFormat) 114 | } 115 | 116 | {props.showDaysHeader && ( 117 | 118 | )} 119 | 120 | { 121 | dayStack.map((days, i) => { 122 | return ( 123 | 124 | ) 125 | }) 126 | } 127 | 128 | 129 | ); 130 | }, areEqual); 131 | 132 | Month.defaultProps = { 133 | titleFormat: 'MMMM YYYY', 134 | titleStyle: { fontSize: 20, padding: 20 }, 135 | dayHeaderProps: {}, 136 | showDaysHeader: false, 137 | capitalizeTitle: false, 138 | }; 139 | 140 | Month.propTypes = { 141 | titleFormat: PropTypes.string, 142 | titleStyle: PropTypes.object, 143 | dayHeaderProps: PropTypes.object, 144 | showDaysHeader: PropTypes.bool, 145 | capitalizeTitle: PropTypes.bool, 146 | }; 147 | 148 | export default Month; -------------------------------------------------------------------------------- /RangeDatepicker/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React, { useEffect, useState } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import { 5 | Text, 6 | View, 7 | FlatList, 8 | StyleSheet, 9 | Button, 10 | } from 'react-native'; 11 | import Month from './Month'; 12 | // import styles from './styles'; 13 | import { dayJsMod } from '../helper'; 14 | 15 | const RangeDatepicker = (props) => { 16 | const [startDate, setStartDate] = useState(props.startDate && dayJsMod(props.startDate, 'YYYYMMDD')); 17 | const [untilDate, setUntilDate] = useState(props.untilDate && dayJsMod(props.untilDate, 'YYYYMMDD')); 18 | const [availableDates, setAvailableDates] = useState(props.availableDates || null); 19 | 20 | useEffect(() => { 21 | setAvailableDates(props.availableDates) 22 | }, [props.availableDates]) 23 | 24 | const onSelectDate = (date) => { 25 | let tempStartDate = null; 26 | let tempUntilDate = null; 27 | // console.log('startDate', startDate); 28 | // console.log('untilDate', untilDate); 29 | 30 | if(startDate && !untilDate) 31 | { 32 | if(date.format('YYYYMMDD') < startDate.format('YYYYMMDD') || isInvalidRange(date)){ 33 | // console.log(1); 34 | tempStartDate = date; 35 | } 36 | else if(date.format('YYYYMMDD') > startDate.format('YYYYMMDD')){ 37 | // console.log(2); 38 | tempStartDate = startDate; 39 | tempUntilDate = date; 40 | } 41 | else{ 42 | // console.log(3); 43 | tempStartDate = null; 44 | tempUntilDate = null; 45 | } 46 | } 47 | else if(!isInvalidRange(date)) { 48 | // console.log(4); 49 | tempStartDate = date; 50 | } 51 | else { 52 | // console.log(5); 53 | tempStartDate = null; 54 | tempUntilDate = null; 55 | } 56 | 57 | setStartDate(tempStartDate); 58 | setUntilDate(tempUntilDate); 59 | props.onSelect(tempStartDate, tempUntilDate); 60 | } 61 | 62 | const isInvalidRange = (date) => { 63 | if(availableDates && availableDates.length > 0){ 64 | //select endDate condition 65 | if(startDate && !untilDate) { 66 | for(let i = startDate.format('YYYYMMDD'); i <= date.format('YYYYMMDD'); i = dayJsMod(i, 'YYYYMMDD').add(1, 'days').format('YYYYMMDD')){ 67 | if(availableDates.indexOf(i) == -1 && startDate.format('YYYYMMDD') != i) 68 | return true; 69 | } 70 | } 71 | //select startDate condition 72 | else if(availableDates.indexOf(date.format('YYYYMMDD')) == -1){ 73 | return true; 74 | } 75 | } 76 | 77 | return false; 78 | } 79 | 80 | const getMonthStack = () => { 81 | let res = []; 82 | const { maxMonth, initialMonth, isHistorical } = props; 83 | let initMonth = dayJsMod(); 84 | if(initialMonth && initialMonth != '') 85 | initMonth = dayJsMod(initialMonth, 'YYYYMM'); 86 | 87 | for(let i = 0; i < maxMonth; i++){ 88 | res.push( 89 | !isHistorical ? ( 90 | initMonth.clone().add(i, 'month').format('YYYYMM') 91 | ) : ( 92 | initMonth.clone().subtract(i, 'month').format('YYYYMM') 93 | ) 94 | ); 95 | } 96 | 97 | return res; 98 | } 99 | 100 | const onReset = () => { 101 | setStartDate(null); 102 | setUntilDate(null); 103 | 104 | props.onSelect(null, null); 105 | } 106 | 107 | const handleConfirmDate = () => { 108 | props.onConfirm && props.onConfirm(startDate,untilDate); 109 | } 110 | 111 | const handleRenderRow = (month, index) => { 112 | const { selectedBackgroundColor, selectedTextColor, todayColor, ignoreMinDate, minDate, maxDate } = props; 113 | if(availableDates && availableDates.length > 0){ 114 | availableDates = availableDates.filter(function(d){ 115 | if(d.indexOf(month) >= 0) 116 | return true; 117 | }); 118 | } 119 | 120 | return ( 121 | 131 | ) 132 | } 133 | 134 | 135 | return ( 136 | 137 | { 138 | props.showClose || props.showReset ? 139 | ( 140 | { 141 | props.showClose && Close 142 | } 143 | { 144 | props.showReset && Reset 145 | } 146 | ) 147 | : 148 | null 149 | } 150 | { 151 | props.showSelectionInfo ? 152 | ( 153 | 154 | 155 | 156 | { startDate ? dayJsMod(startDate).format("MMM DD YYYY") : props.placeHolderStart} 157 | 158 | 159 | 160 | 161 | 162 | / 163 | 164 | 165 | 166 | 167 | 168 | { untilDate ? dayJsMod(untilDate).format("MMM DD YYYY") : props.placeHolderUntil} 169 | 170 | 171 | 172 | ) : null 173 | } 174 | 175 | { 176 | props.infoText != "" && 177 | 178 | {props.infoText} 179 | 180 | } 181 | 182 | { 183 | props.dayHeadings.map((day, i) => { 184 | return ({day}) 185 | }) 186 | } 187 | 188 | { 192 | return handleRenderRow(item, index) 193 | }} 194 | keyExtractor = { (item, index) => index.toString() } 195 | showsVerticalScrollIndicator={false} 196 | /> 197 | 198 | { 199 | props.showButton ? 200 | ( 201 | 202 |