react-native-common-date-picker
Version:
An awesome and cross-platform React Native date picker and calendar component for iOS and Android
243 lines (216 loc) • 9.67 kB
JavaScript
import React from 'react';
import {View, Text, TouchableOpacity, Image} from 'react-native';
import PropTypes from 'prop-types';
import * as Constants from "../../contants";
import {listItemStyles} from "../style";
import WeekBar from "./WeekBar";
import ListItemHeader from "./ListItemHeader";
const CENTER_STYLES = {justifyContent: 'center', alignItems: 'center'};
const PADDING = 12;
const f1 = (Constants.SCREEN_WIDTH - PADDING) / 7;
const f2 = f1.toString();
const f3 = f2.substring(0, f2.indexOf('.') >= 0 ? (f2.indexOf('.') + 3) : 3);
const text_width = parseFloat(f3);
class ListItem extends React.Component {
_selectDate = (date, index) => {
const {selectDate} = this.props;
selectDate && typeof selectDate === 'function' && selectDate(date, index);
};
_needSelectedRangeBgColor = (startDate, endDate, currentDate) => {
if (!startDate || !endDate) return false;
return !!(Constants.greaterThan(currentDate, startDate) && Constants.greaterThan(endDate, currentDate));
};
_getMarkTypeStyles = (currentDate, days) => {
const {
listItemStyle,
startDate,
endDate,
selectedDateMarkType,
selectedDateMarkColor,
selectedDateMarkRangeColor,
} = this.props;
const hasSelected = startDate === currentDate || endDate === currentDate;
let markBorderRadius = 0;
if (listItemStyle.day && typeof listItemStyle.day === 'object' && listItemStyle.day.borderRadius) {
markBorderRadius = listItemStyle.day.borderRadius;
}
const selectedDateStyle = {backgroundColor: 'transparent'};
const selectedDateRangeStyle = {width: text_width, marginTop: 5, backgroundColor: 'transparent'};
// Dot
if (selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.DOT && hasSelected) {
selectedDateStyle.backgroundColor = selectedDateMarkColor;
}
// Circle
if (selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.CIRCLE) {
selectedDateRangeStyle.width = 30;
selectedDateRangeStyle.height = 30;
selectedDateRangeStyle.borderRadius = markBorderRadius || 999;
selectedDateRangeStyle.justifyContent = 'center';
selectedDateRangeStyle.alignItems = 'center';
if (hasSelected) {
selectedDateStyle.borderRadius = markBorderRadius || 999;
selectedDateRangeStyle.backgroundColor = selectedDateMarkColor;
}
}
// Ellipse or Semiellipse
if (selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.ELLIPSE || selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.SEMIELLIPSE) {
if (hasSelected) {
selectedDateStyle.borderRadius = markBorderRadius || 999;
selectedDateStyle.backgroundColor = selectedDateMarkColor;
selectedDateRangeStyle.backgroundColor = selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.ELLIPSE ? selectedDateMarkRangeColor : selectedDateMarkColor;
if (startDate && endDate) {
if (startDate === currentDate) {
selectedDateRangeStyle.borderTopLeftRadius = markBorderRadius || 999;
selectedDateRangeStyle.borderBottomLeftRadius = markBorderRadius || 999;
}
if (endDate === currentDate) {
selectedDateRangeStyle.borderTopRightRadius = markBorderRadius || 999;
selectedDateRangeStyle.borderBottomRightRadius = markBorderRadius || 999;
}
} else {
selectedDateRangeStyle.borderRadius = markBorderRadius || 999;
}
}
}
// Rectangle
if (selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.RECTANGLE) {
selectedDateStyle.borderRadius = markBorderRadius;
selectedDateRangeStyle.borderRadius = markBorderRadius;
if (hasSelected) {
selectedDateStyle.backgroundColor = selectedDateMarkColor;
selectedDateRangeStyle.backgroundColor = selectedDateMarkColor;
}
}
// Square
if (selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.SQUARE) {
selectedDateRangeStyle.width = 30;
selectedDateRangeStyle.height = 30;
selectedDateStyle.borderRadius = markBorderRadius;
selectedDateRangeStyle.borderRadius = markBorderRadius;
selectedDateRangeStyle.justifyContent = 'center';
selectedDateRangeStyle.alignItems = 'center';
if (hasSelected) {
selectedDateRangeStyle.backgroundColor = selectedDateMarkColor;
}
}
if (this._needSelectedRangeBgColor(startDate, endDate, currentDate)) {
selectedDateRangeStyle.backgroundColor = selectedDateMarkRangeColor;
}
return [selectedDateRangeStyle, selectedDateStyle];
};
_renderDot = styles => {
return (<View style={{borderRadius: 2.5, backgroundColor: styles[0].backgroundColor}}>
<View style={{width: 5, height: 5, borderRadius: 2.5, backgroundColor: styles[1].backgroundColor}}/>
</View>);
};
_renderDays = (day, index, days) => {
const {
item,
minDate,
maxDate,
listItemStyle,
beyondDatesDisabled,
beyondDatesDisabledTextColor,
selectedDateMarkType,
} = this.props;
const currentDate = `${item.year}-${item.month}-${day}`;
const markTypeStyles = this._getMarkTypeStyles(currentDate, days);
let dayStyle = {};
if (listItemStyle.day && typeof listItemStyle.day === 'object') {
const temDayStyle = Object.assign({}, listItemStyle.day);
delete temDayStyle.width;
delete temDayStyle.height;
dayStyle = temDayStyle;
}
const disabledDayStyle = {};
let disabled = false;
if (Constants.greaterThan(minDate, currentDate) || Constants.greaterThan(currentDate, maxDate)) {
disabledDayStyle.color = beyondDatesDisabledTextColor;
disabled = beyondDatesDisabled;
}
const isDot = selectedDateMarkType === Constants.DEFAULT_DATE_MARK_TYPE.DOT;
return day < 0 ? <View key={index} style={{width: text_width}}/> :
<TouchableOpacity
key={index}
disabled={disabled}
onPress={() => this._selectDate(currentDate, index)}
activeOpacity={0.6}
style={{width: text_width, ...CENTER_STYLES}}
>
<View style={[isDot ? {} : markTypeStyles[0]]}>
<View style={[isDot ? {...CENTER_STYLES, marginTop: 5} : markTypeStyles[1]]}>
<Text style={[listItemStyles.day, dayStyle, disabledDayStyle]}>{day}</Text>
{isDot && this._renderDot(markTypeStyles)}
</View>
</View>
</TouchableOpacity>;
};
render() {
const {
item,
listItemStyle,
showWeeks,
horizontal,
weeks,
weeksTextStyle,
weeksStyle,
weeksChineseType,
firstDayOnWeeks,
headerTitleType,
rightArrowClick,
leftArrowClick,
hideArrow,
arrowAlign,
arrowColor,
arrowSize,
} = this.props;
const _wks = weeksChineseType && weeks === Constants.DEFAULT_WEEK_EN ? Constants.DEFAULT_WEEK_ZH : weeks;
const _weeks = Constants.getWeekDays(_wks, firstDayOnWeeks);
return <View style={[listItemStyles.container, listItemStyle.container || {}]}>
<ListItemHeader
item={item}
headerTitleType={headerTitleType}
listItemStyle={listItemStyle}
leftArrowClick={leftArrowClick}
rightArrowClick={rightArrowClick}
hideArrow={hideArrow}
arrowColor={arrowColor}
arrowSize={arrowSize}
arrowAlign={arrowAlign}
horizontal={horizontal}
/>
{showWeeks && horizontal && <WeekBar
weeks={_weeks}
style={weeksStyle}
textStyle={weeksTextStyle}
/>}
<View style={[listItemStyles.dayContent, {paddingLeft: PADDING / 2}, listItemStyle.dayContent || {}]}>
{item.days.map((day, index) => this._renderDays(day, index, item.days))}
</View>
</View>;
}
}
ListItem.propTypes = {
showWeeks: PropTypes.bool,
horizontal: PropTypes.bool,
item: PropTypes.object.isRequired,
startDate: PropTypes.string,
endDate: PropTypes.string,
minDate: PropTypes.string,
maxDate: PropTypes.string,
beyondDatesDisabled: PropTypes.bool,
beyondDatesDisabledTextColor: PropTypes.string,
selectDate: PropTypes.func,
headerTitleType: PropTypes.number,
listItemStyle: PropTypes.object,
selectedDateMarkType: PropTypes.string,
selectedDateMarkColor: PropTypes.string,
selectedDateMarkRangeColor: PropTypes.string,
leftArrowClick: PropTypes.func,
rightArrowClick: PropTypes.func,
hideArrow: PropTypes.bool,
arrowColor: PropTypes.string,
arrowSize: PropTypes.number,
arrowAlign: PropTypes.string,
};
export default ListItem;