TelegramPWA/src/hooks/useKeyboardListNavigation.ts
Alexander Zinchuk 7e41f190b2 StricterDOM: Fix several component errors (#4374)
Co-authored-by: zubiden <19638254+zubiden@users.noreply.github.com>
2024-03-29 20:51:24 +01:00

66 lines
1.8 KiB
TypeScript

import type { RefObject } from 'react';
import { useEffect, useState } from '../lib/teact/teact';
import { requestMeasure, requestMutation } from '../lib/fasterdom/fasterdom';
import useLastCallback from './useLastCallback';
const useKeyboardListNavigation = (
elementRef: RefObject<HTMLElement>,
isOpen: boolean,
onSelectWithEnter?: (index: number) => void,
itemSelector?: string,
noCaptureFocus?: boolean,
) => {
const [focusedIndex, setFocusedIndex] = useState(-1);
useEffect(() => {
setFocusedIndex(-1);
const element = elementRef.current;
if (isOpen && element && !noCaptureFocus) {
requestMutation(() => { element.tabIndex = -1; });
requestMeasure(() => element.focus());
}
}, [elementRef, isOpen, noCaptureFocus]);
return useLastCallback((e: React.KeyboardEvent<any>) => {
const element = elementRef.current;
if (!element) {
return;
}
if (e.keyCode === 13 && onSelectWithEnter) {
onSelectWithEnter(focusedIndex);
return;
}
if (e.keyCode !== 38 && e.keyCode !== 40) {
return;
}
const focusedElement = document.activeElement;
const elementChildren = Array.from(itemSelector ? element.querySelectorAll(itemSelector) : element.children);
let newIndex = (focusedElement && elementChildren.indexOf(focusedElement)) || focusedIndex;
if (e.keyCode === 38 && newIndex > 0) {
newIndex--;
} else if (e.keyCode === 40 && newIndex < elementChildren.length - 1) {
newIndex++;
} else if (elementChildren.length === 1) {
newIndex = 0;
} else {
return;
}
const item = elementChildren[newIndex] as HTMLElement;
if (item) {
setFocusedIndex(newIndex);
item.focus();
}
});
};
export default useKeyboardListNavigation;