react-native-gesture-image-viewer 2.1.4 → 2.2.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/lib/module/GestureTrigger.js +22 -5
- package/lib/module/GestureTrigger.js.map +1 -1
- package/lib/module/GestureViewerRegistry.js +52 -8
- package/lib/module/GestureViewerRegistry.js.map +1 -1
- package/lib/module/useGestureViewer.js +83 -28
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/module/useGestureViewerPaging.js +15 -1
- package/lib/module/useGestureViewerPaging.js.map +1 -1
- package/lib/module/useGestureViewerPaging.web.js +15 -2
- package/lib/module/useGestureViewerPaging.web.js.map +1 -1
- package/lib/typescript/src/GestureTrigger.d.ts +9 -3
- package/lib/typescript/src/GestureTrigger.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerRegistry.d.ts +11 -4
- package/lib/typescript/src/GestureViewerRegistry.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerPaging.d.ts +1 -1
- package/lib/typescript/src/useGestureViewerPaging.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts +1 -0
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts +1 -1
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/GestureTrigger.tsx +31 -6
- package/src/GestureViewerRegistry.ts +67 -8
- package/src/useGestureViewer.ts +112 -35
- package/src/useGestureViewerPaging.ts +17 -1
- package/src/useGestureViewerPaging.types.ts +1 -0
- package/src/useGestureViewerPaging.web.ts +21 -1
|
@@ -12,11 +12,13 @@ type WithOnPress = {
|
|
|
12
12
|
* @typeParam T - The child's props type. Must include an optional `onPress` handler.
|
|
13
13
|
*
|
|
14
14
|
* @property id - Optional identifier to associate this trigger with a `GestureViewer`.
|
|
15
|
+
* @property index - Optional item index used to align dismiss animations with the current viewer index.
|
|
15
16
|
* @property children - A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`).
|
|
16
17
|
* @property onPress - Optional handler invoked after the child's own `onPress`.
|
|
17
18
|
*/
|
|
18
19
|
export type GestureTriggerProps<T extends WithOnPress> = {
|
|
19
20
|
id?: string;
|
|
21
|
+
index?: number;
|
|
20
22
|
children: ReactElement<T>;
|
|
21
23
|
onPress?: (...args: unknown[]) => void;
|
|
22
24
|
};
|
|
@@ -25,15 +27,19 @@ export type GestureTriggerProps<T extends WithOnPress> = {
|
|
|
25
27
|
*
|
|
26
28
|
* @remarks
|
|
27
29
|
* Behavior on press:
|
|
28
|
-
* - Registers the child's native node
|
|
30
|
+
* - Registers the child's native node as the active trigger under the given `id`.
|
|
29
31
|
* - Invokes the child's own `onPress` first (if provided).
|
|
30
32
|
* - Invokes the `onPress` passed to `GestureTrigger` next (if provided).
|
|
31
33
|
*
|
|
34
|
+
* When `index` is provided, the trigger is also registered by item index while mounted,
|
|
35
|
+
* allowing dismiss animations to target the currently visible item instead of only the opening trigger.
|
|
36
|
+
*
|
|
32
37
|
* Type parameters:
|
|
33
38
|
* - `T` — The child's props type. Must include an optional `onPress` handler, ensuring the child is pressable.
|
|
34
39
|
*
|
|
35
40
|
* Props:
|
|
36
41
|
* - `id` — Optional identifier to associate this trigger with a `GestureViewer`. Defaults to `"default"`.
|
|
42
|
+
* - `index` — Optional item index used to support dismiss animations back to the current item trigger.
|
|
37
43
|
* - `children` — A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`, custom button).
|
|
38
44
|
* - `onPress` — Optional handler invoked after the child's `onPress`. Receives the same arguments as the child's handler.
|
|
39
45
|
*
|
|
@@ -43,13 +49,13 @@ export type GestureTriggerProps<T extends WithOnPress> = {
|
|
|
43
49
|
*
|
|
44
50
|
* Example:
|
|
45
51
|
* ```tsx
|
|
46
|
-
* <GestureTrigger id="gallery" onPress={() => openModal(index)}>
|
|
52
|
+
* <GestureTrigger id="gallery" index={index} onPress={() => openModal(index)}>
|
|
47
53
|
* <Pressable style={styles.thumb}>
|
|
48
54
|
* <Image source={{ uri }} style={styles.thumbImage} />
|
|
49
55
|
* </Pressable>
|
|
50
56
|
* </GestureTrigger>
|
|
51
57
|
* ```
|
|
52
58
|
*/
|
|
53
|
-
export declare function GestureTrigger<T extends WithOnPress>({ id, children, onPress, }: GestureTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
export declare function GestureTrigger<T extends WithOnPress>({ id, index, children, onPress, }: GestureTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
54
60
|
export {};
|
|
55
61
|
//# sourceMappingURL=GestureTrigger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureTrigger.d.ts","sourceRoot":"","sources":["../../../src/GestureTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAM1C;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,CAAC;AAE9D
|
|
1
|
+
{"version":3,"file":"GestureTrigger.d.ts","sourceRoot":"","sources":["../../../src/GestureTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAM1C;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,IAAI;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,EAAE,EACpD,EAAc,EACd,KAAK,EACL,QAAQ,EACR,OAAO,GACR,EAAE,mBAAmB,CAAC,CAAC,CAAC,2CAqDxB"}
|
|
@@ -3,15 +3,22 @@ import GestureViewerManager from './GestureViewerManager';
|
|
|
3
3
|
declare class GestureViewerRegistry {
|
|
4
4
|
private managers;
|
|
5
5
|
private subscribers;
|
|
6
|
-
private
|
|
6
|
+
private activeTriggerSubscribers;
|
|
7
|
+
private activeTriggers;
|
|
8
|
+
private indexedTriggers;
|
|
7
9
|
subscribeToManager(id: string, callback: (manager: GestureViewerManager | null) => void): () => void;
|
|
10
|
+
subscribeToActiveTrigger(id: string, callback: (node: View | null) => void): () => void;
|
|
8
11
|
createManager(id: string): GestureViewerManager | null;
|
|
9
12
|
getManager(id: string): GestureViewerManager | null;
|
|
10
13
|
deleteManager(id: string): void;
|
|
11
14
|
notifySubscribers(id: string, manager: GestureViewerManager | null): void;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
notifyActiveTriggerSubscribers(id: string, node: View | null): void;
|
|
16
|
+
setActiveTriggerNode(id: string, node: View | null): void;
|
|
17
|
+
getActiveTriggerNode(id: string): View | null;
|
|
18
|
+
clearActiveTriggerNode(id: string): void;
|
|
19
|
+
setIndexedTriggerNode(id: string, index: number, node: View | null): void;
|
|
20
|
+
getIndexedTriggerNode(id: string, index: number): View | null;
|
|
21
|
+
clearIndexedTriggerNode(id: string, index: number): void;
|
|
15
22
|
}
|
|
16
23
|
export declare const registry: GestureViewerRegistry;
|
|
17
24
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GestureViewerRegistry.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,cAAM,qBAAqB;IACzB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAA0E;IAC7F,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"GestureViewerRegistry.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,cAAM,qBAAqB;IACzB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAA0E;IAC7F,OAAO,CAAC,wBAAwB,CAAuD;IACvF,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,eAAe,CAA+C;IAEtE,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI;IAsBvF,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI;IAoB1E,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;IAcxB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAQlE,8BAA8B,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAQ5D,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAKlD,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7C,sBAAsB,CAAC,EAAE,EAAE,MAAM;IAKjC,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAQlE,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7D,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAalD;AAED,eAAO,MAAM,QAAQ,uBAA8B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAK/D,KAAK,qBAAqB,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAC1C,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,EAC3B,YAAY,GACZ,iBAAiB,GACjB,eAAe,GACf,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,gBAAgB,CACnB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,EAAE,EAAE,kRAmBzC,qBAAqB,CAAC,KAAK,EAAE,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAK/D,KAAK,qBAAqB,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAC1C,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,EAC3B,YAAY,GACZ,iBAAiB,GACjB,eAAe,GACf,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,gBAAgB,CACnB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,EAAE,EAAE,kRAmBzC,qBAAqB,CAAC,KAAK,EAAE,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyrBlC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { UseGestureViewerPagingArgs, UseGestureViewerPagingResult } from './useGestureViewerPaging.types';
|
|
2
|
-
export declare function useGestureViewerPaging({ autoPlay, autoPlayInterval, currentIndex, dataLength, enableHorizontalSwipe, enableLoop, isRotated, isZoomed, itemSpacing, manager, scrollTo, syncCurrentIndex, width, }: UseGestureViewerPagingArgs): UseGestureViewerPagingResult;
|
|
2
|
+
export declare function useGestureViewerPaging({ autoPlay, autoPlayInterval, currentIndex, dataLength, enableHorizontalSwipe, enableLoop, isRotated, isZoomed, itemSpacing, manager, scrollTo, syncCurrentIndex, syncPendingIndex, width, }: UseGestureViewerPagingArgs): UseGestureViewerPagingResult;
|
|
3
3
|
//# sourceMappingURL=useGestureViewerPaging.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGestureViewerPaging.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAC;AAGxC,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,KAAK,GACN,EAAE,0BAA0B,GAAG,4BAA4B,
|
|
1
|
+
{"version":3,"file":"useGestureViewerPaging.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAC;AAGxC,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,GACN,EAAE,0BAA0B,GAAG,4BAA4B,CAuG3D"}
|
|
@@ -19,6 +19,7 @@ export type UseGestureViewerPagingArgs = {
|
|
|
19
19
|
scale: SharedValue<number>;
|
|
20
20
|
scrollTo: (index: number, animated: boolean) => void;
|
|
21
21
|
syncCurrentIndex: (nextIndex: number) => void;
|
|
22
|
+
syncPendingIndex: (nextIndex: number) => void;
|
|
22
23
|
translateX: SharedValue<number>;
|
|
23
24
|
translateY: SharedValue<number>;
|
|
24
25
|
width: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGestureViewerPaging.types.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,oBAAoB,MAAM,wBAAwB,CAAC;AAE/D,MAAM,MAAM,0BAA0B,GAAG;IACvC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,mBAAmB,CAAC,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACvC,iBAAiB,CAAC,EAAE,eAAe,CAAC,mBAAmB,CAAC,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACzC,CAAC"}
|
|
1
|
+
{"version":3,"file":"useGestureViewerPaging.types.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,oBAAoB,MAAM,wBAAwB,CAAC;AAE/D,MAAM,MAAM,0BAA0B,GAAG;IACvC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,mBAAmB,CAAC,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACvC,iBAAiB,CAAC,EAAE,eAAe,CAAC,mBAAmB,CAAC,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACzC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { UseGestureViewerPagingArgs, UseGestureViewerPagingResult } from './useGestureViewerPaging.types';
|
|
2
|
-
export declare function useGestureViewerPaging({ adjustedInitialIndex, autoPlay, autoPlayInterval, currentIndex, dataLength, enableDoubleTapZoom, enableHorizontalSwipe, enableLoop, height, isRotated, isZoomed, itemSpacing, manager, maxZoomScale, scale, scrollTo, syncCurrentIndex, translateX, translateY, width, }: UseGestureViewerPagingArgs): UseGestureViewerPagingResult;
|
|
2
|
+
export declare function useGestureViewerPaging({ adjustedInitialIndex, autoPlay, autoPlayInterval, currentIndex, dataLength, enableDoubleTapZoom, enableHorizontalSwipe, enableLoop, height, isRotated, isZoomed, itemSpacing, manager, maxZoomScale, scale, scrollTo, syncCurrentIndex, syncPendingIndex, translateX, translateY, width, }: UseGestureViewerPagingArgs): UseGestureViewerPagingResult;
|
|
3
3
|
//# sourceMappingURL=useGestureViewerPaging.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGestureViewerPaging.web.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.web.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAC;AAqBxC,wBAAgB,sBAAsB,CAAC,EACrC,oBAAoB,EACpB,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,0BAA0B,GAAG,4BAA4B,
|
|
1
|
+
{"version":3,"file":"useGestureViewerPaging.web.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.web.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAC;AAqBxC,wBAAgB,sBAAsB,CAAC,EACrC,oBAAoB,EACpB,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,0BAA0B,GAAG,4BAA4B,CAwW3D"}
|
package/package.json
CHANGED
package/src/GestureTrigger.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
|
-
import { Children, cloneElement, isValidElement, useMemo, useRef } from 'react';
|
|
2
|
+
import { Children, cloneElement, isValidElement, useCallback, useMemo, useRef } from 'react';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import { registry } from './GestureViewerRegistry';
|
|
@@ -16,11 +16,13 @@ type WithOnPress = { onPress?: (...args: unknown[]) => void };
|
|
|
16
16
|
* @typeParam T - The child's props type. Must include an optional `onPress` handler.
|
|
17
17
|
*
|
|
18
18
|
* @property id - Optional identifier to associate this trigger with a `GestureViewer`.
|
|
19
|
+
* @property index - Optional item index used to align dismiss animations with the current viewer index.
|
|
19
20
|
* @property children - A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`).
|
|
20
21
|
* @property onPress - Optional handler invoked after the child's own `onPress`.
|
|
21
22
|
*/
|
|
22
23
|
export type GestureTriggerProps<T extends WithOnPress> = {
|
|
23
24
|
id?: string;
|
|
25
|
+
index?: number;
|
|
24
26
|
children: ReactElement<T>;
|
|
25
27
|
onPress?: (...args: unknown[]) => void;
|
|
26
28
|
};
|
|
@@ -30,15 +32,19 @@ export type GestureTriggerProps<T extends WithOnPress> = {
|
|
|
30
32
|
*
|
|
31
33
|
* @remarks
|
|
32
34
|
* Behavior on press:
|
|
33
|
-
* - Registers the child's native node
|
|
35
|
+
* - Registers the child's native node as the active trigger under the given `id`.
|
|
34
36
|
* - Invokes the child's own `onPress` first (if provided).
|
|
35
37
|
* - Invokes the `onPress` passed to `GestureTrigger` next (if provided).
|
|
36
38
|
*
|
|
39
|
+
* When `index` is provided, the trigger is also registered by item index while mounted,
|
|
40
|
+
* allowing dismiss animations to target the currently visible item instead of only the opening trigger.
|
|
41
|
+
*
|
|
37
42
|
* Type parameters:
|
|
38
43
|
* - `T` — The child's props type. Must include an optional `onPress` handler, ensuring the child is pressable.
|
|
39
44
|
*
|
|
40
45
|
* Props:
|
|
41
46
|
* - `id` — Optional identifier to associate this trigger with a `GestureViewer`. Defaults to `"default"`.
|
|
47
|
+
* - `index` — Optional item index used to support dismiss animations back to the current item trigger.
|
|
42
48
|
* - `children` — A single React element whose props include `onPress` (e.g., `Pressable`, `Touchable*`, custom button).
|
|
43
49
|
* - `onPress` — Optional handler invoked after the child's `onPress`. Receives the same arguments as the child's handler.
|
|
44
50
|
*
|
|
@@ -48,7 +54,7 @@ export type GestureTriggerProps<T extends WithOnPress> = {
|
|
|
48
54
|
*
|
|
49
55
|
* Example:
|
|
50
56
|
* ```tsx
|
|
51
|
-
* <GestureTrigger id="gallery" onPress={() => openModal(index)}>
|
|
57
|
+
* <GestureTrigger id="gallery" index={index} onPress={() => openModal(index)}>
|
|
52
58
|
* <Pressable style={styles.thumb}>
|
|
53
59
|
* <Image source={{ uri }} style={styles.thumbImage} />
|
|
54
60
|
* </Pressable>
|
|
@@ -57,10 +63,29 @@ export type GestureTriggerProps<T extends WithOnPress> = {
|
|
|
57
63
|
*/
|
|
58
64
|
export function GestureTrigger<T extends WithOnPress>({
|
|
59
65
|
id = 'default',
|
|
66
|
+
index,
|
|
60
67
|
children,
|
|
61
68
|
onPress,
|
|
62
69
|
}: GestureTriggerProps<T>) {
|
|
63
|
-
const ref = useRef<View>(null);
|
|
70
|
+
const ref = useRef<View | null>(null);
|
|
71
|
+
|
|
72
|
+
const handleRef = useCallback(
|
|
73
|
+
(node: View | null) => {
|
|
74
|
+
ref.current = node;
|
|
75
|
+
|
|
76
|
+
if (index === undefined) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (node) {
|
|
81
|
+
registry.setIndexedTriggerNode(id, index, node);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
registry.clearIndexedTriggerNode(id, index);
|
|
86
|
+
},
|
|
87
|
+
[id, index],
|
|
88
|
+
);
|
|
64
89
|
|
|
65
90
|
const wrapped = useMemo(() => {
|
|
66
91
|
const child = Children.only(children);
|
|
@@ -72,7 +97,7 @@ export function GestureTrigger<T extends WithOnPress>({
|
|
|
72
97
|
const originalOnPress = child.props?.onPress;
|
|
73
98
|
|
|
74
99
|
const handlePress = (...args: unknown[]) => {
|
|
75
|
-
registry.
|
|
100
|
+
registry.setActiveTriggerNode(id, ref.current);
|
|
76
101
|
originalOnPress?.(...args);
|
|
77
102
|
onPress?.(...args);
|
|
78
103
|
|
|
@@ -90,7 +115,7 @@ export function GestureTrigger<T extends WithOnPress>({
|
|
|
90
115
|
}, [id, onPress, children]);
|
|
91
116
|
|
|
92
117
|
return (
|
|
93
|
-
<View ref={
|
|
118
|
+
<View ref={handleRef} collapsable={false}>
|
|
94
119
|
{wrapped}
|
|
95
120
|
</View>
|
|
96
121
|
);
|
|
@@ -5,7 +5,9 @@ import GestureViewerManager from './GestureViewerManager';
|
|
|
5
5
|
class GestureViewerRegistry {
|
|
6
6
|
private managers = new Map<string, GestureViewerManager>();
|
|
7
7
|
private subscribers = new Map<string, Set<(manager: GestureViewerManager | null) => void>>();
|
|
8
|
-
private
|
|
8
|
+
private activeTriggerSubscribers = new Map<string, Set<(node: View | null) => void>>();
|
|
9
|
+
private activeTriggers = new Map<string, View | null>();
|
|
10
|
+
private indexedTriggers = new Map<string, Map<number, View | null>>();
|
|
9
11
|
|
|
10
12
|
subscribeToManager(id: string, callback: (manager: GestureViewerManager | null) => void) {
|
|
11
13
|
if (!this.subscribers.has(id)) {
|
|
@@ -29,6 +31,26 @@ class GestureViewerRegistry {
|
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
subscribeToActiveTrigger(id: string, callback: (node: View | null) => void) {
|
|
35
|
+
if (!this.activeTriggerSubscribers.has(id)) {
|
|
36
|
+
this.activeTriggerSubscribers.set(id, new Set());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.activeTriggerSubscribers.get(id)?.add(callback);
|
|
40
|
+
|
|
41
|
+
callback(this.getActiveTriggerNode(id));
|
|
42
|
+
|
|
43
|
+
return () => {
|
|
44
|
+
const subscribers = this.activeTriggerSubscribers.get(id);
|
|
45
|
+
|
|
46
|
+
subscribers?.delete(callback);
|
|
47
|
+
|
|
48
|
+
if (subscribers && subscribers.size === 0) {
|
|
49
|
+
this.activeTriggerSubscribers.delete(id);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
createManager(id: string): GestureViewerManager | null {
|
|
33
55
|
if (this.managers.has(id)) {
|
|
34
56
|
return this.managers.get(id) || null;
|
|
@@ -55,7 +77,8 @@ class GestureViewerRegistry {
|
|
|
55
77
|
|
|
56
78
|
this.notifySubscribers(id, null);
|
|
57
79
|
|
|
58
|
-
this.
|
|
80
|
+
this.activeTriggers.delete(id);
|
|
81
|
+
this.notifyActiveTriggerSubscribers(id, null);
|
|
59
82
|
}
|
|
60
83
|
}
|
|
61
84
|
|
|
@@ -67,16 +90,52 @@ class GestureViewerRegistry {
|
|
|
67
90
|
}
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
|
|
71
|
-
this.
|
|
93
|
+
notifyActiveTriggerSubscribers(id: string, node: View | null) {
|
|
94
|
+
const listeners = this.activeTriggerSubscribers.get(id);
|
|
95
|
+
|
|
96
|
+
if (listeners) {
|
|
97
|
+
[...listeners].forEach((callback) => callback(node));
|
|
98
|
+
}
|
|
72
99
|
}
|
|
73
100
|
|
|
74
|
-
|
|
75
|
-
|
|
101
|
+
setActiveTriggerNode(id: string, node: View | null) {
|
|
102
|
+
this.activeTriggers.set(id, node);
|
|
103
|
+
this.notifyActiveTriggerSubscribers(id, node);
|
|
76
104
|
}
|
|
77
105
|
|
|
78
|
-
|
|
79
|
-
this.
|
|
106
|
+
getActiveTriggerNode(id: string): View | null {
|
|
107
|
+
return this.activeTriggers.get(id) ?? null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
clearActiveTriggerNode(id: string) {
|
|
111
|
+
this.activeTriggers.delete(id);
|
|
112
|
+
this.notifyActiveTriggerSubscribers(id, null);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
setIndexedTriggerNode(id: string, index: number, node: View | null) {
|
|
116
|
+
if (!this.indexedTriggers.has(id)) {
|
|
117
|
+
this.indexedTriggers.set(id, new Map());
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.indexedTriggers.get(id)?.set(index, node);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getIndexedTriggerNode(id: string, index: number): View | null {
|
|
124
|
+
return this.indexedTriggers.get(id)?.get(index) ?? null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
clearIndexedTriggerNode(id: string, index: number) {
|
|
128
|
+
const triggersByIndex = this.indexedTriggers.get(id);
|
|
129
|
+
|
|
130
|
+
if (!triggersByIndex) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
triggersByIndex.delete(index);
|
|
135
|
+
|
|
136
|
+
if (triggersByIndex.size === 0) {
|
|
137
|
+
this.indexedTriggers.delete(id);
|
|
138
|
+
}
|
|
80
139
|
}
|
|
81
140
|
}
|
|
82
141
|
|
package/src/useGestureViewer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { InteractionManager, Platform, useWindowDimensions } from 'react-native';
|
|
2
|
+
import { InteractionManager, Platform, type View, useWindowDimensions } from 'react-native';
|
|
3
3
|
import { Gesture, type GestureType } from 'react-native-gesture-handler';
|
|
4
4
|
import {
|
|
5
5
|
Easing,
|
|
@@ -62,11 +62,17 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
62
62
|
const [shouldStartTriggerAnimation, setShouldStartTriggerAnimation] = useState(false);
|
|
63
63
|
const [manager, setManager] = useState<GestureViewerManager | null>(null);
|
|
64
64
|
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
65
|
+
const [activeTriggerNode, setActiveTriggerNode] = useState<View | null>(null);
|
|
65
66
|
|
|
66
67
|
const listRef = useRef<any>(null);
|
|
67
68
|
const triggerRectRef = useRef<TriggerRect | null>(null);
|
|
69
|
+
const pendingIndexRef = useRef(initialIndex);
|
|
68
70
|
const onAnimationCompleteRef = useRef(triggerAnimation?.onAnimationComplete);
|
|
69
71
|
|
|
72
|
+
const isValidTriggerRect = useCallback((rect: TriggerRect | null): rect is TriggerRect => {
|
|
73
|
+
return !!rect && rect.width > 0 && rect.height > 0;
|
|
74
|
+
}, []);
|
|
75
|
+
|
|
70
76
|
const initialTranslateY = useSharedValue(0);
|
|
71
77
|
const initialTranslateX = useSharedValue(0);
|
|
72
78
|
const startScale = useSharedValue(1);
|
|
@@ -138,12 +144,25 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
138
144
|
rotation.value = 0;
|
|
139
145
|
}, [initialTranslateX, initialTranslateY, rotation, scale, startScale, translateX, translateY]);
|
|
140
146
|
|
|
147
|
+
const syncPendingIndex = useCallback(
|
|
148
|
+
(nextIndex: number) => {
|
|
149
|
+
if (nextIndex < 0 || nextIndex >= dataLength) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
pendingIndexRef.current = nextIndex;
|
|
154
|
+
},
|
|
155
|
+
[dataLength],
|
|
156
|
+
);
|
|
157
|
+
|
|
141
158
|
const syncCurrentIndex = useCallback(
|
|
142
159
|
(nextIndex: number) => {
|
|
143
160
|
if (!manager || nextIndex < 0 || nextIndex >= dataLength) {
|
|
144
161
|
return;
|
|
145
162
|
}
|
|
146
163
|
|
|
164
|
+
pendingIndexRef.current = nextIndex;
|
|
165
|
+
|
|
147
166
|
const managerCurrentIndex = manager.getState().currentIndex;
|
|
148
167
|
|
|
149
168
|
if (nextIndex === managerCurrentIndex) {
|
|
@@ -206,7 +225,10 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
206
225
|
|
|
207
226
|
const unsubscribeFromRegistry = registry.subscribeToManager(id, (managerInstance) => {
|
|
208
227
|
setManager(managerInstance);
|
|
209
|
-
unsubscribe = managerInstance?.subscribe((state) =>
|
|
228
|
+
unsubscribe = managerInstance?.subscribe((state) => {
|
|
229
|
+
pendingIndexRef.current = state.currentIndex;
|
|
230
|
+
setCurrentIndex(state.currentIndex);
|
|
231
|
+
});
|
|
210
232
|
});
|
|
211
233
|
|
|
212
234
|
return () => {
|
|
@@ -216,6 +238,12 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
216
238
|
}, [id]);
|
|
217
239
|
|
|
218
240
|
useEffect(() => {
|
|
241
|
+
return registry.subscribeToActiveTrigger(id, setActiveTriggerNode);
|
|
242
|
+
}, [id]);
|
|
243
|
+
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
pendingIndexRef.current = initialIndex;
|
|
246
|
+
|
|
219
247
|
if (!manager) {
|
|
220
248
|
return;
|
|
221
249
|
}
|
|
@@ -331,32 +359,41 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
331
359
|
]);
|
|
332
360
|
|
|
333
361
|
useEffect(() => {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (node && typeof node.measure === 'function') {
|
|
337
|
-
node.measure((_x, _y, width, height, pageX, pageY) => {
|
|
338
|
-
triggerRectRef.current = { height, width, x: pageX, y: pageY };
|
|
339
|
-
triggerOpacity.value = 0;
|
|
340
|
-
setShouldStartTriggerAnimation(true);
|
|
341
|
-
registry.clearTriggerNode(id);
|
|
342
|
-
});
|
|
362
|
+
if (!activeTriggerNode || typeof activeTriggerNode.measure !== 'function') {
|
|
363
|
+
return;
|
|
343
364
|
}
|
|
344
365
|
|
|
366
|
+
activeTriggerNode.measure((_x, _y, measuredWidth, measuredHeight, pageX, pageY) => {
|
|
367
|
+
const nextTriggerRect = {
|
|
368
|
+
height: measuredHeight,
|
|
369
|
+
width: measuredWidth,
|
|
370
|
+
x: pageX,
|
|
371
|
+
y: pageY,
|
|
372
|
+
} satisfies TriggerRect;
|
|
373
|
+
|
|
374
|
+
if (!isValidTriggerRect(nextTriggerRect)) {
|
|
375
|
+
registry.clearActiveTriggerNode(id);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
triggerRectRef.current = nextTriggerRect;
|
|
380
|
+
triggerOpacity.value = 0;
|
|
381
|
+
setShouldStartTriggerAnimation(true);
|
|
382
|
+
registry.clearActiveTriggerNode(id);
|
|
383
|
+
});
|
|
384
|
+
}, [activeTriggerNode, id, isValidTriggerRect, triggerOpacity]);
|
|
385
|
+
|
|
386
|
+
useEffect(() => {
|
|
345
387
|
return () => {
|
|
346
388
|
triggerRectRef.current = null;
|
|
347
389
|
};
|
|
348
|
-
}, [
|
|
349
|
-
|
|
350
|
-
const handleDismiss = useCallback(() => {
|
|
351
|
-
onDismissStart?.();
|
|
390
|
+
}, []);
|
|
352
391
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
triggerRectRef.current.height / height,
|
|
359
|
-
);
|
|
392
|
+
const animateDismissToRect = useCallback(
|
|
393
|
+
(rect: TriggerRect) => {
|
|
394
|
+
const endX = rect.x + rect.width / 2 - width / 2;
|
|
395
|
+
const endY = rect.y + rect.height / 2 - height / 2;
|
|
396
|
+
const endScale = Math.min(rect.width / width, rect.height / height);
|
|
360
397
|
|
|
361
398
|
triggerScale.value = withTiming(endScale, animationConfig);
|
|
362
399
|
triggerTranslateX.value = withTiming(endX, animationConfig);
|
|
@@ -366,23 +403,62 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
366
403
|
scheduleOnRN(onDismiss);
|
|
367
404
|
}
|
|
368
405
|
});
|
|
369
|
-
|
|
370
|
-
|
|
406
|
+
},
|
|
407
|
+
[
|
|
408
|
+
animationConfig,
|
|
409
|
+
height,
|
|
410
|
+
onDismiss,
|
|
411
|
+
triggerOpacity,
|
|
412
|
+
triggerScale,
|
|
413
|
+
triggerTranslateX,
|
|
414
|
+
triggerTranslateY,
|
|
415
|
+
width,
|
|
416
|
+
],
|
|
417
|
+
);
|
|
371
418
|
|
|
419
|
+
const dismissWithoutTrigger = useCallback(() => {
|
|
372
420
|
if (onDismiss) {
|
|
373
421
|
scheduleOnRN(onDismiss);
|
|
374
422
|
}
|
|
375
|
-
}, [
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
onDismissStart
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
423
|
+
}, [onDismiss]);
|
|
424
|
+
|
|
425
|
+
const handleDismiss = useCallback(() => {
|
|
426
|
+
onDismissStart?.();
|
|
427
|
+
|
|
428
|
+
const dismissTargetIndex = pendingIndexRef.current;
|
|
429
|
+
const indexedTriggerNode = registry.getIndexedTriggerNode(id, dismissTargetIndex);
|
|
430
|
+
|
|
431
|
+
if (indexedTriggerNode && typeof indexedTriggerNode.measure === 'function') {
|
|
432
|
+
indexedTriggerNode.measure((_x, _y, measuredWidth, measuredHeight, pageX, pageY) => {
|
|
433
|
+
const currentTriggerRect = {
|
|
434
|
+
height: measuredHeight,
|
|
435
|
+
width: measuredWidth,
|
|
436
|
+
x: pageX,
|
|
437
|
+
y: pageY,
|
|
438
|
+
} satisfies TriggerRect;
|
|
439
|
+
|
|
440
|
+
if (isValidTriggerRect(currentTriggerRect)) {
|
|
441
|
+
animateDismissToRect(currentTriggerRect);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (isValidTriggerRect(triggerRectRef.current)) {
|
|
446
|
+
animateDismissToRect(triggerRectRef.current);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
dismissWithoutTrigger();
|
|
451
|
+
});
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (isValidTriggerRect(triggerRectRef.current)) {
|
|
456
|
+
animateDismissToRect(triggerRectRef.current);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
dismissWithoutTrigger();
|
|
461
|
+
}, [animateDismissToRect, dismissWithoutTrigger, id, isValidTriggerRect, onDismissStart]);
|
|
386
462
|
|
|
387
463
|
const dismissGesture = useMemo(() => {
|
|
388
464
|
const canDismiss = !isZoomed && dismissOptions.enabled;
|
|
@@ -645,6 +721,7 @@ export const useGestureViewer = <ItemT, LC>({
|
|
|
645
721
|
scale,
|
|
646
722
|
scrollTo,
|
|
647
723
|
syncCurrentIndex,
|
|
724
|
+
syncPendingIndex,
|
|
648
725
|
translateX,
|
|
649
726
|
translateY,
|
|
650
727
|
width,
|
|
@@ -20,6 +20,7 @@ export function useGestureViewerPaging({
|
|
|
20
20
|
manager,
|
|
21
21
|
scrollTo,
|
|
22
22
|
syncCurrentIndex,
|
|
23
|
+
syncPendingIndex,
|
|
23
24
|
width,
|
|
24
25
|
}: UseGestureViewerPagingArgs): UseGestureViewerPagingResult {
|
|
25
26
|
useEffect(() => {
|
|
@@ -99,13 +100,28 @@ export function useGestureViewerPaging({
|
|
|
99
100
|
],
|
|
100
101
|
);
|
|
101
102
|
|
|
103
|
+
const onScroll = useCallback(
|
|
104
|
+
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
105
|
+
if (!enableHorizontalSwipe) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const { contentOffset } = event.nativeEvent;
|
|
110
|
+
const scrollIndex = Math.round(contentOffset.x / (width + itemSpacing));
|
|
111
|
+
const { realIndex } = getLoopAdjustedIndex(scrollIndex, dataLength, enableLoop);
|
|
112
|
+
|
|
113
|
+
syncPendingIndex(realIndex);
|
|
114
|
+
},
|
|
115
|
+
[dataLength, enableHorizontalSwipe, enableLoop, itemSpacing, syncPendingIndex, width],
|
|
116
|
+
);
|
|
117
|
+
|
|
102
118
|
const onScrollBeginDrag = useCallback(() => {
|
|
103
119
|
manager?.handleScrollBeginDrag();
|
|
104
120
|
}, [manager]);
|
|
105
121
|
|
|
106
122
|
return {
|
|
107
123
|
onMomentumScrollEnd,
|
|
108
|
-
onScroll
|
|
124
|
+
onScroll,
|
|
109
125
|
onScrollBeginDrag,
|
|
110
126
|
onWebDoubleClick: undefined,
|
|
111
127
|
};
|
|
@@ -21,6 +21,7 @@ export type UseGestureViewerPagingArgs = {
|
|
|
21
21
|
scale: SharedValue<number>;
|
|
22
22
|
scrollTo: (index: number, animated: boolean) => void;
|
|
23
23
|
syncCurrentIndex: (nextIndex: number) => void;
|
|
24
|
+
syncPendingIndex: (nextIndex: number) => void;
|
|
24
25
|
translateX: SharedValue<number>;
|
|
25
26
|
translateY: SharedValue<number>;
|
|
26
27
|
width: number;
|
|
@@ -43,6 +43,7 @@ export function useGestureViewerPaging({
|
|
|
43
43
|
scale,
|
|
44
44
|
scrollTo,
|
|
45
45
|
syncCurrentIndex,
|
|
46
|
+
syncPendingIndex,
|
|
46
47
|
translateX,
|
|
47
48
|
translateY,
|
|
48
49
|
width,
|
|
@@ -302,15 +303,34 @@ export function useGestureViewerPaging({
|
|
|
302
303
|
return;
|
|
303
304
|
}
|
|
304
305
|
|
|
306
|
+
const offsetX = event.nativeEvent.contentOffset.x;
|
|
307
|
+
const runtime = webScrollRuntimeRef.current;
|
|
308
|
+
const pendingState = resolveWebScrollFinalState({
|
|
309
|
+
dataLength,
|
|
310
|
+
enableLoop,
|
|
311
|
+
lastSettledPhysicalIndex: runtime.lastSettledPhysicalIndex,
|
|
312
|
+
offsetX,
|
|
313
|
+
pageWidth: width + itemSpacing,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
if (pendingState) {
|
|
317
|
+
syncPendingIndex(pendingState.logicalIndex);
|
|
318
|
+
}
|
|
319
|
+
|
|
305
320
|
syncProgrammaticActorFromManager();
|
|
306
321
|
beginWebUserInteraction();
|
|
307
|
-
scheduleWebScrollSettle(
|
|
322
|
+
scheduleWebScrollSettle(offsetX);
|
|
308
323
|
},
|
|
309
324
|
[
|
|
310
325
|
beginWebUserInteraction,
|
|
326
|
+
dataLength,
|
|
311
327
|
enableHorizontalSwipe,
|
|
328
|
+
enableLoop,
|
|
329
|
+
itemSpacing,
|
|
312
330
|
scheduleWebScrollSettle,
|
|
331
|
+
syncPendingIndex,
|
|
313
332
|
syncProgrammaticActorFromManager,
|
|
333
|
+
width,
|
|
314
334
|
],
|
|
315
335
|
);
|
|
316
336
|
|