You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
44 lines
1.7 KiB
44 lines
1.7 KiB
const handleArrowKeys = (e, { allowVerticalArrows }) => { |
|
const { activeElement } = document; |
|
const getNthChildSafe = (element, index) => (element ? element.children[index] : null); |
|
const getStandardItem = item => item && (item.hasAttribute('aria-hidden') ? null : item); |
|
const { nextSibling: nextRow, previousSibling: previousRow } = activeElement.parentElement; |
|
const nextSibling = getStandardItem(activeElement.nextSibling || getNthChildSafe(nextRow, 0)); |
|
const previousRowLength = previousRow ? previousRow.children.length - 1 : 0; |
|
const previousSibling = getStandardItem( |
|
activeElement.previousSibling || getNthChildSafe(previousRow, previousRowLength), |
|
); |
|
const getVerticalSibling = row => |
|
getNthChildSafe(row, Array.from(activeElement.parentElement.children).indexOf(activeElement)); |
|
const downSibling = getStandardItem(getVerticalSibling(nextRow)); |
|
const upSibling = getStandardItem(getVerticalSibling(previousRow)); |
|
const isDefaultSelectable = activeElement.dataset.isDefaultSelectable === 'true'; |
|
|
|
if (!isDefaultSelectable) activeElement.tabIndex = '-1'; |
|
const focusIfAvailable = element => { |
|
e.preventDefault(); |
|
/* istanbul ignore else */ |
|
if (element) { |
|
element.setAttribute('tabindex', '0'); |
|
element.focus(); |
|
} |
|
}; |
|
switch (e.key) { |
|
case 'ArrowRight': |
|
focusIfAvailable(nextSibling); |
|
break; |
|
case 'ArrowLeft': |
|
focusIfAvailable(previousSibling); |
|
break; |
|
case 'ArrowDown': |
|
/* istanbul ignore else */ |
|
if (allowVerticalArrows) focusIfAvailable(downSibling); |
|
break; |
|
case 'ArrowUp': |
|
/* istanbul ignore else */ |
|
if (allowVerticalArrows) focusIfAvailable(upSibling); |
|
break; |
|
} |
|
}; |
|
|
|
export default handleArrowKeys;
|
|
|