@amazon-devices/react-navigation__stack 7.0.1759135970 → 8.0.9000000000

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 (273) hide show
  1. package/SystemBundles/98ca5eeb45684e3e5615c766e1d3a956fee53d14cd6c2318098c23c210bd76d7.bundle +13464 -0
  2. package/SystemBundles/98ca5eeb45684e3e5615c766e1d3a956fee53d14cd6c2318098c23c210bd76d7.map +4638 -0
  3. package/SystemModules/amzn__react-navigation__stack-8.modules.txt +32 -0
  4. package/SystemModules/amzn__react-navigation__stack-8.private.modules.txt +92 -0
  5. package/SystemModules/keplerscript-system-bundle-config.json +4 -4
  6. package/kepler-compatibility.json +2 -2
  7. package/lib/module/TransitionConfigs/CardStyleInterpolators.js +57 -1
  8. package/lib/module/TransitionConfigs/CardStyleInterpolators.js.map +1 -1
  9. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js +30 -16
  10. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js.map +1 -1
  11. package/lib/module/TransitionConfigs/TransitionPresets.js +32 -4
  12. package/lib/module/TransitionConfigs/TransitionPresets.js.map +1 -1
  13. package/lib/module/TransitionConfigs/TransitionSpecs.js +32 -2
  14. package/lib/module/TransitionConfigs/TransitionSpecs.js.map +1 -1
  15. package/lib/module/index.js +13 -11
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/navigators/createStackNavigator.js +46 -48
  18. package/lib/module/navigators/createStackNavigator.js.map +1 -1
  19. package/lib/module/package.json +1 -0
  20. package/lib/module/types.js +2 -0
  21. package/lib/module/types.js.map +1 -1
  22. package/lib/module/utils/CardAnimationContext.js +3 -1
  23. package/lib/module/utils/CardAnimationContext.js.map +1 -1
  24. package/lib/module/utils/GestureHandlerRefContext.js +3 -1
  25. package/lib/module/utils/GestureHandlerRefContext.js.map +1 -1
  26. package/lib/module/utils/ModalPresentationContext.js +3 -2
  27. package/lib/module/utils/ModalPresentationContext.js.map +1 -1
  28. package/lib/module/utils/conditional.js +3 -1
  29. package/lib/module/utils/conditional.js.map +1 -1
  30. package/lib/module/utils/findLastIndex.js +4 -2
  31. package/lib/module/utils/findLastIndex.js.map +1 -1
  32. package/lib/module/utils/gestureActivationCriteria.js +60 -0
  33. package/lib/module/utils/gestureActivationCriteria.js.map +1 -0
  34. package/lib/module/utils/getDistanceForDirection.js +5 -3
  35. package/lib/module/utils/getDistanceForDirection.js.map +1 -1
  36. package/lib/module/utils/getInvertedMultiplier.js +5 -4
  37. package/lib/module/utils/getInvertedMultiplier.js.map +1 -1
  38. package/lib/module/utils/getModalRoutesKeys.js +12 -0
  39. package/lib/module/utils/getModalRoutesKeys.js.map +1 -0
  40. package/lib/module/utils/getShadowStyle.js +24 -0
  41. package/lib/module/utils/getShadowStyle.js.map +1 -0
  42. package/lib/module/utils/{debounce.js → throttle.js} +5 -4
  43. package/lib/module/utils/throttle.js.map +1 -0
  44. package/lib/module/utils/useCardAnimation.js +4 -2
  45. package/lib/module/utils/useCardAnimation.js.map +1 -1
  46. package/lib/module/utils/useGestureHandlerRef.js +5 -3
  47. package/lib/module/utils/useGestureHandlerRef.js.map +1 -1
  48. package/lib/module/utils/useKeyboardManager.js +8 -6
  49. package/lib/module/utils/useKeyboardManager.js.map +1 -1
  50. package/lib/module/views/GestureHandler.android.js +3 -1
  51. package/lib/module/views/GestureHandler.android.js.map +1 -1
  52. package/lib/module/views/GestureHandler.ios.js +3 -1
  53. package/lib/module/views/GestureHandler.ios.js.map +1 -1
  54. package/lib/module/views/GestureHandler.js +6 -1
  55. package/lib/module/views/GestureHandler.js.map +1 -1
  56. package/lib/module/views/GestureHandler.kepler.js +4 -0
  57. package/lib/module/views/GestureHandler.kepler.js.map +1 -0
  58. package/lib/module/views/GestureHandlerNative.js +13 -9
  59. package/lib/module/views/GestureHandlerNative.js.map +1 -1
  60. package/lib/module/views/Header/Header.js +12 -8
  61. package/lib/module/views/Header/Header.js.map +1 -1
  62. package/lib/module/views/Header/HeaderContainer.js +103 -93
  63. package/lib/module/views/Header/HeaderContainer.js.map +1 -1
  64. package/lib/module/views/Header/HeaderSegment.js +43 -31
  65. package/lib/module/views/Header/HeaderSegment.js.map +1 -1
  66. package/lib/module/views/Screens.js +17 -9
  67. package/lib/module/views/Screens.js.map +1 -1
  68. package/lib/module/views/Stack/Card.js +313 -338
  69. package/lib/module/views/Stack/Card.js.map +1 -1
  70. package/lib/module/views/Stack/CardA11yWrapper.js +43 -0
  71. package/lib/module/views/Stack/CardA11yWrapper.js.map +1 -0
  72. package/lib/module/views/Stack/CardContainer.js +116 -90
  73. package/lib/module/views/Stack/CardContainer.js.map +1 -1
  74. package/lib/module/views/Stack/CardContent.js +74 -0
  75. package/lib/module/views/Stack/CardContent.js.map +1 -0
  76. package/lib/module/views/Stack/CardStack.js +241 -180
  77. package/lib/module/views/Stack/CardStack.js.map +1 -1
  78. package/lib/module/views/Stack/StackView.js +80 -64
  79. package/lib/module/views/Stack/StackView.js.map +1 -1
  80. package/lib/typescript/package.json +1 -0
  81. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +8 -0
  82. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -1
  83. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +3 -3
  84. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -1
  85. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +8 -0
  86. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -1
  87. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +10 -0
  88. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -1
  89. package/lib/typescript/src/index.d.ts +8 -8
  90. package/lib/typescript/src/index.d.ts.map +1 -1
  91. package/lib/typescript/src/navigators/createStackNavigator.d.ts +15 -7
  92. package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -1
  93. package/lib/typescript/src/types.d.ts +84 -24
  94. package/lib/typescript/src/types.d.ts.map +1 -1
  95. package/lib/typescript/src/utils/CardAnimationContext.d.ts +1 -2
  96. package/lib/typescript/src/utils/CardAnimationContext.d.ts.map +1 -1
  97. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts +1 -2
  98. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts.map +1 -1
  99. package/lib/typescript/src/utils/ModalPresentationContext.d.ts +1 -2
  100. package/lib/typescript/src/utils/ModalPresentationContext.d.ts.map +1 -1
  101. package/lib/typescript/src/utils/conditional.d.ts +1 -1
  102. package/lib/typescript/src/utils/conditional.d.ts.map +1 -1
  103. package/lib/typescript/src/utils/findLastIndex.d.ts +1 -1
  104. package/lib/typescript/src/utils/findLastIndex.d.ts.map +1 -1
  105. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts +57 -0
  106. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts.map +1 -0
  107. package/lib/typescript/src/utils/getDistanceForDirection.d.ts +1 -1
  108. package/lib/typescript/src/utils/getDistanceForDirection.d.ts.map +1 -1
  109. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts +1 -1
  110. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts.map +1 -1
  111. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts +4 -0
  112. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts.map +1 -0
  113. package/lib/typescript/src/utils/getShadowStyle.d.ts +27 -0
  114. package/lib/typescript/src/utils/getShadowStyle.d.ts.map +1 -0
  115. package/lib/typescript/src/utils/throttle.d.ts +2 -0
  116. package/lib/typescript/src/utils/throttle.d.ts.map +1 -0
  117. package/lib/typescript/src/utils/useCardAnimation.d.ts +1 -1
  118. package/lib/typescript/src/utils/useCardAnimation.d.ts.map +1 -1
  119. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts +1 -1
  120. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts.map +1 -1
  121. package/lib/typescript/src/utils/useKeyboardManager.d.ts +1 -1
  122. package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -1
  123. package/lib/typescript/src/views/GestureHandler.d.ts +3 -2
  124. package/lib/typescript/src/views/GestureHandler.d.ts.map +1 -1
  125. package/lib/typescript/src/views/GestureHandler.kepler.d.ts +2 -0
  126. package/lib/typescript/src/views/GestureHandler.kepler.d.ts.map +1 -0
  127. package/lib/typescript/src/views/GestureHandlerNative.d.ts +4 -5
  128. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -1
  129. package/lib/typescript/src/views/Header/Header.d.ts +1 -2
  130. package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
  131. package/lib/typescript/src/views/Header/HeaderContainer.d.ts +4 -5
  132. package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
  133. package/lib/typescript/src/views/Header/HeaderSegment.d.ts +2 -2
  134. package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
  135. package/lib/typescript/src/views/Screens.d.ts +7 -5
  136. package/lib/typescript/src/views/Screens.d.ts.map +1 -1
  137. package/lib/typescript/src/views/Stack/Card.d.ts +14 -42
  138. package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
  139. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +15 -0
  140. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +1 -0
  141. package/lib/typescript/src/views/Stack/CardContainer.d.ts +6 -8
  142. package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
  143. package/lib/typescript/src/views/Stack/CardContent.d.ts +13 -0
  144. package/lib/typescript/src/views/Stack/CardContent.d.ts.map +1 -0
  145. package/lib/typescript/src/views/Stack/CardStack.d.ts +8 -7
  146. package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
  147. package/lib/typescript/src/views/Stack/StackView.d.ts +10 -81
  148. package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -1
  149. package/package.json +1 -1
  150. package/src/TransitionConfigs/CardStyleInterpolators.tsx +72 -6
  151. package/src/TransitionConfigs/HeaderStyleInterpolators.tsx +43 -25
  152. package/src/TransitionConfigs/TransitionPresets.tsx +35 -5
  153. package/src/TransitionConfigs/TransitionSpecs.tsx +30 -2
  154. package/src/index.tsx +12 -7
  155. package/src/navigators/createStackNavigator.tsx +47 -63
  156. package/src/types.tsx +116 -24
  157. package/src/utils/CardAnimationContext.tsx +3 -3
  158. package/src/utils/GestureHandlerRefContext.tsx +2 -2
  159. package/src/utils/ModalPresentationContext.tsx +1 -3
  160. package/src/utils/conditional.tsx +1 -1
  161. package/src/utils/findLastIndex.tsx +2 -5
  162. package/src/utils/gestureActivationCriteria.tsx +70 -0
  163. package/src/utils/getDistanceForDirection.tsx +5 -4
  164. package/src/utils/getInvertedMultiplier.tsx +5 -6
  165. package/src/utils/getModalRoutesKeys.ts +21 -0
  166. package/src/utils/getShadowStyle.tsx +37 -0
  167. package/src/utils/throttle.tsx +16 -0
  168. package/src/utils/useCardAnimation.tsx +2 -2
  169. package/src/utils/useGestureHandlerRef.tsx +3 -3
  170. package/src/utils/useKeyboardManager.tsx +5 -7
  171. package/src/views/GestureHandler.kepler.tsx +1 -0
  172. package/src/views/GestureHandler.tsx +2 -2
  173. package/src/views/GestureHandlerNative.tsx +5 -5
  174. package/src/views/Header/Header.tsx +8 -7
  175. package/src/views/Header/HeaderContainer.tsx +23 -18
  176. package/src/views/Header/HeaderSegment.tsx +41 -43
  177. package/src/views/Screens.tsx +4 -2
  178. package/src/views/Stack/Card.tsx +480 -462
  179. package/src/views/Stack/CardA11yWrapper.tsx +67 -0
  180. package/src/views/Stack/CardContainer.tsx +127 -108
  181. package/src/views/Stack/CardContent.tsx +92 -0
  182. package/src/views/Stack/CardStack.tsx +370 -243
  183. package/src/views/Stack/StackView.tsx +73 -62
  184. package/SystemBundles/b598f9dfffcd611d6cd7d6a3c5ab3d66234659a03b40b6579fddb628e61b8313.bundle +0 -28538
  185. package/SystemBundles/b598f9dfffcd611d6cd7d6a3c5ab3d66234659a03b40b6579fddb628e61b8313.map +0 -1
  186. package/SystemModules/amzn__react-navigation__stack-7.modules.txt +0 -95
  187. package/SystemModules/amzn__react-navigation__stack-7.private.modules.txt +0 -185
  188. package/THIRD_PARTY_NOTICES.txt +0 -24
  189. package/lib/commonjs/TransitionConfigs/CardStyleInterpolators.js +0 -353
  190. package/lib/commonjs/TransitionConfigs/CardStyleInterpolators.js.map +0 -1
  191. package/lib/commonjs/TransitionConfigs/HeaderStyleInterpolators.js +0 -259
  192. package/lib/commonjs/TransitionConfigs/HeaderStyleInterpolators.js.map +0 -1
  193. package/lib/commonjs/TransitionConfigs/TransitionPresets.js +0 -134
  194. package/lib/commonjs/TransitionConfigs/TransitionPresets.js.map +0 -1
  195. package/lib/commonjs/TransitionConfigs/TransitionSpecs.js +0 -100
  196. package/lib/commonjs/TransitionConfigs/TransitionSpecs.js.map +0 -1
  197. package/lib/commonjs/index.js +0 -69
  198. package/lib/commonjs/index.js.map +0 -1
  199. package/lib/commonjs/navigators/createStackNavigator.js +0 -82
  200. package/lib/commonjs/navigators/createStackNavigator.js.map +0 -1
  201. package/lib/commonjs/types.js +0 -6
  202. package/lib/commonjs/types.js.map +0 -1
  203. package/lib/commonjs/utils/CardAnimationContext.js +0 -11
  204. package/lib/commonjs/utils/CardAnimationContext.js.map +0 -1
  205. package/lib/commonjs/utils/GestureHandlerRefContext.js +0 -11
  206. package/lib/commonjs/utils/GestureHandlerRefContext.js.map +0 -1
  207. package/lib/commonjs/utils/ModalPresentationContext.js +0 -12
  208. package/lib/commonjs/utils/ModalPresentationContext.js.map +0 -1
  209. package/lib/commonjs/utils/conditional.js +0 -32
  210. package/lib/commonjs/utils/conditional.js.map +0 -1
  211. package/lib/commonjs/utils/debounce.js +0 -19
  212. package/lib/commonjs/utils/debounce.js.map +0 -1
  213. package/lib/commonjs/utils/findLastIndex.js +0 -15
  214. package/lib/commonjs/utils/findLastIndex.js.map +0 -1
  215. package/lib/commonjs/utils/getDistanceForDirection.js +0 -20
  216. package/lib/commonjs/utils/getDistanceForDirection.js.map +0 -1
  217. package/lib/commonjs/utils/getInvertedMultiplier.js +0 -20
  218. package/lib/commonjs/utils/getInvertedMultiplier.js.map +0 -1
  219. package/lib/commonjs/utils/memoize.js +0 -33
  220. package/lib/commonjs/utils/memoize.js.map +0 -1
  221. package/lib/commonjs/utils/useCardAnimation.js +0 -19
  222. package/lib/commonjs/utils/useCardAnimation.js.map +0 -1
  223. package/lib/commonjs/utils/useGestureHandlerRef.js +0 -19
  224. package/lib/commonjs/utils/useGestureHandlerRef.js.map +0 -1
  225. package/lib/commonjs/utils/useKeyboardManager.js +0 -96
  226. package/lib/commonjs/utils/useKeyboardManager.js.map +0 -1
  227. package/lib/commonjs/views/GestureHandler.android.js +0 -17
  228. package/lib/commonjs/views/GestureHandler.android.js.map +0 -1
  229. package/lib/commonjs/views/GestureHandler.ios.js +0 -17
  230. package/lib/commonjs/views/GestureHandler.ios.js.map +0 -1
  231. package/lib/commonjs/views/GestureHandler.js +0 -24
  232. package/lib/commonjs/views/GestureHandler.js.map +0 -1
  233. package/lib/commonjs/views/GestureHandlerNative.js +0 -34
  234. package/lib/commonjs/views/GestureHandlerNative.js.map +0 -1
  235. package/lib/commonjs/views/Header/Header.js +0 -61
  236. package/lib/commonjs/views/Header/Header.js.map +0 -1
  237. package/lib/commonjs/views/Header/HeaderContainer.js +0 -127
  238. package/lib/commonjs/views/Header/HeaderContainer.js.map +0 -1
  239. package/lib/commonjs/views/Header/HeaderSegment.js +0 -139
  240. package/lib/commonjs/views/Header/HeaderSegment.js.map +0 -1
  241. package/lib/commonjs/views/ModalStatusBarManager.js +0 -42
  242. package/lib/commonjs/views/ModalStatusBarManager.js.map +0 -1
  243. package/lib/commonjs/views/Screens.js +0 -44
  244. package/lib/commonjs/views/Screens.js.map +0 -1
  245. package/lib/commonjs/views/Stack/Card.js +0 -469
  246. package/lib/commonjs/views/Stack/Card.js.map +0 -1
  247. package/lib/commonjs/views/Stack/CardContainer.js +0 -259
  248. package/lib/commonjs/views/Stack/CardContainer.js.map +0 -1
  249. package/lib/commonjs/views/Stack/CardSheet.js +0 -54
  250. package/lib/commonjs/views/Stack/CardSheet.js.map +0 -1
  251. package/lib/commonjs/views/Stack/CardStack.js +0 -442
  252. package/lib/commonjs/views/Stack/CardStack.js.map +0 -1
  253. package/lib/commonjs/views/Stack/StackView.js +0 -333
  254. package/lib/commonjs/views/Stack/StackView.js.map +0 -1
  255. package/lib/module/utils/debounce.js.map +0 -1
  256. package/lib/module/utils/memoize.js +0 -27
  257. package/lib/module/utils/memoize.js.map +0 -1
  258. package/lib/module/views/ModalStatusBarManager.js +0 -34
  259. package/lib/module/views/ModalStatusBarManager.js.map +0 -1
  260. package/lib/module/views/Stack/CardSheet.js +0 -46
  261. package/lib/module/views/Stack/CardSheet.js.map +0 -1
  262. package/lib/typescript/src/utils/debounce.d.ts +0 -2
  263. package/lib/typescript/src/utils/debounce.d.ts.map +0 -1
  264. package/lib/typescript/src/utils/memoize.d.ts +0 -2
  265. package/lib/typescript/src/utils/memoize.d.ts.map +0 -1
  266. package/lib/typescript/src/views/ModalStatusBarManager.d.ts +0 -12
  267. package/lib/typescript/src/views/ModalStatusBarManager.d.ts.map +0 -1
  268. package/lib/typescript/src/views/Stack/CardSheet.d.ts +0 -15
  269. package/lib/typescript/src/views/Stack/CardSheet.d.ts.map +0 -1
  270. package/src/utils/debounce.tsx +0 -17
  271. package/src/utils/memoize.tsx +0 -33
  272. package/src/views/ModalStatusBarManager.tsx +0 -50
  273. package/src/views/Stack/CardSheet.tsx +0 -61
@@ -1,20 +1,20 @@
1
1
  import {
2
- Background,
3
2
  getDefaultHeaderHeight,
4
3
  SafeAreaProviderCompat,
5
4
  } from '@amazon-devices/react-navigation__elements';
6
5
  import type {
6
+ LocaleDirection,
7
7
  ParamListBase,
8
8
  Route,
9
9
  StackNavigationState,
10
10
  } from '@amazon-devices/react-navigation__native';
11
- import Color from 'color';
12
11
  import * as React from 'react';
13
12
  import {
14
13
  Animated,
15
- LayoutChangeEvent,
14
+ type LayoutChangeEvent,
16
15
  Platform,
17
16
  StyleSheet,
17
+ View,
18
18
  } from 'react-native';
19
19
  import type { EdgeInsets } from '@amazon-devices/react-native-safe-area-context';
20
20
 
@@ -23,33 +23,45 @@ import {
23
23
  forNoAnimation as forNoAnimationCard,
24
24
  } from '../../TransitionConfigs/CardStyleInterpolators';
25
25
  import {
26
+ BottomSheetAndroid,
26
27
  DefaultTransition,
28
+ FadeFromBottomAndroid,
29
+ FadeFromRightAndroid,
27
30
  ModalFadeTransition,
31
+ ModalSlideFromBottomIOS,
28
32
  ModalTransition,
33
+ RevealFromBottomAndroid,
34
+ ScaleFromCenterAndroid,
35
+ SlideFromLeftIOS,
36
+ SlideFromRightIOS,
29
37
  } from '../../TransitionConfigs/TransitionPresets';
30
38
  import type {
31
39
  Layout,
32
40
  Scene,
33
- StackDescriptor,
41
+ StackAnimationName,
42
+ StackCardStyleInterpolator,
34
43
  StackDescriptorMap,
35
44
  StackHeaderMode,
36
45
  StackNavigationOptions,
46
+ TransitionPreset,
37
47
  } from '../../types';
38
- import findLastIndex from '../../utils/findLastIndex';
39
- import getDistanceForDirection from '../../utils/getDistanceForDirection';
48
+ import { findLastIndex } from '../../utils/findLastIndex';
49
+ import { getDistanceForDirection } from '../../utils/getDistanceForDirection';
50
+ import { getModalRouteKeys } from '../../utils/getModalRoutesKeys';
40
51
  import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
41
52
  import { MaybeScreen, MaybeScreenContainer } from '../Screens';
42
- import { getIsModalPresentation } from './Card';
43
- import CardContainer from './CardContainer';
53
+ import { CardContainer } from './CardContainer';
44
54
 
45
55
  type GestureValues = {
46
56
  [key: string]: Animated.Value;
47
57
  };
48
58
 
49
59
  type Props = {
60
+ direction: LocaleDirection;
50
61
  insets: EdgeInsets;
51
62
  state: StackNavigationState<ParamListBase>;
52
63
  descriptors: StackDescriptorMap;
64
+ preloadedDescriptors: StackDescriptorMap;
53
65
  routes: Route<string>[];
54
66
  openingRouteKeys: string[];
55
67
  closingRouteKeys: string[];
@@ -59,7 +71,6 @@ type Props = {
59
71
  route: Route<string>;
60
72
  }) => Route<string> | undefined;
61
73
  renderHeader: (props: HeaderContainerProps) => React.ReactNode;
62
- renderScene: (props: { route: Route<string> }) => React.ReactNode;
63
74
  isParentHeaderShown: boolean;
64
75
  isParentModal: boolean;
65
76
  onTransitionStart: (
@@ -79,11 +90,31 @@ type State = {
79
90
  scenes: Scene[];
80
91
  gestures: GestureValues;
81
92
  layout: Layout;
93
+ activeStates: (0 | 1 | Animated.AnimatedInterpolation<0 | 1>)[];
82
94
  headerHeights: Record<string, number>;
83
95
  };
84
96
 
97
+ const NAMED_TRANSITIONS_PRESETS = {
98
+ default: DefaultTransition,
99
+ fade: ModalFadeTransition,
100
+ fade_from_bottom: FadeFromBottomAndroid,
101
+ fade_from_right: FadeFromRightAndroid,
102
+ none: DefaultTransition,
103
+ reveal_from_bottom: RevealFromBottomAndroid,
104
+ scale_from_center: ScaleFromCenterAndroid,
105
+ slide_from_left: SlideFromLeftIOS,
106
+ slide_from_right: SlideFromRightIOS,
107
+ slide_from_bottom: Platform.select({
108
+ ios: ModalSlideFromBottomIOS,
109
+ default: BottomSheetAndroid,
110
+ }),
111
+ } as const satisfies Record<StackAnimationName, TransitionPreset>;
112
+
113
+ const EPSILON = 1e-5;
114
+
85
115
  const STATE_INACTIVE = 0;
86
116
  const STATE_TRANSITIONING_OR_BELOW_TOP = 1;
117
+ const STATE_ON_TOP = 2;
87
118
 
88
119
  const FALLBACK_DESCRIPTOR = Object.freeze({ options: {} });
89
120
 
@@ -107,6 +138,16 @@ const getInterpolationIndex = (scenes: Scene[], index: number) => {
107
138
  return interpolationIndex;
108
139
  };
109
140
 
141
+ const getIsModalPresentation = (
142
+ cardStyleInterpolator: StackCardStyleInterpolator
143
+ ) => {
144
+ return (
145
+ cardStyleInterpolator === forModalPresentationIOS ||
146
+ // Handle custom modal presentation interpolators as well
147
+ cardStyleInterpolator.name === 'forModalPresentationIOS'
148
+ );
149
+ };
150
+
110
151
  const getIsModal = (
111
152
  scene: Scene,
112
153
  interpolationIndex: number,
@@ -158,22 +199,30 @@ const getHeaderHeights = (
158
199
 
159
200
  const getDistanceFromOptions = (
160
201
  layout: Layout,
161
- descriptor?: StackDescriptor
202
+ options: StackNavigationOptions | undefined,
203
+ isRTL: boolean
162
204
  ) => {
163
- const {
164
- presentation,
165
- gestureDirection = presentation === 'modal'
205
+ if (options?.gestureDirection) {
206
+ return getDistanceForDirection(layout, options.gestureDirection, isRTL);
207
+ }
208
+
209
+ const defaultGestureDirection =
210
+ options?.presentation === 'modal'
166
211
  ? ModalTransition.gestureDirection
167
- : DefaultTransition.gestureDirection,
168
- } = (descriptor?.options || {}) as StackNavigationOptions;
212
+ : DefaultTransition.gestureDirection;
169
213
 
170
- return getDistanceForDirection(layout, gestureDirection);
214
+ const gestureDirection = options?.animation
215
+ ? NAMED_TRANSITIONS_PRESETS[options?.animation]?.gestureDirection
216
+ : defaultGestureDirection;
217
+
218
+ return getDistanceForDirection(layout, gestureDirection, isRTL);
171
219
  };
172
220
 
173
221
  const getProgressFromGesture = (
174
222
  gesture: Animated.Value,
175
223
  layout: Layout,
176
- descriptor?: StackDescriptor
224
+ options: StackNavigationOptions | undefined,
225
+ isRTL: boolean
177
226
  ) => {
178
227
  const distance = getDistanceFromOptions(
179
228
  {
@@ -182,7 +231,8 @@ const getProgressFromGesture = (
182
231
  width: Math.max(1, layout.width),
183
232
  height: Math.max(1, layout.height),
184
233
  },
185
- descriptor
234
+ options,
235
+ isRTL
186
236
  );
187
237
 
188
238
  if (distance > 0) {
@@ -198,7 +248,21 @@ const getProgressFromGesture = (
198
248
  });
199
249
  };
200
250
 
201
- export default class CardStack extends React.Component<Props, State> {
251
+ function getDefaultAnimation(animation: StackAnimationName | undefined) {
252
+ // Disable screen transition animation by default on web, windows and macos to match the native behavior
253
+ const excludedPlatforms =
254
+ Platform.OS !== 'web' &&
255
+ Platform.OS !== 'windows' &&
256
+ Platform.OS !== 'macos';
257
+
258
+ return animation ?? (excludedPlatforms ? 'default' : 'none');
259
+ }
260
+
261
+ export function getAnimationEnabled(animation: StackAnimationName | undefined) {
262
+ return getDefaultAnimation(animation) !== 'none';
263
+ }
264
+
265
+ export class CardStack extends React.Component<Props, State> {
202
266
  static getDerivedStateFromProps(
203
267
  props: Props,
204
268
  state: State
@@ -210,164 +274,284 @@ export default class CardStack extends React.Component<Props, State> {
210
274
  return null;
211
275
  }
212
276
 
213
- const gestures = props.routes.reduce<GestureValues>((acc, curr) => {
214
- const descriptor = props.descriptors[curr.key];
215
- const { animationEnabled } = descriptor?.options || {};
277
+ const gestures = [
278
+ ...props.routes,
279
+ ...props.state.preloadedRoutes,
280
+ ].reduce<GestureValues>((acc, curr) => {
281
+ const descriptor =
282
+ props.descriptors[curr.key] || props.preloadedDescriptors[curr.key];
283
+ const { animation } = descriptor?.options || {};
216
284
 
217
285
  acc[curr.key] =
218
286
  state.gestures[curr.key] ||
219
287
  new Animated.Value(
220
- props.openingRouteKeys.includes(curr.key) &&
221
- animationEnabled !== false
222
- ? getDistanceFromOptions(state.layout, descriptor)
288
+ (props.openingRouteKeys.includes(curr.key) &&
289
+ getAnimationEnabled(animation)) ||
290
+ props.state.preloadedRoutes.includes(curr)
291
+ ? getDistanceFromOptions(
292
+ state.layout,
293
+ descriptor?.options,
294
+ props.direction === 'rtl'
295
+ )
223
296
  : 0
224
297
  );
225
298
 
226
299
  return acc;
227
300
  }, {});
228
301
 
229
- const scenes = props.routes.map((route, index, self) => {
230
- const previousRoute = self[index - 1];
231
- const nextRoute = self[index + 1];
232
-
233
- const oldScene = state.scenes[index];
302
+ const modalRouteKeys = getModalRouteKeys(
303
+ [...props.routes, ...props.state.preloadedRoutes],
304
+ {
305
+ ...props.descriptors,
306
+ ...props.preloadedDescriptors,
307
+ }
308
+ );
234
309
 
235
- const currentGesture = gestures[route.key];
236
- const previousGesture = previousRoute
237
- ? gestures[previousRoute.key]
238
- : undefined;
239
- const nextGesture = nextRoute ? gestures[nextRoute.key] : undefined;
310
+ const scenes = [...props.routes, ...props.state.preloadedRoutes].map(
311
+ (route, index, self) => {
312
+ // For preloaded screens, we don't care about the previous and the next screen
313
+ const isPreloaded = props.state.preloadedRoutes.includes(route);
314
+ const previousRoute = isPreloaded ? undefined : self[index - 1];
315
+ const nextRoute = isPreloaded ? undefined : self[index + 1];
316
+
317
+ const oldScene = state.scenes[index];
318
+
319
+ const currentGesture = gestures[route.key];
320
+ const previousGesture = previousRoute
321
+ ? gestures[previousRoute.key]
322
+ : undefined;
323
+ const nextGesture = nextRoute ? gestures[nextRoute.key] : undefined;
324
+
325
+ const descriptor =
326
+ (isPreloaded ? props.preloadedDescriptors : props.descriptors)[
327
+ route.key
328
+ ] ||
329
+ state.descriptors[route.key] ||
330
+ (oldScene ? oldScene.descriptor : FALLBACK_DESCRIPTOR);
331
+
332
+ const nextOptions =
333
+ nextRoute &&
334
+ (
335
+ props.descriptors[nextRoute?.key] ||
336
+ state.descriptors[nextRoute?.key]
337
+ )?.options;
338
+
339
+ const previousOptions =
340
+ previousRoute &&
341
+ (
342
+ props.descriptors[previousRoute?.key] ||
343
+ state.descriptors[previousRoute?.key]
344
+ )?.options;
345
+
346
+ // When a screen is not the last, it should use next screen's transition config
347
+ // Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
348
+ // For example combining a slide and a modal transition would look wrong otherwise
349
+ // With this approach, combining different transition styles in the same navigator mostly looks right
350
+ // This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
351
+ // but the majority of the transitions look alright
352
+ const optionsForTransitionConfig =
353
+ index !== self.length - 1 &&
354
+ nextOptions &&
355
+ nextOptions?.presentation !== 'transparentModal'
356
+ ? nextOptions
357
+ : descriptor.options;
358
+
359
+ // Assume modal if there are already modal screens in the stack
360
+ // or current screen is a modal when no presentation is specified
361
+ const isModal = modalRouteKeys.includes(route.key);
362
+
363
+ const animation = getDefaultAnimation(
364
+ optionsForTransitionConfig.animation
365
+ );
240
366
 
241
- const descriptor =
242
- props.descriptors[route.key] ||
243
- state.descriptors[route.key] ||
244
- (oldScene ? oldScene.descriptor : FALLBACK_DESCRIPTOR);
245
-
246
- const nextDescriptor =
247
- props.descriptors[nextRoute?.key] || state.descriptors[nextRoute?.key];
248
-
249
- const previousDescriptor =
250
- props.descriptors[previousRoute?.key] ||
251
- state.descriptors[previousRoute?.key];
252
-
253
- // When a screen is not the last, it should use next screen's transition config
254
- // Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
255
- // For example combining a slide and a modal transition would look wrong otherwise
256
- // With this approach, combining different transition styles in the same navigator mostly looks right
257
- // This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
258
- // but majority of the transitions look alright
259
- const optionsForTransitionConfig =
260
- index !== self.length - 1 &&
261
- nextDescriptor &&
262
- nextDescriptor.options.presentation !== 'transparentModal'
263
- ? nextDescriptor.options
264
- : descriptor.options;
265
-
266
- let defaultTransitionPreset =
267
- optionsForTransitionConfig.presentation === 'modal'
268
- ? ModalTransition
269
- : optionsForTransitionConfig.presentation === 'transparentModal'
270
- ? ModalFadeTransition
271
- : DefaultTransition;
272
-
273
- const {
274
- animationEnabled = Platform.OS !== 'web' &&
275
- Platform.OS !== 'windows' &&
276
- Platform.OS !== 'macos',
277
- gestureEnabled = Platform.OS === 'ios' && animationEnabled,
278
- gestureDirection = defaultTransitionPreset.gestureDirection,
279
- transitionSpec = defaultTransitionPreset.transitionSpec,
280
- cardStyleInterpolator = animationEnabled === false
281
- ? forNoAnimationCard
282
- : defaultTransitionPreset.cardStyleInterpolator,
283
- headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
284
- cardOverlayEnabled = (Platform.OS !== 'ios' &&
285
- optionsForTransitionConfig.presentation !== 'transparentModal') ||
286
- getIsModalPresentation(cardStyleInterpolator),
287
- } = optionsForTransitionConfig;
288
-
289
- const headerMode: StackHeaderMode =
290
- descriptor.options.headerMode ??
291
- (!(
292
- optionsForTransitionConfig.presentation === 'modal' ||
293
- optionsForTransitionConfig.presentation === 'transparentModal' ||
294
- nextDescriptor?.options.presentation === 'modal' ||
295
- nextDescriptor?.options.presentation === 'transparentModal' ||
296
- getIsModalPresentation(cardStyleInterpolator)
297
- ) &&
298
- Platform.OS === 'ios' &&
299
- descriptor.options.header === undefined
300
- ? 'float'
301
- : 'screen');
302
-
303
- const scene = {
304
- route,
305
- descriptor: {
306
- ...descriptor,
307
- options: {
308
- ...descriptor.options,
309
- animationEnabled,
310
- cardOverlayEnabled,
311
- cardStyleInterpolator,
312
- gestureDirection,
313
- gestureEnabled,
314
- headerStyleInterpolator,
315
- transitionSpec,
316
- headerMode,
367
+ const isAnimationEnabled = getAnimationEnabled(animation);
368
+
369
+ const transitionPreset =
370
+ animation !== 'default'
371
+ ? NAMED_TRANSITIONS_PRESETS[animation]
372
+ : optionsForTransitionConfig.presentation === 'transparentModal'
373
+ ? ModalFadeTransition
374
+ : optionsForTransitionConfig.presentation === 'modal' || isModal
375
+ ? ModalTransition
376
+ : DefaultTransition;
377
+
378
+ const {
379
+ gestureEnabled = Platform.OS === 'ios' && isAnimationEnabled,
380
+ gestureDirection = transitionPreset.gestureDirection,
381
+ transitionSpec = transitionPreset.transitionSpec,
382
+ cardStyleInterpolator = isAnimationEnabled
383
+ ? transitionPreset.cardStyleInterpolator
384
+ : forNoAnimationCard,
385
+ headerStyleInterpolator = transitionPreset.headerStyleInterpolator,
386
+ cardOverlayEnabled = (Platform.OS !== 'ios' &&
387
+ optionsForTransitionConfig.presentation !== 'transparentModal') ||
388
+ getIsModalPresentation(cardStyleInterpolator),
389
+ } = optionsForTransitionConfig;
390
+
391
+ const headerMode: StackHeaderMode =
392
+ descriptor.options.headerMode ??
393
+ (!(
394
+ optionsForTransitionConfig.presentation === 'modal' ||
395
+ optionsForTransitionConfig.presentation === 'transparentModal' ||
396
+ nextOptions?.presentation === 'modal' ||
397
+ nextOptions?.presentation === 'transparentModal' ||
398
+ getIsModalPresentation(cardStyleInterpolator)
399
+ ) &&
400
+ Platform.OS === 'ios' &&
401
+ descriptor.options.header === undefined
402
+ ? 'float'
403
+ : 'screen');
404
+
405
+ const isRTL = props.direction === 'rtl';
406
+
407
+ const scene = {
408
+ route,
409
+ descriptor: {
410
+ ...descriptor,
411
+ options: {
412
+ ...descriptor.options,
413
+ animation,
414
+ cardOverlayEnabled,
415
+ cardStyleInterpolator,
416
+ gestureDirection,
417
+ gestureEnabled,
418
+ headerStyleInterpolator,
419
+ transitionSpec,
420
+ headerMode,
421
+ },
317
422
  },
318
- },
319
- progress: {
320
- current: getProgressFromGesture(
321
- currentGesture,
322
- state.layout,
323
- descriptor
324
- ),
325
- next:
326
- nextGesture &&
327
- nextDescriptor?.options.presentation !== 'transparentModal'
423
+ progress: {
424
+ current: getProgressFromGesture(
425
+ currentGesture,
426
+ state.layout,
427
+ descriptor.options,
428
+ isRTL
429
+ ),
430
+ next:
431
+ nextGesture && nextOptions?.presentation !== 'transparentModal'
432
+ ? getProgressFromGesture(
433
+ nextGesture,
434
+ state.layout,
435
+ nextOptions,
436
+ isRTL
437
+ )
438
+ : undefined,
439
+ previous: previousGesture
328
440
  ? getProgressFromGesture(
329
- nextGesture,
441
+ previousGesture,
330
442
  state.layout,
331
- nextDescriptor
443
+ previousOptions,
444
+ isRTL
332
445
  )
333
446
  : undefined,
334
- previous: previousGesture
335
- ? getProgressFromGesture(
336
- previousGesture,
337
- state.layout,
338
- previousDescriptor
339
- )
340
- : undefined,
341
- },
342
- __memo: [
343
- state.layout,
344
- descriptor,
345
- nextDescriptor,
346
- previousDescriptor,
347
- currentGesture,
348
- nextGesture,
349
- previousGesture,
350
- ],
351
- };
447
+ },
448
+ __memo: [
449
+ state.layout,
450
+ descriptor,
451
+ nextOptions,
452
+ previousOptions,
453
+ currentGesture,
454
+ nextGesture,
455
+ previousGesture,
456
+ ],
457
+ };
458
+
459
+ if (
460
+ oldScene &&
461
+ scene.__memo.every((it, i) => {
462
+ // @ts-expect-error: we haven't added __memo to the annotation to prevent usage elsewhere
463
+ return oldScene.__memo[i] === it;
464
+ })
465
+ ) {
466
+ return oldScene;
467
+ }
352
468
 
353
- if (
354
- oldScene &&
355
- scene.__memo.every((it, i) => {
356
- // @ts-expect-error: we haven't added __memo to the annotation to prevent usage elsewhere
357
- return oldScene.__memo[i] === it;
358
- })
359
- ) {
360
- return oldScene;
469
+ return scene;
361
470
  }
471
+ );
362
472
 
363
- return scene;
364
- });
473
+ let activeStates = state.activeStates;
474
+
475
+ if (props.routes.length !== state.routes.length) {
476
+ let activeScreensLimit = 1;
477
+
478
+ for (let i = props.routes.length - 1; i >= 0; i--) {
479
+ const { options } = scenes[i].descriptor;
480
+
481
+ const {
482
+ // By default, we don't want to detach the previous screen of the active one for modals
483
+ detachPreviousScreen = options.presentation === 'transparentModal'
484
+ ? false
485
+ : getIsModalPresentation(options.cardStyleInterpolator)
486
+ ? i !==
487
+ findLastIndex(scenes, (scene) => {
488
+ const { cardStyleInterpolator } = scene.descriptor.options;
489
+
490
+ return (
491
+ cardStyleInterpolator === forModalPresentationIOS ||
492
+ cardStyleInterpolator?.name === 'forModalPresentationIOS'
493
+ );
494
+ })
495
+ : true,
496
+ } = options;
497
+
498
+ if (detachPreviousScreen === false) {
499
+ activeScreensLimit++;
500
+ } else {
501
+ // Check at least last 2 screens before stopping
502
+ // This will make sure that screen isn't detached when another screen is animating on top of the transparent one
503
+ // e.g. opaque -> transparent -> opaque
504
+ if (i <= props.routes.length - 2) {
505
+ break;
506
+ }
507
+ }
508
+ }
509
+
510
+ activeStates = props.routes.map((_, index, self) => {
511
+ // The activity state represents state of the screen:
512
+ // 0 - inactive, the screen is detached
513
+ // 1 - transitioning or below the top screen, the screen is mounted but interaction is disabled
514
+ // 2 - on top of the stack, the screen is mounted and interaction is enabled
515
+ let activityState:
516
+ | Animated.AnimatedInterpolation<0 | 1 | 2>
517
+ | 0
518
+ | 1
519
+ | 2;
520
+
521
+ const lastActiveState = state.activeStates[index];
522
+ const activeAfterTransition = index >= self.length - activeScreensLimit;
523
+
524
+ if (lastActiveState === STATE_INACTIVE && !activeAfterTransition) {
525
+ // screen was inactive before and it will still be inactive after the transition
526
+ activityState = STATE_INACTIVE;
527
+ } else {
528
+ const sceneForActivity = scenes[self.length - 1];
529
+ const outputValue =
530
+ index === self.length - 1
531
+ ? STATE_ON_TOP // the screen is on top after the transition
532
+ : activeAfterTransition
533
+ ? STATE_TRANSITIONING_OR_BELOW_TOP // the screen should stay active after the transition, it is not on top but is in activeLimit
534
+ : STATE_INACTIVE; // the screen should be active only during the transition, it is at the edge of activeLimit
535
+
536
+ activityState = sceneForActivity
537
+ ? sceneForActivity.progress.current.interpolate({
538
+ inputRange: [0, 1 - EPSILON, 1],
539
+ outputRange: [1, 1, outputValue],
540
+ extrapolate: 'clamp',
541
+ })
542
+ : STATE_TRANSITIONING_OR_BELOW_TOP;
543
+ }
544
+
545
+ return activityState;
546
+ });
547
+ }
365
548
 
366
549
  return {
367
550
  routes: props.routes,
368
551
  scenes,
369
552
  gestures,
370
553
  descriptors: props.descriptors,
554
+ activeStates,
371
555
  headerHeights: getHeaderHeights(
372
556
  scenes,
373
557
  props.insets,
@@ -388,6 +572,7 @@ export default class CardStack extends React.Component<Props, State> {
388
572
  gestures: {},
389
573
  layout: SafeAreaProviderCompat.initialMetrics.frame,
390
574
  descriptors: this.props.descriptors,
575
+ activeStates: [],
391
576
  // Used when card's header is null and mode is float to make transition
392
577
  // between screens with headers and those without headers smooth.
393
578
  // This is not a great heuristic here. We don't know synchronously
@@ -472,11 +657,11 @@ export default class CardStack extends React.Component<Props, State> {
472
657
  insets,
473
658
  state,
474
659
  routes,
660
+ openingRouteKeys,
475
661
  closingRouteKeys,
476
662
  onOpenRoute,
477
663
  onCloseRoute,
478
664
  renderHeader,
479
- renderScene,
480
665
  isParentHeaderShown,
481
666
  isParentModal,
482
667
  onTransitionStart,
@@ -487,12 +672,12 @@ export default class CardStack extends React.Component<Props, State> {
487
672
  detachInactiveScreens = Platform.OS === 'web' ||
488
673
  Platform.OS === 'android' ||
489
674
  Platform.OS === 'ios' ||
490
- //amznmod_react add kepler platform
491
- //@ts-ignore
675
+ // @ts-ignore - accept kepler as a platform
492
676
  Platform.OS === 'kepler',
493
677
  } = this.props;
494
678
 
495
- const { scenes, layout, gestures, headerHeights } = this.state;
679
+ const { scenes, layout, gestures, activeStates, headerHeights } =
680
+ this.state;
496
681
 
497
682
  const focusedRoute = state.routes[state.index];
498
683
  const focusedHeaderHeight = headerHeights[focusedRoute.key];
@@ -512,41 +697,8 @@ export default class CardStack extends React.Component<Props, State> {
512
697
  return false;
513
698
  });
514
699
 
515
- let activeScreensLimit = 1;
516
-
517
- for (let i = scenes.length - 1; i >= 0; i--) {
518
- const { options } = scenes[i].descriptor;
519
- const {
520
- // By default, we don't want to detach the previous screen of the active one for modals
521
- detachPreviousScreen = options.presentation === 'transparentModal'
522
- ? false
523
- : getIsModalPresentation(options.cardStyleInterpolator)
524
- ? i !==
525
- findLastIndex(scenes, (scene) => {
526
- const { cardStyleInterpolator } = scene.descriptor.options;
527
-
528
- return (
529
- cardStyleInterpolator === forModalPresentationIOS ||
530
- cardStyleInterpolator?.name === 'forModalPresentationIOS'
531
- );
532
- })
533
- : true,
534
- } = options;
535
-
536
- if (detachPreviousScreen === false) {
537
- activeScreensLimit++;
538
- } else {
539
- // Check at least last 2 screens before stopping
540
- // This will make sure that screen isn't detached when another screen is animating on top of the transparent one
541
- // For example, (Opaque -> Transparent -> Opaque)
542
- if (i <= scenes.length - 2) {
543
- break;
544
- }
545
- }
546
- }
547
-
548
- const floatingHeader = (
549
- <React.Fragment key="header">
700
+ return (
701
+ <View style={styles.container}>
550
702
  {renderHeader({
551
703
  mode: 'float',
552
704
  layout,
@@ -563,44 +715,34 @@ export default class CardStack extends React.Component<Props, State> {
563
715
  ],
564
716
  ],
565
717
  })}
566
- </React.Fragment>
567
- );
568
-
569
- return (
570
- <Background>
571
- {isFloatHeaderAbsolute ? null : floatingHeader}
572
718
  <MaybeScreenContainer
573
719
  enabled={detachInactiveScreens}
574
720
  style={styles.container}
575
721
  onLayout={this.handleLayout}
576
722
  >
577
- {routes.map((route, index, self) => {
723
+ {[...routes, ...state.preloadedRoutes].map((route, index) => {
578
724
  const focused = focusedRoute.key === route.key;
579
725
  const gesture = gestures[route.key];
580
726
  const scene = scenes[index];
581
-
582
- // For the screens that shouldn't be active, the value is 0
583
- // For those that should be active, but are not the top screen, the value is 1
584
- // For those on top of the stack and with interaction enabled, the value is 2
585
- // For the old implementation, it stays the same it was
586
- let isScreenActive:
587
- | 2
588
- | 1
589
- | 0 = 1;
590
-
591
- if (index < self.length - activeScreensLimit - 1) {
592
- // screen should be inactive because it is too deep in the stack
593
- isScreenActive = STATE_INACTIVE;
594
- } else {
595
- isScreenActive = STATE_TRANSITIONING_OR_BELOW_TOP;
727
+ // It is possible that for a short period the route appears in both arrays.
728
+ // Particularly, if the screen is removed with `retain`, then it needs a moment to execute the animation.
729
+ // However, due to the router action, it immediately populates the `preloadedRoutes` array.
730
+ // Practically, the logic below takes care that it is rendered only once.
731
+ const isPreloaded =
732
+ state.preloadedRoutes.includes(route) && !routes.includes(route);
733
+ if (
734
+ state.preloadedRoutes.includes(route) &&
735
+ routes.includes(route) &&
736
+ index >= routes.length
737
+ ) {
738
+ return null;
596
739
  }
597
740
 
598
741
  const {
599
742
  headerShown = true,
600
743
  headerTransparent,
601
- headerStyle,
602
- headerTintColor,
603
744
  freezeOnBlur,
745
+ autoHideHomeIndicator,
604
746
  } = scene.descriptor.options;
605
747
 
606
748
  const safeAreaInsetTop = insets.top;
@@ -611,26 +753,6 @@ export default class CardStack extends React.Component<Props, State> {
611
753
  const headerHeight =
612
754
  headerShown !== false ? headerHeights[route.key] : 0;
613
755
 
614
- let headerDarkContent: boolean | undefined;
615
-
616
- if (headerShown) {
617
- if (typeof headerTintColor === 'string') {
618
- headerDarkContent = Color(headerTintColor).isDark();
619
- } else {
620
- const flattenedHeaderStyle = StyleSheet.flatten(headerStyle);
621
-
622
- if (
623
- flattenedHeaderStyle &&
624
- 'backgroundColor' in flattenedHeaderStyle &&
625
- typeof flattenedHeaderStyle.backgroundColor === 'string'
626
- ) {
627
- headerDarkContent = !Color(
628
- flattenedHeaderStyle.backgroundColor
629
- ).isDark();
630
- }
631
- }
632
- }
633
-
634
756
  // Start from current card and count backwards the number of cards with same interpolation
635
757
  const interpolationIndex = getInterpolationIndex(scenes, index);
636
758
  const isModal = getIsModal(
@@ -647,21 +769,28 @@ export default class CardStack extends React.Component<Props, State> {
647
769
  scenes[index + 1]?.descriptor.options.detachPreviousScreen !==
648
770
  false;
649
771
 
772
+ const activityState = isPreloaded
773
+ ? STATE_INACTIVE
774
+ : activeStates[index];
775
+
650
776
  return (
651
777
  <MaybeScreen
652
778
  key={route.key}
653
- style={StyleSheet.absoluteFill}
779
+ style={[StyleSheet.absoluteFill]}
654
780
  enabled={detachInactiveScreens}
655
- active={isScreenActive}
781
+ active={activityState}
656
782
  freezeOnBlur={freezeOnBlur}
783
+ shouldFreeze={activityState === STATE_INACTIVE && !isPreloaded}
784
+ homeIndicatorHidden={autoHideHomeIndicator}
657
785
  pointerEvents="box-none"
658
786
  >
659
787
  <CardContainer
660
788
  index={index}
661
789
  interpolationIndex={interpolationIndex}
662
790
  modal={isModal}
663
- active={index === self.length - 1}
791
+ active={index === routes.length - 1}
664
792
  focused={focused}
793
+ opening={openingRouteKeys.includes(route.key)}
665
794
  closing={closingRouteKeys.includes(route.key)}
666
795
  layout={layout}
667
796
  gesture={gesture}
@@ -678,25 +807,23 @@ export default class CardStack extends React.Component<Props, State> {
678
807
  onHeaderHeightChange={this.handleHeaderLayout}
679
808
  getPreviousScene={this.getPreviousScene}
680
809
  getFocusedRoute={this.getFocusedRoute}
681
- headerDarkContent={headerDarkContent}
682
810
  hasAbsoluteFloatHeader={
683
811
  isFloatHeaderAbsolute && !headerTransparent
684
812
  }
685
813
  renderHeader={renderHeader}
686
- renderScene={renderScene}
687
814
  onOpenRoute={onOpenRoute}
688
815
  onCloseRoute={onCloseRoute}
689
816
  onTransitionStart={onTransitionStart}
690
817
  onTransitionEnd={onTransitionEnd}
691
818
  isNextScreenTransparent={isNextScreenTransparent}
692
819
  detachCurrentScreen={detachCurrentScreen}
820
+ preloaded={isPreloaded}
693
821
  />
694
822
  </MaybeScreen>
695
823
  );
696
824
  })}
697
825
  </MaybeScreenContainer>
698
- {isFloatHeaderAbsolute ? floatingHeader : null}
699
- </Background>
826
+ </View>
700
827
  );
701
828
  }
702
829
  }
@@ -708,8 +835,8 @@ const styles = StyleSheet.create({
708
835
  absolute: {
709
836
  position: 'absolute',
710
837
  top: 0,
711
- left: 0,
712
- right: 0,
838
+ start: 0,
839
+ end: 0,
713
840
  },
714
841
  floating: {
715
842
  zIndex: 1,