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

Function useFocusContainment

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

Source from the content-addressed store, hash-verified

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

Callers 1

FocusScopeFunction · 0.85

Calls 3

getOwnerDocumentFunction · 0.90
addEventListenerMethod · 0.80
removeEventListenerMethod · 0.80

Tested by

no test coverage detected