UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

104 lines (103 loc) 3.86 kB
import * as React from 'react'; import { moveBack } from "./moveBack.js"; import { moveForward } from "./moveForward.js"; export function useListNavigation({ items, skip, pageSize, processHomeKey = true, processEndKey = true, anchorRef, disabled = false, initialValue = -1, onAnchorKeyDown, }) { const [activeItemIndex, setActiveItemIndex] = React.useState(initialValue); const reset = React.useCallback(() => { setActiveItemIndex(initialValue); }, [initialValue]); React.useEffect(() => { if (items) { reset(); } }, [items, reset]); React.useLayoutEffect(() => { if (disabled) { return undefined; } const canNavigate = items.some((item) => !skip?.(item)); if (!canNavigate) { return undefined; } const anchor = anchorRef?.current; if (!anchor) { return undefined; } const handleKeyDown = (event) => { const shouldProcessKeydown = onAnchorKeyDown?.(activeItemIndex, event); if (shouldProcessKeydown === false) { return; } switch (event.key) { case 'ArrowDown': { event.preventDefault(); // Go 1 step forward setActiveItemIndex((previousActiveItemIndex) => moveForward(items, previousActiveItemIndex, 1, skip)); break; } case 'ArrowUp': { event.preventDefault(); // Go 1 step back setActiveItemIndex((previousActiveItemIndex) => moveBack(items, previousActiveItemIndex, 1, skip)); break; } case 'PageDown': { if (!pageSize) { return; } event.preventDefault(); // Go pageSize steps forward setActiveItemIndex((previousActiveItemIndex) => moveForward(items, previousActiveItemIndex, pageSize, skip)); break; } case 'PageUp': { if (!pageSize) { return; } event.preventDefault(); // Go pageSize steps back setActiveItemIndex((previousActiveItemIndex) => moveBack(items, previousActiveItemIndex, pageSize, skip)); break; } case 'Home': { if (!processHomeKey) { return; } event.preventDefault(); // Go to the start of the list setActiveItemIndex((previousActiveItemIndex) => moveBack(items, previousActiveItemIndex, previousActiveItemIndex, skip)); break; } case 'End': { if (!processEndKey) { return; } event.preventDefault(); // Go to the end of the list setActiveItemIndex((previousActiveItemIndex) => moveBack(items, previousActiveItemIndex, previousActiveItemIndex + 1, skip)); break; } } }; anchor.addEventListener('keydown', handleKeyDown); return () => { anchor.removeEventListener('keydown', handleKeyDown); }; }, [ activeItemIndex, anchorRef, disabled, items, onAnchorKeyDown, pageSize, processEndKey, processHomeKey, skip, ]); return { activeItemIndex, setActiveItemIndex, reset, }; } //# sourceMappingURL=useListNavigation.js.map