@amazon-devices/react-navigation__stack 2.0.1758683737

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 (242) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +5 -0
  3. package/SystemBundles/ed2637c0b74cd42ce066fca701acc5cb0850978c5296fae5bd715d5e4c67b128.bundle +29321 -0
  4. package/SystemBundles/ed2637c0b74cd42ce066fca701acc5cb0850978c5296fae5bd715d5e4c67b128.map +1 -0
  5. package/SystemModules/amzn__react-navigation__stack-2.modules.txt +95 -0
  6. package/SystemModules/amzn__react-navigation__stack-2.private.modules.txt +258 -0
  7. package/SystemModules/keplerscript-system-bundle-config.json +7 -0
  8. package/THIRD_PARTY_NOTICES.txt +24 -0
  9. package/kepler-compatibility.json +8 -0
  10. package/kepler-transformed-package-info.json +3 -0
  11. package/lib/commonjs/TransitionConfigs/CardStyleInterpolators.js +353 -0
  12. package/lib/commonjs/TransitionConfigs/CardStyleInterpolators.js.map +1 -0
  13. package/lib/commonjs/TransitionConfigs/HeaderStyleInterpolators.js +259 -0
  14. package/lib/commonjs/TransitionConfigs/HeaderStyleInterpolators.js.map +1 -0
  15. package/lib/commonjs/TransitionConfigs/TransitionPresets.js +134 -0
  16. package/lib/commonjs/TransitionConfigs/TransitionPresets.js.map +1 -0
  17. package/lib/commonjs/TransitionConfigs/TransitionSpecs.js +100 -0
  18. package/lib/commonjs/TransitionConfigs/TransitionSpecs.js.map +1 -0
  19. package/lib/commonjs/index.js +69 -0
  20. package/lib/commonjs/index.js.map +1 -0
  21. package/lib/commonjs/navigators/createStackNavigator.js +82 -0
  22. package/lib/commonjs/navigators/createStackNavigator.js.map +1 -0
  23. package/lib/commonjs/types.js +6 -0
  24. package/lib/commonjs/types.js.map +1 -0
  25. package/lib/commonjs/utils/CardAnimationContext.js +11 -0
  26. package/lib/commonjs/utils/CardAnimationContext.js.map +1 -0
  27. package/lib/commonjs/utils/GestureHandlerRefContext.js +11 -0
  28. package/lib/commonjs/utils/GestureHandlerRefContext.js.map +1 -0
  29. package/lib/commonjs/utils/ModalPresentationContext.js +12 -0
  30. package/lib/commonjs/utils/ModalPresentationContext.js.map +1 -0
  31. package/lib/commonjs/utils/conditional.js +32 -0
  32. package/lib/commonjs/utils/conditional.js.map +1 -0
  33. package/lib/commonjs/utils/debounce.js +19 -0
  34. package/lib/commonjs/utils/debounce.js.map +1 -0
  35. package/lib/commonjs/utils/findLastIndex.js +15 -0
  36. package/lib/commonjs/utils/findLastIndex.js.map +1 -0
  37. package/lib/commonjs/utils/getDistanceForDirection.js +20 -0
  38. package/lib/commonjs/utils/getDistanceForDirection.js.map +1 -0
  39. package/lib/commonjs/utils/getInvertedMultiplier.js +20 -0
  40. package/lib/commonjs/utils/getInvertedMultiplier.js.map +1 -0
  41. package/lib/commonjs/utils/memoize.js +33 -0
  42. package/lib/commonjs/utils/memoize.js.map +1 -0
  43. package/lib/commonjs/utils/useCardAnimation.js +19 -0
  44. package/lib/commonjs/utils/useCardAnimation.js.map +1 -0
  45. package/lib/commonjs/utils/useGestureHandlerRef.js +19 -0
  46. package/lib/commonjs/utils/useGestureHandlerRef.js.map +1 -0
  47. package/lib/commonjs/utils/useKeyboardManager.js +96 -0
  48. package/lib/commonjs/utils/useKeyboardManager.js.map +1 -0
  49. package/lib/commonjs/views/GestureHandler.android.js +17 -0
  50. package/lib/commonjs/views/GestureHandler.android.js.map +1 -0
  51. package/lib/commonjs/views/GestureHandler.ios.js +17 -0
  52. package/lib/commonjs/views/GestureHandler.ios.js.map +1 -0
  53. package/lib/commonjs/views/GestureHandler.js +24 -0
  54. package/lib/commonjs/views/GestureHandler.js.map +1 -0
  55. package/lib/commonjs/views/GestureHandlerNative.js +34 -0
  56. package/lib/commonjs/views/GestureHandlerNative.js.map +1 -0
  57. package/lib/commonjs/views/Header/Header.js +61 -0
  58. package/lib/commonjs/views/Header/Header.js.map +1 -0
  59. package/lib/commonjs/views/Header/HeaderContainer.js +127 -0
  60. package/lib/commonjs/views/Header/HeaderContainer.js.map +1 -0
  61. package/lib/commonjs/views/Header/HeaderSegment.js +139 -0
  62. package/lib/commonjs/views/Header/HeaderSegment.js.map +1 -0
  63. package/lib/commonjs/views/ModalStatusBarManager.js +42 -0
  64. package/lib/commonjs/views/ModalStatusBarManager.js.map +1 -0
  65. package/lib/commonjs/views/Screens.js +44 -0
  66. package/lib/commonjs/views/Screens.js.map +1 -0
  67. package/lib/commonjs/views/Stack/Card.js +469 -0
  68. package/lib/commonjs/views/Stack/Card.js.map +1 -0
  69. package/lib/commonjs/views/Stack/CardContainer.js +259 -0
  70. package/lib/commonjs/views/Stack/CardContainer.js.map +1 -0
  71. package/lib/commonjs/views/Stack/CardSheet.js +54 -0
  72. package/lib/commonjs/views/Stack/CardSheet.js.map +1 -0
  73. package/lib/commonjs/views/Stack/CardStack.js +442 -0
  74. package/lib/commonjs/views/Stack/CardStack.js.map +1 -0
  75. package/lib/commonjs/views/Stack/StackView.js +333 -0
  76. package/lib/commonjs/views/Stack/StackView.js.map +1 -0
  77. package/lib/module/TransitionConfigs/CardStyleInterpolators.js +338 -0
  78. package/lib/module/TransitionConfigs/CardStyleInterpolators.js.map +1 -0
  79. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js +248 -0
  80. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js.map +1 -0
  81. package/lib/module/TransitionConfigs/TransitionPresets.js +128 -0
  82. package/lib/module/TransitionConfigs/TransitionPresets.js.map +1 -0
  83. package/lib/module/TransitionConfigs/TransitionSpecs.js +94 -0
  84. package/lib/module/TransitionConfigs/TransitionSpecs.js.map +1 -0
  85. package/lib/module/index.js +33 -0
  86. package/lib/module/index.js.map +1 -0
  87. package/lib/module/navigators/createStackNavigator.js +73 -0
  88. package/lib/module/navigators/createStackNavigator.js.map +1 -0
  89. package/lib/module/types.js +2 -0
  90. package/lib/module/types.js.map +1 -0
  91. package/lib/module/utils/CardAnimationContext.js +3 -0
  92. package/lib/module/utils/CardAnimationContext.js.map +1 -0
  93. package/lib/module/utils/GestureHandlerRefContext.js +3 -0
  94. package/lib/module/utils/GestureHandlerRefContext.js.map +1 -0
  95. package/lib/module/utils/ModalPresentationContext.js +4 -0
  96. package/lib/module/utils/ModalPresentationContext.js.map +1 -0
  97. package/lib/module/utils/conditional.js +26 -0
  98. package/lib/module/utils/conditional.js.map +1 -0
  99. package/lib/module/utils/debounce.js +13 -0
  100. package/lib/module/utils/debounce.js.map +1 -0
  101. package/lib/module/utils/findLastIndex.js +9 -0
  102. package/lib/module/utils/findLastIndex.js.map +1 -0
  103. package/lib/module/utils/getDistanceForDirection.js +13 -0
  104. package/lib/module/utils/getDistanceForDirection.js.map +1 -0
  105. package/lib/module/utils/getInvertedMultiplier.js +14 -0
  106. package/lib/module/utils/getInvertedMultiplier.js.map +1 -0
  107. package/lib/module/utils/memoize.js +27 -0
  108. package/lib/module/utils/memoize.js.map +1 -0
  109. package/lib/module/utils/useCardAnimation.js +10 -0
  110. package/lib/module/utils/useCardAnimation.js.map +1 -0
  111. package/lib/module/utils/useGestureHandlerRef.js +10 -0
  112. package/lib/module/utils/useGestureHandlerRef.js.map +1 -0
  113. package/lib/module/utils/useKeyboardManager.js +88 -0
  114. package/lib/module/utils/useKeyboardManager.js.map +1 -0
  115. package/lib/module/views/GestureHandler.android.js +2 -0
  116. package/lib/module/views/GestureHandler.android.js.map +1 -0
  117. package/lib/module/views/GestureHandler.ios.js +2 -0
  118. package/lib/module/views/GestureHandler.ios.js.map +1 -0
  119. package/lib/module/views/GestureHandler.js +16 -0
  120. package/lib/module/views/GestureHandler.js.map +1 -0
  121. package/lib/module/views/GestureHandlerNative.js +14 -0
  122. package/lib/module/views/GestureHandlerNative.js.map +1 -0
  123. package/lib/module/views/Header/Header.js +52 -0
  124. package/lib/module/views/Header/Header.js.map +1 -0
  125. package/lib/module/views/Header/HeaderContainer.js +118 -0
  126. package/lib/module/views/Header/HeaderContainer.js.map +1 -0
  127. package/lib/module/views/Header/HeaderSegment.js +130 -0
  128. package/lib/module/views/Header/HeaderSegment.js.map +1 -0
  129. package/lib/module/views/ModalStatusBarManager.js +34 -0
  130. package/lib/module/views/ModalStatusBarManager.js.map +1 -0
  131. package/lib/module/views/Screens.js +34 -0
  132. package/lib/module/views/Screens.js.map +1 -0
  133. package/lib/module/views/Stack/Card.js +458 -0
  134. package/lib/module/views/Stack/Card.js.map +1 -0
  135. package/lib/module/views/Stack/CardContainer.js +250 -0
  136. package/lib/module/views/Stack/CardContainer.js.map +1 -0
  137. package/lib/module/views/Stack/CardSheet.js +46 -0
  138. package/lib/module/views/Stack/CardSheet.js.map +1 -0
  139. package/lib/module/views/Stack/CardStack.js +432 -0
  140. package/lib/module/views/Stack/CardStack.js.map +1 -0
  141. package/lib/module/views/Stack/StackView.js +323 -0
  142. package/lib/module/views/Stack/StackView.js.map +1 -0
  143. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +35 -0
  144. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -0
  145. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +23 -0
  146. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -0
  147. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +42 -0
  148. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -0
  149. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +36 -0
  150. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -0
  151. package/lib/typescript/src/index.d.ts +29 -0
  152. package/lib/typescript/src/index.d.ts.map +1 -0
  153. package/lib/typescript/src/navigators/createStackNavigator.d.ts +8 -0
  154. package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -0
  155. package/lib/typescript/src/types.d.ts +481 -0
  156. package/lib/typescript/src/types.d.ts.map +1 -0
  157. package/lib/typescript/src/utils/CardAnimationContext.d.ts +5 -0
  158. package/lib/typescript/src/utils/CardAnimationContext.d.ts.map +1 -0
  159. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts +4 -0
  160. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts.map +1 -0
  161. package/lib/typescript/src/utils/ModalPresentationContext.d.ts +4 -0
  162. package/lib/typescript/src/utils/ModalPresentationContext.d.ts.map +1 -0
  163. package/lib/typescript/src/utils/conditional.d.ts +10 -0
  164. package/lib/typescript/src/utils/conditional.d.ts.map +1 -0
  165. package/lib/typescript/src/utils/debounce.d.ts +2 -0
  166. package/lib/typescript/src/utils/debounce.d.ts.map +1 -0
  167. package/lib/typescript/src/utils/findLastIndex.d.ts +2 -0
  168. package/lib/typescript/src/utils/findLastIndex.d.ts.map +1 -0
  169. package/lib/typescript/src/utils/getDistanceForDirection.d.ts +3 -0
  170. package/lib/typescript/src/utils/getDistanceForDirection.d.ts.map +1 -0
  171. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts +3 -0
  172. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts.map +1 -0
  173. package/lib/typescript/src/utils/memoize.d.ts +2 -0
  174. package/lib/typescript/src/utils/memoize.d.ts.map +1 -0
  175. package/lib/typescript/src/utils/useCardAnimation.d.ts +2 -0
  176. package/lib/typescript/src/utils/useCardAnimation.d.ts.map +1 -0
  177. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts +3 -0
  178. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts.map +1 -0
  179. package/lib/typescript/src/utils/useKeyboardManager.d.ts +6 -0
  180. package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -0
  181. package/lib/typescript/src/views/GestureHandler.android.d.ts +2 -0
  182. package/lib/typescript/src/views/GestureHandler.android.d.ts.map +1 -0
  183. package/lib/typescript/src/views/GestureHandler.d.ts +14 -0
  184. package/lib/typescript/src/views/GestureHandler.d.ts.map +1 -0
  185. package/lib/typescript/src/views/GestureHandler.ios.d.ts +2 -0
  186. package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +1 -0
  187. package/lib/typescript/src/views/GestureHandlerNative.d.ts +6 -0
  188. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -0
  189. package/lib/typescript/src/views/Header/Header.d.ts +5 -0
  190. package/lib/typescript/src/views/Header/Header.d.ts.map +1 -0
  191. package/lib/typescript/src/views/Header/HeaderContainer.d.ts +20 -0
  192. package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -0
  193. package/lib/typescript/src/views/Header/HeaderSegment.d.ts +14 -0
  194. package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -0
  195. package/lib/typescript/src/views/ModalStatusBarManager.d.ts +12 -0
  196. package/lib/typescript/src/views/ModalStatusBarManager.d.ts.map +1 -0
  197. package/lib/typescript/src/views/Screens.d.ts +13 -0
  198. package/lib/typescript/src/views/Screens.d.ts.map +1 -0
  199. package/lib/typescript/src/views/Stack/Card.d.ts +76 -0
  200. package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -0
  201. package/lib/typescript/src/views/Stack/CardContainer.d.ts +63 -0
  202. package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -0
  203. package/lib/typescript/src/views/Stack/CardSheet.d.ts +15 -0
  204. package/lib/typescript/src/views/Stack/CardSheet.d.ts.map +1 -0
  205. package/lib/typescript/src/views/Stack/CardStack.d.ts +67 -0
  206. package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -0
  207. package/lib/typescript/src/views/Stack/StackView.d.ts +122 -0
  208. package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -0
  209. package/package.json +1 -0
  210. package/src/TransitionConfigs/CardStyleInterpolators.tsx +394 -0
  211. package/src/TransitionConfigs/HeaderStyleInterpolators.tsx +268 -0
  212. package/src/TransitionConfigs/TransitionPresets.tsx +152 -0
  213. package/src/TransitionConfigs/TransitionSpecs.tsx +96 -0
  214. package/src/index.tsx +51 -0
  215. package/src/navigators/createStackNavigator.tsx +136 -0
  216. package/src/types.tsx +547 -0
  217. package/src/utils/CardAnimationContext.tsx +7 -0
  218. package/src/utils/GestureHandlerRefContext.tsx +5 -0
  219. package/src/utils/ModalPresentationContext.tsx +5 -0
  220. package/src/utils/conditional.tsx +33 -0
  221. package/src/utils/debounce.tsx +17 -0
  222. package/src/utils/findLastIndex.tsx +12 -0
  223. package/src/utils/getDistanceForDirection.tsx +18 -0
  224. package/src/utils/getInvertedMultiplier.tsx +18 -0
  225. package/src/utils/memoize.tsx +33 -0
  226. package/src/utils/useCardAnimation.tsx +15 -0
  227. package/src/utils/useGestureHandlerRef.tsx +15 -0
  228. package/src/utils/useKeyboardManager.tsx +105 -0
  229. package/src/views/GestureHandler.android.tsx +1 -0
  230. package/src/views/GestureHandler.ios.tsx +1 -0
  231. package/src/views/GestureHandler.tsx +23 -0
  232. package/src/views/GestureHandlerNative.tsx +23 -0
  233. package/src/views/Header/Header.tsx +72 -0
  234. package/src/views/Header/HeaderContainer.tsx +186 -0
  235. package/src/views/Header/HeaderSegment.tsx +205 -0
  236. package/src/views/ModalStatusBarManager.tsx +50 -0
  237. package/src/views/Screens.tsx +43 -0
  238. package/src/views/Stack/Card.tsx +628 -0
  239. package/src/views/Stack/CardContainer.tsx +320 -0
  240. package/src/views/Stack/CardSheet.tsx +61 -0
  241. package/src/views/Stack/CardStack.tsx +717 -0
  242. package/src/views/Stack/StackView.tsx +474 -0
@@ -0,0 +1,717 @@
1
+ import {
2
+ Background,
3
+ getDefaultHeaderHeight,
4
+ SafeAreaProviderCompat,
5
+ } from '@amazon-devices/react-navigation__elements';
6
+ import type {
7
+ ParamListBase,
8
+ Route,
9
+ StackNavigationState,
10
+ } from '@amazon-devices/react-navigation__native';
11
+ import Color from 'color';
12
+ import * as React from 'react';
13
+ import {
14
+ Animated,
15
+ LayoutChangeEvent,
16
+ Platform,
17
+ StyleSheet,
18
+ } from 'react-native';
19
+ import type { EdgeInsets } from '@amazon-devices/react-native-safe-area-context';
20
+
21
+ import {
22
+ forModalPresentationIOS,
23
+ forNoAnimation as forNoAnimationCard,
24
+ } from '../../TransitionConfigs/CardStyleInterpolators';
25
+ import {
26
+ DefaultTransition,
27
+ ModalFadeTransition,
28
+ ModalTransition,
29
+ } from '../../TransitionConfigs/TransitionPresets';
30
+ import type {
31
+ Layout,
32
+ Scene,
33
+ StackDescriptor,
34
+ StackDescriptorMap,
35
+ StackHeaderMode,
36
+ StackNavigationOptions,
37
+ } from '../../types';
38
+ import findLastIndex from '../../utils/findLastIndex';
39
+ import getDistanceForDirection from '../../utils/getDistanceForDirection';
40
+ import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
41
+ import { MaybeScreen, MaybeScreenContainer } from '../Screens';
42
+ import { getIsModalPresentation } from './Card';
43
+ import CardContainer from './CardContainer';
44
+
45
+ type GestureValues = {
46
+ [key: string]: Animated.Value;
47
+ };
48
+
49
+ type Props = {
50
+ insets: EdgeInsets;
51
+ state: StackNavigationState<ParamListBase>;
52
+ descriptors: StackDescriptorMap;
53
+ routes: Route<string>[];
54
+ openingRouteKeys: string[];
55
+ closingRouteKeys: string[];
56
+ onOpenRoute: (props: { route: Route<string> }) => void;
57
+ onCloseRoute: (props: { route: Route<string> }) => void;
58
+ getPreviousRoute: (props: {
59
+ route: Route<string>;
60
+ }) => Route<string> | undefined;
61
+ renderHeader: (props: HeaderContainerProps) => React.ReactNode;
62
+ renderScene: (props: { route: Route<string> }) => React.ReactNode;
63
+ isParentHeaderShown: boolean;
64
+ isParentModal: boolean;
65
+ onTransitionStart: (
66
+ props: { route: Route<string> },
67
+ closing: boolean
68
+ ) => void;
69
+ onTransitionEnd: (props: { route: Route<string> }, closing: boolean) => void;
70
+ onGestureStart: (props: { route: Route<string> }) => void;
71
+ onGestureEnd: (props: { route: Route<string> }) => void;
72
+ onGestureCancel: (props: { route: Route<string> }) => void;
73
+ detachInactiveScreens?: boolean;
74
+ };
75
+
76
+ type State = {
77
+ routes: Route<string>[];
78
+ descriptors: StackDescriptorMap;
79
+ scenes: Scene[];
80
+ gestures: GestureValues;
81
+ layout: Layout;
82
+ headerHeights: Record<string, number>;
83
+ };
84
+
85
+ const STATE_INACTIVE = 0;
86
+ const STATE_TRANSITIONING_OR_BELOW_TOP = 1;
87
+
88
+ const FALLBACK_DESCRIPTOR = Object.freeze({ options: {} });
89
+
90
+ const getInterpolationIndex = (scenes: Scene[], index: number) => {
91
+ const { cardStyleInterpolator } = scenes[index].descriptor.options;
92
+
93
+ // Start from current card and count backwards the number of cards with same interpolation
94
+ let interpolationIndex = 0;
95
+
96
+ for (let i = index - 1; i >= 0; i--) {
97
+ const cardStyleInterpolatorCurrent =
98
+ scenes[i]?.descriptor.options.cardStyleInterpolator;
99
+
100
+ if (cardStyleInterpolatorCurrent !== cardStyleInterpolator) {
101
+ break;
102
+ }
103
+
104
+ interpolationIndex++;
105
+ }
106
+
107
+ return interpolationIndex;
108
+ };
109
+
110
+ const getIsModal = (
111
+ scene: Scene,
112
+ interpolationIndex: number,
113
+ isParentModal: boolean
114
+ ) => {
115
+ if (isParentModal) {
116
+ return true;
117
+ }
118
+
119
+ const { cardStyleInterpolator } = scene.descriptor.options;
120
+ const isModalPresentation = getIsModalPresentation(cardStyleInterpolator);
121
+ const isModal = isModalPresentation && interpolationIndex !== 0;
122
+
123
+ return isModal;
124
+ };
125
+
126
+ const getHeaderHeights = (
127
+ scenes: Scene[],
128
+ insets: EdgeInsets,
129
+ isParentHeaderShown: boolean,
130
+ isParentModal: boolean,
131
+ layout: Layout,
132
+ previous: Record<string, number>
133
+ ) => {
134
+ return scenes.reduce<Record<string, number>>((acc, curr, index) => {
135
+ const {
136
+ headerStatusBarHeight = isParentHeaderShown ? 0 : insets.top,
137
+ headerStyle,
138
+ } = curr.descriptor.options;
139
+
140
+ const style = StyleSheet.flatten(headerStyle || {});
141
+
142
+ const height =
143
+ 'height' in style && typeof style.height === 'number'
144
+ ? style.height
145
+ : previous[curr.route.key];
146
+
147
+ const interpolationIndex = getInterpolationIndex(scenes, index);
148
+ const isModal = getIsModal(curr, interpolationIndex, isParentModal);
149
+
150
+ acc[curr.route.key] =
151
+ typeof height === 'number'
152
+ ? height
153
+ : getDefaultHeaderHeight(layout, isModal, headerStatusBarHeight);
154
+
155
+ return acc;
156
+ }, {});
157
+ };
158
+
159
+ const getDistanceFromOptions = (
160
+ layout: Layout,
161
+ descriptor?: StackDescriptor
162
+ ) => {
163
+ const {
164
+ presentation,
165
+ gestureDirection = presentation === 'modal'
166
+ ? ModalTransition.gestureDirection
167
+ : DefaultTransition.gestureDirection,
168
+ } = (descriptor?.options || {}) as StackNavigationOptions;
169
+
170
+ return getDistanceForDirection(layout, gestureDirection);
171
+ };
172
+
173
+ const getProgressFromGesture = (
174
+ gesture: Animated.Value,
175
+ layout: Layout,
176
+ descriptor?: StackDescriptor
177
+ ) => {
178
+ const distance = getDistanceFromOptions(
179
+ {
180
+ // Make sure that we have a non-zero distance, otherwise there will be incorrect progress
181
+ // This causes blank screen on web if it was previously inside container with display: none
182
+ width: Math.max(1, layout.width),
183
+ height: Math.max(1, layout.height),
184
+ },
185
+ descriptor
186
+ );
187
+
188
+ if (distance > 0) {
189
+ return gesture.interpolate({
190
+ inputRange: [0, distance],
191
+ outputRange: [1, 0],
192
+ });
193
+ }
194
+
195
+ return gesture.interpolate({
196
+ inputRange: [distance, 0],
197
+ outputRange: [0, 1],
198
+ });
199
+ };
200
+
201
+ export default class CardStack extends React.Component<Props, State> {
202
+ static getDerivedStateFromProps(
203
+ props: Props,
204
+ state: State
205
+ ): Partial<State> | null {
206
+ if (
207
+ props.routes === state.routes &&
208
+ props.descriptors === state.descriptors
209
+ ) {
210
+ return null;
211
+ }
212
+
213
+ const gestures = props.routes.reduce<GestureValues>((acc, curr) => {
214
+ const descriptor = props.descriptors[curr.key];
215
+ const { animationEnabled } = descriptor?.options || {};
216
+
217
+ acc[curr.key] =
218
+ state.gestures[curr.key] ||
219
+ new Animated.Value(
220
+ props.openingRouteKeys.includes(curr.key) &&
221
+ animationEnabled !== false
222
+ ? getDistanceFromOptions(state.layout, descriptor)
223
+ : 0
224
+ );
225
+
226
+ return acc;
227
+ }, {});
228
+
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];
234
+
235
+ const currentGesture = gestures[route.key];
236
+ const previousGesture = previousRoute
237
+ ? gestures[previousRoute.key]
238
+ : undefined;
239
+ const nextGesture = nextRoute ? gestures[nextRoute.key] : undefined;
240
+
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,
317
+ },
318
+ },
319
+ progress: {
320
+ current: getProgressFromGesture(
321
+ currentGesture,
322
+ state.layout,
323
+ descriptor
324
+ ),
325
+ next:
326
+ nextGesture &&
327
+ nextDescriptor?.options.presentation !== 'transparentModal'
328
+ ? getProgressFromGesture(
329
+ nextGesture,
330
+ state.layout,
331
+ nextDescriptor
332
+ )
333
+ : 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
+ };
352
+
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;
361
+ }
362
+
363
+ return scene;
364
+ });
365
+
366
+ return {
367
+ routes: props.routes,
368
+ scenes,
369
+ gestures,
370
+ descriptors: props.descriptors,
371
+ headerHeights: getHeaderHeights(
372
+ scenes,
373
+ props.insets,
374
+ props.isParentHeaderShown,
375
+ props.isParentModal,
376
+ state.layout,
377
+ state.headerHeights
378
+ ),
379
+ };
380
+ }
381
+
382
+ constructor(props: Props) {
383
+ super(props);
384
+
385
+ this.state = {
386
+ routes: [],
387
+ scenes: [],
388
+ gestures: {},
389
+ layout: SafeAreaProviderCompat.initialMetrics.frame,
390
+ descriptors: this.props.descriptors,
391
+ // Used when card's header is null and mode is float to make transition
392
+ // between screens with headers and those without headers smooth.
393
+ // This is not a great heuristic here. We don't know synchronously
394
+ // on mount what the header height is so we have just used the most
395
+ // common cases here.
396
+ headerHeights: {},
397
+ };
398
+ }
399
+
400
+ private handleLayout = (e: LayoutChangeEvent) => {
401
+ const { height, width } = e.nativeEvent.layout;
402
+
403
+ const layout = { width, height };
404
+
405
+ this.setState((state, props) => {
406
+ if (height === state.layout.height && width === state.layout.width) {
407
+ return null;
408
+ }
409
+
410
+ return {
411
+ layout,
412
+ headerHeights: getHeaderHeights(
413
+ state.scenes,
414
+ props.insets,
415
+ props.isParentHeaderShown,
416
+ props.isParentModal,
417
+ layout,
418
+ state.headerHeights
419
+ ),
420
+ };
421
+ });
422
+ };
423
+
424
+ private handleHeaderLayout = ({
425
+ route,
426
+ height,
427
+ }: {
428
+ route: Route<string>;
429
+ height: number;
430
+ }) => {
431
+ this.setState(({ headerHeights }) => {
432
+ const previousHeight = headerHeights[route.key];
433
+
434
+ if (previousHeight === height) {
435
+ return null;
436
+ }
437
+
438
+ return {
439
+ headerHeights: {
440
+ ...headerHeights,
441
+ [route.key]: height,
442
+ },
443
+ };
444
+ });
445
+ };
446
+
447
+ private getFocusedRoute = () => {
448
+ const { state } = this.props;
449
+
450
+ return state.routes[state.index];
451
+ };
452
+
453
+ private getPreviousScene = ({ route }: { route: Route<string> }) => {
454
+ const { getPreviousRoute } = this.props;
455
+ const { scenes } = this.state;
456
+
457
+ const previousRoute = getPreviousRoute({ route });
458
+
459
+ if (previousRoute) {
460
+ const previousScene = scenes.find(
461
+ (scene) => scene.descriptor.route.key === previousRoute.key
462
+ );
463
+
464
+ return previousScene;
465
+ }
466
+
467
+ return undefined;
468
+ };
469
+
470
+ render() {
471
+ const {
472
+ insets,
473
+ state,
474
+ routes,
475
+ closingRouteKeys,
476
+ onOpenRoute,
477
+ onCloseRoute,
478
+ renderHeader,
479
+ renderScene,
480
+ isParentHeaderShown,
481
+ isParentModal,
482
+ onTransitionStart,
483
+ onTransitionEnd,
484
+ onGestureStart,
485
+ onGestureEnd,
486
+ onGestureCancel,
487
+ detachInactiveScreens = Platform.OS === 'web' ||
488
+ Platform.OS === 'android' ||
489
+ Platform.OS === 'ios' ||
490
+ //amznmod_react add kepler platform
491
+ //@ts-ignore
492
+ Platform.OS === 'kepler',
493
+ } = this.props;
494
+
495
+ const { scenes, layout, gestures, headerHeights } = this.state;
496
+
497
+ const focusedRoute = state.routes[state.index];
498
+ const focusedHeaderHeight = headerHeights[focusedRoute.key];
499
+
500
+ const isFloatHeaderAbsolute = this.state.scenes.slice(-2).some((scene) => {
501
+ const options = scene.descriptor.options ?? {};
502
+ const { headerMode, headerTransparent, headerShown = true } = options;
503
+
504
+ if (
505
+ headerTransparent ||
506
+ headerShown === false ||
507
+ headerMode === 'screen'
508
+ ) {
509
+ return true;
510
+ }
511
+
512
+ return false;
513
+ });
514
+
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">
550
+ {renderHeader({
551
+ mode: 'float',
552
+ layout,
553
+ scenes,
554
+ getPreviousScene: this.getPreviousScene,
555
+ getFocusedRoute: this.getFocusedRoute,
556
+ onContentHeightChange: this.handleHeaderLayout,
557
+ style: [
558
+ styles.floating,
559
+ isFloatHeaderAbsolute && [
560
+ // Without this, the header buttons won't be touchable on Android when headerTransparent: true
561
+ { height: focusedHeaderHeight },
562
+ styles.absolute,
563
+ ],
564
+ ],
565
+ })}
566
+ </React.Fragment>
567
+ );
568
+
569
+ return (
570
+ <Background>
571
+ {isFloatHeaderAbsolute ? null : floatingHeader}
572
+ <MaybeScreenContainer
573
+ enabled={detachInactiveScreens}
574
+ style={styles.container}
575
+ onLayout={this.handleLayout}
576
+ >
577
+ {routes.map((route, index, self) => {
578
+ const focused = focusedRoute.key === route.key;
579
+ const gesture = gestures[route.key];
580
+ 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;
596
+ }
597
+
598
+ const {
599
+ headerShown = true,
600
+ headerTransparent,
601
+ headerStyle,
602
+ headerTintColor,
603
+ freezeOnBlur,
604
+ } = scene.descriptor.options;
605
+
606
+ const safeAreaInsetTop = insets.top;
607
+ const safeAreaInsetRight = insets.right;
608
+ const safeAreaInsetBottom = insets.bottom;
609
+ const safeAreaInsetLeft = insets.left;
610
+
611
+ const headerHeight =
612
+ headerShown !== false ? headerHeights[route.key] : 0;
613
+
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
+ // Start from current card and count backwards the number of cards with same interpolation
635
+ const interpolationIndex = getInterpolationIndex(scenes, index);
636
+ const isModal = getIsModal(
637
+ scene,
638
+ interpolationIndex,
639
+ isParentModal
640
+ );
641
+
642
+ const isNextScreenTransparent =
643
+ scenes[index + 1]?.descriptor.options.presentation ===
644
+ 'transparentModal';
645
+
646
+ const detachCurrentScreen =
647
+ scenes[index + 1]?.descriptor.options.detachPreviousScreen !==
648
+ false;
649
+
650
+ return (
651
+ <MaybeScreen
652
+ key={route.key}
653
+ style={StyleSheet.absoluteFill}
654
+ enabled={detachInactiveScreens}
655
+ active={isScreenActive}
656
+ freezeOnBlur={freezeOnBlur}
657
+ pointerEvents="box-none"
658
+ >
659
+ <CardContainer
660
+ index={index}
661
+ interpolationIndex={interpolationIndex}
662
+ modal={isModal}
663
+ active={index === self.length - 1}
664
+ focused={focused}
665
+ closing={closingRouteKeys.includes(route.key)}
666
+ layout={layout}
667
+ gesture={gesture}
668
+ scene={scene}
669
+ safeAreaInsetTop={safeAreaInsetTop}
670
+ safeAreaInsetRight={safeAreaInsetRight}
671
+ safeAreaInsetBottom={safeAreaInsetBottom}
672
+ safeAreaInsetLeft={safeAreaInsetLeft}
673
+ onGestureStart={onGestureStart}
674
+ onGestureCancel={onGestureCancel}
675
+ onGestureEnd={onGestureEnd}
676
+ headerHeight={headerHeight}
677
+ isParentHeaderShown={isParentHeaderShown}
678
+ onHeaderHeightChange={this.handleHeaderLayout}
679
+ getPreviousScene={this.getPreviousScene}
680
+ getFocusedRoute={this.getFocusedRoute}
681
+ headerDarkContent={headerDarkContent}
682
+ hasAbsoluteFloatHeader={
683
+ isFloatHeaderAbsolute && !headerTransparent
684
+ }
685
+ renderHeader={renderHeader}
686
+ renderScene={renderScene}
687
+ onOpenRoute={onOpenRoute}
688
+ onCloseRoute={onCloseRoute}
689
+ onTransitionStart={onTransitionStart}
690
+ onTransitionEnd={onTransitionEnd}
691
+ isNextScreenTransparent={isNextScreenTransparent}
692
+ detachCurrentScreen={detachCurrentScreen}
693
+ />
694
+ </MaybeScreen>
695
+ );
696
+ })}
697
+ </MaybeScreenContainer>
698
+ {isFloatHeaderAbsolute ? floatingHeader : null}
699
+ </Background>
700
+ );
701
+ }
702
+ }
703
+
704
+ const styles = StyleSheet.create({
705
+ container: {
706
+ flex: 1,
707
+ },
708
+ absolute: {
709
+ position: 'absolute',
710
+ top: 0,
711
+ left: 0,
712
+ right: 0,
713
+ },
714
+ floating: {
715
+ zIndex: 1,
716
+ },
717
+ });