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,9 +1,10 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useRef, type MouseEvent } from 'react';
|
|
2
2
|
import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import type {
|
|
5
5
|
UseGestureViewerPagingArgs,
|
|
6
6
|
UseGestureViewerPagingResult,
|
|
7
|
+
WebClickTarget,
|
|
7
8
|
} from './useGestureViewerPaging.types';
|
|
8
9
|
import { applyTapZoomAtPoint } from './utils/tapZoom';
|
|
9
10
|
import {
|
|
@@ -35,6 +36,7 @@ export function useGestureViewerPaging({
|
|
|
35
36
|
enableHorizontalSwipe,
|
|
36
37
|
enableLoop,
|
|
37
38
|
height,
|
|
39
|
+
onSingleTap,
|
|
38
40
|
isRotated,
|
|
39
41
|
isZoomed,
|
|
40
42
|
itemSpacing,
|
|
@@ -43,10 +45,13 @@ export function useGestureViewerPaging({
|
|
|
43
45
|
scale,
|
|
44
46
|
scrollTo,
|
|
45
47
|
syncCurrentIndex,
|
|
48
|
+
syncPendingIndex,
|
|
46
49
|
translateX,
|
|
47
50
|
translateY,
|
|
48
51
|
width,
|
|
49
52
|
}: UseGestureViewerPagingArgs): UseGestureViewerPagingResult {
|
|
53
|
+
const webSingleTapTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
54
|
+
|
|
50
55
|
const webScrollRuntimeRef = useRef<WebScrollRuntime>({
|
|
51
56
|
actor: 'idle',
|
|
52
57
|
isAutoplayPausedByUser: false,
|
|
@@ -58,6 +63,13 @@ export function useGestureViewerPaging({
|
|
|
58
63
|
resumeAutoplayTimer: null,
|
|
59
64
|
});
|
|
60
65
|
|
|
66
|
+
const clearWebSingleTapTimer = useCallback(() => {
|
|
67
|
+
if (webSingleTapTimerRef.current) {
|
|
68
|
+
clearTimeout(webSingleTapTimerRef.current);
|
|
69
|
+
webSingleTapTimerRef.current = null;
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
61
73
|
const clearWebSettleTimer = useCallback(() => {
|
|
62
74
|
const runtime = webScrollRuntimeRef.current;
|
|
63
75
|
|
|
@@ -231,10 +243,11 @@ export function useGestureViewerPaging({
|
|
|
231
243
|
|
|
232
244
|
useEffect(() => {
|
|
233
245
|
return () => {
|
|
246
|
+
clearWebSingleTapTimer();
|
|
234
247
|
clearWebSettleTimer();
|
|
235
248
|
clearWebAutoplayResumeTimer();
|
|
236
249
|
};
|
|
237
|
-
}, [clearWebAutoplayResumeTimer, clearWebSettleTimer]);
|
|
250
|
+
}, [clearWebAutoplayResumeTimer, clearWebSettleTimer, clearWebSingleTapTimer]);
|
|
238
251
|
|
|
239
252
|
useEffect(() => {
|
|
240
253
|
if (
|
|
@@ -302,15 +315,34 @@ export function useGestureViewerPaging({
|
|
|
302
315
|
return;
|
|
303
316
|
}
|
|
304
317
|
|
|
318
|
+
const offsetX = event.nativeEvent.contentOffset.x;
|
|
319
|
+
const runtime = webScrollRuntimeRef.current;
|
|
320
|
+
const pendingState = resolveWebScrollFinalState({
|
|
321
|
+
dataLength,
|
|
322
|
+
enableLoop,
|
|
323
|
+
lastSettledPhysicalIndex: runtime.lastSettledPhysicalIndex,
|
|
324
|
+
offsetX,
|
|
325
|
+
pageWidth: width + itemSpacing,
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
if (pendingState) {
|
|
329
|
+
syncPendingIndex(pendingState.logicalIndex);
|
|
330
|
+
}
|
|
331
|
+
|
|
305
332
|
syncProgrammaticActorFromManager();
|
|
306
333
|
beginWebUserInteraction();
|
|
307
|
-
scheduleWebScrollSettle(
|
|
334
|
+
scheduleWebScrollSettle(offsetX);
|
|
308
335
|
},
|
|
309
336
|
[
|
|
310
337
|
beginWebUserInteraction,
|
|
338
|
+
dataLength,
|
|
311
339
|
enableHorizontalSwipe,
|
|
340
|
+
enableLoop,
|
|
341
|
+
itemSpacing,
|
|
312
342
|
scheduleWebScrollSettle,
|
|
343
|
+
syncPendingIndex,
|
|
313
344
|
syncProgrammaticActorFromManager,
|
|
345
|
+
width,
|
|
314
346
|
],
|
|
315
347
|
);
|
|
316
348
|
|
|
@@ -331,50 +363,62 @@ export function useGestureViewerPaging({
|
|
|
331
363
|
manager?.handleScrollBeginDrag();
|
|
332
364
|
}, [beginWebUserInteraction, clearWebSettleTimer, manager]);
|
|
333
365
|
|
|
334
|
-
const
|
|
335
|
-
(event:
|
|
336
|
-
|
|
366
|
+
const onWebClick = useCallback(
|
|
367
|
+
(event: MouseEvent<WebClickTarget>) => {
|
|
368
|
+
const detail = event.detail;
|
|
369
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
370
|
+
const resolvedX = event.clientX - rect.left;
|
|
371
|
+
const resolvedY = event.clientY - rect.top;
|
|
372
|
+
|
|
373
|
+
if (!enableDoubleTapZoom) {
|
|
374
|
+
if (!onSingleTap) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
clearWebSingleTapTimer();
|
|
379
|
+
onSingleTap(resolvedX, resolvedY);
|
|
337
380
|
return;
|
|
338
381
|
}
|
|
339
382
|
|
|
340
|
-
|
|
341
|
-
|
|
383
|
+
if (detail === 2) {
|
|
384
|
+
clearWebSingleTapTimer();
|
|
342
385
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
let locationX = nativeEvent?.locationX;
|
|
346
|
-
let locationY = nativeEvent?.locationY;
|
|
386
|
+
pauseWebAutoplayWithoutPagingInteraction();
|
|
387
|
+
scheduleWebAutoplayResume();
|
|
347
388
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
389
|
+
applyTapZoomAtPoint({
|
|
390
|
+
x: resolvedX,
|
|
391
|
+
y: resolvedY,
|
|
392
|
+
width,
|
|
393
|
+
height,
|
|
394
|
+
maxZoomScale,
|
|
395
|
+
scale,
|
|
396
|
+
translateX,
|
|
397
|
+
translateY,
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
355
401
|
|
|
356
|
-
|
|
357
|
-
|
|
402
|
+
if (detail !== 1 || !onSingleTap) {
|
|
403
|
+
return;
|
|
358
404
|
}
|
|
359
405
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
scale,
|
|
367
|
-
translateX,
|
|
368
|
-
translateY,
|
|
369
|
-
});
|
|
406
|
+
clearWebSingleTapTimer();
|
|
407
|
+
|
|
408
|
+
webSingleTapTimerRef.current = setTimeout(() => {
|
|
409
|
+
onSingleTap(resolvedX, resolvedY);
|
|
410
|
+
webSingleTapTimerRef.current = null;
|
|
411
|
+
}, 250);
|
|
370
412
|
},
|
|
371
413
|
[
|
|
414
|
+
clearWebSingleTapTimer,
|
|
372
415
|
enableDoubleTapZoom,
|
|
373
416
|
height,
|
|
374
417
|
maxZoomScale,
|
|
418
|
+
onSingleTap,
|
|
375
419
|
pauseWebAutoplayWithoutPagingInteraction,
|
|
376
|
-
scheduleWebAutoplayResume,
|
|
377
420
|
scale,
|
|
421
|
+
scheduleWebAutoplayResume,
|
|
378
422
|
translateX,
|
|
379
423
|
translateY,
|
|
380
424
|
width,
|
|
@@ -385,6 +429,6 @@ export function useGestureViewerPaging({
|
|
|
385
429
|
onMomentumScrollEnd,
|
|
386
430
|
onScroll,
|
|
387
431
|
onScrollBeginDrag,
|
|
388
|
-
|
|
432
|
+
onWebClick,
|
|
389
433
|
};
|
|
390
434
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { GestureViewerDismissDirection } from '../types';
|
|
2
|
+
|
|
3
|
+
export const shouldDismissByDirection = (
|
|
4
|
+
translationY: number,
|
|
5
|
+
threshold: number,
|
|
6
|
+
direction: GestureViewerDismissDirection,
|
|
7
|
+
): boolean => {
|
|
8
|
+
'worklet';
|
|
9
|
+
|
|
10
|
+
if (direction === 'up') {
|
|
11
|
+
return translationY < -threshold;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (direction === 'both') {
|
|
15
|
+
return Math.abs(translationY) > threshold;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return translationY > threshold;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getDismissDistance = (
|
|
22
|
+
translationY: number,
|
|
23
|
+
direction: GestureViewerDismissDirection,
|
|
24
|
+
): number => {
|
|
25
|
+
'worklet';
|
|
26
|
+
|
|
27
|
+
if (direction === 'up') {
|
|
28
|
+
return Math.max(-translationY, 0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (direction === 'both') {
|
|
32
|
+
return Math.abs(translationY);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return Math.max(translationY, 0);
|
|
36
|
+
};
|