Repository: adobe/react-spectrum
File: packages/@react-aria/focus/src/FocusScope.tsx (TypeScript)

Code before:

    scope = scope.parent;
  }

  return true;
}

function getRadiosInGroup(element: HTMLInputElement): HTMLInputElement[] {
  if (!element.form) {
    // Radio buttons outside a form - query the document
    return Array.from(
      getOwnerDocument(element).querySelectorAll<HTMLInputElement>(
        `input[type="radio"][name="${CSS.escape(element.name)}"]`
      )
    ).filter(radio => !radio.form);
  }

  // namedItem returns RadioNodeList (iterable) for 2+ elements, but a single Element for exactly 1.
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection/namedItem
  const radioList = element.form.elements.namedItem(element.name);
  if (radioList instanceof RadioNodeList) {
    return Array.from(radioList).filter(
      (el): el is HTMLInputElement => el instanceof HTMLInputElement
    );
  }
  if (radioList instanceof HTMLInputElement) {
    return [radioList];
  }
  return [];
}

function isTabbableRadio(element: HTMLInputElement): boolean {
  if (element.checked) {
    return true;
  }
  const radios = getRadiosInGroup(element);
  return radios.length > 0 && !radios.some(radio => radio.checked);
}

function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: boolean) {
  let focusedNode = useRef<FocusableElement>(undefined);

  let raf = useRef<ReturnType<typeof requestAnimationFrame>>(undefined);
  useLayoutEffect(() => {
    let scope = scopeRef.current;
    if (!contain) {
      // if contain was changed, then we should cancel any ongoing waits to pull focus back into containment
      if (raf.current) {
        cancelAnimationFrame(raf.current);
        raf.current = undefined;
      }

Review comment (suggestion):
```suggestion
  if (radioList instanceof ownerWindow.HTMLInputElement) {
```

Code after:
    }

    scope = scope.parent;
  }

  return true;
}

function getRadiosInGroup(element: HTMLInputElement): HTMLInputElement[] {
  if (!element.form) {
    // Radio buttons outside a form - query the document
    return Array.from(
      getOwnerDocument(element).querySelectorAll<HTMLInputElement>(
        `input[type="radio"][name="${CSS.escape(element.name)}"]`
      )
    ).filter(radio => !radio.form);
  }

  // namedItem returns RadioNodeList (iterable) for 2+ elements, but a single Element for exactly 1.
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection/namedItem
  const radioList = element.form.elements.namedItem(element.name);
  let ownerWindow = getOwnerWindow(element);
  if (radioList instanceof ownerWindow.RadioNodeList) {
    return Array.from(radioList).filter(
      (el): el is HTMLInputElement => el instanceof ownerWindow.HTMLInputElement
    );
  }
  if (radioList instanceof ownerWindow.HTMLInputElement) {
    return [radioList];
  }
  return [];
}

function isTabbableRadio(element: HTMLInputElement): boolean {
  if (element.checked) {
    return true;
  }
  const radios = getRadiosInGroup(element);
  return radios.length > 0 && !radios.some(radio => radio.checked);
}

function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: boolean) {
  let focusedNode = useRef<FocusableElement>(undefined);

  let raf = useRef<ReturnType<typeof requestAnimationFrame>>(undefined);
  useLayoutEffect(() => {
    let scope = scopeRef.current;
    if (!contain) {
      // if contain was changed, then we should cancel any ongoing waits to pull focus back into containment
      if (raf.current) {
        cancelAnimationFrame(raf.current);