@gravity-ui/uikit
Version:
Gravity UI base styling and components
75 lines (74 loc) • 2.9 kB
JavaScript
import * as React from 'react';
import { KeyCode } from "../../../constants.js";
import { findNextIndex } from "../utils/findNextIndex.js";
import { scrollToListItem } from "../utils/scrollToListItem.js";
// Use this hook if you need keyboard support for tree structure lists
export const useListKeydown = ({ containerRef, onItemClick, enabled, list }) => {
const activateItem = React.useCallback((index, scrollTo = true) => {
if (typeof index === 'number' && list.structure.visibleFlattenIds[index]) {
if (scrollTo) {
scrollToListItem(list.structure.visibleFlattenIds[index], containerRef?.current);
}
list.state.setActiveItemId?.(list.structure.visibleFlattenIds[index]);
}
}, [list.structure.visibleFlattenIds, list.state, containerRef]);
const handleKeyMove = React.useCallback((event, step, defaultItemIndex = 0) => {
event.preventDefault();
const maybeIndex = typeof list.state.activeItemId === 'string'
? list.structure.visibleFlattenIds.findIndex((i) => i === list.state.activeItemId)
: -1;
const nextIndex = findNextIndex({
list: list.structure.visibleFlattenIds,
index: (maybeIndex > -1 ? maybeIndex : defaultItemIndex) + step,
step: Math.sign(step),
disabledItemsById: list.state.disabledById,
});
activateItem(nextIndex);
}, [
activateItem,
list.state.activeItemId,
list.state.disabledById,
list.structure.visibleFlattenIds,
]);
React.useLayoutEffect(() => {
const anchor = containerRef?.current;
if (enabled || !anchor) {
return undefined;
}
const handleKeyDown = (event) => {
switch (event.key) {
case KeyCode.ARROW_DOWN: {
handleKeyMove(event, 1, -1);
break;
}
case KeyCode.ARROW_UP: {
handleKeyMove(event, -1);
break;
}
case KeyCode.SPACEBAR:
case KeyCode.ENTER: {
if (list.state.activeItemId &&
!list.state.disabledById[list.state.activeItemId]) {
event.preventDefault();
onItemClick?.({ id: list.state.activeItemId });
}
break;
}
default: {
}
}
};
anchor.addEventListener('keydown', handleKeyDown);
return () => {
anchor.removeEventListener('keydown', handleKeyDown);
};
}, [
containerRef,
enabled,
handleKeyMove,
list.state.activeItemId,
list.state.disabledById,
onItemClick,
]);
};
//# sourceMappingURL=useListKeydown.js.map