69 lines
2.8 KiB
JavaScript
69 lines
2.8 KiB
JavaScript
import * as React from 'react';
|
|
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
|
|
import { ArrowDown, ArrowRight, ArrowUp } from '@fluentui/keyboard-keys';
|
|
import { useArrowNavigationGroup, useFocusableGroup, useMergedTabsterAttributes_unstable, useFocusFinders, GroupperMoveFocusEvent, MoverMoveFocusEvent, GroupperMoveFocusActions, MoverKeys } from '@fluentui/react-tabster';
|
|
import { isHTMLElement } from '@fluentui/react-utilities';
|
|
export function useTableCompositeNavigation() {
|
|
const horizontalAttr = useArrowNavigationGroup({
|
|
axis: 'horizontal'
|
|
});
|
|
const gridAttr = useArrowNavigationGroup({
|
|
axis: 'grid'
|
|
});
|
|
const groupperAttr = useFocusableGroup({
|
|
tabBehavior: 'limited-trap-focus'
|
|
});
|
|
const { findFirstFocusable } = useFocusFinders();
|
|
const { targetDocument } = useFluent();
|
|
const rowAttr = useMergedTabsterAttributes_unstable(horizontalAttr, groupperAttr);
|
|
const onKeyDown = React.useCallback((e)=>{
|
|
if (!targetDocument) {
|
|
return;
|
|
}
|
|
let activeElement = targetDocument.activeElement;
|
|
if (!activeElement || !e.currentTarget.contains(activeElement)) {
|
|
return;
|
|
}
|
|
const activeElementRole = activeElement.getAttribute('role');
|
|
// Enter groupper when in row focus mode to navigate cells
|
|
if (e.key === ArrowRight && activeElementRole === 'row' && isHTMLElement(activeElement)) {
|
|
var _findFirstFocusable;
|
|
(_findFirstFocusable = findFirstFocusable(activeElement)) === null || _findFirstFocusable === void 0 ? void 0 : _findFirstFocusable.focus();
|
|
}
|
|
if (activeElementRole === 'row') {
|
|
return;
|
|
}
|
|
const isInCell = (()=>{
|
|
let cur = isHTMLElement(activeElement) ? activeElement : null;
|
|
while(cur){
|
|
const curRole = cur.getAttribute('role');
|
|
if (curRole === 'cell' || curRole === 'gridcell') {
|
|
return true;
|
|
}
|
|
cur = cur.parentElement;
|
|
}
|
|
return false;
|
|
})();
|
|
// Escape groupper focus trap before arrow down
|
|
if ((e.key === ArrowDown || e.key === ArrowUp) && isInCell) {
|
|
activeElement.dispatchEvent(new GroupperMoveFocusEvent({
|
|
action: GroupperMoveFocusActions.Escape
|
|
}));
|
|
activeElement = targetDocument.activeElement;
|
|
if (activeElement) {
|
|
activeElement.dispatchEvent(new MoverMoveFocusEvent({
|
|
key: MoverKeys[e.key]
|
|
}));
|
|
}
|
|
}
|
|
}, [
|
|
targetDocument,
|
|
findFirstFocusable
|
|
]);
|
|
return {
|
|
onTableKeyDown: onKeyDown,
|
|
tableTabsterAttribute: gridAttr,
|
|
tableRowTabsterAttribute: rowAttr
|
|
};
|
|
}
|