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

Function useFocusContainment

packages/react-aria/src/focus/FocusScope.tsx:335–475  ·  view source on GitHub ↗
(scopeRef: RefObject<Element[] | null>, contain?: boolean)

Source from the content-addressed store, hash-verified

333}
334
335function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: boolean) {
336 let focusedNode = useRef<FocusableElement>(undefined);
337
338 let raf = useRef<ReturnType<typeof requestAnimationFrame>>(undefined);
339 useLayoutEffect(() => {
340 let scope = scopeRef.current;
341 if (!contain) {
342 // if contain was changed, then we should cancel any ongoing waits to pull focus back into containment
343 if (raf.current) {
344 cancelAnimationFrame(raf.current);
345 raf.current = undefined;
346 }
347 return;
348 }
349
350 const ownerDocument = getOwnerDocument(scope ? scope[0] : undefined);
351
352 // Handle the Tab key to contain focus within the scope
353 let onKeyDown = e => {
354 if (
355 e.key !== 'Tab' ||
356 e.altKey ||
357 e.ctrlKey ||
358 e.metaKey ||
359 !shouldContainFocus(scopeRef) ||
360 e.isComposing
361 ) {
362 return;
363 }
364
365 let focusedElement = getActiveElement(ownerDocument);
366 let scope = scopeRef.current;
367 if (!scope || !isElementInScope(focusedElement, scope)) {
368 return;
369 }
370
371 let scopeRoot = getScopeRoot(scope);
372 let walker = getFocusableTreeWalker(scopeRoot, {tabbable: true}, scope);
373 if (!focusedElement) {
374 return;
375 }
376 walker.currentNode = focusedElement;
377 let nextElement = (
378 e.shiftKey ? walker.previousNode() : walker.nextNode()
379 ) as FocusableElement;
380 if (!nextElement) {
381 walker.currentNode = e.shiftKey
382 ? scope[scope.length - 1].nextElementSibling!
383 : scope[0].previousElementSibling!;
384 nextElement = (e.shiftKey ? walker.previousNode() : walker.nextNode()) as FocusableElement;
385 }
386
387 e.preventDefault();
388 if (nextElement) {
389 focusElement(nextElement, true);
390 if (nextElement instanceof getOwnerWindow(nextElement).HTMLInputElement) {
391 nextElement.select();
392 }

Callers 1

FocusScopeFunction · 0.85

Calls 3

getOwnerDocumentFunction · 0.90
addEventListenerMethod · 0.80
removeEventListenerMethod · 0.80

Tested by

no test coverage detected