react-native-gesture-image-viewer 2.1.4 → 2.3.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 +6 -1
- package/lib/module/GestureTrigger.js +22 -5
- package/lib/module/GestureTrigger.js.map +1 -1
- package/lib/module/GestureViewer.js +2 -2
- package/lib/module/GestureViewer.js.map +1 -1
- package/lib/module/GestureViewerManager.js +3 -0
- package/lib/module/GestureViewerManager.js.map +1 -1
- package/lib/module/GestureViewerRegistry.js +52 -8
- package/lib/module/GestureViewerRegistry.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/useGestureViewer.js +141 -43
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/module/useGestureViewerEvent.js +15 -1
- package/lib/module/useGestureViewerEvent.js.map +1 -1
- package/lib/module/useGestureViewerPaging.js +16 -2
- package/lib/module/useGestureViewerPaging.js.map +1 -1
- package/lib/module/useGestureViewerPaging.web.js +62 -28
- package/lib/module/useGestureViewerPaging.web.js.map +1 -1
- package/lib/module/utils/dismiss.js +25 -0
- package/lib/module/utils/dismiss.js.map +1 -0
- package/lib/typescript/src/GestureTrigger.d.ts +9 -3
- package/lib/typescript/src/GestureTrigger.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerManager.d.ts +2 -1
- package/lib/typescript/src/GestureViewerManager.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/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +33 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts +2 -2
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerEvent.d.ts +15 -1
- package/lib/typescript/src/useGestureViewerEvent.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 +10 -1
- 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/lib/typescript/src/utils/dismiss.d.ts +4 -0
- package/lib/typescript/src/utils/dismiss.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/GestureTrigger.tsx +31 -6
- package/src/GestureViewer.tsx +4 -2
- package/src/GestureViewerManager.ts +4 -0
- package/src/GestureViewerRegistry.ts +67 -8
- package/src/index.tsx +1 -0
- package/src/types.ts +31 -4
- package/src/useGestureViewer.ts +219 -81
- package/src/useGestureViewerEvent.ts +15 -1
- package/src/useGestureViewerPaging.ts +18 -2
- package/src/useGestureViewerPaging.types.ts +8 -1
- package/src/useGestureViewerPaging.web.ts +77 -33
- package/src/utils/dismiss.ts +36 -0
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"useGestureViewerPaging.web.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerPaging.web.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAE7B,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,WAAW,EACX,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,CA8X3D"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GestureViewerDismissDirection } from '../types';
|
|
2
|
+
export declare const shouldDismissByDirection: (translationY: number, threshold: number, direction: GestureViewerDismissDirection) => boolean;
|
|
3
|
+
export declare const getDismissDistance: (translationY: number, direction: GestureViewerDismissDirection) => number;
|
|
4
|
+
//# sourceMappingURL=dismiss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dismiss.d.ts","sourceRoot":"","sources":["../../../../src/utils/dismiss.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAC;AAE9D,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,EACpB,WAAW,MAAM,EACjB,WAAW,6BAA6B,KACvC,OAYF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,cAAc,MAAM,EACpB,WAAW,6BAA6B,KACvC,MAYF,CAAC"}
|
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
|
);
|
package/src/GestureViewer.tsx
CHANGED
|
@@ -59,7 +59,7 @@ export function GestureViewer<ItemT, LC>({
|
|
|
59
59
|
dismissGesture,
|
|
60
60
|
zoomGesture,
|
|
61
61
|
nativeScrollGesture,
|
|
62
|
-
|
|
62
|
+
onWebClick,
|
|
63
63
|
onMomentumScrollEnd,
|
|
64
64
|
onScroll,
|
|
65
65
|
onScrollBeginDrag,
|
|
@@ -191,7 +191,9 @@ export function GestureViewer<ItemT, LC>({
|
|
|
191
191
|
<Animated.View style={[styles.background, backdropStyleProps, backdropStyle]} />
|
|
192
192
|
<Animated.View
|
|
193
193
|
style={[styles.content, animatedStyle]}
|
|
194
|
-
{...(Platform.OS === 'web' && {
|
|
194
|
+
{...(Platform.OS === 'web' && {
|
|
195
|
+
onClick: onWebClick,
|
|
196
|
+
})}
|
|
195
197
|
{...(Platform.OS === 'web' &&
|
|
196
198
|
isFlashListLike(Component) && { dataSet: { 'flash-list-paging-enabled-fix': true } })}
|
|
197
199
|
>
|
|
@@ -86,6 +86,10 @@ class GestureViewerManager {
|
|
|
86
86
|
this.emitEvent('rotationChange', { rotation, previousRotation });
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
emitTap = (data: GestureViewerEventData['tap']) => {
|
|
90
|
+
this.emitEvent('tap', data);
|
|
91
|
+
};
|
|
92
|
+
|
|
89
93
|
getState(): GestureViewerState {
|
|
90
94
|
return {
|
|
91
95
|
currentIndex: this.currentIndex,
|
|
@@ -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/index.tsx
CHANGED
|
@@ -8,6 +8,7 @@ export type {
|
|
|
8
8
|
GestureViewerEventType,
|
|
9
9
|
GestureViewerProps,
|
|
10
10
|
GestureViewerState,
|
|
11
|
+
GestureViewerSingleTapEvent,
|
|
11
12
|
} from './types';
|
|
12
13
|
export { useGestureViewerController } from './useGestureViewerController';
|
|
13
14
|
export { useGestureViewerEvent } from './useGestureViewerEvent';
|
package/src/types.ts
CHANGED
|
@@ -75,6 +75,15 @@ export type TriggerRect = {
|
|
|
75
75
|
height: number;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
+
export type GestureViewerSingleTapEvent<ItemT> = {
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
index: number;
|
|
82
|
+
item: ItemT;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export type GestureViewerDismissDirection = 'down' | 'up' | 'both';
|
|
86
|
+
|
|
78
87
|
export interface TriggerAnimationConfig extends WithTimingConfig {
|
|
79
88
|
/**
|
|
80
89
|
* Animation duration in milliseconds
|
|
@@ -121,9 +130,18 @@ export interface GestureViewerProps<ItemT, LC> {
|
|
|
121
130
|
* A callback function that is called to render the item.
|
|
122
131
|
*/
|
|
123
132
|
renderItem: (item: ItemT, index: number) => React.ReactElement;
|
|
133
|
+
/**
|
|
134
|
+
* A callback function that is called when a single tap is confirmed on the viewer content.
|
|
135
|
+
* @remarks
|
|
136
|
+
* - The callback runs only after the tap is resolved as a single tap, so it may be slightly delayed when double-tap zoom is enabled.
|
|
137
|
+
* - It is not called for swipe, pinch, dismiss, or double-tap zoom gestures.
|
|
138
|
+
* - Prefer this callback over overlaying a pressable in `renderContainer` for fullscreen tap handling.
|
|
139
|
+
*/
|
|
140
|
+
onSingleTap?: (event: GestureViewerSingleTapEvent<ItemT>) => void;
|
|
124
141
|
/**
|
|
125
142
|
* A callback function that is called to render the container.
|
|
126
143
|
* @remarks Useful for composing additional UI (e.g., close button, toolbars) around the viewer.
|
|
144
|
+
* Prefer `onSingleTap` for fullscreen tap handling instead of overlaying a pressable over the viewer content.
|
|
127
145
|
* The second argument provides control helpers such as `dismiss()` to close the viewer.
|
|
128
146
|
*
|
|
129
147
|
* @param children - The viewer content to be rendered inside your container.
|
|
@@ -183,8 +201,8 @@ export interface GestureViewerProps<ItemT, LC> {
|
|
|
183
201
|
*/
|
|
184
202
|
autoPlayInterval?: number;
|
|
185
203
|
/**
|
|
186
|
-
* Dismiss gesture options.
|
|
187
|
-
* @remarks Useful for closing modals with
|
|
204
|
+
* Dismiss gesture options.
|
|
205
|
+
* @remarks Useful for closing modals with configurable vertical swipe gestures.
|
|
188
206
|
*/
|
|
189
207
|
dismiss?: {
|
|
190
208
|
/**
|
|
@@ -192,6 +210,12 @@ export interface GestureViewerProps<ItemT, LC> {
|
|
|
192
210
|
* @defaultValue true
|
|
193
211
|
*/
|
|
194
212
|
enabled?: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Controls which vertical swipe direction can trigger `onDismiss`.
|
|
215
|
+
* @remarks Use `down` for backward-compatible behavior, `up` for upward-only dismiss, or `both` for either direction.
|
|
216
|
+
* @defaultValue 'down'
|
|
217
|
+
*/
|
|
218
|
+
direction?: GestureViewerDismissDirection;
|
|
195
219
|
/**
|
|
196
220
|
* `threshold` controls when `onDismiss` is called by applying a threshold value during vertical gestures.
|
|
197
221
|
* @defaultValue 80
|
|
@@ -203,7 +227,7 @@ export interface GestureViewerProps<ItemT, LC> {
|
|
|
203
227
|
*/
|
|
204
228
|
resistance?: number;
|
|
205
229
|
/**
|
|
206
|
-
* By default, the background `opacity` gradually decreases
|
|
230
|
+
* By default, the background `opacity` gradually decreases as you drag in the configured dismiss direction.
|
|
207
231
|
* @remarks When `false`, this animation is disabled.
|
|
208
232
|
* @defaultValue true
|
|
209
233
|
*/
|
|
@@ -425,11 +449,14 @@ export type GestureViewerState = {
|
|
|
425
449
|
readonly totalCount: number;
|
|
426
450
|
};
|
|
427
451
|
|
|
428
|
-
export type GestureViewerEventType = 'zoomChange' | 'rotationChange';
|
|
452
|
+
export type GestureViewerEventType = 'zoomChange' | 'rotationChange' | 'tap';
|
|
453
|
+
|
|
454
|
+
export type SingleTapEventData = { kind: 'single'; x: number; y: number; index: number };
|
|
429
455
|
|
|
430
456
|
export type GestureViewerEventData = {
|
|
431
457
|
zoomChange: { scale: number; previousScale: number | null };
|
|
432
458
|
rotationChange: { rotation: number; previousRotation: number | null };
|
|
459
|
+
tap: SingleTapEventData;
|
|
433
460
|
};
|
|
434
461
|
|
|
435
462
|
export type GestureViewerEventCallback<T extends GestureViewerEventType> = (
|