{"version":3,"file":"handle-year-view-key-down.cjs","names":[],"sources":["../../../src/components/YearView/handle-year-view-key-down.ts"],"sourcesContent":["import { RefObject } from 'react';\n\n/** Reference to a 3D array of day buttons: [monthIndex][weekIndex][dayIndex] */\nexport type YearViewControlsRef = RefObject<HTMLButtonElement[][][]>;\n\ntype Direction = 'up' | 'down' | 'left' | 'right';\n\ninterface DayPosition {\n  monthIndex: number;\n  weekIndex: number;\n  dayIndex: number;\n}\n\nfunction getDirection(key: KeyboardEvent['key']): Direction | null {\n  switch (key) {\n    case 'ArrowDown':\n      return 'down';\n    case 'ArrowUp':\n      return 'up';\n    case 'ArrowRight':\n      return 'right';\n    case 'ArrowLeft':\n      return 'left';\n    default:\n      return null;\n  }\n}\n\nfunction getControlsSize(controlsRef: YearViewControlsRef): number[][] | null {\n  if (!controlsRef.current) {\n    return null;\n  }\n  return controlsRef.current.map((month) =>\n    month ? month.map((week) => (week ? week.length : 0)) : []\n  );\n}\n\ninterface GetNextPositionInput {\n  direction: Direction;\n  monthIndex: number;\n  weekIndex: number;\n  dayIndex: number;\n  size: number[][];\n}\n\nfunction getNextPosition({\n  direction,\n  monthIndex,\n  weekIndex,\n  dayIndex,\n  size,\n}: GetNextPositionInput): DayPosition | null {\n  const currentMonthSize = size[monthIndex];\n  if (!currentMonthSize) {\n    return null;\n  }\n\n  switch (direction) {\n    case 'up': {\n      if (weekIndex === 0) {\n        if (monthIndex === 0) {\n          return null;\n        }\n        const prevMonthSize = size[monthIndex - 1];\n        if (!prevMonthSize || prevMonthSize.length === 0) {\n          return null;\n        }\n\n        const lastWeekIndex = prevMonthSize.length - 1;\n        const clampedDayIndex = Math.min(dayIndex, prevMonthSize[lastWeekIndex] - 1);\n        return {\n          monthIndex: monthIndex - 1,\n          weekIndex: lastWeekIndex,\n          dayIndex: clampedDayIndex,\n        };\n      }\n\n      const prevWeekSize = currentMonthSize[weekIndex - 1];\n      const clampedDayIndex = Math.min(dayIndex, prevWeekSize - 1);\n      return {\n        monthIndex,\n        weekIndex: weekIndex - 1,\n        dayIndex: clampedDayIndex,\n      };\n    }\n\n    case 'down': {\n      if (weekIndex === currentMonthSize.length - 1) {\n        if (monthIndex === size.length - 1) {\n          return null;\n        }\n        const nextMonthSize = size[monthIndex + 1];\n        if (!nextMonthSize || nextMonthSize.length === 0) {\n          return null;\n        }\n\n        const clampedDayIndex = Math.min(dayIndex, nextMonthSize[0] - 1);\n        return {\n          monthIndex: monthIndex + 1,\n          weekIndex: 0,\n          dayIndex: clampedDayIndex,\n        };\n      }\n\n      const nextWeekSize = currentMonthSize[weekIndex + 1];\n      const clampedDayIndex = Math.min(dayIndex, nextWeekSize - 1);\n      return {\n        monthIndex,\n        weekIndex: weekIndex + 1,\n        dayIndex: clampedDayIndex,\n      };\n    }\n\n    case 'left': {\n      if (dayIndex === 0) {\n        if (weekIndex === 0) {\n          if (monthIndex === 0) {\n            return null;\n          }\n          const prevMonthSize = size[monthIndex - 1];\n          if (!prevMonthSize || prevMonthSize.length === 0) {\n            return null;\n          }\n          const lastWeekIndex = prevMonthSize.length - 1;\n          return {\n            monthIndex: monthIndex - 1,\n            weekIndex: lastWeekIndex,\n            dayIndex: prevMonthSize[lastWeekIndex] - 1,\n          };\n        }\n\n        return {\n          monthIndex,\n          weekIndex: weekIndex - 1,\n          dayIndex: currentMonthSize[weekIndex - 1] - 1,\n        };\n      }\n\n      return {\n        monthIndex,\n        weekIndex,\n        dayIndex: dayIndex - 1,\n      };\n    }\n\n    case 'right': {\n      const currentWeekSize = currentMonthSize[weekIndex];\n\n      if (dayIndex === currentWeekSize - 1) {\n        if (weekIndex === currentMonthSize.length - 1) {\n          if (monthIndex === size.length - 1) {\n            return null;\n          }\n          const nextMonthSize = size[monthIndex + 1];\n          if (!nextMonthSize || nextMonthSize.length === 0) {\n            return null;\n          }\n          return {\n            monthIndex: monthIndex + 1,\n            weekIndex: 0,\n            dayIndex: 0,\n          };\n        }\n\n        return {\n          monthIndex,\n          weekIndex: weekIndex + 1,\n          dayIndex: 0,\n        };\n      }\n\n      return {\n        monthIndex,\n        weekIndex,\n        dayIndex: dayIndex + 1,\n      };\n    }\n\n    default:\n      return null;\n  }\n}\n\ninterface FocusOnNextControlInput {\n  controlsRef: YearViewControlsRef;\n  direction: Direction;\n  monthIndex: number;\n  weekIndex: number;\n  dayIndex: number;\n  size: number[][];\n}\n\nfunction focusOnNextFocusableControl({\n  controlsRef,\n  direction,\n  monthIndex,\n  weekIndex,\n  dayIndex,\n  size,\n}: FocusOnNextControlInput): void {\n  const nextPosition = getNextPosition({\n    direction,\n    monthIndex,\n    weekIndex,\n    dayIndex,\n    size,\n  });\n\n  if (!nextPosition) {\n    return;\n  }\n\n  const controlToFocus =\n    controlsRef.current?.[nextPosition.monthIndex]?.[nextPosition.weekIndex]?.[\n      nextPosition.dayIndex\n    ];\n\n  if (!controlToFocus) {\n    return;\n  }\n\n  if (\n    controlToFocus.disabled ||\n    controlToFocus.getAttribute('data-hidden') ||\n    controlToFocus.getAttribute('data-outside') ||\n    controlToFocus.getAttribute('data-day-placeholder')\n  ) {\n    focusOnNextFocusableControl({\n      controlsRef,\n      direction,\n      monthIndex: nextPosition.monthIndex,\n      weekIndex: nextPosition.weekIndex,\n      dayIndex: nextPosition.dayIndex,\n      size,\n    });\n  } else {\n    controlToFocus.focus();\n  }\n}\n\nexport interface HandleYearViewKeyDownInput {\n  controlsRef: YearViewControlsRef;\n  monthIndex: number;\n  weekIndex: number;\n  dayIndex: number;\n  event: React.KeyboardEvent<HTMLButtonElement>;\n}\n\nexport function handleYearViewKeyDown({\n  controlsRef,\n  monthIndex,\n  weekIndex,\n  dayIndex,\n  event,\n}: HandleYearViewKeyDownInput): void {\n  const direction = getDirection(event.key);\n\n  if (direction) {\n    event.preventDefault();\n\n    const size = getControlsSize(controlsRef);\n\n    if (!size) {\n      return;\n    }\n\n    focusOnNextFocusableControl({\n      controlsRef,\n      direction,\n      monthIndex,\n      weekIndex,\n      dayIndex,\n      size,\n    });\n  }\n}\n"],"mappings":"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"}