import React, { useMemo, useState, useEffect } from 'react'; import { classNames } from '../../utils'; import { useLocale } from '../GrapesProvider'; import { IconButton } from '../IconButton'; import { isSameDay, isDayBefore, isDayAfter, getDateInRange, } from '../DatePicker/utils/'; import { useTranslate } from '../../hooks/useTranslate'; import styles from './Calendar.module.css'; import { colors } from '../../colors'; export type CalendarProps = { /** * The current date. */ value: Date | undefined; /** * The earliest date allowed by the Calendar */ minDate?: Date; /** * The oldest date allowed by the Calendar */ maxDate?: Date; /** * Handler that is called when a date is clicked. */ onClick: (date: Date) => void; /** * className for the element */ className?: string; }; export const Calendar = ({ value, onClick, maxDate, minDate, className, }: CalendarProps) => { const locale = useLocale(); const [date, setDate] = useState(new Date()); const t = useTranslate(); useEffect(() => { setDate(getDateInRange(value ?? new Date(), minDate, maxDate)); }, [value, minDate, maxDate]); const month = date.getMonth(); const year = date.getFullYear(); const IntlLocale = new Intl.Locale(locale); // Used to display either Monday or Sunday as first day of the week let weekOffset = /us/gi.test(locale) ? 7 : 1; // @ts-expect-error getWeekInfo exist on Locale if (IntlLocale.getWeekInfo !== undefined) { // @ts-expect-error getWeekInfo exist on Locale const { firstDay } = IntlLocale.getWeekInfo(); weekOffset = firstDay; } const firstDate = new Date(year, month, 1); const firstWeekday = firstDate.getDay(); const lastDate = new Date(year, month + 1, 0); const daysInMonth = lastDate.getDate(); const calendar = Array.from( { length: daysInMonth }, (_, i) => new Date(year, month, i + 1), ); const weekdays = useMemo(() => { const dayDtf = new Intl.DateTimeFormat(locale, { weekday: 'short', }); return Array.from( { length: 7 }, (_, i) => dayDtf.format(new Date(2024, 6, i + weekOffset)), // target july 2024 because first day was monday ); }, [weekOffset, locale]); const monthTimeFormat = useMemo( () => new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric', }), [locale], ); const accessiblityTimeFormat = useMemo( () => new Intl.DateTimeFormat(locale, { dateStyle: 'full', }), [locale], ); return (
setDate(new Date(year, month - 1, 1))} aria-label={t('previousMonth')} />

{monthTimeFormat.format(date)}

setDate(new Date(year, month + 1, 1))} aria-label={t('nextMonth')} />
{weekdays.map((weekday) => ( ))} {calendar.map((date, i) => { const isSelectedDate = isSameDay(date, value); const isDateAfter = isDayAfter(maxDate, date); const isDateBefore = isDayBefore(minDate, date); return ( ); })}
); };