@react-navigation/stack 8.0.0-alpha.51 → 8.0.0-alpha.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/TransitionConfigs/CardStyleInterpolators.js +241 -83
- package/lib/module/TransitionConfigs/CardStyleInterpolators.js.map +1 -1
- package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js +11 -44
- package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js.map +1 -1
- package/lib/module/TransitionConfigs/TransitionEasings.js +71 -0
- package/lib/module/TransitionConfigs/TransitionEasings.js.map +1 -0
- package/lib/module/TransitionConfigs/TransitionPresets.js +50 -10
- package/lib/module/TransitionConfigs/TransitionPresets.js.map +1 -1
- package/lib/module/TransitionConfigs/TransitionSpecs.js +69 -34
- package/lib/module/TransitionConfigs/TransitionSpecs.js.map +1 -1
- package/lib/module/navigators/createStackNavigator.js +25 -16
- package/lib/module/navigators/createStackNavigator.js.map +1 -1
- package/lib/module/views/Header/Header.js +2 -0
- package/lib/module/views/Header/Header.js.map +1 -1
- package/lib/module/views/Header/HeaderContainer.js +8 -3
- package/lib/module/views/Header/HeaderContainer.js.map +1 -1
- package/lib/module/views/Header/HeaderSegment.js +3 -6
- package/lib/module/views/Header/HeaderSegment.js.map +1 -1
- package/lib/module/views/Stack/Card.js +57 -32
- package/lib/module/views/Stack/Card.js.map +1 -1
- package/lib/module/views/Stack/CardContainer.js +17 -2
- package/lib/module/views/Stack/CardContainer.js.map +1 -1
- package/lib/module/views/Stack/CardStack.js +24 -13
- package/lib/module/views/Stack/CardStack.js.map +1 -1
- package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +19 -11
- package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +3 -3
- package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionEasings.d.ts +38 -0
- package/lib/typescript/src/TransitionConfigs/TransitionEasings.d.ts.map +1 -0
- package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +14 -2
- package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +43 -14
- package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -1
- package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +44 -28
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/Header.d.ts +1 -1
- package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts +1 -0
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/Card.d.ts +9 -3
- package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardContainer.d.ts +3 -1
- package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/TransitionConfigs/CardStyleInterpolators.tsx +351 -100
- package/src/TransitionConfigs/HeaderStyleInterpolators.tsx +15 -46
- package/src/TransitionConfigs/TransitionEasings.tsx +90 -0
- package/src/TransitionConfigs/TransitionPresets.tsx +56 -10
- package/src/TransitionConfigs/TransitionSpecs.tsx +68 -34
- package/src/navigators/createStackNavigator.tsx +33 -24
- package/src/types.tsx +46 -29
- package/src/views/Header/Header.tsx +2 -0
- package/src/views/Header/HeaderContainer.tsx +10 -4
- package/src/views/Header/HeaderSegment.tsx +4 -4
- package/src/views/Stack/Card.tsx +82 -37
- package/src/views/Stack/CardContainer.tsx +17 -2
- package/src/views/Stack/CardStack.tsx +69 -14
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Easing } from 'react-native';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Exact piecewise path for Android's fast-out-extra-slow-in easing.
|
|
5
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/interpolator/fast_out_extra_slow_in.xml
|
|
6
|
+
*/
|
|
7
|
+
const FAST_OUT_EXTRA_SLOW_IN_INITIAL = Easing.bezier(0.3, 0, 0.8, 0.15);
|
|
8
|
+
const FAST_OUT_EXTRA_SLOW_IN_FINAL = Easing.bezier(0.05, 0.7, 0.1, 1);
|
|
9
|
+
|
|
10
|
+
export const FAST_OUT_EXTRA_SLOW_IN = (t: number) => {
|
|
11
|
+
const breakpoint = 1 / 6;
|
|
12
|
+
|
|
13
|
+
if (t < breakpoint) {
|
|
14
|
+
return 0.4 * FAST_OUT_EXTRA_SLOW_IN_INITIAL(t / breakpoint);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
0.4 +
|
|
19
|
+
0.6 * FAST_OUT_EXTRA_SLOW_IN_FINAL((t - breakpoint) / (1 - breakpoint))
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/interpolator/fast_out_slow_in.xml
|
|
25
|
+
*/
|
|
26
|
+
export const FAST_OUT_SLOW_IN = Easing.bezier(0.4, 0, 0.2, 1);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/interpolator/linear_out_slow_in.xml
|
|
30
|
+
*/
|
|
31
|
+
export const LINEAR_OUT_SLOW_IN = Easing.bezier(0, 0, 0.2, 1);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r47/core/res/res/interpolator/activity_close_dim.xml
|
|
35
|
+
*/
|
|
36
|
+
export const ACTIVITY_CLOSE_DIM = Easing.bezier(0.33, 0, 1, 1);
|
|
37
|
+
|
|
38
|
+
export const decelerate = (power: number, t: number) => 1 - (1 - t) ** power;
|
|
39
|
+
|
|
40
|
+
export const accelerate = (power: number, t: number) => t ** power;
|
|
41
|
+
|
|
42
|
+
export const clamp = (value: number) => Math.min(1, Math.max(0, value));
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Creates interpolation ranges for a property that follows its own timeline.
|
|
46
|
+
*
|
|
47
|
+
* @param options - Options for the property timeline.
|
|
48
|
+
* @param options.duration - Total transition duration in milliseconds.
|
|
49
|
+
* @param options.easing - Easing used by the transition.
|
|
50
|
+
* @param options.closing - Whether the transition is closing.
|
|
51
|
+
* @param options.stops - Times in milliseconds to include in the ranges.
|
|
52
|
+
* @param options.output - Returns the property value at a time in milliseconds.
|
|
53
|
+
*/
|
|
54
|
+
export function timeline({
|
|
55
|
+
duration,
|
|
56
|
+
easing,
|
|
57
|
+
closing = false,
|
|
58
|
+
stops = [],
|
|
59
|
+
output,
|
|
60
|
+
}: {
|
|
61
|
+
duration: number;
|
|
62
|
+
easing: (value: number) => number;
|
|
63
|
+
closing?: boolean;
|
|
64
|
+
stops?: number[];
|
|
65
|
+
output: (time: number) => number;
|
|
66
|
+
}) {
|
|
67
|
+
const times = [
|
|
68
|
+
...new Set([
|
|
69
|
+
...Array.from(
|
|
70
|
+
{ length: Math.floor(duration / 10) + 1 },
|
|
71
|
+
(_, index) => index * 10
|
|
72
|
+
),
|
|
73
|
+
...stops,
|
|
74
|
+
duration,
|
|
75
|
+
]),
|
|
76
|
+
].sort((a, b) => a - b);
|
|
77
|
+
|
|
78
|
+
const points = times
|
|
79
|
+
.map((time) => ({
|
|
80
|
+
input: closing ? 1 - easing(time / duration) : easing(time / duration),
|
|
81
|
+
output: output(time),
|
|
82
|
+
}))
|
|
83
|
+
.sort((a, b) => a.input - b.input);
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
inputRange: points.map(({ input }) => input),
|
|
87
|
+
outputRange: points.map(({ output }) => output),
|
|
88
|
+
extrapolate: 'clamp' as const,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -3,11 +3,13 @@ import { Platform } from 'react-native';
|
|
|
3
3
|
import type { TransitionPreset } from '../types';
|
|
4
4
|
import {
|
|
5
5
|
forBottomSheetAndroid,
|
|
6
|
+
forCrossDissolveIOS,
|
|
7
|
+
forDialogAndroid,
|
|
6
8
|
forFadeFromBottomAndroid,
|
|
7
|
-
forFadeFromCenter
|
|
9
|
+
forFadeFromCenter,
|
|
8
10
|
forFadeFromRightAndroid,
|
|
11
|
+
forFlipIOS,
|
|
9
12
|
forHorizontalIOS,
|
|
10
|
-
forHorizontalIOSInverted,
|
|
11
13
|
forModalPresentationIOS,
|
|
12
14
|
forRevealFromBottomAndroid,
|
|
13
15
|
forScaleFromCenterAndroid,
|
|
@@ -17,8 +19,12 @@ import { forFade, forUIKit } from './HeaderStyleInterpolators';
|
|
|
17
19
|
import {
|
|
18
20
|
BottomSheetSlideInSpec,
|
|
19
21
|
BottomSheetSlideOutSpec,
|
|
22
|
+
DialogAndroidSpec,
|
|
20
23
|
FadeInFromBottomAndroidSpec,
|
|
24
|
+
FadeInFromRightAndroidSpec,
|
|
21
25
|
FadeOutToBottomAndroidSpec,
|
|
26
|
+
FadeOutToRightAndroidSpec,
|
|
27
|
+
FlipIOSSpec,
|
|
22
28
|
RevealFromBottomAndroidSpec,
|
|
23
29
|
ScaleFromCenterAndroidSpec,
|
|
24
30
|
TransitionIOSSpec,
|
|
@@ -80,6 +86,19 @@ export const FadeFromBottomAndroid: TransitionPreset = {
|
|
|
80
86
|
headerStyleInterpolator: forFade,
|
|
81
87
|
};
|
|
82
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Standard Android dialog transition.
|
|
91
|
+
*/
|
|
92
|
+
export const DialogAndroid: TransitionPreset = {
|
|
93
|
+
gestureDirection: 'vertical',
|
|
94
|
+
transitionSpec: {
|
|
95
|
+
open: DialogAndroidSpec,
|
|
96
|
+
close: DialogAndroidSpec,
|
|
97
|
+
},
|
|
98
|
+
cardStyleInterpolator: forDialogAndroid,
|
|
99
|
+
headerStyleInterpolator: forFade,
|
|
100
|
+
};
|
|
101
|
+
|
|
83
102
|
/**
|
|
84
103
|
* Standard Android navigation transition when opening or closing an Activity on Android 9 (Pie).
|
|
85
104
|
*/
|
|
@@ -107,20 +126,20 @@ export const ScaleFromCenterAndroid: TransitionPreset = {
|
|
|
107
126
|
};
|
|
108
127
|
|
|
109
128
|
/**
|
|
110
|
-
* Standard Android navigation transition when opening or closing an Activity on Android 14.
|
|
129
|
+
* Standard Android navigation transition when opening or closing an Activity on Android 14 and later.
|
|
111
130
|
*/
|
|
112
131
|
export const FadeFromRightAndroid: TransitionPreset = {
|
|
113
132
|
gestureDirection: 'horizontal',
|
|
114
133
|
transitionSpec: {
|
|
115
|
-
open:
|
|
116
|
-
close:
|
|
134
|
+
open: FadeInFromRightAndroidSpec,
|
|
135
|
+
close: FadeOutToRightAndroidSpec,
|
|
117
136
|
},
|
|
118
137
|
cardStyleInterpolator: forFadeFromRightAndroid,
|
|
119
138
|
headerStyleInterpolator: forFade,
|
|
120
139
|
};
|
|
121
140
|
|
|
122
141
|
/**
|
|
123
|
-
* Standard bottom sheet
|
|
142
|
+
* Standard Material 3 bottom sheet transition.
|
|
124
143
|
*/
|
|
125
144
|
export const BottomSheetAndroid: TransitionPreset = {
|
|
126
145
|
gestureDirection: 'vertical',
|
|
@@ -138,10 +157,36 @@ export const BottomSheetAndroid: TransitionPreset = {
|
|
|
138
157
|
export const ModalFadeTransition: TransitionPreset = {
|
|
139
158
|
gestureDirection: 'vertical',
|
|
140
159
|
transitionSpec: {
|
|
141
|
-
open:
|
|
142
|
-
close:
|
|
160
|
+
open: TransitionIOSSpec,
|
|
161
|
+
close: TransitionIOSSpec,
|
|
143
162
|
},
|
|
144
|
-
cardStyleInterpolator:
|
|
163
|
+
cardStyleInterpolator: forFadeFromCenter,
|
|
164
|
+
headerStyleInterpolator: forFade,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Standard iOS horizontal flip transition.
|
|
169
|
+
*/
|
|
170
|
+
export const ModalFlipIOS: TransitionPreset = {
|
|
171
|
+
gestureDirection: 'horizontal',
|
|
172
|
+
transitionSpec: {
|
|
173
|
+
open: FlipIOSSpec,
|
|
174
|
+
close: FlipIOSSpec,
|
|
175
|
+
},
|
|
176
|
+
cardStyleInterpolator: forFlipIOS,
|
|
177
|
+
headerStyleInterpolator: forFade,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Standard iOS cross-dissolve transition.
|
|
182
|
+
*/
|
|
183
|
+
export const CrossDissolveIOS: TransitionPreset = {
|
|
184
|
+
gestureDirection: 'horizontal',
|
|
185
|
+
transitionSpec: {
|
|
186
|
+
open: TransitionIOSSpec,
|
|
187
|
+
close: TransitionIOSSpec,
|
|
188
|
+
},
|
|
189
|
+
cardStyleInterpolator: forCrossDissolveIOS,
|
|
145
190
|
headerStyleInterpolator: forFade,
|
|
146
191
|
};
|
|
147
192
|
|
|
@@ -174,5 +219,6 @@ export const ModalTransition = Platform.select({
|
|
|
174
219
|
*/
|
|
175
220
|
export const SlideFromLeftIOS: TransitionPreset = {
|
|
176
221
|
...SlideFromRightIOS,
|
|
177
|
-
|
|
222
|
+
gestureDirection: 'horizontal-inverted',
|
|
223
|
+
cardStyleInterpolator: forHorizontalIOS,
|
|
178
224
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Easing } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { TransitionSpec } from '../types';
|
|
4
|
+
import { FAST_OUT_EXTRA_SLOW_IN } from './TransitionEasings';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* Approximation of the standard iOS navigation transition.
|
|
7
8
|
*/
|
|
8
9
|
export const TransitionIOSSpec: TransitionSpec = {
|
|
9
10
|
animation: 'spring',
|
|
@@ -17,9 +18,21 @@ export const TransitionIOSSpec: TransitionSpec = {
|
|
|
17
18
|
},
|
|
18
19
|
};
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Configuration for the standard iOS horizontal flip transition.
|
|
23
|
+
*/
|
|
24
|
+
export const FlipIOSSpec: TransitionSpec = {
|
|
25
|
+
animation: 'timing',
|
|
26
|
+
config: {
|
|
27
|
+
duration: 700,
|
|
28
|
+
easing: Easing.inOut(Easing.ease),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
20
32
|
/**
|
|
21
33
|
* Configuration for activity open animation from Android Nougat.
|
|
22
|
-
* See
|
|
34
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-7.1.2_r37/core/res/res/anim/activity_open_enter.xml
|
|
35
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-7.1.2_r37/core/res/res/anim/activity_open_exit.xml
|
|
23
36
|
*/
|
|
24
37
|
export const FadeInFromBottomAndroidSpec: TransitionSpec = {
|
|
25
38
|
animation: 'timing',
|
|
@@ -31,94 +44,115 @@ export const FadeInFromBottomAndroidSpec: TransitionSpec = {
|
|
|
31
44
|
|
|
32
45
|
/**
|
|
33
46
|
* Configuration for activity close animation from Android Nougat.
|
|
34
|
-
* See
|
|
47
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-7.1.2_r37/core/res/res/anim/activity_close_enter.xml
|
|
48
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-7.1.2_r37/core/res/res/anim/activity_close_exit.xml
|
|
35
49
|
*/
|
|
36
50
|
export const FadeOutToBottomAndroidSpec: TransitionSpec = {
|
|
37
51
|
animation: 'timing',
|
|
38
52
|
config: {
|
|
39
|
-
duration:
|
|
40
|
-
easing: Easing.in(Easing.
|
|
53
|
+
duration: 250,
|
|
54
|
+
easing: Easing.in(Easing.poly(4)),
|
|
41
55
|
},
|
|
42
56
|
};
|
|
43
57
|
|
|
44
58
|
/**
|
|
45
|
-
*
|
|
46
|
-
* See
|
|
59
|
+
* Configuration for the standard Android dialog transition.
|
|
60
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/anim/dialog_enter.xml
|
|
61
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/anim/dialog_exit.xml
|
|
62
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/values/config.xml
|
|
63
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/core/res/res/values/themes_material.xml
|
|
64
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
|
|
65
|
+
*/
|
|
66
|
+
export const DialogAndroidSpec: TransitionSpec = {
|
|
67
|
+
animation: 'timing',
|
|
68
|
+
config: {
|
|
69
|
+
duration: 220,
|
|
70
|
+
easing: Easing.out(Easing.poly(5)),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Configuration for activity open animation from Android Pie.
|
|
76
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r47/core/res/res/anim/activity_open_enter.xml
|
|
77
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r47/core/res/res/anim/activity_open_exit.xml
|
|
78
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r47/core/res/res/anim/activity_close_enter.xml
|
|
79
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r47/core/res/res/anim/activity_close_exit.xml
|
|
47
80
|
*/
|
|
48
81
|
export const RevealFromBottomAndroidSpec: TransitionSpec = {
|
|
49
82
|
animation: 'timing',
|
|
50
83
|
config: {
|
|
51
84
|
duration: 425,
|
|
52
|
-
|
|
53
|
-
// See http://aosp.opersys.com/xref/android-9.0.0_r47/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
|
|
54
|
-
easing: Easing.bezier(0.20833, 0.82, 0.25, 1),
|
|
85
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
55
86
|
},
|
|
56
87
|
};
|
|
57
88
|
|
|
58
89
|
/**
|
|
59
|
-
*
|
|
60
|
-
* See
|
|
90
|
+
* Configuration for activity open animation from Android Q.
|
|
91
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r2/core/res/res/anim/activity_open_enter.xml
|
|
92
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r2/core/res/res/anim/activity_open_exit.xml
|
|
93
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r2/core/res/res/anim/activity_close_enter.xml
|
|
94
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r2/core/res/res/anim/activity_close_exit.xml
|
|
61
95
|
*/
|
|
62
96
|
export const ScaleFromCenterAndroidSpec: TransitionSpec = {
|
|
63
97
|
animation: 'timing',
|
|
64
98
|
config: {
|
|
65
99
|
duration: 400,
|
|
66
|
-
|
|
67
|
-
// See http://aosp.opersys.com/xref/android-10.0.0_r2/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
|
|
68
|
-
easing: Easing.bezier(0.20833, 0.82, 0.25, 1),
|
|
100
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
69
101
|
},
|
|
70
102
|
};
|
|
71
103
|
|
|
72
104
|
/**
|
|
73
|
-
*
|
|
105
|
+
* Configuration for activity open animation from Android 14 and later.
|
|
74
106
|
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/anim/activity_open_enter.xml
|
|
107
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/anim/activity_open_exit.xml
|
|
75
108
|
*/
|
|
76
109
|
export const FadeInFromRightAndroidSpec: TransitionSpec = {
|
|
77
110
|
animation: 'timing',
|
|
78
111
|
config: {
|
|
79
112
|
duration: 450,
|
|
80
|
-
|
|
81
|
-
// See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/interpolator/fast_out_extra_slow_in.xml
|
|
82
|
-
easing: Easing.bezier(0.20833, 0.82, 0.25, 1),
|
|
113
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
83
114
|
},
|
|
84
115
|
};
|
|
85
116
|
|
|
86
117
|
/**
|
|
87
|
-
*
|
|
118
|
+
* Configuration for activity close animation from Android 14 and later.
|
|
119
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/anim/activity_close_enter.xml
|
|
88
120
|
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/anim/activity_close_exit.xml
|
|
89
121
|
*/
|
|
90
|
-
export const
|
|
122
|
+
export const FadeOutToRightAndroidSpec: TransitionSpec = {
|
|
91
123
|
animation: 'timing',
|
|
92
124
|
config: {
|
|
93
125
|
duration: 450,
|
|
94
|
-
|
|
95
|
-
// See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-14.0.0_r51/core/res/res/interpolator/fast_out_extra_slow_in.xml
|
|
96
|
-
easing: Easing.bezier(0.20833, 0.82, 0.25, 1),
|
|
126
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
97
127
|
},
|
|
98
128
|
};
|
|
99
129
|
|
|
100
130
|
/**
|
|
101
|
-
* Configuration for bottom sheet slide in animation from Material
|
|
102
|
-
* See https://github.com/material-components/material-components-android/blob/
|
|
131
|
+
* Configuration for bottom sheet slide in animation from Material 3.
|
|
132
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/bottomsheet/res/anim/m3_bottom_sheet_slide_in.xml
|
|
133
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/motion/res/values/tokens.xml
|
|
134
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/dialog/res/values/tokens.xml
|
|
135
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
|
|
103
136
|
*/
|
|
104
137
|
export const BottomSheetSlideInSpec: TransitionSpec = {
|
|
105
138
|
animation: 'timing',
|
|
106
139
|
config: {
|
|
107
|
-
duration:
|
|
108
|
-
|
|
109
|
-
easing: (t) => Math.cos((t + 1) * Math.PI) / 2.0 + 0.5,
|
|
140
|
+
duration: 400,
|
|
141
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
110
142
|
},
|
|
111
143
|
};
|
|
112
144
|
|
|
113
145
|
/**
|
|
114
|
-
* Configuration for bottom sheet slide out animation from Material
|
|
115
|
-
* See https://github.com/material-components/material-components-android/blob/
|
|
146
|
+
* Configuration for bottom sheet slide out animation from Material 3.
|
|
147
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/bottomsheet/res/anim/m3_bottom_sheet_slide_out.xml
|
|
148
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/motion/res/values/tokens.xml
|
|
149
|
+
* See https://github.com/material-components/material-components-android/blob/1.14.0/lib/java/com/google/android/material/dialog/res/values/tokens.xml
|
|
150
|
+
* See https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-17.0.0_r1/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
|
|
116
151
|
*/
|
|
117
152
|
export const BottomSheetSlideOutSpec: TransitionSpec = {
|
|
118
153
|
animation: 'timing',
|
|
119
154
|
config: {
|
|
120
|
-
duration:
|
|
121
|
-
|
|
122
|
-
easing: (t) => (t === 1.0 ? 1 : Math.pow(t, 2)),
|
|
155
|
+
duration: 350,
|
|
156
|
+
easing: FAST_OUT_EXTRA_SLOW_IN,
|
|
123
157
|
},
|
|
124
158
|
};
|
|
@@ -52,31 +52,40 @@ function StackNavigator({
|
|
|
52
52
|
router,
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
React.useEffect(
|
|
56
|
-
|
|
57
|
-
// @ts-expect-error: there may not be a tab navigator in parent
|
|
58
|
-
navigation.addListener?.('tabPress', (e) => {
|
|
59
|
-
const isFocused = navigation.isFocused();
|
|
55
|
+
React.useEffect(() => {
|
|
56
|
+
let handle: ReturnType<typeof requestAnimationFrame> | undefined;
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
58
|
+
// @ts-expect-error: there may not be a tab navigator in parent
|
|
59
|
+
const unsubscribe = navigation.addListener?.('tabPress', (e) => {
|
|
60
|
+
const isFocused = navigation.isFocused();
|
|
61
|
+
|
|
62
|
+
cancelAnimationFrame(handle);
|
|
63
|
+
|
|
64
|
+
// Run the operation in the next frame so we're sure all listeners have been run
|
|
65
|
+
// This is necessary to know if preventDefault() has been called
|
|
66
|
+
handle = requestAnimationFrame(() => {
|
|
67
|
+
const currentState = navigation.getState();
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
isFocused &&
|
|
71
|
+
(currentState.index > 0 || currentState.routes[0]?.history?.length) &&
|
|
72
|
+
!(e as EventArg<'tabPress', true>).defaultPrevented
|
|
73
|
+
) {
|
|
74
|
+
// When user taps on already focused tab and we're inside the tab,
|
|
75
|
+
// reset the stack to replicate native behaviour
|
|
76
|
+
navigation.dispatch({
|
|
77
|
+
...StackActions.popToTop(),
|
|
78
|
+
target: currentState.key,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return () => {
|
|
85
|
+
cancelAnimationFrame(handle);
|
|
86
|
+
unsubscribe?.();
|
|
87
|
+
};
|
|
88
|
+
}, [navigation]);
|
|
80
89
|
|
|
81
90
|
return (
|
|
82
91
|
<NavigationContent>
|
package/src/types.tsx
CHANGED
|
@@ -8,7 +8,6 @@ import type {
|
|
|
8
8
|
import type {
|
|
9
9
|
DefaultNavigatorOptions,
|
|
10
10
|
Descriptor,
|
|
11
|
-
LocaleDirection,
|
|
12
11
|
NavigationHelpers,
|
|
13
12
|
NavigationProp,
|
|
14
13
|
ParamListBase,
|
|
@@ -97,6 +96,9 @@ export type StackAnimationName =
|
|
|
97
96
|
| 'fade'
|
|
98
97
|
| 'fade_from_bottom'
|
|
99
98
|
| 'fade_from_right'
|
|
99
|
+
| 'flip'
|
|
100
|
+
| 'ios_from_left'
|
|
101
|
+
| 'ios_from_right'
|
|
100
102
|
| 'none'
|
|
101
103
|
| 'reveal_from_bottom'
|
|
102
104
|
| 'scale_from_center'
|
|
@@ -107,7 +109,8 @@ export type StackAnimationName =
|
|
|
107
109
|
type SceneOptionsDefaults = TransitionPreset & {
|
|
108
110
|
animation: StackAnimationName;
|
|
109
111
|
gestureEnabled: boolean;
|
|
110
|
-
cardOverlayEnabled: boolean;
|
|
112
|
+
cardOverlayEnabled: boolean | undefined;
|
|
113
|
+
cardShadowEnabled: boolean | undefined;
|
|
111
114
|
headerMode: StackHeaderMode;
|
|
112
115
|
};
|
|
113
116
|
|
|
@@ -127,6 +130,10 @@ export type Scene = {
|
|
|
127
130
|
* Animated nodes representing the progress of the animation.
|
|
128
131
|
*/
|
|
129
132
|
progress: SceneProgress;
|
|
133
|
+
/**
|
|
134
|
+
* Animated node representing whether the screen is closing.
|
|
135
|
+
*/
|
|
136
|
+
closing: Animated.Value;
|
|
130
137
|
};
|
|
131
138
|
|
|
132
139
|
export type SceneProgress = {
|
|
@@ -256,6 +263,10 @@ export type StackHeaderProps = {
|
|
|
256
263
|
* Animated nodes representing the progress of the animation.
|
|
257
264
|
*/
|
|
258
265
|
progress: SceneProgress;
|
|
266
|
+
/**
|
|
267
|
+
* Direction multiplier for the transition.
|
|
268
|
+
*/
|
|
269
|
+
inverted: 1 | -1;
|
|
259
270
|
/**
|
|
260
271
|
* Options for the current screen.
|
|
261
272
|
*/
|
|
@@ -320,7 +331,8 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|
|
320
331
|
header?: (props: StackHeaderProps) => React.ReactNode;
|
|
321
332
|
/**
|
|
322
333
|
* Whether the header floats above the screen or part of the screen.
|
|
323
|
-
* Defaults to `float` on iOS for
|
|
334
|
+
* Defaults to `float` on iOS for animations where the header transitions
|
|
335
|
+
* separately, and `screen` otherwise.
|
|
324
336
|
*/
|
|
325
337
|
headerMode?: StackHeaderMode;
|
|
326
338
|
/**
|
|
@@ -329,14 +341,17 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|
|
329
341
|
*/
|
|
330
342
|
headerShown?: boolean;
|
|
331
343
|
/**
|
|
332
|
-
* Whether a shadow is visible for the card during transitions.
|
|
344
|
+
* Whether a shadow is visible for the card during transitions.
|
|
345
|
+
* Defaults to whether `cardStyleInterpolator` returns a `shadowStyle`.
|
|
346
|
+
* Setting this overrides the default behavior.
|
|
333
347
|
*/
|
|
334
|
-
cardShadowEnabled?: boolean;
|
|
348
|
+
cardShadowEnabled?: boolean | undefined;
|
|
335
349
|
/**
|
|
336
350
|
* Whether to have a semi-transparent dark overlay visible under the card during transitions.
|
|
337
|
-
* Defaults to `
|
|
351
|
+
* Defaults to whether `cardStyleInterpolator` returns an `overlayStyle`.
|
|
352
|
+
* Setting this overrides the default behavior.
|
|
338
353
|
*/
|
|
339
|
-
cardOverlayEnabled?: boolean;
|
|
354
|
+
cardOverlayEnabled?: boolean | undefined;
|
|
340
355
|
/**
|
|
341
356
|
* Function that returns a React Element to display as a overlay for the card.
|
|
342
357
|
*/
|
|
@@ -371,8 +386,12 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|
|
371
386
|
* Supported values:
|
|
372
387
|
* - 'none': don't animate the screen
|
|
373
388
|
* - 'default': use the platform default animation
|
|
374
|
-
* - 'fade': fade
|
|
389
|
+
* - 'fade': fade between screens
|
|
375
390
|
* - 'fade_from_bottom': fade screen in or out from bottom
|
|
391
|
+
* - 'fade_from_right': fade screen in from the right
|
|
392
|
+
* - 'flip': flip the screen horizontally
|
|
393
|
+
* - 'ios_from_left': use the iOS-style slide from left
|
|
394
|
+
* - 'ios_from_right': use the iOS-style slide from right
|
|
376
395
|
* - 'slide_from_bottom': slide in the new screen from bottom
|
|
377
396
|
* - 'slide_from_right': slide in the new screen from right
|
|
378
397
|
* - 'slide_from_left': slide in the new screen from left
|
|
@@ -386,7 +405,9 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|
|
386
405
|
*/
|
|
387
406
|
animationTypeForReplace?: 'push' | 'pop';
|
|
388
407
|
/**
|
|
389
|
-
* Whether you can use gestures to dismiss this screen. Defaults to `true`
|
|
408
|
+
* Whether you can use gestures to dismiss this screen. Defaults to `true`
|
|
409
|
+
* on iOS for navigation-style transitions with an interactive dismissal,
|
|
410
|
+
* and `false` otherwise.
|
|
390
411
|
* Not supported on Web.
|
|
391
412
|
*/
|
|
392
413
|
gestureEnabled?: boolean;
|
|
@@ -440,36 +461,32 @@ export type TransitionSpec =
|
|
|
440
461
|
>;
|
|
441
462
|
};
|
|
442
463
|
|
|
464
|
+
type StackCardInterpolationState = {
|
|
465
|
+
/**
|
|
466
|
+
* Animated node representing the progress value of the screen.
|
|
467
|
+
*/
|
|
468
|
+
progress: Animated.AnimatedInterpolation<number>;
|
|
469
|
+
/**
|
|
470
|
+
* Animated node representing whether the screen is using the closing or
|
|
471
|
+
* opening animation (1 - closing, 0 - opening).
|
|
472
|
+
*/
|
|
473
|
+
closing: Animated.AnimatedInterpolation<0 | 1>;
|
|
474
|
+
};
|
|
475
|
+
|
|
443
476
|
export type StackCardInterpolationProps = {
|
|
444
477
|
/**
|
|
445
478
|
* Values for the current screen.
|
|
446
479
|
*/
|
|
447
|
-
current:
|
|
448
|
-
/**
|
|
449
|
-
* Animated node representing the progress value of the current screen.
|
|
450
|
-
*/
|
|
451
|
-
progress: Animated.AnimatedInterpolation<number>;
|
|
452
|
-
};
|
|
480
|
+
current: StackCardInterpolationState;
|
|
453
481
|
/**
|
|
454
482
|
* Values for the screen after this one in the stack.
|
|
455
483
|
* This can be `undefined` in case the screen animating is the last one.
|
|
456
484
|
*/
|
|
457
|
-
next?:
|
|
458
|
-
| {
|
|
459
|
-
/**
|
|
460
|
-
* Animated node representing the progress value of the next screen.
|
|
461
|
-
*/
|
|
462
|
-
progress: Animated.AnimatedInterpolation<number>;
|
|
463
|
-
}
|
|
464
|
-
| undefined;
|
|
485
|
+
next?: StackCardInterpolationState | undefined;
|
|
465
486
|
/**
|
|
466
487
|
* The index of the card with this interpolation in the stack.
|
|
467
488
|
*/
|
|
468
489
|
index: number;
|
|
469
|
-
/**
|
|
470
|
-
* Animated node representing whether the card is closing (1 - closing, 0 - not closing).
|
|
471
|
-
*/
|
|
472
|
-
closing: Animated.AnimatedInterpolation<0 | 1>;
|
|
473
490
|
/**
|
|
474
491
|
* Animated node representing whether the card is being swiped (1 - swiping, 0 - not swiping).
|
|
475
492
|
*/
|
|
@@ -548,9 +565,9 @@ export type StackHeaderInterpolationProps = {
|
|
|
548
565
|
}
|
|
549
566
|
| undefined;
|
|
550
567
|
/**
|
|
551
|
-
*
|
|
568
|
+
* Direction multiplier for the transition.
|
|
552
569
|
*/
|
|
553
|
-
|
|
570
|
+
inverted: 1 | -1;
|
|
554
571
|
/**
|
|
555
572
|
* Layout measurements for various items we use for animation.
|
|
556
573
|
*/
|
|
@@ -11,6 +11,7 @@ import { HeaderSegment } from './HeaderSegment';
|
|
|
11
11
|
export const Header = React.memo(function Header({
|
|
12
12
|
back,
|
|
13
13
|
progress,
|
|
14
|
+
inverted,
|
|
14
15
|
options,
|
|
15
16
|
route,
|
|
16
17
|
navigation,
|
|
@@ -54,6 +55,7 @@ export const Header = React.memo(function Header({
|
|
|
54
55
|
return (
|
|
55
56
|
<HeaderSegment
|
|
56
57
|
{...options}
|
|
58
|
+
inverted={inverted}
|
|
57
59
|
title={getHeaderTitle(options, route.name)}
|
|
58
60
|
progress={progress}
|
|
59
61
|
modal={isModal}
|