react-native-gesture-image-viewer 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/lib/module/GestureViewer.js +21 -9
- package/lib/module/GestureViewer.js.map +1 -1
- package/lib/module/GestureViewerManager.js +51 -20
- package/lib/module/GestureViewerManager.js.map +1 -1
- package/lib/module/useGestureViewer.js +34 -20
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/module/utils.js +52 -0
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/src/GestureViewer.d.ts +1 -1
- package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerManager.d.ts +6 -0
- package/lib/typescript/src/GestureViewerManager.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +5 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts +2 -1
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/utils.d.ts +9 -0
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/GestureViewer.tsx +47 -31
- package/src/GestureViewerManager.ts +61 -15
- package/src/types.ts +5 -0
- package/src/useGestureViewer.ts +41 -18
- package/src/utils.ts +53 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureViewer.d.ts","sourceRoot":"","sources":["../../../src/GestureViewer.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAyE,MAAM,cAAc,CAAC;AAIpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,QAAQ,EAAE,EAC3D,EAAc,EACd,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,eAAe,EACf,aAAa,EACb,KAAK,EAAE,WAAW,EAClB,SAAS,EACT,aAAa,EAAE,kBAAkB,EACjC,cAAc,EACd,YAAgB,EAChB,WAAe,EACf,OAAe,EACf,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"GestureViewer.d.ts","sourceRoot":"","sources":["../../../src/GestureViewer.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAyE,MAAM,cAAc,CAAC;AAIpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,QAAQ,EAAE,EAC3D,EAAc,EACd,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,eAAe,EACf,aAAa,EACb,KAAK,EAAE,WAAW,EAClB,SAAS,EACT,aAAa,EAAE,kBAAkB,EACjC,cAAc,EACd,YAAgB,EAChB,WAAe,EACf,OAAe,EACf,UAAkB,EAClB,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,2CAsJ3B"}
|
|
@@ -11,9 +11,12 @@ declare class GestureViewerManager {
|
|
|
11
11
|
private maxZoomScale;
|
|
12
12
|
private listRef;
|
|
13
13
|
private enableSwipeGesture;
|
|
14
|
+
private enableLoop;
|
|
14
15
|
private listeners;
|
|
15
16
|
private rotation;
|
|
16
17
|
private eventListeners;
|
|
18
|
+
private animationTimeout;
|
|
19
|
+
private static readonly LOOP_ANIMATION_DURATION;
|
|
17
20
|
private notifyListeners;
|
|
18
21
|
subscribe(listener: (state: GestureViewerControllerState) => void): () => void;
|
|
19
22
|
addEventListener<T extends GestureViewerEventType>(eventType: T, callback: GestureViewerEventCallback<T>): () => void;
|
|
@@ -24,6 +27,7 @@ declare class GestureViewerManager {
|
|
|
24
27
|
currentIndex: number;
|
|
25
28
|
totalCount: number;
|
|
26
29
|
};
|
|
30
|
+
setEnableLoop(enabled: boolean): void;
|
|
27
31
|
setWidth(width: number): void;
|
|
28
32
|
setHeight(height: number): void;
|
|
29
33
|
setListRef(ref: any): void;
|
|
@@ -38,9 +42,11 @@ declare class GestureViewerManager {
|
|
|
38
42
|
zoomOut: (multiplier?: number) => void;
|
|
39
43
|
resetZoom: (scale?: number) => void;
|
|
40
44
|
goToIndex: (index: number) => void;
|
|
45
|
+
cancelAnimation: () => void;
|
|
41
46
|
goToPrevious: () => void;
|
|
42
47
|
goToNext: () => void;
|
|
43
48
|
cleanUp(): void;
|
|
49
|
+
private updateCurrentIndex;
|
|
44
50
|
}
|
|
45
51
|
export default GestureViewerManager;
|
|
46
52
|
//# sourceMappingURL=GestureViewerManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureViewerManager.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EACV,4BAA4B,EAC5B,0BAA0B,EAE1B,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAGjB,cAAM,oBAAoB;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,SAAS,CAA4D;IAC7E,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,cAAc,CAA+D;
|
|
1
|
+
{"version":3,"file":"GestureViewerManager.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EACV,4BAA4B,EAC5B,0BAA0B,EAE1B,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAGjB,cAAM,oBAAoB;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAA4D;IAC7E,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,cAAc,CAA+D;IACrF,OAAO,CAAC,gBAAgB,CAA+B;IAEvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAO;IAEtD,OAAO,CAAC,eAAe;IAMvB,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,4BAA4B,KAAK,IAAI;IAQjE,gBAAgB,CAAC,CAAC,SAAS,sBAAsB,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAoBxG,OAAO,CAAC,SAAS;IAQjB,cAAc,GAAI,OAAO,MAAM,EAAE,eAAe,MAAM,GAAG,IAAI,UAE3D;IAEF,kBAAkB,GAAI,UAAU,MAAM,EAAE,kBAAkB,MAAM,GAAG,IAAI,UAErE;IAEF,QAAQ;;;;IAOR,aAAa,CAAC,OAAO,EAAE,OAAO;IAI9B,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,UAAU,CAAC,GAAG,EAAE,GAAG;IAInB,aAAa,CAAC,MAAM,EAAE,MAAM;IAI5B,qBAAqB,CAAC,OAAO,EAAE,OAAO;IAItC,eAAe,CAAC,KAAK,EAAE,MAAM;IAM7B,mBAAmB,CACjB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAC1B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,YAAY,EAAE,MAAM;IAQtB,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;IAIzC,MAAM,GAAI,QAAO,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAQ,EAAE,mBAAgB,UA2B9D;IAEF,MAAM,GAAI,mBAAiB,UAoBzB;IAEF,OAAO,GAAI,mBAAiB,UA0B1B;IAEF,SAAS,GAAI,cAAS,UAQpB;IAEF,SAAS,GAAI,OAAO,MAAM,UA4CxB;IAEF,eAAe,aAKb;IAEF,YAAY,aAEV;IAEF,QAAQ,aAEN;IAEF,OAAO;IAeP,OAAO,CAAC,kBAAkB,CAGxB;CACH;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -120,6 +120,11 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
|
|
|
120
120
|
* @defaultValue true
|
|
121
121
|
*/
|
|
122
122
|
enableDoubleTapGesture?: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Enables infinite loop navigation.
|
|
125
|
+
* @defaultValue false
|
|
126
|
+
*/
|
|
127
|
+
enableLoop?: boolean;
|
|
123
128
|
/**
|
|
124
129
|
* The maximum zoom scale.
|
|
125
130
|
* @defaultValue 2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type NativeScrollEvent, type NativeSyntheticEvent } from 'react-native';
|
|
2
2
|
import type { GestureViewerProps } from './types';
|
|
3
3
|
type UseGestureViewerProps<T = any> = Omit<GestureViewerProps<T>, 'renderItem' | 'renderContainer' | 'ListComponent' | 'listProps' | 'containerStyle' | 'backdropStyle'>;
|
|
4
|
-
export declare const useGestureViewer: <T = any>({ data, initialIndex, onIndexChange, onDismiss, width: customWidth, dismissThreshold, resistance, animateBackdrop, enableDismissGesture, enableSwipeGesture, enableZoomGesture, enableDoubleTapGesture, enableZoomPanGesture, maxZoomScale, itemSpacing, useSnap, id, }: UseGestureViewerProps<T>) => {
|
|
4
|
+
export declare const useGestureViewer: <T = any>({ data, initialIndex, onIndexChange, onDismiss, width: customWidth, dismissThreshold, resistance, animateBackdrop, enableDismissGesture, enableSwipeGesture, enableZoomGesture, enableDoubleTapGesture, enableZoomPanGesture, enableLoop, maxZoomScale, itemSpacing, useSnap, id, }: UseGestureViewerProps<T>) => {
|
|
5
5
|
currentIndex: number;
|
|
6
6
|
dataLength: number;
|
|
7
7
|
translateY: import("react-native-reanimated").SharedValue<number>;
|
|
@@ -11,6 +11,7 @@ export declare const useGestureViewer: <T = any>({ data, initialIndex, onIndexCh
|
|
|
11
11
|
dismissGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture").PanGesture;
|
|
12
12
|
zoomGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/gestureComposition").ComposedGesture;
|
|
13
13
|
onMomentumScrollEnd: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
14
|
+
onScrollBeginDrag: () => void;
|
|
14
15
|
animatedStyle: {
|
|
15
16
|
transform: ({
|
|
16
17
|
translateY: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGlD,KAAK,qBAAqB,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CACxC,kBAAkB,CAAC,CAAC,CAAC,EACrB,YAAY,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,CACtG,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGlD,KAAK,qBAAqB,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CACxC,kBAAkB,CAAC,CAAC,CAAC,EACrB,YAAY,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,CACtG,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,GAAG,EAAE,qRAqBvC,qBAAqB,CAAC,CAAC,CAAC;;;;;;;;;iCA6Kf,oBAAoB,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyRlD,CAAC"}
|
|
@@ -13,4 +13,13 @@ export declare const createBoundsConstraint: ({ width, height }: {
|
|
|
13
13
|
translateX: number;
|
|
14
14
|
translateY: number;
|
|
15
15
|
};
|
|
16
|
+
export declare const createLoopData: <T>(dataRef: React.RefObject<T[]>, enableLoop: boolean) => T[];
|
|
17
|
+
export declare const getLoopAdjustedIndex: (scrollIndex: number, originalDataLength: number, enableLoop: boolean) => {
|
|
18
|
+
realIndex: number;
|
|
19
|
+
needsJump: boolean;
|
|
20
|
+
jumpToIndex?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const createScrollAction: (listRef: any, width: number) => {
|
|
23
|
+
scrollTo: (index: number, animated: boolean) => void;
|
|
24
|
+
};
|
|
16
25
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEtE,eAAO,MAAM,gBAAgB,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,mBAE9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,iBAM5D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,GAY7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAChC,mBAAmB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,MACpD,mCAAmC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;;;CAiB5F,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEtE,eAAO,MAAM,gBAAgB,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,mBAE9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,iBAM5D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,GAY7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAChC,mBAAmB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,MACpD,mCAAmC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;;;CAiB5F,CAAC;AAEJ,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,SAAS,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,OAAO,KAAG,CAAC,EAevF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,EACnB,oBAAoB,MAAM,EAC1B,YAAY,OAAO,KAClB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAoB/D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,GAAG,EAAE,OAAO,MAAM;sBAC1C,MAAM,YAAY,OAAO;CAO3C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-gesture-image-viewer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "🖼️ A highly customizable and easy-to-use React Native image viewer with gesture support and external controls",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
package/src/GestureViewer.tsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { type FlatList, Platform, type ScrollViewProps, StyleSheet, useWindowDimensions, View } from 'react-native';
|
|
3
3
|
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
4
4
|
import Animated from 'react-native-reanimated';
|
|
5
5
|
import { registry } from './GestureViewerRegistry';
|
|
6
6
|
import type { GestureViewerProps } from './types';
|
|
7
7
|
import { useGestureViewer } from './useGestureViewer';
|
|
8
|
-
import { isFlashListLike, isFlatListLike, isScrollViewLike } from './utils';
|
|
8
|
+
import { createLoopData, isFlashListLike, isFlatListLike, isScrollViewLike } from './utils';
|
|
9
9
|
import WebPagingFixStyle from './WebPagingFixStyle';
|
|
10
10
|
|
|
11
11
|
export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
@@ -21,14 +21,20 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
21
21
|
initialIndex = 0,
|
|
22
22
|
itemSpacing = 0,
|
|
23
23
|
useSnap = false,
|
|
24
|
+
enableLoop = false,
|
|
24
25
|
...props
|
|
25
26
|
}: GestureViewerProps<T, LC>) {
|
|
26
27
|
const Component = ListComponent as React.ComponentType<any>;
|
|
27
28
|
|
|
29
|
+
const dataRef = useRef(data);
|
|
30
|
+
dataRef.current = data;
|
|
31
|
+
|
|
28
32
|
const { width: screenWidth } = useWindowDimensions();
|
|
29
33
|
|
|
30
34
|
const width = useSnap ? customWidth || screenWidth : screenWidth;
|
|
31
35
|
|
|
36
|
+
const loopData = useMemo(() => createLoopData(dataRef, enableLoop), [enableLoop]);
|
|
37
|
+
|
|
32
38
|
const {
|
|
33
39
|
listRef,
|
|
34
40
|
isZoomed,
|
|
@@ -36,6 +42,7 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
36
42
|
dismissGesture,
|
|
37
43
|
zoomGesture,
|
|
38
44
|
onMomentumScrollEnd,
|
|
45
|
+
onScrollBeginDrag,
|
|
39
46
|
animatedStyle,
|
|
40
47
|
backdropStyle,
|
|
41
48
|
} = useGestureViewer({
|
|
@@ -45,14 +52,26 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
45
52
|
initialIndex,
|
|
46
53
|
itemSpacing,
|
|
47
54
|
useSnap,
|
|
55
|
+
enableLoop,
|
|
48
56
|
...props,
|
|
49
57
|
});
|
|
50
58
|
|
|
59
|
+
const keyExtractor = useCallback(
|
|
60
|
+
(item: T, index: number) => {
|
|
61
|
+
if (enableLoop) {
|
|
62
|
+
return typeof item === 'string' ? `${item}-${index}` : `item-${index}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return typeof item === 'string' ? item : `image-${index}`;
|
|
66
|
+
},
|
|
67
|
+
[enableLoop],
|
|
68
|
+
);
|
|
69
|
+
|
|
51
70
|
const renderItem = useCallback(
|
|
52
71
|
({ item, index }: { item: T; index: number }) => {
|
|
53
72
|
return (
|
|
54
73
|
<View
|
|
55
|
-
key={
|
|
74
|
+
key={keyExtractor(item, index)}
|
|
56
75
|
style={[
|
|
57
76
|
{
|
|
58
77
|
width,
|
|
@@ -67,7 +86,7 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
67
86
|
</View>
|
|
68
87
|
);
|
|
69
88
|
},
|
|
70
|
-
[width, itemSpacing, renderItemProp],
|
|
89
|
+
[width, itemSpacing, renderItemProp, keyExtractor],
|
|
71
90
|
);
|
|
72
91
|
|
|
73
92
|
const getItemLayout = useCallback(
|
|
@@ -79,11 +98,6 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
79
98
|
[width, itemSpacing],
|
|
80
99
|
);
|
|
81
100
|
|
|
82
|
-
const keyExtractor = useCallback(
|
|
83
|
-
(item: T, index: number) => (typeof item === 'string' ? item : `image-${index}`),
|
|
84
|
-
[],
|
|
85
|
-
);
|
|
86
|
-
|
|
87
101
|
const gesture = useMemo(() => {
|
|
88
102
|
return Gesture.Race(dismissGesture, zoomGesture);
|
|
89
103
|
}, [zoomGesture, dismissGesture]);
|
|
@@ -94,25 +108,27 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
94
108
|
return () => registry.deleteManager(id);
|
|
95
109
|
}, [id]);
|
|
96
110
|
|
|
97
|
-
const commonProps
|
|
98
|
-
() =>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
const commonProps = useMemo(
|
|
112
|
+
() =>
|
|
113
|
+
({
|
|
114
|
+
horizontal: true,
|
|
115
|
+
scrollEnabled: !isZoomed && !isRotated,
|
|
116
|
+
showsHorizontalScrollIndicator: false,
|
|
117
|
+
onMomentumScrollEnd: onMomentumScrollEnd,
|
|
118
|
+
onScrollBeginDrag,
|
|
119
|
+
...(useSnap
|
|
120
|
+
? {
|
|
121
|
+
snapToInterval: width + itemSpacing,
|
|
122
|
+
snapToAlignment: 'center',
|
|
123
|
+
decelerationRate: 'fast',
|
|
124
|
+
}
|
|
125
|
+
: {
|
|
126
|
+
pagingEnabled: true,
|
|
127
|
+
}),
|
|
128
|
+
scrollEventThrottle: 16,
|
|
129
|
+
removeClippedSubviews: true,
|
|
130
|
+
}) satisfies ScrollViewProps,
|
|
131
|
+
[width, itemSpacing, isZoomed, isRotated, onMomentumScrollEnd, onScrollBeginDrag, useSnap],
|
|
116
132
|
);
|
|
117
133
|
|
|
118
134
|
const listComponent = (
|
|
@@ -127,16 +143,16 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
|
|
|
127
143
|
>
|
|
128
144
|
{isScrollViewLike(Component) ? (
|
|
129
145
|
<Component ref={listRef} {...commonProps} {...listProps}>
|
|
130
|
-
{
|
|
146
|
+
{loopData.map((item, index) => renderItem({ item, index }))}
|
|
131
147
|
</Component>
|
|
132
148
|
) : (
|
|
133
149
|
isFlatListLike(Component) && (
|
|
134
150
|
<Component
|
|
135
151
|
ref={listRef}
|
|
136
152
|
{...commonProps}
|
|
137
|
-
data={
|
|
153
|
+
data={loopData}
|
|
138
154
|
renderItem={renderItem}
|
|
139
|
-
initialScrollIndex={initialIndex}
|
|
155
|
+
initialScrollIndex={enableLoop && data.length > 1 ? initialIndex + 1 : initialIndex}
|
|
140
156
|
keyExtractor={keyExtractor}
|
|
141
157
|
windowSize={3}
|
|
142
158
|
maxToRenderPerBatch={3}
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
GestureViewerEventData,
|
|
6
6
|
GestureViewerEventType,
|
|
7
7
|
} from './types';
|
|
8
|
-
import { createBoundsConstraint } from './utils';
|
|
8
|
+
import { createBoundsConstraint, createScrollAction } from './utils';
|
|
9
9
|
|
|
10
10
|
class GestureViewerManager {
|
|
11
11
|
private currentIndex = 0;
|
|
@@ -18,9 +18,13 @@ class GestureViewerManager {
|
|
|
18
18
|
private maxZoomScale = 2;
|
|
19
19
|
private listRef: any | null = null;
|
|
20
20
|
private enableSwipeGesture = true;
|
|
21
|
+
private enableLoop = false;
|
|
21
22
|
private listeners = new Set<(state: GestureViewerControllerState) => void>();
|
|
22
23
|
private rotation: SharedValue<number> | null = null;
|
|
23
24
|
private eventListeners = new Map<GestureViewerEventType, Set<(data: any) => void>>();
|
|
25
|
+
private animationTimeout: NodeJS.Timeout | null = null;
|
|
26
|
+
|
|
27
|
+
private static readonly LOOP_ANIMATION_DURATION = 300;
|
|
24
28
|
|
|
25
29
|
private notifyListeners() {
|
|
26
30
|
const state = this.getState();
|
|
@@ -79,6 +83,10 @@ class GestureViewerManager {
|
|
|
79
83
|
};
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
setEnableLoop(enabled: boolean) {
|
|
87
|
+
this.enableLoop = enabled;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
setWidth(width: number) {
|
|
83
91
|
this.width = width;
|
|
84
92
|
}
|
|
@@ -215,40 +223,73 @@ class GestureViewerManager {
|
|
|
215
223
|
};
|
|
216
224
|
|
|
217
225
|
goToIndex = (index: number) => {
|
|
218
|
-
if (
|
|
226
|
+
if (!this.enableSwipeGesture || !this.listRef) {
|
|
219
227
|
return;
|
|
220
228
|
}
|
|
221
229
|
|
|
222
|
-
this.
|
|
230
|
+
this.cancelAnimation();
|
|
231
|
+
|
|
232
|
+
const { scrollTo } = createScrollAction(this.listRef, this.width);
|
|
233
|
+
|
|
234
|
+
if (this.enableLoop && this.dataLength > 1) {
|
|
235
|
+
if (index < 0) {
|
|
236
|
+
scrollTo(0, true);
|
|
237
|
+
|
|
238
|
+
this.animationTimeout = setTimeout(() => {
|
|
239
|
+
scrollTo(this.dataLength, false);
|
|
240
|
+
this.updateCurrentIndex(this.dataLength - 1);
|
|
241
|
+
}, GestureViewerManager.LOOP_ANIMATION_DURATION);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (index >= this.dataLength) {
|
|
246
|
+
scrollTo(this.dataLength + 1, true);
|
|
247
|
+
|
|
248
|
+
this.animationTimeout = setTimeout(() => {
|
|
249
|
+
scrollTo(1, false);
|
|
250
|
+
this.updateCurrentIndex(0);
|
|
251
|
+
}, GestureViewerManager.LOOP_ANIMATION_DURATION);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const scrollIndex = index + 1;
|
|
256
|
+
|
|
257
|
+
scrollTo(scrollIndex, true);
|
|
258
|
+
this.updateCurrentIndex(index);
|
|
259
|
+
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
223
262
|
|
|
224
|
-
if (this.
|
|
225
|
-
|
|
226
|
-
} else if (this.listRef.scrollTo) {
|
|
227
|
-
this.listRef.scrollTo({ x: index * this.width, animated: true });
|
|
263
|
+
if (index < 0 || index >= this.dataLength) {
|
|
264
|
+
return;
|
|
228
265
|
}
|
|
229
266
|
|
|
230
|
-
|
|
267
|
+
scrollTo(index, true);
|
|
268
|
+
this.updateCurrentIndex(index);
|
|
231
269
|
};
|
|
232
270
|
|
|
233
|
-
|
|
234
|
-
if (this.
|
|
235
|
-
|
|
271
|
+
cancelAnimation = () => {
|
|
272
|
+
if (this.animationTimeout) {
|
|
273
|
+
clearTimeout(this.animationTimeout);
|
|
274
|
+
this.animationTimeout = null;
|
|
236
275
|
}
|
|
237
276
|
};
|
|
238
277
|
|
|
278
|
+
goToPrevious = () => {
|
|
279
|
+
this.goToIndex(this.currentIndex - 1);
|
|
280
|
+
};
|
|
281
|
+
|
|
239
282
|
goToNext = () => {
|
|
240
|
-
|
|
241
|
-
this.goToIndex(this.currentIndex + 1);
|
|
242
|
-
}
|
|
283
|
+
this.goToIndex(this.currentIndex + 1);
|
|
243
284
|
};
|
|
244
285
|
|
|
245
286
|
cleanUp() {
|
|
287
|
+
this.cancelAnimation();
|
|
246
288
|
this.listeners.clear();
|
|
247
289
|
this.listRef = null;
|
|
248
290
|
this.enableSwipeGesture = true;
|
|
249
291
|
this.currentIndex = 0;
|
|
250
292
|
this.dataLength = 0;
|
|
251
|
-
|
|
252
293
|
this.maxZoomScale = 2;
|
|
253
294
|
this.scale = null;
|
|
254
295
|
this.translateX = null;
|
|
@@ -256,6 +297,11 @@ class GestureViewerManager {
|
|
|
256
297
|
this.rotation = null;
|
|
257
298
|
this.eventListeners.clear();
|
|
258
299
|
}
|
|
300
|
+
|
|
301
|
+
private updateCurrentIndex = (targetIndex: number) => {
|
|
302
|
+
this.currentIndex = targetIndex;
|
|
303
|
+
this.notifyListeners();
|
|
304
|
+
};
|
|
259
305
|
}
|
|
260
306
|
|
|
261
307
|
export default GestureViewerManager;
|
package/src/types.ts
CHANGED
|
@@ -130,6 +130,11 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
|
|
|
130
130
|
* @defaultValue true
|
|
131
131
|
*/
|
|
132
132
|
enableDoubleTapGesture?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Enables infinite loop navigation.
|
|
135
|
+
* @defaultValue false
|
|
136
|
+
*/
|
|
137
|
+
enableLoop?: boolean;
|
|
133
138
|
/**
|
|
134
139
|
* The maximum zoom scale.
|
|
135
140
|
* @defaultValue 2
|
package/src/useGestureViewer.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import type GestureViewerManager from './GestureViewerManager';
|
|
20
20
|
import { registry } from './GestureViewerRegistry';
|
|
21
21
|
import type { GestureViewerProps } from './types';
|
|
22
|
-
import { createBoundsConstraint } from './utils';
|
|
22
|
+
import { createBoundsConstraint, createScrollAction, getLoopAdjustedIndex } from './utils';
|
|
23
23
|
|
|
24
24
|
type UseGestureViewerProps<T = any> = Omit<
|
|
25
25
|
GestureViewerProps<T>,
|
|
@@ -42,6 +42,7 @@ export const useGestureViewer = <T = any>({
|
|
|
42
42
|
enableZoomGesture = true,
|
|
43
43
|
enableDoubleTapGesture = true,
|
|
44
44
|
enableZoomPanGesture = true,
|
|
45
|
+
enableLoop = false,
|
|
45
46
|
maxZoomScale = 2,
|
|
46
47
|
itemSpacing = 0,
|
|
47
48
|
useSnap = false,
|
|
@@ -71,11 +72,28 @@ export const useGestureViewer = <T = any>({
|
|
|
71
72
|
|
|
72
73
|
const dataLength = data?.length || 0;
|
|
73
74
|
|
|
75
|
+
const adjustedInitialIndex = useMemo(() => {
|
|
76
|
+
if (enableLoop && data.length > 1) {
|
|
77
|
+
return initialIndex + 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return initialIndex;
|
|
81
|
+
}, [enableLoop, data.length, initialIndex]);
|
|
82
|
+
|
|
74
83
|
const constrainTranslation = useMemo(
|
|
75
84
|
() => createBoundsConstraint({ width, height: screenHeight }),
|
|
76
85
|
[width, screenHeight],
|
|
77
86
|
);
|
|
78
87
|
|
|
88
|
+
const scrollTo = useCallback(
|
|
89
|
+
(index: number, animated: boolean) => {
|
|
90
|
+
const scrollAction = createScrollAction(listRef.current, width + itemSpacing);
|
|
91
|
+
|
|
92
|
+
return scrollAction.scrollTo(index, animated);
|
|
93
|
+
},
|
|
94
|
+
[width, itemSpacing],
|
|
95
|
+
);
|
|
96
|
+
|
|
79
97
|
const emitZoomChange = useCallback(
|
|
80
98
|
(currentScale: number, prevScale: number | null) => {
|
|
81
99
|
manager?.emitZoomChange(currentScale, prevScale);
|
|
@@ -150,6 +168,7 @@ export const useGestureViewer = <T = any>({
|
|
|
150
168
|
manager.setHeight(screenHeight);
|
|
151
169
|
manager.setZoomSharedValues(scale, translateX, translateY, maxZoomScale);
|
|
152
170
|
manager.setRotation(rotation);
|
|
171
|
+
manager.setEnableLoop(enableLoop);
|
|
153
172
|
manager.notifyStateChange();
|
|
154
173
|
}, [
|
|
155
174
|
dataLength,
|
|
@@ -159,6 +178,7 @@ export const useGestureViewer = <T = any>({
|
|
|
159
178
|
width,
|
|
160
179
|
itemSpacing,
|
|
161
180
|
maxZoomScale,
|
|
181
|
+
enableLoop,
|
|
162
182
|
scale,
|
|
163
183
|
screenHeight,
|
|
164
184
|
translateX,
|
|
@@ -186,28 +206,18 @@ export const useGestureViewer = <T = any>({
|
|
|
186
206
|
startScale.value = 1;
|
|
187
207
|
rotation.value = 0;
|
|
188
208
|
|
|
189
|
-
if (
|
|
209
|
+
if (adjustedInitialIndex <= 0 || !listRef.current) {
|
|
190
210
|
return;
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
const runAfterInteractions = InteractionManager.runAfterInteractions(() => {
|
|
194
|
-
|
|
195
|
-
listRef.current.scrollToIndex({
|
|
196
|
-
index: initialIndex,
|
|
197
|
-
animated: false,
|
|
198
|
-
});
|
|
199
|
-
} else if (listRef.current.scrollTo) {
|
|
200
|
-
listRef.current.scrollTo({
|
|
201
|
-
x: initialIndex * (width + itemSpacing),
|
|
202
|
-
animated: false,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
214
|
+
scrollTo(adjustedInitialIndex, false);
|
|
205
215
|
});
|
|
206
216
|
|
|
207
217
|
return () => {
|
|
208
218
|
runAfterInteractions?.cancel();
|
|
209
219
|
};
|
|
210
|
-
}, [
|
|
220
|
+
}, [adjustedInitialIndex, translateY, backdropOpacity, translateX, scale, startScale, rotation, scrollTo]);
|
|
211
221
|
|
|
212
222
|
const onMomentumScrollEnd = useCallback(
|
|
213
223
|
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
@@ -216,12 +226,18 @@ export const useGestureViewer = <T = any>({
|
|
|
216
226
|
}
|
|
217
227
|
|
|
218
228
|
const contentOffset = event.nativeEvent.contentOffset;
|
|
219
|
-
const
|
|
229
|
+
const scrollIndex = Math.round(contentOffset.x / (width + itemSpacing));
|
|
220
230
|
|
|
221
|
-
|
|
231
|
+
const { realIndex, needsJump, jumpToIndex } = getLoopAdjustedIndex(scrollIndex, dataLength, enableLoop);
|
|
232
|
+
|
|
233
|
+
if (needsJump && jumpToIndex !== undefined) {
|
|
234
|
+
scrollTo(jumpToIndex, false);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (realIndex !== currentIndex && realIndex >= 0 && realIndex < dataLength) {
|
|
222
238
|
if (manager) {
|
|
223
|
-
manager.setCurrentIndex(
|
|
224
|
-
setCurrentIndex(
|
|
239
|
+
manager.setCurrentIndex(realIndex);
|
|
240
|
+
setCurrentIndex(realIndex);
|
|
225
241
|
manager.notifyStateChange();
|
|
226
242
|
}
|
|
227
243
|
|
|
@@ -235,12 +251,14 @@ export const useGestureViewer = <T = any>({
|
|
|
235
251
|
}
|
|
236
252
|
},
|
|
237
253
|
[
|
|
254
|
+
scrollTo,
|
|
238
255
|
manager,
|
|
239
256
|
currentIndex,
|
|
240
257
|
dataLength,
|
|
241
258
|
width,
|
|
242
259
|
itemSpacing,
|
|
243
260
|
enableSwipeGesture,
|
|
261
|
+
enableLoop,
|
|
244
262
|
translateX,
|
|
245
263
|
translateY,
|
|
246
264
|
scale,
|
|
@@ -463,6 +481,10 @@ export const useGestureViewer = <T = any>({
|
|
|
463
481
|
return { opacity };
|
|
464
482
|
}, [animateBackdrop]);
|
|
465
483
|
|
|
484
|
+
const onScrollBeginDrag = useCallback(() => {
|
|
485
|
+
manager?.cancelAnimation();
|
|
486
|
+
}, [manager]);
|
|
487
|
+
|
|
466
488
|
return {
|
|
467
489
|
currentIndex,
|
|
468
490
|
dataLength,
|
|
@@ -474,6 +496,7 @@ export const useGestureViewer = <T = any>({
|
|
|
474
496
|
zoomGesture,
|
|
475
497
|
|
|
476
498
|
onMomentumScrollEnd,
|
|
499
|
+
onScrollBeginDrag,
|
|
477
500
|
|
|
478
501
|
animatedStyle,
|
|
479
502
|
backdropStyle,
|
package/src/utils.ts
CHANGED
|
@@ -48,3 +48,56 @@ export const createBoundsConstraint =
|
|
|
48
48
|
translateY: Math.max(-maxTranslateY, Math.min(maxTranslateY, translateY)),
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
+
|
|
52
|
+
export const createLoopData = <T>(dataRef: React.RefObject<T[]>, enableLoop: boolean): T[] => {
|
|
53
|
+
const data = dataRef.current;
|
|
54
|
+
|
|
55
|
+
if (!enableLoop || !data?.length || data.length <= 1) {
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const lastItem = data[data.length - 1];
|
|
60
|
+
const firstItem = data[0];
|
|
61
|
+
|
|
62
|
+
if (lastItem === undefined || firstItem === undefined) {
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return [lastItem, ...data, firstItem];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const getLoopAdjustedIndex = (
|
|
70
|
+
scrollIndex: number,
|
|
71
|
+
originalDataLength: number,
|
|
72
|
+
enableLoop: boolean,
|
|
73
|
+
): { realIndex: number; needsJump: boolean; jumpToIndex?: number } => {
|
|
74
|
+
if (!enableLoop || originalDataLength <= 1) {
|
|
75
|
+
return { realIndex: scrollIndex, needsJump: false };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (scrollIndex === 0) {
|
|
79
|
+
return {
|
|
80
|
+
realIndex: originalDataLength - 1,
|
|
81
|
+
needsJump: true,
|
|
82
|
+
jumpToIndex: originalDataLength,
|
|
83
|
+
};
|
|
84
|
+
} else if (scrollIndex === originalDataLength + 1) {
|
|
85
|
+
return {
|
|
86
|
+
realIndex: 0,
|
|
87
|
+
needsJump: true,
|
|
88
|
+
jumpToIndex: 1,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { realIndex: scrollIndex - 1, needsJump: false };
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const createScrollAction = (listRef: any, width: number) => ({
|
|
96
|
+
scrollTo: (index: number, animated: boolean) => {
|
|
97
|
+
if (listRef?.scrollToIndex) {
|
|
98
|
+
listRef.scrollToIndex({ index, animated });
|
|
99
|
+
} else if (listRef?.scrollTo) {
|
|
100
|
+
listRef.scrollTo({ x: index * width, animated });
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
});
|