import { useMemo, memo, useCallback } from 'react';
import { format } from '../../utils';
import {
getGridCount,
gridCounts,
startAtIndex,
beginOffset,
estimatedMonthHeight,
useRangeChecker,
generateCalendarGrid,
getRealIndex,
addMonths,
} from './dateUtils';
import { getCalendarHeaderHeight } from './DatePickerInlineHeader';
import type { MonthMultiProps, MonthRangeProps, MonthSingleProps } from './types';
import Week from './Week';
import { useDatePickerStoreValue } from './DatePickerContext';
import { View } from 'react-native';
import { Text } from '../Text';
import {
datePickerMonthStyles,
monthHeaderSingleMarginTop,
weekSize,
montHeaderHeight,
monthHeaderSingleMarginBottom,
monthHeaderSingleHeight,
dayNamesHeight,
} from './utils';
export type Props = MonthSingleProps | MonthRangeProps | MonthMultiProps;
function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
const {
index,
mode,
date,
dates,
startDate,
endDate,
onPressDate,
scrollMode,
disableWeekDays,
validRange,
// customMonthStyles,
} = props;
const { localDate } = useDatePickerStoreValue(state => ({ localDate: state.localDate }));
// const monthStyles = useComponentStyles('DatePicker_Month', customMonthStyles);
const isHorizontal = scrollMode === 'horizontal';
const { isDisabled, isWithinValidRange } = useRangeChecker(validRange);
const { monthName, month, year } = useMemo(() => {
const realIndex = getRealIndex(index);
const md = addMonths(new Date(), realIndex);
const y = mode === 'single' ? localDate.getFullYear() : md.getFullYear();
const m = mode === 'single' ? localDate.getMonth() : md.getMonth();
return { monthName: format(md, 'LLLL'), month: m, year: y };
}, [index, localDate, mode]);
const grid = useMemo(
() =>
generateCalendarGrid({
year,
month,
index,
isDisabled,
mode,
isWithinValidRange,
startDate,
endDate,
dates,
date,
monthGrid,
}),
[year, month, index, isDisabled, mode, isWithinValidRange, startDate, endDate, dates, date],
);
const { headerStyle, yearButtonStyle, yearInnerStyle, monthLabelStyle, weekContainerStyle } =
useMemo(() => {
// const {
// monthLabel: _monthLabel,
// yearButton,
// yearButtonInner,
// month: _monthStyle,
// monthHeader,
// dockedHeaderStyle,
// weekContainerStyle: weekContainer,
// } = monthStyles;
// const { typescale, ...monthLabel } = _monthLabel;
return {
headerStyle: [
datePickerMonthStyles.monthHeader,
isHorizontal
? [
datePickerMonthStyles.dockedHeaderStyle,
{
marginTop: monthHeaderSingleMarginTop,
marginBottom: monthHeaderSingleMarginBottom,
},
]
: null,
],
yearButtonStyle: datePickerMonthStyles.yearButton,
yearInnerStyle: datePickerMonthStyles.yearButtonInner,
monthLabelStyle: [datePickerMonthStyles.monthLabel],
weekContainerStyle: datePickerMonthStyles.weekContainerStyle,
};
}, [isHorizontal]);
const renderHeader = useCallback(() => {
if (!isHorizontal) {
return (
{monthName} {year}
);
}
return null;
}, [
headerStyle,
isHorizontal,
monthLabelStyle,
monthName,
year,
yearButtonStyle,
yearInnerStyle,
]);
return (
{renderHeader()}
{grid.map(({ weekIndex, generatedDays }) => (
))}
);
}
const monthGrid = (index: number) => {
return Array(getGridCount(index))
.fill(null)
.map((_, weekGrid) => {
const days = Array(7).fill(null);
return { weekGrid, days };
});
};
function getIndexCount(index: number): number {
if (index > startAtIndex) {
return index - startAtIndex;
}
return -(startAtIndex - index);
}
function weeksOffset(index: number): number {
if (index === startAtIndex) {
return 0;
}
let off = 0;
if (index > startAtIndex) {
for (let i = 0; i < index - startAtIndex; i++) {
const cIndex = startAtIndex + i;
off += gridCounts[cIndex] || getGridCount(cIndex);
}
} else {
for (let i = 0; i < startAtIndex - index; i++) {
const cIndex = startAtIndex - i - 1;
off -= gridCounts[cIndex] || getGridCount(cIndex);
}
}
return off;
}
export function getIndexFromHorizontalOffset(offset: number, width: number): number {
return startAtIndex + Math.floor(offset / width);
}
export function getIndexFromVerticalOffset(offset: number): number {
let estimatedIndex = startAtIndex + Math.ceil(offset / estimatedMonthHeight);
const realOffset = getVerticalMonthsOffset(estimatedIndex);
const difference = (realOffset - beginOffset - offset) / estimatedMonthHeight;
if (difference >= 1 || difference <= -1) {
estimatedIndex -= Math.floor(difference);
}
return estimatedIndex;
}
export function getHorizontalMonthOffset(index: number, width: number) {
if (index < 0) {
return 0;
}
return width * index;
}
export function getVerticalMonthsOffset(index: number) {
const count = getIndexCount(index);
const ob = weeksOffset(index);
const monthsHeight = weekSize * ob;
const c = monthsHeight + count * (dayNamesHeight + montHeaderHeight);
return (c || 0) + beginOffset;
}
export function getMonthHeight(scrollMode: 'horizontal' | 'vertical', index: number): number {
const calendarHeight = getCalendarHeaderHeight(scrollMode);
const gc = getGridCount(index);
const currentMonthHeight = weekSize * gc;
const extraHeight = scrollMode === 'horizontal' ? monthHeaderSingleHeight : montHeaderHeight;
const c = calendarHeight + currentMonthHeight + extraHeight;
return c || 0;
}
export default memo(Month);