diff --git a/README.md b/README.md
index 249e5dd..bb50b1f 100644
--- a/README.md
+++ b/README.md
@@ -71,11 +71,12 @@ const App = () => (
## Props
-| Prop name | Type | Description | Default |
-| ---------------- | -------- | ------------------------------------------------------------------------------------------ | --------- |
-| **children** | function | Render props function called with 4 props: `ref`, `outerRef`, `style` and `onScroll` | undefined |
-| **throttleTime** | number | Timing (ms) for the throttle on window scroll event handler | 10 |
-| **isGrid** | boolean | Set to true if rendering a react-window Grid component (FixedSizeGrid or VariableSizeGrid) | false |
+| Prop name | Type | Description | Default |
+| -------------------- | ---------- | ------------------------------------------------------------------------------------------ | --------- |
+| **children** | function | Render props function called with 4 props: `ref`, `outerRef`, `style` and `onScroll` | undefined |
+| **throttleTime** | number | Timing (ms) for the throttle on window scroll event handler | 10 |
+| **isGrid** | boolean | Set to true if rendering a react-window Grid component (FixedSizeGrid or VariableSizeGrid) | false |
+| **scrollElementRef** | ElementRef | The element in your project that is scrolling, if not window | window |
## License
diff --git a/example/src/App.jsx b/example/src/App.jsx
index 3dd1111..b5352a3 100644
--- a/example/src/App.jsx
+++ b/example/src/App.jsx
@@ -1,27 +1,65 @@
-import React, { useState } from 'react'
+import React, { useMemo, useState, useEffect, useCallback } from 'react'
import FixedSizeList from './FixedSizeList'
import VariableSizeList from './VariableSizeList'
import FixedSizeGrid from './FixedSizeGrid'
import VariableSizeGrid from './VariableSizeGrid'
+const types = ['window', 'element'];
const lists = ['Fixed List', 'Variable List', 'Fixed Grid', 'Variable Grid']
const App = () => {
- const [selected, setSelected] = useState(lists[0])
+ const [selectedType, setSelectedType] = useState(types[0]);
+ const [selectedList, setSelectedList] = useState(lists[0]);
+ // Normally we would use `useRef`, but since we are flipping back and forth we need to trigger a render.
+ const [scrollElementRef, setScrollElementRef] = useState();
+
+ useEffect(() => {
+ if (selectedType === 'window') {
+ document.body.style.overflow = 'inherit';
+ } else {
+ document.body.style.overflow = 'hidden';
+ }
+ }, [selectedType])
+
+ const currentScrollRef = useMemo(() => selectedType === 'element' ? scrollElementRef || undefined : undefined, [selectedType, scrollElementRef]);
+ const getListSelected = useCallback(() => (
+ <>
+ {selectedList === 'Fixed List' && }
+ {selectedList === 'Variable List' && }
+ {selectedList === 'Fixed Grid' && }
+ {selectedList === 'Variable Grid' && }
+ >
+ ), [selectedList, currentScrollRef]);
+
return (
<>
+
-
- {selected === 'Fixed List' && }
- {selected === 'Variable List' && }
- {selected === 'Fixed Grid' && }
- {selected === 'Variable Grid' && }
+ {selectedType === 'element' && (
+
+
Top Bar
+
+
Left Bar
+
+
Content Tabs
+
{getListSelected()}
+
+
+
+ )}
+ {selectedType === 'window' && getListSelected()}
>
)
}
diff --git a/example/src/FixedSizeGrid.jsx b/example/src/FixedSizeGrid.jsx
index 55d6dc1..a88643a 100644
--- a/example/src/FixedSizeGrid.jsx
+++ b/example/src/FixedSizeGrid.jsx
@@ -3,8 +3,8 @@ import { FixedSizeGrid as Grid } from 'react-window'
import { ReactWindowScroller } from 'react-window-scroller'
import { Cell } from './Cell'
-const FixedSizeGrid = () => (
-
+const FixedSizeGrid = ({ scrollElementRef }) => (
+
{({ ref, outerRef, style, onScroll }) => (
(
-
+const FixedSizeList = ({ scrollElementRef }) => (
+
{({ ref, outerRef, style, onScroll }) => (
25 + Math.round(Math.random() * 50)
)
-const VariableSizeGrid = () => (
-
+const VariableSizeGrid = ({ scrollElementRef }) => (
+
{({ ref, outerRef, style, onScroll }) => (
rowSizes[index]
-const VariableSizeList = () => (
-
+const VariableSizeList = ({ scrollElementRef }) => (
+
{({ ref, outerRef, style, onScroll }) => (
+const elementScrollPositionKey = documentScrollPositionKey
+
+const getScrollPositionWindow = (axis) =>
window[windowScrollPositionKey[axis]] ||
document.documentElement[documentScrollPositionKey[axis]] ||
document.body[documentScrollPositionKey[axis]] ||
0
+const getScrollPositionElement = (ref, axis) =>
+ ref[elementScrollPositionKey[axis]]
+
+const getScrollPosition = (ref, axis) => {
+ if (ref === window) {
+ return getScrollPositionWindow(axis)
+ }
+ return getScrollPositionElement(ref, axis)
+}
+
export const ReactWindowScroller = ({
children,
throttleTime = 10,
- isGrid = false
+ isGrid = false,
+ scrollElementRef = window
}) => {
const ref = useRef()
const outerRef = useRef()
@@ -28,36 +41,43 @@ export const ReactWindowScroller = ({
useEffect(() => {
const handleWindowScroll = throttle(() => {
const { offsetTop = 0, offsetLeft = 0 } = outerRef.current || {}
- const scrollTop = getScrollPosition('y') - offsetTop
- const scrollLeft = getScrollPosition('x') - offsetLeft
+
+ const scrollTop = getScrollPosition(scrollElementRef, 'y') - offsetTop
+ const scrollLeft = getScrollPosition(scrollElementRef, 'x') - offsetLeft
if (isGrid) ref.current && ref.current.scrollTo({ scrollLeft, scrollTop })
if (!isGrid) ref.current && ref.current.scrollTo(scrollTop)
}, throttleTime)
- window.addEventListener('scroll', handleWindowScroll)
+ scrollElementRef.addEventListener('scroll', handleWindowScroll)
return () => {
handleWindowScroll.cancel()
- window.removeEventListener('scroll', handleWindowScroll)
+ scrollElementRef.removeEventListener('scroll', handleWindowScroll)
}
- }, [isGrid])
+ }, [isGrid, scrollElementRef, throttleTime])
const onScroll = useCallback(
- ({ scrollLeft, scrollTop, scrollOffset, scrollUpdateWasRequested }) => {
+ ({
+ scrollLeft = 0, // This is not provided by react-window
+ scrollTop = 0, // This is not provided by react-window
+ scrollOffset,
+ scrollUpdateWasRequested
+ }) => {
if (!scrollUpdateWasRequested) return
- const top = getScrollPosition('y')
- const left = getScrollPosition('x')
+ const top = getScrollPosition(scrollElementRef, 'y')
+ const left = getScrollPosition(scrollElementRef, 'x')
const { offsetTop = 0, offsetLeft = 0 } = outerRef.current || {}
scrollOffset += Math.min(top, offsetTop)
scrollTop += Math.min(top, offsetTop)
scrollLeft += Math.min(left, offsetLeft)
- if (!isGrid && scrollOffset !== top) window.scrollTo(0, scrollOffset)
+ if (!isGrid && scrollOffset !== top)
+ scrollElementRef.scrollTo(0, scrollOffset)
if (isGrid && (scrollTop !== top || scrollLeft !== left)) {
- window.scrollTo(scrollLeft, scrollTop)
+ scrollElementRef.scrollTo(scrollLeft, scrollTop)
}
},
- [isGrid]
+ [isGrid, scrollElementRef]
)
return children({