aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks/use-autofocus/use-autofocus.ts
blob: 0d21a599219912244c92f91dd873b851876b3427 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { useCallback, useRef, type MutableRefObject } from 'react';
import { useTimeout } from '../use-timeout';

export type UseAutofocusCondition = () => boolean;

export type UseAutofocusConfig = {
  /**
   * A condition to met before giving focus to the element.
   */
  condition?: UseAutofocusCondition;
  /**
   * A delay in ms before giving focus to the element.
   */
  delay?: number;
};

/**
 * React hook to give focus to an element automatically.
 *
 * @param {UseAutofocusConfig} [config] - A configuration object.
 * @returns {RefObject<T>} The element reference.
 */
export const useAutofocus = <T extends HTMLElement>(
  config?: UseAutofocusConfig
): MutableRefObject<T | null> => {
  const { condition, delay } = config ?? {};
  const ref = useRef<T | null>(null);

  const setFocus = useCallback(() => {
    const shouldFocus = condition ? condition() : true;

    if (ref.current && shouldFocus) {
      ref.current.focus();
    }
  }, [condition]);

  useTimeout(setFocus, delay);

  return ref;
};