UNPKG

react-native-common-date-picker

Version:

An awesome and cross-platform React Native date picker and calendar component for iOS and Android

439 lines (381 loc) 16.1 kB
import React, {Component} from 'react'; import {View} from 'react-native'; import DatePickerList from './DatePickerList'; import PropTypes from 'prop-types'; import styles from './style'; import ToolBar from '../components/ToolBar'; import * as Constants from '../contants'; class DatePicker extends Component { constructor(props) { super(props); this.state = Constants.getDatePickerInitialData(props); } shouldComponentUpdate(nextProps, nextState) { if (this.props.defaultDate !== nextProps.defaultDate) { this.setState({ isDefaultDateChanged: true }, () => { const obj = Constants.getDatePickerInitialData(nextProps); this.setState(obj); }); } return true; } _onValueChange = (key, selectedIndex) => { const {years, months, days} = this.state; const _getSelectedIndex = dates => selectedIndex < 0 ? 0 : Math.min(selectedIndex, dates.length - 1); switch (key) { case Constants.DATE_KEY_TYPE.YEAR: const yearIndex = _getSelectedIndex(years); this.setState({ selectedYear: years[yearIndex].date, months: Constants.selectDatePickerData(yearIndex, years), }, this._onValueChangeCallBack); break; case Constants.DATE_KEY_TYPE.MONTH: const monthIndex = _getSelectedIndex(months); this.setState({ selectedMonth: months[monthIndex].date, days: Constants.selectDatePickerData(monthIndex, months), }, this._onValueChangeCallBack); break; case Constants.DATE_KEY_TYPE.DAY: const dayIndex = _getSelectedIndex(days); this.setState({selectedDay: days[dayIndex].date}, this._onValueChangeCallBack); break; default: break; } }; _onValueChangeCallBack = () => { const {onValueChange, monthDisplayMode} = this.props; const {selectedYear, selectedMonth, selectedDay} = this.state; const _selectedDate = `${selectedYear}-${selectedMonth}-${selectedDay}`; const selectedDate = Constants.toStandardStringWith(_selectedDate, monthDisplayMode); onValueChange && typeof onValueChange === 'function' && onValueChange(selectedDate); }; render() { const { type, backgroundColor, width, rows, rowHeight, selectedRowBackgroundColor, unselectedRowBackgroundColor, selectedBorderLineColor, selectedBorderLineWidth, selectedBorderLineMarginHorizontal, selectedTextFontSize, selectedTextColor, selectedTextStyle, unselectedTextColor, unselectedTextStyle, textMarginHorizontal, showToolBar, toolBarPosition, toolBarStyle, toolBarCancelStyle, toolBarConfirmStyle, titleStyle, titleText, cancelText, confirmText, cancel, confirm, cancelDisabled, confirmDisabled, monthDisplayMode, yearSuffix, monthSuffix, daySuffix, } = this.props; const { years, months, days, selectedYear, selectedMonth, selectedDay, defaultYearIndex, defaultMonthIndex, defaultDayIndex, isDefaultDateChanged, } = this.state; if (isDefaultDateChanged) return null; const dataSource = Constants.getDatePickerData(type, years, months, days); const _toolBar = (<ToolBar style={[{backgroundColor}, toolBarStyle]} cancelStyle={toolBarCancelStyle} confirmStyle={toolBarConfirmStyle} titleStyle={titleStyle} titleText={titleText} cancelText={cancelText} cancel={() => cancel && typeof cancel === 'function' && cancel()} confirm={() => { const _selectedDate = `${selectedYear}-${selectedMonth}-${selectedDay}`; const selectedDate = Constants.toStandardStringWith(_selectedDate, monthDisplayMode); confirm && typeof confirm === 'function' && confirm(selectedDate); }} confirmText={confirmText} cancelDisabled={cancelDisabled} confirmDisabled={confirmDisabled} />); return ( <View> {showToolBar && toolBarPosition === Constants.DEFAULT_TOOL_BAR_POSITION.TOP && _toolBar} <View style={[styles.datePickerContainer, {backgroundColor}]}> { dataSource.map((item, index) => { const {key, data} = item; const initialScrollIndex = key === Constants.DATE_KEY_TYPE.YEAR ? defaultYearIndex : (key === Constants.DATE_KEY_TYPE.MONTH ? defaultMonthIndex : defaultDayIndex); return (<DatePickerList key={index} data={data} dataIndex={index} keyType={key} rows={rows} rowHeight={rowHeight} dataLength={dataSource.length} initialScrollIndex={initialScrollIndex} width={Constants.datePickerListWidth(type, width)} onValueChange={selectedIndex => this._onValueChange(key, selectedIndex)} selectedRowBackgroundColor={selectedRowBackgroundColor || backgroundColor} unselectedRowBackgroundColor={unselectedRowBackgroundColor || backgroundColor} selectedBorderLineColor={selectedBorderLineColor} selectedBorderLineWidth={selectedBorderLineWidth} selectedBorderLineMarginHorizontal={selectedBorderLineMarginHorizontal} selectedTextFontSize={selectedTextFontSize} selectedTextColor={selectedTextColor} selectedTextStyle={selectedTextStyle} unselectedTextColor={unselectedTextColor} unselectedTextStyle={unselectedTextStyle} textMarginHorizontal={textMarginHorizontal} yearSuffix={yearSuffix} monthSuffix={monthSuffix} daySuffix={daySuffix} />); }) } </View> {showToolBar && toolBarPosition === Constants.DEFAULT_TOOL_BAR_POSITION.BOTTOM && _toolBar} </View> ); } } DatePicker.propTypes = { /** * Container background color. Default is 'white'. */ backgroundColor: PropTypes.string, /** * Date type in order. Default is 'YYYY-MM-DD'. WOW! All kinds of date type order are supported. Awesome! * NOTE: for 'MM-DD'、'DD-MM'、'MM', the same year for minDate and maxDate is required. E.g: minDate={'2020-03-10'}, maxDate={'2020-06-25'}. * For 'DD', the year and the month for minDate and maxDate must be the same. E.g: minDate={'2020-03-06'}, maxDate={'2020-03-25'}. */ type: PropTypes.oneOf([ 'YYYY-MM-DD', 'MM-DD-YYYY', 'DD-MM-YYYY', 'YYYY-MM', 'MM-YYYY', 'MM-DD', 'DD-MM', 'YYYY', 'MM', 'DD', ]), /** * The min date. Default is '2000-1-1'. Other supported formats: '2000-01-01'、'2000-1-01'、'2000-01-1'、 * '2000/01/01'、'2000/1/1'. A string type or Date type are supported. */ minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), /** * The min date. Default is today. Other supported formats are the same as minDate. A string type or Date type are * also supported. E.g: new Date(). */ maxDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), /** * The default date. Default is equal to maxDate. Other supported formats are the same as minDate and maxDate. * A string type or Date type are also supported. E.g: new Date(). */ defaultDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), /** * Whether to show tool bar, default is true. If false, hide tool bar on top. */ showToolBar: PropTypes.bool, /** * The position of tool bar, default is 'top' that is at the top of screen. So far, just both 'top' and 'bottom' * are supported. */ toolBarPosition: PropTypes.oneOf(['top', 'bottom']), /** * Tool bar view styles, passed like {backgroundColor: 'red'} as you like. */ toolBarStyle: PropTypes.object, /** * Tool bar cancel button text styles, passed like {color: 'red', fontSize: 15} as you like. * Note that you can control the active opacity of the button through {activeOpacity: 1}. */ toolBarCancelStyle: PropTypes.object, /** * Tool bar confirm button text styles, passed like {color: 'red', fontSize: 15} as you like. * Note that you can control the active opacity of the button through {activeOpacity: 1}. */ toolBarConfirmStyle: PropTypes.object, /** * Tool bar title text style. */ titleStyle: PropTypes.object, /** * Tool bar title text, default is "". */ titleText: PropTypes.string, /** * Tool bar cancel button text, default is "Cancel". */ cancelText: PropTypes.string, /** * Tool bar confirm button text, default is "Confirm". */ confirmText: PropTypes.string, /** * On date value change callback in real time. Once you has selected the date each time, you'll get the date you selected. * For example, you can set like this to get the selected date: * ...... * onValueChange={selectedDate => console.warn(selectedDate)} * ...... */ onValueChange: PropTypes.func, /** * Tool bar cancel button callback. */ cancel: PropTypes.func, /** * Tool bar confirm button callback with a date string like "2020-06-10". */ confirm: PropTypes.func, /** * Whether to disable the cancel button. Default is false. */ cancelDisabled: PropTypes.bool, /** * Whether to disable the confirm button. Default is false. */ confirmDisabled: PropTypes.bool, /** * Width for date picker. Default is screen width. Note that the height for date picker relied on the rowHeight and the rows below. */ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Row number for date picker. Default is 5. Note that Only one of [5, 7] is supported up to now. E.g: rows={5} or rows={7}. */ rows: PropTypes.oneOf([5, 7]), /** * Height for each row. Default is 35. */ rowHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Background color for the selected row. Default is 'white'. */ selectedRowBackgroundColor: PropTypes.string, /** * Background color for the unselected row. Default is 'white'. */ unselectedRowBackgroundColor: PropTypes.string, /** * Border line color for the selected row. Default is '#d3d3d3'. */ selectedBorderLineColor: PropTypes.string, /** * Border line width for the selected row. Default is 0.5. string and number type are supported. E.g: selectedBorderLineWidth={20} or selectedBorderLineWidth={'20'}. */ selectedBorderLineWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Border line margin horizontal. Default is 0. */ selectedBorderLineMarginHorizontal: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Font size for the selected row text. Default is 22. string and number type are supported. E.g: selectedTextFontSize={20} or selectedTextFontSize={'20'}. */ selectedTextFontSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Text color for the selected row text. Default is 'black'. */ selectedTextColor: PropTypes.string, /** * The selected text styles. Note that if both `selectedTextStyle` and `selectedTextFontSize` are set, `selectedTextStyle` * will have higher priority. For example, if selectedTextStyle={{fontSize: 15}} and selectedTextFontSize=10, then the selected * font size will be 15. */ selectedTextStyle: PropTypes.object, /** * Text color for the unselected row text. Default is '#9d9d9d'. */ unselectedTextColor: PropTypes.string, /** * The unselected text styles. Note that if both `unselectedTextStyle` and `unselectedTextColor` are set, `unselectedTextStyle` * will have higher priority. For example, if unselectedTextStyle={{color: 'white'}} and unselectedTextColor={'black'}, then the * unselected text color will be `white`. Besides, the fontSize is not supported for the unselected text, it's only determined by * the selected text font size setting. For example, if you set unselectedTextStyle={{fontSize: 15}}, it won't work. */ unselectedTextStyle: PropTypes.object, /** * Text margin horizontal distance to left and right. Default is 0. */ textMarginHorizontal: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * The display of the month. Default is 'digit', namely "1, 2, 3, ..., 12". If monthDisplayMode={'en-short'}, "Jan, Feb, ..., * Nov, Dec" will be displayed. If monthDisplayMode={'en-long'}, similarly, "January, February, ..., November, December" will be displayed. */ monthDisplayMode: PropTypes.oneOf([ 'digit', 'en-short', 'en-long', ]), /** * Year suffix string to display for each row. E.g: if yearSuffix={'年'}, the year column will follow a '年' suffix like 2020年. */ yearSuffix: PropTypes.string, /** * Month suffix string to display for each row. E.g: if monthSuffix={'月'}, the month column will follow a '月' suffix like 6月. */ monthSuffix: PropTypes.string, /** * Day suffix string to display for each row. E.g: if daySuffix={'日'}, the year column will follow a '日' suffix like 10日. */ daySuffix: PropTypes.string, }; DatePicker.defaultProps = { backgroundColor: 'white', type: 'YYYY-MM-DD', minDate: Constants.DEFAULT_MIN_DATE, maxDate: Constants.DEFAULT_MAX_DATE, width: Constants.SCREEN_WIDTH, rows: Constants.DATE_PICKER_ROWS, rowHeight: Constants.DATE_PICKER_ROW_HEIGHT, selectedRowBackgroundColor: '', unselectedRowBackgroundColor: '', selectedBorderLineColor: '#d3d3d3', selectedBorderLineWidth: 0.5, selectedBorderLineMarginHorizontal: 0, selectedTextFontSize: 22, selectedTextColor: 'black', selectedTextStyle: {}, unselectedTextColor: '#9d9d9d', unselectedTextStyle: {}, textMarginHorizontal: 0, showToolBar: true, toolBarPosition: Constants.DEFAULT_TOOL_BAR_POSITION.TOP, cancelText: Constants.DEFAULT_CANCEL_TEXT, confirmText: Constants.DEFAULT_CONFIRM_TEXT, cancel: () => { }, confirm: () => { }, cancelDisabled: false, confirmDisabled: false, monthDisplayMode: Constants.MONTH_DISPLAY_MODE.DIGIT, yearSuffix: '', monthSuffix: '', daySuffix: '', }; export default DatePicker;