UNPKG

react-native-gesture-image-viewer

Version:

🖼️ React Native Image Viewer - Reanimated-powered image gestures with full control

186 lines (185 loc) 5.69 kB
"use strict"; import { useCallback, useEffect, useMemo, useRef } from 'react'; import { Platform, StyleSheet, useWindowDimensions, View } from 'react-native'; import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'; import Animated from 'react-native-reanimated'; import { registry } from "./GestureViewerRegistry.js"; import { useGestureViewer } from "./useGestureViewer.js"; import { createLoopData, isFlashListLike, isFlatListLike, isScrollViewLike } from "./utils.js"; import WebPagingFixStyle from "./WebPagingFixStyle.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export function GestureViewer({ id = 'default', data, renderItem: renderItemProp, renderContainer, ListComponent, width: customWidth, height: customHeight, listProps, backdropStyle: backdropStyleProps, containerStyle, initialIndex = 0, itemSpacing = 0, useSnap = false, enableLoop = false, ...props }) { const Component = ListComponent; const dataRef = useRef(data); const { width: screenWidth, height: screenHeight } = useWindowDimensions(); const width = customWidth || screenWidth; const height = customHeight || screenHeight; const loopData = useMemo(() => createLoopData(dataRef, enableLoop), [enableLoop]); const isScrollView = isScrollViewLike(Component); const { listRef, isZoomed, isRotated, dismissGesture, zoomGesture, onMomentumScrollEnd, onScrollBeginDrag, handleDismiss, animatedStyle, backdropStyle } = useGestureViewer({ id, data, width, height, initialIndex, itemSpacing, enableLoop, ...props }); const keyExtractor = useCallback((item, index) => { if (enableLoop) { return typeof item === 'string' ? `${item}-${index}` : `item-${index}`; } return typeof item === 'string' ? item : `image-${index}`; }, [enableLoop]); const renderItem = useCallback(({ item, index }) => { return /*#__PURE__*/_jsx(View, { style: [{ width, height, marginHorizontal: itemSpacing / 2 }, styles.item], children: renderItemProp(item, index) }, isScrollView ? keyExtractor(item, index) : undefined); }, [width, itemSpacing, renderItemProp, keyExtractor, isScrollView, height]); const getItemLayout = useCallback((_, index) => ({ length: width + itemSpacing, offset: (width + itemSpacing) * index, index }), [width, itemSpacing]); const gesture = useMemo(() => { return Gesture.Race(dismissGesture, zoomGesture); }, [zoomGesture, dismissGesture]); useEffect(() => { dataRef.current = data; }, [data]); useEffect(() => { registry.createManager(id); return () => registry.deleteManager(id); }, [id]); const commonProps = useMemo(() => ({ horizontal: true, scrollEnabled: !isZoomed && !isRotated, showsHorizontalScrollIndicator: false, onMomentumScrollEnd: onMomentumScrollEnd, onScrollBeginDrag, ...(useSnap ? { snapToInterval: width + itemSpacing, snapToAlignment: 'center', decelerationRate: 'fast' } : { pagingEnabled: true }), scrollEventThrottle: 16, removeClippedSubviews: true }), [width, itemSpacing, isZoomed, isRotated, onMomentumScrollEnd, onScrollBeginDrag, useSnap]); const control = useMemo(() => ({ dismiss: handleDismiss }), [handleDismiss]); const listComponent = /*#__PURE__*/_jsx(GestureHandlerRootView, { children: /*#__PURE__*/_jsx(GestureDetector, { gesture: gesture, children: /*#__PURE__*/_jsxs(View, { style: [{ height, width }, containerStyle], children: [/*#__PURE__*/_jsx(Animated.View, { style: [styles.background, backdropStyleProps, backdropStyle] }), /*#__PURE__*/_jsx(Animated.View, { style: [styles.content, animatedStyle], ...(Platform.OS === 'web' && isFlashListLike(Component) && { dataSet: { 'flash-list-paging-enabled-fix': true } }), children: isScrollView ? /*#__PURE__*/_jsx(Component, { ref: listRef, ...commonProps, ...listProps, children: loopData.map((item, index) => renderItem({ item, index })) }) : isFlatListLike(Component) && /*#__PURE__*/_jsx(Component, { ref: listRef, ...commonProps, data: loopData, renderItem: renderItem, initialScrollIndex: enableLoop && data.length > 1 ? initialIndex + 1 : initialIndex, keyExtractor: keyExtractor, getItemLayout: getItemLayout, ...(isFlashListLike(Component) ? { estimatedItemSize: width + itemSpacing } : { windowSize: 3, maxToRenderPerBatch: 3 }), ...(Platform.OS === 'web' && isFlatListLike(Component) && { dataSet: { 'flat-list-paging-enabled-fix': true } }), ...listProps }) }), /*#__PURE__*/_jsx(WebPagingFixStyle, { Component: Component })] }) }) }); return renderContainer ? renderContainer(listComponent, control) : listComponent; } const styles = StyleSheet.create({ item: { justifyContent: 'center', alignItems: 'center' }, content: { flex: 1, width: '100%', height: '100%' }, background: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'black' } }); //# sourceMappingURL=GestureViewer.js.map