RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/views/room/composer/messageBox/hooks/useMessageBoxAutoFocus.ts

Summary

Maintainability
A
2 hrs
Test Coverage
import type { Ref } from 'react';
import { useCallback, useEffect, useRef } from 'react';

/**
 * if the user is types outside the message box and its not actually typing in any input field
 * then the message box should be focused
 * @returns callbackRef to bind the logic to the message box
 */
export const useMessageBoxAutoFocus = (enabled: boolean): Ref<HTMLElement> => {
    const ref = useRef<HTMLElement>();

    useEffect(() => {
        const handleKeyDown = (e: KeyboardEvent) => {
            const { current: node } = ref;
            const { target } = e;

            if (!target) {
                return;
            }

            if (target === node) {
                return;
            }
            if (!((e.keyCode > 45 && e.keyCode < 91) || e.keyCode === 8)) {
                return;
            }

            if (/input|textarea|select/i.test((target as HTMLElement).tagName)) {
                return;
            }

            if (e.ctrlKey === true || e.metaKey === true) {
                return;
            }

            node?.focus();
        };

        document.addEventListener('keydown', handleKeyDown);

        return () => {
            document.removeEventListener('keydown', handleKeyDown);
        };
    }, []);

    return useCallback(
        (node: HTMLElement | null) => {
            if (!node) {
                return;
            }

            ref.current = node;

            if (!enabled) {
                return;
            }

            if (ref.current) {
                ref.current.focus();
            }
        },
        [enabled, ref],
    );
};