UNPKG

2.18 kBPlain TextView Raw
1import { useState } from "react";
2
3import type { CalendarDay } from "./classes/index.js";
4import { calculateFocusTarget } from "./helpers/calculateFocusTarget.js";
5import { getNextFocus } from "./helpers/getNextFocus.js";
6import type {
7 MoveFocusBy,
8 MoveFocusDir,
9 DateLib,
10 DayPickerProps,
11 Modifiers
12} from "./types/index.js";
13import { Calendar } from "./useCalendar.js";
14
15export type UseFocus = {
16 /** The date that is currently focused. */
17 focused: CalendarDay | undefined;
18
19 /** Check if the given day is the focus target when entering the calendar. */
20 isFocusTarget: (day: CalendarDay) => boolean;
21
22 /** Focus the given day. */
23 setFocused: (day: CalendarDay | undefined) => void;
24
25 /** Blur the focused day. */
26 blur: () => void;
27
28 /** Move the current focus to the next day according to the given direction. */
29 moveFocus: (moveBy: MoveFocusBy, moveDir: MoveFocusDir) => void;
30};
31
32/** @private */
33export function useFocus<T extends DayPickerProps>(
34 props: T,
35 calendar: Calendar,
36 getModifiers: (day: CalendarDay) => Modifiers,
37 isSelected: (date: Date) => boolean,
38 dateLib: DateLib
39): UseFocus {
40 const { autoFocus } = props;
41 const [lastFocused, setLastFocused] = useState<CalendarDay | undefined>();
42
43 const focusTarget = calculateFocusTarget(
44 calendar.days,
45 getModifiers,
46 isSelected || (() => false),
47 lastFocused
48 );
49 const [focusedDay, setFocused] = useState<CalendarDay | undefined>(
50 autoFocus ? focusTarget : undefined
51 );
52
53 const blur = () => {
54 setLastFocused(focusedDay);
55 setFocused(undefined);
56 };
57
58 const moveFocus = (moveBy: MoveFocusBy, moveDir: MoveFocusDir) => {
59 if (!focusedDay) return;
60 const nextFocus = getNextFocus(
61 moveBy,
62 moveDir,
63 focusedDay,
64 calendar.navStart,
65 calendar.navEnd,
66 props,
67 dateLib
68 );
69 if (!nextFocus) return;
70
71 calendar.goToDay(nextFocus);
72 setFocused(nextFocus);
73 };
74
75 const isFocusTarget = (day: CalendarDay) => {
76 return Boolean(focusTarget?.isEqualTo(day));
77 };
78
79 const useFocus: UseFocus = {
80 isFocusTarget,
81 setFocused,
82 focused: focusedDay,
83 blur,
84 moveFocus
85 };
86
87 return useFocus;
88}