import React, { useCallback, useMemo, useRef } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import { addDays, format, isSameDay } from "date-fns";
import { DayProps, DayWrapperProps, OnDateSelect } from "./types";
import { useCalendarContext } from "./context";
import { DayLabel } from "./DayLabels";
// The calendar renders a lot of Days, so we wrap them in order to
// prevent context updates from re-rendering everything
export const DayWrapper = React.memo(
({ date, isInDisplayedMonth, dateFormatted }: DayWrapperProps) => {
const dateRef = useRef(date);
const memoDate = useMemo(() => {
if (isSameDay(dateRef.current, date)) {
return dateRef.current;
} else {
dateRef.current = date;
return date;
}
}, [date]);
const { selectedDate, onDateSelect, DayComponent, theme } =
useCalendarContext();
const isSelected = useMemo(() => {
return !!selectedDate && isSameDay(memoDate, selectedDate);
}, [memoDate, selectedDate]);
const isToday = useMemo(() => isSameDay(memoDate, new Date()), [memoDate]);
const onDateSelectRef = useRef(onDateSelect);
onDateSelectRef.current = onDateSelect;
const onDateSelectCb: OnDateSelect = useCallback((date, options) => {
return onDateSelectRef.current?.(date, options);
}, []);
return (
);
}
);
export const DayItem = React.memo(
({
date,
isInDisplayedMonth,
isSelected,
DayComponent,
isToday,
onDateSelect,
theme,
dateFormatted,
}: DayProps) => {
const dayText = format(date, "d");
const deselectedColor = isInDisplayedMonth
? theme.dayFontColor
: theme.dayInactiveFontColor;
const color = isSelected ? theme.daySelectedFontColor : deselectedColor;
if (DayComponent) {
return (
);
}
const padding = 10;
return (
onDateSelect?.(date, { isSelected })}
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
flexDirection: "row",
padding,
}}
>
{dayText}
);
}
);
export const DayPage = React.memo(({ index }: { index: number }) => {
const { referenceDate, HeaderComponent, theme } = useCalendarContext();
const dayOffset = useMemo(
() => addDays(referenceDate, index),
[referenceDate, index]
);
const firstDayOfMonth = useMemo(() => new Date(dayOffset), [dayOffset]);
firstDayOfMonth.setDate(1);
const dayDateFormatted = format(dayOffset, "yyyy-MM-dd");
const headerText = format(dayOffset, theme.headerDateFormat);
return (
<>
{HeaderComponent ? (
) : (
{headerText}
)}
>
);
});
const styles = StyleSheet.create({
row: {
flexDirection: "row",
},
});