pay-sdk-react
Version:
A cross-platform payment SDK for React, supporting Alipay, WeChat Pay, PayPal, Stripe, Payssion, and Airwallex, compatible with H5, PC, and App environments.
82 lines (81 loc) • 2.49 kB
JavaScript
import { useEffect } from "react";
import { getScrollParent } from "../utils/get-scroll-parent";
import { supportsPassive } from "../utils/supports-passive";
import { useTouch } from "./use-touch";
let totalLockCount = 0;
const BODY_LOCK_CLASS = "yfm-overflow-hidden";
function getScrollableElement(el) {
let current = el === null || el === void 0 ? void 0 : el.parentElement;
while (current) {
if (current.clientHeight < current.scrollHeight) {
return current;
}
current = current.parentElement;
}
return null;
}
export function useLockScroll(rootRef, shouldLock) {
const touch = useTouch();
const onTouchMove = event => {
touch.move(event);
const direction = touch.deltaY.current > 0 ? "10" : "01";
const el = getScrollParent(event.target, rootRef.current);
if (!el) return;
// This has perf cost but we have to compatible with iOS 12
if (shouldLock === "strict") {
const scrollableParent = getScrollableElement(event.target);
if (scrollableParent === document.body || scrollableParent === document.documentElement) {
event.preventDefault();
return;
}
}
const {
scrollHeight,
offsetHeight,
scrollTop
} = el;
const {
height
} = el.getBoundingClientRect();
let status = "11";
if (scrollTop === 0) {
status = offsetHeight >= scrollHeight ? "00" : "01";
} else if (scrollHeight <= Math.round(height + scrollTop)) {
status = "10";
}
if (status !== "11" && touch.isVertical() && !(parseInt(status, 2) & parseInt(direction, 2))) {
if (event.cancelable && supportsPassive) {
event.preventDefault();
}
}
};
const lock = () => {
document.addEventListener("touchstart", touch.start);
document.addEventListener("touchmove", onTouchMove, supportsPassive ? {
passive: false
} : false);
if (!totalLockCount) {
document.body.classList.add(BODY_LOCK_CLASS);
}
totalLockCount++;
};
const unlock = () => {
if (totalLockCount) {
document.removeEventListener("touchstart", touch.start);
document.removeEventListener("touchmove", onTouchMove);
totalLockCount--;
if (!totalLockCount) {
document.body.classList.remove(BODY_LOCK_CLASS);
}
}
};
useEffect(() => {
if (shouldLock) {
lock();
return () => {
unlock();
};
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldLock]);
}