Skip to content
10 changes: 5 additions & 5 deletions CalendarPicker/Controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ export default function Controls(props) {
label,
component,
onPressControl,
customHitSlop,
disabled,
} = props;

return (
<TouchableOpacity
onPress={() => onPressControl()}
style={styles}
disabled={disabled}
hitSlop={{ top: 20, bottom: 20, left: 40, right: 40 }}
hitSlop={typeof customHitSlop !== 'undefined' ? customHitSlop : { top: 20, bottom: 20, left: 40, right: 40 }}
>
<View style={{opacity: disabled ? 0 : 1}}>
{ component ||
<View style={{ opacity: disabled ? 0 : 1 }}>
{component ||
<Text style={[textStyles]}>
{ label }
{label}
</Text>
}
</View>
Expand Down
83 changes: 42 additions & 41 deletions CalendarPicker/Day.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,21 @@ export default function Day(props) {
selectedRangeEndStyle,
textStyle,
todayTextStyle,
selectedDayTextStyle: propSelectedDayTextStyle,
minDate,
maxDate,
disabledDates,
disabledDatesTextStyle,
enabledDates,
enabledDatesTextStyle,
minRangeDuration,
maxRangeDuration,
enableDateChange
} = props;

const thisDay = moment({year, month, day, hour: 12 });
const thisDay = moment({ year, month, day, hour: 12 });
const today = moment();

let dateOutOfRange;
let daySelectedStyle = styles.dayButton; // may be overridden depending on state
let selectedDayTextStyle = {};
let selectedDayColorStyle = {};
let propSelectedDayStyle;
let dateIsBeforeMin = false;
let dateIsAfterMax = false;
Expand All @@ -59,13 +58,15 @@ export default function Day(props) {
if (minDate) {
dateIsBeforeMin = thisDay.isBefore(minDate, 'day');
}

if (disabledDates) {
if (Array.isArray(disabledDates) && disabledDates.indexOf(thisDay.valueOf()) >= 0) {
dateIsDisabled = true;
}
else if (disabledDates instanceof Function) {
dateIsDisabled = disabledDates(thisDay);
if (enabledDates) {
if (Array.isArray(enabledDates) && !enabledDates.indexOf(thisDay.valueOf()) >= 0) {
if (enabledDates.indexOf(thisDay.valueOf()) >= 0) {
dateIsDisabled = false;
} else {
dateIsDisabled = true;
}
} else if (enabledDates instanceof Function) {
dateIsDisabled = enabledDates(thisDay);
}
}

Expand All @@ -75,22 +76,22 @@ export default function Day(props) {

if (maxRangeDuration) {
if (Array.isArray(maxRangeDuration)) {
let maxRangeEntry = maxRangeDuration.find(mrd => selectedStartDate.isSame(mrd.date, 'day') );
let maxRangeEntry = maxRangeDuration.find(mrd => selectedStartDate.isSame(mrd.date, 'day'));
if (maxRangeEntry && daysDiff > maxRangeEntry.maxDuration) {
dateRangeGreaterThanMax = true;
}
} else if(daysDiff > maxRangeDuration) {
} else if (daysDiff > maxRangeDuration) {
dateRangeGreaterThanMax = true;
}
}

if (minRangeDuration) {
if (Array.isArray(minRangeDuration)) {
let minRangeEntry = minRangeDuration.find(mrd => selectedStartDate.isSame(mrd.date, 'day') );
let minRangeEntry = minRangeDuration.find(mrd => selectedStartDate.isSame(mrd.date, 'day'));
if (minRangeEntry && daysDiff < minRangeEntry.minDuration) {
dateRangeLessThanMin = true;
}
} else if(daysDiff < minRangeDuration) {
} else if (daysDiff < minRangeDuration) {
dateRangeLessThanMin = true;
}
}
Expand All @@ -107,7 +108,7 @@ export default function Day(props) {
let isThisDateInSelectedRange =
selectedStartDate
&& selectedEndDate
&& thisDay.isBetween(selectedStartDate, selectedEndDate,'day','[]');
&& thisDay.isBetween(selectedStartDate, selectedEndDate, 'day', '[]');

// If date is in range let's apply styles
if (!dateOutOfRange || isThisDaySameAsSelectedStart || isThisDaySameAsSelectedEnd || isThisDateInSelectedRange) {
Expand All @@ -116,7 +117,7 @@ export default function Day(props) {
if (isToday) {
daySelectedStyle = styles.selectedToday;
// todayTextStyle prop overrides selectedDayTextColor (created via makeStyles)
selectedDayTextStyle = [propSelectedDayTextStyle, todayTextStyle || styles.selectedDayLabel];
selectedDayColorStyle = todayTextStyle || styles.selectedDayLabel;
}

if (Array.isArray(customDatesStyles)) {
Expand All @@ -143,10 +144,10 @@ export default function Day(props) {

// set selected day style
if (!allowRangeSelection &&
selectedStartDate &&
isThisDaySameAsSelectedStart) {
selectedStartDate &&
isThisDaySameAsSelectedStart) {
daySelectedStyle = styles.selectedDay;
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel, isToday && todayTextStyle];
selectedDayColorStyle = [styles.selectedDayLabel, isToday && todayTextStyle];
// selectedDayStyle prop overrides selectedDayColor (created via makeStyles)
propSelectedDayStyle = selectedDayStyle || styles.selectedDayBackground;
}
Expand All @@ -157,44 +158,44 @@ export default function Day(props) {
// Apply style for start date
if (isThisDaySameAsSelectedStart) {
daySelectedStyle = [styles.startDayWrapper, selectedRangeStyle, selectedRangeStartStyle];
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel];
selectedDayColorStyle = styles.selectedDayLabel;
}
// Apply style for end date
if (isThisDaySameAsSelectedEnd) {
daySelectedStyle = [styles.endDayWrapper, selectedRangeStyle, selectedRangeEndStyle];
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel];
selectedDayColorStyle = styles.selectedDayLabel;
}
// Apply style if start date is the same as end date
if (isThisDaySameAsSelectedEnd &&
isThisDaySameAsSelectedStart &&
selectedEndDate.isSame(selectedStartDate, 'day')) {
isThisDaySameAsSelectedStart &&
selectedEndDate.isSame(selectedStartDate, 'day')) {
daySelectedStyle = [styles.selectedDay, styles.selectedDayBackground, selectedRangeStyle];
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel];
selectedDayColorStyle = styles.selectedDayLabel;
}
// Apply style if this day is in range
if (thisDay.isBetween(selectedStartDate, selectedEndDate, 'day')) {
daySelectedStyle = [styles.inRangeDay, selectedRangeStyle];
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel];
selectedDayColorStyle = styles.selectedDayLabel;
}
}
// Apply style if start date has been selected but end date has not
if (selectedStartDate &&
!selectedEndDate &&
isThisDaySameAsSelectedStart) {
!selectedEndDate &&
isThisDaySameAsSelectedStart) {
daySelectedStyle = [styles.startDayWrapper, selectedRangeStyle, selectedRangeStartStyle];
selectedDayTextStyle = [propSelectedDayTextStyle, styles.selectedDayLabel];
selectedDayColorStyle = styles.selectedDayLabel;
}
}

if (dateOutOfRange) { // selected start or end date, but not selectable now
return (
<View style={[styles.dayWrapper, customContainerStyle]}>
<View style={[customDateStyle, daySelectedStyle, propSelectedDayStyle ]}>
<View style={[customDateStyle, daySelectedStyle, propSelectedDayStyle]}>
<Text style={[styles.dayLabel, textStyle,
styles.disabledText, disabledDatesTextStyle,
styles.selectedDisabledText, selectedDisabledDatesTextStyle,
styles.disabledText, enabledDatesTextStyle,
styles.selectedDisabledText, selectedDisabledDatesTextStyle,
]}>
{ day }
{day}
</Text>
</View>
</View>
Expand All @@ -204,10 +205,10 @@ export default function Day(props) {
<View style={[styles.dayWrapper, customContainerStyle]}>
<TouchableOpacity
disabled={!enableDateChange}
style={[customDateStyle, daySelectedStyle, propSelectedDayStyle ]}
onPress={() => onPressDay({year, month, day}) }>
<Text style={[styles.dayLabel, textStyle, customTextStyle, selectedDayTextStyle]}>
{ day }
style={[customDateStyle, daySelectedStyle, propSelectedDayStyle]}
onPress={() => onPressDay({ year, month, day })}>
<Text style={[styles.dayLabel, textStyle, customTextStyle, selectedDayColorStyle]}>
{day}
</Text>
</TouchableOpacity>
</View>
Expand All @@ -217,8 +218,8 @@ export default function Day(props) {
else { // dateOutOfRange = true but not selected start or end date
return (
<View style={styles.dayWrapper}>
<Text style={[textStyle, styles.disabledText, disabledDatesTextStyle]}>
{ day }
<Text style={[textStyle, styles.disabledText, enabledDatesTextStyle]}>
{day}
</Text>
</View>
);
Expand All @@ -233,7 +234,7 @@ Day.propTypes = {
styles: PropTypes.shape({}),
day: PropTypes.number,
onPressDay: PropTypes.func,
disabledDates: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
enabledDates: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
minRangeDuration: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
maxRangeDuration: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
};
46 changes: 20 additions & 26 deletions CalendarPicker/DaysGridView.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ import React, { Component } from 'react';
import {
View,
Text,
ViewPropTypes
} from 'react-native';
import PropTypes from 'prop-types';
import Day from './Day';
import EmptyDay from './EmptyDay';
import { Utils } from './Utils';
import moment from 'moment';

const ViewPropTypes = PropTypes.shape({
style: PropTypes.any,
});

export default class DaysGridView extends Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -93,10 +90,9 @@ export default class DaysGridView extends Component {
// Check that selected date(s) match this month.
if (isSelectedDiff && (
Utils.compareDates(selectedStartDate, firstDayOfMonth, 'month') ||
Utils.compareDates(selectedEndDate, firstDayOfMonth, 'month') ||
Utils.compareDates(prevSelStart, firstDayOfMonth, 'month') ||
Utils.compareDates(prevSelEnd, firstDayOfMonth, 'month') ))
{
Utils.compareDates(selectedEndDate, firstDayOfMonth, 'month') ||
Utils.compareDates(prevSelStart, firstDayOfMonth, 'month') ||
Utils.compareDates(prevSelEnd, firstDayOfMonth, 'month'))) {
// Range selection potentially affects all dates in the month. Recreate.
if (this.props.allowRangeSelection) {
this.setState({
Expand All @@ -107,17 +103,16 @@ export default class DaysGridView extends Component {
// Search for affected dates and modify those only
const daysGrid = [...this.state.daysGrid];
const { year } = this.props;
for (let i = 0; i <daysGrid.length; i++) {
for (let j = 0; j <daysGrid[i].length; j++) {
for (let i = 0; i < daysGrid.length; i++) {
for (let j = 0; j < daysGrid[i].length; j++) {
const { month, day } = daysGrid[i][j];
// Empty days and stragglers can't be selected.
if (month === undefined) { continue; }
// Check single date
const thisDay = { year, month, day };
const isSelected = Utils.compareDates(selectedStartDate, thisDay, 'day');
const isPrevSelected = Utils.compareDates(prevSelStart, thisDay, 'day');
if (isSelected || isPrevSelected)
{
if (isSelected || isPrevSelected) {
daysGrid[i][j] = this.renderDayInCurrentMonth(day);
}
}
Expand Down Expand Up @@ -153,7 +148,7 @@ export default class DaysGridView extends Component {
});
}

renderDayStraggler({key, day}) {
renderDayStraggler({ key, day }) {
return ({
day,
// month doesn't matter for stragglers as long as isn't set to current month
Expand All @@ -162,8 +157,8 @@ export default class DaysGridView extends Component {
key={key}
day={day}
styles={this.props.styles}
disabledDates={() => true}
disabledDatesTextStyle={this.props.disabledDatesTextStyle}
enabledDates={() => true}
enabledDatesTextStyle={this.props.enabledDatesTextStyle}
textStyle={this.props.textStyle}
/>
)
Expand Down Expand Up @@ -233,13 +228,13 @@ export default class DaysGridView extends Component {
const { daysGrid } = this.state;
const renderedDaysGrid = daysGrid.map((weekRow, i) => (
<View key={i} style={styles.weekRow}>
{ weekRow.map(day => day.component ) }
{ weekRow.map(day => day.component)}
</View>
));

return (
<View style={styles.daysWrapper}>
{ renderedDaysGrid }
{ renderedDaysGrid}
</View>
);
}
Expand All @@ -251,12 +246,11 @@ DaysGridView.propTypes = {
year: PropTypes.number.isRequired,
onPressDay: PropTypes.func,
startFromMonday: PropTypes.bool,
selectedDayStyle: PropTypes.oneOfType([PropTypes.undefined, ViewPropTypes.style]),
selectedRangeStartStyle: PropTypes.oneOfType([PropTypes.undefined, ViewPropTypes.style]),
selectedRangeStyle: PropTypes.oneOfType([PropTypes.undefined, ViewPropTypes.style]),
selectedRangeEndStyle: PropTypes.oneOfType([PropTypes.undefined, ViewPropTypes.style]),
selectedDayStyle: PropTypes.oneOfType([PropTypes.any, ViewPropTypes.style]),
selectedRangeStartStyle: PropTypes.oneOfType([PropTypes.any, ViewPropTypes.style]),
selectedRangeStyle: PropTypes.oneOfType([PropTypes.any, ViewPropTypes.style]),
selectedRangeEndStyle: PropTypes.oneOfType([PropTypes.any, ViewPropTypes.style]),
todayTextStyle: Text.propTypes.style,
selectedDayTextStyle: Text.propTypes.style,
customDatesStyles: PropTypes.oneOfType([
PropTypes.func,
PropTypes.arrayOf(PropTypes.shape({
Expand All @@ -265,13 +259,13 @@ DaysGridView.propTypes = {
PropTypes.instanceOf(Date),
PropTypes.instanceOf(moment)
]),
containerStyle: ViewPropTypes,
style: ViewPropTypes,
containerStyle: ViewPropTypes.style,
style: ViewPropTypes.style,
textStyle: Text.propTypes.style,
})),
]),
disabledDates: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
disabledDatesTextStyle: Text.propTypes.style,
enabledDates: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
enabledDatesTextStyle: Text.propTypes.style,
minRangeDuration: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
maxRangeDuration: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
};
8 changes: 5 additions & 3 deletions CalendarPicker/HeaderControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function HeaderControls(props) {
previousComponent,
nextComponent,
previousTitle,
customHitSlop,
nextTitle,
previousTitleStyle,
nextTitleStyle,
Expand Down Expand Up @@ -54,21 +55,22 @@ export default function HeaderControls(props) {
styles={styles.previousContainer}
textStyles={[styles.navButtonText, textStyle, previousTitleStyle]}
/>
<View style={[styles.monthYearHeaderWrapper,monthYearHeaderWrapperStyle]}>
<View style={[styles.monthYearHeaderWrapper, monthYearHeaderWrapperStyle]}>
<TouchableOpacity onPress={onPressMonth}>
<Text style={[styles.monthHeaderMainText, textStyle]} {...accessibilityProps}>
{ monthName }
{monthName}
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={onPressYear}>
<Text style={[styles.yearHeaderMainText, textStyle]}>
{ year }
{year}
</Text>
</TouchableOpacity>
</View>
<Controls
disabled={disableNextMonth}
label={nextTitle}
customHitSlop={customHitSlop}
component={nextComponent}
onPressControl={onPressNext}
styles={styles.nextContainer}
Expand Down
Loading