react-native-gesture-image-viewer 2.0.0-beta.4 → 2.0.0-beta.5
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 +32 -15
- package/lib/module/GestureTrigger.js +82 -0
- package/lib/module/GestureTrigger.js.map +1 -0
- package/lib/module/GestureViewer.js +9 -3
- package/lib/module/GestureViewer.js.map +1 -1
- package/lib/module/GestureViewerRegistry.js +11 -0
- package/lib/module/GestureViewerRegistry.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/useGestureViewer.js +102 -10
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/typescript/src/GestureTrigger.d.ts +55 -0
- package/lib/typescript/src/GestureTrigger.d.ts.map +1 -0
- package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerRegistry.d.ts +5 -0
- package/lib/typescript/src/GestureViewerRegistry.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +56 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts +9 -8
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/GestureTrigger.tsx +86 -0
- package/src/GestureViewer.tsx +8 -2
- package/src/GestureViewerRegistry.ts +16 -0
- package/src/index.tsx +2 -0
- package/src/types.ts +56 -1
- package/src/useGestureViewer.ts +141 -10
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal contract for a pressable child's props.
|
|
4
|
+
* The child must optionally accept an `onPress` handler.
|
|
5
|
+
*/
|
|
6
|
+
type WithOnPress = {
|
|
7
|
+
onPress?: (...args: unknown[]) => void;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Props for `GestureTrigger`.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam T - The child's props type. Must include an optional `onPress` handler.
|
|
13
|
+
*
|
|
14
|
+
* @property id - Optional identifier to associate this trigger with a `GestureViewer`.
|
|
15
|
+
* @property children - A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`).
|
|
16
|
+
* @property onPress - Optional handler invoked after the child's own `onPress`.
|
|
17
|
+
*/
|
|
18
|
+
export type GestureTriggerProps<T extends WithOnPress> = {
|
|
19
|
+
id?: string;
|
|
20
|
+
children: ReactElement<T>;
|
|
21
|
+
onPress?: (...args: unknown[]) => void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Wraps a pressable child element and registers its native view as a trigger for `GestureViewer`.
|
|
25
|
+
*
|
|
26
|
+
* @remark
|
|
27
|
+
* Behavior on press:
|
|
28
|
+
* - Registers the child's native node to the internal registry under the given `id`.
|
|
29
|
+
* - Invokes the child's own `onPress` first (if provided).
|
|
30
|
+
* - Invokes the `onPress` passed to `GestureTrigger` next (if provided).
|
|
31
|
+
*
|
|
32
|
+
* Type parameters:
|
|
33
|
+
* - `T` — The child's props type. Must include an optional `onPress` handler, ensuring the child is pressable.
|
|
34
|
+
*
|
|
35
|
+
* Props:
|
|
36
|
+
* - `id` — Optional identifier to associate this trigger with a `GestureViewer`. Defaults to `"default"`.
|
|
37
|
+
* - `children` — A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`, custom button).
|
|
38
|
+
* - `onPress` — Optional handler invoked after the child's `onPress`. Receives the same arguments as the child's handler.
|
|
39
|
+
*
|
|
40
|
+
* Notes:
|
|
41
|
+
* - If neither the child nor this component provides `onPress`, a dev warning is logged and nothing happens on press.
|
|
42
|
+
* - Only a single child is allowed; wrap lists using `React.Children.map` when needed.
|
|
43
|
+
*
|
|
44
|
+
* Example:
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <GestureTrigger id="gallery" onPress={() => openModal(index)}>
|
|
47
|
+
* <Pressable style={styles.thumb}>
|
|
48
|
+
* <Image source={{ uri }} style={styles.thumbImage} />
|
|
49
|
+
* </Pressable>
|
|
50
|
+
* </GestureTrigger>
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function GestureTrigger<T extends WithOnPress>({ id, children, onPress }: GestureTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=GestureTrigger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GestureTrigger.d.ts","sourceRoot":"","sources":["../../../src/GestureTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,IAAI;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,EAAE,EAAE,EAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,2CA6BlH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureViewer.d.ts","sourceRoot":"","sources":["../../../src/GestureViewer.tsx"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,UAAU,EAA+D,MAAM,cAAc,CAAC;AAItH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,UAAU,EAAE,EAC7D,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,cAAsB,EACtB,UAAkB,EAClB,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,EAAY,KAAK,UAAU,EAA+D,MAAM,cAAc,CAAC;AAItH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,UAAU,EAAE,EAC7D,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,cAAsB,EACtB,UAAkB,EAClB,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,2CA8J3B"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import type { View } from 'react-native';
|
|
1
2
|
import GestureViewerManager from './GestureViewerManager';
|
|
2
3
|
declare class GestureViewerRegistry {
|
|
3
4
|
private managers;
|
|
4
5
|
private subscribers;
|
|
6
|
+
private triggers;
|
|
5
7
|
subscribeToManager(id: string, callback: (manager: GestureViewerManager | null) => void): () => void;
|
|
6
8
|
createManager(id: string): GestureViewerManager | null;
|
|
7
9
|
getManager(id: string): GestureViewerManager | null;
|
|
8
10
|
deleteManager(id: string): void;
|
|
9
11
|
notifySubscribers(id: string, manager: GestureViewerManager | null): void;
|
|
12
|
+
setTriggerNode(id: string, node: View | null): void;
|
|
13
|
+
getTriggerNode(id: string): View | null;
|
|
14
|
+
clearTriggerNode(id: string): void;
|
|
10
15
|
}
|
|
11
16
|
export declare const registry: GestureViewerRegistry;
|
|
12
17
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureViewerRegistry.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,cAAM,qBAAqB;IACzB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAA0E;
|
|
1
|
+
{"version":3,"file":"GestureViewerRegistry.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,cAAM,qBAAqB;IACzB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAA0E;IAC7F,OAAO,CAAC,QAAQ,CAAkC;IAElD,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI;IAsBvF,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI;IAatD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI;IAInD,aAAa,CAAC,EAAE,EAAE,MAAM;IAaxB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAQlE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAI5C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIvC,gBAAgB,CAAC,EAAE,EAAE,MAAM;CAG5B;AAED,eAAO,MAAM,QAAQ,uBAA8B,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { GestureTriggerProps } from './GestureTrigger';
|
|
2
|
+
export { GestureTrigger } from './GestureTrigger';
|
|
1
3
|
export { GestureViewer } from './GestureViewer';
|
|
2
4
|
export type { GestureViewerController, GestureViewerEventCallback, GestureViewerEventData, GestureViewerEventType, GestureViewerProps, GestureViewerState, } from './types';
|
|
3
5
|
export { useGestureViewerController } from './useGestureViewerController';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { FlatList as RNFlatList, ScrollView as RNScrollView, StyleProp, ViewStyle } from 'react-native';
|
|
3
3
|
import type { FlatList as GHFlatList, ScrollView as GHScrollView } from 'react-native-gesture-handler';
|
|
4
|
+
import type { WithTimingConfig } from 'react-native-reanimated';
|
|
4
5
|
export type FlatListComponent = typeof RNFlatList | typeof GHFlatList;
|
|
5
6
|
export type ScrollViewComponent = typeof RNScrollView | typeof GHScrollView;
|
|
6
7
|
type GetComponentProps<T> = T extends React.ComponentType<infer P> ? P : never;
|
|
7
8
|
type ConditionalListProps<LC> = LC extends FlatListComponent ? React.ComponentProps<LC> : LC extends ScrollViewComponent ? React.ComponentProps<LC> : GetComponentProps<LC>;
|
|
9
|
+
export type TriggerRect = {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
export interface TriggerAnimationConfig extends WithTimingConfig {
|
|
16
|
+
/**
|
|
17
|
+
* Animation duration in milliseconds
|
|
18
|
+
* @defaultValue 300
|
|
19
|
+
*/
|
|
20
|
+
duration?: WithTimingConfig['duration'];
|
|
21
|
+
/**
|
|
22
|
+
* Animation easing function
|
|
23
|
+
* @defaultValue Easing.bezier(0.25, 0.1, 0.25, 1.0)
|
|
24
|
+
*/
|
|
25
|
+
easing?: WithTimingConfig['easing'];
|
|
26
|
+
/**
|
|
27
|
+
* Callback function called after animation completion
|
|
28
|
+
*/
|
|
29
|
+
onAnimationComplete?: () => void;
|
|
30
|
+
}
|
|
8
31
|
export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
9
32
|
/**
|
|
10
33
|
* When you want to efficiently manage multiple `GestureViewer` instances, you can use the `id` prop to use multiple `GestureViewer` components.
|
|
@@ -25,14 +48,27 @@ export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
|
25
48
|
* A callback function that is called when the `GestureViewer` is dismissed.
|
|
26
49
|
*/
|
|
27
50
|
onDismiss?: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* A callback function that is called when the dismiss interaction starts.
|
|
53
|
+
* @remarks Useful to hide external UI (e.g., headers, buttons) while the dismiss gesture/animation is in progress.
|
|
54
|
+
*/
|
|
55
|
+
onDismissStart?: () => void;
|
|
28
56
|
/**
|
|
29
57
|
* A callback function that is called to render the item.
|
|
30
58
|
*/
|
|
31
59
|
renderItem: (item: T, index: number) => React.ReactElement;
|
|
32
60
|
/**
|
|
33
61
|
* A callback function that is called to render the container.
|
|
62
|
+
* @remarks Useful for composing additional UI (e.g., close button, toolbars) around the viewer.
|
|
63
|
+
* The second argument provides control helpers such as `dismiss()` to close the viewer.
|
|
64
|
+
*
|
|
65
|
+
* @param children - The viewer content to be rendered inside your container.
|
|
66
|
+
* @param helpers - Control helpers for the viewer. Currently includes `dismiss()`.
|
|
67
|
+
* @returns A React element that wraps and renders the provided `children`.
|
|
34
68
|
*/
|
|
35
|
-
renderContainer?: (children: React.ReactElement
|
|
69
|
+
renderContainer?: (children: React.ReactElement, helpers: {
|
|
70
|
+
dismiss: () => void;
|
|
71
|
+
}) => React.ReactElement;
|
|
36
72
|
/**
|
|
37
73
|
* Support for any list component like `ScrollView`, `FlatList`, `FlashList` through the `ListComponent` prop.
|
|
38
74
|
*/
|
|
@@ -137,6 +173,25 @@ export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
|
137
173
|
* @defaultValue 2
|
|
138
174
|
*/
|
|
139
175
|
maxZoomScale?: number;
|
|
176
|
+
/**
|
|
177
|
+
* Trigger-based animation settings
|
|
178
|
+
* @remarks You can customize animation duration, easing, and system reduce-motion behavior.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```tsx
|
|
182
|
+
* <GestureViewer
|
|
183
|
+
* triggerAnimation={{
|
|
184
|
+
* duration: 250,
|
|
185
|
+
* easing: Easing.out(Easing.cubic),
|
|
186
|
+
* reduceMotion: 'system',
|
|
187
|
+
* onAnimationComplete: () => {
|
|
188
|
+
* console.log('Animation complete');
|
|
189
|
+
* },
|
|
190
|
+
* }}
|
|
191
|
+
* />
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
triggerAnimation?: TriggerAnimationConfig;
|
|
140
195
|
}
|
|
141
196
|
/**
|
|
142
197
|
* Supported rotation angles in degrees.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,IAAI,UAAU,EAAE,UAAU,IAAI,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7G,OAAO,KAAK,EAAE,QAAQ,IAAI,UAAU,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
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, onDismiss, width: customWidth, dismiss, enableDoubleTapZoom, enablePinchZoom, enableHorizontalSwipe, enablePanWhenZoomed, enableLoop, maxZoomScale, itemSpacing, enableSnapMode, id, }: UseGestureViewerProps<T>) => {
|
|
4
|
+
export declare const useGestureViewer: <T = any>({ data, initialIndex, onDismiss, width: customWidth, dismiss, enableDoubleTapZoom, enablePinchZoom, enableHorizontalSwipe, enablePanWhenZoomed, enableLoop, maxZoomScale, itemSpacing, enableSnapMode, id, onDismissStart, triggerAnimation, }: UseGestureViewerProps<T>) => {
|
|
5
5
|
dataLength: number;
|
|
6
|
-
translateY: import("react-native-reanimated").SharedValue<number>;
|
|
7
6
|
listRef: import("react").RefObject<any>;
|
|
8
7
|
isZoomed: boolean;
|
|
9
8
|
isRotated: boolean;
|
|
@@ -11,26 +10,28 @@ export declare const useGestureViewer: <T = any>({ data, initialIndex, onDismiss
|
|
|
11
10
|
zoomGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/gestureComposition").ComposedGesture;
|
|
12
11
|
onMomentumScrollEnd: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
13
12
|
onScrollBeginDrag: () => void;
|
|
13
|
+
handleDismiss: () => void;
|
|
14
14
|
animatedStyle: {
|
|
15
|
+
opacity: number;
|
|
15
16
|
transform: ({
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
translateX: number;
|
|
18
|
+
translateY?: undefined;
|
|
18
19
|
scale?: undefined;
|
|
19
20
|
rotate?: undefined;
|
|
20
21
|
} | {
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
translateY: number;
|
|
23
|
+
translateX?: undefined;
|
|
23
24
|
scale?: undefined;
|
|
24
25
|
rotate?: undefined;
|
|
25
26
|
} | {
|
|
26
27
|
scale: number;
|
|
27
|
-
translateY?: undefined;
|
|
28
28
|
translateX?: undefined;
|
|
29
|
+
translateY?: undefined;
|
|
29
30
|
rotate?: undefined;
|
|
30
31
|
} | {
|
|
31
32
|
rotate: string;
|
|
32
|
-
translateY?: undefined;
|
|
33
33
|
translateX?: undefined;
|
|
34
|
+
translateY?: undefined;
|
|
34
35
|
scale?: undefined;
|
|
35
36
|
})[];
|
|
36
37
|
};
|
|
@@ -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,
|
|
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;AAG/D,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,gPAiBvC,qBAAqB,CAAC,CAAC,CAAC;;;;;;;iCAuRf,oBAAoB,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0SlD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-gesture-image-viewer",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.5",
|
|
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",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import { Children, cloneElement, isValidElement, useMemo, useRef } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { registry } from './GestureViewerRegistry';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Minimal contract for a pressable child's props.
|
|
8
|
+
* The child must optionally accept an `onPress` handler.
|
|
9
|
+
*/
|
|
10
|
+
type WithOnPress = { onPress?: (...args: unknown[]) => void };
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Props for `GestureTrigger`.
|
|
14
|
+
*
|
|
15
|
+
* @typeParam T - The child's props type. Must include an optional `onPress` handler.
|
|
16
|
+
*
|
|
17
|
+
* @property id - Optional identifier to associate this trigger with a `GestureViewer`.
|
|
18
|
+
* @property children - A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`).
|
|
19
|
+
* @property onPress - Optional handler invoked after the child's own `onPress`.
|
|
20
|
+
*/
|
|
21
|
+
export type GestureTriggerProps<T extends WithOnPress> = {
|
|
22
|
+
id?: string;
|
|
23
|
+
children: ReactElement<T>;
|
|
24
|
+
onPress?: (...args: unknown[]) => void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Wraps a pressable child element and registers its native view as a trigger for `GestureViewer`.
|
|
29
|
+
*
|
|
30
|
+
* @remark
|
|
31
|
+
* Behavior on press:
|
|
32
|
+
* - Registers the child's native node to the internal registry under the given `id`.
|
|
33
|
+
* - Invokes the child's own `onPress` first (if provided).
|
|
34
|
+
* - Invokes the `onPress` passed to `GestureTrigger` next (if provided).
|
|
35
|
+
*
|
|
36
|
+
* Type parameters:
|
|
37
|
+
* - `T` — The child's props type. Must include an optional `onPress` handler, ensuring the child is pressable.
|
|
38
|
+
*
|
|
39
|
+
* Props:
|
|
40
|
+
* - `id` — Optional identifier to associate this trigger with a `GestureViewer`. Defaults to `"default"`.
|
|
41
|
+
* - `children` — A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`, custom button).
|
|
42
|
+
* - `onPress` — Optional handler invoked after the child's `onPress`. Receives the same arguments as the child's handler.
|
|
43
|
+
*
|
|
44
|
+
* Notes:
|
|
45
|
+
* - If neither the child nor this component provides `onPress`, a dev warning is logged and nothing happens on press.
|
|
46
|
+
* - Only a single child is allowed; wrap lists using `React.Children.map` when needed.
|
|
47
|
+
*
|
|
48
|
+
* Example:
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <GestureTrigger id="gallery" onPress={() => openModal(index)}>
|
|
51
|
+
* <Pressable style={styles.thumb}>
|
|
52
|
+
* <Image source={{ uri }} style={styles.thumbImage} />
|
|
53
|
+
* </Pressable>
|
|
54
|
+
* </GestureTrigger>
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function GestureTrigger<T extends WithOnPress>({ id = 'default', children, onPress }: GestureTriggerProps<T>) {
|
|
58
|
+
const ref = useRef<View>(null);
|
|
59
|
+
|
|
60
|
+
const wrapped = useMemo(() => {
|
|
61
|
+
const child = Children.only(children);
|
|
62
|
+
|
|
63
|
+
if (!isValidElement(child)) {
|
|
64
|
+
return children;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const originalOnPress = child.props?.onPress;
|
|
68
|
+
|
|
69
|
+
const handlePress = (...args: unknown[]) => {
|
|
70
|
+
registry.setTriggerNode(id, ref.current);
|
|
71
|
+
originalOnPress?.(...args);
|
|
72
|
+
onPress?.(...args);
|
|
73
|
+
|
|
74
|
+
if (__DEV__ && !originalOnPress && !onPress) {
|
|
75
|
+
console.warn('[GestureTrigger] No onPress found on child or props. Nothing will happen on press.');
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return cloneElement(child, {
|
|
80
|
+
...child.props,
|
|
81
|
+
onPress: handlePress,
|
|
82
|
+
});
|
|
83
|
+
}, [id, onPress, children]);
|
|
84
|
+
|
|
85
|
+
return <View ref={ref}>{wrapped}</View>;
|
|
86
|
+
}
|
package/src/GestureViewer.tsx
CHANGED
|
@@ -27,7 +27,6 @@ export function GestureViewer<T = any, LC = typeof ScrollView>({
|
|
|
27
27
|
const Component = ListComponent as React.ComponentType<any>;
|
|
28
28
|
|
|
29
29
|
const dataRef = useRef(data);
|
|
30
|
-
dataRef.current = data;
|
|
31
30
|
|
|
32
31
|
const { width: screenWidth } = useWindowDimensions();
|
|
33
32
|
|
|
@@ -47,6 +46,7 @@ export function GestureViewer<T = any, LC = typeof ScrollView>({
|
|
|
47
46
|
onScrollBeginDrag,
|
|
48
47
|
animatedStyle,
|
|
49
48
|
backdropStyle,
|
|
49
|
+
handleDismiss,
|
|
50
50
|
} = useGestureViewer({
|
|
51
51
|
id,
|
|
52
52
|
data,
|
|
@@ -104,6 +104,10 @@ export function GestureViewer<T = any, LC = typeof ScrollView>({
|
|
|
104
104
|
return Gesture.Race(dismissGesture, zoomGesture);
|
|
105
105
|
}, [zoomGesture, dismissGesture]);
|
|
106
106
|
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
dataRef.current = data;
|
|
109
|
+
}, [data]);
|
|
110
|
+
|
|
107
111
|
useEffect(() => {
|
|
108
112
|
registry.createManager(id);
|
|
109
113
|
|
|
@@ -133,6 +137,8 @@ export function GestureViewer<T = any, LC = typeof ScrollView>({
|
|
|
133
137
|
[width, itemSpacing, isZoomed, isRotated, onMomentumScrollEnd, onScrollBeginDrag, enableSnapMode],
|
|
134
138
|
);
|
|
135
139
|
|
|
140
|
+
const control = useMemo(() => ({ dismiss: handleDismiss }), [handleDismiss]);
|
|
141
|
+
|
|
136
142
|
const listComponent = (
|
|
137
143
|
<GestureHandlerRootView>
|
|
138
144
|
<GestureDetector gesture={gesture}>
|
|
@@ -174,7 +180,7 @@ export function GestureViewer<T = any, LC = typeof ScrollView>({
|
|
|
174
180
|
</GestureHandlerRootView>
|
|
175
181
|
);
|
|
176
182
|
|
|
177
|
-
return renderContainer ? renderContainer(listComponent) : listComponent;
|
|
183
|
+
return renderContainer ? renderContainer(listComponent, control) : listComponent;
|
|
178
184
|
}
|
|
179
185
|
|
|
180
186
|
const styles = StyleSheet.create({
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { View } from 'react-native';
|
|
1
2
|
import GestureViewerManager from './GestureViewerManager';
|
|
2
3
|
|
|
3
4
|
class GestureViewerRegistry {
|
|
4
5
|
private managers = new Map<string, GestureViewerManager>();
|
|
5
6
|
private subscribers = new Map<string, Set<(manager: GestureViewerManager | null) => void>>();
|
|
7
|
+
private triggers = new Map<string, View | null>();
|
|
6
8
|
|
|
7
9
|
subscribeToManager(id: string, callback: (manager: GestureViewerManager | null) => void) {
|
|
8
10
|
if (!this.subscribers.has(id)) {
|
|
@@ -51,6 +53,8 @@ class GestureViewerRegistry {
|
|
|
51
53
|
this.managers.delete(id);
|
|
52
54
|
|
|
53
55
|
this.notifySubscribers(id, null);
|
|
56
|
+
|
|
57
|
+
this.triggers.delete(id);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
|
|
@@ -61,6 +65,18 @@ class GestureViewerRegistry {
|
|
|
61
65
|
[...listeners].forEach((callback) => callback(manager));
|
|
62
66
|
}
|
|
63
67
|
}
|
|
68
|
+
|
|
69
|
+
setTriggerNode(id: string, node: View | null) {
|
|
70
|
+
this.triggers.set(id, node);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getTriggerNode(id: string): View | null {
|
|
74
|
+
return this.triggers.get(id) ?? null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
clearTriggerNode(id: string) {
|
|
78
|
+
this.triggers.delete(id);
|
|
79
|
+
}
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
export const registry = new GestureViewerRegistry();
|
package/src/index.tsx
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { FlatList as RNFlatList, ScrollView as RNScrollView, StyleProp, ViewStyle } from 'react-native';
|
|
3
3
|
import type { FlatList as GHFlatList, ScrollView as GHScrollView } from 'react-native-gesture-handler';
|
|
4
|
+
import type { WithTimingConfig } from 'react-native-reanimated';
|
|
4
5
|
|
|
5
6
|
export type FlatListComponent = typeof RNFlatList | typeof GHFlatList;
|
|
6
7
|
export type ScrollViewComponent = typeof RNScrollView | typeof GHScrollView;
|
|
@@ -13,6 +14,30 @@ type ConditionalListProps<LC> = LC extends FlatListComponent
|
|
|
13
14
|
? React.ComponentProps<LC>
|
|
14
15
|
: GetComponentProps<LC>;
|
|
15
16
|
|
|
17
|
+
export type TriggerRect = {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export interface TriggerAnimationConfig extends WithTimingConfig {
|
|
25
|
+
/**
|
|
26
|
+
* Animation duration in milliseconds
|
|
27
|
+
* @defaultValue 300
|
|
28
|
+
*/
|
|
29
|
+
duration?: WithTimingConfig['duration'];
|
|
30
|
+
/**
|
|
31
|
+
* Animation easing function
|
|
32
|
+
* @defaultValue Easing.bezier(0.25, 0.1, 0.25, 1.0)
|
|
33
|
+
*/
|
|
34
|
+
easing?: WithTimingConfig['easing'];
|
|
35
|
+
/**
|
|
36
|
+
* Callback function called after animation completion
|
|
37
|
+
*/
|
|
38
|
+
onAnimationComplete?: () => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
17
42
|
/**
|
|
18
43
|
* When you want to efficiently manage multiple `GestureViewer` instances, you can use the `id` prop to use multiple `GestureViewer` components.
|
|
@@ -33,14 +58,25 @@ export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
|
33
58
|
* A callback function that is called when the `GestureViewer` is dismissed.
|
|
34
59
|
*/
|
|
35
60
|
onDismiss?: () => void;
|
|
61
|
+
/**
|
|
62
|
+
* A callback function that is called when the dismiss interaction starts.
|
|
63
|
+
* @remarks Useful to hide external UI (e.g., headers, buttons) while the dismiss gesture/animation is in progress.
|
|
64
|
+
*/
|
|
65
|
+
onDismissStart?: () => void;
|
|
36
66
|
/**
|
|
37
67
|
* A callback function that is called to render the item.
|
|
38
68
|
*/
|
|
39
69
|
renderItem: (item: T, index: number) => React.ReactElement;
|
|
40
70
|
/**
|
|
41
71
|
* A callback function that is called to render the container.
|
|
72
|
+
* @remarks Useful for composing additional UI (e.g., close button, toolbars) around the viewer.
|
|
73
|
+
* The second argument provides control helpers such as `dismiss()` to close the viewer.
|
|
74
|
+
*
|
|
75
|
+
* @param children - The viewer content to be rendered inside your container.
|
|
76
|
+
* @param helpers - Control helpers for the viewer. Currently includes `dismiss()`.
|
|
77
|
+
* @returns A React element that wraps and renders the provided `children`.
|
|
42
78
|
*/
|
|
43
|
-
renderContainer?: (children: React.ReactElement) => React.ReactElement;
|
|
79
|
+
renderContainer?: (children: React.ReactElement, helpers: { dismiss: () => void }) => React.ReactElement;
|
|
44
80
|
/**
|
|
45
81
|
* Support for any list component like `ScrollView`, `FlatList`, `FlashList` through the `ListComponent` prop.
|
|
46
82
|
*/
|
|
@@ -145,6 +181,25 @@ export interface GestureViewerProps<T = any, LC = typeof RNScrollView> {
|
|
|
145
181
|
* @defaultValue 2
|
|
146
182
|
*/
|
|
147
183
|
maxZoomScale?: number;
|
|
184
|
+
/**
|
|
185
|
+
* Trigger-based animation settings
|
|
186
|
+
* @remarks You can customize animation duration, easing, and system reduce-motion behavior.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```tsx
|
|
190
|
+
* <GestureViewer
|
|
191
|
+
* triggerAnimation={{
|
|
192
|
+
* duration: 250,
|
|
193
|
+
* easing: Easing.out(Easing.cubic),
|
|
194
|
+
* reduceMotion: 'system',
|
|
195
|
+
* onAnimationComplete: () => {
|
|
196
|
+
* console.log('Animation complete');
|
|
197
|
+
* },
|
|
198
|
+
* }}
|
|
199
|
+
* />
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
triggerAnimation?: TriggerAnimationConfig;
|
|
148
203
|
}
|
|
149
204
|
|
|
150
205
|
/**
|