react-native-tx-modern-datetimepicker
Version:
Fix bugs and improve for lib: HosseinShabani/react-native-modern-datepicker. A customizable calendar, time & month picker for React Native
191 lines (177 loc) • 4.97 kB
JavaScript
import React, { createContext, useReducer, useContext, useState } from 'react'
import { View, StyleSheet } from 'react-native'
import PropTypes from 'prop-types'
import { Calendar, SelectMonth, SelectTime } from './components'
import { utils } from '../utils'
const options = {
backgroundColor: '#fff',
textHeaderColor: '#222',
textDefaultColor: '#222',
selectedTextColor: '#fff',
mainColor: '#0277BD',
textSecondaryColor: '#223344',
borderColor: 'rgba(122, 146, 165, 0.1)',
headerBorderWidth: 1,
defaultFont: 'System',
headerFont: 'System',
textFontSize: 14,
textHeaderFontSize: 16,
headerAnimationDistance: 100,
daysAnimationDistance: 200,
textHeaderStyle: {},
textDayNamesStyle: {},
textDayStyle: {},
textDaySelectedStyle: {},
textTodayStyle: {},
textMonthStyle: {},
textActionTimeStyle: {},
viewDaysNameStyle: {},
viewDaysContainerStyle: {},
viewDayItemStyle: {},
viewDayItemSelectedStyle: {},
viewHeaderItemStyle: {},
viewHeaderContainerStyle: {},
viewButtonActionSelectTimeStyle: {},
viewButtonActionCancelTimeStyle: {},
viewButtonsActionTimeStyle: {},
viewMonthItemSelectedStyle: {},
viewMonthItemStyle: {},
imageArrow: {},
inputYearStyle: {},
}
const reducer = (state, action) => {
switch (action.type) {
case 'set':
return { ...state, ...action }
case 'toggleMonth':
return { ...state, monthOpen: !state.monthOpen }
case 'toggleTime':
return { ...state, timeOpen: !state.timeOpen }
default:
throw new Error('Unexpected action')
}
}
const CalendarContext = createContext()
const useCalendar = () => {
const contextValue = useContext(CalendarContext)
return contextValue
}
const DatePicker = (props) => {
const calendarUtils = new utils(props)
const contextValue = {
...props,
reverse: props.reverse === 'unset' ? false : props.reverse,
options: { ...options, ...props.options },
utils: calendarUtils,
state: useReducer(reducer, {
activeDate: props.current || calendarUtils.getToday(),
selectedDate: props.selected
? calendarUtils.getFormated(calendarUtils.getDate(props.selected))
: '',
monthOpen: props.mode === 'monthYear',
timeOpen: props.mode === 'time',
}),
}
const [minHeight, setMinHeight] = useState(300)
const style = styles(contextValue.options)
const renderBody = () => {
switch (contextValue.mode) {
default:
case 'dateTimePicker':
return (
<React.Fragment>
<Calendar />
<SelectMonth />
<SelectTime />
</React.Fragment>
)
case 'calendar':
return (
<React.Fragment>
<Calendar />
<SelectMonth />
</React.Fragment>
)
case 'monthYear':
return <SelectMonth />
case 'time':
return <SelectTime />
}
}
return (
<CalendarContext.Provider value={contextValue}>
<View
style={[style.container, { minHeight }, props.style]}
onLayout={({ nativeEvent }) => setMinHeight(nativeEvent.layout.width * 0.9 + 55)}
>
{renderBody()}
</View>
</CalendarContext.Provider>
)
}
const styles = (theme) =>
StyleSheet.create({
container: {
backgroundColor: theme.backgroundColor,
position: 'relative',
width: '100%',
overflow: 'hidden',
},
})
const optionsShape = {
backgroundColor: PropTypes.string,
textHeaderColor: PropTypes.string,
textDefaultColor: PropTypes.string,
selectedTextColor: PropTypes.string,
mainColor: PropTypes.string,
textSecondaryColor: PropTypes.string,
borderColor: PropTypes.string,
headerBorderWidth: PropTypes.number,
defaultFont: PropTypes.string,
headerFont: PropTypes.string,
textFontSize: PropTypes.number,
textHeaderFontSize: PropTypes.number,
headerAnimationDistance: PropTypes.number,
daysAnimationDistance: PropTypes.number,
}
const modeArray = ['dateTimePicker', 'calendar', 'monthYear', 'time']
const minuteIntervalArray = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60]
DatePicker.defaultProps = {
onSelectedChange: () => null,
onMonthYearChange: () => null,
onTimeChange: () => null,
onDateChange: () => null,
current: '',
selected: '',
minimumDate: '',
maximumDate: '',
selectorStartingYear: 0,
selectorEndingYear: 3000,
disableDateChange: false,
configs: {},
reverse: 'unset',
options: {},
mode: 'dateTimePicker',
minuteInterval: 5,
style: {},
}
DatePicker.propTypes = {
onSelectedChange: PropTypes.func,
onMonthYearChange: PropTypes.func,
onTimeChange: PropTypes.func,
onDateChange: PropTypes.func,
current: PropTypes.string,
selected: PropTypes.string,
minimumDate: PropTypes.string,
maximumDate: PropTypes.string,
selectorStartingYear: PropTypes.number,
selectorEndingYear: PropTypes.number,
disableDateChange: PropTypes.bool,
configs: PropTypes.object,
reverse: PropTypes.oneOf([true, false, 'unset']),
options: PropTypes.shape(optionsShape),
mode: PropTypes.oneOf(modeArray),
minuteInterval: PropTypes.oneOf(minuteIntervalArray),
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
}
export { DatePicker, CalendarContext, useCalendar }