70 lines
2.6 KiB
JavaScript
70 lines
2.6 KiB
JavaScript
import { nextTypeAheadElement } from '../utils/nextTypeAheadElement';
|
|
import { treeDataTypes } from '../utils/tokens';
|
|
import { useRovingTabIndex } from './useRovingTabIndexes';
|
|
import * as React from 'react';
|
|
import { useHTMLElementWalkerRef } from './useHTMLElementWalkerRef';
|
|
import { useMergedRefs } from '@fluentui/react-utilities';
|
|
/**
|
|
* @internal
|
|
*/ export function useTreeNavigation() {
|
|
'use no memo';
|
|
const { rove, initialize: initializeRovingTabIndex } = useRovingTabIndex();
|
|
const { walkerRef, rootRef: walkerRootRef } = useHTMLElementWalkerRef();
|
|
const rootRefCallback = React.useCallback((root)=>{
|
|
if (root && walkerRef.current) {
|
|
initializeRovingTabIndex(walkerRef.current);
|
|
}
|
|
}, [
|
|
walkerRef,
|
|
initializeRovingTabIndex
|
|
]);
|
|
const getNextElement = (data)=>{
|
|
if (!walkerRef.current) {
|
|
return null;
|
|
}
|
|
switch(data.type){
|
|
case treeDataTypes.Click:
|
|
return data.target;
|
|
case treeDataTypes.TypeAhead:
|
|
walkerRef.current.currentElement = data.target;
|
|
return nextTypeAheadElement(walkerRef.current, data.event.key);
|
|
case treeDataTypes.ArrowLeft:
|
|
walkerRef.current.currentElement = data.target;
|
|
return walkerRef.current.parentElement();
|
|
case treeDataTypes.ArrowRight:
|
|
walkerRef.current.currentElement = data.target;
|
|
return walkerRef.current.firstChild();
|
|
case treeDataTypes.End:
|
|
walkerRef.current.currentElement = walkerRef.current.root;
|
|
return lastChildRecursive(walkerRef.current);
|
|
case treeDataTypes.Home:
|
|
walkerRef.current.currentElement = walkerRef.current.root;
|
|
return walkerRef.current.firstChild();
|
|
case treeDataTypes.ArrowDown:
|
|
walkerRef.current.currentElement = data.target;
|
|
return walkerRef.current.nextElement();
|
|
case treeDataTypes.ArrowUp:
|
|
walkerRef.current.currentElement = data.target;
|
|
return walkerRef.current.previousElement();
|
|
}
|
|
};
|
|
function navigate(data, focusOptions) {
|
|
const nextElement = getNextElement(data);
|
|
if (nextElement) {
|
|
rove(nextElement, focusOptions);
|
|
}
|
|
}
|
|
return {
|
|
navigate,
|
|
treeRef: useMergedRefs(walkerRootRef, rootRefCallback)
|
|
};
|
|
}
|
|
function lastChildRecursive(walker) {
|
|
let lastElement = null;
|
|
let nextElement = null;
|
|
while(nextElement = walker.lastChild()){
|
|
lastElement = nextElement;
|
|
}
|
|
return lastElement;
|
|
}
|