{
  "name": "calender",
  "dependencies": [
    "lucide-react",
    "motion",
    "date-fns"
  ],
  "files": [
    {
      "path": "ui/calender.tsx",
      "content": "import {\n  addDays,\n  addMonths,\n  addYears,\n  eachDayOfInterval,\n  endOfMonth,\n  endOfWeek,\n  endOfYear,\n  format,\n  getDay,\n  getHours,\n  getMinutes,\n  getMonth,\n  getYear,\n  isAfter,\n  isBefore,\n  isSameDay,\n  isSameMonth,\n  isToday,\n  isWeekend,\n  isWithinInterval,\n  type Locale,\n  setHours,\n  setMinutes,\n  setMonth,\n  setYear,\n  startOfDay,\n  startOfMonth,\n  startOfWeek,\n  startOfYear,\n  subDays,\n  subMonths,\n  subYears,\n} from \"date-fns\";\nimport { enUS } from \"date-fns/locale\";\nimport {\n  AlertCircle,\n  Calendar as CalendarIcon,\n  Check,\n  ChevronLeft,\n  ChevronRight,\n  ChevronsLeft,\n  ChevronsRight,\n  Clock,\n  X,\n} from \"lucide-react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport * as React from \"react\";\nimport {\n  useCallback,\n  useEffect,\n  useId,\n  useMemo,\n  useRef,\n  useState,\n} from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport type CalendarMode = \"single\" | \"range\" | \"multiple\";\nexport type CalendarView = \"days\" | \"months\" | \"years\" | \"time\";\nexport type CalendarSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface DateRange {\n  from: Date | undefined;\n  to: Date | undefined;\n}\n\nexport interface PresetRange {\n  label: string;\n  getValue: () => DateRange;\n}\n\nexport interface CalendarLocale {\n  weekdays: string[];\n  weekdaysShort: string[];\n  months: string[];\n  monthsShort: string[];\n  today: string;\n  clear: string;\n  close: string;\n  selectTime: string;\n  backToCalendar: string;\n  selected: string;\n  weekNumber: string;\n}\n\n// Base props shared by all modes\ninterface BaseCalendarProps {\n  // Display\n  placeholder?: string;\n  disabled?: boolean;\n  readOnly?: boolean;\n  required?: boolean;\n  className?: string;\n  size?: CalendarSize;\n\n  // Constraints\n  minDate?: Date;\n  maxDate?: Date;\n  disabledDates?: Date[];\n  disabledDaysOfWeek?: number[];\n  disableWeekends?: boolean;\n  disablePastDates?: boolean;\n  disableFutureDates?: boolean;\n\n  // Validation\n  error?: boolean;\n  errorMessage?: string;\n\n  // Features\n  showTime?: boolean;\n  use24Hour?: boolean;\n  minuteStep?: number;\n  showWeekNumbers?: boolean;\n  showTodayButton?: boolean;\n  showClearButton?: boolean;\n  weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n  monthsToShow?: 1 | 2 | 3;\n\n  // Range presets\n  showPresets?: boolean;\n  presets?: PresetRange[];\n\n  // Events\n  highlightedDates?: { date: Date; color?: string; label?: string }[];\n\n  // Customization\n  formatStr?: string;\n  closeOnSelect?: boolean;\n  locale?: Locale;\n  localeStrings?: Partial<CalendarLocale>;\n\n  // Callbacks\n  onMonthChange?: (date: Date) => void;\n  onYearChange?: (date: Date) => void;\n  onViewChange?: (view: CalendarView) => void;\n  onOpen?: () => void;\n  onClose?: () => void;\n\n  // Accessibility\n  id?: string;\n  name?: string;\n  \"aria-label\"?: string;\n  \"aria-describedby\"?: string;\n\n  // Custom renderers\n  renderDay?: (date: Date, defaultRender: React.ReactNode) => React.ReactNode;\n  renderHeader?: (\n    date: Date,\n    defaultRender: React.ReactNode,\n  ) => React.ReactNode;\n\n  // Form integration\n  onBlur?: () => void;\n  onFocus?: () => void;\n}\n\n// Single date selection mode\ninterface SingleModeProps extends BaseCalendarProps {\n  mode?: \"single\";\n  value?: Date;\n  defaultValue?: Date;\n  onChange?: (value: Date | undefined) => void;\n}\n\n// Range selection mode\ninterface RangeModeProps extends BaseCalendarProps {\n  mode: \"range\";\n  value?: DateRange;\n  defaultValue?: DateRange;\n  onChange?: (value: DateRange | undefined) => void;\n}\n\n// Multiple dates selection mode\ninterface MultipleModeProps extends BaseCalendarProps {\n  mode: \"multiple\";\n  value?: Date[];\n  defaultValue?: Date[];\n  onChange?: (value: Date[]) => void;\n}\n\n// Union type for all calendar props (external API)\nexport type AnimatedCalendarProps =\n  | SingleModeProps\n  | RangeModeProps\n  | MultipleModeProps;\n\n// Internal unified type for component implementation\ninterface InternalCalendarProps extends BaseCalendarProps {\n  mode?: CalendarMode;\n  value?: Date | DateRange | Date[];\n  defaultValue?: Date | DateRange | Date[];\n  onChange?: (value: Date | DateRange | Date[] | undefined) => void;\n}\n\n// ============================================================================\n// CONSTANTS & DEFAULTS\n// ============================================================================\n\nconst defaultLocaleStrings: CalendarLocale = {\n  weekdays: [\n    \"Sunday\",\n    \"Monday\",\n    \"Tuesday\",\n    \"Wednesday\",\n    \"Thursday\",\n    \"Friday\",\n    \"Saturday\",\n  ],\n  weekdaysShort: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"],\n  months: [\n    \"January\",\n    \"February\",\n    \"March\",\n    \"April\",\n    \"May\",\n    \"June\",\n    \"July\",\n    \"August\",\n    \"September\",\n    \"October\",\n    \"November\",\n    \"December\",\n  ],\n  monthsShort: [\n    \"Jan\",\n    \"Feb\",\n    \"Mar\",\n    \"Apr\",\n    \"May\",\n    \"Jun\",\n    \"Jul\",\n    \"Aug\",\n    \"Sep\",\n    \"Oct\",\n    \"Nov\",\n    \"Dec\",\n  ],\n  today: \"Today\",\n  clear: \"Clear\",\n  close: \"Close\",\n  selectTime: \"Select time\",\n  backToCalendar: \"Back to calendar\",\n  selected: \"selected\",\n  weekNumber: \"Week\",\n};\n\nconst defaultPresets: PresetRange[] = [\n  {\n    label: \"Today\",\n    getValue: () => ({\n      from: startOfDay(new Date()),\n      to: startOfDay(new Date()),\n    }),\n  },\n  {\n    label: \"Yesterday\",\n    getValue: () => ({\n      from: startOfDay(subDays(new Date(), 1)),\n      to: startOfDay(subDays(new Date(), 1)),\n    }),\n  },\n  {\n    label: \"Last 7 days\",\n    getValue: () => ({\n      from: startOfDay(subDays(new Date(), 6)),\n      to: startOfDay(new Date()),\n    }),\n  },\n  {\n    label: \"Last 30 days\",\n    getValue: () => ({\n      from: startOfDay(subDays(new Date(), 29)),\n      to: startOfDay(new Date()),\n    }),\n  },\n  {\n    label: \"This month\",\n    getValue: () => ({\n      from: startOfMonth(new Date()),\n      to: endOfMonth(new Date()),\n    }),\n  },\n  {\n    label: \"Last month\",\n    getValue: () => ({\n      from: startOfMonth(subMonths(new Date(), 1)),\n      to: endOfMonth(subMonths(new Date(), 1)),\n    }),\n  },\n  {\n    label: \"This year\",\n    getValue: () => ({\n      from: startOfYear(new Date()),\n      to: endOfYear(new Date()),\n    }),\n  },\n];\n\nconst sizeClasses = {\n  sm: { cell: \"h-7 w-7 text-xs\", header: \"text-sm\", container: \"p-2\" },\n  md: { cell: \"h-9 w-9 text-sm\", header: \"text-base\", container: \"p-4\" },\n  lg: { cell: \"h-11 w-11 text-base\", header: \"text-lg\", container: \"p-5\" },\n};\n\n// ============================================================================\n// ANIMATION VARIANTS\n// ============================================================================\n\nconst slideVariants = {\n  enter: (direction: number) => ({ x: direction > 0 ? 280 : -280, opacity: 0 }),\n  center: { x: 0, opacity: 1 },\n  exit: (direction: number) => ({ x: direction < 0 ? 280 : -280, opacity: 0 }),\n};\n\nconst fadeScale = {\n  initial: { opacity: 0, scale: 0.95 },\n  animate: { opacity: 1, scale: 1 },\n  exit: { opacity: 0, scale: 0.95 },\n};\n\n// ============================================================================\n// UTILITY HOOKS\n// ============================================================================\n\nfunction useControllableState<T>(\n  controlledValue: T | undefined,\n  defaultValue: T,\n  onChange?: (value: T) => void,\n): [T, (value: T) => void] {\n  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n  const isControlled = controlledValue !== undefined;\n  const value = isControlled ? controlledValue : uncontrolledValue;\n\n  const setValue = useCallback(\n    (newValue: T) => {\n      if (!isControlled) {\n        setUncontrolledValue(newValue);\n      }\n      onChange?.(newValue);\n    },\n    [isControlled, onChange],\n  );\n\n  return [value, setValue];\n}\n\n// ============================================================================\n// SUB-COMPONENTS\n// ============================================================================\n\n// Time Picker\nconst TimePicker = React.memo(\n  ({\n    value,\n    onChange,\n    use24Hour = true,\n    minuteStep = 5,\n    size = \"md\",\n    localeStrings,\n    disabled,\n  }: {\n    value: Date;\n    onChange: (date: Date) => void;\n    use24Hour?: boolean;\n    minuteStep?: number;\n    size?: CalendarSize;\n    localeStrings: CalendarLocale;\n    disabled?: boolean;\n  }) => {\n    const hours = getHours(value);\n    const minutes = getMinutes(value);\n    const isPM = hours >= 12;\n    const displayHours = use24Hour ? hours : hours % 12 || 12;\n    const sizes = sizeClasses[size];\n\n    const updateTime = useCallback(\n      (newHours: number, newMinutes: number) => {\n        let updated = setHours(value, Math.max(0, Math.min(23, newHours)));\n        updated = setMinutes(updated, Math.max(0, Math.min(59, newMinutes)));\n        onChange(updated);\n      },\n      [value, onChange],\n    );\n\n    const incrementHour = () => updateTime((hours + 1) % 24, minutes);\n    const decrementHour = () => updateTime((hours - 1 + 24) % 24, minutes);\n    const incrementMinute = () =>\n      updateTime(hours, (minutes + minuteStep) % 60);\n    const decrementMinute = () =>\n      updateTime(hours, (minutes - minuteStep + 60) % 60);\n    const toggleAMPM = () =>\n      updateTime(isPM ? hours - 12 : hours + 12, minutes);\n\n    return (\n      <div\n        className=\"pointer-events-auto flex items-center justify-center gap-3 px-2 py-4\"\n        role=\"group\"\n        aria-label={localeStrings.selectTime}\n        onClick={(e) => e.stopPropagation()}\n      >\n        {/* Hours */}\n        <div className=\"flex flex-col items-center gap-1\">\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.preventDefault();\n              e.stopPropagation();\n              incrementHour();\n            }}\n            disabled={disabled}\n            className=\"pointer-events-auto rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n            aria-label=\"Increase hours\"\n          >\n            <ChevronLeft className=\"h-4 w-4 rotate-90\" />\n          </button>\n          <input\n            type=\"text\"\n            inputMode=\"numeric\"\n            value={displayHours.toString().padStart(2, \"0\")}\n            onClick={(e) => e.stopPropagation()}\n            onChange={(e) => {\n              const val = parseInt(e.target.value, 10) || 0;\n              if (use24Hour) {\n                updateTime(Math.min(23, Math.max(0, val)), minutes);\n              } else {\n                const newHours = Math.min(12, Math.max(1, val));\n                updateTime(\n                  isPM\n                    ? newHours === 12\n                      ? 12\n                      : newHours + 12\n                    : newHours === 12\n                      ? 0\n                      : newHours,\n                  minutes,\n                );\n              }\n            }}\n            disabled={disabled}\n            className={cn(\n              \"pointer-events-auto w-12 rounded border-none bg-transparent text-center font-bold font-mono focus:outline-none focus:ring-2 focus:ring-primary\",\n              sizes.header,\n            )}\n            aria-label=\"Hours\"\n            maxLength={2}\n          />\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.preventDefault();\n              e.stopPropagation();\n              decrementHour();\n            }}\n            disabled={disabled}\n            className=\"pointer-events-auto rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n            aria-label=\"Decrease hours\"\n          >\n            <ChevronRight className=\"h-4 w-4 rotate-90\" />\n          </button>\n        </div>\n\n        <span className={cn(\"font-bold text-muted-foreground\", sizes.header)}>\n          :\n        </span>\n\n        {/* Minutes */}\n        <div className=\"flex flex-col items-center gap-1\">\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.preventDefault();\n              e.stopPropagation();\n              incrementMinute();\n            }}\n            disabled={disabled}\n            className=\"pointer-events-auto rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n            aria-label=\"Increase minutes\"\n          >\n            <ChevronLeft className=\"h-4 w-4 rotate-90\" />\n          </button>\n          <input\n            type=\"text\"\n            inputMode=\"numeric\"\n            value={minutes.toString().padStart(2, \"0\")}\n            onClick={(e) => e.stopPropagation()}\n            onChange={(e) => {\n              const val = parseInt(e.target.value, 10) || 0;\n              updateTime(hours, Math.min(59, Math.max(0, val)));\n            }}\n            disabled={disabled}\n            className={cn(\n              \"pointer-events-auto w-12 rounded border-none bg-transparent text-center font-bold font-mono focus:outline-none focus:ring-2 focus:ring-primary\",\n              sizes.header,\n            )}\n            aria-label=\"Minutes\"\n            maxLength={2}\n          />\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.preventDefault();\n              e.stopPropagation();\n              decrementMinute();\n            }}\n            disabled={disabled}\n            className=\"pointer-events-auto rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n            aria-label=\"Decrease minutes\"\n          >\n            <ChevronRight className=\"h-4 w-4 rotate-90\" />\n          </button>\n        </div>\n\n        {/* AM/PM */}\n        {!use24Hour && (\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.preventDefault();\n              e.stopPropagation();\n              toggleAMPM();\n            }}\n            disabled={disabled}\n            className=\"pointer-events-auto ml-2 rounded-lg bg-accent px-3 py-2 font-semibold text-sm transition-colors hover:bg-accent/80 disabled:opacity-50\"\n            aria-label={`Switch to ${isPM ? \"AM\" : \"PM\"}`}\n          >\n            {isPM ? \"PM\" : \"AM\"}\n          </button>\n        )}\n      </div>\n    );\n  },\n);\nTimePicker.displayName = \"TimePicker\";\n\n// Month Picker\nconst MonthPicker = React.memo(\n  ({\n    currentMonth,\n    onSelect,\n    minDate,\n    maxDate,\n    size = \"md\",\n    localeStrings,\n    disabled,\n    prefersReducedMotion,\n  }: {\n    currentMonth: Date;\n    onSelect: (month: number) => void;\n    minDate?: Date;\n    maxDate?: Date;\n    size?: CalendarSize;\n    localeStrings: CalendarLocale;\n    disabled?: boolean;\n    prefersReducedMotion: boolean;\n  }) => {\n    const currentYear = getYear(currentMonth);\n    const currentMonthIndex = getMonth(currentMonth);\n    const _sizes = sizeClasses[size];\n\n    const isMonthDisabled = useCallback(\n      (month: number) => {\n        if (disabled) return true;\n        const date = new Date(currentYear, month, 1);\n        if (minDate && isBefore(endOfMonth(date), startOfDay(minDate)))\n          return true;\n        if (maxDate && isAfter(startOfMonth(date), startOfDay(maxDate)))\n          return true;\n        return false;\n      },\n      [currentYear, minDate, maxDate, disabled],\n    );\n\n    return (\n      <div\n        className=\"grid grid-cols-3 gap-2 p-2\"\n        role=\"listbox\"\n        aria-label=\"Select month\"\n      >\n        {localeStrings.monthsShort.map((month, index) => {\n          const isDisabled = isMonthDisabled(index);\n          const isSelected = index === currentMonthIndex;\n          return (\n            <motion.button\n              key={month}\n              type=\"button\"\n              role=\"option\"\n              aria-selected={isSelected}\n              aria-disabled={isDisabled}\n              initial={\n                prefersReducedMotion ? false : { opacity: 0, scale: 0.8 }\n              }\n              animate={{ opacity: 1, scale: 1 }}\n              transition={{ delay: prefersReducedMotion ? 0 : index * 0.02 }}\n              whileHover={\n                !isDisabled && !prefersReducedMotion\n                  ? { scale: 1.05 }\n                  : undefined\n              }\n              whileTap={\n                !isDisabled && !prefersReducedMotion\n                  ? { scale: 0.95 }\n                  : undefined\n              }\n              onClick={() => !isDisabled && onSelect(index)}\n              disabled={isDisabled}\n              className={cn(\n                \"rounded-lg px-2 py-3 font-medium text-sm transition-all focus:outline-none focus:ring-2 focus:ring-primary\",\n                isSelected\n                  ? \"bg-primary text-primary-foreground shadow-md\"\n                  : \"text-foreground hover:bg-accent\",\n                isDisabled && \"cursor-not-allowed opacity-30\",\n              )}\n            >\n              {month}\n            </motion.button>\n          );\n        })}\n      </div>\n    );\n  },\n);\nMonthPicker.displayName = \"MonthPicker\";\n\n// Year Picker\nconst YearPicker = React.memo(\n  ({\n    currentYear,\n    onSelect,\n    minDate,\n    maxDate,\n    size: _size = \"md\",\n    disabled,\n    prefersReducedMotion,\n  }: {\n    currentYear: number;\n    onSelect: (year: number) => void;\n    minDate?: Date;\n    maxDate?: Date;\n    size?: CalendarSize;\n    disabled?: boolean;\n    prefersReducedMotion: boolean;\n  }) => {\n    const [startYear, setStartYear] = useState(currentYear - 6);\n    const years = useMemo(\n      () => Array.from({ length: 12 }, (_, i) => startYear + i),\n      [startYear],\n    );\n\n    const isYearDisabled = useCallback(\n      (year: number) => {\n        if (disabled) return true;\n        if (minDate && year < getYear(minDate)) return true;\n        if (maxDate && year > getYear(maxDate)) return true;\n        return false;\n      },\n      [minDate, maxDate, disabled],\n    );\n\n    return (\n      <div className=\"space-y-2 p-2\" role=\"listbox\" aria-label=\"Select year\">\n        <div className=\"mb-2 flex items-center justify-between\">\n          <button\n            type=\"button\"\n            onClick={() => setStartYear((s) => s - 12)}\n            className=\"rounded-lg p-1.5 transition-colors hover:bg-accent\"\n            aria-label=\"Previous 12 years\"\n          >\n            <ChevronsLeft className=\"h-4 w-4\" />\n          </button>\n          <span className=\"font-medium text-muted-foreground text-sm\">\n            {years[0]} – {years[years.length - 1]}\n          </span>\n          <button\n            type=\"button\"\n            onClick={() => setStartYear((s) => s + 12)}\n            className=\"rounded-lg p-1.5 transition-colors hover:bg-accent\"\n            aria-label=\"Next 12 years\"\n          >\n            <ChevronsRight className=\"h-4 w-4\" />\n          </button>\n        </div>\n        <div className=\"grid grid-cols-3 gap-2\">\n          {years.map((year, index) => {\n            const isDisabled = isYearDisabled(year);\n            const isSelected = year === currentYear;\n            return (\n              <motion.button\n                key={year}\n                type=\"button\"\n                role=\"option\"\n                aria-selected={isSelected}\n                aria-disabled={isDisabled}\n                initial={\n                  prefersReducedMotion ? false : { opacity: 0, scale: 0.8 }\n                }\n                animate={{ opacity: 1, scale: 1 }}\n                transition={{ delay: prefersReducedMotion ? 0 : index * 0.02 }}\n                whileHover={\n                  !isDisabled && !prefersReducedMotion\n                    ? { scale: 1.05 }\n                    : undefined\n                }\n                whileTap={\n                  !isDisabled && !prefersReducedMotion\n                    ? { scale: 0.95 }\n                    : undefined\n                }\n                onClick={() => !isDisabled && onSelect(year)}\n                disabled={isDisabled}\n                className={cn(\n                  \"rounded-lg px-2 py-3 font-medium text-sm transition-all focus:outline-none focus:ring-2 focus:ring-primary\",\n                  isSelected\n                    ? \"bg-primary text-primary-foreground shadow-md\"\n                    : \"text-foreground hover:bg-accent\",\n                  isDisabled && \"cursor-not-allowed opacity-30\",\n                )}\n              >\n                {year}\n              </motion.button>\n            );\n          })}\n        </div>\n      </div>\n    );\n  },\n);\nYearPicker.displayName = \"YearPicker\";\n\n// Presets Panel\nconst PresetsPanel = React.memo(\n  ({\n    presets,\n    onSelect,\n    disabled,\n  }: {\n    presets: PresetRange[];\n    onSelect: (range: DateRange) => void;\n    disabled?: boolean;\n  }) => (\n    <div\n      className=\"mr-3 min-w-[140px] space-y-1 border-border border-r pr-3\"\n      role=\"group\"\n      aria-label=\"Quick date presets\"\n    >\n      <span className=\"mb-2 block font-semibold text-muted-foreground text-xs uppercase tracking-wider\">\n        Quick Select\n      </span>\n      {presets.map((preset, index) => (\n        <motion.button\n          key={preset.label}\n          type=\"button\"\n          initial={{ opacity: 0, x: -10 }}\n          animate={{ opacity: 1, x: 0 }}\n          transition={{ delay: index * 0.03 }}\n          whileHover={{ x: 4 }}\n          onClick={() => !disabled && onSelect(preset.getValue())}\n          disabled={disabled}\n          className=\"w-full rounded-lg px-3 py-2 text-left text-sm transition-colors hover:bg-accent focus:outline-none focus:ring-2 focus:ring-primary disabled:opacity-50\"\n        >\n          {preset.label}\n        </motion.button>\n      ))}\n    </div>\n  ),\n);\nPresetsPanel.displayName = \"PresetsPanel\";\n\n// ============================================================================\n// MAIN CALENDAR CONTENT\n// ============================================================================\n\nconst CalendarContent = React.memo(\n  ({\n    mode = \"single\",\n    value,\n    onChange,\n    minDate,\n    maxDate,\n    disabledDates = [],\n    disabledDaysOfWeek = [],\n    disableWeekends = false,\n    disablePastDates = false,\n    disableFutureDates = false,\n    showTime = false,\n    use24Hour = true,\n    minuteStep = 5,\n    showWeekNumbers = false,\n    showTodayButton = true,\n    showClearButton = true,\n    weekStartsOn = 0,\n    monthsToShow = 1,\n    showPresets = false,\n    presets = defaultPresets,\n    highlightedDates = [],\n    closeOnSelect = true,\n    size = \"md\",\n    disabled = false,\n    readOnly = false,\n    localeStrings = defaultLocaleStrings,\n    locale = enUS,\n    onMonthChange,\n    onYearChange,\n    onViewChange,\n    renderDay,\n    onClose,\n    id,\n  }: InternalCalendarProps & {\n    onClose?: () => void;\n    localeStrings: CalendarLocale;\n  }) => {\n    const prefersReducedMotion = useReducedMotion() ?? false;\n    const calendarRef = useRef<HTMLDivElement>(null);\n    const announcerRef = useRef<HTMLDivElement>(null);\n    const sizes = sizeClasses[size];\n\n    // Get initial date from value\n    const getInitialDate = useCallback(() => {\n      if (!value) return new Date();\n      if (mode === \"single\" && value instanceof Date) return value;\n      if (mode === \"range\") return (value as DateRange).from || new Date();\n      if (mode === \"multiple\" && Array.isArray(value))\n        return value[0] || new Date();\n      return new Date();\n    }, [value, mode]);\n\n    const [currentMonth, setCurrentMonth] = useState(getInitialDate);\n    const [direction, setDirection] = useState(0);\n    const [view, setView] = useState<CalendarView>(\"days\");\n    const [focusedDate, setFocusedDate] = useState<Date | null>(null);\n    const [rangeHover, setRangeHover] = useState<Date | null>(null);\n    const [rangeStart, setRangeStart] = useState<Date | undefined>(\n      mode === \"range\" ? (value as DateRange)?.from : undefined,\n    );\n\n    // Announce changes for screen readers\n    const announce = useCallback((message: string) => {\n      if (announcerRef.current) {\n        announcerRef.current.textContent = message;\n      }\n    }, []);\n\n    // View change handler\n    const handleViewChange = useCallback(\n      (newView: CalendarView) => {\n        setView(newView);\n        onViewChange?.(newView);\n        announce(`Switched to ${newView} view`);\n      },\n      [onViewChange, announce],\n    );\n\n    // Generate calendar days\n    const generateDays = useCallback(\n      (month: Date) => {\n        const monthStart = startOfMonth(month);\n        const monthEnd = endOfMonth(month);\n        const calendarStart = startOfWeek(monthStart, { weekStartsOn });\n        const calendarEnd = endOfWeek(monthEnd, { weekStartsOn });\n        return eachDayOfInterval({ start: calendarStart, end: calendarEnd });\n      },\n      [weekStartsOn],\n    );\n\n    const getWeekDays = useCallback(() => {\n      const days = [...localeStrings.weekdaysShort];\n      return [...days.slice(weekStartsOn), ...days.slice(0, weekStartsOn)];\n    }, [weekStartsOn, localeStrings.weekdaysShort]);\n\n    // Navigation handlers\n    const navigate = useCallback(\n      (delta: number, type: \"month\" | \"year\") => {\n        setDirection(delta);\n        setCurrentMonth((prev) => {\n          const newDate =\n            type === \"month\"\n              ? delta > 0\n                ? addMonths(prev, 1)\n                : subMonths(prev, 1)\n              : delta > 0\n                ? addYears(prev, 1)\n                : subYears(prev, 1);\n\n          if (type === \"month\") onMonthChange?.(newDate);\n          else onYearChange?.(newDate);\n\n          announce(format(newDate, \"MMMM yyyy\", { locale }));\n          return newDate;\n        });\n      },\n      [onMonthChange, onYearChange, announce, locale],\n    );\n\n    // Check if day is disabled\n    const isDayDisabled = useCallback(\n      (day: Date) => {\n        if (disabled || readOnly) return true;\n        const dayStart = startOfDay(day);\n        const today = startOfDay(new Date());\n\n        if (minDate && isBefore(dayStart, startOfDay(minDate))) return true;\n        if (maxDate && isAfter(dayStart, startOfDay(maxDate))) return true;\n        if (disabledDates.some((d) => isSameDay(d, day))) return true;\n        if (disableWeekends && isWeekend(day)) return true;\n        if (disabledDaysOfWeek.includes(getDay(day))) return true;\n        if (disablePastDates && isBefore(dayStart, today)) return true;\n        if (disableFutureDates && isAfter(dayStart, today)) return true;\n\n        return false;\n      },\n      [\n        disabled,\n        readOnly,\n        minDate,\n        maxDate,\n        disabledDates,\n        disableWeekends,\n        disabledDaysOfWeek,\n        disablePastDates,\n        disableFutureDates,\n      ],\n    );\n\n    // Date selection handler\n    const handleSelectDate = useCallback(\n      (day: Date) => {\n        if (isDayDisabled(day)) return;\n\n        if (mode === \"single\") {\n          const dateToSet =\n            showTime && value instanceof Date\n              ? setMinutes(setHours(day, getHours(value)), getMinutes(value))\n              : day;\n          onChange?.(dateToSet);\n          announce(`Selected ${format(dateToSet, \"PPPP\", { locale })}`);\n          if (closeOnSelect && !showTime) onClose?.();\n        } else if (mode === \"range\") {\n          if (!rangeStart) {\n            setRangeStart(day);\n            onChange?.({ from: day, to: undefined });\n            announce(`Range start: ${format(day, \"PP\", { locale })}`);\n          } else {\n            const range = isBefore(day, rangeStart)\n              ? { from: day, to: rangeStart }\n              : { from: rangeStart, to: day };\n            onChange?.(range);\n            setRangeStart(undefined);\n            announce(\n              `Range: ${format(range.from, \"PP\", { locale })} to ${format(range.to, \"PP\", { locale })}`,\n            );\n            if (closeOnSelect) onClose?.();\n          }\n        } else if (mode === \"multiple\") {\n          const currentDates = (value as Date[]) || [];\n          const exists = currentDates.some((d) => isSameDay(d, day));\n          const newDates = exists\n            ? currentDates.filter((d) => !isSameDay(d, day))\n            : [...currentDates, day];\n          onChange?.(newDates);\n          announce(\n            `${exists ? \"Deselected\" : \"Selected\"} ${format(day, \"PP\", { locale })}. ${newDates.length} dates selected.`,\n          );\n        }\n      },\n      [\n        mode,\n        onChange,\n        onClose,\n        rangeStart,\n        showTime,\n        value,\n        closeOnSelect,\n        isDayDisabled,\n        announce,\n        locale,\n      ],\n    );\n\n    // Selection state checks\n    const isDaySelected = useCallback(\n      (day: Date) => {\n        if (mode === \"single\" && value instanceof Date)\n          return isSameDay(day, value);\n        if (mode === \"range\" && value) {\n          const range = value as DateRange;\n          return (\n            (range.from && isSameDay(day, range.from)) ||\n            (range.to && isSameDay(day, range.to))\n          );\n        }\n        if (mode === \"multiple\" && Array.isArray(value)) {\n          return value.some((d) => isSameDay(d, day));\n        }\n        return false;\n      },\n      [mode, value],\n    );\n\n    const isDayInRange = useCallback(\n      (day: Date) => {\n        if (mode !== \"range\") return false;\n        const range = value as DateRange | undefined;\n\n        // Completed range\n        if (range?.from && range?.to) {\n          return (\n            isWithinInterval(day, { start: range.from, end: range.to }) &&\n            !isSameDay(day, range.from) &&\n            !isSameDay(day, range.to)\n          );\n        }\n\n        // Hover preview\n        if (rangeStart && rangeHover) {\n          const start = isBefore(rangeHover, rangeStart)\n            ? rangeHover\n            : rangeStart;\n          const end = isBefore(rangeHover, rangeStart)\n            ? rangeStart\n            : rangeHover;\n          return (\n            isWithinInterval(day, { start, end }) &&\n            !isSameDay(day, start) &&\n            !isSameDay(day, end)\n          );\n        }\n\n        return false;\n      },\n      [mode, value, rangeStart, rangeHover],\n    );\n\n    const getHighlight = useCallback(\n      (day: Date) => {\n        return highlightedDates.find((h) => isSameDay(h.date, day));\n      },\n      [highlightedDates],\n    );\n\n    // Keyboard navigation\n    useEffect(() => {\n      const handleKeyDown = (e: KeyboardEvent) => {\n        if (view !== \"days\" || disabled || readOnly) return;\n\n        const baseDate =\n          focusedDate || (value instanceof Date ? value : new Date());\n        let newDate = baseDate;\n        let handled = true;\n\n        switch (e.key) {\n          case \"ArrowLeft\":\n            newDate = addDays(baseDate, -1);\n            break;\n          case \"ArrowRight\":\n            newDate = addDays(baseDate, 1);\n            break;\n          case \"ArrowUp\":\n            newDate = addDays(baseDate, -7);\n            break;\n          case \"ArrowDown\":\n            newDate = addDays(baseDate, 7);\n            break;\n          case \"Home\":\n            newDate = startOfMonth(baseDate);\n            break;\n          case \"End\":\n            newDate = endOfMonth(baseDate);\n            break;\n          case \"PageUp\":\n            newDate = e.shiftKey\n              ? subYears(baseDate, 1)\n              : subMonths(baseDate, 1);\n            break;\n          case \"PageDown\":\n            newDate = e.shiftKey\n              ? addYears(baseDate, 1)\n              : addMonths(baseDate, 1);\n            break;\n          case \"Enter\":\n          case \" \":\n            if (focusedDate && !isDayDisabled(focusedDate)) {\n              handleSelectDate(focusedDate);\n            }\n            e.preventDefault();\n            return;\n          case \"Escape\":\n            onClose?.();\n            e.preventDefault();\n            return;\n          default:\n            handled = false;\n        }\n\n        if (handled) {\n          e.preventDefault();\n          setFocusedDate(newDate);\n          if (!isSameMonth(newDate, currentMonth)) {\n            setDirection(isAfter(newDate, currentMonth) ? 1 : -1);\n            setCurrentMonth(startOfMonth(newDate));\n          }\n          announce(format(newDate, \"EEEE, MMMM d, yyyy\", { locale }));\n        }\n      };\n\n      const el = calendarRef.current;\n      if (el) {\n        el.addEventListener(\"keydown\", handleKeyDown);\n        return () => el.removeEventListener(\"keydown\", handleKeyDown);\n      }\n    }, [\n      focusedDate,\n      view,\n      currentMonth,\n      value,\n      disabled,\n      readOnly,\n      isDayDisabled,\n      handleSelectDate,\n      onClose,\n      announce,\n      locale,\n    ]);\n\n    // Action handlers\n    const handleClear = useCallback(() => {\n      onChange?.(undefined);\n      setRangeStart(undefined);\n      announce(\"Selection cleared\");\n    }, [onChange, announce]);\n\n    const handlePresetSelect = useCallback(\n      (range: DateRange) => {\n        onChange?.(range);\n        if (range.from) setCurrentMonth(range.from);\n        announce(\n          `Selected: ${range.from && range.to ? `${format(range.from, \"PP\")} to ${format(range.to, \"PP\")}` : \"preset\"}`,\n        );\n        if (closeOnSelect) onClose?.();\n      },\n      [onChange, closeOnSelect, onClose, announce],\n    );\n\n    const handleMonthSelect = useCallback(\n      (month: number) => {\n        const newDate = setMonth(currentMonth, month);\n        setCurrentMonth(newDate);\n        handleViewChange(\"days\");\n        onMonthChange?.(newDate);\n      },\n      [currentMonth, handleViewChange, onMonthChange],\n    );\n\n    const handleYearSelect = useCallback(\n      (year: number) => {\n        const newDate = setYear(currentMonth, year);\n        setCurrentMonth(newDate);\n        handleViewChange(\"months\");\n        onYearChange?.(newDate);\n      },\n      [currentMonth, handleViewChange, onYearChange],\n    );\n\n    const handleTimeChange = useCallback(\n      (newDate: Date) => {\n        if (mode === \"single\") {\n          // Ensure we have a valid date, use today if needed\n          const baseDate =\n            value instanceof Date ? value : startOfDay(new Date());\n          const updatedDate = setMinutes(\n            setHours(baseDate, getHours(newDate)),\n            getMinutes(newDate),\n          );\n          onChange?.(updatedDate);\n          announce(\n            `Time set to ${format(updatedDate, use24Hour ? \"HH:mm\" : \"hh:mm a\")}`,\n          );\n        }\n      },\n      [mode, onChange, use24Hour, announce, value],\n    );\n\n    const goToToday = useCallback(() => {\n      const today = new Date();\n      setDirection(isAfter(today, currentMonth) ? 1 : -1);\n      setCurrentMonth(today);\n      if (mode === \"single\" && !isDayDisabled(today)) {\n        handleSelectDate(today);\n      }\n    }, [currentMonth, mode, isDayDisabled, handleSelectDate]);\n\n    // Render single day cell\n    const renderDayCell = useCallback(\n      (day: Date, monthDate: Date, index: number) => {\n        const isCurrentMonth = isSameMonth(day, monthDate);\n        const isSelected = isDaySelected(day);\n        const isTodayDate = isToday(day);\n        const isDisabled = isDayDisabled(day);\n        const inRange = isDayInRange(day);\n        const highlight = getHighlight(day);\n        const isFocused = focusedDate && isSameDay(day, focusedDate);\n\n        const dayContent = (\n          <motion.button\n            key={day.toISOString()}\n            type=\"button\"\n            role=\"gridcell\"\n            aria-selected={isSelected}\n            aria-disabled={isDisabled}\n            aria-current={isTodayDate ? \"date\" : undefined}\n            aria-label={`${format(day, \"EEEE, MMMM d, yyyy\", { locale })}${isSelected ? \", selected\" : \"\"}${isTodayDate ? \", today\" : \"\"}${highlight ? `, ${highlight.label}` : \"\"}`}\n            tabIndex={isFocused ? 0 : -1}\n            initial={prefersReducedMotion ? false : { opacity: 0, scale: 0.8 }}\n            animate={{ opacity: 1, scale: 1 }}\n            transition={{\n              duration: 0.1,\n              delay: prefersReducedMotion ? 0 : index * 0.003,\n            }}\n            whileHover={\n              !isDisabled && !prefersReducedMotion ? { scale: 1.1 } : undefined\n            }\n            whileTap={\n              !isDisabled && !prefersReducedMotion ? { scale: 0.95 } : undefined\n            }\n            onClick={() => handleSelectDate(day)}\n            onMouseEnter={() => {\n              if (mode === \"range\" && rangeStart && !isDisabled)\n                setRangeHover(day);\n            }}\n            onMouseLeave={() => setRangeHover(null)}\n            onFocus={() => setFocusedDate(day)}\n            disabled={isDisabled}\n            className={cn(\n              sizes.cell,\n              \"relative flex items-center justify-center rounded-lg font-medium outline-none transition-all\",\n              !isCurrentMonth && \"text-muted-foreground/40\",\n              isDisabled && \"cursor-not-allowed opacity-25\",\n              !isSelected &&\n                isCurrentMonth &&\n                !inRange &&\n                \"text-foreground hover:bg-accent\",\n              isSelected && \"bg-primary text-primary-foreground shadow-sm\",\n              isTodayDate &&\n                !isSelected &&\n                \"ring-2 ring-primary ring-offset-2 ring-offset-background\",\n              inRange && \"rounded-none bg-primary/15\",\n              isFocused && \"ring-2 ring-ring ring-offset-1\",\n            )}\n          >\n            <span className=\"relative z-10\">{format(day, \"d\")}</span>\n\n            {/* Today indicator */}\n            {isTodayDate && !isSelected && (\n              <span className=\"absolute bottom-0.5 left-1/2 h-1 w-1 -translate-x-1/2 rounded-full bg-primary\" />\n            )}\n\n            {/* Event highlight */}\n            {highlight && (\n              <span\n                className=\"absolute top-0.5 right-0.5 h-1.5 w-1.5 rounded-full\"\n                style={{\n                  backgroundColor: highlight.color || \"hsl(var(--primary))\",\n                }}\n                title={highlight.label}\n              />\n            )}\n          </motion.button>\n        );\n\n        return renderDay ? renderDay(day, dayContent) : dayContent;\n      },\n      [\n        sizes.cell,\n        isDaySelected,\n        isDayDisabled,\n        isDayInRange,\n        getHighlight,\n        focusedDate,\n        handleSelectDate,\n        mode,\n        rangeStart,\n        prefersReducedMotion,\n        locale,\n        renderDay,\n      ],\n    );\n\n    // Render month grid\n    const renderMonthGrid = useCallback(\n      (monthDate: Date, isSecondary = false) => {\n        const days = generateDays(monthDate);\n\n        return (\n          <div\n            className=\"space-y-1\"\n            role=\"grid\"\n            aria-label={format(monthDate, \"MMMM yyyy\", { locale })}\n          >\n            {isSecondary && (\n              <div className=\"mb-2 flex h-8 items-center justify-center\">\n                <span\n                  className={cn(\"font-semibold text-foreground\", sizes.header)}\n                >\n                  {format(monthDate, \"MMMM yyyy\", { locale })}\n                </span>\n              </div>\n            )}\n\n            {/* Week days header */}\n            <div\n              className={cn(\n                \"grid gap-0.5\",\n                showWeekNumbers ? \"grid-cols-8\" : \"grid-cols-7\",\n              )}\n              role=\"row\"\n              tabIndex={-1}\n            >\n              {showWeekNumbers && (\n                <div\n                  className={cn(\n                    sizes.cell,\n                    \"flex items-center justify-center font-medium text-muted-foreground text-xs\",\n                  )}\n                  role=\"columnheader\"\n                  tabIndex={-1}\n                >\n                  #\n                </div>\n              )}\n              {getWeekDays().map((day, i) => (\n                <div\n                  key={day}\n                  role=\"columnheader\"\n                  aria-label={localeStrings.weekdays[(weekStartsOn + i) % 7]}\n                  className={cn(\n                    sizes.cell,\n                    \"flex items-center justify-center font-semibold text-muted-foreground text-xs\",\n                  )}\n                  tabIndex={-1}\n                >\n                  {day}\n                </div>\n              ))}\n            </div>\n\n            {/* Days grid */}\n            <AnimatePresence mode=\"wait\" custom={direction}>\n              <motion.div\n                key={format(monthDate, \"yyyy-MM\")}\n                custom={direction}\n                variants={prefersReducedMotion ? undefined : slideVariants}\n                initial={isSecondary || prefersReducedMotion ? false : \"enter\"}\n                animate=\"center\"\n                exit={isSecondary || prefersReducedMotion ? undefined : \"exit\"}\n                transition={{ duration: prefersReducedMotion ? 0 : 0.2 }}\n                className={cn(\n                  \"grid gap-0.5\",\n                  showWeekNumbers ? \"grid-cols-8\" : \"grid-cols-7\",\n                )}\n                role=\"rowgroup\"\n              >\n                {days.map((day, index) => {\n                  const showWeekNumber = showWeekNumbers && index % 7 === 0;\n                  return (\n                    <React.Fragment key={day.toISOString()}>\n                      {showWeekNumber && (\n                        <div\n                          className={cn(\n                            sizes.cell,\n                            \"flex items-center justify-center text-muted-foreground text-xs\",\n                          )}\n                          role=\"rowheader\"\n                          tabIndex={-1}\n                        >\n                          {format(day, \"w\")}\n                        </div>\n                      )}\n                      {renderDayCell(day, monthDate, index)}\n                    </React.Fragment>\n                  );\n                })}\n              </motion.div>\n            </AnimatePresence>\n          </div>\n        );\n      },\n      [\n        generateDays,\n        getWeekDays,\n        showWeekNumbers,\n        sizes,\n        direction,\n        prefersReducedMotion,\n        renderDayCell,\n        locale,\n        localeStrings.weekdays,\n        weekStartsOn,\n      ],\n    );\n\n    const calendarWidth =\n      monthsToShow === 1\n        ? \"w-auto\"\n        : monthsToShow === 2\n          ? \"min-w-[580px]\"\n          : \"min-w-[860px]\";\n\n    return (\n      <motion.div\n        ref={calendarRef}\n        id={id}\n        tabIndex={0}\n        role=\"application\"\n        aria-label=\"Calendar\"\n        initial={\n          prefersReducedMotion ? false : { opacity: 0, scale: 0.95, y: -10 }\n        }\n        animate={{ opacity: 1, scale: 1, y: 0 }}\n        transition={{ duration: prefersReducedMotion ? 0 : 0.2 }}\n        className={cn(\n          \"pointer-events-auto overflow-hidden rounded-xl border bg-card shadow-black/10 shadow-xl focus:outline-none focus:ring-2 focus:ring-primary\",\n          sizes.container,\n          calendarWidth,\n          showPresets && mode === \"range\" && \"flex\",\n          disabled && \"pointer-events-none opacity-50\",\n        )}\n      >\n        {/* Screen reader announcer */}\n        <div\n          ref={announcerRef}\n          className=\"sr-only\"\n          role=\"status\"\n          aria-live=\"polite\"\n          aria-atomic=\"true\"\n        />\n\n        {/* Presets panel */}\n        {showPresets && mode === \"range\" && (\n          <PresetsPanel\n            presets={presets}\n            onSelect={handlePresetSelect}\n            disabled={disabled}\n          />\n        )}\n\n        <div className=\"flex-1\">\n          {/* Header */}\n          <div className=\"mb-3 flex items-center justify-between\">\n            <div className=\"flex items-center gap-0.5\">\n              <button\n                type=\"button\"\n                onClick={() => navigate(-1, \"year\")}\n                disabled={disabled}\n                className=\"rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n                aria-label=\"Previous year\"\n              >\n                <ChevronsLeft className=\"h-4 w-4\" />\n              </button>\n              <button\n                type=\"button\"\n                onClick={() => navigate(-1, \"month\")}\n                disabled={disabled}\n                className=\"rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n                aria-label=\"Previous month\"\n              >\n                <ChevronLeft className=\"h-4 w-4\" />\n              </button>\n            </div>\n\n            <div className=\"flex items-center gap-1\">\n              <button\n                type=\"button\"\n                onClick={() =>\n                  handleViewChange(view === \"months\" ? \"days\" : \"months\")\n                }\n                disabled={disabled}\n                className={cn(\n                  \"rounded-lg px-2 py-1 font-bold transition-colors hover:bg-accent\",\n                  sizes.header,\n                )}\n                aria-label={`Select month, currently ${format(currentMonth, \"MMMM\", { locale })}`}\n              >\n                {format(currentMonth, \"MMMM\", { locale })}\n              </button>\n              <button\n                type=\"button\"\n                onClick={() =>\n                  handleViewChange(view === \"years\" ? \"days\" : \"years\")\n                }\n                disabled={disabled}\n                className={cn(\n                  \"rounded-lg px-2 py-1 font-bold transition-colors hover:bg-accent\",\n                  sizes.header,\n                )}\n                aria-label={`Select year, currently ${format(currentMonth, \"yyyy\")}`}\n              >\n                {format(currentMonth, \"yyyy\")}\n              </button>\n            </div>\n\n            <div className=\"flex items-center gap-0.5\">\n              <button\n                type=\"button\"\n                onClick={() => navigate(1, \"month\")}\n                disabled={disabled}\n                className=\"rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n                aria-label=\"Next month\"\n              >\n                <ChevronRight className=\"h-4 w-4\" />\n              </button>\n              <button\n                type=\"button\"\n                onClick={() => navigate(1, \"year\")}\n                disabled={disabled}\n                className=\"rounded-lg p-1.5 transition-colors hover:bg-accent disabled:opacity-50\"\n                aria-label=\"Next year\"\n              >\n                <ChevronsRight className=\"h-4 w-4\" />\n              </button>\n            </div>\n          </div>\n\n          {/* View content */}\n          <AnimatePresence mode=\"wait\">\n            {view === \"days\" && (\n              <motion.div\n                key=\"days\"\n                {...(prefersReducedMotion ? {} : fadeScale)}\n                className=\"flex gap-4\"\n              >\n                {renderMonthGrid(currentMonth)}\n                {monthsToShow >= 2 && (\n                  <>\n                    <div className=\"w-px bg-border\" />\n                    {renderMonthGrid(addMonths(currentMonth, 1), true)}\n                  </>\n                )}\n                {monthsToShow === 3 && (\n                  <>\n                    <div className=\"w-px bg-border\" />\n                    {renderMonthGrid(addMonths(currentMonth, 2), true)}\n                  </>\n                )}\n              </motion.div>\n            )}\n            {view === \"months\" && (\n              <MonthPicker\n                key=\"months\"\n                currentMonth={currentMonth}\n                onSelect={handleMonthSelect}\n                minDate={minDate}\n                maxDate={maxDate}\n                size={size}\n                localeStrings={localeStrings}\n                disabled={disabled}\n                prefersReducedMotion={prefersReducedMotion}\n              />\n            )}\n            {view === \"years\" && (\n              <YearPicker\n                key=\"years\"\n                currentYear={getYear(currentMonth)}\n                onSelect={handleYearSelect}\n                minDate={minDate}\n                maxDate={maxDate}\n                size={size}\n                disabled={disabled}\n                prefersReducedMotion={prefersReducedMotion}\n              />\n            )}\n            {view === \"time\" && mode === \"single\" && (\n              <TimePicker\n                key=\"time\"\n                value={value instanceof Date ? value : new Date()}\n                onChange={handleTimeChange}\n                use24Hour={use24Hour}\n                minuteStep={minuteStep}\n                size={size}\n                localeStrings={localeStrings}\n                disabled={disabled}\n              />\n            )}\n          </AnimatePresence>\n\n          {/* Time toggle */}\n          {showTime && mode === \"single\" && view === \"days\" && (\n            <button\n              type=\"button\"\n              onClick={(e) => {\n                e.preventDefault();\n                e.stopPropagation();\n                // If no date selected, select today first\n                if (!(value instanceof Date)) {\n                  const today = new Date();\n                  onChange?.(today);\n                }\n                handleViewChange(\"time\");\n              }}\n              disabled={disabled}\n              className=\"mt-3 flex w-full items-center justify-center gap-2 rounded-lg bg-accent/50 py-2 font-medium text-sm transition-colors hover:bg-accent disabled:opacity-50\"\n            >\n              <Clock className=\"h-4 w-4\" />\n              {value instanceof Date\n                ? format(value, use24Hour ? \"HH:mm\" : \"hh:mm a\")\n                : localeStrings.selectTime}\n            </button>\n          )}\n\n          {view === \"time\" && (\n            <button\n              type=\"button\"\n              onClick={(e) => {\n                e.preventDefault();\n                e.stopPropagation();\n                handleViewChange(\"days\");\n              }}\n              disabled={disabled}\n              className=\"mt-3 flex w-full items-center justify-center gap-2 rounded-lg bg-accent/50 py-2 font-medium text-sm transition-colors hover:bg-accent disabled:opacity-50\"\n            >\n              <CalendarIcon className=\"h-4 w-4\" />\n              {localeStrings.backToCalendar}\n            </button>\n          )}\n\n          {/* Footer */}\n          {(showTodayButton ||\n            showClearButton ||\n            (mode === \"multiple\" && value)) &&\n            view === \"days\" && (\n              <div className=\"mt-4 flex items-center justify-between border-border/50 border-t pt-3\">\n                <div className=\"flex items-center gap-2\">\n                  {showTodayButton && (\n                    <button\n                      type=\"button\"\n                      onClick={goToToday}\n                      disabled={disabled}\n                      className=\"flex items-center gap-1 rounded-md px-3 py-1.5 font-semibold text-xs transition-colors hover:bg-accent disabled:opacity-50\"\n                    >\n                      <Check className=\"h-3 w-3\" />\n                      {localeStrings.today}\n                    </button>\n                  )}\n                  {mode === \"multiple\" &&\n                    Array.isArray(value) &&\n                    value.length > 0 && (\n                      <span className=\"text-muted-foreground text-xs\">\n                        {value.length} {localeStrings.selected}\n                      </span>\n                    )}\n                </div>\n                {showClearButton && value && (\n                  <button\n                    type=\"button\"\n                    onClick={handleClear}\n                    disabled={disabled}\n                    className=\"flex items-center gap-1 rounded-md px-3 py-1.5 font-medium text-muted-foreground text-xs transition-colors hover:bg-accent disabled:opacity-50\"\n                  >\n                    <X className=\"h-3 w-3\" />\n                    {localeStrings.clear}\n                  </button>\n                )}\n              </div>\n            )}\n        </div>\n      </motion.div>\n    );\n  },\n);\nCalendarContent.displayName = \"CalendarContent\";\n\n// ============================================================================\n// POPOVER CALENDAR\n// ============================================================================\n\nexport function AnimatedCalendar({\n  mode = \"single\",\n  value: controlledValue,\n  defaultValue,\n  onChange,\n  placeholder = \"Pick a date\",\n  disabled = false,\n  readOnly = false,\n  required = false,\n  error = false,\n  errorMessage,\n  className,\n  size = \"md\",\n  formatStr,\n  showTime,\n  use24Hour = true,\n  locale = enUS,\n  localeStrings: customLocaleStrings,\n  onOpen,\n  onClose,\n  onBlur,\n  onFocus,\n  id,\n  name,\n  \"aria-label\": ariaLabel,\n  \"aria-describedby\": ariaDescribedBy,\n  ...props\n}: AnimatedCalendarProps) {\n  const [isOpen, setIsOpen] = useState(false);\n  const generatedId = useId();\n  const triggerId = id || generatedId;\n  const errorId = `${triggerId}-error`;\n\n  const localeStrings = useMemo(\n    () => ({\n      ...defaultLocaleStrings,\n      ...customLocaleStrings,\n    }),\n    [customLocaleStrings],\n  );\n\n  // Internal state uses unified type for implementation\n  type InternalValue = Date | DateRange | Date[] | undefined;\n  const [value, setValue] = useControllableState<InternalValue>(\n    controlledValue as InternalValue,\n    (defaultValue ?? (mode === \"multiple\" ? [] : undefined)) as InternalValue,\n    onChange as ((value: InternalValue) => void) | undefined,\n  );\n\n  const handleOpenChange = useCallback(\n    (open: boolean) => {\n      setIsOpen(open);\n      if (open) {\n        onOpen?.();\n        onFocus?.();\n      } else {\n        onClose?.();\n        onBlur?.();\n      }\n    },\n    [onOpen, onClose, onFocus, onBlur],\n  );\n\n  const getDisplayValue = useMemo(() => {\n    if (!value) return placeholder;\n\n    if (mode === \"single\" && value instanceof Date) {\n      const fmt =\n        formatStr ||\n        (showTime ? (use24Hour ? \"PPP HH:mm\" : \"PPP hh:mm a\") : \"PPP\");\n      return format(value, fmt, { locale });\n    }\n    if (mode === \"range\") {\n      const range = value as DateRange;\n      if (range.from && range.to) {\n        return `${format(range.from, \"MMM d\", { locale })} – ${format(range.to, \"MMM d, yyyy\", { locale })}`;\n      }\n      if (range.from)\n        return `${format(range.from, \"MMM d, yyyy\", { locale })} – ...`;\n      return placeholder;\n    }\n    if (mode === \"multiple\" && Array.isArray(value)) {\n      if (value.length === 0) return placeholder;\n      const firstDate = value[0];\n      if (value.length === 1 && firstDate)\n        return format(firstDate, \"PPP\", { locale });\n      return `${value.length} dates selected`;\n    }\n    return placeholder;\n  }, [value, mode, placeholder, formatStr, showTime, use24Hour, locale]);\n\n  const sizeClasses = {\n    sm: \"w-[240px] h-8 text-xs\",\n    md: \"w-[280px] h-10 text-sm\",\n    lg: \"w-[320px] h-12 text-base\",\n  };\n\n  return (\n    <div className=\"relative\">\n      <Popover open={isOpen} onOpenChange={handleOpenChange}>\n        <PopoverTrigger asChild>\n          <Button\n            id={triggerId}\n            type=\"button\"\n            variant=\"outline\"\n            disabled={disabled}\n            aria-label={ariaLabel || placeholder}\n            aria-describedby={cn(\n              ariaDescribedBy,\n              error && errorMessage && errorId,\n            )}\n            aria-invalid={error}\n            aria-required={required}\n            aria-expanded={isOpen}\n            aria-haspopup=\"dialog\"\n            className={cn(\n              sizeClasses[size],\n              \"justify-start text-left font-normal\",\n              !value && \"text-muted-foreground\",\n              error && \"border-destructive focus:ring-destructive\",\n              className,\n            )}\n          >\n            <CalendarIcon className=\"mr-2 h-4 w-4 shrink-0\" />\n            <span className=\"flex-1 truncate\">{getDisplayValue}</span>\n            {required && <span className=\"ml-1 text-destructive\">*</span>}\n          </Button>\n        </PopoverTrigger>\n        <PopoverContent\n          className=\"w-auto border-0 bg-transparent p-0 shadow-none\"\n          align=\"start\"\n        >\n          <CalendarContent\n            {...(props as InternalCalendarProps)}\n            mode={mode}\n            value={value as Date | DateRange | Date[] | undefined}\n            onChange={\n              setValue as (value: Date | DateRange | Date[] | undefined) => void\n            }\n            disabled={disabled}\n            readOnly={readOnly}\n            showTime={showTime}\n            use24Hour={use24Hour}\n            size={size}\n            locale={locale}\n            localeStrings={localeStrings as CalendarLocale}\n            onClose={() => handleOpenChange(false)}\n          />\n        </PopoverContent>\n      </Popover>\n\n      {/* Hidden input for form integration */}\n      {name && (\n        <input\n          type=\"hidden\"\n          name={name}\n          value={\n            value instanceof Date ? value.toISOString() : JSON.stringify(value)\n          }\n        />\n      )}\n\n      {/* Error message */}\n      {error && errorMessage && (\n        <p\n          id={errorId}\n          className=\"mt-1.5 flex items-center gap-1 text-destructive text-xs\"\n        >\n          <AlertCircle className=\"h-3 w-3\" />\n          {errorMessage}\n        </p>\n      )}\n    </div>\n  );\n}\n\n// ============================================================================\n// STANDALONE CALENDAR\n// ============================================================================\n\nexport function AnimatedCalendarStandalone({\n  localeStrings: customLocaleStrings,\n  ...props\n}: Omit<\n  AnimatedCalendarProps,\n  \"placeholder\" | \"onOpen\" | \"onClose\" | \"onBlur\" | \"onFocus\"\n>) {\n  const localeStrings = useMemo(\n    () => ({\n      ...defaultLocaleStrings,\n      ...customLocaleStrings,\n    }),\n    [customLocaleStrings],\n  );\n\n  return (\n    <CalendarContent\n      {...(props as InternalCalendarProps)}\n      localeStrings={localeStrings as CalendarLocale}\n    />\n  );\n}\n",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}