react-native-scrollable-page-view
Version:
A ViewPager react-native and react-native-web.
126 lines • 4.8 kB
JavaScript
import { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from "react";
import { Platform, ScrollView, View } from "react-native";
export var PageView = forwardRef(function PageView(_a, ref) {
var _b = _a.delay, delay = _b === void 0 ? 100 : _b, onChangePage = _a.onChangePage, currentPage = _a.currentPage, scrollEnabled = _a.scrollEnabled, style = _a.style, children = _a.children;
var _c = useState(false), ready = _c[0], setReady = _c[1];
var _d = useState(0), width = _d[0], setWidth = _d[1];
var _e = useState(0), height = _e[0], setHeight = _e[1];
var contentOffsetX = useRef(0);
var paning = useRef(false);
var onScrollTimer = useRef();
var scrollViewRef = useRef(null);
useImperativeHandle(ref, function () {
return {
next: function () { },
};
}, []);
var onLayout = useCallback(function (event) {
var layout = event.nativeEvent.layout;
setWidth(layout.width);
setHeight(layout.height);
setReady(true);
}, []);
var isTouchable = useMemo(function () {
if (Platform.OS === "web") {
if (window.navigator.maxTouchPoints === 0) {
return false;
}
}
return true;
}, []);
var childCount = useMemo(function () {
return Children.count(children);
}, [children]);
var animate = useCallback(function () {
var _a;
if (paning.current) {
onScrollTimer.current = setTimeout(animate, 16);
return;
}
var x = contentOffsetX.current;
var halfWidth = width / 2;
var index = 0;
var left = 0;
while (true) {
if (index === childCount) {
break;
}
if (Math.abs(x - left) < halfWidth) {
break;
}
index++;
left += width;
}
(_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({ x: left, animated: true });
if (onChangePage) {
onChangePage(index);
}
}, [width, childCount, onChangePage]);
var onScroll = useCallback(function (event) {
contentOffsetX.current = event.nativeEvent.contentOffset.x;
if (onScrollTimer.current) {
clearTimeout(onScrollTimer.current);
}
onScrollTimer.current = setTimeout(function () {
animate();
}, delay);
}, [isTouchable, animate]);
var childs = useMemo(function () {
if (!ready) {
return <></>;
}
return (<>
{Children.map(children, function (child, index) {
return (<View key={index} style={{
position: "absolute",
top: 0,
left: index * width,
width: width,
height: height,
}}>
{child}
</View>);
})}
</>);
}, [children, width, height, ready]);
useEffect(function () {
if (ready &&
typeof currentPage === "number" &&
currentPage > -1 &&
currentPage < childCount) {
contentOffsetX.current = width * currentPage;
animate();
}
}, [ready, currentPage, childCount, width]);
useEffect(function () {
var _a, _b;
var onMouseDown = function () {
paning.current = true;
};
var onMouseUp = function () {
paning.current = false;
};
if (!isTouchable) {
var addEventListener_1 = (_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener;
var removeEventListener_1 = (_b = scrollViewRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener;
if (addEventListener_1 && removeEventListener_1) {
addEventListener_1("mouseup", onMouseUp);
addEventListener_1("mousedown", onMouseDown);
return function () {
removeEventListener_1("mouseup", onMouseUp);
removeEventListener_1("mousedown", onMouseDown);
};
}
}
}, []);
return (<ScrollView scrollEventThrottle={16} onResponderGrant={function () {
paning.current = true;
}} onResponderMove={function () {
paning.current = true;
}} onResponderRelease={function () {
paning.current = false;
}} onScroll={onScroll} ref={scrollViewRef} scrollEnabled={scrollEnabled} horizontal style={style} onLayout={onLayout}>
{ready ? childs : null}
</ScrollView>);
});
//# sourceMappingURL=PageView.js.map