{"version":3,"file":"index.cjs","sources":["../src/utils/date-conversion.ts","../src/utils/formatting.ts","../src/utils/normalize.ts","../src/utils/validation.ts","../src/utils/calendar-grid.ts","../src/utils/date-comparison.ts","../src/utils/preset-ranges.ts","../src/utils/weekday-utils.ts","../src/components/CalendarHeader.tsx","../src/components/TimeSelector.tsx","../src/utils/translations.ts","../src/hooks/useCalendarState/helpers/time.ts","../src/hooks/useCalendarState/helpers/resolveDisplayMonth.ts","../src/hooks/useCalendarState/reducers/dateSelection.ts","../src/hooks/useCalendarState/reducers/range.ts","../src/hooks/useCalendarState/reducers/week.ts","../src/hooks/useCalendarState/reducers/multi.ts","../src/hooks/useCalendarState/reducers/time.ts","../src/hooks/useCalendarState/reducers/navigation.ts","../src/hooks/useCalendarState/index.ts","../src/hooks/useCalendarState/reducers/index.ts","../src/hooks/useCalendarState/actions.ts","../src/utils/constraints.ts","../src/hooks/useKeyboardNavigation.ts","../src/hooks/useFocusTrap.ts","../src/hooks/useCalendarSetup.ts","../src/hooks/useCalendarCallbacks.ts","../src/hooks/useModalState.ts","../src/hooks/useClickOutside.ts","../src/hooks/useEscapeKey.ts","../src/hooks/useCalendarErrorHandling.ts","../src/hooks/useCallbackOnChange.ts","../src/components/CalendarGridView.tsx","../src/hooks/useFocusManagement.ts","../src/utils/calendar-selection.ts","../src/components/MonthView.tsx","../src/components/YearView.tsx","../src/components/CalendarCore.tsx","../src/components/DtPickerTrigger.tsx","../src/components/DtPicker.tsx","../src/hooks/useCalendarPicker.ts","../src/hooks/useModalPosition.ts","../src/components/DtCalendar.tsx","../src/utils/index.ts"],"sourcesContent":["/**\n * Date conversion utilities for Gregorian and Jalali calendars\n */\n\nimport { toJalaali, toGregorian } from 'jalaali-js'\nimport type { Day, Range, Multi } from '../types'\nimport type {\n  CalendarLocale,\n  CalendarSystem,\n  RangeDate\n} from '../types/calendar'\nimport { isValidDay } from './validation'\n\n/**\n * Convert Gregorian Day to Jalali Day\n * @throws {Error} If the input date is invalid or conversion fails\n */\nexport function gregorianToJalali(day: Day): Day {\n  try {\n    // Validate input first\n    if (!isValidDay(day, 'gregorian')) {\n      throw new Error(`Invalid Gregorian date: ${JSON.stringify(day)}`)\n    }\n\n    const jDate = toJalaali(day.year, day.month, day.day)\n    return {\n      year: jDate.jy,\n      month: jDate.jm,\n      day: jDate.jd,\n      hour: day.hour,\n      minute: day.minute\n    }\n  } catch (error) {\n    console.error(`Failed to convert Gregorian date: ${error}`)\n    throw new Error(\n      `Date conversion failed: ${error instanceof Error ? error.message : String(error)}`\n    )\n  }\n}\n\n/**\n * Convert Jalali Day to Gregorian Day\n * @throws {Error} If the input date is invalid or conversion fails\n */\nexport function jalaliToGregorian(day: Day): Day {\n  try {\n    // Validate input first\n    if (!isValidDay(day, 'jalali')) {\n      throw new Error(`Invalid Jalali date: ${JSON.stringify(day)}`)\n    }\n\n    const gDate = toGregorian(day.year, day.month, day.day)\n    return {\n      year: gDate.gy,\n      month: gDate.gm,\n      day: gDate.gd,\n      hour: day.hour,\n      minute: day.minute\n    }\n  } catch (error) {\n    console.error(`Failed to convert Jalali date: ${error}`)\n    throw new Error(\n      `Date conversion failed: ${error instanceof Error ? error.message : String(error)}`\n    )\n  }\n}\n\n/**\n * Convert a Day object to the target locale\n * @param day - Day object in source locale\n * @param fromLocale - Source locale ('gregorian' or 'jalali')\n * @param toLocale - Target locale ('gregorian' or 'jalali')\n * @returns Day object in target locale\n * @throws {Error} If conversion fails\n */\nexport function convertToLocale(\n  day: Day,\n  fromLocale: CalendarLocale,\n  toLocale: CalendarLocale\n): Day {\n  // If already in target locale, return as-is\n  if (fromLocale === toLocale) {\n    return day\n  }\n\n  // Convert between calendars\n  if (fromLocale === 'jalali' && toLocale === 'gregorian') {\n    return jalaliToGregorian(day)\n  }\n\n  if (fromLocale === 'gregorian' && toLocale === 'jalali') {\n    return gregorianToJalali(day)\n  }\n\n  // Same locale (shouldn't reach here due to early return, but TypeScript needs it)\n  return day\n}\n\n/**\n * Normalize calendar system input to CalendarLocale\n * Converts shorthand aliases ('ge' -> 'gregorian', 'ja' -> 'jalali')\n */\nexport function normalizeCalendarSystem(\n  input: CalendarSystem | undefined\n): CalendarLocale {\n  if (!input) return 'gregorian'\n  if (input === 'ge') return 'gregorian'\n  if (input === 'ja') return 'jalali'\n  return input\n}\n\n/**\n * Get today's date in the specified locale\n */\nexport function getToday(calendarSystem: CalendarLocale): Day {\n  const today = new Date()\n  const gregorianDay: Day = {\n    year: today.getFullYear(),\n    month: today.getMonth() + 1, // JavaScript months are 0-indexed\n    day: today.getDate()\n  }\n\n  if (calendarSystem === 'jalali') {\n    return gregorianToJalali(gregorianDay)\n  }\n\n  return gregorianDay\n}\n\n/**\n * Convert a JavaScript Date object to a Day object in the specified locale\n * Uses local time methods to preserve user's intended date when converting from Date objects\n * Note: When used with dates created by dayToDate (UTC), the time component may differ\n * based on timezone, but the date (year/month/day) will be correct\n */\nexport function dateToDay(date: Date, calendarSystem: CalendarLocale): Day {\n  const gregorianDay: Day = {\n    year: date.getFullYear(),\n    month: date.getMonth() + 1,\n    day: date.getDate(),\n    hour: date.getHours(),\n    minute: date.getMinutes()\n  }\n\n  if (calendarSystem === 'jalali') {\n    return gregorianToJalali(gregorianDay)\n  }\n\n  return gregorianDay\n}\n\n/**\n * Convert a Day object to a JavaScript Date object\n * Converts Jalali dates to Gregorian before creating Date object\n * Uses UTC to ensure the date always matches the calendar date regardless of timezone\n * @param day - Day object in the specified calendar system\n * @param calendarSystem - Calendar system of the input day ('gregorian' or 'jalali')\n * @returns JavaScript Date object (in UTC, but represents the correct calendar date)\n * @throws {Error} If the input date is invalid or conversion fails\n */\nexport function dayToDate(\n  day: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Date {\n  try {\n    // Validate input first\n    if (!isValidDay(day, calendarSystem)) {\n      throw new Error(`Invalid ${calendarSystem} date: ${JSON.stringify(day)}`)\n    }\n\n    // If day is in Jalali, convert to Gregorian first\n    const gregorianDay =\n      calendarSystem === 'jalali' ? jalaliToGregorian(day) : day\n\n    // Use Date.UTC() to create the date in UTC timezone\n    // This ensures the date always matches the calendar date regardless of user's timezone\n    // For example: December 27, 2025 should always be 2025-12-27T00:00:00.000Z, not 2025-12-26T23:00:00.000Z\n    return new Date(\n      Date.UTC(\n        gregorianDay.year,\n        gregorianDay.month - 1, // JavaScript months are 0-indexed\n        gregorianDay.day,\n        gregorianDay.hour ?? 0,\n        gregorianDay.minute ?? 0,\n        0, // seconds\n        0 // milliseconds\n      )\n    )\n  } catch (error) {\n    console.error('Failed to convert Day to Date:', error)\n    throw new Error(\n      `Date conversion failed: ${error instanceof Error ? error.message : String(error)}`\n    )\n  }\n}\n\n/**\n * Convert a normalized value (Day | Range | Multi | null) to JavaScript Date equivalent\n * Always returns Gregorian dates, converting from Jalali if necessary\n * @param value - Normalized value (Day | Range | Multi | null)\n * @param type - Calendar selection type\n * @param calendarSystem - Calendar system of the input value\n * @returns JavaScript Date equivalent (always Gregorian)\n */\nexport function convertToJsDate(\n  value: Day | Range | Multi | null,\n  type: 'single' | 'range' | 'multi' | 'week',\n  calendarSystem: CalendarLocale\n): Date | RangeDate | Date[] | null {\n  if (value === null) {\n    return null\n  }\n\n  if (type === 'single' && 'year' in value && !('from' in value)) {\n    const day = value as Day\n    return dayToDate(day, calendarSystem)\n  }\n\n  if ((type === 'range' || type === 'week') && 'from' in value) {\n    const range = value as Range\n    return {\n      from: range.from ? dayToDate(range.from, calendarSystem) : null,\n      to: range.to ? dayToDate(range.to, calendarSystem) : null\n    }\n  }\n\n  if (type === 'multi' && Array.isArray(value)) {\n    const multi = value as Multi\n    return multi.map((day) => dayToDate(day, calendarSystem))\n  }\n\n  return null\n}\n","/**\n * Date formatting utilities for display in input fields\n */\n\nimport type {\n  Day,\n  Range,\n  Multi,\n  Week,\n  CalendarLocale,\n  CalendarType\n} from '../types'\nimport type { ValidationResult } from '../types/calendar'\nimport { validateDay } from './validation'\nimport { getYearRange } from './calendar-grid'\n\n// --- Constants & Helpers ---\n\nconst PERSIAN_DIGITS = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']\nconst PERSIAN_TO_ENGLISH: Record<string, string> = {\n  '۰': '0',\n  '۱': '1',\n  '۲': '2',\n  '۳': '3',\n  '۴': '4',\n  '۵': '5',\n  '۶': '6',\n  '۷': '7',\n  '۸': '8',\n  '۹': '9'\n}\n\n/**\n * Detect time format from dateFormat string\n * Returns '12' if format contains 'hh' (12-hour), '24' if format contains 'HH' (24-hour), or '24' as default\n */\nexport function detectTimeFormatFromDateFormat(\n  dateFormat?: string\n): '12' | '24' {\n  if (!dateFormat) {\n    return '24' // Default to 24-hour format\n  }\n  // Check for 12-hour format token (lowercase hh)\n  if (dateFormat.includes('hh')) {\n    return '12'\n  }\n  // Check for 24-hour format token (uppercase HH)\n  if (dateFormat.includes('HH')) {\n    return '24'\n  }\n  // Default to 24-hour format if no time tokens are present\n  return '24'\n}\n\n/**\n * Convert a number to Persian numerals\n */\nexport function toPersianNumeral(num: number | string): string {\n  return num.toString().replace(/\\d/g, (d) => PERSIAN_DIGITS[parseInt(d, 10)])\n}\n\n/**\n * Convert Persian numerals in a string to English numerals\n */\nexport function toEnglishNumeral(str: string): string {\n  return str.replace(/[۰-۹]/g, (char) => PERSIAN_TO_ENGLISH[char] || char)\n}\n\n/**\n * Format a number according to the specified number system\n */\nexport function formatNumber(\n  num: number | string,\n  numberSystem: 'latin' | 'persian'\n): string {\n  if (numberSystem === 'persian') {\n    return toPersianNumeral(num)\n  }\n  return num.toString()\n}\n\n/**\n * Format a date according to a custom format string\n * Supports tokens:\n * - Date: YYYY (year), MM (month), DD (day)\n * - Time: HH (24-hour), hh (12-hour), mm (minutes), A (AM/PM), a (am/pm)\n * Supports custom separators and order\n * Examples: \"DD/MM/YYYY\", \"MM-DD-YYYY HH:mm\", \"YYYY년 MM월 DD일 hh:mm A\"\n * The format string itself determines whether to use 12-hour (hh) or 24-hour (HH) format\n * Time tokens are only rendered if showTime is true AND the day has time values\n */\nfunction formatDateWithCustomFormat(\n  day: Day,\n  format: string,\n  numberSystem: 'latin' | 'persian',\n  showTime = false\n): string {\n  const { year, month, day: dayNum, hour, minute } = day\n  const hasTime = hour !== undefined && minute !== undefined\n  // Only render time if showTime is enabled AND day has time values\n  const shouldShowTime = showTime && hasTime\n\n  // Prepare date strings\n  const YYYY = year.toString()\n  const MM = month.toString().padStart(2, '0')\n  const DD = dayNum.toString().padStart(2, '0')\n\n  // Prepare time strings\n  let HH = '',\n    hh = '',\n    mm = '',\n    A = '',\n    a = ''\n\n  if (shouldShowTime) {\n    HH = hour.toString().padStart(2, '0')\n    mm = minute.toString().padStart(2, '0')\n\n    // Convert to 12-hour format\n    const hour12 = hour % 12 || 12\n    hh = hour12.toString().padStart(2, '0')\n\n    const isPm = hour >= 12\n    A = isPm ? 'PM' : 'AM'\n    a = isPm ? 'pm' : 'am'\n  }\n\n  // Map of tokens to their values\n  const tokens: Record<string, string> = {\n    YYYY,\n    MM,\n    DD,\n    HH,\n    hh,\n    mm,\n    A,\n    a\n  }\n\n  // Regex to match tokens\n  const tokenRegex = /YYYY|MM|DD|HH|hh|mm|A|a/g\n\n  let formatted = format.replace(tokenRegex, (match) => {\n    // If we shouldn't show time but the token asks for it, return empty string\n    if (!shouldShowTime && ['HH', 'hh', 'mm', 'A', 'a'].includes(match)) {\n      return ''\n    }\n    return tokens[match] ?? match\n  })\n\n  // Cleanup if time tokens were removed (extra spaces/colons)\n  if (!shouldShowTime) {\n    formatted = formatted\n      .replace(/HH|hh|mm/g, '') // Ensure any remaining time tokens are gone\n      .replace(/A|a/g, '')\n      .replace(/\\s*:\\s*/g, '') // Remove empty colons\n      .replace(/\\s+/g, ' ') // Collapse multiple spaces\n      .replace(/\\s+$/g, '') // Remove trailing spaces\n      .trim()\n  }\n\n  // Convert to Persian numerals if number system is 'persian'\n  if (numberSystem === 'persian') {\n    formatted = toPersianNumeral(formatted)\n  }\n\n  return formatted\n}\n\n/**\n * Format a single day for display\n */\nfunction formatDay(\n  day: Day,\n  numberSystem: 'latin' | 'persian',\n  showTime = false,\n  dateFormat?: string\n): string {\n  let formatted: string\n\n  if (dateFormat) {\n    // Use custom format (includes time if format string contains time tokens and showTime is true)\n    formatted = formatDateWithCustomFormat(\n      day,\n      dateFormat,\n      numberSystem,\n      showTime\n    )\n  } else {\n    // Default format: YYYY/MM/DD\n    const { year, month, day: dayNum, hour, minute } = day\n    const YYYY = year.toString()\n    const MM = month.toString().padStart(2, '0')\n    const DD = dayNum.toString().padStart(2, '0')\n\n    formatted = `${YYYY}/${MM}/${DD}`\n\n    // Append time if showTime is true and time is available (defaults to 24-hour format)\n    if (showTime && hour !== undefined && minute !== undefined) {\n      const HH = hour.toString().padStart(2, '0')\n      const mm = minute.toString().padStart(2, '0')\n      formatted += ` ${HH}:${mm}`\n    }\n\n    // Convert to Persian numerals if number system is 'persian'\n    if (numberSystem === 'persian') {\n      formatted = toPersianNumeral(formatted)\n    }\n  }\n\n  return formatted\n}\n\n/**\n * Format a date value for input display based on type\n */\nexport function formatDateForInput(\n  value: Day | Range | Multi | Week | null,\n  numberSystem: 'latin' | 'persian',\n  type: CalendarType,\n  showTime = false,\n  fromLabel = 'from',\n  toLabel = 'to',\n  dateFormat?: string\n): string {\n  if (!value) return ''\n\n  // Helper to keep code DRY\n  const fmt = (d: Day) => formatDay(d, numberSystem, showTime, dateFormat)\n\n  if (type === 'single' && 'year' in value) {\n    return fmt(value as Day)\n  }\n\n  if (type === 'range' && 'from' in value && 'to' in value) {\n    const range = value as Range\n    const fromStr = fmt(range.from)\n    // Handle case where to is null (when selecting start date)\n    if (!range.to) {\n      return `${fromLabel} ${fromStr}`\n    }\n    const toStr = fmt(range.to)\n    return `${fromLabel} ${fromStr} ${toLabel} ${toStr}`\n  }\n\n  if (type === 'week' && 'from' in value && 'to' in value) {\n    const week = value as Week\n    const fromStr = fmt(week.from)\n    const toStr = fmt(week.to)\n    const weekLabel = numberSystem === 'persian' ? 'هفته' : 'Week'\n    return `${weekLabel}: ${fromStr} - ${toStr}`\n  }\n\n  if (type === 'multi' && Array.isArray(value)) {\n    const multi = value as Multi\n    if (multi.length === 0) return ''\n    if (multi.length === 1) {\n      return fmt(multi[0])\n    }\n    // Return comma-separated list of formatted dates\n    return multi.map(fmt).join(',')\n  }\n\n  return ''\n}\n\n/**\n * Format a value for onChange callback output\n * Returns null if value is null, otherwise returns formatted string\n */\nexport function formatValueToString(\n  value: Day | Range | Multi | Week | null,\n  type: CalendarType,\n  numberSystem: 'latin' | 'persian',\n  withTime: boolean,\n  dateFormat?: string,\n  fromLabel = 'from',\n  toLabel = 'to'\n): string | null {\n  if (value === null) {\n    return null\n  }\n\n  const formatted = formatDateForInput(\n    value,\n    numberSystem,\n    type,\n    withTime,\n    fromLabel,\n    toLabel,\n    dateFormat\n  )\n\n  return formatted || null\n}\n\n/**\n * Convert Day to string format (for utility functions like convertToFa/convertToEn)\n */\nexport function dayToString(day: Day, divider = '/'): string {\n  const { year, month, day: dayNum } = day\n  return [\n    year,\n    month.toString().padStart(2, '0'),\n    dayNum.toString().padStart(2, '0')\n  ].join(divider)\n}\n\n// --- Parsing Logic ---\n\n/**\n * Helper to parse simple formats (YYYY/MM/DD, YYYY-MM-DD, etc.)\n */\nfunction parseSimpleDate(dateStr: string): Day | null {\n  const match = dateStr.match(/^(\\d{4})[/\\-.](\\d{1,2})[/\\-.](\\d{1,2})$/)\n  if (!match) return null\n\n  return {\n    year: parseInt(match[1], 10),\n    month: parseInt(match[2], 10),\n    day: parseInt(match[3], 10)\n  }\n}\n\n/**\n * Helper to escape Regex special characters\n */\nfunction escapeRegExp(string: string): string {\n  return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Parse a date string to Day object\n * Supports formats: YYYY/MM/DD, YYYY-MM-DD, etc.\n * If dateFormat is provided, parses according to the format pattern (e.g., \"DD/MM/YYYY\", \"MM-DD-YYYY\")\n * For Jalali locale, also supports Persian numerals\n */\nexport function parseDateString(\n  dateString: string,\n  calendarSystem: CalendarLocale,\n  dateFormat?: string\n): Day | null {\n  let cleaned = dateString.trim()\n\n  // 1. Normalize numerals (Persian to English)\n  if (calendarSystem === 'jalali') {\n    cleaned = toEnglishNumeral(cleaned)\n    // 2. Normalize Persian AM/PM to English (So regex can match it)\n    cleaned = cleaned\n      .replace(/ب\\.ظ/g, 'PM')\n      .replace(/ق\\.ظ/g, 'AM')\n      .replace(/بظ/g, 'PM')\n      .replace(/قظ/g, 'AM')\n  }\n\n  if (dateFormat) {\n    let regexStr = escapeRegExp(dateFormat)\n\n    regexStr = regexStr\n      .replace(/YYYY/g, '(?<year>\\\\d{4})')\n      .replace(/HH/g, '(?<hour24>\\\\d{1,2})')\n      .replace(/hh/g, '(?<hour12>\\\\d{1,2})')\n      .replace(/MM/g, '(?<month>\\\\d{1,2})')\n      .replace(/DD/g, '(?<day>\\\\d{1,2})')\n      .replace(/mm/g, '(?<minute>\\\\d{1,2})')\n      .replace(/(?<![a-zA-Z])A(?![a-zA-Z])/g, '(?<ampmUpper>AM|PM)')\n      .replace(/(?<![a-zA-Z])a(?![a-zA-Z])/g, '(?<ampmLower>am|pm)')\n\n    const matcher = new RegExp(`^${regexStr}$`, 'i')\n    const match = cleaned.match(matcher)\n\n    if (match && match.groups) {\n      const year = parseInt(match.groups.year, 10)\n      const month = parseInt(match.groups.month, 10)\n      const day = parseInt(match.groups.day, 10)\n\n      if (!isNaN(year) && !isNaN(month) && !isNaN(day)) {\n        const result: Day = { year, month, day }\n\n        let hour: number | undefined\n        let minute: number | undefined\n\n        // Handle 24-hour format\n        if (match.groups.hour24 !== undefined) {\n          hour = parseInt(match.groups.hour24, 10)\n          // Default minute to 0 if only hour is provided\n          minute =\n            match.groups.minute !== undefined\n              ? parseInt(match.groups.minute, 10)\n              : 0\n        }\n        // Handle 12-hour format\n        else if (match.groups.hour12 !== undefined) {\n          const hour12 = parseInt(match.groups.hour12, 10)\n          const ampm =\n            match.groups.ampmUpper?.toUpperCase() ||\n            match.groups.ampmLower?.toUpperCase() ||\n            ''\n\n          if (hour12 === 12) {\n            hour = ampm === 'PM' ? 12 : 0\n          } else {\n            hour = ampm === 'PM' ? hour12 + 12 : hour12\n          }\n\n          // Default minute to 0\n          minute =\n            match.groups.minute !== undefined\n              ? parseInt(match.groups.minute, 10)\n              : 0\n        }\n\n        if (hour !== undefined && minute !== undefined) {\n          result.hour = hour\n          result.minute = minute\n        }\n\n        return result\n      }\n    }\n  }\n\n  // Fallback if no format provided or regex failed\n  // (You might want to return null here if you want strict parsing only when dateFormat is present)\n  return parseSimpleDate(cleaned) // Assuming parseSimpleDate is defined elsewhere as before\n}\n/**\n * Parse and validate a date string in one step\n * Combines parseDateString and validateDay for convenience\n * Also validates that the year is within the calendar's year range\n * @param dateString - Date string to parse (e.g., \"2024/12/25\", \"2024-12-25\", \"25/12/2024\")\n * @param calendarSystem - Calendar system ('gregorian' or 'jalali')\n * @param dateFormat - Optional format pattern (e.g., \"DD/MM/YYYY\", \"MM-DD-YYYY\"). If provided, parses according to this format.\n * @returns ValidationResult with parsed and validated Day object, or error if parsing/validation fails\n */\nexport function parseAndValidateDate(\n  dateString: string,\n  calendarSystem: CalendarLocale,\n  dateFormat?: string\n): ValidationResult<Day> {\n  // Parse the date string\n  const parsed = parseDateString(dateString, calendarSystem, dateFormat)\n\n  if (!parsed) {\n    return {\n      success: false,\n      error: {\n        code: 'PARSE_ERROR',\n        message: `Could not parse date string: \"${dateString}\"`,\n        details: { dateString, calendarSystem }\n      }\n    }\n  }\n\n  // Check if year is within the calendar's year range\n  const yearRangeArr = getYearRange(parsed.year, 12, calendarSystem)\n  // Optimization: Find min/max without iterating whole array if possible,\n  // but using spread for compatibility with existing getYearRange return type\n  const minYear = Math.min(...yearRangeArr)\n  const maxYear = Math.max(...yearRangeArr)\n\n  if (parsed.year < minYear || parsed.year > maxYear) {\n    return {\n      success: false,\n      error: {\n        code: 'YEAR_OUT_OF_RANGE',\n        message: `Year ${parsed.year} is not in the range of calendar`,\n        details: {\n          year: parsed.year,\n          calendarSystem,\n          yearRange: { min: minYear, max: maxYear }\n        }\n      }\n    }\n  }\n\n  // Validate the parsed date\n  return validateDay(parsed, calendarSystem)\n}\n","/**\n * Value normalization utilities\n * Handles converting various input formats to normalized Day/Range/Multi objects\n */\n\nimport type {\n  Day,\n  Range,\n  Multi,\n  Week,\n  CalendarLocale,\n  CalendarType\n} from '../types'\nimport type { CalendarError } from '../types/calendar'\nimport { dateToDay } from './date-conversion'\nimport { parseDateString } from './formatting'\nimport { getWeekBounds } from './calendar-grid'\nimport { isValidDay } from './validation'\n\n/**\n * Check if we're in development mode\n * Uses a simple check that works in both browser and Node environments\n */\nconst isDevelopment = (() => {\n  try {\n    // Check for common development indicators\n    if (typeof window !== 'undefined') {\n      // Browser environment - check for dev tools or localhost\n      return (\n        window.location?.hostname === 'localhost' ||\n        window.location?.hostname === '127.0.0.1' ||\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        (window as any).__DEV__ === true\n      )\n    }\n    // Node environment - assume development unless explicitly set to production\n    return true // Default to showing warnings in Node (can be overridden)\n  } catch {\n    return false // If we can't determine, don't show warnings\n  }\n})()\n\n/**\n * Type guards\n */\nexport function isDayObject(value: unknown): value is Day {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    'year' in value &&\n    'month' in value &&\n    'day' in value &&\n    typeof (value as Day).year === 'number' &&\n    typeof (value as Day).month === 'number' &&\n    typeof (value as Day).day === 'number'\n  )\n}\n\nexport function isRangeObject(value: unknown): value is Range {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    'from' in value &&\n    'to' in value &&\n    isDayObject((value as Range).from) &&\n    isDayObject((value as Range).to)\n  )\n}\n\nexport function isMultiArray(value: unknown): value is Multi {\n  return (\n    Array.isArray(value) &&\n    value.length > 0 &&\n    value.every((item) => isDayObject(item))\n  )\n}\n\n/**\n * Check if two values are structurally equal\n * Handles Day, Range, and Multi types\n */\nexport function areValuesEqual(v1: unknown, v2: unknown): boolean {\n  if (v1 === v2) return true\n\n  // Treat null and undefined as equal (both mean \"no value\")\n  if ((v1 === null || v1 === undefined) && (v2 === null || v2 === undefined)) {\n    return true\n  }\n\n  if (!v1 || !v2) return false\n\n  // Check Day equality\n  if (isDayObject(v1) && isDayObject(v2)) {\n    return (\n      v1.year === v2.year &&\n      v1.month === v2.month &&\n      v1.day === v2.day &&\n      (v1.hour || 0) === (v2.hour || 0) &&\n      (v1.minute || 0) === (v2.minute || 0)\n    )\n  }\n\n  // Handle Date objects - convert both to timestamps for comparison\n  if (v1 instanceof Date && v2 instanceof Date) {\n    return v1.getTime() === v2.getTime()\n  }\n\n  // Handle comparison between Date and Day objects\n  // For now, we'll assume gregorian calendar for Date comparison\n  // This is a limitation but covers the most common case\n  if (v1 instanceof Date && isDayObject(v2)) {\n    const dayFromDate = dateToDay(v1, 'gregorian')\n    return areValuesEqual(dayFromDate, v2)\n  }\n  if (isDayObject(v1) && v2 instanceof Date) {\n    const dayFromDate = dateToDay(v2, 'gregorian')\n    return areValuesEqual(v1, dayFromDate)\n  }\n\n  // Check Range equality\n  if (isRangeObject(v1) && isRangeObject(v2)) {\n    return areValuesEqual(v1.from, v2.from) && areValuesEqual(v1.to, v2.to)\n  }\n\n  // Check Multi equality\n  if (Array.isArray(v1) && Array.isArray(v2)) {\n    if (v1.length !== v2.length) return false\n    // Sort logic might be needed if order doesn't matter, but usually order matters or is sorted\n    // For now assume same order or just exact match\n    return v1.every((day, i) => areValuesEqual(day, v2[i]))\n  }\n\n  return false\n}\n\n/**\n * Deep equality comparison for normalized calendar value types (Day, Range, Multi, null)\n * Performs content-based comparison instead of reference comparison\n * This is optimized for comparing already-normalized values (unlike areValuesEqual which handles mixed types)\n *\n * @param a - First normalized value to compare\n * @param b - Second normalized value to compare\n * @returns true if values have identical content, false otherwise\n */\nexport function areNormalizedValuesEqual(\n  a: Day | Range | Multi | null | undefined,\n  b: Day | Range | Multi | null | undefined\n): boolean {\n  // Handle null/undefined cases\n  if (a === null || a === undefined) {\n    return b === null || b === undefined\n  }\n  if (b === null || b === undefined) {\n    return false\n  }\n\n  // Handle Day objects\n  if (\n    'year' in a &&\n    'month' in a &&\n    'day' in a &&\n    !('from' in a) &&\n    !Array.isArray(a)\n  ) {\n    const dayA = a as Day\n    if (\n      !(\n        'year' in b &&\n        'month' in b &&\n        'day' in b &&\n        !('from' in b) &&\n        !Array.isArray(b)\n      )\n    ) {\n      return false\n    }\n    const dayB = b as Day\n    return (\n      dayA.year === dayB.year &&\n      dayA.month === dayB.month &&\n      dayA.day === dayB.day &&\n      (dayA.hour ?? undefined) === (dayB.hour ?? undefined) &&\n      (dayA.minute ?? undefined) === (dayB.minute ?? undefined)\n    )\n  }\n\n  // Handle Range objects\n  if ('from' in a && 'to' in a && !Array.isArray(a)) {\n    const rangeA = a as Range\n    if (!('from' in b && 'to' in b && !Array.isArray(b))) {\n      return false\n    }\n    const rangeB = b as Range\n    return (\n      areNormalizedValuesEqual(rangeA.from, rangeB.from) &&\n      areNormalizedValuesEqual(rangeA.to, rangeB.to)\n    )\n  }\n\n  // Handle Multi (array of Day objects)\n  if (Array.isArray(a)) {\n    if (!Array.isArray(b)) {\n      return false\n    }\n    const multiA = a as Multi\n    const multiB = b as Multi\n    if (multiA.length !== multiB.length) {\n      return false\n    }\n    // Compare each Day in the array\n    for (let i = 0; i < multiA.length; i++) {\n      if (!areNormalizedValuesEqual(multiA[i], multiB[i])) {\n        return false\n      }\n    }\n    return true\n  }\n\n  // Fallback: reference equality for unknown types\n  return a === b\n}\n\n/**\n * Normalize a single day object\n * Ensures all required fields are present and valid\n * Supports: Day objects, Date objects, date strings, and timestamps (numbers)\n * Returns result with value and errors\n */\nfunction normalizeDayWithErrors(\n  day: unknown,\n  calendarSystem: CalendarLocale,\n  fieldName: string = 'date'\n): { value: Day | null; error: CalendarError | null } {\n  if (!day) {\n    return { value: null, error: null }\n  }\n\n  // Handle Day objects (already in the correct format)\n  if (isDayObject(day)) {\n    // Validate day object\n    if (isValidDay(day, calendarSystem)) {\n      return {\n        value: {\n          year: day.year,\n          month: day.month,\n          day: day.day,\n          hour: day.hour,\n          minute: day.minute\n        },\n        error: null\n      }\n    } else {\n      const error: CalendarError = {\n        type: 'normalization',\n        field: fieldName,\n        value: day,\n        message: `Invalid day object: date is invalid for the given locale`\n      }\n      if (isDevelopment) {\n        console.warn(`[react-calendar-datetime-picker] ${error.message}`, day)\n      }\n      return { value: null, error }\n    }\n  }\n\n  // Handle Date objects\n  if (day instanceof Date) {\n    if (isNaN(day.getTime())) {\n      const error: CalendarError = {\n        type: 'normalization',\n        field: fieldName,\n        value: day,\n        message: `Invalid Date object: date is invalid`\n      }\n      if (isDevelopment) {\n        console.warn(`[react-calendar-datetime-picker] ${error.message}`, day)\n      }\n      return { value: null, error }\n    }\n    return { value: dateToDay(day, calendarSystem), error: null }\n  }\n\n  // Handle numbers (timestamps)\n  if (typeof day === 'number') {\n    const date = new Date(day)\n    if (isNaN(date.getTime())) {\n      const error: CalendarError = {\n        type: 'normalization',\n        field: fieldName,\n        value: day,\n        message: `Invalid timestamp: ${day} cannot be converted to a valid date`\n      }\n      if (isDevelopment) {\n        console.warn(`[react-calendar-datetime-picker] ${error.message}`)\n      }\n      return { value: null, error }\n    }\n    return { value: dateToDay(date, calendarSystem), error: null }\n  }\n\n  // Handle strings (date strings like \"2024/12/25\", \"2024-12-25\", ISO strings, etc.)\n  if (typeof day === 'string') {\n    // First try to parse as Date (handles ISO strings like \"2024-12-25T00:00:00Z\")\n    const dateFromString = new Date(day)\n    if (!isNaN(dateFromString.getTime())) {\n      return { value: dateToDay(dateFromString, calendarSystem), error: null }\n    }\n\n    // Fall back to simple date string parsing (handles \"2024/12/25\", \"2024-12-25\", etc.)\n    const parsed = parseDateString(day, calendarSystem)\n    if (parsed) {\n      return { value: parsed, error: null }\n    }\n\n    const error: CalendarError = {\n      type: 'normalization',\n      field: fieldName,\n      value: day,\n      message: `Invalid date string: \"${day}\" cannot be parsed as a date`\n    }\n    if (isDevelopment) {\n      console.warn(`[react-calendar-datetime-picker] ${error.message}`)\n    }\n    return { value: null, error }\n  }\n\n  const error: CalendarError = {\n    type: 'normalization',\n    field: fieldName,\n    value: day,\n    message: `Unsupported date format: expected Day object, Date, string, or number, got ${typeof day}`\n  }\n  if (isDevelopment) {\n    console.warn(`[react-calendar-datetime-picker] ${error.message}`, day)\n  }\n  return { value: null, error }\n}\n\n/**\n * Normalize initial value based on calendar type with error information\n */\nexport function normalizeInitValueWithErrors(\n  value: unknown,\n  calendarSystem: CalendarLocale,\n  type: CalendarType,\n  fieldName: string = 'initValue'\n): { value: Day | Range | Multi | Week | null; errors: CalendarError[] } {\n  const errors: CalendarError[] = []\n\n  if (!value) {\n    return { value: null, errors }\n  }\n\n  // Handle single date\n  if (type === 'single') {\n    const result = normalizeDayWithErrors(value, calendarSystem, fieldName)\n    if (result.error) {\n      errors.push(result.error)\n    }\n    return { value: result.value, errors }\n  }\n\n  // Handle range\n  if (type === 'range') {\n    if (isRangeObject(value)) {\n      const fromResult = normalizeDayWithErrors(\n        value.from,\n        calendarSystem,\n        `${fieldName}.from`\n      )\n      const toResult = normalizeDayWithErrors(\n        value.to,\n        calendarSystem,\n        `${fieldName}.to`\n      )\n\n      if (fromResult.error) errors.push(fromResult.error)\n      if (toResult.error) errors.push(toResult.error)\n\n      if (fromResult.value && toResult.value) {\n        return { value: { from: fromResult.value, to: toResult.value }, errors }\n      }\n    } else {\n      const error: CalendarError = {\n        type: 'normalization',\n        field: fieldName,\n        value,\n        message: `Invalid range format: expected object with 'from' and 'to' properties`\n      }\n      if (isDevelopment) {\n        console.warn(`[react-calendar-datetime-picker] ${error.message}`, value)\n      }\n      errors.push(error)\n    }\n    return { value: null, errors }\n  }\n\n  // Handle week (similar to range but always calculates week bounds)\n  if (type === 'week') {\n    // Week can accept a single date (which will be converted to week bounds) or a week object\n    if (isRangeObject(value)) {\n      const fromResult = normalizeDayWithErrors(\n        value.from,\n        calendarSystem,\n        `${fieldName}.from`\n      )\n      const toResult = normalizeDayWithErrors(\n        value.to,\n        calendarSystem,\n        `${fieldName}.to`\n      )\n\n      if (fromResult.error) errors.push(fromResult.error)\n      if (toResult.error) errors.push(toResult.error)\n\n      if (fromResult.value && toResult.value) {\n        return { value: { from: fromResult.value, to: toResult.value }, errors }\n      }\n    } else {\n      // Single date - convert to week bounds\n      const dayResult = normalizeDayWithErrors(value, calendarSystem, fieldName)\n      if (dayResult.error) {\n        errors.push(dayResult.error)\n        return { value: null, errors }\n      }\n      if (dayResult.value) {\n        // Use default weekStart based on calendar system (not available in normalize)\n        const defaultWeekStart = calendarSystem === 'jalali' ? 6 : 0\n        const weekBounds = getWeekBounds(\n          dayResult.value,\n          calendarSystem,\n          defaultWeekStart\n        )\n        return { value: weekBounds, errors }\n      }\n    }\n    return { value: null, errors }\n  }\n\n  // Handle multi\n  if (type === 'multi') {\n    if (isMultiArray(value)) {\n      const normalized: Day[] = []\n      value.forEach((day, index) => {\n        const result = normalizeDayWithErrors(\n          day,\n          calendarSystem,\n          `${fieldName}[${index}]`\n        )\n        if (result.error) {\n          errors.push(result.error)\n        } else if (result.value) {\n          normalized.push(result.value)\n        }\n      })\n      return { value: normalized.length > 0 ? normalized : null, errors }\n    } else {\n      const error: CalendarError = {\n        type: 'normalization',\n        field: fieldName,\n        value,\n        message: `Invalid multi format: expected array of date objects`\n      }\n      if (isDevelopment) {\n        console.warn(`[react-calendar-datetime-picker] ${error.message}`, value)\n      }\n      errors.push(error)\n    }\n    return { value: null, errors }\n  }\n\n  return { value: null, errors }\n}\n\n/**\n * Normalize initial value based on calendar type (backward compatible)\n * @deprecated Use normalizeInitValueWithErrors for error information\n */\nexport function normalizeInitValue(\n  value: unknown,\n  calendarSystem: CalendarLocale,\n  type: CalendarType\n): Day | Range | Multi | Week | null {\n  return normalizeInitValueWithErrors(value, calendarSystem, type).value\n}\n\n/**\n * Extract month from a value for display purposes\n */\nexport function extractMonthFromValue(\n  value: Day | Range | Multi | Week | null\n): Day | null {\n  if (!value) return null\n\n  if (isDayObject(value)) {\n    return { year: value.year, month: value.month, day: 1 }\n  }\n\n  if (isRangeObject(value)) {\n    return { year: value.from.year, month: value.from.month, day: 1 }\n  }\n\n  if (Array.isArray(value) && value.length > 0) {\n    const firstDay = value[0]\n    return { year: firstDay.year, month: firstDay.month, day: 1 }\n  }\n\n  return null\n}\n","/**\n * Date validation utilities\n */\n\nimport type { Day, Range, Multi, CalendarLocale, CalendarType } from '../types'\nimport type { ValidationResult } from '../types/calendar'\nimport { jalaliToGregorian } from './date-conversion'\nimport { isDayObject } from './normalize'\n\n/**\n * Check if a year is a leap year in Gregorian calendar\n */\nfunction isGregorianLeapYear(year: number): boolean {\n  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n}\n\n/**\n * Check if a year is a leap year in Jalali calendar\n */\nfunction isJalaliLeapYear(year: number): boolean {\n  // Jalali leap year calculation using the 33-year cycle\n  // The remainders of dividing the year in the cycle by 33 should be in [1, 5, 9, 13, 17, 22, 26, 30]\n  const remainders = [1, 5, 9, 13, 17, 22, 26, 30]\n  const cycleYear = year % 33\n  return remainders.includes(cycleYear)\n}\n\n/**\n * Check if a year is a leap year in the specified calendar system\n * @param year - Year to check\n * @param calendarSystem - Calendar system ('gregorian' or 'jalali')\n * @returns true if the year is a leap year\n */\nexport function isLeapYear(\n  year: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  if (calendarSystem === 'jalali') {\n    return isJalaliLeapYear(year)\n  } else {\n    return isGregorianLeapYear(year)\n  }\n}\n\n/**\n * Get the number of days in a month\n */\nexport function getDaysInMonth(\n  year: number,\n  month: number,\n  calendarSystem: CalendarLocale\n): number {\n  if (calendarSystem === 'jalali') {\n    // Jalali calendar: first 6 months have 31 days, next 5 have 30, last has 29 or 30\n    if (month <= 6) return 31\n    if (month <= 11) return 30\n    return isJalaliLeapYear(year) ? 30 : 29\n  } else {\n    // Gregorian calendar\n    const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n    if (month === 2 && isGregorianLeapYear(year)) {\n      return 29\n    }\n    return daysInMonth[month - 1]\n  }\n}\n\n/**\n * Validate a Day object\n */\nexport function isValidDay(day: Day, calendarSystem: CalendarLocale): boolean {\n  if (day.year <= 0) return false\n  if (day.month < 1 || day.month > 12) return false\n\n  const maxDay = getDaysInMonth(day.year, day.month, calendarSystem)\n  if (day.day < 1 || day.day > maxDay) return false\n\n  if (day.hour !== undefined && (day.hour < 0 || day.hour > 23)) {\n    return false\n  }\n\n  if (day.minute !== undefined && (day.minute < 0 || day.minute > 59)) {\n    return false\n  }\n\n  return true\n}\n\n/**\n * Check if a date is within the min/max range\n */\nexport function isDateInRange(\n  day: Day,\n  minDate?: Day,\n  maxDate?: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  if (!isValidDay(day, calendarSystem)) return false\n\n  // Convert all dates to the same calendar system for comparison\n  // We'll compare in Gregorian for consistency\n  const dayGregorian =\n    calendarSystem === 'jalali' ? jalaliToGregorian(day) : day\n  const minGregorian = minDate\n    ? calendarSystem === 'jalali'\n      ? jalaliToGregorian(minDate)\n      : minDate\n    : null\n  const maxGregorian = maxDate\n    ? calendarSystem === 'jalali'\n      ? jalaliToGregorian(maxDate)\n      : maxDate\n    : null\n\n  // Compare dates\n  if (minGregorian) {\n    if (\n      dayGregorian.year < minGregorian.year ||\n      (dayGregorian.year === minGregorian.year &&\n        dayGregorian.month < minGregorian.month) ||\n      (dayGregorian.year === minGregorian.year &&\n        dayGregorian.month === minGregorian.month &&\n        dayGregorian.day < minGregorian.day)\n    ) {\n      return false\n    }\n  }\n\n  if (maxGregorian) {\n    if (\n      dayGregorian.year > maxGregorian.year ||\n      (dayGregorian.year === maxGregorian.year &&\n        dayGregorian.month > maxGregorian.month) ||\n      (dayGregorian.year === maxGregorian.year &&\n        dayGregorian.month === maxGregorian.month &&\n        dayGregorian.day > maxGregorian.day)\n    ) {\n      return false\n    }\n  }\n\n  return true\n}\n\n/**\n * Check if a date is in the disabled dates list\n */\nexport function isDateInDisabledList(\n  day: Day,\n  disabledDates?: Day[],\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  if (!disabledDates || disabledDates.length === 0) return false\n\n  // Convert to Gregorian for comparison\n  const dayGregorian =\n    calendarSystem === 'jalali' ? jalaliToGregorian(day) : day\n\n  return disabledDates.some((disabledDay) => {\n    const disabledGregorian =\n      calendarSystem === 'jalali' ? jalaliToGregorian(disabledDay) : disabledDay\n\n    return (\n      dayGregorian.year === disabledGregorian.year &&\n      dayGregorian.month === disabledGregorian.month &&\n      dayGregorian.day === disabledGregorian.day\n    )\n  })\n}\n\n/**\n * Check if a date is disabled (either in disabledDates list or via callback)\n */\nexport function isDateDisabled(\n  day: Day,\n  options: {\n    disabledDates?: Day[]\n    isDateDisabled?: (date: Day) => boolean\n    calendarSystem?: CalendarLocale\n  }\n): boolean {\n  const {\n    disabledDates,\n    isDateDisabled: isDateDisabledCallback,\n    calendarSystem = 'gregorian'\n  } = options\n\n  // Check custom callback first\n  if (isDateDisabledCallback && isDateDisabledCallback(day)) {\n    return true\n  }\n\n  // Check disabled dates list\n  if (isDateInDisabledList(day, disabledDates, calendarSystem)) {\n    return true\n  }\n\n  return false\n}\n\n/**\n * Validate a normalized value (Day | Range | Multi) against constraints\n * Returns true if all dates in the value are selectable, false otherwise\n */\nexport function isValidNormalizedValue(\n  value: Day | Range | Multi | null,\n  type: CalendarType,\n  options: {\n    minDate?: Day\n    maxDate?: Day\n    disabledDates?: Day[]\n    isDateDisabled?: (date: Day) => boolean\n    calendarSystem?: CalendarLocale\n  }\n): boolean {\n  if (!value) return true // null is valid\n\n  if (type === 'single' && 'year' in value) {\n    return isDateSelectable(value as Day, options)\n  }\n\n  if (type === 'range' && 'from' in value) {\n    const range = value as Range\n    const fromValid = !range.from || isDateSelectable(range.from, options)\n    const toValid = !range.to || isDateSelectable(range.to, options)\n    return fromValid && toValid\n  }\n\n  if (type === 'multi' && Array.isArray(value)) {\n    return (value as Multi).every((day: Day) => isDateSelectable(day, options))\n  }\n\n  // For week type or unknown types, return true (let other validation handle it)\n  return true\n}\n\n/**\n * Check if a date can be selected (valid, in range, not disabled)\n */\nexport function isDateSelectable(\n  day: Day,\n  options: {\n    minDate?: Day\n    maxDate?: Day\n    disabledDates?: Day[]\n    isDateDisabled?: (date: Day) => boolean\n    calendarSystem?: CalendarLocale\n  }\n): boolean {\n  const {\n    minDate,\n    maxDate,\n    disabledDates,\n    isDateDisabled: isDateDisabledCallback,\n    calendarSystem = 'gregorian'\n  } = options\n\n  if (!isValidDay(day, calendarSystem)) return false\n  if (!isDateInRange(day, minDate, maxDate, calendarSystem)) return false\n  if (\n    isDateDisabled(day, {\n      disabledDates,\n      isDateDisabled: isDateDisabledCallback,\n      calendarSystem\n    })\n  )\n    return false\n\n  return true\n}\n\n/**\n * Compare two Day objects\n * Returns: -1 if day1 < day2, 0 if equal, 1 if day1 > day2\n */\nexport function compareDays(\n  day1: Day,\n  day2: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): number {\n  // Convert to Gregorian for comparison\n  const d1 = calendarSystem === 'jalali' ? jalaliToGregorian(day1) : day1\n  const d2 = calendarSystem === 'jalali' ? jalaliToGregorian(day2) : day2\n\n  if (d1.year !== d2.year) {\n    return d1.year < d2.year ? -1 : 1\n  }\n  if (d1.month !== d2.month) {\n    return d1.month < d2.month ? -1 : 1\n  }\n  if (d1.day !== d2.day) {\n    return d1.day < d2.day ? -1 : 1\n  }\n\n  return 0\n}\n\n/**\n * Unified validation function using ValidationResult interface\n * Provides consistent error handling across utilities\n * @param day - Day object or unknown value to validate\n * @param locale - Calendar system (gregorian or jalali)\n * @returns ValidationResult with success status and data or error\n */\nexport function validateDay(\n  day: unknown,\n  locale: CalendarLocale\n): ValidationResult<Day> {\n  try {\n    // Check if it's a Day object\n    if (!isDayObject(day)) {\n      return {\n        success: false,\n        error: {\n          code: 'INVALID_TYPE',\n          message: 'Not a Day object',\n          details: { received: typeof day, value: day }\n        }\n      }\n    }\n\n    // Validate the day\n    if (!isValidDay(day, locale)) {\n      return {\n        success: false,\n        error: {\n          code: 'INVALID_DATE',\n          message: `Invalid ${locale} date: Day ${day.day} does not exist in month ${day.month} of year ${day.year}`,\n          details: { day, locale }\n        }\n      }\n    }\n\n    return { success: true, data: day }\n  } catch (error) {\n    return {\n      success: false,\n      error: {\n        code: 'CONVERSION_ERROR',\n        message:\n          error instanceof Error ? error.message : 'Unknown validation error',\n        details: { originalError: error }\n      }\n    }\n  }\n}\n","/**\n * Calendar grid generation utilities\n * Generates calendar grids for both Gregorian and Jalali calendars\n */\n\nimport type { Day, CalendarLocale } from '../types'\nimport { getDaysInMonth } from './validation'\nimport {\n  jalaliToGregorian,\n  getToday,\n  dateToDay,\n  dayToDate\n} from './date-conversion'\n\n/**\n * Calendar day with metadata\n */\nexport interface CalendarDay {\n  /** The day value (1-31) */\n  day: number\n  /** The month this day belongs to (1-12) */\n  month: number\n  /** The year this day belongs to */\n  year: number\n  /** Whether this day is in the current displayed month */\n  isCurrentMonth: boolean\n  /** Whether this day is today */\n  isToday: boolean\n  /** Full Day object for this date */\n  dayObject: Day\n}\n\n/**\n * Get the first day of the week for a given calendar system\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @param weekStart - Optional explicit week start day (0-6). If provided, uses this value.\n * @returns The first day of the week (0 = Sunday, 6 = Saturday)\n */\nfunction getFirstDayOfWeek(\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n): number {\n  // If weekStart is explicitly provided, use it\n  if (weekStart !== undefined) {\n    return weekStart\n  }\n  // Otherwise, default based on calendar system\n  // Gregorian: Sunday (0), Jalali: Saturday (6)\n  return calendarSystem === 'jalali' ? 6 : 0\n}\n\n/**\n * Get the day of week for a given date\n * Always returns in Gregorian format: 0 = Sunday, 6 = Saturday\n * This ensures consistency regardless of calendar system or locale\n */\nfunction getDayOfWeek(\n  year: number,\n  month: number,\n  day: number,\n  calendarSystem: CalendarLocale\n): number {\n  if (calendarSystem === 'jalali') {\n    // For Jalali, convert to Gregorian first to use JavaScript Date\n    const jalaliDay: Day = { year, month, day }\n    const gregorianDay = jalaliToGregorian(jalaliDay)\n    const date = new Date(\n      gregorianDay.year,\n      gregorianDay.month - 1,\n      gregorianDay.day\n    )\n    // Return in Gregorian format (0 = Sunday, 6 = Saturday)\n    // The grid generation will handle weekStart alignment\n    return date.getDay() // 0 = Sunday, 6 = Saturday\n  } else {\n    // Gregorian: use JavaScript Date directly\n    const date = new Date(year, month - 1, day)\n    return date.getDay() // 0 = Sunday, 6 = Saturday\n  }\n}\n\n/**\n * Generate calendar grid for a given month\n * Returns a 6x7 grid (6 weeks × 7 days)\n * @param month - The month to generate grid for\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @param weekStart - Optional first day of the week (0-6). If not provided, defaults based on calendar system.\n */\nexport function generateCalendarGrid(\n  month: Day,\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n): CalendarDay[][] {\n  const { year, month: monthNum } = month\n  const firstDayOfWeek = getFirstDayOfWeek(calendarSystem, weekStart)\n  const daysInMonth = getDaysInMonth(year, monthNum, calendarSystem)\n\n  // Get the first day of the month's day of week\n  const firstDayWeekday = getDayOfWeek(year, monthNum, 1, calendarSystem)\n\n  // Calculate how many days from previous month to show\n  const daysFromPrevMonth = (firstDayWeekday - firstDayOfWeek + 7) % 7\n\n  // Calculate previous month/year\n  let prevMonth = monthNum - 1\n  let prevYear = year\n  if (prevMonth < 1) {\n    prevMonth = 12\n    prevYear = year - 1\n  }\n  const daysInPrevMonth = getDaysInMonth(prevYear, prevMonth, calendarSystem)\n\n  // Get today's date for comparison\n  const todayDayObj = getToday(calendarSystem)\n\n  const grid: CalendarDay[][] = []\n  let currentWeek: CalendarDay[] = []\n\n  // Add days from previous month\n  for (let i = daysFromPrevMonth - 1; i >= 0; i--) {\n    const day = daysInPrevMonth - i\n    currentWeek.push({\n      day,\n      month: prevMonth,\n      year: prevYear,\n      isCurrentMonth: false,\n      isToday: false,\n      dayObject: { year: prevYear, month: prevMonth, day }\n    })\n  }\n\n  // Add days from current month\n  for (let day = 1; day <= daysInMonth; day++) {\n    const isToday =\n      year === todayDayObj.year &&\n      monthNum === todayDayObj.month &&\n      day === todayDayObj.day\n\n    currentWeek.push({\n      day,\n      month: monthNum,\n      year,\n      isCurrentMonth: true,\n      isToday,\n      dayObject: { year, month: monthNum, day }\n    })\n\n    // If week is complete (7 days), start a new week\n    if (currentWeek.length === 7) {\n      grid.push(currentWeek)\n      currentWeek = []\n    }\n  }\n\n  // Add days from next month to fill the last week\n  let nextMonth = monthNum + 1\n  let nextYear = year\n  if (nextMonth > 12) {\n    nextMonth = 1\n    nextYear = year + 1\n  }\n\n  let nextMonthDay = 1\n  while (currentWeek.length < 7) {\n    currentWeek.push({\n      day: nextMonthDay,\n      month: nextMonth,\n      year: nextYear,\n      isCurrentMonth: false,\n      isToday: false,\n      dayObject: { year: nextYear, month: nextMonth, day: nextMonthDay }\n    })\n    nextMonthDay++\n  }\n\n  // Add the last week if it has any days\n  if (currentWeek.length > 0) {\n    grid.push(currentWeek)\n  }\n\n  // Ensure we have 6 weeks (some months might only need 5)\n  while (grid.length < 6) {\n    const lastWeek = grid[grid.length - 1]\n    const lastDay = lastWeek[lastWeek.length - 1]\n    const nextDay = lastDay.day + 1\n    const nextMonth = lastDay.month\n    const nextYear = lastDay.year\n\n    const newWeek: CalendarDay[] = []\n    for (let i = 0; i < 7; i++) {\n      newWeek.push({\n        day: nextDay + i,\n        month: nextMonth,\n        year: nextYear,\n        isCurrentMonth: false,\n        isToday: false,\n        dayObject: {\n          year: nextYear,\n          month: nextMonth,\n          day: nextDay + i\n        }\n      })\n    }\n    grid.push(newWeek)\n  }\n\n  return grid\n}\n\n/**\n * Calculate the months to display based on the base month and number of months\n * Returns an array of Day objects representing the months to display\n */\nexport function getMonthsToDisplay(\n  baseMonth: Day,\n  numberOfMonths: number,\n  _calendarSystem: CalendarLocale\n): Day[] {\n  const months: Day[] = []\n\n  for (let i = 0; i < numberOfMonths; i++) {\n    let year = baseMonth.year\n    let month = baseMonth.month + i\n\n    // Handle month overflow\n    while (month > 12) {\n      month -= 12\n      year += 1\n    }\n\n    months.push({\n      year,\n      month,\n      day: 1 // Use first day of month for month representation\n    })\n  }\n\n  return months\n}\n\n/**\n * Get a list of years for year selection view\n * Returns appropriate years based on locale\n * Gregorian: 1900 to current year + 30\n * Jalali: 1300 to current Jalali year + 30\n */\nexport function getYearRange(\n  _centerYear: number,\n  _range = 12,\n  calendarSystem: CalendarLocale = 'gregorian'\n): number[] {\n  if (calendarSystem === 'jalali') {\n    // Jalali calendar: typically years 1300-1450 (roughly 1921-2071 Gregorian)\n    const today = getToday(calendarSystem)\n    const currentYear = today.year\n    const startYear = 1300\n    const endYear = currentYear + 30\n    const years: number[] = []\n\n    for (let year = startYear; year <= endYear; year++) {\n      years.push(year)\n    }\n\n    return years\n  } else {\n    // Gregorian calendar: 1900 to current year + 30\n    const currentYear = new Date().getFullYear()\n    const startYear = 1900\n    const endYear = currentYear + 30\n    const years: number[] = []\n\n    for (let year = startYear; year <= endYear; year++) {\n      years.push(year)\n    }\n\n    return years\n  }\n}\n\n/**\n * Get a list of months (1-12) for month selection view\n */\nexport function getMonths(): number[] {\n  return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n}\n\n/**\n * Get the start and end dates of a week containing the given date\n * Week starts on Sunday for Gregorian, Saturday for Jalali (unless weekStart is specified)\n * @param day - The day to get week bounds for\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @param weekStart - Optional first day of the week (0-6). If not provided, defaults based on calendar system.\n */\nexport function getWeekBounds(\n  day: Day,\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n): { from: Day; to: Day } {\n  const dayOfWeek = getDayOfWeek(day.year, day.month, day.day, calendarSystem)\n  const firstDayOfWeek = getFirstDayOfWeek(calendarSystem, weekStart)\n\n  // Calculate days to subtract to get to the start of the week\n  const daysToSubtract = (dayOfWeek - firstDayOfWeek + 7) % 7\n\n  // Calculate start of week\n  let startDate: Date\n  if (calendarSystem === 'jalali') {\n    const jalaliDay: Day = { year: day.year, month: day.month, day: day.day }\n    const gregorianDay = jalaliToGregorian(jalaliDay)\n    const date = new Date(\n      gregorianDay.year,\n      gregorianDay.month - 1,\n      gregorianDay.day\n    )\n    date.setDate(date.getDate() - daysToSubtract)\n    startDate = date\n  } else {\n    const date = new Date(day.year, day.month - 1, day.day)\n    date.setDate(date.getDate() - daysToSubtract)\n    startDate = date\n  }\n\n  // Calculate end of week (6 days after start)\n  const endDate = new Date(startDate)\n  endDate.setDate(endDate.getDate() + 6)\n\n  // Convert back to Day objects\n  const weekFrom = dateToDay(startDate, calendarSystem)\n  const weekTo = dateToDay(endDate, calendarSystem)\n\n  // Preserve time from the original day if it exists\n  if (day.hour !== undefined) {\n    weekFrom.hour = day.hour\n  }\n  if (day.minute !== undefined) {\n    weekFrom.minute = day.minute\n  }\n  // For end date, use the same time as start (or can be set separately)\n  if (day.hour !== undefined) {\n    weekTo.hour = day.hour\n  }\n  if (day.minute !== undefined) {\n    weekTo.minute = day.minute\n  }\n\n  return { from: weekFrom, to: weekTo }\n}\n\n/**\n * Get ISO week number for a given date (Gregorian only)\n * For Jalali, returns a simple week number within the year\n */\nexport function getWeekNumber(\n  day: Day,\n  calendarSystem: CalendarLocale\n): number {\n  if (calendarSystem === 'jalali') {\n    // For Jalali, calculate week number from start of year\n    // Note: weekStart is not available here, so we use default (Saturday for Jalali)\n    const defaultWeekStart = 6\n    const yearStart: Day = { year: day.year, month: 1, day: 1 }\n    const yearStartWeek = getWeekBounds(\n      yearStart,\n      calendarSystem,\n      defaultWeekStart\n    )\n    const currentWeek = getWeekBounds(day, calendarSystem, defaultWeekStart)\n\n    // Calculate difference in days\n    const startDate = dayToDate(yearStartWeek.from, calendarSystem)\n    const currentDate = dayToDate(currentWeek.from, calendarSystem)\n    const diffTime = currentDate.getTime() - startDate.getTime()\n    const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))\n    const weekNumber = Math.floor(diffDays / 7) + 1\n\n    return weekNumber\n  } else {\n    // ISO week number for Gregorian\n    const date = new Date(day.year, day.month - 1, day.day)\n    const d = new Date(\n      Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())\n    )\n    const dayNum = d.getUTCDay() || 7\n    d.setUTCDate(d.getUTCDate() + 4 - dayNum)\n    const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1))\n    return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)\n  }\n}\n","/**\n * Date comparison and manipulation utilities\n * Works with both Gregorian and Jalali calendars\n */\n\nimport type { Day, CalendarLocale, Range } from '../types'\nimport {\n  jalaliToGregorian,\n  gregorianToJalali,\n  dayToDate\n} from './date-conversion'\nimport { compareDays, getDaysInMonth } from './validation'\n\n/**\n * Check if day1 is before day2\n * @param day1 - First day to compare\n * @param day2 - Second day to compare\n * @param locale - Calendar locale of the days\n * @returns true if day1 is before day2\n */\nexport function isBefore(\n  day1: Day,\n  day2: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  return compareDays(day1, day2, calendarSystem) < 0\n}\n\n/**\n * Check if day1 is after day2\n * @param day1 - First day to compare\n * @param day2 - Second day to compare\n * @param locale - Calendar locale of the days\n * @returns true if day1 is after day2\n */\nexport function isAfter(\n  day1: Day,\n  day2: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  return compareDays(day1, day2, calendarSystem) > 0\n}\n\n/**\n * Check if day1 is the same as day2 (ignores time)\n * @param day1 - First day to compare\n * @param day2 - Second day to compare\n * @param locale - Calendar locale of the days\n * @returns true if both days are the same\n */\nexport function isSameDay(\n  day1: Day,\n  day2: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  return compareDays(day1, day2, calendarSystem) === 0\n}\n\n/**\n * Check if a day is between two other days (inclusive)\n * @param day - Day to check\n * @param start - Start day of the range\n * @param end - End day of the range\n * @param locale - Calendar locale of the days\n * @returns true if day is between start and end (inclusive)\n */\nexport function isBetween(\n  day: Day,\n  start: Day,\n  end: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  const comparison = compareDays(start, end, calendarSystem)\n  // If start is after end, swap them\n  if (comparison > 0) {\n    return (\n      compareDays(day, end, calendarSystem) >= 0 &&\n      compareDays(day, start, calendarSystem) <= 0\n    )\n  }\n  return (\n    compareDays(day, start, calendarSystem) >= 0 &&\n    compareDays(day, end, calendarSystem) <= 0\n  )\n}\n\n/**\n * Add days to a date\n * @param day - Day to add days to\n * @param days - Number of days to add (can be negative)\n * @param locale - Calendar locale\n * @returns New Day object with days added\n */\nexport function addDays(\n  day: Day,\n  days: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  const date = dayToDate(day, calendarSystem)\n  // Use UTC methods to maintain consistency with UTC date creation\n  date.setUTCDate(date.getUTCDate() + days)\n  // Extract UTC values directly to avoid timezone issues when reading back\n  const gregorianDay: Day = {\n    year: date.getUTCFullYear(),\n    month: date.getUTCMonth() + 1,\n    day: date.getUTCDate(),\n    hour: day.hour ?? 0,\n    minute: day.minute ?? 0\n  }\n\n  if (calendarSystem === 'jalali') {\n    return gregorianToJalali(gregorianDay)\n  }\n\n  return gregorianDay\n}\n\n/**\n * Subtract days from a date\n * @param day - Day to subtract days from\n * @param days - Number of days to subtract\n * @param locale - Calendar locale\n * @returns New Day object with days subtracted\n */\nexport function subtractDays(\n  day: Day,\n  days: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  return addDays(day, -days, calendarSystem)\n}\n\n/**\n * Add months to a date\n * @param day - Day to add months to\n * @param months - Number of months to add (can be negative)\n * @param locale - Calendar locale\n * @returns New Day object with months added\n */\nexport function addMonths(\n  day: Day,\n  months: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  if (calendarSystem === 'jalali') {\n    let { year, month, day: d } = day\n\n    // Calculate new total months\n    const totalMonths = year * 12 + (month - 1) + months\n    const newYear = Math.floor(totalMonths / 12)\n    const newMonth = (totalMonths % 12) + 1\n\n    // Handle days in month\n    const maxDay = getDaysInMonth(newYear, newMonth, calendarSystem)\n    const newDay = Math.min(d, maxDay)\n\n    return {\n      year: newYear,\n      month: newMonth,\n      day: newDay,\n      hour: day.hour || 0,\n      minute: day.minute || 0\n    }\n  }\n\n  const date = dayToDate(day, calendarSystem)\n  const originalDay = day.day\n\n  // Set day to 1 to avoid overflow when changing month\n  // Use UTC methods to maintain consistency with UTC date creation\n  date.setUTCDate(1)\n  date.setUTCMonth(date.getUTCMonth() + months)\n\n  // Get max days in the new month\n  // Note: For Gregorian, we use the standard Date behavior for month/year\n  const maxDay = getDaysInMonth(\n    date.getUTCFullYear(),\n    date.getUTCMonth() + 1,\n    calendarSystem\n  )\n\n  // Restore day, capped at maxDay\n  date.setUTCDate(Math.min(originalDay, maxDay))\n\n  // Extract UTC values directly to avoid timezone issues when reading back\n  const gregorianDay: Day = {\n    year: date.getUTCFullYear(),\n    month: date.getUTCMonth() + 1,\n    day: date.getUTCDate(),\n    hour: day.hour ?? 0,\n    minute: day.minute ?? 0\n  }\n\n  return gregorianDay\n}\n\n/**\n * Subtract months from a date\n * @param day - Day to subtract months from\n * @param months - Number of months to subtract\n * @param locale - Calendar locale\n * @returns New Day object with months subtracted\n */\nexport function subtractMonths(\n  day: Day,\n  months: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  return addMonths(day, -months, calendarSystem)\n}\n\n/**\n * Add years to a date\n * @param day - Day to add years to\n * @param years - Number of years to add (can be negative)\n * @param locale - Calendar locale\n * @returns New Day object with years added\n */\nexport function addYears(\n  day: Day,\n  years: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  if (calendarSystem === 'jalali') {\n    const newYear = day.year + years\n    const maxDay = getDaysInMonth(newYear, day.month, calendarSystem)\n    const newDay = Math.min(day.day, maxDay)\n\n    return {\n      ...day,\n      year: newYear,\n      day: newDay,\n      hour: day.hour || 0,\n      minute: day.minute || 0\n    }\n  }\n\n  const date = dayToDate(day, calendarSystem)\n  const originalDay = day.day\n\n  // Set day to 1 to avoid overflow when changing year (e.g. Feb 29)\n  // Use UTC methods to maintain consistency with UTC date creation\n  date.setUTCDate(1)\n  date.setUTCFullYear(date.getUTCFullYear() + years)\n\n  // Get max days in the new month/year\n  const maxDay = getDaysInMonth(\n    date.getUTCFullYear(),\n    date.getUTCMonth() + 1,\n    calendarSystem\n  )\n\n  // Restore day, capped at maxDay\n  date.setUTCDate(Math.min(originalDay, maxDay))\n\n  // Extract UTC values directly to avoid timezone issues when reading back\n  const gregorianDay: Day = {\n    year: date.getUTCFullYear(),\n    month: date.getUTCMonth() + 1,\n    day: date.getUTCDate(),\n    hour: day.hour ?? 0,\n    minute: day.minute ?? 0\n  }\n\n  return gregorianDay\n}\n\n/**\n * Subtract years from a date\n * @param day - Day to subtract years from\n * @param years - Number of years to subtract\n * @param locale - Calendar locale\n * @returns New Day object with years subtracted\n */\nexport function subtractYears(\n  day: Day,\n  years: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  return addYears(day, -years, calendarSystem)\n}\n\n/**\n * Get the difference in days between two dates\n * @param day1 - First day\n * @param day2 - Second day\n * @param locale - Calendar locale\n * @returns Number of days difference (positive if day1 is after day2)\n */\nexport function getDifferenceInDays(\n  day1: Day,\n  day2: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): number {\n  const d1 = calendarSystem === 'jalali' ? jalaliToGregorian(day1) : day1\n  const d2 = calendarSystem === 'jalali' ? jalaliToGregorian(day2) : day2\n\n  // Use UTC to avoid DST issues and ignore time components for pure day difference\n  const date1 = Date.UTC(d1.year, d1.month - 1, d1.day)\n  const date2 = Date.UTC(d2.year, d2.month - 1, d2.day)\n\n  const diffTime = date1 - date2\n  return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Get the difference in months between two dates\n * @param day1 - First day\n * @param day2 - Second day\n * @param locale - Calendar locale\n * @returns Number of months difference (positive if day1 is after day2)\n */\nexport function getDifferenceInMonths(\n  day1: Day,\n  day2: Day,\n  _calendarSystem: CalendarLocale = 'gregorian'\n): number {\n  // If locale is 'jalali', we don't need to convert to Gregorian\n  // We can calculate the difference directly using Jalali dates\n  // This avoids issues with leap year mismatches during conversion\n  const yearDiff = day1.year - day2.year\n  const monthDiff = day1.month - day2.month\n\n  return yearDiff * 12 + monthDiff\n}\n\n/**\n * Get the difference in years between two dates\n * @param day1 - First day\n * @param day2 - Second day\n * @param locale - Calendar locale\n * @returns Number of years difference (positive if day1 is after day2)\n */\nexport function getDifferenceInYears(\n  day1: Day,\n  day2: Day,\n  _calendarSystem: CalendarLocale = 'gregorian'\n): number {\n  // If locale is 'jalali', we don't need to convert to Gregorian\n  // We can calculate the difference directly using Jalali dates\n  let yearDiff = day1.year - day2.year\n\n  // Adjust if the month/day hasn't been reached yet\n  if (\n    day1.month < day2.month ||\n    (day1.month === day2.month && day1.day < day2.day)\n  ) {\n    yearDiff--\n  }\n\n  return yearDiff\n}\n\n/**\n * Convert a Gregorian date to Jalali\n * Alias for gregorianToJalali for convenience\n * @param day - Day object in Gregorian calendar\n * @returns Day object in Jalali calendar\n */\nexport function convertToJalali(day: Day): Day {\n  return gregorianToJalali(day)\n}\n\n/**\n * Convert a Jalali date to Gregorian\n * Alias for jalaliToGregorian for convenience\n * @param day - Day object in Jalali calendar\n * @returns Day object in Gregorian calendar\n */\nexport function convertToGregorian(day: Day): Day {\n  return jalaliToGregorian(day)\n}\n\n/**\n * Get the start of day (sets time to 00:00)\n * @param day - Day object\n * @returns Day object with hour and minute set to 0\n */\nexport function startOfDay(day: Day): Day {\n  return {\n    ...day,\n    hour: 0,\n    minute: 0\n  }\n}\n\n/**\n * Get the end of day (sets time to 23:59)\n * @param day - Day object\n * @returns Day object with hour set to 23 and minute set to 59\n */\nexport function endOfDay(day: Day): Day {\n  return {\n    ...day,\n    hour: 23,\n    minute: 59\n  }\n}\n\n/**\n * Get the start of month (first day of the month)\n * @param day - Day object\n * @param _locale - Calendar locale (unused, kept for API consistency)\n * @returns Day object representing the first day of the month\n */\nexport function startOfMonth(\n  day: Day,\n  _calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  return {\n    ...day,\n    day: 1,\n    hour: 0,\n    minute: 0\n  }\n}\n\n/**\n * Get the end of month (last day of the month)\n * @param day - Day object\n * @param locale - Calendar locale\n * @returns Day object representing the last day of the month\n */\nexport function endOfMonth(\n  day: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  const daysInMonth = getDaysInMonth(day.year, day.month, calendarSystem)\n  return {\n    ...day,\n    day: daysInMonth,\n    hour: 23,\n    minute: 59\n  }\n}\n\n/**\n * Get the start of year (first day of the year)\n * @param day - Day object\n * @returns Day object representing the first day of the year\n */\nexport function startOfYear(day: Day): Day {\n  return {\n    ...day,\n    month: 1,\n    day: 1,\n    hour: 0,\n    minute: 0\n  }\n}\n\n/**\n * Get the end of year (last day of the year)\n * @param day - Day object\n * @param locale - Calendar locale\n * @returns Day object representing the last day of the year\n */\nexport function endOfYear(\n  day: Day,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  const daysInMonth = getDaysInMonth(day.year, 12, calendarSystem)\n  return {\n    ...day,\n    month: 12,\n    day: daysInMonth,\n    hour: 23,\n    minute: 59\n  }\n}\n\n/**\n * Check if two days are in the same month\n * @param day1 - First day to compare\n * @param day2 - Second day to compare\n * @returns true if both days are in the same month and year\n */\nexport function isSameMonth(day1: Day, day2: Day): boolean {\n  return day1.year === day2.year && day1.month === day2.month\n}\n\n/**\n * Check if two days are in the same year\n * @param day1 - First day to compare\n * @param day2 - Second day to compare\n * @returns true if both days are in the same year\n */\nexport function isSameYear(day1: Day, day2: Day): boolean {\n  return day1.year === day2.year\n}\n\n/**\n * Get the start of week for a given day\n * @param day - Day object\n * @param weekStart - First day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)\n * @param locale - Calendar locale\n * @returns Day object representing the first day of the week\n */\nexport function getStartOfWeek(\n  day: Day,\n  weekStart: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  const date = dayToDate(day, calendarSystem)\n  const dayOfWeek = date.getDay() // 0 = Sunday, 6 = Saturday\n\n  // Calculate days to subtract to get to the start of week\n  let daysToSubtract = (dayOfWeek - weekStart + 7) % 7\n\n  return subtractDays(day, daysToSubtract, calendarSystem)\n}\n\n/**\n * Get the end of week for a given day\n * @param day - Day object\n * @param weekStart - First day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)\n * @param locale - Calendar locale\n * @returns Day object representing the last day of the week\n */\nexport function getEndOfWeek(\n  day: Day,\n  weekStart: number,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day {\n  const startOfWeek = getStartOfWeek(day, weekStart, calendarSystem)\n  // Add 6 days to get to the end of the week (7 days total, starting from day 0)\n  return addDays(startOfWeek, 6, calendarSystem)\n}\n\n/**\n * Get all days in a date range (inclusive)\n * @param range - Date range with from and to dates\n * @param locale - Calendar locale\n * @returns Array of Day objects from start to end (inclusive)\n */\nexport function getDaysInRange(\n  range: Range,\n  calendarSystem: CalendarLocale = 'gregorian'\n): Day[] {\n  const { from, to } = range\n\n  // If to is null, return only the from date\n  if (!to) {\n    return [{ ...from }]\n  }\n\n  // Determine which date is earlier\n  const comparison = compareDays(from, to, calendarSystem)\n  const start = comparison <= 0 ? from : to\n  const end = comparison <= 0 ? to : from\n\n  const days: Day[] = []\n  let current: Day = { ...start }\n\n  // Add days until we reach the end date (inclusive)\n  while (compareDays(current, end, calendarSystem) <= 0) {\n    days.push({ ...current })\n    current = addDays(current, 1, calendarSystem)\n  }\n\n  return days\n}\n","/**\n * Preset date range utilities\n * Calculate common date ranges for quick selection\n */\n\nimport type { Range, CalendarLocale } from '../types'\nimport { getToday } from './date-conversion'\nimport {\n  startOfMonth,\n  endOfMonth,\n  subtractMonths,\n  subtractDays\n} from './date-comparison'\n\nexport type PresetRangeType =\n  | 'yesterday'\n  | 'last7days'\n  | 'last30days'\n  | 'thisMonth'\n  | 'lastMonth'\n\nexport interface PresetRange {\n  label: string\n  value: PresetRangeType | 'custom'\n  range: Range\n}\n\n/**\n * Calculate preset date ranges\n */\nexport function getPresetRange(\n  preset: PresetRangeType,\n  calendarSystem: CalendarLocale\n): Range {\n  const today = getToday(calendarSystem)\n  // Ensure time is preserved or set to current time\n  // getToday already returns current time in local day\n\n  switch (preset) {\n    case 'yesterday': {\n      const yesterday = subtractDays(today, 1, calendarSystem)\n      return {\n        from: yesterday,\n        to: yesterday\n      }\n    }\n\n    case 'last7days': {\n      const sevenDaysAgo = subtractDays(today, 6, calendarSystem)\n      return {\n        from: sevenDaysAgo,\n        to: today\n      }\n    }\n\n    case 'last30days': {\n      const thirtyDaysAgo = subtractDays(today, 29, calendarSystem)\n      return {\n        from: thirtyDaysAgo,\n        to: today\n      }\n    }\n\n    case 'thisMonth': {\n      const firstDay = startOfMonth(today, calendarSystem)\n      const lastDay = endOfMonth(today, calendarSystem)\n\n      // Preserve time from today if needed, or default to start/end of day\n      // Currently getPresetRange implementation returned today's time for end dates\n      // But startOfMonth sets time to 00:00.\n      // Let's match previous behavior: from has 00:00 (via startOfMonth logic? No, prev impl used dateToDay(new Date(y, m, 1)))\n      // Wait, dateToDay(new Date(y, m, 1)) sets time to 00:00 implicitly if not provided.\n      // The previous implementation used `todayDate` time for end dates in 'last7days' etc.\n      // For 'thisMonth', it used `new Date(y, m, 1)` -> 00:00.\n\n      // Let's check startOfMonth implementation in date-comparison.ts\n      // It sets hour: 0, minute: 0.\n\n      return {\n        from: firstDay,\n        to: lastDay\n      }\n    }\n\n    case 'lastMonth': {\n      const lastMonthToday = subtractMonths(today, 1, calendarSystem)\n      const firstDay = startOfMonth(lastMonthToday, calendarSystem)\n      const lastDay = endOfMonth(lastMonthToday, calendarSystem)\n\n      return {\n        from: firstDay,\n        to: lastDay\n      }\n    }\n\n    default:\n      return {\n        from: today,\n        to: today\n      }\n  }\n}\n\n/**\n * Get default label for a preset range type\n */\nexport function getPresetLabel(\n  preset: PresetRangeType,\n  presetRanges: Record<PresetRangeType, string>\n): string {\n  return presetRanges[preset]\n}\n\n/**\n * Get preset ranges based on configuration\n */\nexport function getPresetRangesFromConfig(\n  config: import('../types/calendar').PresetRangesConfig,\n  calendarSystem: CalendarLocale,\n  presetRanges: Record<PresetRangeType, string>\n): PresetRange[] {\n  if (!config) {\n    return []\n  }\n\n  const presets: PresetRange[] = []\n  const allPresetTypes: PresetRangeType[] = [\n    'yesterday',\n    'last7days',\n    'last30days',\n    'thisMonth',\n    'lastMonth'\n  ]\n\n  allPresetTypes.forEach((presetType) => {\n    const configValue = config[presetType]\n    if (configValue === true) {\n      const label = getPresetLabel(presetType, presetRanges)\n      presets.push({\n        label,\n        value: presetType,\n        range: getPresetRange(presetType, calendarSystem)\n      })\n    }\n  })\n\n  // Add custom preset ranges if provided\n  if (config.custom && Array.isArray(config.custom)) {\n    config.custom.forEach((customPreset) => {\n      presets.push({\n        label: customPreset.label,\n        value: 'custom' as const,\n        range: {\n          from: customPreset.range.from,\n          to: customPreset.range.to\n        }\n      })\n    })\n  }\n\n  return presets\n}\n\n/**\n * Check if a preset range matches the current selected range\n */\nexport function isPresetRangeActive(\n  presetRange: Range,\n  selectedRange: Range | null,\n  _calendarSystem: CalendarLocale\n): boolean {\n  if (!selectedRange || !selectedRange.from || !selectedRange.to) {\n    return false\n  }\n\n  // If preset range doesn't have a to date, it can't match\n  if (!presetRange.to) {\n    return false\n  }\n\n  // Compare dates ignoring time\n  const presetFrom = presetRange.from\n  const presetTo = presetRange.to\n  const selectedFrom = selectedRange.from\n  const selectedTo = selectedRange.to\n\n  return (\n    presetFrom.year === selectedFrom.year &&\n    presetFrom.month === selectedFrom.month &&\n    presetFrom.day === selectedFrom.day &&\n    presetTo.year === selectedTo.year &&\n    presetTo.month === selectedTo.month &&\n    presetTo.day === selectedTo.day\n  )\n}\n","/**\n * Utility functions for weekday operations, week start handling, and weekend detection\n * Centralizes logic for calendar systems (Gregorian/Jalali) and week start configurations\n */\n\nimport type { CalendarLocale } from '../types'\n\n/**\n * Get the effective first day of the week based on calendar system and user preference\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @param weekStart - Optional explicit week start day (0-6). If not provided, uses calendar system defaults.\n * @returns The first day of the week (0 = Sunday, 6 = Saturday)\n */\nexport function getEffectiveWeekStart(\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n): number {\n  // If weekStart is explicitly provided, use it\n  if (weekStart !== undefined) {\n    return weekStart\n  }\n  // Otherwise, default based on calendar system\n  // Gregorian: Sunday (0), Jalali: Saturday (6)\n  return calendarSystem === 'jalali' ? 6 : 0\n}\n\n/**\n * Rotate an array so that the specified start index becomes position 0\n * @param array - The array to rotate\n * @param startIndex - The index that should become the first element\n * @returns The rotated array\n */\nexport function rotateArray<T>(array: T[], startIndex: number): T[] {\n  if (startIndex === 0) {\n    return [...array]\n  }\n  const rotated = [...array]\n  const moved = rotated.splice(0, startIndex)\n  return [...rotated, ...moved]\n}\n\n/**\n * Get the Gregorian day of week (0-6) for a given position in a rotated weekday array\n * @param position - The position in the rotated array (0-6)\n * @param effectiveWeekStart - The effective week start day (0-6)\n * @returns The corresponding Gregorian day of week (0 = Sunday, 6 = Saturday)\n */\nexport function getGregorianDayOfWeek(\n  position: number,\n  effectiveWeekStart: number\n): number {\n  return (effectiveWeekStart + position) % 7\n}\n\n/**\n * Check if a Gregorian day of week is considered a weekend for the given calendar system\n * @param gregorianDayOfWeek - Gregorian day of week (0 = Sunday, 6 = Saturday)\n * @param calendarSystem - The calendar system\n * @returns True if the day is a weekend\n */\nexport function isWeekendDay(\n  gregorianDayOfWeek: number,\n  calendarSystem: CalendarLocale\n): boolean {\n  if (calendarSystem === 'jalali') {\n    // In Jalali calendar, weekends are Thursday (4) and Friday (5)\n    return gregorianDayOfWeek === 4 || gregorianDayOfWeek === 5\n  } else {\n    // In Gregorian calendar, weekends are Saturday (6) and Sunday (0)\n    return gregorianDayOfWeek === 0 || gregorianDayOfWeek === 6\n  }\n}\n\n/**\n * Get weekend positions in a rotated weekday array\n * @param calendarSystem - The calendar system\n * @param effectiveWeekStart - The effective week start day (0-6)\n * @returns Array of positions (0-6) that are weekends in the rotated array\n */\nexport function getWeekendPositions(\n  calendarSystem: CalendarLocale,\n  effectiveWeekStart: number\n): number[] {\n  const positions: number[] = []\n  for (let position = 0; position < 7; position++) {\n    const gregorianDay = getGregorianDayOfWeek(position, effectiveWeekStart)\n    if (isWeekendDay(gregorianDay, calendarSystem)) {\n      positions.push(position)\n    }\n  }\n  return positions\n}\n\n/**\n * Rotate weekday names according to week start and calendar system\n * Note: weekdayNames are assumed to be in Gregorian order (Sunday first)\n * @param weekdayNames - The weekday names array in Gregorian order (7 elements)\n * @param calendarSystem - The calendar system\n * @param weekStart - Optional explicit week start day\n * @returns The rotated weekday names array\n */\nexport function getRotatedWeekdayNames(\n  weekdayNames: string[],\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n): string[] {\n  const effectiveWeekStart = getEffectiveWeekStart(calendarSystem, weekStart)\n  return rotateArray(weekdayNames, effectiveWeekStart)\n}\n\n/**\n * Get weekend information for weekday rendering\n * @param calendarSystem - The calendar system\n * @param weekStart - Optional explicit week start day\n * @returns Object with weekend positions and effective week start\n */\nexport function getWeekendConfig(\n  calendarSystem: CalendarLocale,\n  weekStart?: number\n) {\n  const effectiveWeekStart = getEffectiveWeekStart(calendarSystem, weekStart)\n  const weekendPositions = getWeekendPositions(\n    calendarSystem,\n    effectiveWeekStart\n  )\n\n  return {\n    effectiveWeekStart,\n    weekendPositions,\n    isWeekend: (position: number) => weekendPositions.includes(position)\n  }\n}\n","/**\n * Calendar Header Component\n * Reusable header with navigation buttons and month/year display\n */\n\nimport React from 'react'\nimport type { Day, CalendarLocale, CalendarTranslations } from '../types'\nimport type { CalendarCustomization } from '../types/calendar'\nimport { formatNumber } from '../utils/formatting'\n\n// Default Chevron Icons\nconst ChevronLeftIcon = ({ className }: { className?: string }) => (\n  <svg\n    className={className}\n    width='16'\n    height='16'\n    viewBox='0 0 16 16'\n    fill='none'\n    xmlns='http://www.w3.org/2000/svg'\n  >\n    <path\n      d='M10 12L6 8L10 4'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n    />\n  </svg>\n)\n\nconst ChevronRightIcon = ({ className }: { className?: string }) => (\n  <svg\n    className={className}\n    width='16'\n    height='16'\n    viewBox='0 0 16 16'\n    fill='none'\n    xmlns='http://www.w3.org/2000/svg'\n  >\n    <path\n      d='M6 12L10 8L6 4'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n    />\n  </svg>\n)\n\nexport interface CalendarHeaderProps {\n  /** Currently displayed month */\n  displayMonth: Day\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Customization options */\n  customization?: CalendarCustomization\n  /** Callback when previous button is clicked */\n  onPrevious: () => void\n  /** Callback when next button is clicked */\n  onNext: () => void\n  /** Callback when month button is clicked */\n  onMonthClick?: () => void\n  /** Callback when year button is clicked */\n  onYearClick?: () => void\n  /** Previous button title */\n  previousTitle?: string\n  /** Next button title */\n  nextTitle?: string\n  /** Show year button (default: true) */\n  showYear?: boolean\n  /** Show month button (default: true) */\n  showMonth?: boolean\n}\n\nexport const CalendarHeader: React.FC<CalendarHeaderProps> = (props) => {\n  const {\n    displayMonth,\n    calendarSystem: _calendarSystem, // Kept for backward compatibility but not used\n    translations,\n    customization = {},\n    onPrevious,\n    onNext,\n    onMonthClick,\n    onYearClick,\n    previousTitle,\n    nextTitle,\n    showYear = true,\n    showMonth = true\n  } = props\n\n  const { classes = {}, icons = {} } = customization\n  const { header: headerClass } = classes\n  const { next: NextBtnIcon, previous: PreviousBtnIcon } = icons\n\n  const monthNames = translations.months\n\n  // Use translations for button titles if not provided\n  const actualPreviousTitle = previousTitle || translations.labels.previousMonth\n  const actualNextTitle = nextTitle || translations.labels.nextMonth\n\n  return (\n    <div className={`calendar-header ${headerClass || ''}`}>\n      <button\n        type='button'\n        onClick={onPrevious}\n        title={actualPreviousTitle}\n        className='calendar-nav-btn calendar-nav-prev'\n      >\n        {PreviousBtnIcon ? (\n          <PreviousBtnIcon className='calendar-nav-icon' />\n        ) : (\n          <ChevronLeftIcon className='calendar-nav-icon' />\n        )}\n      </button>\n\n      <div className='calendar-month-year-btn'>\n        {showMonth &&\n          (onMonthClick ? (\n            <button\n              type='button'\n              onClick={onMonthClick}\n              className='calendar-month-btn'\n            >\n              {monthNames[displayMonth.month - 1]}\n            </button>\n          ) : (\n            <div className='calendar-month-btn' style={{ cursor: 'default' }}>\n              {monthNames[displayMonth.month - 1]}\n            </div>\n          ))}\n        {showYear &&\n          (onYearClick ? (\n            <button\n              type='button'\n              onClick={onYearClick}\n              className='calendar-year-btn'\n            >\n              {formatNumber(displayMonth.year, translations.numbers)}\n            </button>\n          ) : (\n            <div className='calendar-year-btn' style={{ cursor: 'default' }}>\n              {formatNumber(displayMonth.year, translations.numbers)}\n            </div>\n          ))}\n      </div>\n\n      {onNext ? (\n        <button\n          type='button'\n          onClick={onNext}\n          title={actualNextTitle}\n          className='calendar-nav-btn calendar-nav-next'\n        >\n          {NextBtnIcon ? (\n            <NextBtnIcon className='calendar-nav-icon' />\n          ) : (\n            <ChevronRightIcon className='calendar-nav-icon' />\n          )}\n        </button>\n      ) : (\n        <div\n          className='calendar-nav-btn calendar-nav-next'\n          style={{ visibility: 'hidden' }}\n        />\n      )}\n    </div>\n  )\n}\n\nCalendarHeader.displayName = 'CalendarHeader'\n","/**\n * Time Selector Component\n * Allows users to select hour and minute values\n */\n\nimport React from 'react'\nimport type { Day, CalendarTranslations } from '../types'\nimport { toPersianNumeral } from '../utils/formatting'\n\n// 🟢 Pre-computed static arrays to avoid recreation on every render\nconst HOUR_OPTIONS_24 = Array.from({ length: 24 }, (_, i) => i)\nconst HOUR_OPTIONS_12 = Array.from({ length: 12 }, (_, i) => i + 1)\nconst MINUTE_OPTIONS = Array.from({ length: 60 }, (_, i) => i)\n\nexport interface TimeSelectorProps {\n  /** Current day value */\n  day: Day | null\n  /** Time format: '12' for 12-hour format, '24' for 24-hour format */\n  timeFormat: '12' | '24'\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Label for the time selector */\n  label?: string\n  /** Whether the time selector is disabled */\n  disabled?: boolean\n  /** Callback when time changes */\n  onTimeChange: (hour: number, minute: number) => void\n}\n\nconst TimeSelectorInner: React.FC<TimeSelectorProps> = (props) => {\n  const {\n    day,\n    timeFormat,\n    translations,\n    label,\n    disabled = false,\n    onTimeChange\n  } = props\n\n  // Get current hour and minute, default to 0 if not set\n  const currentHour = day?.hour ?? 0\n  const currentMinute = day?.minute ?? 0\n\n  // For 12-hour format, convert to 12-hour display (1-12) and track AM/PM\n  const is24Hour = timeFormat === '24'\n  const displayHour = is24Hour\n    ? currentHour\n    : currentHour === 0\n      ? 12\n      : currentHour > 12\n        ? currentHour - 12\n        : currentHour\n  const isPM = !is24Hour && currentHour >= 12\n\n  // 🟢 Use pre-computed static arrays instead of creating on every render\n  const hourOptions = is24Hour ? HOUR_OPTIONS_24 : HOUR_OPTIONS_12\n  const minuteOptions = MINUTE_OPTIONS\n\n  const handleHourChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    const selectedDisplayHour = parseInt(e.target.value, 10)\n    let newHour: number\n\n    if (is24Hour) {\n      newHour = selectedDisplayHour\n    } else {\n      // Convert 12-hour format back to 24-hour format\n      if (selectedDisplayHour === 12) {\n        newHour = isPM ? 12 : 0\n      } else {\n        newHour = isPM ? selectedDisplayHour + 12 : selectedDisplayHour\n      }\n    }\n\n    onTimeChange(newHour, currentMinute)\n  }\n\n  const handleMinuteChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    const newMinute = parseInt(e.target.value, 10)\n    onTimeChange(currentHour, newMinute)\n  }\n\n  const handleAMPMChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    const newIsPM = e.target.value === 'PM'\n    let newHour: number\n\n    if (displayHour === 12) {\n      newHour = newIsPM ? 12 : 0\n    } else {\n      newHour = newIsPM ? displayHour + 12 : displayHour\n    }\n\n    onTimeChange(newHour, currentMinute)\n  }\n\n  const formatNumber = (num: number): string => {\n    const str = num.toString().padStart(2, '0')\n    return translations.numbers === 'persian' ? toPersianNumeral(str) : str\n  }\n\n  return (\n    <div\n      className={`time-selector ${disabled ? 'time-selector-disabled' : ''}`}\n    >\n      {label && <label className='time-selector-label'>{label}</label>}\n      <div className='time-selector-inputs'>\n        {/* Hour selector */}\n        <select\n          className='time-selector-hour'\n          value={displayHour}\n          onChange={handleHourChange}\n          disabled={disabled}\n          aria-label='Hour'\n        >\n          {hourOptions.map((hour) => (\n            <option key={hour} value={hour}>\n              {formatNumber(hour)}\n            </option>\n          ))}\n        </select>\n\n        <span className='time-selector-separator'>:</span>\n\n        {/* Minute selector */}\n        <select\n          className='time-selector-minute'\n          value={currentMinute}\n          onChange={handleMinuteChange}\n          disabled={disabled}\n          aria-label='Minute'\n        >\n          {minuteOptions.map((minute) => (\n            <option key={minute} value={minute}>\n              {formatNumber(minute)}\n            </option>\n          ))}\n        </select>\n\n        {/* AM/PM selector (only for 12-hour format) */}\n        {!is24Hour && (\n          <select\n            className='time-selector-ampm'\n            value={isPM ? 'PM' : 'AM'}\n            onChange={handleAMPMChange}\n            disabled={disabled}\n            aria-label='AM/PM'\n          >\n            <option value='AM'>{translations.labels.am}</option>\n            <option value='PM'>{translations.labels.pm}</option>\n          </select>\n        )}\n      </div>\n    </div>\n  )\n}\n\n// 🟢 Memoize component to prevent unnecessary re-renders\nexport const TimeSelector = React.memo(\n  TimeSelectorInner,\n  (prevProps, nextProps) => {\n    // Return TRUE if props are equal (skip re-render)\n    // Return FALSE if props differ (re-render needed)\n    return (\n      prevProps.day === nextProps.day &&\n      prevProps.timeFormat === nextProps.timeFormat &&\n      prevProps.translations === nextProps.translations &&\n      prevProps.label === nextProps.label &&\n      prevProps.disabled === nextProps.disabled &&\n      prevProps.onTimeChange === nextProps.onTimeChange\n    )\n  }\n)\n\nTimeSelector.displayName = 'TimeSelector'\n","/**\n * Internationalization translations for calendar component\n * Refactored for better maintainability, performance, and extensibility\n */\n\nimport type { CalendarTranslations, CalendarUILocale } from '../types/calendar'\n\n// ============================================================================\n// TRANSLATION CONSTANTS\n// ============================================================================\n\n/**\n * Month names - Gregorian\n */\nexport const gregorianMonths = {\n  en: [\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  fa: [\n    'ژانویه',\n    'فوریه',\n    'مارس',\n    'آوریل',\n    'مه',\n    'ژوئن',\n    'ژوئیه',\n    'اوت',\n    'سپتامبر',\n    'اکتبر',\n    'نوامبر',\n    'دسامبر'\n  ],\n  de: [\n    'Januar',\n    'Februar',\n    'März',\n    'April',\n    'Mai',\n    'Juni',\n    'Juli',\n    'August',\n    'September',\n    'Oktober',\n    'November',\n    'Dezember'\n  ],\n  es: [\n    'Enero',\n    'Febrero',\n    'Marzo',\n    'Abril',\n    'Mayo',\n    'Junio',\n    'Julio',\n    'Agosto',\n    'Septiembre',\n    'Octubre',\n    'Noviembre',\n    'Diciembre'\n  ],\n  fr: [\n    'Janvier',\n    'Février',\n    'Mars',\n    'Avril',\n    'Mai',\n    'Juin',\n    'Juillet',\n    'Août',\n    'Septembre',\n    'Octobre',\n    'Novembre',\n    'Décembre'\n  ],\n  ko: [\n    '1월',\n    '2월',\n    '3월',\n    '4월',\n    '5월',\n    '6월',\n    '7월',\n    '8월',\n    '9월',\n    '10월',\n    '11월',\n    '12월'\n  ]\n}\n\n/**\n * Month names - Jalali/Persian\n */\nexport const jalaliMonths = {\n  fa: [\n    'فروردین',\n    'اردیبهشت',\n    'خرداد',\n    'تیر',\n    'مرداد',\n    'شهریور',\n    'مهر',\n    'آبان',\n    'آذر',\n    'دی',\n    'بهمن',\n    'اسفند'\n  ],\n  en: [\n    'Farvardin',\n    'Ordibehesht',\n    'Khordad',\n    'Tir',\n    'Mordad',\n    'Shahrivar',\n    'Mehr',\n    'Aban',\n    'Azar',\n    'Dey',\n    'Bahman',\n    'Esfand'\n  ]\n}\n\n/**\n * Weekday names\n */\nconst weekdayNames = {\n  en: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n  fa: ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'],\n  de: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],\n  es: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'],\n  fr: ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa'],\n  ko: ['일', '월', '화', '수', '목', '금', '토']\n}\n\n/**\n * Translation labels\n */\nconst translationLabels = {\n  en: {\n    today: 'Today',\n    clear: 'Clear',\n    ok: 'OK',\n    nextMonth: 'next',\n    previousMonth: 'previous',\n    selectMonth: 'Select month',\n    selectYear: 'Select year',\n    from: 'From',\n    to: 'To',\n    timeFrom: 'From',\n    timeTo: 'To',\n    am: 'AM',\n    pm: 'PM'\n  },\n  fa: {\n    today: 'امروز',\n    clear: 'پاک کردن',\n    ok: 'تایید',\n    nextMonth: 'بعدی',\n    previousMonth: 'قبلی',\n    selectMonth: 'انتخاب ماه',\n    selectYear: 'انتخاب سال',\n    from: 'از',\n    to: 'تا',\n    timeFrom: 'از',\n    timeTo: 'تا',\n    am: 'ق.ظ',\n    pm: 'ب.ظ'\n  },\n  de: {\n    today: 'Heute',\n    clear: 'Löschen',\n    ok: 'OK',\n    nextMonth: 'nächster',\n    previousMonth: 'vorheriger',\n    selectMonth: 'Monat auswählen',\n    selectYear: 'Jahr auswählen',\n    from: 'Von',\n    to: 'Bis',\n    timeFrom: 'Von',\n    timeTo: 'Bis',\n    am: 'AM',\n    pm: 'PM'\n  },\n  es: {\n    today: 'Hoy',\n    clear: 'Limpiar',\n    ok: 'OK',\n    nextMonth: 'siguiente',\n    previousMonth: 'anterior',\n    selectMonth: 'Seleccionar mes',\n    selectYear: 'Seleccionar año',\n    from: 'Desde',\n    to: 'Hasta',\n    timeFrom: 'Desde',\n    timeTo: 'Hasta',\n    am: 'AM',\n    pm: 'PM'\n  },\n  fr: {\n    today: \"Aujourd'hui\",\n    clear: 'Effacer',\n    ok: 'OK',\n    nextMonth: 'suivant',\n    previousMonth: 'précédent',\n    selectMonth: 'Sélectionner mois',\n    selectYear: 'Sélectionner année',\n    from: 'De',\n    to: 'À',\n    timeFrom: 'De',\n    timeTo: 'À',\n    am: 'AM',\n    pm: 'PM'\n  },\n  ko: {\n    today: '오늘',\n    clear: '지우기',\n    ok: '확인',\n    nextMonth: '다음',\n    previousMonth: '이전',\n    selectMonth: '월 선택',\n    selectYear: '연도 선택',\n    from: '시작',\n    to: '종료',\n    timeFrom: '시작',\n    timeTo: '종료',\n    am: '오전',\n    pm: '오후'\n  }\n}\n\n/**\n * Preset ranges translation\n */\nconst presetRangesLabels = {\n  en: {\n    yesterday: 'Yesterday',\n    last7days: 'Last 7 days',\n    last30days: 'Last 30 days',\n    thisMonth: 'This month',\n    lastMonth: 'Last month'\n  },\n  fa: {\n    yesterday: 'دیروز',\n    last7days: '۷ روز گذشته',\n    last30days: '۳۰ روز گذشته',\n    thisMonth: 'این ماه',\n    lastMonth: 'ماه گذشته'\n  },\n  de: {\n    yesterday: 'Gestern',\n    last7days: 'Letzte 7 Tage',\n    last30days: 'Letzte 30 Tage',\n    thisMonth: 'Dieser Monat',\n    lastMonth: 'Letzter Monat'\n  },\n  es: {\n    yesterday: 'Ayer',\n    last7days: 'Últimos 7 días',\n    last30days: 'Últimos 30 días',\n    thisMonth: 'Este mes',\n    lastMonth: 'Mes pasado'\n  },\n  fr: {\n    yesterday: 'Hier',\n    last7days: '7 derniers jours',\n    last30days: '30 derniers jours',\n    thisMonth: 'Ce mois',\n    lastMonth: 'Mois dernier'\n  },\n  ko: {\n    yesterday: '어제',\n    last7days: '최근 7일',\n    last30days: '최근 30일',\n    thisMonth: '이번 달',\n    lastMonth: '지난 달'\n  }\n}\n\n// ============================================================================\n// LOCALE CONFIGURATION\n// ============================================================================\n\n/**\n * Locale configuration with direction and number system\n */\nconst localeConfig = {\n  en: { direction: 'ltr' as const, numberSystem: 'latin' as const },\n  fa: { direction: 'rtl' as const, numberSystem: 'persian' as const },\n  de: { direction: 'ltr' as const, numberSystem: 'latin' as const },\n  es: { direction: 'ltr' as const, numberSystem: 'latin' as const },\n  fr: { direction: 'ltr' as const, numberSystem: 'latin' as const },\n  ko: { direction: 'ltr' as const, numberSystem: 'latin' as const }\n}\n\n/**\n * LTR (Left-to-Right) locales\n */\nexport const ltrLocales: string[] = ['en', 'de', 'es', 'fr', 'ko']\n\n/**\n * RTL (Right-to-Left) locales\n */\nexport const rtlLocales: string[] = ['fa']\n\n// ============================================================================\n// DYNAMIC TRANSLATION FACTORY\n// ============================================================================\n\n/**\n * Create a translation object for a given locale\n * @param locale - The locale code\n * @returns The translation object for the locale\n */\nfunction createTranslation(\n  locale: keyof typeof localeConfig\n): CalendarTranslations {\n  const config = localeConfig[locale]\n  const labels = translationLabels[locale as keyof typeof translationLabels]\n  const presets = presetRangesLabels[locale as keyof typeof presetRangesLabels]\n  // For Persian locale, default to Jalali months; for others, use Gregorian\n  const months =\n    locale === 'fa'\n      ? jalaliMonths.fa\n      : gregorianMonths[locale as keyof typeof gregorianMonths]\n  const weekdays = weekdayNames[locale as keyof typeof weekdayNames]\n\n  return {\n    months,\n    weekdays,\n    direction: config.direction,\n    numbers: config.numberSystem,\n    labels,\n    presetRanges: presets\n  }\n}\n\n// ============================================================================\n// MEMOIZED TRANSLATIONS MAP\n// ============================================================================\n\n/**\n * Map of all translations (created once for performance)\n */\nexport const translations: Record<string, CalendarTranslations> = {\n  en: createTranslation('en'),\n  fa: createTranslation('fa'),\n  de: createTranslation('de'),\n  es: createTranslation('es'),\n  fr: createTranslation('fr'),\n  ko: createTranslation('ko')\n}\n\n// ============================================================================\n// BACKWARD COMPATIBILITY EXPORTS\n// ============================================================================\n\n/**\n * English translations (default)\n */\nexport const enTranslations: CalendarTranslations = translations.en\n\n/**\n * Persian/Farsi translations\n */\nexport const faTranslations: CalendarTranslations = translations.fa\n\n/**\n * German translations\n */\nexport const deTranslations: CalendarTranslations = translations.de\n\n/**\n * Spanish translations\n */\nexport const esTranslations: CalendarTranslations = translations.es\n\n/**\n * French translations\n */\nexport const frTranslations: CalendarTranslations = translations.fr\n\n/**\n * Korean translations\n */\nexport const koTranslations: CalendarTranslations = translations.ko\n\n/**\n * English transliterations of Jalali month names\n */\nexport const jalaliEnglishMonths: string[] = [...jalaliMonths.en]\n\n/**\n * Persian translations of Gregorian month names\n */\nexport const gregorianPersianMonths: string[] = [...gregorianMonths.fa]\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Get text direction for a locale\n * @param locale - The locale code\n * @returns 'ltr' or 'rtl'\n */\nexport function getTextDirection(locale: string): 'ltr' | 'rtl' {\n  return rtlLocales.includes(locale) ? 'rtl' : 'ltr'\n}\n\n/**\n * Get number system for a locale\n * @param locale - The locale code\n * @returns 'latin' or 'persian'\n */\nexport function getNumberSystem(\n  locale: CalendarUILocale | string\n): 'latin' | 'persian' {\n  return (\n    localeConfig[locale as keyof typeof localeConfig]?.numberSystem || 'latin'\n  )\n}\n\n/**\n * Get translations for a specific locale\n * @param locale - The locale to get translations for\n * @returns The translation object for the locale, defaults to English if not found\n */\nexport function getTranslations(locale: string = 'en'): CalendarTranslations {\n  return translations[locale] || translations.en\n}\n\n/**\n * Get effective locale based on provided locale and calendar system\n * If locale is provided, returns it. Otherwise, defaults based on calendar system:\n * - Jalali calendar defaults to 'fa' (Persian)\n * - Gregorian calendar defaults to 'en' (English)\n * @param locale - The provided locale (optional)\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @returns The effective locale to use\n */\nexport function getEffectiveLocale(\n  locale: CalendarUILocale | undefined,\n  calendarSystem: 'gregorian' | 'jalali'\n): CalendarUILocale {\n  if (locale) {\n    return locale\n  }\n  return calendarSystem === 'jalali' ? 'fa' : 'en'\n}\n\n/**\n * Get month names based on calendar system and locale\n * @param calendarSystem - The calendar system ('gregorian' or 'jalali')\n * @param locale - The locale code (optional, defaults to 'en' for gregorian, 'fa' for jalali)\n * @returns Array of month names for the calendar system\n */\nexport function getMonthNamesByCalendarSystem(\n  calendarSystem: 'gregorian' | 'jalali',\n  locale?: string\n): string[] {\n  if (calendarSystem === 'jalali') {\n    const months =\n      jalaliMonths[locale as keyof typeof jalaliMonths] || jalaliMonths.fa\n    return [...months]\n  }\n  // For Gregorian calendar: only Persian locale has its own translations,\n  // all other locales use English months\n  if (locale === 'fa') {\n    return [...gregorianMonths.fa]\n  }\n  const months = gregorianMonths[locale as keyof typeof gregorianMonths]\n  return months ? [...months] : [...gregorianMonths.en]\n}\n\n/**\n * Merge custom translations with default translations\n * @param defaultTranslations - The default translations for the locale\n * @param customTranslations - Custom translations to override defaults\n * @param locale - The locale code to determine default direction if not provided\n * @param calendarSystem - The calendar system to determine month names ('gregorian' or 'jalali')\n * @returns Merged translations object\n */\nexport function mergeTranslations(\n  defaultTranslations: CalendarTranslations,\n  customTranslations?: Partial<CalendarTranslations>,\n  locale?: string,\n  calendarSystem?: 'gregorian' | 'jalali'\n): CalendarTranslations {\n  // If locale and calendarSystem are not provided, preserve original translations\n  // (backward compatibility for simple merge operations)\n  if (locale === undefined && calendarSystem === undefined) {\n    if (!customTranslations) {\n      return defaultTranslations\n    }\n    return {\n      months: customTranslations.months || defaultTranslations.months,\n      weekdays: customTranslations.weekdays || defaultTranslations.weekdays,\n      direction: customTranslations.direction || defaultTranslations.direction,\n      numbers: customTranslations.numbers || defaultTranslations.numbers,\n      labels: {\n        ...defaultTranslations.labels,\n        ...customTranslations.labels\n      },\n      presetRanges: {\n        ...defaultTranslations.presetRanges,\n        ...customTranslations.presetRanges\n      }\n    }\n  }\n\n  // 🎯 IMPORTANT: Apply calendar system logic when locale/calendarSystem are provided\n  // This ensures correct month names for Jalali/Gregorian calendars\n  const calendar = calendarSystem || 'gregorian'\n  const effectiveLocale = locale || (calendar === 'jalali' ? 'fa' : 'en')\n  const baseLocale =\n    calendar === 'jalali' && effectiveLocale !== 'en' ? 'fa' : effectiveLocale\n\n  // 🎯 For Jalali calendar with non-English locales, use Persian translations\n  const isJalaliNonEnglish = calendar === 'jalali' && effectiveLocale !== 'en'\n  const translationLocale = isJalaliNonEnglish ? 'fa' : effectiveLocale\n\n  // 🎯 Determine weekdays based on calendar system\n  // For Jalali calendar: use English weekday names only when locale is 'en', otherwise use Persian\n  // For Gregorian calendar: use locale-based weekday names\n  let defaultWeekdays =\n    calendar === 'jalali'\n      ? effectiveLocale === 'en'\n        ? weekdayNames.en\n        : weekdayNames.fa\n      : weekdayNames[effectiveLocale as keyof typeof weekdayNames] ||\n        weekdayNames.en\n\n  // 🎯 Special case: For any calendar with Persian locale,\n  // rotate Persian weekdays to start with Sunday (یکشنبه) instead of Saturday (شنبه)\n  // This ensures all weekday arrays are in Gregorian order (Sunday first)\n  if (effectiveLocale === 'fa') {\n    // Persian Jalali weekdays: ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'] (Saturday first)\n    // Rotate to: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'] (Sunday first)\n    const persianJalali = weekdayNames.fa\n    defaultWeekdays = [\n      persianJalali[1], // Sunday (یکشنبه)\n      persianJalali[2], // Monday (دوشنبه)\n      persianJalali[3], // Tuesday (سه‌شنبه)\n      persianJalali[4], // Wednesday (چهارشنبه)\n      persianJalali[5], // Thursday (پنج‌شنبه)\n      persianJalali[6], // Friday (جمعه)\n      persianJalali[0] // Saturday (شنبه)\n    ]\n  }\n\n  // Get labels and presetRanges based on calendar system and locale\n  const labels = isJalaliNonEnglish\n    ? translationLabels.fa\n    : translationLabels[translationLocale as keyof typeof translationLabels] ||\n      translationLabels.en\n  const presetRanges = isJalaliNonEnglish\n    ? presetRangesLabels.fa\n    : presetRangesLabels[\n        translationLocale as keyof typeof presetRangesLabels\n      ] || presetRangesLabels.en\n\n  // Determine direction and numbers based on calendar system\n  const direction = isJalaliNonEnglish\n    ? 'rtl'\n    : getTextDirection(effectiveLocale)\n  const numbers = isJalaliNonEnglish\n    ? 'persian'\n    : effectiveLocale === 'en' && calendar === 'jalali'\n      ? 'latin'\n      : getNumberSystem(effectiveLocale)\n\n  // If no customizations, use defaults with calendar system applied\n  if (!customTranslations) {\n    return {\n      months: getMonthNamesByCalendarSystem(calendar, baseLocale),\n      weekdays: defaultWeekdays,\n      direction,\n      numbers,\n      labels,\n      presetRanges\n    }\n  }\n\n  // Merge custom translations with defaults, respecting calendar system\n  return {\n    months:\n      customTranslations.months ||\n      getMonthNamesByCalendarSystem(calendar, baseLocale),\n    weekdays: customTranslations.weekdays || defaultWeekdays,\n    direction: customTranslations.direction || direction,\n    numbers: customTranslations.numbers || numbers,\n    labels: {\n      ...labels,\n      ...customTranslations.labels\n    },\n    presetRanges: {\n      ...presetRanges,\n      ...customTranslations.presetRanges\n    }\n  }\n}\n","/**\n * Time manipulation helpers\n */\n\nimport type { Day } from '../../../types'\n\n/**\n * Add system time to a day if withTime is enabled and time is missing\n */\nexport function addSystemTimeIfNeeded(day: Day, withTime: boolean): Day {\n  if (withTime && (day.hour === undefined || day.minute === undefined)) {\n    const now = new Date()\n    return {\n      ...day,\n      hour: now.getHours(),\n      minute: now.getMinutes()\n    }\n  }\n  return day\n}\n\n/**\n * Add system time to both from and to in a range if needed\n */\nexport function addSystemTimeToRange(\n  range: { from: Day; to: Day | null },\n  withTime: boolean\n): { from: Day; to: Day | null } {\n  return {\n    from: addSystemTimeIfNeeded(range.from, withTime),\n    to: range.to ? addSystemTimeIfNeeded(range.to, withTime) : null\n  }\n}\n","/**\n * Display month resolution helper\n * Extracts display month logic into one helper\n */\n\nimport type { Day, Range, Multi, Week, CalendarLocale } from '../../../types'\nimport { extractMonthFromValue } from '../../../utils/normalize'\nimport { getMonthsToDisplay } from '../../../utils/calendar-grid'\n\n/**\n * Resolve the display month based on the new value and current state\n */\nexport function resolveDisplayMonth(\n  prevDisplay: Day,\n  newValue: Day | Range | Multi | Week | null,\n  numberOfMonths: number,\n  calendarSystem: CalendarLocale,\n  type: 'single' | 'range' | 'multi' | 'week',\n  currentRange?: Range | null\n): Day {\n  const monthFromValue = extractMonthFromValue(newValue)\n  if (!monthFromValue) return prevDisplay\n\n  // For range type, only navigate if starting a new range\n  if (type === 'range') {\n    if (currentRange && currentRange.from && !currentRange.to) {\n      // Keep current displayMonth when selecting end date\n      return prevDisplay\n    }\n  }\n\n  // Check if the month is already visible in multi-month view\n  if (numberOfMonths > 1) {\n    const visibleMonths = getMonthsToDisplay(\n      prevDisplay,\n      numberOfMonths,\n      calendarSystem\n    )\n    const isMonthVisible = visibleMonths.some(\n      (m) => m.year === monthFromValue.year && m.month === monthFromValue.month\n    )\n    if (isMonthVisible) {\n      // Keep current displayMonth if the selected month is already visible\n      return prevDisplay\n    }\n  }\n\n  return monthFromValue\n}\n","/**\n * Date selection reducer\n * Handles SELECT_DATE action for single date selection\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport { addSystemTimeIfNeeded } from '../helpers/time'\nimport { resolveDisplayMonth } from '../helpers/resolveDisplayMonth'\n\nexport function dateSelectionReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  if (action.type !== 'SELECT_DATE' || context.type !== 'single') {\n    return null\n  }\n\n  const dayWithTime = addSystemTimeIfNeeded(action.payload, context.withTime)\n  const newDisplayMonth = resolveDisplayMonth(\n    state.displayMonth,\n    dayWithTime,\n    context.numberOfMonths,\n    context.calendarSystem,\n    'single'\n  )\n\n  return {\n    state: {\n      selectedValue: dayWithTime,\n      displayMonth: newDisplayMonth,\n      currentView: 'calendar'\n    },\n    emittedValue: dayWithTime\n  }\n}\n","/**\n * Range selection reducer\n * Handles range selection actions (SELECT_RANGE_START, SELECT_RANGE_END, SELECT_RANGE_DIRECT)\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport type { Range } from '../../../types'\nimport { addSystemTimeIfNeeded, addSystemTimeToRange } from '../helpers/time'\nimport { resolveDisplayMonth } from '../helpers/resolveDisplayMonth'\nimport { isBefore } from '../../../utils/date-comparison'\n\nexport function rangeReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  if (context.type !== 'range') {\n    return null\n  }\n\n  const currentRange = state.selectedValue as Range | null\n\n  switch (action.type) {\n    case 'SELECT_RANGE_START': {\n      const fromWithTime = addSystemTimeIfNeeded(\n        action.payload,\n        context.withTime\n      )\n      const newRange: Range = { from: fromWithTime, to: null }\n      return {\n        state: {\n          selectedValue: newRange,\n          displayMonth: {\n            year: action.payload.year,\n            month: action.payload.month,\n            day: 1\n          }\n        },\n        emittedValue: newRange\n      }\n    }\n\n    case 'SELECT_RANGE_END': {\n      if (!currentRange || !currentRange.from) {\n        return null\n      }\n\n      const toWithTime = addSystemTimeIfNeeded(action.payload, context.withTime)\n      const fromWithTime = addSystemTimeIfNeeded(\n        currentRange.from,\n        context.withTime\n      )\n\n      // If selected day is before start date, make it the new start\n      let finalRange: Range\n      if (isBefore(action.payload, currentRange.from, context.calendarSystem)) {\n        finalRange = { from: toWithTime, to: fromWithTime }\n      } else {\n        finalRange = { from: fromWithTime, to: toWithTime }\n      }\n\n      return {\n        state: {\n          selectedValue: finalRange\n        },\n        emittedValue: finalRange\n      }\n    }\n\n    case 'SELECT_RANGE_DIRECT': {\n      const newRange = addSystemTimeToRange(action.payload, context.withTime)\n      const newDisplayMonth = resolveDisplayMonth(\n        state.displayMonth,\n        newRange as Range,\n        context.numberOfMonths,\n        context.calendarSystem,\n        'range'\n      )\n\n      return {\n        state: {\n          selectedValue: newRange as Range,\n          displayMonth: newDisplayMonth,\n          currentView: 'calendar'\n        },\n        emittedValue: newRange as Range\n      }\n    }\n\n    case 'SELECT_DATE': {\n      // Handle SELECT_DATE for range type\n      const dayWithTime = addSystemTimeIfNeeded(\n        action.payload,\n        context.withTime\n      )\n\n      // If no range exists or range is complete, start new range\n      if (!currentRange || !currentRange.from || currentRange.to) {\n        const newRange: Range = { from: dayWithTime, to: null }\n        const newDisplayMonth = resolveDisplayMonth(\n          state.displayMonth,\n          newRange,\n          context.numberOfMonths,\n          context.calendarSystem,\n          'range',\n          newRange\n        )\n\n        return {\n          state: {\n            selectedValue: newRange,\n            displayMonth: newDisplayMonth,\n            currentView: 'calendar'\n          },\n          emittedValue: newRange\n        }\n      }\n\n      // If we have a start date, set end date\n      if (currentRange.from) {\n        let finalRange: Range\n        if (isBefore(dayWithTime, currentRange.from, context.calendarSystem)) {\n          finalRange = { from: dayWithTime, to: currentRange.from }\n        } else {\n          finalRange = { from: currentRange.from, to: dayWithTime }\n        }\n\n        // Only update displayMonth when starting a new range, not when completing\n        const newDisplayMonth = resolveDisplayMonth(\n          state.displayMonth,\n          finalRange,\n          context.numberOfMonths,\n          context.calendarSystem,\n          'range',\n          currentRange\n        )\n\n        return {\n          state: {\n            selectedValue: finalRange,\n            displayMonth: newDisplayMonth,\n            currentView: 'calendar'\n          },\n          emittedValue: finalRange\n        }\n      }\n\n      return null\n    }\n\n    default:\n      return null\n  }\n}\n","/**\n * Week selection reducer\n * Handles SELECT_WEEK action\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport type { Week } from '../../../types'\nimport { getWeekBounds } from '../../../utils/calendar-grid'\nimport { addSystemTimeIfNeeded } from '../helpers/time'\nimport { resolveDisplayMonth } from '../helpers/resolveDisplayMonth'\n\nexport function weekReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  if (context.type !== 'week') {\n    return null\n  }\n\n  // Handle both SELECT_WEEK and SELECT_DATE for week type\n  if (action.type === 'SELECT_WEEK' || action.type === 'SELECT_DATE') {\n    const dayToUse = action.payload\n\n    // Calculate week bounds for the selected day\n    const weekBounds = getWeekBounds(\n      dayToUse,\n      context.calendarSystem,\n      context.weekStart\n    )\n    const newValue: Week = {\n      from: addSystemTimeIfNeeded(weekBounds.from, context.withTime),\n      to: addSystemTimeIfNeeded(weekBounds.to, context.withTime)\n    }\n\n    const newDisplayMonth = resolveDisplayMonth(\n      state.displayMonth,\n      newValue,\n      context.numberOfMonths,\n      context.calendarSystem,\n      'week'\n    )\n\n    return {\n      state: {\n        selectedValue: newValue,\n        displayMonth: newDisplayMonth,\n        currentView: 'calendar'\n      },\n      emittedValue: newValue\n    }\n  }\n\n  return null\n}\n","/**\n * Multi date selection reducer\n * Handles TOGGLE_MULTI_DATE action\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport type { Multi } from '../../../types'\nimport { isSameDay } from '../../../utils/date-comparison'\n\nexport function multiReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  if (context.type !== 'multi') {\n    return null\n  }\n\n  // Handle both SELECT_DATE and TOGGLE_MULTI_DATE for multi type\n  if (action.type === 'SELECT_DATE' || action.type === 'TOGGLE_MULTI_DATE') {\n    const currentMulti = (state.selectedValue as Multi) || []\n    const isSelected = currentMulti.some((day) =>\n      isSameDay(day, action.payload, context.calendarSystem)\n    )\n\n    let newValue: Multi\n    if (isSelected) {\n      // Remove from selection\n      newValue = currentMulti.filter(\n        (day) => !isSameDay(day, action.payload, context.calendarSystem)\n      )\n    } else {\n      // Add to selection\n      newValue = [...currentMulti, action.payload]\n    }\n\n    return {\n      state: {\n        selectedValue: newValue\n      },\n      emittedValue: newValue\n    }\n  }\n\n  return null\n}\n","/**\n * Time update reducer\n * Handles UPDATE_TIME action\n * All time merging logic is centralized here\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport type { Range, Week } from '../../../types'\nimport { isSameDay } from '../../../utils/date-comparison'\n\nexport function timeReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  if (action.type !== 'UPDATE_TIME') {\n    return null\n  }\n\n  const { day, hour, minute } = action.payload\n  const updatedDay = { ...day, hour, minute }\n\n  if (context.type === 'single') {\n    return {\n      state: {\n        selectedValue: updatedDay\n      },\n      emittedValue: updatedDay\n    }\n  }\n\n  if (context.type === 'range') {\n    const currentRange = state.selectedValue as Range | null\n    if (!currentRange) {\n      return null\n    }\n\n    const isStartDate =\n      currentRange.from &&\n      isSameDay(currentRange.from, day, context.calendarSystem)\n    const isEndDate =\n      currentRange.to && isSameDay(currentRange.to, day, context.calendarSystem)\n\n    if (isStartDate) {\n      const newRange: Range = {\n        ...currentRange,\n        from: updatedDay\n      }\n      return {\n        state: {\n          selectedValue: newRange\n        },\n        emittedValue: newRange\n      }\n    }\n\n    if (isEndDate) {\n      const newRange: Range = {\n        ...currentRange,\n        to: updatedDay\n      }\n      return {\n        state: {\n          selectedValue: newRange\n        },\n        emittedValue: newRange\n      }\n    }\n\n    return null\n  }\n\n  if (context.type === 'week') {\n    const currentWeek = state.selectedValue as Week | null\n    if (!currentWeek) {\n      return null\n    }\n\n    const isStartDate =\n      currentWeek.from &&\n      isSameDay(currentWeek.from, day, context.calendarSystem)\n    const isEndDate =\n      currentWeek.to && isSameDay(currentWeek.to, day, context.calendarSystem)\n\n    if (isStartDate) {\n      const newWeek: Week = {\n        ...currentWeek,\n        from: updatedDay\n      }\n      return {\n        state: {\n          selectedValue: newWeek\n        },\n        emittedValue: newWeek\n      }\n    }\n\n    if (isEndDate) {\n      const newWeek: Week = {\n        ...currentWeek,\n        to: updatedDay\n      }\n      return {\n        state: {\n          selectedValue: newWeek\n        },\n        emittedValue: newWeek\n      }\n    }\n\n    return null\n  }\n\n  // Multi mode doesn't support time selection\n  return null\n}\n","/**\n * Navigation reducer\n * Handles navigation actions (NAVIGATE_MONTH, SET_VIEW, SELECT_MONTH, SELECT_YEAR, GO_TO_TODAY, SET_DISPLAY_MONTH)\n */\n\nimport type {\n  CalendarState,\n  CalendarAction,\n  ReducerContext,\n  ReducerResult\n} from '../types'\nimport { getToday } from '../../../utils/date-conversion'\n\n/**\n * Navigate to next/previous month\n */\nfunction navigateMonth(\n  currentMonth: { year: number; month: number },\n  direction: 'prev' | 'next'\n): { year: number; month: number; day: number } {\n  let newMonth = currentMonth.month + (direction === 'next' ? 1 : -1)\n  let newYear = currentMonth.year\n\n  if (newMonth > 12) {\n    newMonth = 1\n    newYear++\n  } else if (newMonth < 1) {\n    newMonth = 12\n    newYear--\n  }\n\n  return { year: newYear, month: newMonth, day: 1 }\n}\n\nexport function navigationReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): ReducerResult | null {\n  switch (action.type) {\n    case 'NAVIGATE_MONTH': {\n      return {\n        state: {\n          displayMonth: navigateMonth(state.displayMonth, action.payload)\n        }\n      }\n    }\n\n    case 'SET_VIEW': {\n      return {\n        state: {\n          currentView: action.payload\n        }\n      }\n    }\n\n    case 'SELECT_MONTH': {\n      return {\n        state: {\n          displayMonth: {\n            ...state.displayMonth,\n            month: action.payload,\n            day: 1\n          },\n          currentView: 'calendar'\n        }\n      }\n    }\n\n    case 'SELECT_YEAR': {\n      return {\n        state: {\n          displayMonth: {\n            ...state.displayMonth,\n            year: action.payload,\n            day: 1\n          },\n          currentView: 'months'\n        }\n      }\n    }\n\n    case 'GO_TO_TODAY': {\n      const today = getToday(context.calendarSystem)\n      return {\n        state: {\n          displayMonth: { year: today.year, month: today.month, day: 1 },\n          currentView: 'calendar'\n        }\n      }\n    }\n\n    case 'SET_DISPLAY_MONTH': {\n      return {\n        state: {\n          displayMonth: action.payload\n        }\n      }\n    }\n\n    default:\n      return null\n  }\n}\n","/**\n * useCalendarState Hook\n * Refactored into a clean, modular structure\n * Main hook is now small (~50 lines), only responsible for:\n * - creating reducer context\n * - calling useReducer\n * - syncing initValue\n * - exposing action creators\n */\n\nimport { useReducer, useEffect, useRef } from 'react'\nimport type {\n  Day,\n  Range,\n  Multi,\n  CalendarLocale,\n  CalendarType,\n  CalendarTranslations,\n  CalendarUILocale,\n  RangeDate\n} from '../../types'\nimport {\n  extractMonthFromValue,\n  areNormalizedValuesEqual\n} from '../../utils/normalize'\nimport { getToday, convertToJsDate } from '../../utils/date-conversion'\nimport { formatValueToString } from '../../utils/formatting'\nimport { getNumberSystem } from '../../utils/translations'\nimport type { CalendarState, CalendarAction, ReducerContext } from './types'\nimport { calendarReducer } from './reducers'\nimport { createActions } from './actions'\n\n/**\n * Hook options\n */\nexport interface UseCalendarStateOptions {\n  /** Initial value - should be normalized (Day | Range | Multi | null) */\n  initValue?: Day | Range | Multi | null\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Calendar selection type */\n  type: CalendarType\n  /** Enable time selection */\n  withTime?: boolean\n  /** Number of months displayed */\n  numberOfMonths?: 1 | 2 | 3\n  /** First day of the week (0 = Sunday, 6 = Saturday) */\n  weekStart?: number\n  /** Callback when value changes */\n  onChange: (\n    normalizedValue: Day | Range | Multi | null,\n    jsDateValue: Date | RangeDate | Date[] | null,\n    formattedString: string | null\n  ) => void\n  /** Callback when calendar value changes (requires initValue) */\n  onCalenderChange?: (\n    normalizedValue: Day | Range | Multi | null,\n    jsDateValue: Date | RangeDate | Date[] | null,\n    formattedString: string | null\n  ) => void\n  /** Custom date format string */\n  dateFormat?: string\n  /** Locale for formatting */\n  locale?: CalendarUILocale\n  /** Translations object (includes number system and labels) */\n  translations?: CalendarTranslations\n}\n\n/**\n * useCalendarState Hook\n */\nexport function useCalendarState(options: UseCalendarStateOptions) {\n  const {\n    initValue,\n    calendarSystem,\n    type,\n    withTime = false,\n    numberOfMonths = 1,\n    weekStart,\n    onChange,\n    onCalenderChange,\n    dateFormat,\n    locale,\n    translations\n  } = options\n\n  // Extract month from normalized initValue for initial display month\n  const monthFromInitValue = extractMonthFromValue(initValue || null)\n\n  // Initial state\n  const initialState: CalendarState = {\n    selectedValue: initValue || null,\n    displayMonth: monthFromInitValue || getToday(calendarSystem),\n    currentView: 'calendar'\n  }\n\n  // Reducer context\n  const context: ReducerContext = {\n    type,\n    calendarSystem,\n    withTime,\n    numberOfMonths,\n    weekStart\n  }\n\n  // Track emitted values for callback handling\n  // Using ref to store emitted values from reducers (written in reducer, read in useEffect)\n  const emittedValueRef = useRef<Day | Range | Multi | null | undefined>(\n    undefined\n  )\n\n  // Reducer wrapper that includes context\n  // Note: Reducers are called by React when dispatch is invoked (from event handlers),\n  // not during render, so writing to refs here is safe\n  const reducer = (state: CalendarState, action: CalendarAction) => {\n    const result = calendarReducer(state, action, context)\n\n    // Store emitted value for callback handling in useEffect\n    // This is safe: reducers run outside render phase when dispatch is called\n    if (result.emittedValue !== undefined) {\n      emittedValueRef.current = result.emittedValue\n    }\n\n    return result.state\n  }\n\n  // Note: The linter warning about ref access is a false positive.\n  // Reducers are only called when dispatch is invoked (from event handlers),\n  // not during render. Writing to refs in reducers is safe and a common pattern.\n  // eslint-disable-next-line\n  const [state, dispatch] = useReducer(reducer, initialState)\n\n  // Track previous initValue to detect changes\n  const prevInitValueRef = useRef(initValue)\n\n  // Sync initValue when it changes externally\n  // Use deep content comparison instead of reference comparison to prevent\n  // unnecessary re-synchronization when props are recreated with identical content\n  // This fixes a race condition in test environments where object references change\n  // even when the content (year, month, day, etc.) remains the same\n  useEffect(() => {\n    if (!areNormalizedValuesEqual(initValue, prevInitValueRef.current)) {\n      dispatch({ type: 'SYNC_INIT_VALUE', payload: initValue || null })\n      prevInitValueRef.current = initValue\n    }\n  }, [initValue])\n\n  // Handle value emission (onChange / onCalenderChange) via useEffect\n  // This runs after state updates, calling callbacks with emitted values\n  // Conversion and formatting happen at the output boundary\n  useEffect(() => {\n    if (emittedValueRef.current !== undefined) {\n      const normalizedValue = emittedValueRef.current\n      emittedValueRef.current = undefined // Clear before calling callbacks\n\n      // Convert to JavaScript Date objects (always Gregorian)\n      const jsDateValue = convertToJsDate(normalizedValue, type, calendarSystem)\n\n      // Determine number system from locale or translations\n      const numberSystem =\n        translations?.numbers || (locale ? getNumberSystem(locale) : 'latin')\n\n      // Get from/to labels from translations\n      const fromLabel = translations?.labels?.from || 'from'\n      const toLabel = translations?.labels?.to || 'to'\n\n      // Format to string\n      const formattedString = formatValueToString(\n        normalizedValue,\n        type,\n        numberSystem,\n        withTime,\n        dateFormat,\n        fromLabel,\n        toLabel\n      )\n\n      // Call onChange with three parameters\n      onChange(normalizedValue, jsDateValue, formattedString)\n\n      if (onCalenderChange && initValue !== undefined) {\n        onCalenderChange(normalizedValue, jsDateValue, formattedString)\n      }\n    }\n  }, [\n    state.selectedValue,\n    onChange,\n    onCalenderChange,\n    initValue,\n    type,\n    calendarSystem,\n    withTime,\n    dateFormat,\n    locale,\n    translations\n  ])\n\n  // Create action creators\n  const actions = createActions(dispatch)\n\n  return {\n    state,\n    actions\n  }\n}\n\n// Re-export types\nexport type { CalendarState, CalendarAction } from './types'\n","/**\n * Reducer index\n * Loops through all reducers and returns the first non-null update\n */\n\nimport type { CalendarState, CalendarAction, ReducerContext } from '../types'\nimport type { Day, Range, Multi, Week } from '../../../types'\nimport { dateSelectionReducer } from './dateSelection'\nimport { rangeReducer } from './range'\nimport { weekReducer } from './week'\nimport { multiReducer } from './multi'\nimport { timeReducer } from './time'\nimport { navigationReducer } from './navigation'\nimport { extractMonthFromValue } from '../../../utils/normalize'\n\n/**\n * Main calendar reducer\n * Tries each domain-specific reducer and returns the first non-null result\n */\nexport function calendarReducer(\n  state: CalendarState,\n  action: CalendarAction,\n  context: ReducerContext\n): { state: CalendarState; emittedValue?: Day | Range | Multi | Week | null } {\n  // Try each reducer in order\n  const reducers = [\n    dateSelectionReducer,\n    rangeReducer,\n    weekReducer,\n    multiReducer,\n    timeReducer,\n    navigationReducer\n  ]\n\n  for (const reducer of reducers) {\n    const result = reducer(state, action, context)\n    if (result) {\n      const newState = {\n        ...state,\n        ...result.state\n      }\n      return {\n        state: newState,\n        emittedValue: result.emittedValue\n      }\n    }\n  }\n\n  // Handle CLEAR_SELECTION\n  if (action.type === 'CLEAR_SELECTION') {\n    return {\n      state: {\n        ...state,\n        selectedValue: null\n      },\n      emittedValue: null\n    }\n  }\n\n  // Handle SYNC_INIT_VALUE\n  if (action.type === 'SYNC_INIT_VALUE') {\n    const monthFromValue = extractMonthFromValue(action.payload)\n    return {\n      state: {\n        ...state,\n        selectedValue: action.payload,\n        displayMonth: monthFromValue || state.displayMonth\n      }\n    }\n  }\n\n  // Default: no change\n  return { state }\n}\n","/**\n * Action creators for calendar state\n */\n\nimport type { Day, Range } from '../../types'\nimport type { CalendarAction } from './types'\n\nexport const createActions = (dispatch: (action: CalendarAction) => void) => ({\n  selectDate: (day: Day) => {\n    dispatch({ type: 'SELECT_DATE', payload: day })\n  },\n  selectRangeStart: (day: Day) => {\n    dispatch({ type: 'SELECT_RANGE_START', payload: day })\n  },\n  selectRangeEnd: (day: Day) => {\n    dispatch({ type: 'SELECT_RANGE_END', payload: day })\n  },\n  selectWeek: (day: Day) => {\n    dispatch({ type: 'SELECT_WEEK', payload: day })\n  },\n  selectRangeDirect: (range: Range) => {\n    dispatch({ type: 'SELECT_RANGE_DIRECT', payload: range })\n  },\n  selectPresetRange: (range: Range) => {\n    dispatch({ type: 'SELECT_RANGE_DIRECT', payload: range })\n  },\n  toggleMultiDate: (day: Day) => {\n    dispatch({ type: 'TOGGLE_MULTI_DATE', payload: day })\n  },\n  updateTime: (day: Day, hour: number, minute: number) => {\n    dispatch({ type: 'UPDATE_TIME', payload: { day, hour, minute } })\n  },\n  clearSelection: () => {\n    dispatch({ type: 'CLEAR_SELECTION' })\n  },\n  setDisplayMonth: (month: Day) => {\n    dispatch({ type: 'SET_DISPLAY_MONTH', payload: month })\n  },\n  navigateMonth: (direction: 'prev' | 'next') => {\n    dispatch({ type: 'NAVIGATE_MONTH', payload: direction })\n  },\n  setView: (view: 'calendar' | 'months' | 'years') => {\n    dispatch({ type: 'SET_VIEW', payload: view })\n  },\n  selectMonth: (month: number) => {\n    dispatch({ type: 'SELECT_MONTH', payload: month })\n  },\n  selectYear: (year: number) => {\n    dispatch({ type: 'SELECT_YEAR', payload: year })\n  },\n  goToToday: () => {\n    dispatch({ type: 'GO_TO_TODAY' })\n  }\n})\n","/**\n * Constraints normalization utilities\n *\n * This module provides utilities for normalizing calendar constraint inputs\n * from various formats (Date objects, strings, timestamps, Day objects) into\n * a consistent internal format (Day objects).\n *\n * Shared between DtPicker and DtCalendar components to ensure consistent\n * constraint handling across the library.\n */\n\nimport type { CalendarLocale, CalendarType, Day } from '../types'\nimport type {\n  CalendarConstraintsInput,\n  CalendarConstraints,\n  CalendarError\n} from '../types/calendar'\nimport { normalizeInitValueWithErrors } from './normalize'\n\n/**\n * Normalize constraints props from flexible DateInput formats to Day/Day[] objects\n *\n * This function converts user-provided constraint inputs (which can be in various\n * formats like Date objects, date strings, timestamps, or Day objects) into\n * normalized Day objects that the calendar components can use internally.\n *\n * The function also collects any normalization errors that occur during the\n * conversion process, allowing the calling component to handle them appropriately\n * (e.g., via the onError callback).\n *\n * @param constraintsInput - User-provided constraints in flexible formats.\n *   Can be undefined if no constraints are provided.\n *   - maxDate: Maximum selectable date (Date, string, timestamp, or Day)\n *   - minDate: Minimum selectable date (Date, string, timestamp, or Day)\n *   - disabledDates: Array of disabled dates (Date[], string[], number[], or Day[])\n *   - isDateDisabled: Callback function to check if a date should be disabled\n * @param locale - Calendar locale ('gregorian' for Gregorian, 'jalali' for Jalali).\n *   Used for proper date conversion and validation.\n * @param _type - Calendar selection type (single, range, multi, week).\n *   Currently not used but kept for API consistency and future extensibility.\n *\n * @returns An object containing:\n *   - constraints: Normalized constraints object with Day objects.\n *     Invalid dates are excluded from the result.\n *   - errors: Array of CalendarError objects describing any normalization failures.\n *     Each error includes the field name, error type, and message.\n *\n * @example\n * ```typescript\n * // Normalize constraints with various input formats\n * const result = normalizeConstraintsProps(\n *   {\n *     maxDate: new Date(2023, 11, 31),\n *     minDate: \"2023-01-01\",\n *     disabledDates: [1672531200000, { year: 2023, month: 1, day: 15 }],\n *     isDateDisabled: (date) => date.day === 1\n *   },\n *   'gregorian',\n *   'single'\n * )\n *\n * // Result:\n * // {\n * //   constraints: {\n * //     maxDate: { year: 2023, month: 12, day: 31 },\n * //     minDate: { year: 2023, month: 1, day: 1 },\n * //     disabledDates: [\n * //       { year: 2023, month: 1, day: 1 },\n * //       { year: 2023, month: 1, day: 15 }\n * //     ],\n * //     isDateDisabled: [Function]\n * //   },\n * //   errors: []\n * // }\n * ```\n *\n * @example\n * ```typescript\n * // Handle invalid dates gracefully\n * const result = normalizeConstraintsProps(\n *   {\n *     maxDate: { year: 2023, month: 13, day: 1 }, // Invalid month\n *     minDate: \"invalid-date-string\"\n *   },\n *   'gregorian',\n *   'single'\n * )\n *\n * // Result:\n * // {\n * //   constraints: {}, // Invalid dates excluded\n * //   errors: [\n * //     { type: 'validation', field: 'constraints.maxDate', ... },\n * //     { type: 'normalization', field: 'constraints.minDate', ... }\n * //   ]\n * // }\n * ```\n */\nexport function normalizeConstraintsProps(\n  constraintsInput: CalendarConstraintsInput | undefined,\n  calendarSystem: CalendarLocale,\n  _type: CalendarType\n): { constraints: CalendarConstraints; errors: CalendarError[] } {\n  // Initialize empty constraints and errors arrays\n  // These will be populated as we process each constraint\n  const constraints: CalendarConstraints = {}\n  const errors: CalendarError[] = []\n\n  // Early return if no constraints provided\n  // This is a valid case - components can work without constraints\n  if (!constraintsInput) {\n    return { constraints, errors }\n  }\n\n  // Normalize maxDate constraint\n  // maxDate defines the latest date that can be selected\n  // Accepts: Date object, date string, timestamp, or Day object\n  if (constraintsInput.maxDate) {\n    const result = normalizeInitValueWithErrors(\n      constraintsInput.maxDate,\n      calendarSystem,\n      'single', // Always 'single' since maxDate is a single date\n      'constraints.maxDate' // Field name for error reporting\n    )\n\n    // Collect any normalization errors\n    // Errors are added to the errors array but don't prevent other constraints from being processed\n    if (result.errors.length > 0) {\n      errors.push(...result.errors)\n    }\n\n    // Only add to constraints if normalization succeeded\n    // Check for 'year' property to ensure it's a valid Day object\n    if (result.value && 'year' in result.value) {\n      constraints.maxDate = result.value as Day\n    }\n  }\n\n  // Normalize minDate constraint\n  // minDate defines the earliest date that can be selected\n  // Accepts: Date object, date string, timestamp, or Day object\n  if (constraintsInput.minDate) {\n    const result = normalizeInitValueWithErrors(\n      constraintsInput.minDate,\n      calendarSystem,\n      'single', // Always 'single' since minDate is a single date\n      'constraints.minDate' // Field name for error reporting\n    )\n\n    // Collect any normalization errors\n    if (result.errors.length > 0) {\n      errors.push(...result.errors)\n    }\n\n    // Only add to constraints if normalization succeeded\n    if (result.value && 'year' in result.value) {\n      constraints.minDate = result.value as Day\n    }\n  }\n\n  // Normalize disabledDates array\n  // disabledDates is an array of specific dates that cannot be selected\n  // Each date in the array can be in different formats\n  if (\n    constraintsInput.disabledDates &&\n    constraintsInput.disabledDates.length > 0\n  ) {\n    const normalizedDates: Day[] = []\n\n    // Process each date in the array individually\n    // This allows partial success - valid dates are kept, invalid ones are skipped\n    constraintsInput.disabledDates.forEach((date, index) => {\n      const result = normalizeInitValueWithErrors(\n        date,\n        calendarSystem,\n        'single', // Each disabled date is a single date\n        `constraints.disabledDates[${index}]` // Include index in field name for precise error reporting\n      )\n\n      // Collect errors for this specific date\n      // The index in the field name helps identify which date failed\n      if (result.errors.length > 0) {\n        errors.push(...result.errors)\n      }\n\n      // Only add valid dates to the normalized array\n      // Invalid dates are silently skipped (errors are still reported)\n      if (result.value && 'year' in result.value) {\n        normalizedDates.push(result.value as Day)\n      }\n    })\n\n    // Only set disabledDates if at least one date was successfully normalized\n    // This prevents setting an empty array when all dates were invalid\n    if (normalizedDates.length > 0) {\n      constraints.disabledDates = normalizedDates\n    }\n  }\n\n  // Pass through the isDateDisabled callback function unchanged\n  // This is a function that takes a Day and returns boolean\n  // No normalization needed - it's already in the correct format\n  if (constraintsInput.isDateDisabled) {\n    constraints.isDateDisabled = constraintsInput.isDateDisabled\n  }\n\n  // Return both normalized constraints and any errors encountered\n  // The calling component can use errors to inform the user or handle them programmatically\n  return { constraints, errors }\n}\n","/**\n * Keyboard Navigation Hook\n * Handles arrow key navigation, keyboard shortcuts, and date selection\n */\n\nimport { useEffect, useCallback, useRef, RefObject } from 'react'\nimport type { Day, CalendarLocale, CalendarType } from '../types'\nimport { dateToDay } from '../utils/date-conversion'\nimport { toGregorian, jalaaliMonthLength } from 'jalaali-js'\n\nexport interface UseKeyboardNavigationOptions {\n  /** Currently focused date */\n  focusedDate: Day\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Calendar selection type */\n  type: CalendarType\n  /** Container ref to scope keyboard events */\n  containerRef: RefObject<HTMLElement>\n  /** Whether keyboard navigation is enabled */\n  enabled?: boolean\n  /** Callback when focused date changes */\n  onFocusedDateChange: (date: Day) => void\n  /** Callback when date should be selected */\n  onDateSelect: (date: Day) => void\n  /** Callback to navigate to today */\n  onGoToToday?: () => void\n  /** Callback to change month */\n  onMonthNavigate?: (direction: 'prev' | 'next') => void\n  /** Callback to validate if date is selectable */\n  isDateSelectable?: (date: Day) => boolean\n}\n\n/**\n * Add days to a date\n */\nconst addDays = (\n  day: Day,\n  daysToAdd: number,\n  calendarSystem: CalendarLocale\n): Day => {\n  // Convert to Gregorian for calculation\n  let date: Date\n  if (calendarSystem === 'jalali') {\n    const greg = toGregorian(day.year, day.month, day.day)\n    date = new Date(greg.gy, greg.gm - 1, greg.gd)\n  } else {\n    date = new Date(day.year, day.month - 1, day.day)\n  }\n\n  // Add days\n  date.setDate(date.getDate() + daysToAdd)\n\n  // Convert back to the correct locale\n  return dateToDay(date, calendarSystem)\n}\n\n/**\n * Custom hook for keyboard navigation in calendar\n */\nexport const useKeyboardNavigation = (\n  options: UseKeyboardNavigationOptions\n) => {\n  const {\n    focusedDate,\n    calendarSystem,\n    containerRef,\n    enabled = true,\n    onFocusedDateChange,\n    onDateSelect,\n    onGoToToday,\n    onMonthNavigate,\n    isDateSelectable\n  } = options\n\n  const focusedDateRef = useRef(focusedDate)\n\n  // Keep ref in sync\n  useEffect(() => {\n    focusedDateRef.current = focusedDate\n  }, [focusedDate])\n\n  /**\n   * Navigate to a new date if it's selectable\n   * If not selectable, try to find the next selectable date in the same direction\n   */\n  const navigateToDate = useCallback(\n    function navigateRecursive(\n      newDate: Day,\n      direction: number = 0,\n      attempts: number = 0\n    ): boolean {\n      // Prevent infinite loops\n      if (attempts > 31) {\n        return false\n      }\n\n      // Check if date is selectable\n      if (isDateSelectable && !isDateSelectable(newDate)) {\n        // If we have a direction, try the next date in that direction\n        if (direction !== 0) {\n          const nextDate = addDays(newDate, direction, calendarSystem)\n          return navigateRecursive(nextDate, direction, attempts + 1)\n        }\n        return false\n      }\n\n      onFocusedDateChange(newDate)\n      return true\n    },\n    [isDateSelectable, onFocusedDateChange, calendarSystem]\n  )\n\n  /**\n   * Handle arrow key navigation\n   */\n  const handleArrowNavigation = useCallback(\n    (direction: 'up' | 'down' | 'left' | 'right') => {\n      const current = focusedDateRef.current\n      let daysToAdd = 0\n\n      switch (direction) {\n        case 'up':\n          daysToAdd = -7\n          break\n        case 'down':\n          daysToAdd = 7\n          break\n        case 'left':\n          daysToAdd = calendarSystem === 'jalali' ? 1 : -1 // RTL support\n          break\n        case 'right':\n          daysToAdd = calendarSystem === 'jalali' ? -1 : 1 // RTL support\n          break\n      }\n\n      const newDate = addDays(current, daysToAdd, calendarSystem)\n\n      // Check if we've moved to a different month (including year boundaries)\n      const monthChanged =\n        newDate.month !== current.month || newDate.year !== current.year\n\n      if (monthChanged && onMonthNavigate) {\n        // Determine navigation direction\n        let navDirection: 'prev' | 'next'\n        if (newDate.year > current.year) {\n          navDirection = 'next'\n        } else if (newDate.year < current.year) {\n          navDirection = 'prev'\n        } else if (newDate.month > current.month) {\n          navDirection = 'next'\n        } else {\n          navDirection = 'prev'\n        }\n\n        onMonthNavigate(navDirection)\n        // Use setTimeout to ensure month navigation completes before focusing\n        setTimeout(() => {\n          navigateToDate(newDate, daysToAdd)\n        }, 0)\n      } else {\n        // Pass the direction to navigateToDate to skip disabled dates\n        navigateToDate(newDate, daysToAdd)\n      }\n    },\n    [calendarSystem, onMonthNavigate, navigateToDate]\n  )\n\n  /**\n   * Handle Home/End keys\n   */\n  const handleHomeEnd = useCallback(\n    (key: 'Home' | 'End') => {\n      const current = focusedDateRef.current\n      let newDate: Day\n\n      if (key === 'Home') {\n        // Go to first day of current month\n        newDate = { ...current, day: 1 }\n      } else {\n        // Go to last day of current month\n        if (calendarSystem === 'jalali') {\n          const lastDay = jalaaliMonthLength(current.year, current.month)\n          newDate = { ...current, day: lastDay }\n        } else {\n          const lastDay = new Date(current.year, current.month, 0).getDate()\n          newDate = { ...current, day: lastDay }\n        }\n      }\n\n      navigateToDate(newDate)\n    },\n    [calendarSystem, navigateToDate]\n  )\n\n  /**\n   * Handle PageUp/PageDown keys\n   */\n  const handlePageUpDown = useCallback(\n    (key: 'PageUp' | 'PageDown') => {\n      const direction = key === 'PageUp' ? 'prev' : 'next'\n\n      if (onMonthNavigate) {\n        onMonthNavigate(direction)\n      }\n\n      // Keep the same day if possible, or adjust to last day of month\n      const current = focusedDateRef.current\n      const monthDelta = key === 'PageUp' ? -1 : 1\n\n      let newMonth = current.month + monthDelta\n      let newYear = current.year\n\n      if (newMonth < 1) {\n        newMonth = 12\n        newYear--\n      } else if (newMonth > 12) {\n        newMonth = 1\n        newYear++\n      }\n\n      // Calculate last day of new month\n      let lastDayOfNewMonth: number\n      if (calendarSystem === 'jalali') {\n        lastDayOfNewMonth = jalaaliMonthLength(newYear, newMonth)\n      } else {\n        lastDayOfNewMonth = new Date(newYear, newMonth, 0).getDate()\n      }\n\n      const newDay = Math.min(current.day, lastDayOfNewMonth)\n      const newDate: Day = { year: newYear, month: newMonth, day: newDay }\n\n      // Use setTimeout to ensure month navigation completes before focusing\n      setTimeout(() => {\n        navigateToDate(newDate, 0)\n      }, 0)\n    },\n    [calendarSystem, onMonthNavigate, navigateToDate]\n  )\n\n  /**\n   * Handle keyboard events\n   */\n  const handleKeyDown = useCallback(\n    (event: KeyboardEvent) => {\n      if (!enabled) return\n\n      const { key, shiftKey, ctrlKey, metaKey } = event\n\n      // Ignore if meta key is pressed (but allow Ctrl for month navigation)\n      if (metaKey) return\n\n      let handled = false\n\n      // Ctrl+Arrow for month navigation\n      if (ctrlKey) {\n        switch (key) {\n          case 'ArrowRight':\n            if (onMonthNavigate) {\n              onMonthNavigate('next')\n              handled = true\n            }\n            break\n          case 'ArrowLeft':\n            if (onMonthNavigate) {\n              onMonthNavigate('prev')\n              handled = true\n            }\n            break\n        }\n        if (handled) {\n          event.preventDefault()\n          event.stopPropagation()\n        }\n        return\n      }\n\n      switch (key) {\n        // Arrow navigation\n        case 'ArrowUp':\n          handleArrowNavigation('up')\n          handled = true\n          break\n        case 'ArrowDown':\n          handleArrowNavigation('down')\n          handled = true\n          break\n        case 'ArrowLeft':\n          handleArrowNavigation('left')\n          handled = true\n          break\n        case 'ArrowRight':\n          handleArrowNavigation('right')\n          handled = true\n          break\n\n        // Select date\n        case 'Enter':\n        case ' ':\n        case 'Spacebar': // For older browsers\n          onDateSelect(focusedDateRef.current)\n          handled = true\n          break\n\n        // Home/End\n        case 'Home':\n          handleHomeEnd('Home')\n          handled = true\n          break\n        case 'End':\n          handleHomeEnd('End')\n          handled = true\n          break\n\n        // PageUp/PageDown\n        case 'PageUp':\n          handlePageUpDown('PageUp')\n          handled = true\n          break\n        case 'PageDown':\n          handlePageUpDown('PageDown')\n          handled = true\n          break\n\n        // Today shortcut (T or t)\n        case 't':\n        case 'T':\n          if (onGoToToday && !shiftKey) {\n            onGoToToday()\n            handled = true\n          }\n          break\n      }\n\n      if (handled) {\n        event.preventDefault()\n        event.stopPropagation()\n      }\n    },\n    [\n      enabled,\n      handleArrowNavigation,\n      handleHomeEnd,\n      handlePageUpDown,\n      onDateSelect,\n      onGoToToday,\n      onMonthNavigate\n    ]\n  )\n\n  // Attach keyboard event listener\n  useEffect(() => {\n    const container = containerRef.current\n    if (!container || !enabled) return\n\n    container.addEventListener('keydown', handleKeyDown)\n\n    return () => {\n      container.removeEventListener('keydown', handleKeyDown)\n    }\n  }, [containerRef, enabled, handleKeyDown])\n\n  return {\n    focusedDate,\n    navigateToDate\n  }\n}\n","/**\n * Focus Trap Hook\n * Traps focus within a container element (useful for modals)\n */\n\nimport { useEffect, RefObject } from 'react'\n\nexport interface UseFocusTrapOptions {\n  /** Container ref to trap focus within */\n  containerRef: RefObject<HTMLElement>\n  /** Whether focus trap is enabled */\n  enabled?: boolean\n  /** Whether to auto-focus first element on mount */\n  autoFocus?: boolean\n  /** Whether to restore focus to trigger element on unmount */\n  restoreFocus?: boolean\n}\n\n/**\n * Get all focusable elements within a container\n */\nconst getFocusableElements = (\n  container: HTMLElement\n): NodeListOf<HTMLElement> => {\n  const selector = [\n    'a[href]',\n    'button:not([disabled])',\n    'textarea:not([disabled])',\n    'input:not([disabled])',\n    'select:not([disabled])',\n    '[tabindex]:not([tabindex=\"-1\"])'\n  ].join(', ')\n\n  return container.querySelectorAll(selector)\n}\n\n/**\n * Custom hook for trapping focus within a container\n */\nexport const useFocusTrap = (options: UseFocusTrapOptions) => {\n  const {\n    containerRef,\n    enabled = true,\n    autoFocus = true,\n    restoreFocus = true\n  } = options\n\n  useEffect(() => {\n    if (!enabled || !containerRef.current) return\n\n    const container = containerRef.current\n    const previouslyFocusedElement = document.activeElement as HTMLElement\n\n    // Auto-focus first focusable element\n    if (autoFocus) {\n      const focusableElements = getFocusableElements(container)\n      if (focusableElements.length > 0) {\n        // Small delay to ensure DOM is ready\n        setTimeout(() => {\n          focusableElements[0].focus({ preventScroll: true })\n        }, 10)\n      }\n    }\n\n    /**\n     * Handle Tab key to trap focus\n     */\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key !== 'Tab') return\n\n      const focusableElements = getFocusableElements(container)\n      if (focusableElements.length === 0) return\n\n      const firstElement = focusableElements[0]\n      const lastElement = focusableElements[focusableElements.length - 1]\n\n      // Shift + Tab\n      if (event.shiftKey) {\n        if (document.activeElement === firstElement) {\n          event.preventDefault()\n          lastElement.focus({ preventScroll: true })\n        }\n      }\n      // Tab\n      else {\n        if (document.activeElement === lastElement) {\n          event.preventDefault()\n          firstElement.focus({ preventScroll: true })\n        }\n      }\n    }\n\n    container.addEventListener('keydown', handleKeyDown)\n\n    // Cleanup\n    return () => {\n      container.removeEventListener('keydown', handleKeyDown)\n\n      // Restore focus to previously focused element\n      if (restoreFocus && previouslyFocusedElement) {\n        previouslyFocusedElement.focus()\n      }\n    }\n  }, [containerRef, enabled, autoFocus, restoreFocus])\n}\n","import { useMemo } from 'react'\nimport type {\n  CalendarTranslations,\n  CalendarUILocale,\n  SharedCalendarProps\n} from '../types/calendar'\nimport { normalizeCalendarSystem } from '../utils/date-conversion'\nimport {\n  getTranslations,\n  mergeTranslations,\n  getEffectiveLocale\n} from '../utils/translations'\n\n/**\n * Result from useCalendarSetup hook\n */\nexport interface CalendarSetupResult {\n  /** Normalized calendar system: 'gregorian' or 'jalali' */\n  normalizedCalendarSystem: 'gregorian' | 'jalali'\n  /** Effective locale based on calendar system and user locale */\n  effectiveLocale: CalendarUILocale\n  /** Merged translations with custom overrides */\n  translations: CalendarTranslations\n  /** Effective week start day (0-6) */\n  effectiveWeekStart: number\n}\n\n/**\n * Setup hook for calendar components\n *\n * Consolidates all calendar configuration logic:\n * - Calendar system normalization (handles 'ge'/'ja' aliases)\n * - Effective locale determination based on calendar system\n * - Translation management (get + merge with customizations)\n * - Week start calculation (with smart defaults)\n *\n * This hook prevents duplication between DtCalendar and DtPicker components.\n *\n * @param calendarSystem - Calendar system ('gregorian', 'jalali', 'ge', 'ja')\n * @param locale - User's desired locale\n * @param weekStart - Optional override for week start day (0-6)\n * @param customization - Customization object including custom translations\n * @returns Calendar setup result with normalized values\n *\n * @example\n * ```tsx\n * const { normalizedCalendarSystem, translations, effectiveWeekStart } = useCalendarSetup(\n *   'jalali',\n *   'en',\n *   undefined,\n *   customization\n * )\n * ```\n */\nexport function useCalendarSetup(\n  calendarSystem: 'gregorian' | 'jalali' | 'ge' | 'ja' = 'gregorian',\n  locale?: CalendarUILocale,\n  weekStart?: number,\n  customization?: SharedCalendarProps['customization']\n): CalendarSetupResult {\n  // Normalize calendarSystem input (handles 'ge'/'ja' aliases)\n  const normalizedCalendarSystem = useMemo(\n    () => normalizeCalendarSystem(calendarSystem),\n    [calendarSystem]\n  )\n\n  // Determine effective locale based on calendar system\n  const effectiveLocale = useMemo(\n    () => getEffectiveLocale(locale, normalizedCalendarSystem),\n    [locale, normalizedCalendarSystem]\n  )\n\n  // Get translations for the locale\n  const defaultTranslations = useMemo(\n    () => getTranslations(effectiveLocale),\n    [effectiveLocale]\n  )\n\n  // Merge with custom translations from customization\n  // Pass calendarSystem to ensure month names come from calendar system\n  const translations = useMemo(() => {\n    return mergeTranslations(\n      defaultTranslations,\n      customization?.translations,\n      effectiveLocale,\n      normalizedCalendarSystem\n    )\n  }, [\n    defaultTranslations,\n    customization?.translations,\n    effectiveLocale,\n    normalizedCalendarSystem\n  ])\n\n  // Auto-determine weekStart with smart defaults\n  // Calendar system determines week start, locale only affects translations\n  const effectiveWeekStart = useMemo(() => {\n    if (weekStart !== undefined) {\n      return weekStart\n    }\n    // Default: Gregorian uses Sunday (0), Jalali uses Saturday (6)\n    return normalizedCalendarSystem === 'jalali' ? 6 : 0\n  }, [weekStart, normalizedCalendarSystem])\n\n  return {\n    normalizedCalendarSystem,\n    effectiveLocale,\n    translations,\n    effectiveWeekStart\n  }\n}\n","import { useCallback } from 'react'\nimport type { Day, Range } from '../types'\n\n/**\n * Calendar actions interface\n */\nexport interface CalendarActions {\n  selectDate: (day: Day) => void\n  selectMonth: (month: number) => void\n  selectYear: (year: number) => void\n  setView: (view: 'calendar' | 'months' | 'years') => void\n  navigateMonth: (direction: 'prev' | 'next') => void\n  goToToday: () => void\n  selectPresetRange?: (range: Range) => void\n}\n\n/**\n * Callback handlers returned from useCalendarCallbacks\n */\nexport interface CalendarCallbackHandlers {\n  handleDateSelect: (day: Day) => void\n  handleMonthSelect: (month: number) => void\n  handleYearSelect: (year: number) => void\n  handleViewChange: (view: 'calendar' | 'months' | 'years') => void\n  handleMonthNavigate: (direction: 'prev' | 'next') => void\n  handleGoToToday: () => void\n  handlePresetRangeSelect: (range: Range) => void\n}\n\n/**\n * Props for useCalendarCallbacks hook\n */\nexport interface UseCalendarCallbacksProps {\n  /** Calendar actions from state management */\n  actions: CalendarActions\n  /** Optional date select callback */\n  onDateSelect?: (day: Day) => void\n  /** Optional month select callback */\n  onMonthSelect?: (month: number) => void\n  /** Optional year select callback */\n  onYearSelect?: (year: number) => void\n  /** Optional view change callback */\n  onViewChange?: (view: 'calendar' | 'months' | 'years') => void\n  /** Optional month navigate callback */\n  onMonthNavigate?: (direction: 'prev' | 'next') => void\n  /** Optional go to today callback */\n  onGoToToday?: () => void\n  /** Selection type ('single', 'range', 'multi', 'week') */\n  type?: 'single' | 'range' | 'multi' | 'week'\n}\n\n/**\n * Calendar callbacks hook\n *\n * Consolidates all callback memoization for calendar interactions.\n * This hook prevents code duplication between DtCalendar and DtPicker\n * by providing a single place to manage all calendar event handlers.\n *\n * Each handler:\n * 1. Calls the appropriate action method\n * 2. Optionally calls the corresponding user callback\n * 3. Is memoized to prevent unnecessary child re-renders\n *\n * @param props - Configuration including actions and optional callbacks\n * @returns Memoized callback handlers\n *\n * @example\n * ```tsx\n * const callbacks = useCalendarCallbacks({\n *   actions,\n *   onDateSelect: (day) => console.log('Selected:', day),\n *   type: 'range'\n * })\n *\n * // Use callbacks in component\n * <CalendarCore onDateSelect={callbacks.handleDateSelect} />\n * ```\n */\nexport function useCalendarCallbacks({\n  actions,\n  onDateSelect,\n  onMonthSelect,\n  onYearSelect,\n  onViewChange,\n  onMonthNavigate,\n  onGoToToday,\n  type = 'single'\n}: UseCalendarCallbacksProps): CalendarCallbackHandlers {\n  const handleDateSelect = useCallback(\n    (day: Day) => {\n      actions.selectDate(day)\n      onDateSelect?.(day)\n    },\n    [actions, onDateSelect]\n  )\n\n  const handleMonthSelect = useCallback(\n    (month: number) => {\n      actions.selectMonth(month)\n      onMonthSelect?.(month)\n    },\n    [actions, onMonthSelect]\n  )\n\n  const handleYearSelect = useCallback(\n    (year: number) => {\n      actions.selectYear(year)\n      onYearSelect?.(year)\n    },\n    [actions, onYearSelect]\n  )\n\n  const handleViewChange = useCallback(\n    (view: 'calendar' | 'months' | 'years') => {\n      actions.setView(view)\n      onViewChange?.(view)\n    },\n    [actions, onViewChange]\n  )\n\n  const handleMonthNavigate = useCallback(\n    (direction: 'prev' | 'next') => {\n      actions.navigateMonth(direction)\n      onMonthNavigate?.(direction)\n    },\n    [actions, onMonthNavigate]\n  )\n\n  const handleGoToToday = useCallback(() => {\n    actions.goToToday()\n    onGoToToday?.()\n  }, [actions, onGoToToday])\n\n  const handlePresetRangeSelect = useCallback(\n    (range: Range) => {\n      if (type === 'range') {\n        // Directly set the range for preset selections\n        actions.selectPresetRange?.(range)\n      } else if (type === 'week') {\n        // For week type, select the start date which will calculate the week bounds\n        actions.selectDate(range.from)\n      }\n    },\n    [actions, type]\n  )\n\n  return {\n    handleDateSelect,\n    handleMonthSelect,\n    handleYearSelect,\n    handleViewChange,\n    handleMonthNavigate,\n    handleGoToToday,\n    handlePresetRangeSelect\n  }\n}\n","import { useState, useRef, useCallback } from 'react'\nimport { useClickOutside, useEscapeKey, useFocusTrap } from './index'\n\n/**\n * Modal state result\n */\nexport interface ModalStateResult {\n  /** Whether modal is currently open */\n  isOpen: boolean\n  /** Modal handlers (open, close, toggle) */\n  handlers: {\n    open: () => void\n    close: () => void\n    toggle: () => void\n  }\n  /** Refs for modal and trigger elements */\n  refs: {\n    /** Ref for modal container */\n    modalRef: React.RefObject<HTMLDivElement>\n    /** Ref for trigger wrapper/picker container */\n    pickerRef: React.RefObject<HTMLDivElement>\n  }\n}\n\n/**\n * Modal state hook\n *\n * Encapsulates all modal state management and behavior:\n * - State (isOpen)\n * - Handlers (open, close, toggle)\n * - Refs for modal and trigger elements\n * - Keyboard handling (Escape key closes modal)\n * - Click outside handling (clicking outside closes modal)\n * - Focus trap (keeps focus within modal when open)\n *\n * This hook consolidates scattered modal logic from components\n * and makes it reusable across different modal components.\n *\n * @param options - Optional configuration\n * @param options.autoFocus - Whether to auto-focus modal content (default: true)\n * @param options.restoreFocus - Whether to restore focus when closing (default: true)\n * @returns Modal state and handlers\n *\n * @example\n * ```tsx\n * const { isOpen, handlers, refs } = useModalState()\n *\n * return (\n *   <div ref={refs.pickerRef}>\n *     <button onClick={handlers.toggle}>Open</button>\n *\n *     {isOpen && (\n *       <div ref={refs.modalRef} role=\"dialog\">\n *         Modal content here\n *       </div>\n *     )}\n *   </div>\n * )\n * ```\n */\nexport function useModalState(options?: {\n  autoFocus?: boolean\n  restoreFocus?: boolean\n}): ModalStateResult {\n  const [isOpen, setIsOpen] = useState(false)\n  const pickerRef = useRef<HTMLDivElement>(null)\n  const modalRef = useRef<HTMLDivElement>(null)\n\n  const handlers = {\n    open: useCallback(() => setIsOpen(true), []),\n    close: useCallback(() => setIsOpen(false), []),\n    toggle: useCallback(() => setIsOpen((prev) => !prev), [])\n  }\n\n  // Handle click outside - closes modal\n  useClickOutside(isOpen, pickerRef, modalRef, handlers.close)\n\n  // Handle Escape key - closes modal\n  useEscapeKey(isOpen, handlers.close)\n\n  // Handle focus trap - keeps focus within modal when open\n  useFocusTrap({\n    containerRef: modalRef as React.RefObject<HTMLElement>,\n    enabled: isOpen,\n    autoFocus: options?.autoFocus ?? true,\n    restoreFocus: options?.restoreFocus ?? true\n  })\n\n  return {\n    isOpen,\n    handlers,\n    refs: {\n      modalRef: modalRef as React.RefObject<HTMLDivElement>,\n      pickerRef: pickerRef as React.RefObject<HTMLDivElement>\n    }\n  }\n}\n","import { useEffect, type RefObject } from 'react'\n\n/**\n * Hook to detect clicks outside of specified elements\n */\nexport function useClickOutside(\n  isOpen: boolean,\n  pickerRef: RefObject<HTMLDivElement | null>,\n  modalRef: RefObject<HTMLDivElement | null>,\n  onClose: () => void\n) {\n  useEffect(() => {\n    if (!isOpen) return\n\n    const handleClickOutside = (event: MouseEvent) => {\n      const target = event.target as Node | null\n      if (!target) return\n\n      // Check if click is on input or buttons - these should not close the modal\n      const clickedElement = target as Element\n      const isInput = clickedElement.closest?.('.calendar-picker-input')\n      const isToggleButton = clickedElement.closest?.('.calendar-picker-toggle')\n      const isClearButton = clickedElement.closest?.('.calendar-picker-clear')\n\n      // If clicking on input or buttons, don't close (they handle their own clicks)\n      if (isInput || isToggleButton || isClearButton) {\n        return\n      }\n\n      // Check if click is inside the calendar-core (the actual calendar component)\n      const calendarCore = modalRef.current?.querySelector('.calendar-core')\n      const isInsideCalendar = calendarCore?.contains(target) ?? false\n\n      // Close if click is outside the calendar\n      if (!isInsideCalendar) {\n        onClose()\n      }\n    }\n\n    // Use a delay to ensure input click handlers fire first\n    const timeoutId = setTimeout(() => {\n      document.addEventListener('mousedown', handleClickOutside, true)\n    }, 150)\n\n    return () => {\n      clearTimeout(timeoutId)\n      document.removeEventListener('mousedown', handleClickOutside, true)\n    }\n  }, [isOpen, pickerRef, modalRef, onClose])\n}\n","import { useEffect } from 'react'\n\n/**\n * Hook to handle Escape key press\n */\nexport function useEscapeKey(isOpen: boolean, onClose: () => void) {\n  useEffect(() => {\n    const handleEscape = (event: KeyboardEvent) => {\n      if (event.key === 'Escape' && isOpen) {\n        onClose()\n      }\n    }\n\n    document.addEventListener('keydown', handleEscape)\n    return () => {\n      document.removeEventListener('keydown', handleEscape)\n    }\n  }, [isOpen, onClose])\n}\n","import { useMemo } from 'react'\nimport type { CalendarError } from '../types/calendar'\nimport { useCallbackOnChange } from './useCallbackOnChange'\n\n/**\n * Hook for handling calendar errors\n *\n * This hook consolidates error handling logic for calendar components.\n * It combines constraints errors and initValue errors, and calls the onError\n * callback when errors change.\n *\n * @param constraintsErrors - Errors from constraints normalization\n * @param initValueErrors - Errors from initValue normalization\n * @param onError - Optional callback to handle errors\n *\n * @example\n * ```tsx\n * const constraintsResult = normalizeConstraintsProps(...)\n * const initValueResult = normalizeInitValueWithErrors(...)\n *\n * useCalendarErrorHandling(\n *   constraintsResult.errors,\n *   initValueResult.errors,\n *   onError\n * )\n * ```\n */\nexport function useCalendarErrorHandling(\n  constraintsErrors: CalendarError[],\n  initValueErrors: CalendarError[],\n  onError?: (errors: CalendarError[]) => void\n): void {\n  // Collect all errors\n  const allErrors = useMemo(\n    () => [...constraintsErrors, ...initValueErrors],\n    [constraintsErrors, initValueErrors]\n  )\n\n  // Use callback on change hook for error handling\n  // Use custom comparison to detect actual error changes (not just reference changes)\n  useCallbackOnChange(\n    allErrors,\n    (errors) => {\n      if (errors.length > 0 && onError) {\n        onError(errors)\n      }\n    },\n    (a, b) => {\n      // Compare arrays by content, not reference\n      if (!a || !b) return a === b\n      if (a.length !== b.length) return false\n      return a.every(\n        (error, index) =>\n          error.type === b[index]?.type &&\n          error.field === b[index]?.field &&\n          error.message === b[index]?.message\n      )\n    }\n  )\n}\n","import { useEffect, useRef } from 'react'\n\n/**\n * Callback on change hook\n *\n * Detects when a value changes and calls a callback function.\n * Useful for effects that should only run when a value actually changes,\n * not on every render.\n *\n * This hook prevents issues with:\n * - Infinite loops from effect dependencies\n * - Calling callbacks too frequently\n * - Fragile string-based comparison logic\n *\n * @param value - The value to monitor for changes\n * @param callback - The function to call when value changes\n * @param compareFn - Optional custom comparison function (defaults to ===)\n *\n * @example\n * ```tsx\n * // Simple equality check\n * useCallbackOnChange(errors, (newErrors) => {\n *   onError(newErrors)\n * })\n *\n * // Custom comparison for complex types\n * useCallbackOnChange(\n *   items,\n *   (newItems) => console.log('Items changed'),\n *   (a, b) => JSON.stringify(a) === JSON.stringify(b)\n * )\n * ```\n */\nexport function useCallbackOnChange<T>(\n  value: T,\n  callback: (value: T) => void,\n  compareFn?: (a: T | undefined, b: T | undefined) => boolean\n): void {\n  const prevValueRef = useRef<T | undefined>(undefined)\n\n  useEffect(() => {\n    // Use custom comparison if provided, otherwise use reference equality (===)\n    const hasChanged = compareFn\n      ? !compareFn(value, prevValueRef.current)\n      : value !== prevValueRef.current\n\n    if (hasChanged) {\n      callback(value)\n      prevValueRef.current = value\n    }\n  }, [value, callback, compareFn])\n}\n","/**\n * Calendar Grid View Component\n * Displays the calendar grid with days\n */\n\nimport React, { useRef, useMemo } from 'react'\nimport type {\n  Day,\n  Range,\n  Multi,\n  Week,\n  CalendarLocale,\n  CalendarType,\n  CalendarTranslations\n} from '../types'\nimport type {\n  CalendarConstraints,\n  CalendarCustomization,\n  PresetRangesConfig\n} from '../types/calendar'\nimport {\n  generateCalendarGrid,\n  getWeekBounds,\n  getMonthsToDisplay\n} from '../utils/calendar-grid'\nimport { isDateSelectable } from '../utils/validation'\nimport {\n  isDaySelected,\n  isDayInRange,\n  isRangeStart,\n  isRangeEnd\n} from '../utils/calendar-selection'\nimport {\n  formatNumber,\n  detectTimeFormatFromDateFormat\n} from '../utils/formatting'\nimport { getToday } from '../utils/date-conversion'\nimport {\n  getPresetRangesFromConfig,\n  isPresetRangeActive\n} from '../utils/preset-ranges'\nimport {\n  getRotatedWeekdayNames,\n  getWeekendConfig\n} from '../utils/weekday-utils'\nimport { CalendarHeader } from './CalendarHeader'\nimport { TimeSelector } from './TimeSelector'\nimport { useKeyboardNavigation, useFocusManagement } from '../hooks'\n\nexport interface CalendarGridViewProps {\n  /** Currently selected value */\n  selectedValue: Day | Range | Multi | Week | null\n  /** Currently displayed month */\n  displayMonth: Day\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Locale for internationalization */\n  locale: string\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Calendar selection type */\n  type: CalendarType\n  /** Enable time selection */\n  withTime?: boolean\n  /** Custom date format string (used to detect time format) */\n  dateFormat?: string\n  /** Time format: '12' for 12-hour format, '24' for 24-hour format (detected from dateFormat if not provided) */\n  timeFormat?: '12' | '24'\n  /** Show weekend highlighting */\n  showWeekend?: boolean\n  /** First day of the week (0 = Sunday, 6 = Saturday) */\n  weekStart?: number\n  /** Show today button */\n  todayBtn?: boolean\n  /** Preset range buttons configuration */\n  presetRanges?: PresetRangesConfig\n  /** Enlarge selected day text */\n  enlargeSelectedDay?: boolean\n  /** Date constraints */\n  constraints?: CalendarConstraints\n  /** Customization options */\n  customization?: CalendarCustomization\n  /** Callback when date is selected */\n  onDateSelect: (day: Day) => void\n  /** Callback when time changes */\n  onTimeChange?: (day: Day, hour: number, minute: number) => void\n  /** Callback when navigating months */\n  onMonthNavigate: (direction: 'prev' | 'next') => void\n  /** Callback when view changes */\n  onViewChange: (view: 'months' | 'years') => void\n  /** Callback to navigate to today's date */\n  onGoToToday?: () => void\n  /** Callback when preset range is selected */\n  onPresetRangeSelect?: (range: Range) => void\n  /** Number of months to display side by side */\n  numberOfMonths?: 1 | 2 | 3\n}\n\nconst CalendarGridViewInner: React.FC<CalendarGridViewProps> = (props) => {\n  const {\n    selectedValue,\n    displayMonth,\n    calendarSystem,\n    locale: _locale,\n    translations,\n    type,\n    withTime = false,\n    dateFormat,\n    timeFormat,\n    showWeekend = false,\n    weekStart,\n    todayBtn = false,\n    presetRanges,\n    enlargeSelectedDay = true,\n    constraints = {},\n    customization = {},\n    onDateSelect,\n    onTimeChange,\n    onMonthNavigate,\n    onViewChange,\n    onGoToToday,\n    onPresetRangeSelect,\n    numberOfMonths = 1\n  } = props\n\n  // Detect time format from dateFormat if not provided\n  const effectiveTimeFormat =\n    timeFormat || detectTimeFormatFromDateFormat(dateFormat)\n\n  const { maxDate, minDate, disabledDates, isDateDisabled } = constraints\n  const { classes = {}, labels = {} } = customization\n\n  const { days: daysClass } = classes\n  const { nextMonth: nextMonthBtnTitle, previousMonth: previousMonthBtnTitle } =\n    labels\n\n  const isRTL = translations.direction === 'rtl'\n  // Rotate weekday names based on weekStart and calendar system\n  const dayNames = useMemo(\n    () =>\n      getRotatedWeekdayNames(translations.weekdays, calendarSystem, weekStart),\n    [translations.weekdays, calendarSystem, weekStart]\n  )\n  const monthNames = translations.months\n\n  // Get all months to display\n  const monthsToDisplay = getMonthsToDisplay(\n    displayMonth,\n    numberOfMonths,\n    calendarSystem\n  )\n\n  // 🟢 Memoize expensive calendar grid generation - only recompute when dependencies change\n  const calendarGrids = useMemo(() => {\n    return monthsToDisplay.map((month) =>\n      generateCalendarGrid(month, calendarSystem, weekStart)\n    )\n  }, [monthsToDisplay, calendarSystem, weekStart])\n\n  // Refs for keyboard navigation\n  const gridRef = useRef<HTMLDivElement>(null)\n  const gridElementRef = gridRef as unknown as React.RefObject<HTMLElement>\n\n  // Get selected date for focus management\n  const getSelectedDate = (): Day | null => {\n    if (!selectedValue) return null\n    if (type === 'single') return selectedValue as Day\n    if (type === 'range') return (selectedValue as Range).from\n    if (type === 'week') return (selectedValue as Week).from\n    if (type === 'multi' && (selectedValue as Multi).length > 0) {\n      return (selectedValue as Multi)[0]\n    }\n    return null\n  }\n\n  // Validation function for keyboard navigation\n  const isDateSelectableForNav = React.useCallback(\n    (day: Day): boolean => {\n      return isDateSelectable(day, {\n        minDate,\n        maxDate,\n        disabledDates,\n        isDateDisabled,\n        calendarSystem\n      })\n    },\n    [minDate, maxDate, disabledDates, isDateDisabled, calendarSystem]\n  )\n\n  // Focus management\n  const { focusedDate, setFocusedDate, getCellRef } = useFocusManagement({\n    initialDate: displayMonth,\n    selectedDate: getSelectedDate()\n  })\n\n  // Sync focused date when displayMonth changes (e.g., after month navigation)\n  React.useEffect(() => {\n    // If focused date is not in the current display month, adjust it\n    if (\n      focusedDate.year !== displayMonth.year ||\n      focusedDate.month !== displayMonth.month\n    ) {\n      // Keep the same day if possible, otherwise use first day of month\n      const newFocusedDate: Day = {\n        year: displayMonth.year,\n        month: displayMonth.month,\n        day: Math.min(focusedDate.day, 31) // Will be validated by isDateSelectable\n      }\n      // Only update if the date is selectable\n      if (isDateSelectableForNav(newFocusedDate)) {\n        setFocusedDate(newFocusedDate)\n      } else {\n        // Try first day of month\n        const firstDay: Day = {\n          year: displayMonth.year,\n          month: displayMonth.month,\n          day: 1\n        }\n        if (isDateSelectableForNav(firstDay)) {\n          setFocusedDate(firstDay)\n        }\n      }\n    }\n  }, [\n    displayMonth.year,\n    displayMonth.month,\n    focusedDate,\n    isDateSelectableForNav,\n    setFocusedDate\n  ]) // Only when month/year changes\n\n  // Wrapper for onGoToToday that also updates focused date\n  const handleGoToToday = React.useCallback(() => {\n    if (onGoToToday) {\n      onGoToToday()\n    }\n    // Update focused date to today\n    const today = getToday(calendarSystem)\n    setFocusedDate(today)\n  }, [onGoToToday, calendarSystem, setFocusedDate])\n\n  // Keyboard navigation\n  useKeyboardNavigation({\n    focusedDate,\n    calendarSystem,\n    type,\n    containerRef: gridElementRef,\n    enabled: true,\n    onFocusedDateChange: setFocusedDate,\n    onDateSelect,\n    onGoToToday: handleGoToToday,\n    onMonthNavigate,\n    isDateSelectable: isDateSelectableForNav\n  })\n\n  // Render a single month grid\n  const renderMonthGrid = (\n    month: Day,\n    grid: ReturnType<typeof generateCalendarGrid>,\n    monthIndex: number\n  ) => {\n    const monthLabel = monthNames[month.month - 1]\n    const yearLabel = formatNumber(month.year, translations.numbers)\n\n    return (\n      <div\n        key={`month-${month.year}-${month.month}`}\n        className={`calendar-month-container ${numberOfMonths > 1 ? 'calendar-month-multi' : ''}`}\n      >\n        {/* Month header for multiple months */}\n        {numberOfMonths > 1 && (\n          <div className='calendar-month-header'>\n            <span className='calendar-month-title'>\n              {monthLabel} {yearLabel}\n            </span>\n          </div>\n        )}\n\n        {/* Day names - only show for first month or each month in multi-month view */}\n        {(monthIndex === 0 || numberOfMonths > 1) && (\n          <div className='calendar-day-names' role='row'>\n            {dayNames.map((name, index) => {\n              const weekendConfig = getWeekendConfig(calendarSystem, weekStart)\n              const isWeekendDay = showWeekend && weekendConfig.isWeekend(index)\n\n              const dayNameClassNames = [\n                'calendar-day-name',\n                isWeekendDay && 'calendar-weekend'\n              ]\n                .filter(Boolean)\n                .join(' ')\n\n              return (\n                <div\n                  key={`day-name-${monthIndex}-${index}-${name}`}\n                  className={dayNameClassNames}\n                  role='columnheader'\n                  aria-label={name}\n                >\n                  {name}\n                </div>\n              )\n            })}\n          </div>\n        )}\n\n        {/* Calendar grid */}\n        <div\n          ref={monthIndex === 0 ? gridRef : undefined}\n          className={`calendar-grid ${daysClass || ''}`}\n          role='grid'\n          aria-label={`${monthLabel} ${yearLabel}`}\n          aria-activedescendant={\n            monthIndex === 0\n              ? `day-${focusedDate.year}-${focusedDate.month}-${focusedDate.day}`\n              : undefined\n          }\n          tabIndex={monthIndex === 0 ? 0 : -1}\n        >\n          {grid\n            .filter((week) => {\n              // Filter out weeks where all days are from other months\n              const hasCurrentMonthDay = week.some((day) => day.isCurrentMonth)\n              return hasCurrentMonthDay\n            })\n            .map((week, weekIndex) => {\n              const hasOtherMonth = week.some((day) => !day.isCurrentMonth)\n              const weekClassNames = [\n                'calendar-week',\n                hasOtherMonth && 'calendar-week-other-month'\n              ]\n                .filter(Boolean)\n                .join(' ')\n\n              return (\n                <div key={weekIndex} className={weekClassNames} role='row'>\n                  {week.map((calendarDay, dayIndex) => {\n                    const day: Day = calendarDay.dayObject\n\n                    // Hide days from other months when displaying multiple months\n                    const isOtherMonth = !calendarDay.isCurrentMonth\n                    if (numberOfMonths > 1 && isOtherMonth) {\n                      // Render empty cell to maintain grid structure\n                      return (\n                        <div\n                          key={`${weekIndex}-${dayIndex}-empty`}\n                          className='calendar-day calendar-day-empty'\n                          role='gridcell'\n                          aria-hidden='true'\n                        />\n                      )\n                    }\n\n                    const isSelected = isDaySelected(\n                      day,\n                      selectedValue,\n                      type,\n                      calendarSystem\n                    )\n                    const isInRange = isDayInRange(\n                      day,\n                      selectedValue,\n                      type,\n                      calendarSystem\n                    )\n                    const isStart = isRangeStart(day, selectedValue, type)\n                    const isEnd = isRangeEnd(day, selectedValue, type)\n                    const isSelectable = isDateSelectable(day, {\n                      minDate,\n                      maxDate,\n                      disabledDates,\n                      isDateDisabled,\n                      calendarSystem\n                    })\n\n                    // Calculate if this day is a weekend\n                    const weekendConfig = getWeekendConfig(\n                      calendarSystem,\n                      weekStart\n                    )\n                    const isWeekend =\n                      showWeekend && weekendConfig.isWeekend(dayIndex)\n\n                    // Determine if this is from previous month or next month\n                    const isPrevMonth =\n                      isOtherMonth &&\n                      (calendarDay.year < month.year ||\n                        (calendarDay.year === month.year &&\n                          calendarDay.month < month.month))\n                    const isNextMonth =\n                      isOtherMonth &&\n                      (calendarDay.year > month.year ||\n                        (calendarDay.year === month.year &&\n                          calendarDay.month > month.month))\n\n                    // Last day of previous month: previous month day where next day is current month\n                    const isLastDayOfPrevMonth =\n                      isPrevMonth &&\n                      dayIndex < 6 &&\n                      week[dayIndex + 1].isCurrentMonth\n\n                    // First day of next month: next month day where previous day is current month\n                    const isFirstDayOfNextMonth =\n                      isNextMonth &&\n                      dayIndex > 0 &&\n                      week[dayIndex - 1].isCurrentMonth\n\n                    const classNames = [\n                      'calendar-day',\n                      isOtherMonth && 'calendar-day-other-month',\n                      isFirstDayOfNextMonth && 'calendar-day-other-month-first',\n                      isLastDayOfPrevMonth && 'calendar-day-other-month-last',\n                      calendarDay.isToday && 'calendar-day-today',\n                      isSelected && 'calendar-day-selected',\n                      isSelected &&\n                        enlargeSelectedDay &&\n                        'calendar-day-selected-enlarged',\n                      isInRange && 'calendar-day-in-range',\n                      isStart && 'calendar-day-range-start',\n                      isEnd && 'calendar-day-range-end',\n                      !isSelectable && 'calendar-day-disabled',\n                      isWeekend && 'calendar-day-weekend'\n                    ]\n                      .filter(Boolean)\n                      .join(' ')\n\n                    const handleClick = () => {\n                      if (isSelectable) {\n                        // For week type, select the entire week containing this day\n                        if (type === 'week') {\n                          const weekBounds = getWeekBounds(\n                            day,\n                            calendarSystem,\n                            weekStart\n                          )\n                          // Select the first day of the week (the week selection logic will handle the rest)\n                          onDateSelect(weekBounds.from)\n                        } else {\n                          onDateSelect(day)\n                        }\n                      }\n                    }\n\n                    // Check if this date is focused\n                    const isFocused =\n                      focusedDate.year === day.year &&\n                      focusedDate.month === day.month &&\n                      focusedDate.day === day.day\n\n                    // Create accessible label\n                    const dayLabel = formatNumber(\n                      calendarDay.day,\n                      translations.numbers\n                    )\n\n                    const monthLabel = monthNames[day.month - 1]\n                    const yearLabel = formatNumber(\n                      day.year,\n                      translations.numbers\n                    )\n\n                    const ariaLabel = `${dayLabel} ${monthLabel} ${yearLabel}`\n                    const todayLabel = translations.labels.today\n                    const fullAriaLabel = calendarDay.isToday\n                      ? `${ariaLabel}, ${todayLabel}`\n                      : ariaLabel\n\n                    return (\n                      <button\n                        key={`${weekIndex}-${dayIndex}-${day.year}-${day.month}-${day.day}`}\n                        ref={getCellRef(day)}\n                        id={`day-${day.year}-${day.month}-${day.day}`}\n                        type='button'\n                        role='gridcell'\n                        onClick={handleClick}\n                        disabled={!isSelectable}\n                        className={classNames}\n                        aria-label={fullAriaLabel}\n                        aria-selected={isSelected}\n                        aria-disabled={!isSelectable}\n                        aria-current={calendarDay.isToday ? 'date' : undefined}\n                        tabIndex={isFocused ? 0 : -1}\n                      >\n                        {formatNumber(calendarDay.day, translations.numbers)}\n                      </button>\n                    )\n                  })}\n                </div>\n              )\n            })}\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div\n      className={`calendar-core ${numberOfMonths > 1 ? 'calendar-core-multi-months' : ''}`}\n      dir={isRTL ? 'rtl' : 'ltr'}\n    >\n      {/* Header - only show for single month or show range for multiple months */}\n      <CalendarHeader\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        translations={translations}\n        customization={customization}\n        onPrevious={() => onMonthNavigate('prev')}\n        onNext={() => onMonthNavigate('next')}\n        onMonthClick={() => onViewChange('months')}\n        onYearClick={() => onViewChange('years')}\n        previousTitle={previousMonthBtnTitle}\n        nextTitle={nextMonthBtnTitle}\n        showMonth={numberOfMonths === 1}\n      />\n\n      {/* Multiple months container */}\n      <div\n        className={`calendar-months-wrapper ${numberOfMonths > 1 ? 'calendar-months-multi' : ''}`}\n      >\n        {monthsToDisplay.map((month, index) =>\n          renderMonthGrid(month, calendarGrids[index], index)\n        )}\n      </div>\n\n      {/* Footer */}\n      {(todayBtn ||\n        (withTime && type !== 'multi' && onTimeChange) ||\n        (presetRanges && type === 'range')) && (\n        <div className='calendar-footer'>\n          {/* Time Selector - Only for single, range, and week modes, not multi */}\n          {withTime && type !== 'multi' && onTimeChange && (\n            <div className='calendar-time-selector'>\n              {type === 'single' ? (\n                <TimeSelector\n                  day={selectedValue as Day | null}\n                  timeFormat={effectiveTimeFormat}\n                  translations={translations}\n                  disabled={!selectedValue}\n                  onTimeChange={(hour, minute) => {\n                    const day = selectedValue as Day | null\n                    if (day) {\n                      onTimeChange(day, hour, minute)\n                    }\n                  }}\n                />\n              ) : type === 'range' ? (\n                <div className='calendar-time-selector-range'>\n                  <TimeSelector\n                    day={(selectedValue as Range | null)?.from || null}\n                    timeFormat={effectiveTimeFormat}\n                    translations={translations}\n                    label={translations.labels.timeFrom}\n                    disabled={!(selectedValue as Range | null)?.from}\n                    onTimeChange={(hour, minute) => {\n                      const range = selectedValue as Range | null\n                      if (range?.from) {\n                        onTimeChange(range.from, hour, minute)\n                      }\n                    }}\n                  />\n                  <TimeSelector\n                    day={(selectedValue as Range | null)?.to || null}\n                    timeFormat={effectiveTimeFormat}\n                    translations={translations}\n                    label={translations.labels.timeTo}\n                    disabled={!(selectedValue as Range | null)?.to}\n                    onTimeChange={(hour, minute) => {\n                      const range = selectedValue as Range | null\n                      if (range?.to) {\n                        onTimeChange(range.to, hour, minute)\n                      }\n                    }}\n                  />\n                </div>\n              ) : type === 'week' ? (\n                <div className='calendar-time-selector-range'>\n                  <TimeSelector\n                    day={(selectedValue as Week | null)?.from || null}\n                    timeFormat={effectiveTimeFormat}\n                    translations={translations}\n                    label={translations.labels.timeFrom}\n                    disabled={!(selectedValue as Week | null)?.from}\n                    onTimeChange={(hour, minute) => {\n                      const week = selectedValue as Week | null\n                      if (week?.from) {\n                        onTimeChange(week.from, hour, minute)\n                      }\n                    }}\n                  />\n                  <TimeSelector\n                    day={(selectedValue as Week | null)?.to || null}\n                    timeFormat={effectiveTimeFormat}\n                    translations={translations}\n                    label={translations.labels.timeTo}\n                    disabled={!(selectedValue as Week | null)?.to}\n                    onTimeChange={(hour, minute) => {\n                      const week = selectedValue as Week | null\n                      if (week?.to) {\n                        onTimeChange(week.to, hour, minute)\n                      }\n                    }}\n                  />\n                </div>\n              ) : null}\n            </div>\n          )}\n\n          {/* Preset Range Buttons - Only for range mode */}\n          {presetRanges && type === 'range' && (\n            <div className='calendar-preset-ranges'>\n              {getPresetRangesFromConfig(\n                presetRanges,\n                calendarSystem,\n                translations.presetRanges\n              ).map((preset, index) => {\n                const currentRange = selectedValue as Range | null\n                const isActive = isPresetRangeActive(\n                  preset.range,\n                  currentRange,\n                  calendarSystem\n                )\n                return (\n                  <button\n                    key={\n                      preset.value === 'custom'\n                        ? `custom-${index}`\n                        : preset.value\n                    }\n                    type='button'\n                    onClick={() => {\n                      if (onPresetRangeSelect) {\n                        onPresetRangeSelect(preset.range)\n                      }\n                    }}\n                    className={`calendar-preset-btn ${\n                      isActive ? 'calendar-preset-btn-active' : ''\n                    }`}\n                  >\n                    {preset.label}\n                  </button>\n                )\n              })}\n            </div>\n          )}\n\n          {/* Today Button */}\n          {todayBtn && (\n            <button\n              type='button'\n              onClick={() => {\n                if (onGoToToday) {\n                  onGoToToday()\n                }\n              }}\n              className='calendar-today-btn'\n            >\n              {translations.labels.today}\n            </button>\n          )}\n        </div>\n      )}\n    </div>\n  )\n}\n\n// 🟢 Memoize component to prevent unnecessary re-renders\nexport const CalendarGridView = React.memo(\n  CalendarGridViewInner,\n  (prevProps, nextProps) => {\n    // Return TRUE if props are equal (skip re-render)\n    return (\n      prevProps.selectedValue === nextProps.selectedValue &&\n      prevProps.displayMonth === nextProps.displayMonth &&\n      prevProps.calendarSystem === nextProps.calendarSystem &&\n      prevProps.locale === nextProps.locale &&\n      prevProps.translations === nextProps.translations &&\n      prevProps.type === nextProps.type &&\n      prevProps.withTime === nextProps.withTime &&\n      prevProps.dateFormat === nextProps.dateFormat &&\n      prevProps.timeFormat === nextProps.timeFormat &&\n      prevProps.showWeekend === nextProps.showWeekend &&\n      prevProps.weekStart === nextProps.weekStart &&\n      prevProps.todayBtn === nextProps.todayBtn &&\n      prevProps.enlargeSelectedDay === nextProps.enlargeSelectedDay &&\n      prevProps.numberOfMonths === nextProps.numberOfMonths &&\n      prevProps.constraints === nextProps.constraints &&\n      prevProps.customization === nextProps.customization &&\n      prevProps.presetRanges === nextProps.presetRanges &&\n      prevProps.onDateSelect === nextProps.onDateSelect &&\n      prevProps.onTimeChange === nextProps.onTimeChange &&\n      prevProps.onMonthNavigate === nextProps.onMonthNavigate &&\n      prevProps.onViewChange === nextProps.onViewChange &&\n      prevProps.onGoToToday === nextProps.onGoToToday &&\n      prevProps.onPresetRangeSelect === nextProps.onPresetRangeSelect\n    )\n  }\n)\n\nCalendarGridView.displayName = 'CalendarGridView'\n","/**\n * Focus Management Hook\n * Manages focus state for calendar date grid\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react'\nimport type { Day } from '../types'\n\nexport interface UseFocusManagementOptions {\n  /** Initial focused date */\n  initialDate: Day\n  /** Currently selected date */\n  selectedDate?: Day | null\n}\n\nexport interface UseFocusManagementReturn {\n  /** Currently focused date */\n  focusedDate: Day\n  /** Set the focused date */\n  setFocusedDate: (date: Day) => void\n  /** Reset focus to selected date or initial date */\n  resetFocus: () => void\n  /** Get ref callback for a date cell */\n  getCellRef: (date: Day) => (element: HTMLButtonElement | null) => void\n  /** Focus a specific date cell */\n  focusDate: (date: Day) => void\n}\n\n/**\n * Custom hook for managing focus in calendar\n */\nexport const useFocusManagement = (\n  options: UseFocusManagementOptions\n): UseFocusManagementReturn => {\n  const { initialDate, selectedDate } = options\n\n  // Use selected date as initial focus if available\n  const [focusedDate, setFocusedDate] = useState<Day>(\n    selectedDate || initialDate\n  )\n\n  // Store refs to all date cells\n  const cellRefs = useRef<Map<string, HTMLButtonElement>>(new Map())\n\n  /**\n   * Generate unique key for a date\n   */\n  const getDateKey = useCallback((date: Day): string => {\n    return `${date.year}-${date.month}-${date.day}`\n  }, [])\n\n  /**\n   * Get ref callback for a date cell\n   */\n  const getCellRef = useCallback(\n    (date: Day) => (element: HTMLButtonElement | null) => {\n      const key = getDateKey(date)\n      if (element) {\n        cellRefs.current.set(key, element)\n      } else {\n        cellRefs.current.delete(key)\n      }\n    },\n    [getDateKey]\n  )\n\n  /**\n   * Focus a specific date cell\n   */\n  const focusDate = useCallback(\n    (date: Day) => {\n      const key = getDateKey(date)\n      const element = cellRefs.current.get(key)\n      if (element) {\n        element.focus({ preventScroll: true })\n      }\n    },\n    [getDateKey]\n  )\n\n  /**\n   * Reset focus to selected date or initial date\n   */\n  const resetFocus = useCallback(() => {\n    const newFocus = selectedDate || initialDate\n    setFocusedDate(newFocus)\n    focusDate(newFocus)\n  }, [selectedDate, initialDate, focusDate])\n\n  /**\n   * Update focused date when selected date changes\n   */\n  useEffect(() => {\n    if (selectedDate) {\n      // eslint-disable-next-line react-hooks/set-state-in-effect\n      setFocusedDate(selectedDate)\n    }\n  }, [selectedDate])\n\n  /**\n   * Focus the focused date cell when it changes\n   */\n  useEffect(() => {\n    const key = getDateKey(focusedDate)\n    const element = cellRefs.current.get(key)\n\n    if (element) {\n      // Use a small delay to ensure DOM is ready after re-renders\n      const timeoutId = setTimeout(() => {\n        element.focus({ preventScroll: true })\n      }, 0)\n\n      return () => clearTimeout(timeoutId)\n    }\n  }, [focusedDate, getDateKey])\n\n  return {\n    focusedDate,\n    setFocusedDate,\n    resetFocus,\n    getCellRef,\n    focusDate\n  }\n}\n","/**\n * Calendar selection utilities\n * Helper functions for determining selection state\n */\n\nimport type {\n  Day,\n  Range,\n  Multi,\n  Week,\n  CalendarType,\n  CalendarLocale\n} from '../types'\nimport { compareDays } from './validation'\n\n/**\n * Check if a day is selected based on selection type\n */\nexport function isDaySelected(\n  day: Day,\n  selectedValue: Day | Range | Multi | Week | null,\n  type: CalendarType,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  if (!selectedValue) return false\n\n  if (type === 'single') {\n    const selected = selectedValue as Day\n    return (\n      day.year === selected.year &&\n      day.month === selected.month &&\n      day.day === selected.day\n    )\n  }\n\n  if (type === 'range') {\n    const range = selectedValue as Range\n    if (!range.from || !range.to) return false\n    const dayCompare = compareDays(day, range.from, calendarSystem)\n    const toCompare = compareDays(day, range.to, calendarSystem)\n    return dayCompare >= 0 && toCompare <= 0\n  }\n\n  if (type === 'week') {\n    const week = selectedValue as Week\n    if (!week.from || !week.to) return false\n    const dayCompare = compareDays(day, week.from, calendarSystem)\n    const toCompare = compareDays(day, week.to, calendarSystem)\n    return dayCompare >= 0 && toCompare <= 0\n  }\n\n  if (type === 'multi') {\n    const multi = selectedValue as Multi\n    return multi.some(\n      (selectedDay) =>\n        day.year === selectedDay.year &&\n        day.month === selectedDay.month &&\n        day.day === selectedDay.day\n    )\n  }\n\n  return false\n}\n\n/**\n * Check if a day is in range selection (for range or week type)\n * Returns true if day is between from and to (exclusive of boundaries for styling)\n */\nexport function isDayInRange(\n  day: Day,\n  selectedValue: Day | Range | Multi | Week | null,\n  type: CalendarType,\n  calendarSystem: CalendarLocale = 'gregorian'\n): boolean {\n  if ((type !== 'range' && type !== 'week') || !selectedValue) return false\n\n  let from: Day | null = null\n  let to: Day | null = null\n\n  if (type === 'range') {\n    const range = selectedValue as Range\n    from = range.from\n    to = range.to\n  } else if (type === 'week') {\n    const week = selectedValue as Week\n    from = week.from\n    to = week.to\n  }\n\n  if (!from || !to) return false\n\n  const dayCompare = compareDays(day, from, calendarSystem)\n  const toCompare = compareDays(day, to, calendarSystem)\n\n  // Day is between from and to (exclusive of boundaries for styling)\n  return dayCompare > 0 && toCompare < 0\n}\n\n/**\n * Check if a day is the start of a range or week selection\n */\nexport function isRangeStart(\n  day: Day,\n  selectedValue: Day | Range | Multi | Week | null,\n  type: CalendarType\n): boolean {\n  if ((type !== 'range' && type !== 'week') || !selectedValue) return false\n\n  let from: Day | null = null\n  if (type === 'range') {\n    const range = selectedValue as Range\n    from = range.from\n  } else if (type === 'week') {\n    const week = selectedValue as Week\n    from = week.from\n  }\n\n  if (!from) return false\n\n  return (\n    day.year === from.year && day.month === from.month && day.day === from.day\n  )\n}\n\n/**\n * Check if a day is the end of a range or week selection\n */\nexport function isRangeEnd(\n  day: Day,\n  selectedValue: Day | Range | Multi | Week | null,\n  type: CalendarType\n): boolean {\n  if ((type !== 'range' && type !== 'week') || !selectedValue) return false\n\n  let to: Day | null = null\n  if (type === 'range') {\n    const range = selectedValue as Range\n    to = range.to\n  } else if (type === 'week') {\n    const week = selectedValue as Week\n    to = week.to\n  }\n\n  if (!to) return false\n\n  return day.year === to.year && day.month === to.month && day.day === to.day\n}\n","/**\n * Month Selection View Component\n * Displays months for selection\n */\n\nimport React from 'react'\nimport type { Day, CalendarLocale, CalendarTranslations } from '../types'\nimport type { CalendarCustomization } from '../types/calendar'\nimport { CalendarHeader } from './CalendarHeader'\n\nexport interface MonthViewProps {\n  /** Currently displayed month */\n  displayMonth: Day\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Locale for internationalization */\n  locale: string\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Customization options */\n  customization?: CalendarCustomization\n  /** Callback when month is selected */\n  onMonthSelect: (month: number) => void\n  /** Callback when view changes */\n  onViewChange: (view: 'calendar' | 'years') => void\n}\n\nconst MonthViewInner: React.FC<MonthViewProps> = (props) => {\n  const {\n    displayMonth,\n    calendarSystem,\n    locale: _locale,\n    translations,\n    customization = {},\n    onMonthSelect,\n    onViewChange\n  } = props\n\n  const { classes = {} } = customization\n  const { months: monthsClass } = classes\n\n  const isRTL = translations.direction === 'rtl'\n  const monthNames = translations.months\n\n  return (\n    <div className='calendar-core' dir={isRTL ? 'rtl' : 'ltr'}>\n      <CalendarHeader\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        translations={translations}\n        customization={customization}\n        onPrevious={() => onViewChange('calendar')}\n        onNext={() => onViewChange('years')}\n        onMonthClick={() => onViewChange('calendar')}\n        onYearClick={() => onViewChange('years')}\n      />\n\n      <div\n        className={`calendar-months ${monthsClass || ''}`}\n        role='grid'\n        aria-label={translations.labels.selectMonth}\n      >\n        {monthNames.map((monthName, index) => {\n          const month = index + 1\n          const isCurrentMonth = month === displayMonth.month\n\n          const classNames = [\n            'calendar-month-item',\n            isCurrentMonth && 'calendar-month-current'\n          ]\n            .filter(Boolean)\n            .join(' ')\n\n          return (\n            <button\n              key={month}\n              type='button'\n              role='gridcell'\n              onClick={() => {\n                onMonthSelect(month)\n                onViewChange('calendar')\n              }}\n              className={classNames}\n              aria-label={monthName}\n              aria-selected={isCurrentMonth}\n              aria-current={isCurrentMonth ? 'date' : undefined}\n            >\n              {monthName}\n            </button>\n          )\n        })}\n      </div>\n    </div>\n  )\n}\n\n// 🟢 Memoize component to prevent unnecessary re-renders\nexport const MonthView = React.memo(MonthViewInner, (prevProps, nextProps) => {\n  return (\n    prevProps.displayMonth === nextProps.displayMonth &&\n    prevProps.calendarSystem === nextProps.calendarSystem &&\n    prevProps.locale === nextProps.locale &&\n    prevProps.translations === nextProps.translations &&\n    prevProps.customization === nextProps.customization &&\n    prevProps.onMonthSelect === nextProps.onMonthSelect &&\n    prevProps.onViewChange === nextProps.onViewChange\n  )\n})\n\nMonthView.displayName = 'MonthView'\n","/**\n * Year Selection View Component\n * Displays years for selection\n */\n\nimport React, { useRef, useEffect } from 'react'\nimport type {\n  Day,\n  CalendarLocale,\n  CalendarListStyle,\n  CalendarTranslations\n} from '../types'\nimport type { CalendarCustomization } from '../types/calendar'\nimport { getYearRange } from '../utils/calendar-grid'\nimport { formatNumber } from '../utils/formatting'\nimport { CalendarHeader } from './CalendarHeader'\n\nexport interface YearViewProps {\n  /** Currently displayed month */\n  displayMonth: Day\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Locale for internationalization */\n  locale: string\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Year list style */\n  yearListStyle?: CalendarListStyle\n  /** Customization options */\n  customization?: CalendarCustomization\n  /** Callback when year is selected */\n  onYearSelect: (year: number) => void\n  /** Callback when view changes */\n  onViewChange: (view: 'months') => void\n}\n\nconst YearViewInner: React.FC<YearViewProps> = (props) => {\n  const {\n    displayMonth,\n    calendarSystem,\n    locale: _locale,\n    translations,\n    yearListStyle = 'grid',\n    customization = {},\n    onYearSelect,\n    onViewChange\n  } = props\n\n  const { classes = {} } = customization\n  const { years: yearsClass } = classes\n\n  const isRTL = translations.direction === 'rtl'\n  const years = getYearRange(displayMonth.year, 12, calendarSystem)\n  const isGrid = yearListStyle === 'grid'\n\n  const yearsContainerRef = useRef<HTMLDivElement>(null)\n  const currentYearIndex = years.findIndex((year) => year === displayMonth.year)\n\n  // Scroll to center the current year when component mounts or year changes\n  useEffect(() => {\n    if (yearsContainerRef.current && currentYearIndex >= 0 && isGrid) {\n      const container = yearsContainerRef.current\n      const yearItemHeight = 55 // Height of each year item\n      const containerHeight = 291 // Height of the scrollable container\n      const columnsPerRow = 5 // Grid has 5 columns\n\n      // Calculate which row the current year is in\n      const rowIndex = Math.floor(currentYearIndex / columnsPerRow)\n\n      // Calculate scroll position to center the row containing the current year\n      const scrollPosition =\n        rowIndex * yearItemHeight - containerHeight / 2 + yearItemHeight / 2\n\n      // Scroll to the calculated position\n      container.scrollTo({\n        top: Math.max(0, scrollPosition),\n        behavior: 'smooth'\n      })\n    } else if (yearsContainerRef.current && currentYearIndex >= 0 && !isGrid) {\n      // For list layout, scroll directly to the year\n      const container = yearsContainerRef.current\n      const yearItemHeight = 55\n      const containerHeight = 291\n\n      const scrollPosition =\n        currentYearIndex * yearItemHeight -\n        containerHeight / 2 +\n        yearItemHeight / 2\n\n      container.scrollTo({\n        top: Math.max(0, scrollPosition),\n        behavior: 'smooth'\n      })\n    }\n  }, [currentYearIndex, displayMonth.year, isGrid])\n\n  return (\n    <div className='calendar-core' dir={isRTL ? 'rtl' : 'ltr'}>\n      <CalendarHeader\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        translations={translations}\n        customization={customization}\n        onPrevious={() => onViewChange('months')}\n        onNext={() => {}}\n        onMonthClick={() => onViewChange('months')}\n        onYearClick={undefined}\n        showYear={true}\n      />\n\n      <div className='year-wrapper'>\n        <div\n          ref={yearsContainerRef}\n          className={`calendar-years ${yearsClass || ''} ${\n            isGrid ? 'calendar-years-grid' : 'calendar-years-list'\n          }`}\n          role='grid'\n          aria-label={translations.labels.selectYear}\n        >\n          {years.map((year) => {\n            const isCurrentYear = year === displayMonth.year\n\n            const classNames = [\n              'calendar-year-item',\n              isCurrentYear && 'calendar-year-current'\n            ]\n              .filter(Boolean)\n              .join(' ')\n\n            const yearLabel = formatNumber(year, translations.numbers)\n\n            return (\n              <button\n                key={year}\n                type='button'\n                role='gridcell'\n                onClick={() => {\n                  onYearSelect(year)\n                  onViewChange('months')\n                }}\n                className={classNames}\n                aria-label={yearLabel}\n                aria-selected={isCurrentYear}\n                aria-current={isCurrentYear ? 'date' : undefined}\n              >\n                {formatNumber(year, translations.numbers)}\n              </button>\n            )\n          })}\n        </div>\n      </div>\n    </div>\n  )\n}\n\n// 🟢 Memoize component to prevent unnecessary re-renders\nexport const YearView = React.memo(YearViewInner, (prevProps, nextProps) => {\n  return (\n    prevProps.displayMonth === nextProps.displayMonth &&\n    prevProps.calendarSystem === nextProps.calendarSystem &&\n    prevProps.locale === nextProps.locale &&\n    prevProps.translations === nextProps.translations &&\n    prevProps.yearListStyle === nextProps.yearListStyle &&\n    prevProps.customization === nextProps.customization &&\n    prevProps.onYearSelect === nextProps.onYearSelect &&\n    prevProps.onViewChange === nextProps.onViewChange\n  )\n})\n\nYearView.displayName = 'YearView'\n","/**\n * CalendarCore Component\n * Shared calendar logic used by both DtPicker and DtCalendar\n */\n\nimport React from 'react'\nimport type {\n  Day,\n  Range,\n  Multi,\n  Week,\n  CalendarLocale,\n  CalendarType,\n  CalendarListStyle,\n  CalendarTranslations\n} from '../types'\nimport type {\n  CalendarConstraints,\n  CalendarCustomization,\n  PresetRangesConfig\n} from '../types/calendar'\nimport { CalendarGridView } from './CalendarGridView'\nimport { MonthView } from './MonthView'\nimport { YearView } from './YearView'\nimport { detectTimeFormatFromDateFormat } from '../utils/formatting'\n\nexport interface CalendarCoreProps {\n  /** Currently selected value */\n  selectedValue: Day | Range | Multi | Week | null\n  /** Currently displayed month */\n  displayMonth: Day\n  /** Current view: 'calendar', 'months', or 'years' */\n  currentView: 'calendar' | 'months' | 'years'\n  /** Calendar system */\n  calendarSystem: CalendarLocale\n  /** Locale for internationalization */\n  locale: string\n  /** Translation object */\n  translations: CalendarTranslations\n  /** Calendar selection type */\n  type: CalendarType\n  /** Enable time selection */\n  withTime?: boolean\n  /** Custom date format string (used to detect time format) */\n  dateFormat?: string\n  /** Time format: '12' for 12-hour format, '24' for 24-hour format (detected from dateFormat if not provided) */\n  timeFormat?: '12' | '24'\n  /** Show weekend highlighting */\n  showWeekend?: boolean\n  /** First day of the week (0 = Sunday, 6 = Saturday) */\n  weekStart?: number\n  /** Show today button */\n  todayBtn?: boolean\n  /** Preset range buttons configuration */\n  presetRanges?: PresetRangesConfig\n  /** Enlarge selected day text */\n  enlargeSelectedDay?: boolean\n  /** Year list style */\n  yearListStyle?: CalendarListStyle\n  /** Date constraints */\n  constraints?: CalendarConstraints\n  /** Customization options */\n  customization?: CalendarCustomization\n  /** Callback when date is selected */\n  onDateSelect: (day: Day) => void\n  /** Callback when time changes */\n  onTimeChange?: (day: Day, hour: number, minute: number) => void\n  /** Callback when month is selected */\n  onMonthSelect: (month: number) => void\n  /** Callback when year is selected */\n  onYearSelect: (year: number) => void\n  /** Callback when view changes */\n  onViewChange: (view: 'calendar' | 'months' | 'years') => void\n  /** Callback when navigating months */\n  onMonthNavigate: (direction: 'prev' | 'next') => void\n  /** Callback to navigate to today's date */\n  onGoToToday?: () => void\n  /** Callback when preset range is selected */\n  onPresetRangeSelect?: (range: Range) => void\n  /** Number of months to display side by side */\n  numberOfMonths?: 1 | 2 | 3\n}\n\nexport const CalendarCore: React.FC<CalendarCoreProps> = (props) => {\n  const {\n    selectedValue,\n    displayMonth,\n    currentView,\n    calendarSystem,\n    locale,\n    translations,\n    type,\n    withTime = false,\n    dateFormat,\n    timeFormat,\n    showWeekend = false,\n    weekStart,\n    todayBtn = false,\n    presetRanges,\n    enlargeSelectedDay = true,\n    yearListStyle = 'grid',\n    constraints = {},\n    customization = {},\n    onDateSelect,\n    onTimeChange,\n    onMonthSelect,\n    onYearSelect,\n    onViewChange,\n    onMonthNavigate,\n    onGoToToday,\n    onPresetRangeSelect,\n    numberOfMonths = 1\n  } = props\n\n  // Detect time format from dateFormat if not provided\n  const effectiveTimeFormat =\n    timeFormat || detectTimeFormatFromDateFormat(dateFormat)\n\n  // Render appropriate view component\n  if (currentView === 'calendar') {\n    return (\n      <CalendarGridView\n        selectedValue={selectedValue}\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        locale={locale}\n        translations={translations}\n        type={type}\n        withTime={withTime}\n        dateFormat={dateFormat}\n        timeFormat={effectiveTimeFormat}\n        showWeekend={showWeekend}\n        weekStart={weekStart}\n        todayBtn={todayBtn}\n        enlargeSelectedDay={enlargeSelectedDay}\n        constraints={constraints}\n        customization={customization}\n        numberOfMonths={numberOfMonths}\n        onDateSelect={onDateSelect}\n        onTimeChange={onTimeChange}\n        onMonthNavigate={onMonthNavigate}\n        onViewChange={onViewChange}\n        onGoToToday={onGoToToday}\n        presetRanges={presetRanges}\n        onPresetRangeSelect={onPresetRangeSelect}\n      />\n    )\n  }\n\n  if (currentView === 'months') {\n    return (\n      <MonthView\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        locale={locale}\n        translations={translations}\n        customization={customization}\n        onMonthSelect={onMonthSelect}\n        onViewChange={onViewChange}\n      />\n    )\n  }\n\n  if (currentView === 'years') {\n    return (\n      <YearView\n        displayMonth={displayMonth}\n        calendarSystem={calendarSystem}\n        locale={locale}\n        translations={translations}\n        yearListStyle={yearListStyle}\n        customization={customization}\n        onYearSelect={onYearSelect}\n        onViewChange={onViewChange}\n      />\n    )\n  }\n\n  return null\n}\n\nCalendarCore.displayName = 'CalendarCore'\n","import React from 'react'\nimport type { CalendarCustomization } from '../types/calendar'\n\n// Default calendar icon SVG component\nconst CalendarIcon = ({ className }: { className?: string }) => (\n  <svg\n    className={className}\n    width='16'\n    height='16'\n    viewBox='0 0 16 16'\n    fill='none'\n    xmlns='http://www.w3.org/2000/svg'\n    aria-hidden='true'\n  >\n    <path\n      d='M3 6h10M5.5 1v3M10.5 1v3M3.5 4h9c.83 0 1.5.67 1.5 1.5v7c0 .83-.67 1.5-1.5 1.5h-9c-.83 0-1.5-.67-1.5-1.5v-7c0-.83.67-1.5 1.5-1.5z'\n      stroke='currentColor'\n      strokeWidth='1.5'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n    />\n  </svg>\n)\n\n/**\n * Props for DtPickerTrigger component\n */\nexport interface DtPickerTriggerProps {\n  /** Custom trigger element (replaces default input) */\n  triggerElement?: React.ReactNode\n  /** Display value in input field */\n  displayValue: string\n  /** Placeholder text */\n  placeholder: string\n  /** Whether input is disabled */\n  isDisabled: boolean\n  /** Whether modal is open */\n  isOpen: boolean\n  /** Show clear button */\n  clearBtn: boolean\n  /** Whether there is a selected value to clear */\n  hasSelectedValue: boolean\n  /** Click handler for trigger */\n  onTriggerClick: (e: React.MouseEvent) => void\n  /** Key down handler for input */\n  onInputKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void\n  /** Clear button click handler */\n  onClear: (e: React.MouseEvent) => void\n  /** Input element ref */\n  inputRef: React.RefObject<HTMLInputElement>\n  /** Trigger wrapper ref (custom or input) */\n  triggerRef: React.RefObject<HTMLElement>\n  /** Input element ID */\n  inputId?: string\n  /** Custom CSS class for input wrapper */\n  inputClass?: string\n  /** Custom CSS class for trigger wrapper (when using custom trigger) */\n  triggerClass?: string\n  /** Translation for clear button label */\n  translationsClear: string\n  /** Customization options (for custom calendar icon) */\n  customization?: CalendarCustomization\n}\n\n/**\n * DtPickerTrigger Component\n *\n * Handles rendering of the calendar picker trigger element.\n * Supports both:\n * 1. Default input field with calendar icon and clear button\n * 2. Custom trigger element passed by user\n *\n * @example\n * ```tsx\n * // Default input trigger\n * <DtPickerTrigger\n *   displayValue=\"2025-01-01\"\n *   placeholder=\"Select date\"\n *   onTriggerClick={handleClick}\n *   // ... other props\n * />\n *\n * // Custom trigger element\n * <DtPickerTrigger\n *   triggerElement={<CustomButton />}\n *   onTriggerClick={handleClick}\n *   // ... other props\n * />\n * ```\n */\nconst DtPickerTriggerInner: React.FC<DtPickerTriggerProps> = ({\n  triggerElement,\n  displayValue,\n  placeholder,\n  isDisabled,\n  isOpen,\n  clearBtn,\n  hasSelectedValue,\n  onTriggerClick,\n  onInputKeyDown,\n  onClear,\n  inputRef,\n  triggerRef,\n  inputId,\n  inputClass,\n  triggerClass,\n  translationsClear,\n  customization\n}) => {\n  // Get custom calendar icon from customization, or use default\n  const CalendarIconComponent = customization?.icons?.calendar || CalendarIcon\n  // Render custom trigger element\n  if (triggerElement) {\n    return (\n      <div\n        ref={triggerRef as React.RefObject<HTMLDivElement>}\n        className={triggerClass || ''}\n        onClick={onTriggerClick}\n        style={{\n          display: 'inline-block',\n          cursor: isDisabled ? 'not-allowed' : 'pointer'\n        }}\n        aria-haspopup='dialog'\n        aria-expanded={isOpen}\n        tabIndex={0}\n        role='button'\n      >\n        {triggerElement}\n      </div>\n    )\n  }\n\n  // Render default input trigger\n  const inputWrapperClass = `calendar-picker-input-wrapper ${inputClass || ''}`\n\n  return (\n    <div className={inputWrapperClass}>\n      <input\n        ref={(el) => {\n          if (el) {\n            inputRef.current = el\n            triggerRef.current = el\n          }\n        }}\n        id={inputId}\n        type='text'\n        readOnly\n        value={displayValue}\n        placeholder={placeholder}\n        disabled={isDisabled}\n        onClick={onTriggerClick}\n        onKeyDown={onInputKeyDown}\n        className='calendar-picker-input'\n        aria-label={placeholder || 'Select date'}\n        aria-haspopup='dialog'\n        aria-expanded={isOpen}\n      />\n      {clearBtn && hasSelectedValue && (\n        <button\n          type='button'\n          onClick={onClear}\n          className='calendar-picker-clear'\n          aria-label={translationsClear}\n        >\n          <span>×</span>\n        </button>\n      )}\n      <button\n        type='button'\n        onClick={onTriggerClick}\n        disabled={isDisabled}\n        className='calendar-picker-toggle'\n        aria-label='Open calendar'\n      >\n        <CalendarIconComponent className='calendar-picker-icon' />\n      </button>\n    </div>\n  )\n}\n\n// 🟢 Memoize component to prevent unnecessary re-renders\nexport const DtPickerTrigger = React.memo(\n  DtPickerTriggerInner,\n  (prevProps, nextProps) => {\n    // Return TRUE if props are equal (skip re-render)\n    // Note: refs are excluded from comparison as they are stable references\n    return (\n      prevProps.triggerElement === nextProps.triggerElement &&\n      prevProps.displayValue === nextProps.displayValue &&\n      prevProps.placeholder === nextProps.placeholder &&\n      prevProps.isDisabled === nextProps.isDisabled &&\n      prevProps.isOpen === nextProps.isOpen &&\n      prevProps.clearBtn === nextProps.clearBtn &&\n      prevProps.hasSelectedValue === nextProps.hasSelectedValue &&\n      prevProps.onTriggerClick === nextProps.onTriggerClick &&\n      prevProps.onInputKeyDown === nextProps.onInputKeyDown &&\n      prevProps.onClear === nextProps.onClear &&\n      prevProps.inputId === nextProps.inputId &&\n      prevProps.inputClass === nextProps.inputClass &&\n      prevProps.triggerClass === nextProps.triggerClass &&\n      prevProps.translationsClear === nextProps.translationsClear &&\n      prevProps.customization === nextProps.customization\n    )\n  }\n)\n\nDtPickerTrigger.displayName = 'DtPickerTrigger'\n","import React, { useMemo, ReactNode, useCallback } from 'react'\nimport type { Day, Range, Multi, RangeDate } from '../types'\nimport type {\n  CalendarSelectionSingle,\n  CalendarSelectionRange,\n  CalendarSelectionMulti,\n  CalendarSelectionWeek,\n  SharedCalendarProps\n} from '../types/calendar'\nimport { CalendarCore } from './CalendarCore'\nimport { DtPickerTrigger } from './DtPickerTrigger'\nimport {\n  useCalendarPicker,\n  useModalPosition,\n  useCalendarSetup,\n  useCalendarCallbacks,\n  useModalState,\n  useCalendarErrorHandling\n} from '../hooks'\nimport { normalizeConstraintsProps } from '../utils/constraints'\nimport { normalizeInitValueWithErrors } from '../utils/normalize'\nimport { detectTimeFormatFromDateFormat } from '../utils/formatting'\n\ninterface DtPickerPropsBase extends SharedCalendarProps {\n  /**\n   * Show time in input field\n   * @default false\n   */\n  showTimeInput?: boolean\n  /**\n   * Show clear button\n   * @default false\n   */\n  clearBtn?: boolean\n  /**\n   * Make input required\n   * @default false\n   */\n  isRequired?: boolean\n  /**\n   * Disable the picker\n   * @default false\n   */\n  isDisabled?: boolean\n  /**\n   * Placeholder text\n   * @default 'Select date'\n   */\n  placeholder?: string\n  /**\n   * Custom CSS class for input\n   */\n  inputClass?: string\n  /**\n   * Auto-close calendar after selection\n   * @default true\n   */\n  autoClose?: boolean\n  /**\n   * Input element ID\n   */\n  inputId?: string\n  /**\n   * Custom trigger element to replace the default input field\n   * When provided, the input field will not be rendered\n   */\n  triggerElement?: ReactNode\n  /**\n   * Custom CSS class for trigger wrapper when using custom trigger\n   */\n  triggerClass?: string\n}\n\nexport interface DtPickerPropsSingle\n  extends DtPickerPropsBase, CalendarSelectionSingle {}\n\nexport interface DtPickerPropsRange\n  extends DtPickerPropsBase, CalendarSelectionRange {}\n\nexport interface DtPickerPropsMulti\n  extends DtPickerPropsBase, CalendarSelectionMulti {}\n\nexport interface DtPickerPropsWeek\n  extends DtPickerPropsBase, CalendarSelectionWeek {}\n\nexport type DtPickerProps =\n  | DtPickerPropsSingle\n  | DtPickerPropsRange\n  | DtPickerPropsMulti\n  | DtPickerPropsWeek\n\n/**\n * DtPicker Component\n *\n * A date picker with input field that opens a modal calendar.\n *\n * @example\n * ```tsx\n * import { DtPicker } from 'react-calendar-datetime-picker'\n *\n * function App() {\n *   const [date, setDate] = useState(null)\n *   return <DtPicker onChange={setDate} calendarSystem=\"gregorian\" />\n * }\n * ```\n */\nexport const DtPicker: React.FC<DtPickerProps> = (props) => {\n  const {\n    initValue,\n    onChange,\n    type = 'single',\n    withTime = false,\n    showTimeInput = false,\n    calendarSystem = 'gregorian',\n    showWeekend = false,\n    weekStart,\n    clearBtn = false,\n    todayBtn = false,\n    presetRanges,\n    isDisabled = false,\n    constraints: constraintsInput,\n    placeholder = 'Select date',\n    inputClass,\n    triggerElement,\n    triggerClass,\n    calenderModalClass,\n    autoClose = true,\n    inputId,\n    dateFormat,\n    numberOfMonths = 1,\n    locale,\n    customization,\n    dark = false,\n    yearListStyle = 'grid',\n    enlargeSelectedDay = true,\n    onDateSelect,\n    onMonthSelect,\n    onYearSelect,\n    onViewChange,\n    onMonthNavigate,\n    onGoToToday,\n    onError\n  } = props\n\n  // 🎯 Use consolidated calendar setup hook\n  const {\n    normalizedCalendarSystem,\n    effectiveLocale,\n    translations,\n    effectiveWeekStart\n  } = useCalendarSetup(calendarSystem, locale, weekStart, customization)\n\n  // 🎯 Use modal state hook (encapsulates all modal behavior)\n  const {\n    isOpen,\n    handlers: modalHandlers,\n    refs: { pickerRef, modalRef }\n  } = useModalState()\n\n  // Create wrapper refs for trigger\n  const inputRef = useMemo(() => React.createRef<HTMLInputElement>(), [])\n  const triggerRef = useMemo(() => React.createRef<HTMLElement>(), [])\n\n  // Normalize constraints props with error tracking\n  const constraintsResult = useMemo(\n    () =>\n      normalizeConstraintsProps(\n        constraintsInput,\n        normalizedCalendarSystem,\n        type\n      ),\n    [constraintsInput, normalizedCalendarSystem, type]\n  )\n  const { constraints, errors: constraintsErrors } = constraintsResult\n\n  // Normalize initValue upfront for proper initial state with error tracking\n  const initValueResult = useMemo(\n    () =>\n      normalizeInitValueWithErrors(\n        initValue,\n        normalizedCalendarSystem,\n        type,\n        'initValue'\n      ),\n    [initValue, normalizedCalendarSystem, type]\n  )\n  // Extract only errors - value is normalized by useCalendarPicker internally\n  const initValueErrors = initValueResult.errors\n\n  // 🎯 Use error handling hook\n  useCalendarErrorHandling(constraintsErrors, initValueErrors, onError)\n\n  // Detect time format from dateFormat string\n  const timeFormat = detectTimeFormatFromDateFormat(dateFormat)\n\n  // Use calendar picker hook for shared calendar logic\n  const { state, actions, displayValue } = useCalendarPicker(\n    initValue,\n    onChange as (\n      normalizedValue: Day | Range | Multi | null,\n      jsDateValue: Date | RangeDate | Date[] | null,\n      formattedString: string | null\n    ) => void,\n    type,\n    normalizedCalendarSystem,\n    withTime,\n    constraintsInput,\n    showTimeInput,\n    autoClose,\n    modalHandlers.close,\n    dateFormat,\n    numberOfMonths,\n    translations\n  )\n\n  // 🎯 Use consolidated calendar callbacks hook\n  const {\n    handleDateSelect,\n    handleMonthSelect,\n    handleYearSelect,\n    handleViewChange,\n    handleMonthNavigate,\n    handleGoToToday,\n    handlePresetRangeSelect\n  } = useCalendarCallbacks({\n    actions,\n    onDateSelect,\n    onMonthSelect,\n    onYearSelect,\n    onViewChange,\n    onMonthNavigate,\n    onGoToToday,\n    type\n  })\n\n  // Use modal position hook\n  const { modalPosition } = useModalPosition(\n    triggerRef,\n    modalRef,\n    isOpen,\n    normalizedCalendarSystem\n  )\n\n  // Handle trigger click (works for both input and custom trigger)\n  const handleTriggerClick = useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation()\n      if (!isDisabled) {\n        modalHandlers.toggle()\n      }\n    },\n    [isDisabled, modalHandlers]\n  )\n\n  // Handle input keydown (Enter to open)\n  const handleInputKeyDown = useCallback(\n    (e: React.KeyboardEvent<HTMLInputElement>) => {\n      if (e.key === 'Enter' && !isDisabled && !isOpen) {\n        e.preventDefault()\n        modalHandlers.open()\n      }\n    },\n    [isDisabled, isOpen, modalHandlers]\n  )\n\n  // Handle clear button\n  const handleClear = useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation()\n      actions.clearSelection()\n      modalHandlers.close()\n    },\n    [actions, modalHandlers]\n  )\n\n  const modalClass = `calendar-picker-modal ${calenderModalClass || ''}`\n  const isRTL = normalizedCalendarSystem === 'jalali'\n\n  return (\n    <div\n      ref={pickerRef}\n      className='calendar-picker'\n      dir={isRTL ? 'rtl' : 'ltr'}\n    >\n      <DtPickerTrigger\n        triggerElement={triggerElement}\n        displayValue={displayValue}\n        placeholder={placeholder}\n        isDisabled={isDisabled}\n        isOpen={isOpen}\n        clearBtn={clearBtn}\n        hasSelectedValue={!!state.selectedValue}\n        onTriggerClick={handleTriggerClick}\n        onInputKeyDown={handleInputKeyDown}\n        onClear={handleClear}\n        inputRef={inputRef as React.RefObject<HTMLInputElement>}\n        triggerRef={triggerRef as React.RefObject<HTMLElement>}\n        inputId={inputId}\n        inputClass={inputClass}\n        triggerClass={triggerClass}\n        translationsClear={translations.labels.clear}\n        customization={customization}\n      />\n\n      {isOpen && (\n        <div\n          ref={modalRef}\n          className={modalClass}\n          role='dialog'\n          aria-modal='true'\n          aria-label={\n            type === 'range'\n              ? 'Select date range'\n              : type === 'multi'\n                ? 'Select multiple dates'\n                : type === 'week'\n                  ? 'Select week'\n                  : 'Select date'\n          }\n          data-theme={dark ? 'dark' : undefined}\n          style={{\n            position: 'fixed',\n            top: modalPosition ? `${modalPosition.top}px` : '-9999px',\n            left: modalPosition ? `${modalPosition.left}px` : '-9999px',\n            zIndex: 1000,\n            visibility: modalPosition ? 'visible' : 'hidden'\n          }}\n        >\n          <CalendarCore\n            selectedValue={state.selectedValue}\n            displayMonth={state.displayMonth}\n            currentView={state.currentView}\n            calendarSystem={normalizedCalendarSystem}\n            locale={effectiveLocale}\n            translations={translations}\n            type={type}\n            withTime={withTime}\n            dateFormat={dateFormat}\n            timeFormat={timeFormat}\n            showWeekend={showWeekend}\n            weekStart={effectiveWeekStart}\n            todayBtn={todayBtn}\n            enlargeSelectedDay={enlargeSelectedDay}\n            constraints={constraints}\n            customization={customization}\n            numberOfMonths={numberOfMonths}\n            yearListStyle={yearListStyle}\n            onDateSelect={handleDateSelect}\n            onTimeChange={actions.updateTime}\n            onMonthSelect={handleMonthSelect}\n            onYearSelect={handleYearSelect}\n            onViewChange={handleViewChange}\n            onMonthNavigate={handleMonthNavigate}\n            onGoToToday={handleGoToToday}\n            presetRanges={presetRanges}\n            onPresetRangeSelect={handlePresetRangeSelect}\n          />\n        </div>\n      )}\n    </div>\n  )\n}\n\nDtPicker.displayName = 'DtPicker'\n","import { useMemo, useEffect, useRef } from 'react'\nimport type {\n  CalendarLocale,\n  CalendarType,\n  InitValueInput,\n  Day,\n  Range,\n  Multi,\n  RangeDate\n} from '../types'\nimport type {\n  CalendarConstraintsInput,\n  CalendarTranslations\n} from '../types/calendar'\nimport {\n  normalizeInitValueWithErrors,\n  areValuesEqual\n} from '../utils/normalize'\nimport { normalizeConstraintsProps } from '../utils/constraints'\nimport { formatDateForInput, formatValueToString } from '../utils/formatting'\nimport { convertToJsDate } from '../utils/date-conversion'\nimport { useCalendarState } from './useCalendarState'\nimport { isValidNormalizedValue } from '../utils/validation'\n\n/**\n * Hook that encapsulates calendar logic shared between DtPicker and DtCalendar\n * Handles normalization, state management, and formatting\n */\nexport function useCalendarPicker(\n  initValue: InitValueInput | undefined,\n  onChange: (\n    normalizedValue: Day | Range | Multi | null,\n    jsDateValue: Date | RangeDate | Date[] | null,\n    formattedString: string | null\n  ) => void,\n  type: CalendarType,\n  calendarSystem: CalendarLocale,\n  withTime: boolean,\n  constraintsInput: CalendarConstraintsInput | undefined,\n  showTimeInput: boolean,\n  autoClose?: boolean,\n  onClose?: () => void,\n  dateFormat?: string,\n  numberOfMonths: 1 | 2 | 3 = 1,\n  translations?: CalendarTranslations\n) {\n  // Normalize constraints props\n  const constraintsResult = useMemo(\n    () => normalizeConstraintsProps(constraintsInput, calendarSystem, type),\n    [constraintsInput, calendarSystem, type]\n  )\n  const { constraints } = constraintsResult\n\n  // Normalize initValue\n  const initValueResult = useMemo(\n    () =>\n      normalizeInitValueWithErrors(\n        initValue,\n        calendarSystem,\n        type,\n        'initValue'\n      ),\n    [initValue, calendarSystem, type]\n  )\n  const { value: normalizedInitValue } = initValueResult\n\n  // Validate normalizedInitValue against constraints\n  // If initValue is outside the allowed range, reject it (set to null)\n  const validatedInitValue = useMemo(() => {\n    if (!normalizedInitValue || !constraints) {\n      return normalizedInitValue\n    }\n\n    const isValid = isValidNormalizedValue(normalizedInitValue, type, {\n      minDate: constraints.minDate,\n      maxDate: constraints.maxDate,\n      disabledDates: constraints.disabledDates,\n      isDateDisabled: constraints.isDateDisabled,\n      calendarSystem\n    })\n\n    return isValid ? normalizedInitValue : null\n  }, [normalizedInitValue, constraints, type, calendarSystem])\n\n  // Track previous initValue to only convert when it actually changes from props\n  const prevInitValueRef = useRef<InitValueInput | undefined>(undefined)\n\n  // Auto-convert initValue to normalized format if they differ\n  // This ensures parent state is consistent with internal state\n  // Only runs when initValue prop actually changes (not on every render)\n  useEffect(() => {\n    // Only convert if initValue prop changed from previous value (including initial mount)\n    const initValueChanged = !areValuesEqual(\n      prevInitValueRef.current,\n      initValue\n    )\n\n    if (initValueChanged && validatedInitValue && onChange) {\n      // Only convert if the format differs (string/Date vs Day object)\n      if (!areValuesEqual(initValue, validatedInitValue)) {\n        // Convert to JavaScript Date objects (always Gregorian)\n        const jsDateValue = convertToJsDate(\n          validatedInitValue,\n          type,\n          calendarSystem\n        )\n\n        // Determine number system from locale or translations\n        const numberSystem = translations?.numbers || 'latin'\n\n        // Get from/to labels from translations\n        const fromLabel = translations?.labels?.from || 'from'\n        const toLabel = translations?.labels?.to || 'to'\n\n        // Format to string\n        const formattedString = formatValueToString(\n          validatedInitValue,\n          type,\n          numberSystem,\n          withTime,\n          dateFormat,\n          fromLabel,\n          toLabel\n        )\n\n        // Call onChange with three parameters\n        onChange(validatedInitValue, jsDateValue, formattedString)\n      }\n    }\n\n    prevInitValueRef.current = initValue\n  }, [\n    initValue,\n    normalizedInitValue,\n    validatedInitValue,\n    onChange,\n    type,\n    calendarSystem,\n    translations,\n    withTime,\n    dateFormat\n  ])\n\n  // Use calendar state hook\n  const { state, actions } = useCalendarState({\n    initValue: validatedInitValue,\n    calendarSystem: calendarSystem,\n    type,\n    onChange: (normalizedValue, jsDateValue, formattedString) => {\n      // Pass all three parameters\n      onChange(normalizedValue, jsDateValue, formattedString)\n      // Auto-close modal after selection if enabled\n      if (autoClose && onClose) {\n        if (type === 'single' || type === 'week') {\n          onClose()\n        } else if (\n          type === 'range' &&\n          normalizedValue &&\n          'from' in normalizedValue &&\n          normalizedValue.from &&\n          normalizedValue.to\n        ) {\n          onClose()\n        }\n      }\n    },\n    withTime,\n    numberOfMonths,\n    dateFormat,\n    locale: undefined, // useCalendarPicker doesn't have locale, will use translations\n    translations\n  })\n\n  // Format display value for input (use state.selectedValue from calendar)\n  const displayValue = useMemo(() => {\n    const fromLabel = translations?.labels?.from || 'from'\n    const toLabel = translations?.labels?.to || 'to'\n    const numberSystem = translations?.numbers || 'latin'\n    return formatDateForInput(\n      state.selectedValue,\n      numberSystem,\n      type,\n      showTimeInput && withTime,\n      fromLabel,\n      toLabel,\n      dateFormat\n    )\n  }, [\n    state.selectedValue,\n    type,\n    showTimeInput,\n    withTime,\n    dateFormat,\n    translations\n  ])\n\n  return {\n    state,\n    actions,\n    constraints,\n    displayValue\n  }\n}\n","import { useState, useEffect, useRef, useMemo, type RefObject } from 'react'\nimport type { CalendarLocale } from '../types'\n\nexport interface ModalPosition {\n  top: number\n  left: number\n  position: 'below' | 'above'\n}\n\n/**\n * Hook to calculate and manage modal position relative to a trigger element\n */\nexport function useModalPosition(\n  triggerRef: RefObject<HTMLElement | null>,\n  modalRef: RefObject<HTMLDivElement | null>,\n  isOpen: boolean,\n  calendarSystem: CalendarLocale\n) {\n  const [modalPosition, setModalPosition] = useState<ModalPosition | null>(null)\n  const isRTL = calendarSystem === 'jalali'\n\n  // Calculate modal position relative to trigger element\n  const calculateModalPosition = useMemo(() => {\n    return () => {\n      if (!triggerRef.current || !modalRef.current) return\n\n      const triggerRect = triggerRef.current.getBoundingClientRect()\n      const modalRect = modalRef.current.getBoundingClientRect()\n      const modalHeight = modalRect.height || 400 // Use actual height or fallback\n      const modalWidth = modalRect.width || 400 // Use actual width or fallback\n      const spacing = 4 // Space between trigger and modal\n      const viewportHeight = window.innerHeight\n      const viewportWidth = window.innerWidth\n\n      let top = triggerRect.bottom + spacing\n      let left = triggerRect.left\n      let position: 'below' | 'above' = 'below'\n\n      // Check if there's enough space below\n      if (top + modalHeight > viewportHeight) {\n        // Not enough space below, position above\n        top = triggerRect.top - modalHeight - spacing\n        position = 'above'\n      }\n\n      // Ensure modal doesn't go above viewport\n      if (top < 0) {\n        top = spacing\n      }\n\n      // Check horizontal positioning\n      // If RTL, align to right edge of trigger\n      if (isRTL) {\n        left = triggerRect.right - modalWidth\n        // If not enough space on left, align to right edge of viewport\n        if (left < 0) {\n          left = viewportWidth - modalWidth - spacing\n        }\n      } else {\n        // LTR: align to left edge of trigger\n        left = triggerRect.left\n        // If not enough space on right, align to left edge of viewport\n        if (left + modalWidth > viewportWidth) {\n          left = viewportWidth - modalWidth - spacing\n        }\n      }\n\n      // Ensure modal doesn't go outside viewport\n      if (left < 0) {\n        left = spacing\n      }\n\n      setModalPosition({ top, left, position })\n    }\n  }, [isRTL, triggerRef, modalRef])\n\n  // Calculate position when modal opens\n  useEffect(() => {\n    if (!isOpen || !modalRef.current || !triggerRef.current) return\n\n    // Small delay to ensure DOM is ready\n    const timeoutId = window.setTimeout(() => {\n      calculateModalPosition()\n    }, 10)\n\n    return () => {\n      window.clearTimeout(timeoutId)\n    }\n  }, [isOpen, calculateModalPosition, modalRef, triggerRef])\n\n  // Store calculateModalPosition in ref for use in effects\n  const calculateModalPositionRef = useRef(calculateModalPosition)\n  useEffect(() => {\n    calculateModalPositionRef.current = calculateModalPosition\n  }, [calculateModalPosition])\n\n  // Recalculate position on window resize or scroll\n  useEffect(() => {\n    if (isOpen) {\n      const handleResize = () => {\n        calculateModalPositionRef.current()\n      }\n      const handleScroll = () => {\n        calculateModalPositionRef.current()\n      }\n\n      window.addEventListener('resize', handleResize)\n      window.addEventListener('scroll', handleScroll, true)\n      return () => {\n        window.removeEventListener('resize', handleResize)\n        window.removeEventListener('scroll', handleScroll, true)\n      }\n    }\n  }, [isOpen])\n\n  // Expose null position when modal is closed to simplify consumers & tests\n  return {\n    modalPosition: isOpen ? modalPosition : null,\n    calculateModalPosition\n  }\n}\n","import React, { useEffect, useRef, useMemo } from 'react'\nimport type { Day, Range, Multi, InitValueInput, RangeDate } from '../types'\nimport type {\n  CalendarSelectionSingle,\n  CalendarSelectionRange,\n  CalendarSelectionMulti,\n  CalendarSelectionWeek,\n  SharedCalendarProps\n} from '../types/calendar'\nimport { CalendarCore } from './CalendarCore'\nimport {\n  useCalendarState,\n  useCalendarSetup,\n  useCalendarCallbacks,\n  useCalendarErrorHandling\n} from '../hooks'\nimport {\n  normalizeInitValueWithErrors,\n  areValuesEqual\n} from '../utils/normalize'\nimport { normalizeConstraintsProps } from '../utils/constraints'\nimport { convertToJsDate } from '../utils/date-conversion'\nimport {\n  formatValueToString,\n  detectTimeFormatFromDateFormat\n} from '../utils/formatting'\nimport { getNumberSystem } from '../utils/translations'\nimport { isValidNormalizedValue } from '../utils/validation'\n\ninterface DtCalendarPropsBase extends SharedCalendarProps {\n  /**\n   * Callback that runs when the calendar value is changed\n   * Note: requires initValue to be provided\n   */\n  onCalenderChange?: (date: Day | Range | Multi | null) => void\n}\n\nexport interface DtCalendarPropsSingle\n  extends DtCalendarPropsBase, CalendarSelectionSingle {}\n\nexport interface DtCalendarPropsRange\n  extends DtCalendarPropsBase, CalendarSelectionRange {}\n\nexport interface DtCalendarPropsMulti\n  extends DtCalendarPropsBase, CalendarSelectionMulti {}\n\nexport interface DtCalendarPropsWeek\n  extends DtCalendarPropsBase, CalendarSelectionWeek {}\n\nexport type DtCalendarProps =\n  | DtCalendarPropsSingle\n  | DtCalendarPropsRange\n  | DtCalendarPropsMulti\n  | DtCalendarPropsWeek\n\n/**\n * DtCalendar Component\n *\n * A standalone calendar component without input field.\n *\n * @example\n * ```tsx\n * import { DtCalendar } from 'react-calendar-datetime-picker'\n *\n * function App() {\n *   const [date, setDate] = useState(null)\n *   return <DtCalendar onChange={setDate} calendarSystem=\"jalali\" />\n * }\n * ```\n */\nexport const DtCalendar: React.FC<DtCalendarProps> = (props) => {\n  const {\n    initValue,\n    onChange,\n    onCalenderChange,\n    type = 'single',\n    withTime = false,\n    calendarSystem = 'gregorian',\n    showWeekend = false,\n    weekStart,\n    todayBtn = false,\n    presetRanges,\n    enlargeSelectedDay = true,\n    dark = false,\n    constraints: constraintsInput,\n    calenderModalClass,\n    customization,\n    onError,\n    onDateSelect: onDateSelectProp,\n    onMonthSelect: onMonthSelectProp,\n    onYearSelect: onYearSelectProp,\n    onViewChange: onViewChangeProp,\n    onMonthNavigate: onMonthNavigateProp,\n    onGoToToday: onGoToTodayProp,\n    numberOfMonths = 1,\n    locale,\n    yearListStyle = 'grid'\n  } = props\n\n  // Detect time format from dateFormat string\n  const timeFormat = detectTimeFormatFromDateFormat(props.dateFormat)\n\n  // 🎯 Use consolidated calendar setup hook\n  const {\n    normalizedCalendarSystem,\n    effectiveLocale,\n    translations,\n    effectiveWeekStart\n  } = useCalendarSetup(calendarSystem, locale, weekStart, customization)\n\n  // Normalize constraints props with error tracking\n  const constraintsResult = useMemo(\n    () =>\n      normalizeConstraintsProps(\n        constraintsInput,\n        normalizedCalendarSystem,\n        type\n      ),\n    [constraintsInput, normalizedCalendarSystem, type]\n  )\n  const { constraints, errors: constraintsErrors } = constraintsResult\n\n  // Normalize initValue upfront for proper initial state with error tracking\n  const initValueResult = useMemo(\n    () =>\n      normalizeInitValueWithErrors(\n        initValue,\n        normalizedCalendarSystem,\n        type,\n        'initValue'\n      ),\n    [initValue, normalizedCalendarSystem, type]\n  )\n  const { value: normalizedInitValue, errors: initValueErrors } =\n    initValueResult\n\n  // Validate normalizedInitValue against constraints\n  // If initValue is outside the allowed range, reject it (set to null)\n  const validatedInitValue = useMemo(() => {\n    if (!normalizedInitValue || !constraints) {\n      return normalizedInitValue\n    }\n\n    const isValid = isValidNormalizedValue(normalizedInitValue, type, {\n      minDate: constraints.minDate,\n      maxDate: constraints.maxDate,\n      disabledDates: constraints.disabledDates,\n      isDateDisabled: constraints.isDateDisabled,\n      calendarSystem: normalizedCalendarSystem\n    })\n\n    return isValid ? normalizedInitValue : null\n  }, [normalizedInitValue, constraints, type, normalizedCalendarSystem])\n\n  // 🎯 Use error handling hook\n  useCalendarErrorHandling(constraintsErrors, initValueErrors, onError)\n\n  // Track previous initValue to only convert when it actually changes from props\n  const prevInitValueRef = useRef<InitValueInput | undefined>(undefined)\n\n  // Auto-convert initValue to normalized format if they differ\n  // This ensures parent state is consistent with internal state\n  // Only runs when initValue prop actually changes (not on every render)\n  useEffect(() => {\n    // Only convert if initValue prop changed from previous value (including initial mount)\n    const initValueChanged = prevInitValueRef.current !== initValue\n\n    if (initValueChanged && validatedInitValue && onChange) {\n      // Only convert if the format differs (string/Date vs Day object)\n      if (!areValuesEqual(initValue, validatedInitValue)) {\n        // Convert to JavaScript Date objects (always Gregorian)\n        const jsDateValue = convertToJsDate(\n          validatedInitValue,\n          type,\n          normalizedCalendarSystem\n        )\n\n        // Determine number system from locale or translations\n        const numberSystem =\n          translations?.numbers ||\n          (effectiveLocale ? getNumberSystem(effectiveLocale) : 'latin')\n\n        // Get from/to labels from translations\n        const fromLabel = translations?.labels?.from || 'from'\n        const toLabel = translations?.labels?.to || 'to'\n\n        // Format to string\n        const formattedString = formatValueToString(\n          validatedInitValue,\n          type,\n          numberSystem,\n          withTime,\n          props.dateFormat,\n          fromLabel,\n          toLabel\n        )\n\n        // Call onChange with three parameters\n        // TypeScript needs explicit cast because onChange is a discriminated union\n        ;(\n          onChange as (\n            normalizedValue: Day | Range | Multi | null,\n            jsDateValue: Date | RangeDate | Date[] | null,\n            formattedString: string | null\n          ) => void\n        )(validatedInitValue, jsDateValue, formattedString)\n      }\n    }\n\n    prevInitValueRef.current = initValue\n  }, [\n    initValue,\n    normalizedInitValue,\n    validatedInitValue,\n    onChange,\n    type,\n    normalizedCalendarSystem,\n    effectiveLocale,\n    translations,\n    withTime,\n    props.dateFormat\n  ])\n\n  // Use calendar state hook\n  const { state, actions } = useCalendarState({\n    initValue: validatedInitValue,\n    calendarSystem: normalizedCalendarSystem,\n    type,\n    onChange: onChange as (\n      normalizedValue: Day | Range | Multi | null,\n      jsDateValue: Date | RangeDate | Date[] | null,\n      formattedString: string | null\n    ) => void,\n    onCalenderChange: onCalenderChange as (\n      normalizedValue: Day | Range | Multi | null,\n      jsDateValue: Date | RangeDate | Date[] | null,\n      formattedString: string | null\n    ) => void,\n    withTime,\n    numberOfMonths,\n    weekStart: effectiveWeekStart,\n    dateFormat: props.dateFormat,\n    locale: effectiveLocale,\n    translations\n  })\n\n  // 🎯 Use consolidated calendar callbacks hook\n  const {\n    handleDateSelect,\n    handleMonthSelect,\n    handleYearSelect,\n    handleViewChange,\n    handleMonthNavigate,\n    handleGoToToday,\n    handlePresetRangeSelect\n  } = useCalendarCallbacks({\n    actions,\n    onDateSelect: onDateSelectProp,\n    onMonthSelect: onMonthSelectProp,\n    onYearSelect: onYearSelectProp,\n    onViewChange: onViewChangeProp,\n    onMonthNavigate: onMonthNavigateProp,\n    onGoToToday: onGoToTodayProp,\n    type\n  })\n\n  return (\n    <div\n      className={`react-calendar-datetime-picker ${calenderModalClass || ''}`}\n      data-theme={dark ? 'dark' : undefined}\n    >\n      <CalendarCore\n        selectedValue={state.selectedValue}\n        displayMonth={state.displayMonth}\n        currentView={state.currentView}\n        calendarSystem={normalizedCalendarSystem}\n        locale={effectiveLocale}\n        translations={translations}\n        type={type}\n        withTime={withTime}\n        dateFormat={props.dateFormat}\n        timeFormat={timeFormat}\n        showWeekend={showWeekend}\n        weekStart={effectiveWeekStart}\n        todayBtn={todayBtn}\n        enlargeSelectedDay={enlargeSelectedDay}\n        constraints={constraints}\n        customization={customization}\n        numberOfMonths={numberOfMonths}\n        yearListStyle={yearListStyle}\n        onDateSelect={handleDateSelect}\n        onTimeChange={actions.updateTime}\n        onMonthSelect={handleMonthSelect}\n        onYearSelect={handleYearSelect}\n        onViewChange={handleViewChange}\n        onMonthNavigate={handleMonthNavigate}\n        onGoToToday={handleGoToToday}\n        presetRanges={presetRanges}\n        onPresetRangeSelect={handlePresetRangeSelect}\n      />\n    </div>\n  )\n}\n\nDtCalendar.displayName = 'DtCalendar'\n","/**\n * Utility functions export\n */\n\n// Date conversion\nexport {\n  gregorianToJalali,\n  jalaliToGregorian,\n  convertToLocale,\n  getToday,\n  dateToDay,\n  dayToDate,\n  convertToJsDate\n} from './date-conversion'\n\n// Normalization\nexport { normalizeInitValue, extractMonthFromValue } from './normalize'\n\n// Formatting\nexport {\n  formatDateForInput,\n  formatValueToString,\n  dayToString,\n  parseDateString,\n  parseAndValidateDate,\n  toPersianNumeral\n} from './formatting'\n\n// Validation\nexport {\n  isValidDay,\n  isDateInRange,\n  isDateDisabled,\n  isDateSelectable,\n  compareDays,\n  getDaysInMonth,\n  validateDay,\n  isLeapYear\n} from './validation'\n\n// Constraints\nexport { normalizeConstraintsProps } from './constraints'\n\n// Calendar grid\nexport { generateCalendarGrid, getYearRange, getMonths } from './calendar-grid'\nexport type { CalendarDay } from './calendar-grid'\n\n// Weekday utilities\nexport {\n  getEffectiveWeekStart,\n  rotateArray,\n  getGregorianDayOfWeek,\n  isWeekendDay,\n  getWeekendPositions,\n  getRotatedWeekdayNames,\n  getWeekendConfig\n} from './weekday-utils'\n\n// Calendar selection\nexport {\n  isDaySelected,\n  isDayInRange,\n  isRangeStart,\n  isRangeEnd\n} from './calendar-selection'\n\n// Date comparison and manipulation\nexport {\n  isBefore,\n  isAfter,\n  isBetween,\n  isSameDay,\n  isSameMonth,\n  isSameYear,\n  addDays,\n  subtractDays,\n  addMonths,\n  subtractMonths,\n  addYears,\n  subtractYears,\n  getDifferenceInDays,\n  getDifferenceInMonths,\n  getDifferenceInYears,\n  convertToJalali,\n  convertToGregorian,\n  startOfDay,\n  endOfDay,\n  startOfMonth,\n  endOfMonth,\n  startOfYear,\n  endOfYear,\n  getStartOfWeek,\n  getEndOfWeek,\n  getDaysInRange\n} from './date-comparison'\n\n// Utility functions for backward compatibility (convertToFa, convertToEn)\nimport { gregorianToJalali, jalaliToGregorian } from './date-conversion'\nimport { dayToString } from './formatting'\nimport type { Day } from '../types'\n\n/**\n * Convert Gregorian date to Jalali date string\n * @param date - Day object in Gregorian calendar\n * @param divider - String divider (default: '/')\n * @returns Formatted Jalali date string\n */\nexport function convertToFa(date: Day, divider = '/'): string {\n  const jalaliDate = gregorianToJalali(date)\n  return dayToString(jalaliDate, divider)\n}\n\n/**\n * Convert Jalali date to Gregorian date string\n * @param date - Day object in Jalali calendar\n * @param divider - String divider (default: '/')\n * @returns Formatted Gregorian date string\n */\nexport function convertToEn(date: Day, divider = '/'): string {\n  const gregorianDate = jalaliToGregorian(date)\n  return dayToString(gregorianDate, divider)\n}\n"],"names":["gregorianToJalali","day","isValidDay","Error","JSON","stringify","jDate","toJalaali","year","month","jy","jm","jd","hour","minute","error","message","String","jalaliToGregorian","gDate","toGregorian","gy","gm","gd","getToday","calendarSystem","today","Date","gregorianDay","getFullYear","getMonth","getDate","dateToDay","date","getHours","getMinutes","dayToDate","UTC","convertToJsDate","value","type","range","from","to","Array","isArray","map","PERSIAN_DIGITS","PERSIAN_TO_ENGLISH","detectTimeFormatFromDateFormat","dateFormat","includes","toPersianNumeral","num","toString","replace","d","parseInt","formatNumber","numberSystem","formatDay","showTime","formatted","format","dayNum","shouldShowTime","YYYY","MM","padStart","DD","HH","hh","mm","A","a","isPm","tokens","match","trim","formatDateWithCustomFormat","formatDateForInput","fromLabel","toLabel","fmt","fromStr","week","toStr","multi","length","join","formatValueToString","withTime","dayToString","divider","parseDateString","dateString","cleaned","char","regexStr","matcher","RegExp","groups","isNaN","result","hour24","hour12","ampm","ampmUpper","toUpperCase","ampmLower","dateStr","parseSimpleDate","window","location","hostname","__DEV__","isDayObject","isRangeObject","areValuesEqual","v1","v2","getTime","every","i","areNormalizedValuesEqual","b","dayA","dayB","rangeA","rangeB","multiA","multiB","normalizeDayWithErrors","fieldName","field","dateFromString","parsed","normalizeInitValueWithErrors","errors","push","fromResult","toResult","dayResult","defaultWeekStart","getWeekBounds","item","isMultiArray","normalized","forEach","index","extractMonthFromValue","firstDay","getDaysInMonth","isJalaliLeapYear","daysInMonth","isGregorianLeapYear","maxDay","isDateInRange","minDate","maxDate","dayGregorian","minGregorian","maxGregorian","isDateDisabled","options","disabledDates","isDateDisabledCallback","some","disabledDay","disabledGregorian","isDateInDisabledList","isValidNormalizedValue","isDateSelectable","fromValid","toValid","compareDays","day1","day2","d1","d2","validateDay","locale","success","data","code","details","received","originalError","getFirstDayOfWeek","weekStart","getDayOfWeek","getDay","getMonthsToDisplay","baseMonth","numberOfMonths","_calendarSystem","months","getYearRange","_centerYear","_range","endYear","years","daysToSubtract","startDate","setDate","endDate","weekFrom","weekTo","isBefore","isSameDay","addDays","days","setUTCDate","getUTCDate","getUTCFullYear","getUTCMonth","subtractDays","addMonths","totalMonths","newYear","Math","floor","newMonth","min","originalDay","setUTCMonth","subtractMonths","addYears","newDay","setUTCFullYear","startOfMonth","endOfMonth","getPresetRange","preset","yesterday","lastMonthToday","getPresetRangesFromConfig","config","presetRanges","presets","presetType","label","getPresetLabel","custom","customPreset","getEffectiveWeekStart","getGregorianDayOfWeek","position","effectiveWeekStart","isWeekendDay","gregorianDayOfWeek","getWeekendConfig","weekendPositions","positions","getWeekendPositions","isWeekend","ChevronLeftIcon","className","jsx","width","height","viewBox","fill","xmlns","children","stroke","strokeWidth","strokeLinecap","strokeLinejoin","ChevronRightIcon","CalendarHeader","props","displayMonth","translations","customization","onPrevious","onNext","onMonthClick","onYearClick","previousTitle","nextTitle","showYear","showMonth","classes","icons","header","headerClass","next","NextBtnIcon","previous","PreviousBtnIcon","monthNames","actualPreviousTitle","labels","previousMonth","actualNextTitle","nextMonth","onClick","title","jsxs","style","cursor","numbers","visibility","displayName","HOUR_OPTIONS_24","_","HOUR_OPTIONS_12","MINUTE_OPTIONS","TimeSelector","React","memo","timeFormat","disabled","onTimeChange","currentHour","currentMinute","is24Hour","displayHour","isPM","hourOptions","minuteOptions","str","onChange","e","selectedDisplayHour","target","newHour","newMinute","newIsPM","am","pm","prevProps","nextProps","gregorianMonths","en","fa","de","es","fr","ko","jalaliMonths","weekdayNames","translationLabels","clear","ok","selectMonth","selectYear","timeFrom","timeTo","presetRangesLabels","last7days","last30days","thisMonth","lastMonth","localeConfig","direction","rtlLocales","createTranslation","weekdays","getNumberSystem","getMonthNamesByCalendarSystem","mergeTranslations","defaultTranslations","customTranslations","calendar","effectiveLocale","baseLocale","isJalaliNonEnglish","translationLocale","defaultWeekdays","persianJalali","getTextDirection","addSystemTimeIfNeeded","now","resolveDisplayMonth","prevDisplay","newValue","currentRange","monthFromValue","m","dateSelectionReducer","state","action","context","dayWithTime","payload","selectedValue","currentView","emittedValue","rangeReducer","newRange","toWithTime","fromWithTime","finalRange","weekReducer","weekBounds","multiReducer","currentMulti","filter","timeReducer","updatedDay","isStartDate","isEndDate","currentWeek","newWeek","navigateMonth","currentMonth","navigationReducer","useCalendarState","initValue","onCalenderChange","monthFromInitValue","initialState","emittedValueRef","useRef","dispatch","useReducer","reducers","reducer","calendarReducer","current","prevInitValueRef","useEffect","normalizedValue","jsDateValue","formattedString","actions","selectDate","selectRangeStart","selectRangeEnd","selectWeek","selectRangeDirect","selectPresetRange","toggleMultiDate","updateTime","clearSelection","setDisplayMonth","setView","view","goToToday","createActions","normalizeConstraintsProps","constraintsInput","_type","constraints","normalizedDates","daysToAdd","greg","getFocusableElements","container","selector","querySelectorAll","useCalendarSetup","normalizedCalendarSystem","useMemo","normalizeCalendarSystem","input","getEffectiveLocale","getTranslations","useCalendarCallbacks","onDateSelect","onMonthSelect","onYearSelect","onViewChange","onMonthNavigate","onGoToToday","handleDateSelect","useCallback","handleMonthSelect","handleYearSelect","handleViewChange","handleMonthNavigate","handleGoToToday","handlePresetRangeSelect","useModalState","isOpen","setIsOpen","useState","pickerRef","modalRef","handlers","open","close","toggle","prev","onClose","handleClickOutside","event","clickedElement","isInput","closest","isToggleButton","isClearButton","calendarCore","querySelector","contains","timeoutId","setTimeout","document","addEventListener","clearTimeout","removeEventListener","useClickOutside","handleEscape","key","useEscapeKey","containerRef","enabled","autoFocus","restoreFocus","previouslyFocusedElement","activeElement","focusableElements","focus","preventScroll","handleKeyDown","firstElement","lastElement","shiftKey","preventDefault","useFocusTrap","refs","useCalendarErrorHandling","constraintsErrors","initValueErrors","onError","callback","compareFn","prevValueRef","useCallbackOnChange","CalendarGridView","_locale","showWeekend","todayBtn","enlargeSelectedDay","onPresetRangeSelect","effectiveTimeFormat","daysClass","nextMonthBtnTitle","previousMonthBtnTitle","isRTL","dayNames","array","startIndex","rotated","moved","splice","rotateArray","getRotatedWeekdayNames","monthsToDisplay","calendarGrids","monthNum","firstDayOfWeek","daysFromPrevMonth","prevMonth","prevYear","daysInPrevMonth","todayDayObj","grid","isCurrentMonth","isToday","dayObject","nextYear","nextMonthDay","lastWeek","lastDay","nextDay","generateCalendarGrid","gridRef","gridElementRef","isDateSelectableForNav","focusedDate","setFocusedDate","getCellRef","initialDate","selectedDate","cellRefs","Map","getDateKey","element","set","delete","focusDate","get","resetFocus","newFocus","useFocusManagement","newFocusedDate","onFocusedDateChange","focusedDateRef","navigateToDate","navigateRecursive","newDate","attempts","handleArrowNavigation","navDirection","handleHomeEnd","jalaaliMonthLength","handlePageUpDown","monthDelta","lastDayOfNewMonth","ctrlKey","metaKey","handled","stopPropagation","useKeyboardNavigation","renderMonthGrid","monthIndex","monthLabel","yearLabel","role","name","weekendConfig","dayNameClassNames","Boolean","ref","tabIndex","weekIndex","weekClassNames","calendarDay","dayIndex","isOtherMonth","isSelected","selected","dayCompare","toCompare","selectedDay","isDaySelected","isInRange","isDayInRange","isStart","isRangeStart","isEnd","isRangeEnd","isSelectable","isPrevMonth","isNextMonth","isLastDayOfPrevMonth","classNames","isFocused","ariaLabel","todayLabel","fullAriaLabel","id","dir","isActive","presetRange","selectedRange","presetFrom","presetTo","selectedFrom","selectedTo","isPresetRangeActive","MonthView","monthsClass","monthName","YearView","yearListStyle","yearsClass","isGrid","yearsContainerRef","currentYearIndex","findIndex","yearItemHeight","containerHeight","columnsPerRow","scrollPosition","scrollTo","top","max","behavior","isCurrentYear","CalendarCore","CalendarIcon","DtPickerTrigger","triggerElement","displayValue","placeholder","isDisabled","clearBtn","hasSelectedValue","onTriggerClick","onInputKeyDown","onClear","inputRef","triggerRef","inputId","inputClass","triggerClass","translationsClear","CalendarIconComponent","display","inputWrapperClass","el","readOnly","onKeyDown","DtPicker","showTimeInput","calenderModalClass","autoClose","dark","modalHandlers","createRef","constraintsResult","initValueResult","normalizedInitValue","validatedInitValue","useCalendarPicker","modalPosition","setModalPosition","calculateModalPosition","triggerRect","getBoundingClientRect","modalRect","modalHeight","modalWidth","viewportHeight","innerHeight","viewportWidth","innerWidth","bottom","left","right","calculateModalPositionRef","handleResize","handleScroll","useModalPosition","handleTriggerClick","handleInputKeyDown","handleClear","modalClass","zIndex","DtCalendar","onDateSelectProp","onMonthSelectProp","onYearSelectProp","onViewChangeProp","onMonthNavigateProp","onGoToTodayProp","diffTime","yearDiff","start","end","yearRangeArr","minYear","maxYear","yearRange"],"mappings":"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AkB,CAC7BC,GAAI,CACF,UACA,WACA,QACA,QACA,MACA,OACA,OACA,SACA,YACA,UACA,WACA,YAEFC,GAAI,CACF,SACA,QACA,OACA,QACA,KACA,OACA,QACA,MACA,UACA,QACA,SACA,UAEFC,GAAI,CACF,SACA,UACA,OACA,QACA,MACA,OACA,OACA,SACA,YACA,UACA,WACA,YAEFC,GAAI,CACF,QACA,UACA,QACA,QACA,OACA,QACA,QACA,SACA,aACA,UACA,YACA,aAEFC,GAAI,CACF,UACA,UACA,OACA,QACA,MACA,OACA,UACA,OACA,YACA,UACA,WACA,YAEFC,GAAI,CACF,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,MACA,MACA,QAOSC,GAAe,CAC1BL,GAAI,CACF,UACA,WACA,QACA,MACA,QACA,SACA,MACA,OACA,MACA,KACA,OACA,SAEFD,GAAI,CACF,YACA,cACA,UACA,MACA,SACA,YACA,OACA,OACA,OACA,MACA,SACA,WAOEO,GAAe,CACnBP,GAAI,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MACzCC,GAAI,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KACnCC,GAAI,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MACzCC,GAAI,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MACzCC,GAAI,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MACzCC,GAAI,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAM/BG,GAAoB,CACxBR,GAAI,CACFrT,MAAO,QACP8T,MAAO,QACPC,GAAI,KACJjD,UAAW,OACXF,cAAe,WACfoD,YAAa,eACbC,WAAY,cACZjT,KAAM,OACNC,GAAI,KACJiT,SAAU,OACVC,OAAQ,KACRnB,GAAI,KACJC,GAAI,MAENK,GAAI,CACFtT,MAAO,QACP8T,MAAO,WACPC,GAAI,QACJjD,UAAW,OACXF,cAAe,OACfoD,YAAa,aACbC,WAAY,aACZjT,KAAM,KACNC,GAAI,KACJiT,SAAU,KACVC,OAAQ,KACRnB,GA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"}