react-native-easy-calendar
Version:
Customizable, easy-to-use, performant calendar components for React Native
157 lines (150 loc) • 6.01 kB
JavaScript
import React, { useEffect, useState, useCallback } from 'react';
import { View } from 'react-native';
import dayjs from 'dayjs';
import localeData from 'dayjs/plugin/localeData';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import utc from 'dayjs/plugin/utc';
import { getSurroundingTimeUnits } from '../Utils';
import { useSurroundingTimeUnits } from '../Hooks';
import { ThemeContext, LocaleContext } from '../Contexts';
import { VIEW } from '../Constants';
import { Months, Days, Arrow as DefaultArrow, Title as DefaultTitle, Weekdays as DefaultWeekdays } from '../Components';
dayjs.extend(localeData);
dayjs.extend(localizedFormat);
dayjs.extend(utc);
const BaseCalendar = ({
ArrowComponent: CustomArrow,
TitleComponent: CustomTitle,
WeekdaysComponent: CustomWeekdays,
DayComponent,
MonthComponent,
allowYearView,
showExtraDates,
onPressDay,
maxDate,
minDate,
initVisibleDate,
dateProperties,
testID
}) => {
const theme = React.useContext(ThemeContext);
const locale = React.useContext(LocaleContext);
const [rightArrowDisabled, disableRightArrow] = useState(false);
const [leftArrowDisabled, disableLeftArrow] = useState(false);
const [activeView, setActiveView] = useState(VIEW.MONTH);
const [visibleDate, setVisibleDate] = useState(initVisibleDate !== null && initVisibleDate !== void 0 ? initVisibleDate : dayjs().local().format());
const localeAwareVisibleDate = React.useMemo(() => dayjs(visibleDate).locale(locale.name, locale), [locale, visibleDate]);
const weekdays = React.useMemo(() => {
var _locale$weekdaysShort;
return (_locale$weekdaysShort = locale.weekdaysShort) !== null && _locale$weekdaysShort !== void 0 ? _locale$weekdaysShort : [''];
}, [locale]);
const {
month,
year
} = useSurroundingTimeUnits(visibleDate);
const verifyUnitIsPastMaxDate = useCallback(unit => {
if (maxDate) {
if (unit.isAfter(maxDate)) {
disableRightArrow(true);
} else {
disableRightArrow(false);
}
}
}, [disableRightArrow, maxDate]);
const verifyUnitIsBeforeMinDate = useCallback(unit => {
if (minDate) {
if (unit.isBefore(minDate)) {
disableLeftArrow(true);
} else {
disableLeftArrow(false);
}
}
}, [disableLeftArrow, minDate]);
const toggleCalendarView = useCallback((newVisibleDate = visibleDate) => {
const {
month: _month,
year: _year
} = getSurroundingTimeUnits(newVisibleDate);
if (activeView === VIEW.MONTH) {
setActiveView(VIEW.YEAR);
verifyUnitIsPastMaxDate(_year.next);
verifyUnitIsBeforeMinDate(_year.last);
}
if (activeView === VIEW.YEAR) {
setActiveView(VIEW.MONTH);
verifyUnitIsPastMaxDate(_month.next);
verifyUnitIsBeforeMinDate(_month.last);
}
}, [activeView, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate, visibleDate]);
useEffect(() => {
verifyUnitIsPastMaxDate(month.next.start);
verifyUnitIsBeforeMinDate(month.last.end);
}, [month.last.end, month.next.start, verifyUnitIsPastMaxDate, verifyUnitIsBeforeMinDate]);
const addMonth = useCallback(() => {
setVisibleDate(month.next.start.local().format());
verifyUnitIsPastMaxDate(month.afterNext);
verifyUnitIsBeforeMinDate(month.current.end);
}, [month, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
const subtractMonth = useCallback(() => {
setVisibleDate(month.last.start.local().format());
verifyUnitIsPastMaxDate(month.current.start);
verifyUnitIsBeforeMinDate(month.beforeLast);
}, [month, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
const addYear = useCallback(() => {
setVisibleDate(year.next.persistMonth.local().format());
verifyUnitIsPastMaxDate(year.afterNext);
verifyUnitIsBeforeMinDate(year.current.end);
}, [year, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
const subtractYear = useCallback(() => {
setVisibleDate(year.last.persistMonth.local().format());
verifyUnitIsPastMaxDate(year.current.start);
verifyUnitIsBeforeMinDate(year.beforeLast);
}, [year, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
const onPressMonth = newVisibleDate => {
setVisibleDate(newVisibleDate);
toggleCalendarView(newVisibleDate);
};
const Weekdays = CustomWeekdays || DefaultWeekdays;
const Arrow = CustomArrow || DefaultArrow;
const Title = CustomTitle || DefaultTitle;
return /*#__PURE__*/React.createElement(View, {
style: theme.calendarContainer,
testID: testID
}, /*#__PURE__*/React.createElement(View, {
testID: 'header',
style: theme.headerContainer
}, /*#__PURE__*/React.createElement(Arrow, {
direction: 'left',
isDisabled: leftArrowDisabled,
onPress: activeView === VIEW.MONTH ? subtractMonth : subtractYear
}), /*#__PURE__*/React.createElement(Title, {
activeView: activeView,
locale: locale,
date: localeAwareVisibleDate.format('YYYY-MM-DD'),
isDisabled: !allowYearView,
onPress: toggleCalendarView
}), /*#__PURE__*/React.createElement(Arrow, {
direction: 'right',
isDisabled: rightArrowDisabled,
onPress: activeView === VIEW.MONTH ? addMonth : addYear
})), activeView === VIEW.MONTH ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Weekdays, {
days: weekdays
}), /*#__PURE__*/React.createElement(Days, {
DayComponent: DayComponent,
visibleDate: localeAwareVisibleDate,
showExtraDates: !!showExtraDates,
dateProperties: dateProperties,
onPressDay: onPressDay,
minDate: minDate,
maxDate: maxDate
})) : /*#__PURE__*/React.createElement(Months, {
MonthComponent: MonthComponent,
visibleDate: localeAwareVisibleDate,
minDate: minDate ? dayjs(minDate).local().format() : undefined,
maxDate: maxDate ? dayjs(maxDate).local().format() : undefined,
dateProperties: dateProperties,
onPressMonth: onPressMonth
}));
};
export default BaseCalendar;
//# sourceMappingURL=BaseCalendar.js.map