11import * as React from "react" ;
2+ import { getDocument } from "reakit-utils/getDocument" ;
23import { sortBasedOnDOMPosition } from "./sortBasedOnDOMPosition" ;
34import { Item } from "./types" ;
45
56type SetItems = ( items : Item [ ] ) => void ;
67
7- function setItemsBasedOnDOMPosition ( items : Item [ ] , setItems : SetItems ) {
8+ function mutateItemsBasedOnDOMPosition ( items : Item [ ] , setItems : SetItems ) {
89 const sortedItems = sortBasedOnDOMPosition ( items ) ;
910 if ( items !== sortedItems ) {
1011 setItems ( sortedItems ) ;
1112 }
1213}
1314
15+ function getCommonParent ( items : Item [ ] ) {
16+ const [ firstItem , ...nextItems ] = items ;
17+ let parentElement = firstItem ?. ref . current ?. parentElement ;
18+ while ( parentElement ) {
19+ const parent = parentElement ;
20+ if ( nextItems . every ( ( item ) => parent . contains ( item . ref . current ) ) ) {
21+ return parentElement ;
22+ }
23+ parentElement = parentElement . parentElement ;
24+ }
25+ return getDocument ( parentElement ) . body ;
26+ }
27+
1428// istanbul ignore next: JSDOM doesn't support IntersectionObverser
1529// See https://github.com/jsdom/jsdom/issues/2032
1630function useIntersectionObserver ( items : Item [ ] , setItems : SetItems ) {
@@ -21,13 +35,12 @@ function useIntersectionObserver(items: Item[], setItems: SetItems) {
2135 const hasPreviousItems = ! ! previousItems . current . length ;
2236 // We don't want to sort items if items have been just registered.
2337 if ( hasPreviousItems ) {
24- setItemsBasedOnDOMPosition ( items , setItems ) ;
38+ mutateItemsBasedOnDOMPosition ( items , setItems ) ;
2539 }
2640 previousItems . current = items ;
2741 } ;
28- const observer = new IntersectionObserver ( callback , {
29- root : document . body ,
30- } ) ;
42+ const root = getCommonParent ( items ) ;
43+ const observer = new IntersectionObserver ( callback , { root } ) ;
3144 for ( const item of items ) {
3245 if ( item . ref . current ) {
3346 observer . observe ( item . ref . current ) ;
@@ -41,7 +54,7 @@ function useIntersectionObserver(items: Item[], setItems: SetItems) {
4154
4255function useTimeoutObserver ( items : Item [ ] , setItems : SetItems ) {
4356 React . useEffect ( ( ) => {
44- const callback = ( ) => setItemsBasedOnDOMPosition ( items , setItems ) ;
57+ const callback = ( ) => mutateItemsBasedOnDOMPosition ( items , setItems ) ;
4558 const timeout = setTimeout ( callback , 250 ) ;
4659 return ( ) => clearTimeout ( timeout ) ;
4760 } ) ;
0 commit comments