puppy-lib-components
Version:
A modern TypeScript React component library with generic UI components and football pickem domain components
101 lines (100 loc) • 5.78 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Typography, IconButton } from '@mui/material';
import { ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon } from '@mui/icons-material';
import { MONTHS, WEEKDAYS, getDaysInMonth, getFirstDayOfMonth, isSameDay, isDateInRange, isDateDisabled, } from './utils';
export const Calendar = ({ date, onDateChange, selectedStart, selectedEnd, rangePosition, onRangePositionChange, minDate, maxDate, disableFuture, disablePast, shouldDisableDate, showDaysOutsideCurrentMonth = false, }) => {
const daysInMonth = getDaysInMonth(date);
const firstDay = getFirstDayOfMonth(date);
const today = new Date();
const handleDateClick = (day, isCurrentMonth = true) => {
if (!isCurrentMonth && !showDaysOutsideCurrentMonth)
return;
const clickedDate = new Date(date.getFullYear(), date.getMonth(), day);
if (isDateDisabled(clickedDate, minDate, maxDate, disableFuture, disablePast, shouldDisableDate, rangePosition)) {
return;
}
if (rangePosition === 'start') {
if (!selectedEnd || clickedDate <= selectedEnd) {
onDateChange(clickedDate);
onRangePositionChange('end');
}
else {
onDateChange(clickedDate);
onRangePositionChange('end');
}
}
else {
if (!selectedStart || clickedDate >= selectedStart) {
onDateChange(clickedDate);
onRangePositionChange('start');
}
else {
onDateChange(clickedDate);
onRangePositionChange('start');
}
}
};
const renderDay = (day, isCurrentMonth = true) => {
const dayDate = new Date(date.getFullYear(), date.getMonth(), day);
const isToday = isSameDay(dayDate, today);
const isSelectedStart = isSameDay(dayDate, selectedStart);
const isSelectedEnd = isSameDay(dayDate, selectedEnd);
const isInRange = isDateInRange(dayDate, selectedStart, selectedEnd);
const isDisabled = isDateDisabled(dayDate, minDate, maxDate, disableFuture, disablePast, shouldDisableDate, rangePosition);
return (_jsx(Box, { sx: {
width: 32,
height: 32,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: isDisabled ? 'not-allowed' : 'pointer',
borderRadius: '50%',
position: 'relative',
backgroundColor: isSelectedStart || isSelectedEnd ? 'primary.main' :
isInRange ? 'primary.light' : 'transparent',
color: isSelectedStart || isSelectedEnd ? 'primary.contrastText' :
isInRange ? 'primary.dark' :
isDisabled ? 'text.disabled' :
!isCurrentMonth ? 'text.disabled' : 'text.primary',
opacity: !isCurrentMonth && !showDaysOutsideCurrentMonth ? 0.3 : 1,
...(isDisabled ? {} : {
'&:hover': {
backgroundColor: isSelectedStart || isSelectedEnd ? 'primary.dark' : 'action.hover',
},
}),
...(isToday && {
border: '2px solid',
borderColor: 'primary.main',
}),
}, onClick: () => handleDateClick(day, isCurrentMonth), children: _jsx(Typography, { variant: "body2", sx: { fontSize: '0.875rem' }, children: day }) }, day));
};
const renderCalendarDays = () => {
const days = [];
// Previous month days
if (showDaysOutsideCurrentMonth) {
const prevMonth = new Date(date.getFullYear(), date.getMonth() - 1, 0);
const daysInPrevMonth = prevMonth.getDate();
for (let i = firstDay - 1; i >= 0; i--) {
days.push(renderDay(daysInPrevMonth - i, false));
}
}
else {
for (let i = 0; i < firstDay; i++) {
days.push(_jsx(Box, { sx: { width: 32, height: 32 } }, `empty-${i}`));
}
}
// Current month days
for (let day = 1; day <= daysInMonth; day++) {
days.push(renderDay(day, true));
}
// Next month days
if (showDaysOutsideCurrentMonth) {
const remainingDays = 42 - days.length; // 6 weeks * 7 days
for (let day = 1; day <= remainingDays; day++) {
days.push(renderDay(day, false));
}
}
return days;
};
return (_jsxs(Box, { sx: { minWidth: 280 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }, children: [_jsxs(Typography, { variant: "h6", children: [MONTHS[date.getMonth()], " ", date.getFullYear()] }), _jsxs(Box, { children: [_jsx(IconButton, { size: "small", onClick: () => onDateChange(new Date(date.getFullYear(), date.getMonth() - 1, 1)), children: _jsx(ChevronLeftIcon, {}) }), _jsx(IconButton, { size: "small", onClick: () => onDateChange(new Date(date.getFullYear(), date.getMonth() + 1, 1)), children: _jsx(ChevronRightIcon, {}) })] })] }), _jsx(Box, { sx: { display: 'flex', mb: 1 }, children: WEEKDAYS.map((day) => (_jsx(Box, { sx: { flex: 1, textAlign: 'center', py: 1 }, children: _jsx(Typography, { variant: "caption", color: "text.secondary", children: day }) }, day))) }), _jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap' }, children: renderCalendarDays().map((day, index) => (_jsx(Box, { sx: { width: '14.28%', display: 'flex', justifyContent: 'center' }, children: day }, index))) })] }));
};