UNPKG

@atlaskit/calendar

Version:

An interactive calendar for date selection experiences.

106 lines (104 loc) 3.72 kB
import { useMemo } from 'react'; import { parseISO } from 'date-fns'; import { daysPerWeek } from '../constants'; import dateToString from '../utils/date-to-string'; import getBaseCalendar from '../utils/get-base-calendar'; function useGetCalendarWithSixthWeek(calendar, { month, year, weekStartDay }) { const shouldDisplaySixthWeek = calendar.length % 6; const calendarLastValue = calendar[calendar.length - 1]; return useMemo(() => { // Some months jump between 5 and 6 weeks to display. In some cases 4 (Feb // with the 1st on a Monday etc). This ensures the UI doesn't jump around by // catering to always showing 6 weeks. if (shouldDisplaySixthWeek) { const lastDayIsSibling = calendarLastValue.siblingMonth; const sliceStart = lastDayIsSibling ? daysPerWeek : 0; return getBaseCalendar(year, month, { weekStartDay }).slice(sliceStart, sliceStart + daysPerWeek).map(date => ({ ...date, siblingMonth: true })); } }, [calendarLastValue, month, shouldDisplaySixthWeek, weekStartDay, year]); } // eslint-disable-next-line @repo/internal/react/require-jsdoc export default function useGetWeeks({ day, daysLong, month, year, today, disabled, disabledDateFilter, minDate: minDateString, maxDate: maxDateString, selected, previouslySelected, weekStartDay }) { const calendar = useMemo(() => getBaseCalendar(year, month - 1, { weekStartDay }), [month, weekStartDay, year]); const calendarWithSixthWeek = useGetCalendarWithSixthWeek(calendar, { month, year, weekStartDay }); if (calendarWithSixthWeek) { calendar.push(...calendarWithSixthWeek); } const minDate = minDateString ? parseISO(minDateString) : undefined; const maxDate = maxDateString ? parseISO(maxDateString) : undefined; const needJsDate = minDateString || maxDateString; return useMemo(() => { const weeks = []; calendar.forEach(date => { const dateAsString = dateToString(date, { fixMonth: true }); const JSDate = needJsDate ? parseISO(dateAsString) : undefined; let week; if (date.weekDay === weekStartDay) { week = { id: dateAsString, values: [] }; weeks.push(week); } else { week = weeks[weeks.length - 1]; } const weekDayOffset = (date.weekDay - weekStartDay) % 7; // Define a bunch of `const`s const weekDayName = daysLong[weekDayOffset]; const isDisabledByArray = disabled ? disabled.indexOf(dateAsString) > -1 : false; const isDisabledByFilter = disabledDateFilter ? disabledDateFilter(dateAsString) : false; const isDisabledByMin = minDate && JSDate ? JSDate < minDate : false; const isDisabledByMax = maxDate && JSDate ? JSDate > maxDate : false; const isDisabled = isDisabledByArray || isDisabledByFilter || isDisabledByMin || isDisabledByMax; const isFocused = day === date.day && !date.siblingMonth; const isPreviouslySelected = !isDisabled && previouslySelected.indexOf(dateAsString) > -1; const isSelected = !isDisabled && selected.indexOf(dateAsString) > -1; const isSiblingMonth = !!date.siblingMonth; const isToday = today === dateAsString; week.values.push({ id: dateAsString, isDisabled, isFocused, isToday, month: date.month + 1, isPreviouslySelected, isSelected, isSiblingMonth, year: date.year, day: date.day, weekDayName }); }); return weeks; }, [calendar, day, disabled, disabledDateFilter, minDate, maxDate, needJsDate, previouslySelected, selected, today, weekStartDay, daysLong]); }