MCPcopy Create free account
hub / github.com/adobe/react-spectrum / getFocusableTreeWalker

Function getFocusableTreeWalker

packages/react-aria/src/focus/FocusScope.tsx:839–896  ·  view source on GitHub ↗
(
  root: Element,
  opts?: FocusManagerOptions,
  scope?: Element[]
)

Source from the content-addressed store, hash-verified

837 * that matches all focusable/tabbable elements.
838 */
839export function getFocusableTreeWalker(
840 root: Element,
841 opts?: FocusManagerOptions,
842 scope?: Element[]
843): ShadowTreeWalker | TreeWalker {
844 let filter = opts?.tabbable ? isTabbable : isFocusable;
845
846 // Ensure that root is an Element or fall back appropriately
847 let rootElement = root?.nodeType === Node.ELEMENT_NODE ? (root as Element) : null;
848
849 // Determine the document to use
850 let doc = getOwnerDocument(rootElement);
851
852 // Create a TreeWalker, ensuring the root is an Element or Document
853 let walker = createShadowTreeWalker(doc, root || doc, NodeFilter.SHOW_ELEMENT, {
854 acceptNode(node) {
855 // Skip nodes inside the starting node.
856 if (nodeContains(opts?.from, node)) {
857 return NodeFilter.FILTER_REJECT;
858 }
859
860 if (
861 opts?.tabbable &&
862 (node as Element).tagName === 'INPUT' &&
863 (node as HTMLInputElement).getAttribute('type') === 'radio'
864 ) {
865 // If the radio is in a form, we can get all the other radios by name
866 if (!isTabbableRadio(node as HTMLInputElement)) {
867 return NodeFilter.FILTER_REJECT;
868 }
869 // If the radio is in the same group as the current node and none are selected, we can skip it
870 if (
871 (walker.currentNode as Element).tagName === 'INPUT' &&
872 (walker.currentNode as HTMLInputElement).type === 'radio' &&
873 (walker.currentNode as HTMLInputElement).name === (node as HTMLInputElement).name
874 ) {
875 return NodeFilter.FILTER_REJECT;
876 }
877 }
878
879 if (
880 filter(node as Element) &&
881 (!scope || isElementInScope(node as Element, scope)) &&
882 (!opts?.accept || opts.accept(node as Element))
883 ) {
884 return NodeFilter.FILTER_ACCEPT;
885 }
886
887 return NodeFilter.FILTER_SKIP;
888 }
889 });
890
891 if (opts?.from) {
892 walker.currentNode = opts.from;
893 }
894
895 return walker;
896}

Callers 15

onTriggerKeyDownFunction · 0.90
focusFunction · 0.90
onKeyDownCaptureFunction · 0.90
onKeyDownFunction · 0.90
tabFunction · 0.90
focusFunction · 0.90
onKeyDownCaptureFunction · 0.90
onKeyDownFunction · 0.90
getNextElementFunction · 0.90
updateFunction · 0.90
focusLastFunction · 0.90
findNextSegmentFunction · 0.90

Calls 2

getOwnerDocumentFunction · 0.90
createShadowTreeWalkerFunction · 0.90

Tested by

no test coverage detected