UNPKG

react-native-scrollable-page-view

Version:
126 lines 4.8 kB
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