react-elegant-ui
Version:
Elegant UI components, made by BEM best practices for react
69 lines • 2.01 kB
JavaScript
import { getScrollParent, isPassiveEventsSupported, isRootHTMLElement } from './utils';
var LISTENER_OPTIONS = isPassiveEventsSupported() ? {
passive: false
} : undefined;
// TODO: use own state for each root node to support other window context
var state = {
count: 0,
lastY: 0,
scrollable: null,
scrollX: 0,
scrollY: 0
};
function onTouchStart(event) {
if (event.changedTouches.length === 1) {
state.scrollable = getScrollParent(event.target);
if (isRootHTMLElement(state.scrollable)) {
return;
}
state.lastY = event.changedTouches[0].pageY;
}
}
function onTouchMove(event) {
var scrollable = state.scrollable,
lastY = state.lastY;
if (event.changedTouches.length > 1) {
return;
}
if (!scrollable || isRootHTMLElement(scrollable)) {
event.preventDefault();
return;
}
var y = event.changedTouches[0].pageY;
var top = scrollable.scrollTop;
var bottom = scrollable.scrollHeight - scrollable.clientHeight;
if (top <= 0 && y > lastY || top >= bottom && y < lastY) {
event.preventDefault();
}
state.lastY = y;
}
function onTouchEnd() {
if (state.scrollable) {
state.scrollable = null;
}
}
export function lock(container) {
if (!isRootHTMLElement(container)) {
return;
}
state.count++;
if (state.count === 1) {
state.scrollX = window.pageXOffset;
state.scrollY = window.pageYOffset;
document.addEventListener('touchstart', onTouchStart, LISTENER_OPTIONS);
document.addEventListener('touchmove', onTouchMove, LISTENER_OPTIONS);
document.addEventListener('touchend', onTouchEnd, LISTENER_OPTIONS);
}
}
export function unlock(container) {
if (!isRootHTMLElement(container) || state.count === 0) {
return;
}
state.count--;
if (state.count === 0) {
document.removeEventListener('touchstart', onTouchStart);
document.removeEventListener('touchmove', onTouchMove);
document.removeEventListener('touchend', onTouchEnd);
window.scrollTo(state.scrollX, state.scrollY);
}
}