UNPKG

mobile-react-infinite-calendar

Version:

A mobile-optimized infinite scroll calendar component for React

87 lines (86 loc) 5.1 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { memo, useMemo, useCallback } from 'react'; import { format, isSameMonth, isToday, getDay, isBefore, startOfDay } from 'date-fns'; import { cn } from '../utils/cn'; import { COLOR_CONSTANTS, UI_CONSTANTS } from '../constants/calendar'; const DayCell = memo(function DayCell({ day, activeMonth, dayEvents, dayHolidays, classNames, onDayClick }) { if (!day) { return (_jsx("div", { className: "relative p-2", style: { minHeight: `${UI_CONSTANTS.DAY_CELL_HEIGHT}px` } })); } // 날짜 상태 계산 (메모이제이션) const dayState = useMemo(() => { const isCurrentMonth = isSameMonth(day, activeMonth); // 과거 날짜이면서 이벤트가 없는 경우만 비활성화 const isPastDate = isBefore(day, startOfDay(new Date())); const hasEvents = dayEvents.length > 0; const isDisabled = isPastDate && !hasEvents; const dayOfWeek = getDay(day); const isHoliday = dayHolidays.length > 0; const holidayColor = dayHolidays.length > 0 ? (dayHolidays[0].color || COLOR_CONSTANTS.DEFAULT_HOLIDAY_COLOR) : null; return { isCurrentMonth, isDisabled, dayOfWeek, isHoliday, holidayColor }; }, [day, activeMonth, dayHolidays, dayEvents]); // 색상 클래스 계산 (메모이제이션) const textColorData = useMemo(() => { const { isHoliday, holidayColor, dayOfWeek } = dayState; let textColorClass = null; if (isHoliday && holidayColor) { switch (holidayColor) { case COLOR_CONSTANTS.HOLIDAY_COLORS.RED: textColorClass = "text-red-500"; break; case COLOR_CONSTANTS.HOLIDAY_COLORS.GREEN: textColorClass = "text-green-500"; break; case COLOR_CONSTANTS.HOLIDAY_COLORS.PURPLE: textColorClass = "text-purple-500"; break; case COLOR_CONSTANTS.HOLIDAY_COLORS.ORANGE: textColorClass = "text-orange-500"; break; case COLOR_CONSTANTS.HOLIDAY_COLORS.PINK: textColorClass = "text-pink-500"; break; case COLOR_CONSTANTS.HOLIDAY_COLORS.YELLOW: textColorClass = "text-yellow-500"; break; default: textColorClass = null; // hex 색상은 스타일로 처리 } } else { // 공휴일이 아닌 경우 요일별 색상 if (dayOfWeek === 0) textColorClass = "text-red-500"; // 일요일 else if (dayOfWeek === 6) textColorClass = "text-blue-500"; // 토요일 } const isCustomHexColor = isHoliday && (holidayColor === null || holidayColor === void 0 ? void 0 : holidayColor.startsWith('#')); return { textColorClass, isCustomHexColor }; }, [dayState]); // 셀 클래스명 계산 (메모이제이션) const cellClassName = useMemo(() => cn("relative p-2 cursor-pointer", "transition-colors", "flex flex-col items-center justify-between", !dayState.isCurrentMonth && "opacity-40 cursor-not-allowed", dayState.isDisabled && "cursor-not-allowed", classNames === null || classNames === void 0 ? void 0 : classNames.dayCell), [dayState.isCurrentMonth, dayState.isDisabled, classNames === null || classNames === void 0 ? void 0 : classNames.dayCell]); // 날짜 텍스트 클래스명 계산 (메모이제이션) const dateTextClassName = useMemo(() => cn("inline-block", dayEvents.length > 0 ? "text-base font-bold" : "text-sm font-medium", isToday(day) && "animate-bounce", textColorData.textColorClass), [dayEvents.length, day, textColorData.textColorClass]); // 클릭 핸들러 (메모이제이션) const handleClick = useCallback(() => { if (!dayState.isDisabled && dayState.isCurrentMonth && onDayClick) { onDayClick(day, { events: dayEvents, holidays: dayHolidays }); } }, [dayState.isDisabled, dayState.isCurrentMonth, onDayClick, day, dayEvents, dayHolidays]); return (_jsxs("div", { onClick: handleClick, className: cellClassName, style: { minHeight: `${UI_CONSTANTS.DAY_CELL_HEIGHT}px`, }, children: [_jsx("div", { className: "flex-1 flex flex-col items-center justify-start pt-2", children: _jsx("div", { className: "text-center min-h-[20px]", children: _jsx("span", { className: dateTextClassName, ...(textColorData.isCustomHexColor && dayState.holidayColor && { style: { color: dayState.holidayColor } }), children: format(day, 'd') }) }) }), _jsx("div", { className: "h-2 flex items-center justify-center", children: dayEvents.length > 0 && (_jsx("span", { className: "text-[4px]", children: "\uD83D\uDD34" })) })] })); }); DayCell.displayName = 'DayCell'; export { DayCell };