react-native-gesture-image-viewer 2.4.0 → 3.0.0-beta.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.
Files changed (133) hide show
  1. package/README.md +5 -3
  2. package/lib/module/GestureViewer.js +88 -146
  3. package/lib/module/GestureViewer.js.map +1 -1
  4. package/lib/module/GestureViewerManager.js +49 -105
  5. package/lib/module/GestureViewerManager.js.map +1 -1
  6. package/lib/module/gestureViewerAnimation.js +18 -0
  7. package/lib/module/gestureViewerAnimation.js.map +1 -0
  8. package/lib/module/gestureViewerPaging.js +66 -0
  9. package/lib/module/gestureViewerPaging.js.map +1 -0
  10. package/lib/module/gestureViewerRenderWindow.js +29 -0
  11. package/lib/module/gestureViewerRenderWindow.js.map +1 -0
  12. package/lib/module/getWebContentProps.js +6 -0
  13. package/lib/module/getWebContentProps.js.map +1 -0
  14. package/lib/module/getWebContentProps.web.js +8 -0
  15. package/lib/module/getWebContentProps.web.js.map +1 -0
  16. package/lib/module/platformTapGestures.js +4 -0
  17. package/lib/module/platformTapGestures.js.map +1 -0
  18. package/lib/module/platformTapGestures.web.js +4 -0
  19. package/lib/module/platformTapGestures.web.js.map +1 -0
  20. package/lib/module/renderWindow.js +160 -0
  21. package/lib/module/renderWindow.js.map +1 -0
  22. package/lib/module/useGestureViewer.js +386 -206
  23. package/lib/module/useGestureViewer.js.map +1 -1
  24. package/lib/module/useGestureViewerController.js +3 -3
  25. package/lib/module/useGestureViewerController.js.map +1 -1
  26. package/lib/module/useGestureViewerManagerBridge.js +85 -0
  27. package/lib/module/useGestureViewerManagerBridge.js.map +1 -0
  28. package/lib/module/useGestureViewerPaging.js +147 -79
  29. package/lib/module/useGestureViewerPaging.js.map +1 -1
  30. package/lib/module/useWebClickHandler.js +7 -0
  31. package/lib/module/useWebClickHandler.js.map +1 -0
  32. package/lib/module/useWebClickHandler.web.js +85 -0
  33. package/lib/module/useWebClickHandler.web.js.map +1 -0
  34. package/lib/module/useWebSingleTapTimer.js +12 -0
  35. package/lib/module/useWebSingleTapTimer.js.map +1 -0
  36. package/lib/module/useWebSingleTapTimer.web.js +25 -0
  37. package/lib/module/useWebSingleTapTimer.web.js.map +1 -0
  38. package/lib/module/utils/index.js +0 -77
  39. package/lib/module/utils/index.js.map +1 -1
  40. package/lib/module/utils/tapZoom.js +4 -3
  41. package/lib/module/utils/tapZoom.js.map +1 -1
  42. package/lib/typescript/src/GestureViewer.d.ts +1 -1
  43. package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
  44. package/lib/typescript/src/GestureViewerManager.d.ts +20 -20
  45. package/lib/typescript/src/GestureViewerManager.d.ts.map +1 -1
  46. package/lib/typescript/src/gestureViewerAnimation.d.ts +15 -0
  47. package/lib/typescript/src/gestureViewerAnimation.d.ts.map +1 -0
  48. package/lib/typescript/src/gestureViewerPaging.d.ts +13 -0
  49. package/lib/typescript/src/gestureViewerPaging.d.ts.map +1 -0
  50. package/lib/typescript/src/gestureViewerRenderWindow.d.ts +15 -0
  51. package/lib/typescript/src/gestureViewerRenderWindow.d.ts.map +1 -0
  52. package/lib/typescript/src/getWebContentProps.d.ts +3 -0
  53. package/lib/typescript/src/getWebContentProps.d.ts.map +1 -0
  54. package/lib/typescript/src/getWebContentProps.web.d.ts +5 -0
  55. package/lib/typescript/src/getWebContentProps.web.d.ts.map +1 -0
  56. package/lib/typescript/src/platformTapGestures.d.ts +2 -0
  57. package/lib/typescript/src/platformTapGestures.d.ts.map +1 -0
  58. package/lib/typescript/src/platformTapGestures.web.d.ts +2 -0
  59. package/lib/typescript/src/platformTapGestures.web.d.ts.map +1 -0
  60. package/lib/typescript/src/renderWindow.d.ts +44 -0
  61. package/lib/typescript/src/renderWindow.d.ts.map +1 -0
  62. package/lib/typescript/src/types.d.ts +36 -53
  63. package/lib/typescript/src/types.d.ts.map +1 -1
  64. package/lib/typescript/src/useGestureViewer.d.ts +9 -9
  65. package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
  66. package/lib/typescript/src/useGestureViewerController.d.ts +1 -1
  67. package/lib/typescript/src/useGestureViewerManagerBridge.d.ts +28 -0
  68. package/lib/typescript/src/useGestureViewerManagerBridge.d.ts.map +1 -0
  69. package/lib/typescript/src/useGestureViewerPaging.d.ts +31 -2
  70. package/lib/typescript/src/useGestureViewerPaging.d.ts.map +1 -1
  71. package/lib/typescript/src/useWebClickHandler.d.ts +35 -0
  72. package/lib/typescript/src/useWebClickHandler.d.ts.map +1 -0
  73. package/lib/typescript/src/useWebClickHandler.web.d.ts +36 -0
  74. package/lib/typescript/src/useWebClickHandler.web.d.ts.map +1 -0
  75. package/lib/typescript/src/useWebSingleTapTimer.d.ts +6 -0
  76. package/lib/typescript/src/useWebSingleTapTimer.d.ts.map +1 -0
  77. package/lib/typescript/src/useWebSingleTapTimer.web.d.ts +6 -0
  78. package/lib/typescript/src/useWebSingleTapTimer.web.d.ts.map +1 -0
  79. package/lib/typescript/src/utils/index.d.ts +0 -20
  80. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  81. package/lib/typescript/src/utils/tapZoom.d.ts.map +1 -1
  82. package/package.json +1 -1
  83. package/src/GestureViewer.tsx +104 -206
  84. package/src/GestureViewerManager.ts +77 -122
  85. package/src/gestureViewerAnimation.ts +18 -0
  86. package/src/gestureViewerPaging.ts +116 -0
  87. package/src/gestureViewerRenderWindow.ts +56 -0
  88. package/src/getWebContentProps.ts +5 -0
  89. package/src/getWebContentProps.web.ts +5 -0
  90. package/src/platformTapGestures.ts +1 -0
  91. package/src/platformTapGestures.web.ts +1 -0
  92. package/src/renderWindow.ts +253 -0
  93. package/src/types.ts +34 -100
  94. package/src/useGestureViewer.ts +557 -271
  95. package/src/useGestureViewerController.ts +3 -3
  96. package/src/useGestureViewerManagerBridge.ts +118 -0
  97. package/src/useGestureViewerPaging.ts +277 -114
  98. package/src/useWebClickHandler.ts +44 -0
  99. package/src/useWebClickHandler.web.ts +146 -0
  100. package/src/useWebSingleTapTimer.ts +10 -0
  101. package/src/useWebSingleTapTimer.web.ts +30 -0
  102. package/src/utils/index.ts +0 -102
  103. package/src/utils/tapZoom.ts +4 -3
  104. package/lib/module/WebPagingFixStyle.js +0 -25
  105. package/lib/module/WebPagingFixStyle.js.map +0 -1
  106. package/lib/module/scheduleInitialScroll.js +0 -21
  107. package/lib/module/scheduleInitialScroll.js.map +0 -1
  108. package/lib/module/useGestureViewerPaging.types.js +0 -4
  109. package/lib/module/useGestureViewerPaging.types.js.map +0 -1
  110. package/lib/module/useGestureViewerPaging.web.js +0 -291
  111. package/lib/module/useGestureViewerPaging.web.js.map +0 -1
  112. package/lib/module/utils/FlashList.js +0 -9
  113. package/lib/module/utils/FlashList.js.map +0 -1
  114. package/lib/module/utils/webScroll.js +0 -70
  115. package/lib/module/utils/webScroll.js.map +0 -1
  116. package/lib/typescript/src/WebPagingFixStyle.d.ts +0 -6
  117. package/lib/typescript/src/WebPagingFixStyle.d.ts.map +0 -1
  118. package/lib/typescript/src/scheduleInitialScroll.d.ts +0 -3
  119. package/lib/typescript/src/scheduleInitialScroll.d.ts.map +0 -1
  120. package/lib/typescript/src/useGestureViewerPaging.types.d.ts +0 -42
  121. package/lib/typescript/src/useGestureViewerPaging.types.d.ts.map +0 -1
  122. package/lib/typescript/src/useGestureViewerPaging.web.d.ts +0 -3
  123. package/lib/typescript/src/useGestureViewerPaging.web.d.ts.map +0 -1
  124. package/lib/typescript/src/utils/FlashList.d.ts +0 -2
  125. package/lib/typescript/src/utils/FlashList.d.ts.map +0 -1
  126. package/lib/typescript/src/utils/webScroll.d.ts +0 -18
  127. package/lib/typescript/src/utils/webScroll.d.ts.map +0 -1
  128. package/src/WebPagingFixStyle.tsx +0 -25
  129. package/src/scheduleInitialScroll.ts +0 -36
  130. package/src/useGestureViewerPaging.types.ts +0 -42
  131. package/src/useGestureViewerPaging.web.ts +0 -453
  132. package/src/utils/FlashList.ts +0 -7
  133. package/src/utils/webScroll.ts +0 -96
@@ -0,0 +1,116 @@
1
+ export type HorizontalSwipeDirection = -1 | 0 | 1;
2
+
3
+ export type HorizontalPagingTarget =
4
+ | {
5
+ kind: 'move';
6
+ targetVirtualIndex: number;
7
+ }
8
+ | {
9
+ kind: 'settle';
10
+ };
11
+
12
+ export function normalizeHorizontalSwipeThreshold(
13
+ value: number | undefined,
14
+ fallback: number,
15
+ ): number {
16
+ if (value === undefined) {
17
+ return fallback;
18
+ }
19
+
20
+ if (Number.isFinite(value) && value >= 0) {
21
+ return value;
22
+ }
23
+
24
+ return fallback;
25
+ }
26
+
27
+ export function resolveHorizontalSwipeDirection(
28
+ translationX: number,
29
+ velocityX: number,
30
+ width: number,
31
+ thresholdRatio: number,
32
+ velocityThreshold: number,
33
+ ): HorizontalSwipeDirection {
34
+ 'worklet';
35
+
36
+ const translationThreshold = width * thresholdRatio;
37
+
38
+ if (-translationX > translationThreshold || velocityX < -velocityThreshold) {
39
+ return 1;
40
+ }
41
+
42
+ if (translationX > translationThreshold || velocityX > velocityThreshold) {
43
+ return -1;
44
+ }
45
+
46
+ return 0;
47
+ }
48
+
49
+ export function applyHorizontalEdgeResistance(
50
+ nextPage: number,
51
+ currentIndex: number,
52
+ dataLength: number,
53
+ centerVirtualIndex: number,
54
+ enableLoop: boolean,
55
+ resistance: number,
56
+ ): number {
57
+ 'worklet';
58
+
59
+ if (dataLength <= 1) {
60
+ return centerVirtualIndex;
61
+ }
62
+
63
+ if (enableLoop) {
64
+ return nextPage;
65
+ }
66
+
67
+ if (currentIndex <= 0 && nextPage < centerVirtualIndex) {
68
+ return centerVirtualIndex + (nextPage - centerVirtualIndex) * resistance;
69
+ }
70
+
71
+ if (currentIndex >= dataLength - 1 && nextPage > centerVirtualIndex) {
72
+ return centerVirtualIndex + (nextPage - centerVirtualIndex) * resistance;
73
+ }
74
+
75
+ return nextPage;
76
+ }
77
+
78
+ export function canMoveHorizontalPage(
79
+ currentIndex: number,
80
+ dataLength: number,
81
+ direction: HorizontalSwipeDirection,
82
+ enableLoop: boolean,
83
+ ): boolean {
84
+ 'worklet';
85
+
86
+ if (direction === 0 || dataLength <= 1) {
87
+ return false;
88
+ }
89
+
90
+ if (enableLoop) {
91
+ return true;
92
+ }
93
+
94
+ const nextIndex = currentIndex + direction;
95
+
96
+ return nextIndex >= 0 && nextIndex < dataLength;
97
+ }
98
+
99
+ export function resolveHorizontalPagingTarget(
100
+ centerVirtualIndex: number,
101
+ currentIndex: number,
102
+ dataLength: number,
103
+ direction: HorizontalSwipeDirection,
104
+ enableLoop: boolean,
105
+ ): HorizontalPagingTarget {
106
+ 'worklet';
107
+
108
+ if (!canMoveHorizontalPage(currentIndex, dataLength, direction, enableLoop)) {
109
+ return { kind: 'settle' };
110
+ }
111
+
112
+ return {
113
+ kind: 'move',
114
+ targetVirtualIndex: centerVirtualIndex + direction,
115
+ };
116
+ }
@@ -0,0 +1,56 @@
1
+ import {
2
+ type RenderWindowSlot,
3
+ clampIndex,
4
+ createRenderWindow,
5
+ getVirtualIndexForLogicalIndex,
6
+ normalizeWindowSize,
7
+ } from './renderWindow';
8
+
9
+ export type GestureViewerRenderWindowState<ItemT> = {
10
+ centerVirtualIndex: number;
11
+ currentIndex: number;
12
+ slots: RenderWindowSlot<ItemT>[];
13
+ };
14
+
15
+ export function resolveGestureViewerRenderWindow<ItemT>({
16
+ centerVirtualIndex,
17
+ currentIndex,
18
+ data,
19
+ enableLoop,
20
+ isTriggerOpening,
21
+ windowSize,
22
+ }: {
23
+ centerVirtualIndex: number;
24
+ currentIndex: number;
25
+ data: ItemT[];
26
+ enableLoop: boolean;
27
+ isTriggerOpening: boolean;
28
+ windowSize?: number;
29
+ }): GestureViewerRenderWindowState<ItemT> {
30
+ const dataLength = data.length;
31
+ const normalizedWindowSize = normalizeWindowSize(windowSize);
32
+ const renderCurrentIndex = clampIndex(currentIndex, dataLength);
33
+ const renderCenterVirtualIndex =
34
+ getVirtualIndexForLogicalIndex(
35
+ renderCurrentIndex,
36
+ centerVirtualIndex,
37
+ dataLength,
38
+ enableLoop,
39
+ ) ?? renderCurrentIndex;
40
+
41
+ const fullSlots = createRenderWindow({
42
+ centerVirtualIndex: renderCenterVirtualIndex,
43
+ data,
44
+ enableLoop,
45
+ windowSize: normalizedWindowSize,
46
+ });
47
+ const slots = isTriggerOpening
48
+ ? fullSlots.filter((slot) => slot.virtualIndex === renderCenterVirtualIndex)
49
+ : fullSlots;
50
+
51
+ return {
52
+ centerVirtualIndex: renderCenterVirtualIndex,
53
+ currentIndex: renderCurrentIndex,
54
+ slots,
55
+ };
56
+ }
@@ -0,0 +1,5 @@
1
+ import type { WebClickHandler } from './useWebClickHandler';
2
+
3
+ export function getWebContentProps(_onWebClick: WebClickHandler) {
4
+ return {};
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { WebClickHandler } from './useWebClickHandler';
2
+
3
+ export function getWebContentProps(onWebClick: WebClickHandler) {
4
+ return { onClick: onWebClick };
5
+ }
@@ -0,0 +1 @@
1
+ export const enableNativeTapGestures = true;
@@ -0,0 +1 @@
1
+ export const enableNativeTapGestures = false;
@@ -0,0 +1,253 @@
1
+ export const DEFAULT_WINDOW_SIZE = 3;
2
+ export const MIN_WINDOW_SIZE = 3;
3
+
4
+ type NavigationDirection = -1 | 1;
5
+
6
+ export type RenderWindowSlot<ItemT> = {
7
+ item: ItemT;
8
+ logicalIndex: number;
9
+ slotKey: string;
10
+ virtualIndex: number;
11
+ };
12
+
13
+ export type NavigationResolution =
14
+ | {
15
+ kind: 'noop';
16
+ }
17
+ | {
18
+ direction: NavigationDirection;
19
+ kind: 'step';
20
+ targetIndex: number;
21
+ }
22
+ | {
23
+ kind: 'jump';
24
+ targetIndex: number;
25
+ };
26
+
27
+ export type NavigationOptions = {
28
+ animated?: boolean;
29
+ };
30
+
31
+ const positiveModulo = (value: number, divisor: number) => ((value % divisor) + divisor) % divisor;
32
+
33
+ const getStepTargetIndex = (
34
+ currentIndex: number,
35
+ dataLength: number,
36
+ enableLoop: boolean,
37
+ direction: NavigationDirection,
38
+ ) => {
39
+ const adjacentIndex = currentIndex + direction;
40
+
41
+ if (adjacentIndex >= 0 && adjacentIndex < dataLength) {
42
+ return adjacentIndex;
43
+ }
44
+
45
+ if (!enableLoop || dataLength <= 1) {
46
+ return null;
47
+ }
48
+
49
+ if (direction === 1 && currentIndex === dataLength - 1) {
50
+ return 0;
51
+ }
52
+
53
+ if (direction === -1 && currentIndex === 0) {
54
+ return dataLength - 1;
55
+ }
56
+
57
+ return null;
58
+ };
59
+
60
+ export function normalizeWindowSize(windowSize?: number): number {
61
+ const candidateWindowSize = windowSize ?? DEFAULT_WINDOW_SIZE;
62
+
63
+ if (!Number.isFinite(candidateWindowSize)) {
64
+ return DEFAULT_WINDOW_SIZE;
65
+ }
66
+
67
+ const integerWindowSize = Math.floor(candidateWindowSize);
68
+ const boundedWindowSize = Math.max(MIN_WINDOW_SIZE, integerWindowSize);
69
+
70
+ return boundedWindowSize % 2 === 0 ? boundedWindowSize + 1 : boundedWindowSize;
71
+ }
72
+
73
+ export function normalizePageSpacing(pageSpacing?: number): number {
74
+ const candidatePageSpacing = pageSpacing ?? 0;
75
+
76
+ if (!Number.isFinite(candidatePageSpacing) || candidatePageSpacing < 0) {
77
+ return 0;
78
+ }
79
+
80
+ return candidatePageSpacing;
81
+ }
82
+
83
+ export function getPageStride(width: number, pageSpacing?: number): number {
84
+ return width + normalizePageSpacing(pageSpacing);
85
+ }
86
+
87
+ export function clampIndex(index: number | undefined, dataLength: number): number {
88
+ if (dataLength <= 0) {
89
+ return 0;
90
+ }
91
+
92
+ const candidateIndex = index ?? 0;
93
+
94
+ if (!Number.isFinite(candidateIndex)) {
95
+ return 0;
96
+ }
97
+
98
+ return Math.min(Math.max(Math.trunc(candidateIndex), 0), dataLength - 1);
99
+ }
100
+
101
+ export function getLogicalIndex(
102
+ virtualIndex: number,
103
+ dataLength: number,
104
+ enableLoop: boolean,
105
+ ): number | null {
106
+ if (dataLength <= 0 || !Number.isFinite(virtualIndex)) {
107
+ return null;
108
+ }
109
+
110
+ if (enableLoop) {
111
+ return positiveModulo(Math.trunc(virtualIndex), dataLength);
112
+ }
113
+
114
+ if (virtualIndex < 0 || virtualIndex >= dataLength) {
115
+ return null;
116
+ }
117
+
118
+ return Math.trunc(virtualIndex);
119
+ }
120
+
121
+ export function getVirtualIndexForLogicalIndex(
122
+ logicalIndex: number,
123
+ centerVirtualIndex: number,
124
+ dataLength: number,
125
+ enableLoop: boolean,
126
+ ): number | null {
127
+ if (dataLength <= 0 || logicalIndex < 0 || logicalIndex >= dataLength) {
128
+ return null;
129
+ }
130
+
131
+ if (!enableLoop) {
132
+ return logicalIndex;
133
+ }
134
+
135
+ const currentLogicalIndex = getLogicalIndex(centerVirtualIndex, dataLength, true);
136
+
137
+ if (currentLogicalIndex === null) {
138
+ return logicalIndex;
139
+ }
140
+
141
+ const forwardDistance = positiveModulo(logicalIndex - currentLogicalIndex, dataLength);
142
+ const backwardDistance = positiveModulo(currentLogicalIndex - logicalIndex, dataLength);
143
+
144
+ return forwardDistance <= backwardDistance
145
+ ? centerVirtualIndex + forwardDistance
146
+ : centerVirtualIndex - backwardDistance;
147
+ }
148
+
149
+ export function createRenderWindow<ItemT>({
150
+ centerVirtualIndex,
151
+ data,
152
+ enableLoop,
153
+ windowSize,
154
+ }: {
155
+ centerVirtualIndex: number;
156
+ data: ItemT[];
157
+ enableLoop: boolean;
158
+ windowSize?: number;
159
+ }): RenderWindowSlot<ItemT>[] {
160
+ const dataLength = data.length;
161
+
162
+ if (dataLength === 0) {
163
+ return [];
164
+ }
165
+
166
+ const normalizedWindowSize = normalizeWindowSize(windowSize);
167
+ const halfWindowSize = enableLoop && dataLength === 1 ? 0 : Math.floor(normalizedWindowSize / 2);
168
+ const slots: RenderWindowSlot<ItemT>[] = [];
169
+
170
+ for (let offset = -halfWindowSize; offset <= halfWindowSize; offset += 1) {
171
+ const virtualIndex = centerVirtualIndex + offset;
172
+ const logicalIndex = getLogicalIndex(virtualIndex, dataLength, enableLoop);
173
+
174
+ if (logicalIndex === null || !(logicalIndex in data)) {
175
+ continue;
176
+ }
177
+
178
+ slots.push({
179
+ item: data[logicalIndex] as ItemT,
180
+ logicalIndex,
181
+ slotKey: `slot-${virtualIndex}`,
182
+ virtualIndex,
183
+ });
184
+ }
185
+
186
+ return slots;
187
+ }
188
+
189
+ export function resolveNavigation({
190
+ currentIndex,
191
+ dataLength,
192
+ enableLoop,
193
+ preferredDirection,
194
+ targetIndex,
195
+ }: {
196
+ currentIndex: number;
197
+ dataLength: number;
198
+ enableLoop: boolean;
199
+ preferredDirection?: NavigationDirection;
200
+ targetIndex: number;
201
+ }): NavigationResolution {
202
+ if (
203
+ dataLength <= 0 ||
204
+ targetIndex < 0 ||
205
+ targetIndex >= dataLength ||
206
+ currentIndex < 0 ||
207
+ currentIndex >= dataLength
208
+ ) {
209
+ return { kind: 'noop' };
210
+ }
211
+
212
+ if (targetIndex === currentIndex) {
213
+ return { kind: 'noop' };
214
+ }
215
+
216
+ if (preferredDirection !== undefined) {
217
+ const preferredTargetIndex = getStepTargetIndex(
218
+ currentIndex,
219
+ dataLength,
220
+ enableLoop,
221
+ preferredDirection,
222
+ );
223
+
224
+ if (preferredTargetIndex === targetIndex) {
225
+ return { direction: preferredDirection, kind: 'step', targetIndex };
226
+ }
227
+ }
228
+
229
+ const forwardTargetIndex = getStepTargetIndex(currentIndex, dataLength, enableLoop, 1);
230
+
231
+ if (forwardTargetIndex === targetIndex) {
232
+ return { direction: 1, kind: 'step', targetIndex };
233
+ }
234
+
235
+ const backwardTargetIndex = getStepTargetIndex(currentIndex, dataLength, enableLoop, -1);
236
+
237
+ if (backwardTargetIndex === targetIndex) {
238
+ return { direction: -1, kind: 'step', targetIndex };
239
+ }
240
+
241
+ return { kind: 'jump', targetIndex };
242
+ }
243
+
244
+ export function shouldRunNavigationDuringTransition(
245
+ resolution: NavigationResolution,
246
+ options?: NavigationOptions,
247
+ ): boolean {
248
+ if (resolution.kind === 'noop') {
249
+ return false;
250
+ }
251
+
252
+ return resolution.kind === 'jump' || options?.animated === false;
253
+ }
package/src/types.ts CHANGED
@@ -1,73 +1,7 @@
1
1
  import type React from 'react';
2
- import type {
3
- FlatListProps,
4
- ListRenderItem,
5
- FlatList as RNFlatList,
6
- ScrollView as RNScrollView,
7
- StyleProp,
8
- ViewabilityConfig,
9
- ViewStyle,
10
- ViewToken,
11
- } from 'react-native';
12
- import type {
13
- FlatList as GHFlatList,
14
- ScrollView as GHScrollView,
15
- } from 'react-native-gesture-handler';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
16
3
  import type { WithTimingConfig } from 'react-native-reanimated';
17
4
 
18
- export type FlatListComponent<ItemT> = typeof RNFlatList<ItemT> | typeof GHFlatList<ItemT>;
19
- export type ScrollViewComponent = typeof RNScrollView | typeof GHScrollView;
20
-
21
- interface ViewabilityConfigCallbackPair<TItem> {
22
- viewabilityConfig: ViewabilityConfig;
23
- onViewableItemsChanged:
24
- | ((info: { viewableItems: ViewToken<TItem>[]; changed: ViewToken<TItem>[] }) => void)
25
- | null;
26
- }
27
-
28
- // Helper type to instantiate generic components with specific type parameter
29
- export type InstantiateGeneric<ItemT, LC> =
30
- LC extends React.ComponentType<infer P>
31
- ? P extends Record<string, any>
32
- ? {
33
- [K in keyof P]: K extends 'data'
34
- ? ArrayLike<ItemT> | null | undefined
35
- : K extends 'renderItem'
36
- ? ListRenderItem<ItemT>
37
- : K extends 'keyExtractor'
38
- ? (item: ItemT, index: number) => string
39
- : K extends 'getItemType'
40
- ? (item: ItemT, index: number, extraData?: any) => string | number | undefined
41
- : K extends 'overrideItemLayout'
42
- ? (
43
- layout: { span?: number; size?: number },
44
- item: ItemT,
45
- index: number,
46
- maxColumns?: number,
47
- extraData?: any,
48
- ) => void
49
- : K extends 'onViewableItemsChanged'
50
- ? FlatListProps<ItemT>['onViewableItemsChanged']
51
- : K extends 'viewabilityConfigCallbackPairs'
52
- ? ViewabilityConfigCallbackPair<ItemT>[]
53
- : P[K];
54
- }
55
- : P
56
- : never;
57
-
58
- export type GetComponentProps<ItemT, LC> =
59
- LC extends React.ComponentType<any> ? InstantiateGeneric<ItemT, LC> : never;
60
-
61
- type ConditionalListProps<ItemT, LC> = LC extends typeof RNFlatList<ItemT>
62
- ? React.ComponentProps<typeof RNFlatList<ItemT>>
63
- : LC extends typeof GHFlatList<ItemT>
64
- ? React.ComponentProps<typeof GHFlatList<ItemT>>
65
- : LC extends typeof RNScrollView
66
- ? React.ComponentProps<typeof RNScrollView>
67
- : LC extends typeof GHScrollView
68
- ? React.ComponentProps<typeof GHScrollView>
69
- : GetComponentProps<ItemT, LC>;
70
-
71
5
  export type TriggerRect = {
72
6
  x: number;
73
7
  y: number;
@@ -109,7 +43,7 @@ export interface TriggerAnimationConfig extends WithTimingConfig {
109
43
  onAnimationComplete?: () => void;
110
44
  }
111
45
 
112
- export interface GestureViewerProps<ItemT, LC> {
46
+ export interface GestureViewerProps<ItemT> {
113
47
  /**
114
48
  * When you want to efficiently manage multiple `GestureViewer` instances, you can use the `id` prop to use multiple `GestureViewer` components.
115
49
  * @remarks `GestureViewer` automatically removes instances from memory when components are unmounted, so no manual memory management is required.
@@ -137,8 +71,8 @@ export interface GestureViewerProps<ItemT, LC> {
137
71
  /**
138
72
  * A callback function that is called to render the item.
139
73
  * @param item - The item to render.
140
- * @param index - The list index of the rendered item.
141
- * @param info - Render state for this list cell.
74
+ * @param index - The index of the item in `data`.
75
+ * @param info - Render state for this mounted slot.
142
76
  */
143
77
  renderItem: (item: ItemT, index: number, info: GestureViewerRenderItemInfo) => React.ReactElement;
144
78
  /**
@@ -163,10 +97,6 @@ export interface GestureViewerProps<ItemT, LC> {
163
97
  children: React.ReactElement,
164
98
  helpers: { dismiss: () => void },
165
99
  ) => React.ReactElement;
166
- /**
167
- * Support for any list component like `ScrollView`, `FlatList`, `FlashList` through the `ListComponent` prop.
168
- */
169
- ListComponent: LC;
170
100
  /**
171
101
  * The width of the `GestureViewer`.
172
102
  * @remarks If you don't set this prop, the width of the `GestureViewer` will be the same as the width of the screen.
@@ -179,11 +109,6 @@ export interface GestureViewerProps<ItemT, LC> {
179
109
  * @defaultValue screen height
180
110
  */
181
111
  height?: number;
182
- /**
183
- * The props to pass to the list component.
184
- * @remarks The `listProps` provides **type inference based on the selected list component**, ensuring accurate autocompletion and type safety in your IDE.
185
- */
186
- listProps?: Partial<ConditionalListProps<ItemT, LC>>;
187
112
  /**
188
113
  * The style of the backdrop.
189
114
  */
@@ -245,11 +170,28 @@ export interface GestureViewerProps<ItemT, LC> {
245
170
  fadeBackdrop?: boolean;
246
171
  };
247
172
  /**
248
- * Controls left/right swipe gestures.
249
- * @remarks When `false`, horizontal gestures are disabled.
250
- * @defaultValue true
173
+ * Horizontal swipe gesture options.
174
+ * @remarks Controls user-driven left/right page swipe gestures. Controller navigation and autoplay remain available when disabled.
251
175
  */
252
- enableHorizontalSwipe?: boolean;
176
+ horizontalSwipe?: {
177
+ /**
178
+ * When `false`, user-driven horizontal page swipe gestures are disabled.
179
+ * @defaultValue true
180
+ */
181
+ enabled?: boolean;
182
+ /**
183
+ * Distance threshold as a ratio of viewer width.
184
+ * @remarks A page commits when absolute horizontal translation is strictly greater than `width * distanceThresholdRatio`, or when velocity passes `velocityThreshold`. Zero and finite values greater than `1` are accepted; negative and non-finite values fall back to the default.
185
+ * @defaultValue 0.25
186
+ */
187
+ distanceThresholdRatio?: number;
188
+ /**
189
+ * Horizontal velocity threshold in points per second.
190
+ * @remarks A page commits when absolute horizontal velocity is strictly greater than `velocityThreshold`, or when distance passes `distanceThresholdRatio`. Zero and every finite non-negative value are accepted; negative and non-finite values fall back to the default.
191
+ * @defaultValue 800
192
+ */
193
+ velocityThreshold?: number;
194
+ };
253
195
  /**
254
196
  * Only works when zoom is active, allows moving item position when zoomed.
255
197
  * @remarks When `false`, gesture movement is disabled during zoom.
@@ -274,25 +216,17 @@ export interface GestureViewerProps<ItemT, LC> {
274
216
  */
275
217
  enableLoop?: boolean;
276
218
  /**
277
- * Enables snap scrolling mode.
278
- *
279
- * @remarks
280
- * **`false` (default)**: Paging mode (`pagingEnabled: true`)
281
- * - Scrolls by full screen size increments
282
- *
283
- * **`true`**: Snap mode (`snapToInterval` auto-calculated)
284
- * - `snapToInterval` is automatically calculated based on `width` and `itemSpacing` values
285
- * - Use this option when you need item spacing
286
- * @defaultValue false
287
- *
219
+ * Number of mounted render-window slots including the current item.
220
+ * @remarks Values are normalized to an odd number of at least 3. For example, `4` becomes `5`.
221
+ * @defaultValue 3
288
222
  */
289
- enableSnapMode?: boolean;
223
+ windowSize?: number;
290
224
  /**
291
- * The spacing between items in pixels.
292
- * @remarks Only applied when `enableSnapMode` is `true`.
225
+ * Horizontal visual space between pages.
226
+ * @remarks Page stride is `width + pageSpacing`; zoom bounds still use `width` and `height`.
293
227
  * @defaultValue 0
294
228
  */
295
- itemSpacing?: number;
229
+ pageSpacing?: number;
296
230
  /**
297
231
  * The maximum zoom scale.
298
232
  * @defaultValue 2
@@ -334,7 +268,7 @@ export type GestureViewerController = {
334
268
  * Updates the currentIndex in the controller state.
335
269
  *
336
270
  * @param index - The target index (must be between 0 and totalCount - 1)
337
- * @throws Will throw an error if index is out of bounds
271
+ * Out-of-range indexes are ignored.
338
272
  *
339
273
  * @example
340
274
  * ```typescript
@@ -344,7 +278,7 @@ export type GestureViewerController = {
344
278
  * controller.goToIndex(totalCount - 1); // Go to last item
345
279
  * ```
346
280
  */
347
- goToIndex: (index: number) => void;
281
+ goToIndex: (index: number, options?: { animated?: boolean }) => void;
348
282
 
349
283
  /**
350
284
  * Navigates to the previous item in the sequence.