import {
DAYS_PER_WEEK,
calculateCalendarDimensions,
getCellType,
getDayNumber,
} from 'shared-utils/calendar/calendar-grid'
import {
getDayViewData,
getDayCellClasses,
getDayButtonClasses,
type IDayViewContext,
type IDayCellClassContext,
} from './calendar-utils'
import type { ICalendarState } from './types'
export const CalendarGrid = ({ state }: { state: ICalendarState }) => {
const {
strings,
year,
month,
activeSelected,
focusedDate,
inRange,
rangeHovered,
range,
multiple,
weeknumbers,
selectableDatesRef,
tabIndexSetRef,
handleDateSelect,
handleRangeHover,
isExcluded,
isDayDisabled,
setFocusedDate,
todayDate,
} = state
const dayViewCtx: IDayViewContext = {
year,
month,
activeSelected,
focusedDate,
tabIndexSetRef,
isDayDisabled,
}
const cellClassCtx: IDayCellClassContext = {
range,
activeSelected,
rangeHovered,
inRange,
isExcluded,
}
const renderDayNames = () => {
const headers: React.ReactNode[] = []
if (weeknumbers) {
headers.push(
{strings.week}
| ,
)
}
for (let i = 0; i < strings.daysShort.length; i++) {
headers.push(
{strings.daysShort[i]}
| ,
)
}
return {headers}
}
const renderDayView = (dayCounter: number, today: Date) => {
const data = getDayViewData(dayCounter, today, dayViewCtx)
const { currentDate, currentDateISO, isSelected, isDisabled: isDisabledVal, ariaLabel, tabindex } = data
selectableDatesRef.current.push({ currentDateISO, isDisabled: isDisabledVal, tabindex })
const cellClasses = getDayCellClasses(data, cellClassCtx)
const buttonClasses = getDayButtonClasses(data, cellClassCtx)
return (
|
)
}
const renderEmptyDayCell = (day: number, key: string) => (
{day}
|
)
const renderCalendarBody = () => {
const today = todayDate
const dimensions = calculateCalendarDimensions(year, month)
selectableDatesRef.current = []
tabIndexSetRef.current = 0
let dayCounter = 1
let currentWeek = dimensions.initialWeek
const rows: React.ReactNode[] = []
for (let i = 0; i < dimensions.numRows; i++) {
const cells: React.ReactNode[] = []
if (weeknumbers) {
cells.push(
{currentWeek}
| ,
)
}
currentWeek++
for (let j = 0; j < DAYS_PER_WEEK; j++) {
const cellType = getCellType(i, j, dayCounter, dimensions)
if (cellType === 'current-month') {
cells.push(renderDayView(dayCounter, today))
dayCounter++
} else {
const dayNumber = getDayNumber(cellType, j, dayCounter, dimensions)
cells.push(renderEmptyDayCell(dayNumber, `${cellType}-${i}-${j}`))
if (cellType === 'next-month') {
dayCounter++
}
}
}
rows.push(
{cells}
,
)
}
return rows
}
return (
{renderDayNames()}
{renderCalendarBody()}
)
}