Skip to content

Commit 50a1b30

Browse files
authored
Merge 60a5d93 into 7c2039d
2 parents 7c2039d + 60a5d93 commit 50a1b30

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

packages/reakit/src/Composite/__utils/useSortBasedOnDOMPosition.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
11
import * as React from "react";
2+
import { getDocument } from "reakit-utils/getDocument";
23
import { sortBasedOnDOMPosition } from "./sortBasedOnDOMPosition";
34
import { Item } from "./types";
45

56
type 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
1630
function 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

4255
function 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

Comments
 (0)