Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@janicduplessis
Created April 19, 2020 19:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janicduplessis/08bd7332be0b332cee2bfe87dab8f40b to your computer and use it in GitHub Desktop.
Save janicduplessis/08bd7332be0b332cee2bfe87dab8f40b to your computer and use it in GitHub Desktop.
import * as React from 'react';
import PropTypes from 'prop-types';
type Props = {
disabled?: boolean;
children: React.ReactNode;
};
export class WindowScrollContext extends React.Component<Props> {
// https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/vendor/react-native/VirtualizedList/index.js#L470
static childContextTypes = {
virtualizedList: PropTypes.shape({
getScrollMetrics: PropTypes.func,
horizontal: PropTypes.bool,
getOutermostParentListRef: PropTypes.func,
getNestedChildState: PropTypes.func,
registerAsNestedChild: PropTypes.func,
unregisterAsNestedChild: PropTypes.func,
}),
};
_nestedChildLists = new Map<string, { ref: any; state: any }>();
getChildContext(): any {
if (this.props.disabled) {
return { virtualizedList: null };
}
return {
virtualizedList: {
getScrollMetrics: this._getScrollMetrics,
horizontal: false,
getOutermostParentListRef: this._getOutermostParentListRef,
getNestedChildState: this._getNestedChildState,
registerAsNestedChild: this._registerAsNestedChild,
unregisterAsNestedChild: this._unregisterAsNestedChild,
},
};
}
componentDidMount() {
window.addEventListener('scroll', this._onScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this._onScroll);
}
_onScroll = () => {
const { documentElement } = document;
const normalizedEvent = {
nativeEvent: {
contentOffset: {
x: 0,
y: window.pageYOffset,
},
contentSize: {
height: documentElement.scrollHeight,
width: documentElement.scrollWidth,
},
layoutMeasurement: {
height: documentElement.clientHeight,
width: documentElement.clientWidth,
},
},
timeStamp: Date.now(),
};
this._nestedChildLists.forEach((childList) => {
childList.ref && childList.ref._onScroll(normalizedEvent);
});
};
_getScrollMetrics = () => {
const { documentElement } = document;
return {
visibleLength: documentElement.clientHeight,
contentLength: documentElement.scrollHeight,
dOffset: 0,
dt: 10,
offset: window.pageYOffset,
timestamp: Date.now(),
velocity: 0,
};
};
_getOutermostParentListRef = () => {
return {
getScrollRef: () => ({
getNativeScrollRef: () => document.documentElement,
}),
};
};
_getNestedChildState = (key: string): any => {
const existingChildData = this._nestedChildLists.get(key);
return existingChildData && existingChildData.state;
};
_registerAsNestedChild = (childList: any) => {
this._nestedChildLists.set(childList.key, {
ref: childList.ref,
state: null,
});
if (childList.ref != null) {
childList.ref.measureLayoutRelativeToContainingList();
}
};
_unregisterAsNestedChild = (childList: { key: string; state: any }): void => {
this._nestedChildLists.set(childList.key, {
ref: null,
state: childList.state,
});
};
render() {
return this.props.children;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment