UNPKG

@aldiand/react-native-ui-datepicker

Version:
232 lines 6.67 kB
import React, { memo, useCallback, useEffect, useReducer } from 'react'; import { getFormated, getDate, dateToUnix, getEndOfDay, getStartOfDay, areDatesOnSameDay } from './utils'; import CalendarContext from './CalendarContext'; import { CalendarActionKind } from './enums'; import Calendar from './components/Calendar'; import dayjs from 'dayjs'; import localeData from 'dayjs/plugin/localeData'; import relativeTime from 'dayjs/plugin/relativeTime'; import localizedFormat from 'dayjs/plugin/localizedFormat'; dayjs.extend(localeData); dayjs.extend(relativeTime); dayjs.extend(localizedFormat); const DateTimePicker = props => { const { mode = 'single', locale = 'en', displayFullDays = false, timePicker = false, firstDayOfWeek, buttonPrevIcon, buttonNextIcon, // startYear, // endYear, minDate, maxDate, date, startDate, endDate, dates, onChange, initialView = 'day', height, ...rest } = props; const initialCalendarView = mode !== 'single' && initialView === 'time' ? 'day' : initialView; const firstDay = firstDayOfWeek && firstDayOfWeek > 0 && firstDayOfWeek <= 6 ? firstDayOfWeek : 0; let currentDate = dayjs(); if (mode === 'single' && date) { currentDate = dayjs(date); } if (mode === 'range' && startDate) { currentDate = dayjs(startDate); } if (mode === 'multiple' && dates && dates.length > 0) { currentDate = dayjs(dates[0]); } let currentYear = currentDate.year(); dayjs.locale(locale); const [state, dispatch] = useReducer((prevState, action) => { switch (action.type) { case CalendarActionKind.SET_CALENDAR_VIEW: return { ...prevState, calendarView: action.payload }; case CalendarActionKind.CHANGE_CURRENT_DATE: return { ...prevState, currentDate: action.payload }; case CalendarActionKind.CHANGE_CURRENT_YEAR: return { ...prevState, currentYear: action.payload }; case CalendarActionKind.CHANGE_SELECTED_DATE: const { date } = action.payload; return { ...prevState, date, currentDate: date }; case CalendarActionKind.CHANGE_SELECTED_RANGE: const { startDate, endDate } = action.payload; return { ...prevState, startDate, endDate }; case CalendarActionKind.CHANGE_SELECTED_MULTIPLE: const { dates } = action.payload; return { ...prevState, dates }; } }, { date, startDate, endDate, dates, calendarView: initialCalendarView, currentDate, currentYear }); useEffect(() => { if (mode === 'single') { const newDate = date && (timePicker ? date : getStartOfDay(date)); dispatch({ type: CalendarActionKind.CHANGE_SELECTED_DATE, payload: { date: newDate } }); } else if (mode === 'range') { dispatch({ type: CalendarActionKind.CHANGE_SELECTED_RANGE, payload: { startDate, endDate } }); } else if (mode === 'multiple') { dispatch({ type: CalendarActionKind.CHANGE_SELECTED_MULTIPLE, payload: { dates } }); } }, [mode, date, startDate, endDate, dates, timePicker]); const setCalendarView = useCallback(view => { dispatch({ type: CalendarActionKind.SET_CALENDAR_VIEW, payload: view }); }, []); const onSelectDate = useCallback(date => { if (onChange) { if (mode === 'single') { const newDate = timePicker ? date : getStartOfDay(date); dispatch({ type: CalendarActionKind.CHANGE_CURRENT_DATE, payload: newDate }); onChange({ date: newDate }); } else if (mode === 'range') { const sd = state.startDate; const ed = state.endDate; let isStart = true; if (sd && !ed && dateToUnix(date) >= dateToUnix(sd)) { isStart = false; } onChange({ startDate: isStart ? getStartOfDay(date) : sd, endDate: !isStart ? getEndOfDay(date) : undefined }); } else if (mode === 'multiple') { const safeDates = state.dates || []; const newDate = getStartOfDay(date); const exists = safeDates.some(ed => areDatesOnSameDay(ed, newDate)); const newDates = exists ? safeDates.filter(ed => !areDatesOnSameDay(ed, newDate)) : [...safeDates, newDate]; newDates.sort((a, b) => dayjs(a).isAfter(dayjs(b)) ? 1 : -1); onChange({ dates: newDates, datePressed: newDate, change: exists ? 'removed' : 'added' }); } } }, [onChange, mode, state.startDate, state.endDate, state.dates, timePicker]); const onSelectMonth = useCallback(month => { const newDate = getDate(state.currentDate).month(month); dispatch({ type: CalendarActionKind.CHANGE_CURRENT_DATE, payload: getFormated(newDate) }); dispatch({ type: CalendarActionKind.SET_CALENDAR_VIEW, payload: 'day' }); }, [state.currentDate]); const onSelectYear = useCallback(year => { const newDate = getDate(state.currentDate).year(year); dispatch({ type: CalendarActionKind.CHANGE_CURRENT_DATE, payload: getFormated(newDate) }); dispatch({ type: CalendarActionKind.SET_CALENDAR_VIEW, payload: 'day' }); }, [state.currentDate]); const onChangeMonth = useCallback(month => { const newDate = getDate(state.currentDate).add(month, 'month'); dispatch({ type: CalendarActionKind.CHANGE_CURRENT_DATE, payload: getFormated(newDate) }); }, [state.currentDate]); const onChangeYear = useCallback(year => { dispatch({ type: CalendarActionKind.CHANGE_CURRENT_YEAR, payload: year }); }, []); return /*#__PURE__*/React.createElement(CalendarContext.Provider, { value: { ...state, locale, mode, displayFullDays, timePicker, minDate, maxDate, firstDayOfWeek: firstDay, height, theme: rest, setCalendarView, onSelectDate, onSelectMonth, onSelectYear, onChangeMonth, onChangeYear } }, /*#__PURE__*/React.createElement(Calendar, { buttonPrevIcon: buttonPrevIcon, buttonNextIcon: buttonNextIcon, height: height })); }; export default /*#__PURE__*/memo(DateTimePicker); //# sourceMappingURL=DateTimePicker.js.map