react-native-gesture-image-viewer
Version:
🖼️ A highly customizable and easy-to-use React Native image viewer with gesture support and external controls
104 lines (84 loc) • 2.93 kB
text/typescript
import { FlatList as RNFlatList, ScrollView as RNScrollView } from 'react-native';
import { FlatList as GestureFlatList, ScrollView as GestureScrollView } from 'react-native-gesture-handler';
import type { FlatListComponent, ScrollViewComponent } from './types';
export const isScrollViewLike = (component: any): component is ScrollViewComponent => {
return component === RNScrollView || component === GestureScrollView;
};
export const isFlatListLike = (component: any): component is FlatListComponent => {
if (component === RNFlatList || component === GestureFlatList || isFlashListLike(component)) {
return true;
}
return false;
};
export const isFlashListLike = (component: any): component is any => {
try {
const FlashList = require('@shopify/flash-list')?.FlashList;
if (FlashList && component === FlashList) {
return true;
}
} catch {
// do nothing
}
return component?.name === 'FlashList';
};
export const createBoundsConstraint =
({ width, height }: { width: number; height: number }) =>
({ scale, translateX, translateY }: { translateX: number; translateY: number; scale: number }) => {
'worklet';
if (scale <= 1) {
return {
translateX,
translateY,
};
}
const maxTranslateX = (width * scale - width) / 2;
const maxTranslateY = (height * scale - height) / 2;
return {
translateX: Math.max(-maxTranslateX, Math.min(maxTranslateX, translateX)),
translateY: Math.max(-maxTranslateY, Math.min(maxTranslateY, translateY)),
};
};
export const createLoopData = <T>(dataRef: React.RefObject<T[]>, enableLoop: boolean): T[] => {
const data = dataRef.current;
if (!enableLoop || !data?.length || data.length <= 1) {
return data;
}
const lastItem = data[data.length - 1];
const firstItem = data[0];
if (lastItem === undefined || firstItem === undefined) {
return data;
}
return [lastItem, ...data, firstItem];
};
export const getLoopAdjustedIndex = (
scrollIndex: number,
originalDataLength: number,
enableLoop: boolean,
): { realIndex: number; needsJump: boolean; jumpToIndex?: number } => {
if (!enableLoop || originalDataLength <= 1) {
return { realIndex: scrollIndex, needsJump: false };
}
if (scrollIndex === 0) {
return {
realIndex: originalDataLength - 1,
needsJump: true,
jumpToIndex: originalDataLength,
};
} else if (scrollIndex === originalDataLength + 1) {
return {
realIndex: 0,
needsJump: true,
jumpToIndex: 1,
};
}
return { realIndex: scrollIndex - 1, needsJump: false };
};
export const createScrollAction = (listRef: any, width: number) => ({
scrollTo: (index: number, animated: boolean) => {
if (listRef?.scrollToIndex) {
listRef.scrollToIndex({ index, animated });
} else if (listRef?.scrollTo) {
listRef.scrollTo({ x: index * width, animated });
}
},
});