You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

33 lines
1.2 KiB

2 months ago
  1. // @flow
  2. import getScrollParent from './getScrollParent';
  3. import getParentNode from './getParentNode';
  4. import getWindow from './getWindow';
  5. import type { Window, VisualViewport } from '../types';
  6. import isScrollParent from './isScrollParent';
  7. /*
  8. given a DOM element, return the list of all scroll parents, up the list of ancesors
  9. until we get to the top window object. This list is what we attach scroll listeners
  10. to, because if any of these parent elements scroll, we'll need to re-calculate the
  11. reference element's position.
  12. */
  13. export default function listScrollParents(
  14. element: Node,
  15. list: Array<Element | Window> = []
  16. ): Array<Element | Window | VisualViewport> {
  17. const scrollParent = getScrollParent(element);
  18. const isBody = scrollParent === element.ownerDocument?.body;
  19. const win = getWindow(scrollParent);
  20. const target = isBody
  21. ? [win].concat(
  22. win.visualViewport || [],
  23. isScrollParent(scrollParent) ? scrollParent : []
  24. )
  25. : scrollParent;
  26. const updatedList = list.concat(target);
  27. return isBody
  28. ? updatedList
  29. : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
  30. updatedList.concat(listScrollParents(getParentNode(target)));
  31. }