react-native-screen-transitions 1.0.3 → 1.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/README.md +240 -245
- package/dist/index.d.mts +909 -5
- package/dist/index.d.ts +909 -5
- package/dist/index.js +816 -426
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +820 -421
- package/dist/index.mjs.map +1 -1
- package/package.json +54 -54
package/dist/index.mjs
CHANGED
|
@@ -5,21 +5,59 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
-
import { Pressable, View } from "react-native";
|
|
8
|
+
import { FlatList, Pressable, ScrollView, View as View2 } from "react-native";
|
|
9
9
|
|
|
10
|
-
// src/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
10
|
+
// src/components/create-transition-aware-component.tsx
|
|
11
|
+
import { forwardRef, memo } from "react";
|
|
12
|
+
import { StyleSheet } from "react-native";
|
|
13
|
+
import Animated, {
|
|
14
|
+
useAnimatedStyle as useAnimatedStyle2
|
|
15
|
+
} from "react-native-reanimated";
|
|
16
|
+
|
|
17
|
+
// src/components/transition-gesture-handler-provider.tsx
|
|
18
|
+
import { useMemo as useMemo2 } from "react";
|
|
19
|
+
import { GestureDetector } from "react-native-gesture-handler";
|
|
20
|
+
import { useSharedValue as useSharedValue3 } from "react-native-reanimated";
|
|
21
|
+
|
|
22
|
+
// src/contexts/gesture.ts
|
|
23
|
+
import { createContext, useContext } from "react";
|
|
24
|
+
import { Gesture } from "react-native-gesture-handler";
|
|
25
|
+
import { useSharedValue } from "react-native-reanimated";
|
|
26
|
+
var GestureContext = createContext(
|
|
27
|
+
void 0
|
|
28
|
+
);
|
|
29
|
+
var useGestureContext = () => {
|
|
30
|
+
const context = useContext(GestureContext);
|
|
31
|
+
const scrollProgressFallback = useSharedValue({
|
|
32
|
+
x: 0,
|
|
33
|
+
y: 0,
|
|
34
|
+
contentHeight: 0,
|
|
35
|
+
contentWidth: 0,
|
|
36
|
+
layoutHeight: 0,
|
|
37
|
+
layoutWidth: 0
|
|
38
|
+
});
|
|
39
|
+
if (!context) {
|
|
40
|
+
return {
|
|
41
|
+
panGesture: Gesture.Pan(),
|
|
42
|
+
nativeGesture: Gesture.Native(),
|
|
43
|
+
scrollProgress: scrollProgressFallback,
|
|
44
|
+
isPlaceholder: true
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return context;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/hooks/use-build-gestures.tsx
|
|
51
|
+
import { useNavigation } from "@react-navigation/native";
|
|
52
|
+
import { useCallback, useMemo } from "react";
|
|
53
|
+
import { useWindowDimensions } from "react-native";
|
|
54
|
+
import {
|
|
55
|
+
Gesture as Gesture2
|
|
56
|
+
} from "react-native-gesture-handler";
|
|
19
57
|
import {
|
|
20
|
-
Extrapolation,
|
|
21
58
|
interpolate,
|
|
22
|
-
|
|
59
|
+
runOnJS as runOnJS2,
|
|
60
|
+
useSharedValue as useSharedValue2
|
|
23
61
|
} from "react-native-reanimated";
|
|
24
62
|
|
|
25
63
|
// src/configs/specs.ts
|
|
@@ -35,173 +73,6 @@ var DefaultSpec = {
|
|
|
35
73
|
restSpeedThreshold: 0.01
|
|
36
74
|
};
|
|
37
75
|
|
|
38
|
-
// src/configs/presets.ts
|
|
39
|
-
var SlideFromTop = (config = {}) => {
|
|
40
|
-
return {
|
|
41
|
-
gestureEnabled: true,
|
|
42
|
-
gestureDirection: "vertical-inverted",
|
|
43
|
-
screenStyleInterpolator: ({
|
|
44
|
-
current,
|
|
45
|
-
next,
|
|
46
|
-
layouts: {
|
|
47
|
-
screen: { height }
|
|
48
|
-
}
|
|
49
|
-
}) => {
|
|
50
|
-
"worklet";
|
|
51
|
-
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
52
|
-
const y = interpolate(progress, [0, 1, 2], [-height, 0, height]);
|
|
53
|
-
return {
|
|
54
|
-
contentStyle: {
|
|
55
|
-
transform: [{ translateY: y }]
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
transitionSpec: {
|
|
60
|
-
open: DefaultSpec,
|
|
61
|
-
close: DefaultSpec
|
|
62
|
-
},
|
|
63
|
-
...config
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
var ZoomIn = (config = {}) => {
|
|
67
|
-
return {
|
|
68
|
-
gestureEnabled: false,
|
|
69
|
-
screenStyleInterpolator: ({ current, next }) => {
|
|
70
|
-
"worklet";
|
|
71
|
-
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
72
|
-
const scale = interpolate(
|
|
73
|
-
progress,
|
|
74
|
-
[0, 1, 2],
|
|
75
|
-
[0.5, 1, 0.5],
|
|
76
|
-
Extrapolation.CLAMP
|
|
77
|
-
);
|
|
78
|
-
const opacity = interpolate(
|
|
79
|
-
progress,
|
|
80
|
-
[0, 1, 2],
|
|
81
|
-
[0, 1, 0],
|
|
82
|
-
Extrapolation.CLAMP
|
|
83
|
-
);
|
|
84
|
-
return {
|
|
85
|
-
contentStyle: {
|
|
86
|
-
transform: [{ scale }],
|
|
87
|
-
opacity
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
|
-
transitionSpec: {
|
|
92
|
-
open: DefaultSpec,
|
|
93
|
-
close: DefaultSpec
|
|
94
|
-
},
|
|
95
|
-
...config
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
var SlideFromBottom = (config = {}) => {
|
|
99
|
-
return {
|
|
100
|
-
gestureEnabled: true,
|
|
101
|
-
gestureDirection: "vertical",
|
|
102
|
-
screenStyleInterpolator: ({
|
|
103
|
-
current,
|
|
104
|
-
next,
|
|
105
|
-
layouts: {
|
|
106
|
-
screen: { height }
|
|
107
|
-
}
|
|
108
|
-
}) => {
|
|
109
|
-
"worklet";
|
|
110
|
-
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
111
|
-
const y = interpolate(progress, [0, 1, 2], [height, 0, -height]);
|
|
112
|
-
return {
|
|
113
|
-
contentStyle: {
|
|
114
|
-
transform: [{ translateY: y }]
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
transitionSpec: {
|
|
119
|
-
open: DefaultSpec,
|
|
120
|
-
close: DefaultSpec
|
|
121
|
-
},
|
|
122
|
-
...config
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
var DraggableCard = (config = {}) => {
|
|
126
|
-
return {
|
|
127
|
-
gestureEnabled: true,
|
|
128
|
-
gestureDirection: ["horizontal", "vertical"],
|
|
129
|
-
screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
|
|
130
|
-
"worklet";
|
|
131
|
-
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
132
|
-
const scale = interpolate(progress, [0, 1, 2], [0, 1, 0.75]);
|
|
133
|
-
const translateY = interpolate(
|
|
134
|
-
current.gesture.normalizedY.value,
|
|
135
|
-
[-1, 1],
|
|
136
|
-
[-screen.height * 0.5, screen.height * 0.5],
|
|
137
|
-
"clamp"
|
|
138
|
-
);
|
|
139
|
-
const translateX = interpolate(
|
|
140
|
-
current.gesture.normalizedX.value,
|
|
141
|
-
[-1, 1],
|
|
142
|
-
[-screen.width * 0.5, screen.width * 0.5],
|
|
143
|
-
"clamp"
|
|
144
|
-
);
|
|
145
|
-
return {
|
|
146
|
-
contentStyle: {
|
|
147
|
-
transform: [{ scale }, { translateY }, { translateX }]
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
},
|
|
151
|
-
transitionSpec: {
|
|
152
|
-
open: DefaultSpec,
|
|
153
|
-
close: DefaultSpec
|
|
154
|
-
},
|
|
155
|
-
...config
|
|
156
|
-
};
|
|
157
|
-
};
|
|
158
|
-
var ElasticCard = (config = { elasticFactor: 0.5 }) => {
|
|
159
|
-
return {
|
|
160
|
-
gestureEnabled: true,
|
|
161
|
-
gestureDirection: "bidirectional",
|
|
162
|
-
screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
|
|
163
|
-
"worklet";
|
|
164
|
-
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
165
|
-
const scale = interpolate(progress, [0, 1, 2], [0, 1, 0.8]);
|
|
166
|
-
const maxElasticityX = screen.width * (config.elasticFactor ?? 0.5);
|
|
167
|
-
const maxElasticityY = screen.height * (config.elasticFactor ?? 0.5);
|
|
168
|
-
const translateX = interpolate(
|
|
169
|
-
current.gesture.normalizedX.value,
|
|
170
|
-
[-1, 0, 1],
|
|
171
|
-
[-maxElasticityX, 0, maxElasticityX],
|
|
172
|
-
"clamp"
|
|
173
|
-
);
|
|
174
|
-
const translateY = interpolate(
|
|
175
|
-
current.gesture.normalizedY.value,
|
|
176
|
-
[-1, 0, 1],
|
|
177
|
-
[-maxElasticityY, 0, maxElasticityY],
|
|
178
|
-
"clamp"
|
|
179
|
-
);
|
|
180
|
-
const overlayColor = interpolateColor(
|
|
181
|
-
next?.progress.value || 0,
|
|
182
|
-
[0, 1],
|
|
183
|
-
["rgba(0,0,0,0)", "rgba(0,0,0,0.5)"]
|
|
184
|
-
);
|
|
185
|
-
return {
|
|
186
|
-
contentStyle: {
|
|
187
|
-
transform: [{ scale }, { translateX }, { translateY }]
|
|
188
|
-
},
|
|
189
|
-
overlayStyle: {
|
|
190
|
-
backgroundColor: overlayColor
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
},
|
|
194
|
-
...config
|
|
195
|
-
};
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
// src/hooks/use-screen-animation.tsx
|
|
199
|
-
import { useNavigation } from "@react-navigation/native";
|
|
200
|
-
import { useCallback, useMemo } from "react";
|
|
201
|
-
import { useWindowDimensions } from "react-native";
|
|
202
|
-
import { useSharedValue } from "react-native-reanimated";
|
|
203
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
204
|
-
|
|
205
76
|
// src/animation-engine.ts
|
|
206
77
|
import {
|
|
207
78
|
cancelAnimation,
|
|
@@ -360,7 +231,8 @@ var animationValues = {
|
|
|
360
231
|
gestureY: {},
|
|
361
232
|
normalizedGestureX: {},
|
|
362
233
|
normalizedGestureY: {},
|
|
363
|
-
gestureDragging: {}
|
|
234
|
+
gestureDragging: {},
|
|
235
|
+
isDismissing: {}
|
|
364
236
|
};
|
|
365
237
|
var triggerAnimation = (screen) => {
|
|
366
238
|
"worklet";
|
|
@@ -410,12 +282,72 @@ ScreenStore.use.subscribeWithSelector(
|
|
|
410
282
|
}
|
|
411
283
|
);
|
|
412
284
|
|
|
413
|
-
// src/utils/
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
285
|
+
// src/utils/create-config.ts
|
|
286
|
+
var createConfig = ({
|
|
287
|
+
navigation: reactNavigation,
|
|
288
|
+
route,
|
|
289
|
+
...config
|
|
290
|
+
}) => {
|
|
291
|
+
return {
|
|
292
|
+
focus: (e) => {
|
|
293
|
+
const parentNavigatorKey = reactNavigation.getParent()?.getState?.()?.key;
|
|
294
|
+
const navigatorKey = reactNavigation.getState().key;
|
|
295
|
+
ScreenStore.updateScreen(e.target, {
|
|
296
|
+
id: e.target,
|
|
297
|
+
name: route.name,
|
|
298
|
+
status: 1,
|
|
299
|
+
closing: false,
|
|
300
|
+
navigatorKey,
|
|
301
|
+
parentNavigatorKey,
|
|
302
|
+
...config
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
beforeRemove: (e) => {
|
|
306
|
+
const shouldSkipPreventDefault2 = ScreenStore.shouldSkipPreventDefault(
|
|
307
|
+
e.target,
|
|
308
|
+
reactNavigation.getState()
|
|
309
|
+
);
|
|
310
|
+
if (shouldSkipPreventDefault2) {
|
|
311
|
+
ScreenStore.removeScreen(e.target);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
e.preventDefault();
|
|
315
|
+
const handleFinish = (finished) => {
|
|
316
|
+
if (!finished) return;
|
|
317
|
+
if (reactNavigation.canGoBack()) {
|
|
318
|
+
reactNavigation.dispatch(e.data?.action);
|
|
319
|
+
ScreenStore.removeScreen(e.target);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
ScreenStore.updateScreen(e.target, {
|
|
323
|
+
status: 0,
|
|
324
|
+
closing: true,
|
|
325
|
+
onAnimationFinish: handleFinish
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
var createScreenConfig = (config) => {
|
|
331
|
+
return {
|
|
332
|
+
listeners: (l) => createConfig({ ...l, ...config || {} })
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// src/utils/default-screen-options.ts
|
|
337
|
+
var defaultScreenOptions = () => ({
|
|
338
|
+
presentation: "containedTransparentModal",
|
|
339
|
+
headerShown: false,
|
|
340
|
+
animation: "none"
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// src/utils/noop-interpolator.ts
|
|
344
|
+
var noopinterpolator = () => {
|
|
345
|
+
"worklet";
|
|
346
|
+
return {
|
|
347
|
+
contentStyle: {},
|
|
348
|
+
overlayStyle: {}
|
|
349
|
+
};
|
|
350
|
+
};
|
|
419
351
|
|
|
420
352
|
// src/utils/gesture/apply-gesture-activation-criteria.ts
|
|
421
353
|
var applyGestureActivationCriteria = ({
|
|
@@ -501,153 +433,329 @@ var mapGestureToProgress = (translation, dimension) => {
|
|
|
501
433
|
return Math.max(0, Math.min(1, rawProgress));
|
|
502
434
|
};
|
|
503
435
|
|
|
504
|
-
// src/
|
|
505
|
-
|
|
436
|
+
// src/hooks/use-key.tsx
|
|
437
|
+
import { useRoute } from "@react-navigation/native";
|
|
438
|
+
var useKey = () => useRoute().key;
|
|
439
|
+
|
|
440
|
+
// src/hooks/use-build-gestures.tsx
|
|
441
|
+
var GESTURE_VELOCITY_IMPACT = 0.3;
|
|
506
442
|
var DEFAULT_GESTURE_RESPONSE_DISTANCE = 50;
|
|
507
|
-
var
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
width,
|
|
512
|
-
height,
|
|
513
|
-
handleDismiss
|
|
443
|
+
var DEFAULT_GESTURE_DIRECTION = "horizontal";
|
|
444
|
+
var DEFAULT_GESTURE_ENABLED = false;
|
|
445
|
+
var useBuildGestures = ({
|
|
446
|
+
scrollProgress
|
|
514
447
|
}) => {
|
|
515
|
-
const
|
|
516
|
-
const
|
|
517
|
-
const
|
|
518
|
-
const
|
|
519
|
-
|
|
448
|
+
const key = useKey();
|
|
449
|
+
const dimensions = useWindowDimensions();
|
|
450
|
+
const navigation = useNavigation();
|
|
451
|
+
const currentScreen = ScreenStore.use(
|
|
452
|
+
useCallback((state) => state.screens[key], [key])
|
|
453
|
+
);
|
|
454
|
+
const handleDismiss = useCallback(
|
|
455
|
+
(screenBeingDismissed) => {
|
|
456
|
+
ScreenStore.handleScreenDismiss(screenBeingDismissed, navigation);
|
|
457
|
+
},
|
|
458
|
+
[navigation]
|
|
459
|
+
);
|
|
460
|
+
const initialTouch = useSharedValue2({
|
|
461
|
+
x: 0,
|
|
462
|
+
y: 0
|
|
463
|
+
});
|
|
464
|
+
const translateX = animationValues.gestureX[key];
|
|
465
|
+
const translateY = animationValues.gestureY[key];
|
|
466
|
+
const normalizedGestureX = animationValues.normalizedGestureX[key];
|
|
467
|
+
const normalizedGestureY = animationValues.normalizedGestureY[key];
|
|
468
|
+
const isDragging = animationValues.gestureDragging[key];
|
|
469
|
+
const isDismissing = animationValues.isDismissing[key];
|
|
470
|
+
const progress = animationValues.screenProgress[key] || 0;
|
|
520
471
|
const {
|
|
521
|
-
gestureDirection =
|
|
522
|
-
gestureEnabled =
|
|
523
|
-
transitionSpec
|
|
472
|
+
gestureDirection = DEFAULT_GESTURE_DIRECTION,
|
|
473
|
+
gestureEnabled = DEFAULT_GESTURE_ENABLED,
|
|
474
|
+
transitionSpec = {
|
|
475
|
+
open: DefaultSpec,
|
|
476
|
+
close: DefaultSpec
|
|
477
|
+
},
|
|
524
478
|
gestureVelocityImpact = GESTURE_VELOCITY_IMPACT,
|
|
525
479
|
gestureResponseDistance = DEFAULT_GESTURE_RESPONSE_DISTANCE
|
|
526
|
-
} =
|
|
480
|
+
} = currentScreen ?? {};
|
|
527
481
|
const directions = Array.isArray(gestureDirection) ? gestureDirection : [gestureDirection];
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
);
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
const allowedDown = directions.includes("vertical");
|
|
556
|
-
const allowedUp = directions.includes("vertical-inverted");
|
|
557
|
-
const allowedRight = directions.includes("horizontal");
|
|
558
|
-
const allowedLeft = directions.includes("horizontal-inverted");
|
|
559
|
-
if (allowedRight || allowedLeft) {
|
|
560
|
-
const absX = Math.abs(event.translationX);
|
|
561
|
-
const currentProgress = mapGestureToProgress(absX, width);
|
|
562
|
-
maxProgress = Math.max(maxProgress, currentProgress);
|
|
482
|
+
const nativeGesture = Gesture2.Native();
|
|
483
|
+
const onTouchesDown = useCallback(
|
|
484
|
+
(e) => {
|
|
485
|
+
"worklet";
|
|
486
|
+
const firstTouch = e.changedTouches[0];
|
|
487
|
+
initialTouch.value = { x: firstTouch.x, y: firstTouch.y };
|
|
488
|
+
},
|
|
489
|
+
[initialTouch]
|
|
490
|
+
);
|
|
491
|
+
const onTouchesMove = useCallback(
|
|
492
|
+
(e, manager) => {
|
|
493
|
+
"worklet";
|
|
494
|
+
const touch = e.changedTouches[0];
|
|
495
|
+
const deltaX = touch.x - initialTouch.value.x;
|
|
496
|
+
const deltaY = touch.y - initialTouch.value.y;
|
|
497
|
+
const isVerticalSwipe = Math.abs(deltaY) > Math.abs(deltaX);
|
|
498
|
+
const isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY);
|
|
499
|
+
const isSwipingDown = isVerticalSwipe && deltaY > 0;
|
|
500
|
+
const isSwipingUp = isVerticalSwipe && deltaY < 0;
|
|
501
|
+
const isSwipingRight = isHorizontalSwipe && deltaX > 0;
|
|
502
|
+
const isSwipingLeft = isHorizontalSwipe && deltaX < 0;
|
|
503
|
+
const minMovement = 5;
|
|
504
|
+
const hasEnoughMovement = Math.abs(deltaX) > minMovement || Math.abs(deltaY) > minMovement;
|
|
505
|
+
if (!hasEnoughMovement) return;
|
|
506
|
+
if (isDragging.value) {
|
|
507
|
+
manager.activate();
|
|
508
|
+
return;
|
|
563
509
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
510
|
+
let shouldActivate = false;
|
|
511
|
+
for (const direction of directions) {
|
|
512
|
+
switch (direction) {
|
|
513
|
+
case "vertical":
|
|
514
|
+
if (isSwipingDown) {
|
|
515
|
+
shouldActivate = scrollProgress.value.y <= 0;
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
case "vertical-inverted":
|
|
519
|
+
if (isSwipingUp) {
|
|
520
|
+
const maxScrollableY = scrollProgress.value.contentHeight - scrollProgress.value.layoutHeight;
|
|
521
|
+
shouldActivate = scrollProgress.value.y >= maxScrollableY;
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
case "horizontal":
|
|
525
|
+
if (isSwipingRight) {
|
|
526
|
+
shouldActivate = scrollProgress.value.x <= 0;
|
|
527
|
+
}
|
|
528
|
+
break;
|
|
529
|
+
case "horizontal-inverted":
|
|
530
|
+
if (isSwipingLeft) {
|
|
531
|
+
const maxProgress = scrollProgress.value.contentWidth - scrollProgress.value.layoutWidth;
|
|
532
|
+
shouldActivate = scrollProgress.value.x >= maxProgress;
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
case "bidirectional":
|
|
536
|
+
if (isSwipingDown) {
|
|
537
|
+
shouldActivate = scrollProgress.value.y <= 0;
|
|
538
|
+
} else if (isSwipingUp) {
|
|
539
|
+
shouldActivate = scrollProgress.value.y <= 0;
|
|
540
|
+
} else if (isSwipingRight || isSwipingLeft) {
|
|
541
|
+
shouldActivate = true;
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
if (shouldActivate) break;
|
|
568
546
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
547
|
+
if ((shouldActivate || isDragging.value) && !isDismissing.value) {
|
|
548
|
+
manager.activate();
|
|
549
|
+
} else {
|
|
550
|
+
manager.fail();
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
[initialTouch, directions, scrollProgress, isDragging, isDismissing]
|
|
554
|
+
);
|
|
555
|
+
const onStart = useCallback(() => {
|
|
573
556
|
"worklet";
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
557
|
+
isDragging.value = 1;
|
|
558
|
+
isDismissing.value = 0;
|
|
559
|
+
}, [isDragging, isDismissing]);
|
|
560
|
+
const onUpdate = useCallback(
|
|
561
|
+
(event) => {
|
|
562
|
+
"worklet";
|
|
563
|
+
let gestureProgress = 0;
|
|
564
|
+
translateX.value = event.translationX;
|
|
565
|
+
translateY.value = event.translationY;
|
|
566
|
+
normalizedGestureX.value = interpolate(
|
|
567
|
+
event.translationX,
|
|
568
|
+
[-dimensions.width, dimensions.width],
|
|
569
|
+
[-1, 1],
|
|
570
|
+
"clamp"
|
|
580
571
|
);
|
|
581
|
-
|
|
582
|
-
translationY
|
|
572
|
+
normalizedGestureY.value = interpolate(
|
|
573
|
+
event.translationY,
|
|
574
|
+
[-dimensions.height, dimensions.height],
|
|
575
|
+
[-1, 1],
|
|
576
|
+
"clamp"
|
|
583
577
|
);
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
578
|
+
if (directions.includes("bidirectional")) {
|
|
579
|
+
const distance = Math.sqrt(
|
|
580
|
+
event.translationX ** 2 + event.translationY ** 2
|
|
581
|
+
);
|
|
582
|
+
gestureProgress = mapGestureToProgress(distance, dimensions.width);
|
|
583
|
+
} else {
|
|
584
|
+
let maxProgress = 0;
|
|
585
|
+
const allowedDown = directions.includes("vertical");
|
|
586
|
+
const allowedUp = directions.includes("vertical-inverted");
|
|
587
|
+
const allowedRight = directions.includes("horizontal");
|
|
588
|
+
const allowedLeft = directions.includes("horizontal-inverted");
|
|
589
|
+
if (allowedRight && event.translationX > 0) {
|
|
590
|
+
const currentProgress = mapGestureToProgress(
|
|
591
|
+
event.translationX,
|
|
592
|
+
dimensions.width
|
|
593
|
+
);
|
|
594
|
+
maxProgress = Math.max(maxProgress, currentProgress);
|
|
595
|
+
}
|
|
596
|
+
if (allowedLeft && event.translationX < 0) {
|
|
597
|
+
const currentProgress = mapGestureToProgress(
|
|
598
|
+
-event.translationX,
|
|
599
|
+
dimensions.width
|
|
600
|
+
);
|
|
601
|
+
maxProgress = Math.max(maxProgress, currentProgress);
|
|
602
|
+
}
|
|
603
|
+
if (allowedDown && event.translationY > 0) {
|
|
604
|
+
const currentProgress = mapGestureToProgress(
|
|
605
|
+
event.translationY,
|
|
606
|
+
dimensions.height
|
|
607
|
+
);
|
|
608
|
+
maxProgress = Math.max(maxProgress, currentProgress);
|
|
609
|
+
}
|
|
610
|
+
if (allowedUp && event.translationY < 0) {
|
|
611
|
+
const currentProgress = mapGestureToProgress(
|
|
612
|
+
-event.translationY,
|
|
613
|
+
dimensions.height
|
|
614
|
+
);
|
|
615
|
+
maxProgress = Math.max(maxProgress, currentProgress);
|
|
616
|
+
}
|
|
617
|
+
gestureProgress = maxProgress;
|
|
599
618
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
619
|
+
progress.value = 1 - gestureProgress;
|
|
620
|
+
},
|
|
621
|
+
[
|
|
622
|
+
dimensions,
|
|
623
|
+
directions,
|
|
624
|
+
translateX,
|
|
625
|
+
translateY,
|
|
626
|
+
normalizedGestureX,
|
|
627
|
+
normalizedGestureY,
|
|
628
|
+
progress
|
|
629
|
+
]
|
|
630
|
+
);
|
|
631
|
+
const onEnd = useCallback(
|
|
632
|
+
(event) => {
|
|
604
633
|
"worklet";
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
634
|
+
const { translationX, translationY, velocityX, velocityY } = event;
|
|
635
|
+
const dismissThreshold = 0.5;
|
|
636
|
+
if (directions.includes("bidirectional")) {
|
|
637
|
+
const finalX = Math.abs(
|
|
638
|
+
translationX + velocityX * gestureVelocityImpact
|
|
639
|
+
);
|
|
640
|
+
const finalY = Math.abs(
|
|
641
|
+
translationY + velocityY * gestureVelocityImpact
|
|
642
|
+
);
|
|
643
|
+
const finalDistance = Math.sqrt(finalX ** 2 + finalY ** 2);
|
|
644
|
+
isDismissing.value = Number(
|
|
645
|
+
finalDistance > dimensions.width * dismissThreshold
|
|
646
|
+
);
|
|
647
|
+
} else {
|
|
648
|
+
const allowedDown = directions.includes("vertical");
|
|
649
|
+
const allowedUp = directions.includes("vertical-inverted");
|
|
650
|
+
const allowedRight = directions.includes("horizontal");
|
|
651
|
+
const allowedLeft = directions.includes("horizontal-inverted");
|
|
652
|
+
if (allowedRight && translationX + velocityX * gestureVelocityImpact > dimensions.width * dismissThreshold) {
|
|
653
|
+
isDismissing.value = 1;
|
|
654
|
+
} else if (allowedLeft && -translationX - velocityX * gestureVelocityImpact > dimensions.width * dismissThreshold) {
|
|
655
|
+
isDismissing.value = 1;
|
|
656
|
+
} else if (allowedDown && translationY + velocityY * gestureVelocityImpact > dimensions.height * dismissThreshold) {
|
|
657
|
+
isDismissing.value = 1;
|
|
658
|
+
} else if (allowedUp && -translationY - velocityY * gestureVelocityImpact > dimensions.height * dismissThreshold) {
|
|
659
|
+
isDismissing.value = 1;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const finalProgress = isDismissing.value ? 0 : 1;
|
|
663
|
+
const spec = isDismissing.value ? transitionSpec?.close : transitionSpec?.open;
|
|
664
|
+
const onFinish = isDismissing.value ? (isFinished) => {
|
|
665
|
+
"worklet";
|
|
666
|
+
if (isFinished) runOnJS2(handleDismiss)(currentScreen?.id);
|
|
667
|
+
} : void 0;
|
|
668
|
+
progress.value = animate(finalProgress, spec, onFinish);
|
|
669
|
+
translateX.value = animate(0, spec);
|
|
670
|
+
translateY.value = animate(0, spec);
|
|
671
|
+
normalizedGestureX.value = animate(0, spec);
|
|
672
|
+
normalizedGestureY.value = animate(0, spec);
|
|
673
|
+
isDragging.value = 0;
|
|
674
|
+
},
|
|
675
|
+
[
|
|
676
|
+
dimensions,
|
|
677
|
+
directions,
|
|
678
|
+
translateX,
|
|
679
|
+
translateY,
|
|
680
|
+
normalizedGestureX,
|
|
681
|
+
normalizedGestureY,
|
|
682
|
+
progress,
|
|
683
|
+
handleDismiss,
|
|
684
|
+
currentScreen?.id,
|
|
685
|
+
transitionSpec?.close,
|
|
686
|
+
transitionSpec?.open,
|
|
687
|
+
gestureVelocityImpact,
|
|
688
|
+
isDragging,
|
|
689
|
+
isDismissing
|
|
690
|
+
]
|
|
691
|
+
);
|
|
692
|
+
const panGesture = useMemo(
|
|
693
|
+
() => Gesture2.Pan().enabled(gestureEnabled).manualActivation(true).onTouchesDown(onTouchesDown).onTouchesMove(onTouchesMove).onStart(onStart).onUpdate(onUpdate).onEnd(onEnd).blocksExternalGesture(nativeGesture),
|
|
694
|
+
[
|
|
695
|
+
gestureEnabled,
|
|
696
|
+
nativeGesture,
|
|
697
|
+
onTouchesDown,
|
|
698
|
+
onTouchesMove,
|
|
699
|
+
onStart,
|
|
700
|
+
onUpdate,
|
|
701
|
+
onEnd
|
|
702
|
+
]
|
|
703
|
+
);
|
|
613
704
|
applyGestureActivationCriteria({
|
|
614
705
|
gestureDirection,
|
|
615
706
|
gestureResponseDistance,
|
|
616
707
|
panGesture
|
|
617
708
|
});
|
|
618
|
-
return panGesture;
|
|
709
|
+
return { panGesture, nativeGesture };
|
|
619
710
|
};
|
|
620
711
|
|
|
621
|
-
// src/
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
712
|
+
// src/components/transition-gesture-handler-provider.tsx
|
|
713
|
+
import { jsx } from "react/jsx-runtime";
|
|
714
|
+
var TransitionGestureHandlerProvider = ({
|
|
715
|
+
children
|
|
716
|
+
}) => {
|
|
717
|
+
const scrollProgress = useSharedValue3({
|
|
718
|
+
x: 0,
|
|
719
|
+
y: 0,
|
|
720
|
+
contentHeight: 0,
|
|
721
|
+
contentWidth: 0,
|
|
722
|
+
layoutHeight: 0,
|
|
723
|
+
layoutWidth: 0
|
|
724
|
+
});
|
|
725
|
+
const { panGesture, nativeGesture } = useBuildGestures({
|
|
726
|
+
scrollProgress
|
|
727
|
+
});
|
|
728
|
+
const value = useMemo2(() => {
|
|
729
|
+
return {
|
|
730
|
+
panGesture,
|
|
731
|
+
scrollProgress,
|
|
732
|
+
nativeGesture
|
|
733
|
+
};
|
|
734
|
+
}, [panGesture, scrollProgress, nativeGesture]);
|
|
735
|
+
return /* @__PURE__ */ jsx(GestureContext.Provider, { value, children: /* @__PURE__ */ jsx(GestureDetector, { gesture: panGesture, children }) });
|
|
628
736
|
};
|
|
629
737
|
|
|
630
|
-
// src/hooks/use-key.tsx
|
|
631
|
-
import { useRoute } from "@react-navigation/native";
|
|
632
|
-
var useKey = () => useRoute().key;
|
|
633
|
-
|
|
634
738
|
// src/hooks/use-screen-animation.tsx
|
|
739
|
+
import { useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
740
|
+
import { useWindowDimensions as useWindowDimensions2 } from "react-native";
|
|
741
|
+
import { useSharedValue as useSharedValue4 } from "react-native-reanimated";
|
|
742
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
635
743
|
var useAnimationBuilder = () => {
|
|
636
744
|
const key = useKey();
|
|
637
|
-
const dimensions =
|
|
745
|
+
const dimensions = useWindowDimensions2();
|
|
638
746
|
const insets = useSafeAreaInsets();
|
|
639
|
-
const
|
|
640
|
-
const
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const
|
|
644
|
-
const
|
|
645
|
-
const
|
|
747
|
+
const progressFallback = useSharedValue4(0);
|
|
748
|
+
const gestureDraggingFallback = useSharedValue4(0);
|
|
749
|
+
const gestureXFallback = useSharedValue4(0);
|
|
750
|
+
const gestureYFallback = useSharedValue4(0);
|
|
751
|
+
const normalizedGestureXFallback = useSharedValue4(0);
|
|
752
|
+
const normalizedGestureYFallback = useSharedValue4(0);
|
|
753
|
+
const isDismissingFallback = useSharedValue4(0);
|
|
646
754
|
const currentScreen = ScreenStore.use(
|
|
647
|
-
|
|
755
|
+
useCallback2((state) => state.screens[key], [key])
|
|
648
756
|
);
|
|
649
757
|
const actualNextScreen = ScreenStore.use(
|
|
650
|
-
|
|
758
|
+
useCallback2(
|
|
651
759
|
(state) => {
|
|
652
760
|
const current = state.screens[key];
|
|
653
761
|
if (!current) return void 0;
|
|
@@ -659,26 +767,7 @@ var useAnimationBuilder = () => {
|
|
|
659
767
|
[key]
|
|
660
768
|
)
|
|
661
769
|
);
|
|
662
|
-
const
|
|
663
|
-
() => buildGestureDetector({
|
|
664
|
-
key,
|
|
665
|
-
progress: animationValues.screenProgress[key],
|
|
666
|
-
screenState: currentScreen || {
|
|
667
|
-
id: key,
|
|
668
|
-
name: key,
|
|
669
|
-
index: 0,
|
|
670
|
-
status: 0,
|
|
671
|
-
closing: false
|
|
672
|
-
},
|
|
673
|
-
width: dimensions.width,
|
|
674
|
-
height: dimensions.height,
|
|
675
|
-
handleDismiss: (screenBeingDismissed) => {
|
|
676
|
-
ScreenStore.handleScreenDismiss(screenBeingDismissed, navigation);
|
|
677
|
-
}
|
|
678
|
-
}),
|
|
679
|
-
[key, currentScreen, dimensions, navigation]
|
|
680
|
-
);
|
|
681
|
-
const getAnimationValuesForScreen = useCallback(
|
|
770
|
+
const getAnimationValuesForScreen = useCallback2(
|
|
682
771
|
(screenId) => ({
|
|
683
772
|
progress: animationValues.screenProgress[screenId] || progressFallback,
|
|
684
773
|
gesture: {
|
|
@@ -686,7 +775,8 @@ var useAnimationBuilder = () => {
|
|
|
686
775
|
x: animationValues.gestureX[screenId] || gestureXFallback,
|
|
687
776
|
y: animationValues.gestureY[screenId] || gestureYFallback,
|
|
688
777
|
normalizedX: animationValues.normalizedGestureX[screenId] || normalizedGestureXFallback,
|
|
689
|
-
normalizedY: animationValues.normalizedGestureY[screenId] || normalizedGestureYFallback
|
|
778
|
+
normalizedY: animationValues.normalizedGestureY[screenId] || normalizedGestureYFallback,
|
|
779
|
+
isDismissing: animationValues.isDismissing[screenId] || isDismissingFallback
|
|
690
780
|
}
|
|
691
781
|
}),
|
|
692
782
|
[
|
|
@@ -695,18 +785,18 @@ var useAnimationBuilder = () => {
|
|
|
695
785
|
gestureXFallback,
|
|
696
786
|
gestureYFallback,
|
|
697
787
|
normalizedGestureXFallback,
|
|
698
|
-
normalizedGestureYFallback
|
|
788
|
+
normalizedGestureYFallback,
|
|
789
|
+
isDismissingFallback
|
|
699
790
|
]
|
|
700
791
|
);
|
|
701
|
-
return
|
|
792
|
+
return useMemo3(() => {
|
|
702
793
|
return {
|
|
703
794
|
current: getAnimationValuesForScreen(key),
|
|
704
795
|
next: actualNextScreen ? getAnimationValuesForScreen(actualNextScreen.id) : void 0,
|
|
705
796
|
layouts: { screen: dimensions },
|
|
706
797
|
insets,
|
|
707
798
|
closing: currentScreen?.closing || false,
|
|
708
|
-
screenStyleInterpolator: actualNextScreen?.screenStyleInterpolator || currentScreen?.screenStyleInterpolator || noopinterpolator
|
|
709
|
-
gestureDetector: panGesture
|
|
799
|
+
screenStyleInterpolator: actualNextScreen?.screenStyleInterpolator || currentScreen?.screenStyleInterpolator || noopinterpolator
|
|
710
800
|
};
|
|
711
801
|
}, [
|
|
712
802
|
key,
|
|
@@ -714,7 +804,6 @@ var useAnimationBuilder = () => {
|
|
|
714
804
|
actualNextScreen,
|
|
715
805
|
dimensions,
|
|
716
806
|
insets,
|
|
717
|
-
panGesture,
|
|
718
807
|
getAnimationValuesForScreen
|
|
719
808
|
]);
|
|
720
809
|
};
|
|
@@ -722,73 +811,15 @@ var _useScreenAnimation = () => {
|
|
|
722
811
|
return useAnimationBuilder();
|
|
723
812
|
};
|
|
724
813
|
var useScreenAnimation = () => {
|
|
725
|
-
const {
|
|
726
|
-
screenStyleInterpolator: _,
|
|
727
|
-
gestureDetector: __,
|
|
728
|
-
...animationProps
|
|
729
|
-
} = useAnimationBuilder();
|
|
814
|
+
const { screenStyleInterpolator: _, ...animationProps } = useAnimationBuilder();
|
|
730
815
|
return animationProps;
|
|
731
816
|
};
|
|
732
817
|
|
|
733
|
-
// src/utils/create-config.ts
|
|
734
|
-
var createConfig = ({
|
|
735
|
-
navigation: reactNavigation,
|
|
736
|
-
route,
|
|
737
|
-
...config
|
|
738
|
-
}) => {
|
|
739
|
-
return {
|
|
740
|
-
focus: (e) => {
|
|
741
|
-
const parentNavigatorKey = reactNavigation.getParent()?.getState?.()?.key;
|
|
742
|
-
const navigatorKey = reactNavigation.getState().key;
|
|
743
|
-
ScreenStore.updateScreen(e.target, {
|
|
744
|
-
id: e.target,
|
|
745
|
-
name: route.name,
|
|
746
|
-
status: 1,
|
|
747
|
-
closing: false,
|
|
748
|
-
navigatorKey,
|
|
749
|
-
parentNavigatorKey,
|
|
750
|
-
...config
|
|
751
|
-
});
|
|
752
|
-
},
|
|
753
|
-
beforeRemove: (e) => {
|
|
754
|
-
const shouldSkipPreventDefault2 = ScreenStore.shouldSkipPreventDefault(
|
|
755
|
-
e.target,
|
|
756
|
-
reactNavigation.getState()
|
|
757
|
-
);
|
|
758
|
-
if (shouldSkipPreventDefault2) {
|
|
759
|
-
ScreenStore.removeScreen(e.target);
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
e.preventDefault();
|
|
763
|
-
const handleFinish = (finished) => {
|
|
764
|
-
if (!finished) return;
|
|
765
|
-
if (reactNavigation.canGoBack()) {
|
|
766
|
-
reactNavigation.dispatch(e.data?.action);
|
|
767
|
-
ScreenStore.removeScreen(e.target);
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
ScreenStore.updateScreen(e.target, {
|
|
771
|
-
status: 0,
|
|
772
|
-
closing: true,
|
|
773
|
-
onAnimationFinish: handleFinish
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
};
|
|
778
|
-
|
|
779
|
-
// src/utils/create-transition-component.tsx
|
|
780
|
-
import { forwardRef, memo } from "react";
|
|
781
|
-
import { StyleSheet } from "react-native";
|
|
782
|
-
import { GestureDetector } from "react-native-gesture-handler";
|
|
783
|
-
import Animated, {
|
|
784
|
-
useAnimatedStyle as useAnimatedStyle2
|
|
785
|
-
} from "react-native-reanimated";
|
|
786
|
-
|
|
787
818
|
// src/hooks/use-skip-first-frame.tsx
|
|
788
819
|
import { useEffect } from "react";
|
|
789
|
-
import { useAnimatedStyle, useSharedValue as
|
|
820
|
+
import { useAnimatedStyle, useSharedValue as useSharedValue5 } from "react-native-reanimated";
|
|
790
821
|
var useSkipFirstFrame = () => {
|
|
791
|
-
const opacity =
|
|
822
|
+
const opacity = useSharedValue5(0);
|
|
792
823
|
const style = useAnimatedStyle(() => {
|
|
793
824
|
"worklet";
|
|
794
825
|
return {
|
|
@@ -803,18 +834,14 @@ var useSkipFirstFrame = () => {
|
|
|
803
834
|
return { style };
|
|
804
835
|
};
|
|
805
836
|
|
|
806
|
-
// src/
|
|
807
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
808
|
-
function
|
|
837
|
+
// src/components/create-transition-aware-component.tsx
|
|
838
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
839
|
+
function createTransitionAwareComponent(Wrapped) {
|
|
809
840
|
const AnimatedComponent = Animated.createAnimatedComponent(Wrapped);
|
|
810
841
|
const Inner = forwardRef(
|
|
811
842
|
(props, ref) => {
|
|
812
843
|
const { children, style, ...rest } = props;
|
|
813
|
-
const {
|
|
814
|
-
screenStyleInterpolator,
|
|
815
|
-
gestureDetector,
|
|
816
|
-
...screenInterpolationProps
|
|
817
|
-
} = _useScreenAnimation();
|
|
844
|
+
const { screenStyleInterpolator, ...screenInterpolationProps } = _useScreenAnimation();
|
|
818
845
|
const screenContainerStyle = useAnimatedStyle2(() => {
|
|
819
846
|
"worklet";
|
|
820
847
|
return screenStyleInterpolator(screenInterpolationProps).contentStyle || {};
|
|
@@ -824,8 +851,15 @@ function createTransitionComponent(Wrapped) {
|
|
|
824
851
|
return screenStyleInterpolator(screenInterpolationProps).overlayStyle || {};
|
|
825
852
|
});
|
|
826
853
|
const { style: flickerFixStyle } = useSkipFirstFrame();
|
|
827
|
-
return /* @__PURE__ */ jsxs(Animated.View, { style: [{ flex: 1 }, flickerFixStyle], children: [
|
|
828
|
-
/* @__PURE__ */
|
|
854
|
+
return /* @__PURE__ */ jsx2(TransitionGestureHandlerProvider, { children: /* @__PURE__ */ jsxs(Animated.View, { style: [{ flex: 1 }, flickerFixStyle], children: [
|
|
855
|
+
/* @__PURE__ */ jsx2(
|
|
856
|
+
Animated.View,
|
|
857
|
+
{
|
|
858
|
+
style: [StyleSheet.absoluteFillObject, overlayStyle],
|
|
859
|
+
pointerEvents: "none"
|
|
860
|
+
}
|
|
861
|
+
),
|
|
862
|
+
/* @__PURE__ */ jsx2(
|
|
829
863
|
AnimatedComponent,
|
|
830
864
|
{
|
|
831
865
|
...rest,
|
|
@@ -837,41 +871,406 @@ function createTransitionComponent(Wrapped) {
|
|
|
837
871
|
],
|
|
838
872
|
children
|
|
839
873
|
}
|
|
840
|
-
) }),
|
|
841
|
-
/* @__PURE__ */ jsx(
|
|
842
|
-
Animated.View,
|
|
843
|
-
{
|
|
844
|
-
style: [
|
|
845
|
-
StyleSheet.absoluteFillObject,
|
|
846
|
-
overlayStyle,
|
|
847
|
-
{ zIndex: 1e4 }
|
|
848
|
-
],
|
|
849
|
-
pointerEvents: "none"
|
|
850
|
-
}
|
|
851
874
|
)
|
|
852
|
-
] });
|
|
875
|
+
] }) });
|
|
853
876
|
}
|
|
854
877
|
);
|
|
855
878
|
Inner.displayName = `Transition(${Wrapped.displayName || Wrapped.name || "Component"})`;
|
|
856
879
|
return memo(Inner);
|
|
857
880
|
}
|
|
858
881
|
|
|
859
|
-
// src/
|
|
860
|
-
|
|
882
|
+
// src/components/create-transition-aware-scrollable.tsx
|
|
883
|
+
import { forwardRef as forwardRef2, memo as memo2 } from "react";
|
|
884
|
+
import { View } from "react-native";
|
|
885
|
+
import { GestureDetector as GestureDetector2 } from "react-native-gesture-handler";
|
|
886
|
+
import Animated2 from "react-native-reanimated";
|
|
887
|
+
|
|
888
|
+
// src/hooks/use-scroll-progress.tsx
|
|
889
|
+
import { useCallback as useCallback3 } from "react";
|
|
890
|
+
import { useAnimatedScrollHandler } from "react-native-reanimated";
|
|
891
|
+
var useScrollProgress = (props) => {
|
|
892
|
+
const { scrollProgress } = useGestureContext();
|
|
893
|
+
const scrollHandler = useAnimatedScrollHandler({
|
|
894
|
+
onScroll: (event) => {
|
|
895
|
+
scrollProgress.modify((value) => {
|
|
896
|
+
"worklet";
|
|
897
|
+
return {
|
|
898
|
+
...value,
|
|
899
|
+
x: event.contentOffset.x,
|
|
900
|
+
y: event.contentOffset.y,
|
|
901
|
+
layoutHeight: event.layoutMeasurement.height,
|
|
902
|
+
layoutWidth: event.layoutMeasurement.width,
|
|
903
|
+
contentHeight: event.contentSize.height,
|
|
904
|
+
contentWidth: event.contentSize.width
|
|
905
|
+
};
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
const onContentSizeChange = useCallback3(
|
|
910
|
+
(width, height) => {
|
|
911
|
+
props.onContentSizeChange?.(width, height);
|
|
912
|
+
scrollProgress.modify((value) => {
|
|
913
|
+
"worklet";
|
|
914
|
+
return {
|
|
915
|
+
...value,
|
|
916
|
+
contentWidth: width,
|
|
917
|
+
contentHeight: height
|
|
918
|
+
};
|
|
919
|
+
});
|
|
920
|
+
},
|
|
921
|
+
[scrollProgress, props.onContentSizeChange]
|
|
922
|
+
);
|
|
923
|
+
return {
|
|
924
|
+
scrollHandler,
|
|
925
|
+
onContentSizeChange
|
|
926
|
+
};
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
// src/components/create-transition-aware-scrollable.tsx
|
|
930
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
931
|
+
function createTransitionAwareScrollable(ScrollableComponent) {
|
|
932
|
+
const WithTransitionAwareness = createTransitionAwareComponent(View);
|
|
933
|
+
const AnimatedScrollableComponent = Animated2.createAnimatedComponent(ScrollableComponent);
|
|
934
|
+
const WithScrollAwareness = forwardRef2((props, ref) => {
|
|
935
|
+
const { nativeGesture } = useGestureContext();
|
|
936
|
+
const { scrollHandler, onContentSizeChange } = useScrollProgress({
|
|
937
|
+
onScroll: props.onScroll,
|
|
938
|
+
onContentSizeChange: props.onContentSizeChange
|
|
939
|
+
});
|
|
940
|
+
return /* @__PURE__ */ jsx3(GestureDetector2, { gesture: nativeGesture, children: /* @__PURE__ */ jsx3(
|
|
941
|
+
AnimatedScrollableComponent,
|
|
942
|
+
{
|
|
943
|
+
...props,
|
|
944
|
+
ref,
|
|
945
|
+
onScroll: scrollHandler,
|
|
946
|
+
onContentSizeChange,
|
|
947
|
+
scrollEventThrottle: props.scrollEventThrottle || 16
|
|
948
|
+
}
|
|
949
|
+
) });
|
|
950
|
+
});
|
|
951
|
+
const Wrapped = forwardRef2((props, ref) => {
|
|
952
|
+
const { isPlaceholder } = useGestureContext();
|
|
953
|
+
if (isPlaceholder) {
|
|
954
|
+
return /* @__PURE__ */ jsx3(WithTransitionAwareness, { children: /* @__PURE__ */ jsx3(WithScrollAwareness, { ...props, ref }) });
|
|
955
|
+
}
|
|
956
|
+
return /* @__PURE__ */ jsx3(WithScrollAwareness, { ...props, ref });
|
|
957
|
+
});
|
|
958
|
+
WithScrollAwareness.displayName = `Transition(${ScrollableComponent.displayName || ScrollableComponent.name || "Component"})`;
|
|
959
|
+
return memo2(Wrapped);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// src/configs/presets.ts
|
|
963
|
+
var presets_exports = {};
|
|
964
|
+
__export(presets_exports, {
|
|
965
|
+
DraggableCard: () => DraggableCard,
|
|
966
|
+
ElasticCard: () => ElasticCard,
|
|
967
|
+
SlideFromBottom: () => SlideFromBottom,
|
|
968
|
+
SlideFromTop: () => SlideFromTop,
|
|
969
|
+
ZoomIn: () => ZoomIn
|
|
970
|
+
});
|
|
971
|
+
import {
|
|
972
|
+
Extrapolation,
|
|
973
|
+
interpolate as interpolate2,
|
|
974
|
+
interpolateColor
|
|
975
|
+
} from "react-native-reanimated";
|
|
976
|
+
var SlideFromTop = (config = {}) => {
|
|
977
|
+
return {
|
|
978
|
+
gestureEnabled: true,
|
|
979
|
+
gestureDirection: "vertical-inverted",
|
|
980
|
+
screenStyleInterpolator: ({
|
|
981
|
+
current,
|
|
982
|
+
next,
|
|
983
|
+
layouts: {
|
|
984
|
+
screen: { height }
|
|
985
|
+
}
|
|
986
|
+
}) => {
|
|
987
|
+
"worklet";
|
|
988
|
+
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
989
|
+
const y = interpolate2(progress, [0, 1, 2], [-height, 0, height]);
|
|
990
|
+
return {
|
|
991
|
+
contentStyle: {
|
|
992
|
+
transform: [{ translateY: y }]
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
},
|
|
996
|
+
transitionSpec: {
|
|
997
|
+
open: DefaultSpec,
|
|
998
|
+
close: DefaultSpec
|
|
999
|
+
},
|
|
1000
|
+
...config
|
|
1001
|
+
};
|
|
1002
|
+
};
|
|
1003
|
+
var ZoomIn = (config = {}) => {
|
|
1004
|
+
return {
|
|
1005
|
+
gestureEnabled: false,
|
|
1006
|
+
screenStyleInterpolator: ({ current, next }) => {
|
|
1007
|
+
"worklet";
|
|
1008
|
+
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
1009
|
+
const scale = interpolate2(
|
|
1010
|
+
progress,
|
|
1011
|
+
[0, 1, 2],
|
|
1012
|
+
[0.5, 1, 0.5],
|
|
1013
|
+
Extrapolation.CLAMP
|
|
1014
|
+
);
|
|
1015
|
+
const opacity = interpolate2(
|
|
1016
|
+
progress,
|
|
1017
|
+
[0, 1, 2],
|
|
1018
|
+
[0, 1, 0],
|
|
1019
|
+
Extrapolation.CLAMP
|
|
1020
|
+
);
|
|
1021
|
+
return {
|
|
1022
|
+
contentStyle: {
|
|
1023
|
+
transform: [{ scale }],
|
|
1024
|
+
opacity
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
},
|
|
1028
|
+
transitionSpec: {
|
|
1029
|
+
open: DefaultSpec,
|
|
1030
|
+
close: DefaultSpec
|
|
1031
|
+
},
|
|
1032
|
+
...config
|
|
1033
|
+
};
|
|
1034
|
+
};
|
|
1035
|
+
var SlideFromBottom = (config = {}) => {
|
|
1036
|
+
return {
|
|
1037
|
+
gestureEnabled: true,
|
|
1038
|
+
gestureDirection: "vertical",
|
|
1039
|
+
screenStyleInterpolator: ({
|
|
1040
|
+
current,
|
|
1041
|
+
next,
|
|
1042
|
+
layouts: {
|
|
1043
|
+
screen: { height }
|
|
1044
|
+
}
|
|
1045
|
+
}) => {
|
|
1046
|
+
"worklet";
|
|
1047
|
+
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
1048
|
+
const y = interpolate2(progress, [0, 1, 2], [height, 0, -height]);
|
|
1049
|
+
return {
|
|
1050
|
+
contentStyle: {
|
|
1051
|
+
transform: [{ translateY: y }]
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
},
|
|
1055
|
+
transitionSpec: {
|
|
1056
|
+
open: DefaultSpec,
|
|
1057
|
+
close: DefaultSpec
|
|
1058
|
+
},
|
|
1059
|
+
...config
|
|
1060
|
+
};
|
|
1061
|
+
};
|
|
1062
|
+
var DraggableCard = (config = {}) => {
|
|
1063
|
+
return {
|
|
1064
|
+
gestureEnabled: true,
|
|
1065
|
+
gestureDirection: ["horizontal", "vertical"],
|
|
1066
|
+
screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
|
|
1067
|
+
"worklet";
|
|
1068
|
+
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
1069
|
+
const scale = interpolate2(progress, [0, 1, 2], [0, 1, 0.75]);
|
|
1070
|
+
const translateY = interpolate2(
|
|
1071
|
+
current.gesture.normalizedY.value,
|
|
1072
|
+
[-1, 1],
|
|
1073
|
+
[-screen.height * 0.5, screen.height * 0.5],
|
|
1074
|
+
"clamp"
|
|
1075
|
+
);
|
|
1076
|
+
const translateX = interpolate2(
|
|
1077
|
+
current.gesture.normalizedX.value,
|
|
1078
|
+
[-1, 1],
|
|
1079
|
+
[-screen.width * 0.5, screen.width * 0.5],
|
|
1080
|
+
"clamp"
|
|
1081
|
+
);
|
|
1082
|
+
return {
|
|
1083
|
+
contentStyle: {
|
|
1084
|
+
transform: [{ scale }, { translateY }, { translateX }]
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
},
|
|
1088
|
+
transitionSpec: {
|
|
1089
|
+
open: DefaultSpec,
|
|
1090
|
+
close: DefaultSpec
|
|
1091
|
+
},
|
|
1092
|
+
...config
|
|
1093
|
+
};
|
|
1094
|
+
};
|
|
1095
|
+
var ElasticCard = (config = { elasticFactor: 0.5 }) => {
|
|
1096
|
+
return {
|
|
1097
|
+
gestureEnabled: true,
|
|
1098
|
+
gestureDirection: "bidirectional",
|
|
1099
|
+
screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
|
|
1100
|
+
"worklet";
|
|
1101
|
+
const progress = current.progress.value + (next?.progress.value ?? 0);
|
|
1102
|
+
const scale = interpolate2(progress, [0, 1, 2], [0, 1, 0.8]);
|
|
1103
|
+
const maxElasticityX = screen.width * (config.elasticFactor ?? 0.5);
|
|
1104
|
+
const maxElasticityY = screen.height * (config.elasticFactor ?? 0.5);
|
|
1105
|
+
const translateX = interpolate2(
|
|
1106
|
+
current.gesture.normalizedX.value,
|
|
1107
|
+
[-1, 0, 1],
|
|
1108
|
+
[-maxElasticityX, 0, maxElasticityX],
|
|
1109
|
+
"clamp"
|
|
1110
|
+
);
|
|
1111
|
+
const translateY = interpolate2(
|
|
1112
|
+
current.gesture.normalizedY.value,
|
|
1113
|
+
[-1, 0, 1],
|
|
1114
|
+
[-maxElasticityY, 0, maxElasticityY],
|
|
1115
|
+
"clamp"
|
|
1116
|
+
);
|
|
1117
|
+
const overlayColor = interpolateColor(
|
|
1118
|
+
current.progress.value,
|
|
1119
|
+
[0, 1],
|
|
1120
|
+
["rgba(0,0,0,0)", "rgba(0,0,0,0.5)"]
|
|
1121
|
+
);
|
|
1122
|
+
return {
|
|
1123
|
+
contentStyle: {
|
|
1124
|
+
transform: [{ scale }, { translateX }, { translateY }]
|
|
1125
|
+
},
|
|
1126
|
+
overlayStyle: {
|
|
1127
|
+
backgroundColor: !next ? overlayColor : "rgba(0,0,0,0)"
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
},
|
|
1131
|
+
...config
|
|
1132
|
+
};
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
// src/navigator/create-transitionable-stack-navigator.tsx
|
|
1136
|
+
import {
|
|
1137
|
+
createNavigatorFactory,
|
|
1138
|
+
StackRouter,
|
|
1139
|
+
useNavigationBuilder
|
|
1140
|
+
} from "@react-navigation/native";
|
|
1141
|
+
import {
|
|
1142
|
+
NativeStackView
|
|
1143
|
+
} from "@react-navigation/native-stack";
|
|
1144
|
+
import React, { Children, isValidElement, useMemo as useMemo4 } from "react";
|
|
1145
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1146
|
+
var DEFAULT_SCREEN_OPTIONS = {
|
|
861
1147
|
presentation: "containedTransparentModal",
|
|
862
1148
|
headerShown: false,
|
|
863
1149
|
animation: "none"
|
|
864
|
-
|
|
1150
|
+
/**
|
|
1151
|
+
* EXPERIMENTAL:
|
|
1152
|
+
When handling forward navigation, this would be the prop we would use to prevent the underlying screen from not being interactable.
|
|
1153
|
+
- pointerEvents: "box-none",
|
|
1154
|
+
*/
|
|
1155
|
+
};
|
|
1156
|
+
var CONFLICTING_SCREEN_OPTIONS = {
|
|
1157
|
+
gestureEnabled: false,
|
|
1158
|
+
gestureDirection: "horizontal"
|
|
1159
|
+
};
|
|
1160
|
+
function TransitionableStackNavigator({
|
|
1161
|
+
id,
|
|
1162
|
+
initialRouteName,
|
|
1163
|
+
children,
|
|
1164
|
+
layout,
|
|
1165
|
+
screenListeners,
|
|
1166
|
+
screenOptions,
|
|
1167
|
+
screenLayout,
|
|
1168
|
+
UNSTABLE_router,
|
|
1169
|
+
...rest
|
|
1170
|
+
}) {
|
|
1171
|
+
const screenProcessor = useMemo4(() => {
|
|
1172
|
+
const childOptions = /* @__PURE__ */ new Map();
|
|
1173
|
+
const modifiedChildren = Children.toArray(children).filter(isValidElement).map((child) => {
|
|
1174
|
+
const resolvedOptions = typeof child.props.options === "function" ? child.props.options({
|
|
1175
|
+
route: child.props.route,
|
|
1176
|
+
navigation: child.props.navigation
|
|
1177
|
+
}) : child.props.options || {};
|
|
1178
|
+
childOptions.set(child.props.name, resolvedOptions);
|
|
1179
|
+
const skipDefaultScreenOptions = resolvedOptions?.skipDefaultScreenOptions === true;
|
|
1180
|
+
return React.cloneElement(child, {
|
|
1181
|
+
...child.props,
|
|
1182
|
+
options: {
|
|
1183
|
+
...skipDefaultScreenOptions ? {} : DEFAULT_SCREEN_OPTIONS,
|
|
1184
|
+
...resolvedOptions,
|
|
1185
|
+
...CONFLICTING_SCREEN_OPTIONS
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
});
|
|
1189
|
+
return {
|
|
1190
|
+
children: modifiedChildren,
|
|
1191
|
+
childOptions
|
|
1192
|
+
};
|
|
1193
|
+
}, [children]);
|
|
1194
|
+
const screenListenersWithTransitions = useMemo4(() => {
|
|
1195
|
+
return (props) => {
|
|
1196
|
+
const resolvedNavigatorConfig = typeof screenOptions === "function" ? screenOptions({
|
|
1197
|
+
navigation: props.navigation,
|
|
1198
|
+
route: props.route,
|
|
1199
|
+
theme: {}
|
|
1200
|
+
}) : screenOptions;
|
|
1201
|
+
const resolvedChildConfig = screenProcessor.childOptions.get(props.route.name);
|
|
1202
|
+
const mergedConfig = {
|
|
1203
|
+
...resolvedNavigatorConfig,
|
|
1204
|
+
...resolvedChildConfig
|
|
1205
|
+
//Child should override navigator config
|
|
1206
|
+
};
|
|
1207
|
+
const transitionListeners = createConfig({
|
|
1208
|
+
navigation: props.navigation,
|
|
1209
|
+
route: props.route,
|
|
1210
|
+
screenStyleInterpolator: mergedConfig.screenStyleInterpolator,
|
|
1211
|
+
transitionSpec: mergedConfig.transitionSpec,
|
|
1212
|
+
gestureEnabled: mergedConfig.gestureEnabled,
|
|
1213
|
+
gestureDirection: mergedConfig.gestureDirection,
|
|
1214
|
+
gestureResponseDistance: typeof mergedConfig.gestureResponseDistance === "number" ? mergedConfig.gestureResponseDistance : void 0,
|
|
1215
|
+
gestureVelocityImpact: mergedConfig.gestureVelocityImpact
|
|
1216
|
+
});
|
|
1217
|
+
const existingListeners = typeof screenListeners === "function" ? screenListeners(props) : screenListeners || {};
|
|
1218
|
+
return {
|
|
1219
|
+
...existingListeners,
|
|
1220
|
+
...transitionListeners
|
|
1221
|
+
};
|
|
1222
|
+
};
|
|
1223
|
+
}, [screenListeners, screenOptions, screenProcessor.childOptions]);
|
|
1224
|
+
const buildingBlocks = {
|
|
1225
|
+
id,
|
|
1226
|
+
initialRouteName,
|
|
1227
|
+
children: screenProcessor.children,
|
|
1228
|
+
layout,
|
|
1229
|
+
screenListeners: screenListenersWithTransitions,
|
|
1230
|
+
screenOptions,
|
|
1231
|
+
screenLayout,
|
|
1232
|
+
UNSTABLE_router
|
|
1233
|
+
};
|
|
1234
|
+
const { state, describe, descriptors, navigation, NavigationContent } = useNavigationBuilder(StackRouter, buildingBlocks);
|
|
1235
|
+
return /* @__PURE__ */ jsx4(NavigationContent, { children: /* @__PURE__ */ jsx4(NativeStackView, { ...rest, state, navigation, descriptors, describe }) });
|
|
1236
|
+
}
|
|
1237
|
+
function createTransitionableStackNavigator() {
|
|
1238
|
+
return createNavigatorFactory(TransitionableStackNavigator)();
|
|
1239
|
+
}
|
|
865
1240
|
|
|
866
1241
|
// src/index.ts
|
|
867
1242
|
var index_default = {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1243
|
+
View: createTransitionAwareComponent(View2),
|
|
1244
|
+
Pressable: createTransitionAwareComponent(Pressable),
|
|
1245
|
+
ScrollView: createTransitionAwareScrollable(ScrollView),
|
|
1246
|
+
FlatList: createTransitionAwareScrollable(FlatList),
|
|
872
1247
|
defaultScreenOptions,
|
|
873
1248
|
presets: presets_exports,
|
|
874
|
-
specs: specs_exports
|
|
1249
|
+
specs: specs_exports,
|
|
1250
|
+
/**
|
|
1251
|
+
* Create a transition aware component
|
|
1252
|
+
*/
|
|
1253
|
+
createTransitionAwareComponent,
|
|
1254
|
+
/**
|
|
1255
|
+
* Create a transition aware scrollable component
|
|
1256
|
+
*/
|
|
1257
|
+
createTransitionAwareScrollable,
|
|
1258
|
+
/**
|
|
1259
|
+
* Create a transitionable native stack navigator.
|
|
1260
|
+
*
|
|
1261
|
+
*/
|
|
1262
|
+
createTransitionableStackNavigator,
|
|
1263
|
+
/**
|
|
1264
|
+
* @deprecated Use {@link createTransitionableStackNavigator} instead.
|
|
1265
|
+
*/
|
|
1266
|
+
createConfig,
|
|
1267
|
+
/**
|
|
1268
|
+
* @deprecated Use {@link createTransitionableStackNavigator} instead.
|
|
1269
|
+
*/
|
|
1270
|
+
createScreenConfig
|
|
1271
|
+
/**
|
|
1272
|
+
* @deprecated Use {@link createTransitionableStackNavigator} instead.
|
|
1273
|
+
*/
|
|
875
1274
|
};
|
|
876
1275
|
export {
|
|
877
1276
|
index_default as default,
|