UNPKG

react-native-calendars-datepicker

Version:

Customizable date picker for React Native that supports Hijri calendar

495 lines (490 loc) 19.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _utils = require("./utils"); var _calendarContext = require("./calendar-context"); var _enums = require("./enums"); var _calendar = _interopRequireDefault(require("./components/calendar")); var _dayjs = _interopRequireDefault(require("dayjs")); var _localeData = _interopRequireDefault(require("dayjs/plugin/localeData")); var _relativeTime = _interopRequireDefault(require("dayjs/plugin/relativeTime")); var _localizedFormat = _interopRequireDefault(require("dayjs/plugin/localizedFormat")); var _utc = _interopRequireDefault(require("dayjs/plugin/utc")); var _timezone = _interopRequireDefault(require("dayjs/plugin/timezone")); var _duration = _interopRequireDefault(require("dayjs/plugin/duration")); var _usePrevious = require("./hooks/use-previous"); var _jalaliPluginDayjs = _interopRequireDefault(require("jalali-plugin-dayjs")); var _dayjsCalendarsystems = _interopRequireDefault(require("@calidy/dayjs-calendarsystems")); var _HijriCalendarSystem = _interopRequireDefault(require("@calidy/dayjs-calendarsystems/calendarSystems/HijriCalendarSystem")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } _dayjs.default.extend(_localeData.default); _dayjs.default.extend(_relativeTime.default); _dayjs.default.extend(_localizedFormat.default); _dayjs.default.extend(_utc.default); _dayjs.default.extend(_timezone.default); _dayjs.default.extend(_duration.default); _dayjs.default.extend(_jalaliPluginDayjs.default); _dayjs.default.extend(_dayjsCalendarsystems.default); /* Register new calendar system, here I'm using Hijri for other sytems visit URL: https://github.com/calidy-com/dayjs-calendarsystems */ _dayjs.default.registerCalendarSystem('islamic', new _HijriCalendarSystem.default()); const DateTimePicker = props => { const { mode = 'single', calendar = 'gregory', locale = 'en', numerals = 'latn', timeZone, showOutsideDays = false, timePicker = false, firstDayOfWeek, // startYear, // endYear, minDate, maxDate, enabledDates, disabledDates, date, startDate, endDate, dates, min, max, onChange, initialView = 'day', containerHeight = _enums.CONTAINER_HEIGHT, weekdaysHeight = _enums.WEEKDAYS_HEIGHT, style = {}, className = '', classNames = {}, styles = {}, navigationPosition, weekdaysFormat = 'min', monthsFormat = 'full', monthCaptionFormat = 'full', multiRangeMode, hideHeader, hideWeekdays, disableMonthPicker, disableYearPicker, components = {}, month, year, onMonthChange = () => {}, onYearChange = () => {}, use12Hours } = props; _dayjs.default.tz.setDefault(timeZone); if (calendar !== 'islamic') { _dayjs.default.calendar(calendar); } _dayjs.default.locale(locale); const prevTimezone = (0, _usePrevious.usePrevious)(timeZone); const initialCalendarView = (0, _react.useMemo)(() => mode !== 'single' && initialView === 'time' ? 'day' : initialView, [mode, initialView]); const firstDay = (0, _react.useMemo)(() => firstDayOfWeek && firstDayOfWeek > 0 && firstDayOfWeek <= 6 ? firstDayOfWeek : 0, [firstDayOfWeek]); const initialState = (0, _react.useMemo)(() => { let initialDate = (0, _dayjs.default)().tz(timeZone); if (calendar === 'islamic') { initialDate = (0, _utils.getDayjs)(initialDate, calendar); } if (mode === 'single' && date) { initialDate = (0, _utils.getDayjs)(date, calendar); } if (mode === 'range' && startDate) { initialDate = (0, _utils.getDayjs)(startDate, calendar); } if (mode === 'multiple' && dates && dates.length > 0) { initialDate = (0, _utils.getDayjs)(dates[0], calendar); } if (minDate && initialDate.isBefore(minDate)) { initialDate = (0, _utils.getDayjs)(minDate, calendar); } if (month !== undefined && month && month >= 0 && month <= 11) { initialDate = initialDate.month(month); } if (year !== undefined && year >= 0) { initialDate = initialDate.year(year); } let _date = date ? (0, _utils.getDayjs)(date, calendar) : date; if (_date && maxDate && (0, _utils.getDayjs)(_date, calendar).isAfter(maxDate)) { _date = (0, _utils.getDayjs)(maxDate, calendar); } if (_date && minDate && (0, _utils.getDayjs)(_date, calendar).isBefore(minDate)) { _date = (0, _dayjs.default)(minDate); } let start = startDate ? (0, _utils.getDayjs)(startDate, calendar) : startDate; if (start && maxDate && (0, _utils.getDayjs)(start, calendar).isAfter(maxDate)) { start = (0, _utils.getDayjs)(maxDate, calendar); } if (start && minDate && (0, _utils.getDayjs)(start, calendar).isBefore(minDate)) { start = (0, _utils.getDayjs)(minDate, calendar); } let end = endDate ? (0, _utils.getDayjs)(endDate, calendar) : endDate; if (end && maxDate && (0, _utils.getDayjs)(end, calendar).isAfter(maxDate)) { end = (0, _utils.getDayjs)(maxDate, calendar); } if (end && minDate && (0, _utils.getDayjs)(end, calendar).isBefore(minDate)) { end = (0, _utils.getDayjs)(minDate, calendar); } return { date: _date, startDate: start, endDate: end, dates, calendarView: initialCalendarView, currentDate: initialDate, currentYear: initialDate.year(), isRTL: calendar === 'jalali' || _reactNative.I18nManager.isRTL }; }, [mode, calendar, date, startDate, endDate, dates, minDate, maxDate, month, year, timeZone, initialCalendarView]); const [state, dispatch] = (0, _react.useReducer)((prevState, action) => { switch (action.type) { case _enums.CalendarActionKind.SET_CALENDAR_VIEW: return { ...prevState, calendarView: action.payload }; case _enums.CalendarActionKind.CHANGE_CURRENT_DATE: return { ...prevState, currentDate: action.payload }; case _enums.CalendarActionKind.CHANGE_CURRENT_YEAR: return { ...prevState, currentYear: action.payload }; case _enums.CalendarActionKind.CHANGE_SELECTED_DATE: const { date: selectedDate } = action.payload; return { ...prevState, date: selectedDate, currentDate: selectedDate }; case _enums.CalendarActionKind.CHANGE_SELECTED_RANGE: const { startDate: start, endDate: end } = action.payload; return { ...prevState, startDate: start, endDate: end }; case _enums.CalendarActionKind.CHANGE_SELECTED_MULTIPLE: const { dates: selectedDates } = action.payload; return { ...prevState, dates: selectedDates }; case _enums.CalendarActionKind.SET_IS_RTL: return { ...prevState, isRTL: action.payload }; case _enums.CalendarActionKind.RESET_STATE: return action.payload; default: return prevState; } }, initialState); const stateRef = (0, _react.useRef)(state); stateRef.current = state; (0, _react.useEffect)(() => { const newState = { ...initialState, isRTL: calendar === 'jalali' || _reactNative.I18nManager.isRTL }; dispatch({ type: _enums.CalendarActionKind.RESET_STATE, payload: newState }); }, [calendar]); (0, _react.useEffect)(() => { if (prevTimezone !== timeZone) { const newDate = (0, _dayjs.default)().tz(timeZone); dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE, payload: newDate }); } }, [timeZone, prevTimezone]); (0, _react.useEffect)(() => { if (mode === 'single') { let _date = (date && (timePicker ? _dayjs.default.tz(date, timeZone) : (0, _utils.getStartOfDay)(_dayjs.default.tz(date, timeZone), calendar))) ?? date; if (_date && maxDate && _dayjs.default.tz(_date, timeZone).isAfter(maxDate)) { _date = _dayjs.default.tz(maxDate, timeZone); } if (_date && minDate && _dayjs.default.tz(_date, timeZone).isBefore(minDate)) { _date = _dayjs.default.tz(minDate, timeZone); } if (_date) { dispatch({ type: _enums.CalendarActionKind.CHANGE_SELECTED_DATE, payload: { date: (0, _utils.getDayjs)(_date, calendar) } }); } if (prevTimezone !== timeZone) { onChange({ date: _date ? (0, _utils.getDayjs)(_date, calendar).toDate() : _date }); } } else if (mode === 'range') { let start = startDate ? _dayjs.default.tz(startDate, timeZone) : startDate; if (start && maxDate && _dayjs.default.tz(start, timeZone).isAfter(maxDate)) { start = _dayjs.default.tz(maxDate, timeZone); } if (start && minDate && _dayjs.default.tz(start, timeZone).isBefore(minDate)) { start = _dayjs.default.tz(minDate, timeZone); } let end = endDate ? _dayjs.default.tz(endDate, timeZone) : endDate; if (end && maxDate && _dayjs.default.tz(end, timeZone).isAfter(maxDate)) { end = _dayjs.default.tz(maxDate, timeZone); } if (end && minDate && _dayjs.default.tz(end, timeZone).isBefore(minDate)) { end = _dayjs.default.tz(minDate, timeZone); } dispatch({ type: _enums.CalendarActionKind.CHANGE_SELECTED_RANGE, payload: { startDate: start, endDate: end } }); if (prevTimezone !== timeZone) { onChange({ startDate: start ? (0, _utils.getDayjs)(start, calendar).toDate() : start, endDate: end ? (0, _utils.getDayjs)(end, calendar).toDate() : end }); } } else if (mode === 'multiple') { const _dates = dates === null || dates === void 0 ? void 0 : dates.map(date => (0, _utils.getDayjs)(date, calendar).tz(timeZone)); dispatch({ type: _enums.CalendarActionKind.CHANGE_SELECTED_MULTIPLE, payload: { dates: _dates } }); if (prevTimezone !== timeZone) { onChange({ dates: _dates.map(item => (0, _utils.getDayjs)(item, calendar).toDate()), change: 'updated' }); } } }, [mode, date, startDate, endDate, dates, minDate, maxDate, timePicker, prevTimezone, timeZone, calendar, onChange]); const setCalendarView = (0, _react.useCallback)(view => { dispatch({ type: _enums.CalendarActionKind.SET_CALENDAR_VIEW, payload: view }); }, []); const onSelectDate = (0, _react.useCallback)(selectedDate => { if (onChange) { if (mode === 'single') { const newDate = timePicker ? _dayjs.default.tz(selectedDate, timeZone) : _dayjs.default.tz((0, _utils.getStartOfDay)(selectedDate, calendar), timeZone); dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE, payload: newDate }); onChange({ date: newDate ? (0, _utils.getDayjs)(newDate, calendar).toDate() : newDate }); } else if (mode === 'range') { // set time to 00:00:00 let start = (0, _utils.removeTime)(stateRef.current.startDate, timeZone, calendar); let end = (0, _utils.removeTime)(stateRef.current.endDate, timeZone, calendar); const selected = (0, _utils.removeTime)(selectedDate, timeZone, calendar); let isStart = true; let isReset = false; const selectedUnix = (0, _utils.dateToUnix)(selected, calendar); const startUnix = (0, _utils.dateToUnix)(start, calendar); const endUnix = (0, _utils.dateToUnix)(end, calendar); if (selectedUnix !== endUnix && selectedUnix >= startUnix && startUnix !== endUnix) { isStart = false; } else if (start && selectedUnix === startUnix) { isReset = true; } if (start && end) { if (startUnix === endUnix && selectedUnix > startUnix) { isStart = false; } if (selectedUnix > startUnix && selectedUnix === endUnix) { end = undefined; } } if (start && !end && selectedUnix < startUnix) { end = start; } if (isStart && end && (min || max)) { const numberOfDays = (0, _utils.getDayjs)(end, calendar).diff(selected, 'day'); if (max && numberOfDays > max || min && numberOfDays < min) { isStart = true; end = undefined; } } if (!isStart && start && (min || max)) { const numberOfDays = (0, _utils.getDayjs)(selected, calendar).diff(start, 'day'); if (selectedUnix === startUnix) { isReset = true; } else if (max && numberOfDays > max || min && numberOfDays < min) { isStart = true; end = undefined; } } if (isReset) { onChange({ startDate: undefined, endDate: undefined }); } else { onChange({ startDate: isStart ? (0, _utils.getDayjs)(selected, calendar).toDate() : start ? _dayjs.default.tz(start).toDate() : start, endDate: !isStart ? _dayjs.default.tz((0, _utils.getEndOfDay)(selected, calendar), timeZone).toDate() : end ? _dayjs.default.tz((0, _utils.getEndOfDay)(end, calendar), timeZone).toDate() : end }); } } else if (mode === 'multiple') { const safeDates = stateRef.current.dates || []; const newDate = _dayjs.default.tz((0, _utils.getDayjs)(selectedDate, calendar), timeZone).startOf('day'); const exists = safeDates.some(ed => (0, _utils.areDatesOnSameDay)(ed, newDate, calendar)); const newDates = exists ? safeDates.filter(ed => !(0, _utils.areDatesOnSameDay)(ed, newDate, calendar)) : [...safeDates, newDate]; if (max && newDates.length > max) { return; } newDates.sort((a, b) => (0, _dayjs.default)(a).isAfter((0, _dayjs.default)(b)) ? 1 : -1); const _dates = newDates.map(date => (0, _dayjs.default)(date).tz(timeZone)); onChange({ dates: _dates.map(item => (0, _dayjs.default)(item).toDate()), datePressed: newDate ? (0, _dayjs.default)(newDate).toDate() : newDate, change: exists ? 'removed' : 'added' }); } } }, [mode, timePicker, min, max, timeZone]); // set the active displayed month const onSelectMonth = (0, _react.useCallback)(value => { const currentMonth = stateRef.current.currentDate.month(); const newDate = stateRef.current.currentDate.month(value); // Only call onMonthChange if the month actually changed if (value !== currentMonth) { onMonthChange(value); } dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE, payload: (0, _utils.getDayjs)(newDate, calendar) }); setCalendarView('day'); }, [calendar, setCalendarView, onMonthChange]); // set the active displayed year const onSelectYear = (0, _react.useCallback)(value => { const currentYear = (0, _utils.getDayjs)(stateRef.current.currentDate, calendar).year(); const newDate = (0, _utils.getDayjs)(stateRef.current.currentDate, calendar).year(value); // Only call onYearChange if the year actually changed if (value !== currentYear) { onYearChange(value); } dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE, payload: newDate }); setCalendarView('day'); }, [calendar, setCalendarView, onYearChange]); const onChangeMonth = (0, _react.useCallback)(value => { const currentMonth = stateRef.current.currentDate.month(); const newDate = stateRef.current.currentDate.month(currentMonth + value); dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE, payload: newDate }); }, []); const onChangeYear = (0, _react.useCallback)(value => { dispatch({ type: _enums.CalendarActionKind.CHANGE_CURRENT_YEAR, payload: value }); }, [dispatch]); (0, _react.useEffect)(() => { if (month !== undefined && month >= 0 && month <= 11) { onSelectMonth(month); } }, [month]); (0, _react.useEffect)(() => { if (year !== undefined && year >= 0) { onSelectYear(year); } }, [year]); const memoizedStyles = (0, _utils.useDeepCompareMemo)({ ...styles }, [styles]); const memoizedClassNames = (0, _utils.useDeepCompareMemo)({ ...classNames }, [classNames]); const memoizedComponents = (0, _react.useMemo)(() => ({ ...components }), [components]); const baseContextValue = (0, _react.useMemo)(() => ({ mode, calendar, locale, numerals, timeZone, showOutsideDays, timePicker, minDate, maxDate, min, max, enabledDates, disabledDates, firstDayOfWeek: firstDay, containerHeight, weekdaysHeight, navigationPosition, weekdaysFormat, monthsFormat, monthCaptionFormat, multiRangeMode, hideHeader, hideWeekdays, disableMonthPicker, disableYearPicker, style, className, use12Hours }), [mode, calendar, locale, numerals, timeZone, showOutsideDays, timePicker, minDate, maxDate, min, max, enabledDates, disabledDates, firstDay, containerHeight, weekdaysHeight, navigationPosition, weekdaysFormat, monthsFormat, monthCaptionFormat, multiRangeMode, hideHeader, hideWeekdays, disableMonthPicker, disableYearPicker, style, className, use12Hours]); const handlerContextValue = (0, _react.useMemo)(() => ({ setCalendarView, onSelectDate, onSelectMonth, onSelectYear, onChangeMonth, onChangeYear }), [setCalendarView, onSelectDate, onSelectMonth, onSelectYear, onChangeMonth, onChangeYear]); const styleContextValue = (0, _react.useMemo)(() => ({ classNames: memoizedClassNames, styles: memoizedStyles }), [memoizedClassNames, memoizedStyles]); const memoizedValue = (0, _react.useMemo)(() => ({ ...state, ...baseContextValue, ...handlerContextValue, ...styleContextValue, components: memoizedComponents }), [state, baseContextValue, handlerContextValue, styleContextValue, memoizedComponents]); return /*#__PURE__*/_react.default.createElement(_calendarContext.CalendarContext.Provider, { value: memoizedValue }, /*#__PURE__*/_react.default.createElement(_calendar.default, null)); }; var _default = exports.default = DateTimePicker; //# sourceMappingURL=datetime-picker.js.map