import { memo } from "react"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { DEFAULT_CELL_SIZE, SMALL_CELL_SIZE } from "./constants"; import type { CalendarDayCell, CalendarSize } from "./types"; import { getCalendarCellStateClass, getCellIntensityClass } from "./utils"; export interface CalendarCellProps { day: CalendarDayCell; maxCount: number; tooltipText: string; onClick?: (date: string) => void; size?: CalendarSize; disableTooltip?: boolean; } export const CalendarCell = memo((props: CalendarCellProps) => { const { day, maxCount, tooltipText, onClick, size = "default", disableTooltip = false } = props; const handleClick = () => { if (onClick) { onClick(day.date); } }; const sizeConfig = size === "small" ? SMALL_CELL_SIZE : DEFAULT_CELL_SIZE; const smallExtraClasses = size === "small" ? `${SMALL_CELL_SIZE.dimensions} min-h-0` : ""; const baseClasses = cn( "aspect-square w-full flex items-center justify-center text-center transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 select-none border border-border/10 bg-muted/20", sizeConfig.font, sizeConfig.borderRadius, smallExtraClasses, ); const isInteractive = Boolean(onClick); const ariaLabel = day.isSelected ? `${tooltipText} (selected)` : tooltipText; if (!day.isCurrentMonth) { return
{day.label}
; } const intensityClass = getCellIntensityClass(day, maxCount); const buttonClasses = cn( baseClasses, intensityClass, getCalendarCellStateClass(day), day.isToday && "underline decoration-1 underline-offset-4", isInteractive ? "cursor-pointer hover:bg-muted/40 hover:border-border/30 hover:text-foreground" : "cursor-default", ); const button = ( ); const shouldShowTooltip = tooltipText && !disableTooltip; if (!shouldShowTooltip) { return button; } return ( {button}

{tooltipText}

); }); CalendarCell.displayName = "CalendarCell";