react-native-screen-transitions 2.4.1 → 2.4.2-beta.1

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 (284) hide show
  1. package/lib/commonjs/__configs__/presets.js.map +1 -1
  2. package/lib/commonjs/components/controllers/screen-lifecycle.blank.js +59 -0
  3. package/lib/commonjs/components/controllers/screen-lifecycle.blank.js.map +1 -0
  4. package/lib/commonjs/components/root-transition-aware.js.map +1 -1
  5. package/lib/commonjs/constants.js.map +1 -1
  6. package/lib/commonjs/hooks/animation/use-screen-animation.js +9 -5
  7. package/lib/commonjs/hooks/animation/use-screen-animation.js.map +1 -1
  8. package/lib/commonjs/index.js +7 -0
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/integrations/blank-stack/components/Header.js +135 -0
  11. package/lib/commonjs/integrations/blank-stack/components/Header.js.map +1 -0
  12. package/lib/commonjs/integrations/blank-stack/components/Screens.js +64 -0
  13. package/lib/commonjs/integrations/blank-stack/components/Screens.js.map +1 -0
  14. package/lib/commonjs/integrations/blank-stack/components/StackView.js +85 -0
  15. package/lib/commonjs/integrations/blank-stack/components/StackView.js.map +1 -0
  16. package/lib/commonjs/integrations/blank-stack/navigators/createBlankStackNavigator.js +68 -0
  17. package/lib/commonjs/integrations/blank-stack/navigators/createBlankStackNavigator.js.map +1 -0
  18. package/lib/commonjs/integrations/blank-stack/providers/screen-transition-provider.js +10 -0
  19. package/lib/commonjs/integrations/blank-stack/providers/screen-transition-provider.js.map +1 -0
  20. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js +66 -0
  21. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js.map +1 -0
  22. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js +16 -0
  23. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js.map +1 -0
  24. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js +208 -0
  25. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js.map +1 -0
  26. package/lib/commonjs/{types/navigator.js → integrations/blank-stack/utils/with-stack-navigation/_types.js} +1 -1
  27. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_types.js.map +1 -0
  28. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js +15 -0
  29. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js.map +1 -0
  30. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.js +23 -0
  31. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.js.map +1 -0
  32. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js +15 -0
  33. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js.map +1 -0
  34. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js +14 -0
  35. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js.map +1 -0
  36. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js +13 -0
  37. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js.map +1 -0
  38. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/index.js +71 -0
  39. package/lib/commonjs/integrations/blank-stack/utils/with-stack-navigation/index.js.map +1 -0
  40. package/lib/commonjs/integrations/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  41. package/lib/commonjs/integrations/native-stack/providers/screen-transition-provider.js +10 -0
  42. package/lib/commonjs/integrations/native-stack/providers/screen-transition-provider.js.map +1 -0
  43. package/lib/commonjs/integrations/native-stack/utils/getModalRoutesKeys.js.map +1 -1
  44. package/lib/commonjs/integrations/native-stack/utils/useInvalidPreventRemoveError.js.map +1 -1
  45. package/lib/commonjs/integrations/native-stack/views/NativeStackView.js.map +1 -1
  46. package/lib/commonjs/integrations/native-stack/views/NativeStackView.native.js +1 -1
  47. package/lib/commonjs/integrations/native-stack/views/NativeStackView.native.js.map +1 -1
  48. package/lib/commonjs/integrations/native-stack/views/useHeaderConfigProps.js.map +1 -1
  49. package/lib/commonjs/providers/create-screen-transition-provider.js +35 -0
  50. package/lib/commonjs/providers/create-screen-transition-provider.js.map +1 -0
  51. package/lib/commonjs/providers/keys.js.map +1 -1
  52. package/lib/commonjs/providers/transition-styles.js +18 -4
  53. package/lib/commonjs/providers/transition-styles.js.map +1 -1
  54. package/lib/commonjs/stores/animations.js.map +1 -1
  55. package/lib/commonjs/stores/bounds/index.js.map +1 -1
  56. package/lib/commonjs/stores/gestures.js.map +1 -1
  57. package/lib/commonjs/stores/utils/reset-stores-for-screen.js.map +1 -1
  58. package/lib/commonjs/types/blank-stack.navigator.js +6 -0
  59. package/lib/{module/types/navigator.js.map → commonjs/types/blank-stack.navigator.js.map} +1 -1
  60. package/lib/commonjs/types/native-stack.navigator.js +6 -0
  61. package/lib/commonjs/types/native-stack.navigator.js.map +1 -0
  62. package/lib/commonjs/utils/animation/derivations.js +1 -14
  63. package/lib/commonjs/utils/animation/derivations.js.map +1 -1
  64. package/lib/commonjs/utils/bounds/constants.js.map +1 -1
  65. package/lib/commonjs/utils/bounds/index.js +23 -90
  66. package/lib/commonjs/utils/bounds/index.js.map +1 -1
  67. package/lib/commonjs/utils/gesture/apply-offset-rules.js.map +1 -1
  68. package/lib/commonjs/utils/gesture/check-gesture-activation.js.map +1 -1
  69. package/lib/module/__configs__/presets.js.map +1 -1
  70. package/lib/module/components/controllers/screen-lifecycle.blank.js +53 -0
  71. package/lib/module/components/controllers/screen-lifecycle.blank.js.map +1 -0
  72. package/lib/module/components/root-transition-aware.js.map +1 -1
  73. package/lib/module/constants.js.map +1 -1
  74. package/lib/module/hooks/animation/use-screen-animation.js +9 -5
  75. package/lib/module/hooks/animation/use-screen-animation.js.map +1 -1
  76. package/lib/module/index.js +1 -0
  77. package/lib/module/index.js.map +1 -1
  78. package/lib/module/integrations/blank-stack/components/Header.js +131 -0
  79. package/lib/module/integrations/blank-stack/components/Header.js.map +1 -0
  80. package/lib/module/integrations/blank-stack/components/Screens.js +58 -0
  81. package/lib/module/integrations/blank-stack/components/Screens.js.map +1 -0
  82. package/lib/module/integrations/blank-stack/components/StackView.js +81 -0
  83. package/lib/module/integrations/blank-stack/components/StackView.js.map +1 -0
  84. package/lib/module/integrations/blank-stack/navigators/createBlankStackNavigator.js +63 -0
  85. package/lib/module/integrations/blank-stack/navigators/createBlankStackNavigator.js.map +1 -0
  86. package/lib/module/integrations/blank-stack/providers/screen-transition-provider.js +6 -0
  87. package/lib/module/integrations/blank-stack/providers/screen-transition-provider.js.map +1 -0
  88. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js +60 -0
  89. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js.map +1 -0
  90. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js +11 -0
  91. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js.map +1 -0
  92. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js +202 -0
  93. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js.map +1 -0
  94. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_types.js +4 -0
  95. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_types.js.map +1 -0
  96. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js +10 -0
  97. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js.map +1 -0
  98. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.js +19 -0
  99. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.js.map +1 -0
  100. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js +10 -0
  101. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js.map +1 -0
  102. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js +9 -0
  103. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js.map +1 -0
  104. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js +8 -0
  105. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js.map +1 -0
  106. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/index.js +65 -0
  107. package/lib/module/integrations/blank-stack/utils/with-stack-navigation/index.js.map +1 -0
  108. package/lib/module/integrations/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  109. package/lib/module/integrations/native-stack/providers/screen-transition-provider.js +6 -0
  110. package/lib/module/integrations/native-stack/providers/screen-transition-provider.js.map +1 -0
  111. package/lib/module/integrations/native-stack/utils/getModalRoutesKeys.js.map +1 -1
  112. package/lib/module/integrations/native-stack/utils/useInvalidPreventRemoveError.js.map +1 -1
  113. package/lib/module/integrations/native-stack/views/NativeStackView.js.map +1 -1
  114. package/lib/module/integrations/native-stack/views/NativeStackView.native.js +1 -1
  115. package/lib/module/integrations/native-stack/views/NativeStackView.native.js.map +1 -1
  116. package/lib/module/integrations/native-stack/views/useHeaderConfigProps.js.map +1 -1
  117. package/lib/module/providers/create-screen-transition-provider.js +31 -0
  118. package/lib/module/providers/create-screen-transition-provider.js.map +1 -0
  119. package/lib/module/providers/keys.js.map +1 -1
  120. package/lib/module/providers/transition-styles.js +19 -5
  121. package/lib/module/providers/transition-styles.js.map +1 -1
  122. package/lib/module/stores/animations.js.map +1 -1
  123. package/lib/module/stores/bounds/index.js.map +1 -1
  124. package/lib/module/stores/gestures.js.map +1 -1
  125. package/lib/module/stores/utils/reset-stores-for-screen.js.map +1 -1
  126. package/lib/module/types/blank-stack.navigator.js +4 -0
  127. package/lib/{commonjs/types/navigator.js.map → module/types/blank-stack.navigator.js.map} +1 -1
  128. package/lib/module/types/native-stack.navigator.js +4 -0
  129. package/lib/module/types/native-stack.navigator.js.map +1 -0
  130. package/lib/module/utils/animation/derivations.js +1 -14
  131. package/lib/module/utils/animation/derivations.js.map +1 -1
  132. package/lib/module/utils/bounds/constants.js.map +1 -1
  133. package/lib/module/utils/bounds/index.js +24 -91
  134. package/lib/module/utils/bounds/index.js.map +1 -1
  135. package/lib/module/utils/gesture/apply-offset-rules.js.map +1 -1
  136. package/lib/module/utils/gesture/check-gesture-activation.js.map +1 -1
  137. package/lib/typescript/__configs__/index.d.ts +9 -9
  138. package/lib/typescript/__configs__/index.d.ts.map +1 -1
  139. package/lib/typescript/__configs__/presets.d.ts +1 -1
  140. package/lib/typescript/__configs__/presets.d.ts.map +1 -1
  141. package/lib/typescript/components/controllers/screen-lifecycle.blank.d.ts +7 -0
  142. package/lib/typescript/components/controllers/screen-lifecycle.blank.d.ts.map +1 -0
  143. package/lib/typescript/components/root-transition-aware.d.ts.map +1 -1
  144. package/lib/typescript/constants.d.ts +2 -2
  145. package/lib/typescript/constants.d.ts.map +1 -1
  146. package/lib/typescript/hooks/animation/use-screen-animation.d.ts +1 -1
  147. package/lib/typescript/hooks/animation/use-screen-animation.d.ts.map +1 -1
  148. package/lib/typescript/index.d.ts +20 -18
  149. package/lib/typescript/index.d.ts.map +1 -1
  150. package/lib/typescript/integrations/blank-stack/components/Header.d.ts +5 -0
  151. package/lib/typescript/integrations/blank-stack/components/Header.d.ts.map +1 -0
  152. package/lib/typescript/integrations/blank-stack/components/Screens.d.ts +15 -0
  153. package/lib/typescript/integrations/blank-stack/components/Screens.d.ts.map +1 -0
  154. package/lib/typescript/integrations/blank-stack/components/StackView.d.ts +2 -0
  155. package/lib/typescript/integrations/blank-stack/components/StackView.d.ts.map +1 -0
  156. package/lib/typescript/integrations/blank-stack/navigators/createBlankStackNavigator.d.ts +16 -0
  157. package/lib/typescript/integrations/blank-stack/navigators/createBlankStackNavigator.d.ts.map +1 -0
  158. package/lib/typescript/integrations/blank-stack/providers/screen-transition-provider.d.ts +8 -0
  159. package/lib/typescript/integrations/blank-stack/providers/screen-transition-provider.d.ts.map +1 -0
  160. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.d.ts +8 -0
  161. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.d.ts.map +1 -0
  162. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.d.ts +2 -0
  163. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.d.ts.map +1 -0
  164. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.d.ts +20 -0
  165. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.d.ts.map +1 -0
  166. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_types.d.ts +23 -0
  167. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_types.d.ts.map +1 -0
  168. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.d.ts +3 -0
  169. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.d.ts.map +1 -0
  170. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.d.ts +4 -0
  171. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.d.ts.map +1 -0
  172. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.d.ts +4 -0
  173. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.d.ts.map +1 -0
  174. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.d.ts +3 -0
  175. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.d.ts.map +1 -0
  176. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.d.ts +3 -0
  177. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.d.ts.map +1 -0
  178. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/index.d.ts +6 -0
  179. package/lib/typescript/integrations/blank-stack/utils/with-stack-navigation/index.d.ts.map +1 -0
  180. package/lib/typescript/integrations/native-stack/navigators/createNativeStackNavigator.d.ts +1 -1
  181. package/lib/typescript/integrations/native-stack/navigators/createNativeStackNavigator.d.ts.map +1 -1
  182. package/lib/typescript/integrations/native-stack/providers/screen-transition-provider.d.ts +8 -0
  183. package/lib/typescript/integrations/native-stack/providers/screen-transition-provider.d.ts.map +1 -0
  184. package/lib/typescript/integrations/native-stack/utils/getModalRoutesKeys.d.ts +1 -1
  185. package/lib/typescript/integrations/native-stack/utils/getModalRoutesKeys.d.ts.map +1 -1
  186. package/lib/typescript/integrations/native-stack/utils/useInvalidPreventRemoveError.d.ts +1 -1
  187. package/lib/typescript/integrations/native-stack/utils/useInvalidPreventRemoveError.d.ts.map +1 -1
  188. package/lib/typescript/integrations/native-stack/views/NativeStackView.d.ts +1 -1
  189. package/lib/typescript/integrations/native-stack/views/NativeStackView.d.ts.map +1 -1
  190. package/lib/typescript/integrations/native-stack/views/NativeStackView.native.d.ts +1 -1
  191. package/lib/typescript/integrations/native-stack/views/NativeStackView.native.d.ts.map +1 -1
  192. package/lib/typescript/integrations/native-stack/views/useHeaderConfigProps.d.ts +1 -1
  193. package/lib/typescript/integrations/native-stack/views/useHeaderConfigProps.d.ts.map +1 -1
  194. package/lib/typescript/providers/create-screen-transition-provider.d.ts +15 -0
  195. package/lib/typescript/providers/create-screen-transition-provider.d.ts.map +1 -0
  196. package/lib/typescript/providers/keys.d.ts +15 -13
  197. package/lib/typescript/providers/keys.d.ts.map +1 -1
  198. package/lib/typescript/providers/transition-styles.d.ts.map +1 -1
  199. package/lib/typescript/stores/animations.d.ts +1 -1
  200. package/lib/typescript/stores/animations.d.ts.map +1 -1
  201. package/lib/typescript/stores/bounds/index.d.ts +1 -1
  202. package/lib/typescript/stores/bounds/index.d.ts.map +1 -1
  203. package/lib/typescript/stores/gestures.d.ts +1 -1
  204. package/lib/typescript/stores/gestures.d.ts.map +1 -1
  205. package/lib/typescript/stores/utils/reset-stores-for-screen.d.ts +1 -1
  206. package/lib/typescript/stores/utils/reset-stores-for-screen.d.ts.map +1 -1
  207. package/lib/typescript/types/animation.d.ts +2 -4
  208. package/lib/typescript/types/animation.d.ts.map +1 -1
  209. package/lib/typescript/types/blank-stack.navigator.d.ts +214 -0
  210. package/lib/typescript/types/blank-stack.navigator.d.ts.map +1 -0
  211. package/lib/typescript/types/bounds.d.ts +0 -57
  212. package/lib/typescript/types/bounds.d.ts.map +1 -1
  213. package/lib/typescript/types/{navigator.d.ts → native-stack.navigator.d.ts} +5 -1
  214. package/lib/typescript/types/native-stack.navigator.d.ts.map +1 -0
  215. package/lib/typescript/utils/animation/derivations.d.ts +1 -4
  216. package/lib/typescript/utils/animation/derivations.d.ts.map +1 -1
  217. package/lib/typescript/utils/bounds/_types/builder.d.ts +2 -2
  218. package/lib/typescript/utils/bounds/_types/builder.d.ts.map +1 -1
  219. package/lib/typescript/utils/bounds/_utils/geometry.d.ts +2 -2
  220. package/lib/typescript/utils/bounds/_utils/geometry.d.ts.map +1 -1
  221. package/lib/typescript/utils/bounds/constants.d.ts +2 -2
  222. package/lib/typescript/utils/bounds/constants.d.ts.map +1 -1
  223. package/lib/typescript/utils/bounds/index.d.ts +4 -4
  224. package/lib/typescript/utils/bounds/index.d.ts.map +1 -1
  225. package/lib/typescript/utils/gesture/apply-offset-rules.d.ts +2 -2
  226. package/lib/typescript/utils/gesture/apply-offset-rules.d.ts.map +1 -1
  227. package/lib/typescript/utils/gesture/check-gesture-activation.d.ts +2 -2
  228. package/lib/typescript/utils/gesture/check-gesture-activation.d.ts.map +1 -1
  229. package/package.json +1 -1
  230. package/src/__configs__/presets.ts +590 -590
  231. package/src/components/controllers/screen-lifecycle.blank.ts +62 -0
  232. package/src/components/root-transition-aware.tsx +27 -27
  233. package/src/constants.ts +47 -47
  234. package/src/hooks/animation/use-screen-animation.tsx +52 -47
  235. package/src/index.ts +33 -22
  236. package/src/integrations/blank-stack/components/Header.tsx +141 -0
  237. package/src/integrations/blank-stack/components/Screens.tsx +96 -0
  238. package/src/integrations/blank-stack/components/StackView.tsx +100 -0
  239. package/src/integrations/blank-stack/navigators/createBlankStackNavigator.tsx +111 -0
  240. package/src/integrations/blank-stack/providers/screen-transition-provider.tsx +8 -0
  241. package/src/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.tsx +62 -0
  242. package/src/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-previous.tsx +11 -0
  243. package/src/integrations/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.tsx +280 -0
  244. package/src/integrations/blank-stack/utils/with-stack-navigation/_types.ts +36 -0
  245. package/src/integrations/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.ts +15 -0
  246. package/src/integrations/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.ts +29 -0
  247. package/src/integrations/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.ts +17 -0
  248. package/src/integrations/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.ts +12 -0
  249. package/src/integrations/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.ts +11 -0
  250. package/src/integrations/blank-stack/utils/with-stack-navigation/index.tsx +93 -0
  251. package/src/integrations/native-stack/navigators/createNativeStackNavigator.tsx +95 -95
  252. package/src/integrations/native-stack/providers/screen-transition-provider.tsx +8 -0
  253. package/src/integrations/native-stack/utils/getModalRoutesKeys.ts +14 -14
  254. package/src/integrations/native-stack/utils/useInvalidPreventRemoveError.tsx +23 -23
  255. package/src/integrations/native-stack/views/NativeStackView.native.tsx +609 -609
  256. package/src/integrations/native-stack/views/NativeStackView.tsx +188 -188
  257. package/src/integrations/native-stack/views/useHeaderConfigProps.tsx +260 -260
  258. package/src/providers/create-screen-transition-provider.tsx +46 -0
  259. package/src/providers/keys.tsx +46 -34
  260. package/src/providers/transition-styles.tsx +24 -11
  261. package/src/stores/animations.ts +23 -23
  262. package/src/stores/bounds/index.ts +82 -82
  263. package/src/stores/gestures.ts +36 -36
  264. package/src/stores/utils/reset-stores-for-screen.ts +4 -4
  265. package/src/types/animation.ts +2 -4
  266. package/src/types/blank-stack.navigator.ts +266 -0
  267. package/src/types/bounds.ts +0 -64
  268. package/src/types/{navigator.ts → native-stack.navigator.ts} +5 -0
  269. package/src/utils/animation/derivations.ts +3 -20
  270. package/src/utils/bounds/_types/builder.ts +111 -111
  271. package/src/utils/bounds/_utils/geometry.ts +2 -2
  272. package/src/utils/bounds/constants.ts +29 -29
  273. package/src/utils/bounds/index.ts +35 -105
  274. package/src/utils/gesture/apply-offset-rules.ts +271 -271
  275. package/src/utils/gesture/check-gesture-activation.ts +260 -260
  276. package/lib/commonjs/providers/screen-transition-provider.js +0 -34
  277. package/lib/commonjs/providers/screen-transition-provider.js.map +0 -1
  278. package/lib/module/providers/screen-transition-provider.js +0 -30
  279. package/lib/module/providers/screen-transition-provider.js.map +0 -1
  280. package/lib/module/types/navigator.js +0 -4
  281. package/lib/typescript/providers/screen-transition-provider.d.ts +0 -11
  282. package/lib/typescript/providers/screen-transition-provider.d.ts.map +0 -1
  283. package/lib/typescript/types/navigator.d.ts.map +0 -1
  284. package/src/providers/screen-transition-provider.tsx +0 -33
@@ -1,43 +1,43 @@
1
1
  import {
2
- getDefaultHeaderHeight,
3
- getHeaderTitle,
4
- HeaderBackContext,
5
- HeaderHeightContext,
6
- HeaderShownContext,
7
- SafeAreaProviderCompat,
8
- useFrameSize,
2
+ getDefaultHeaderHeight,
3
+ getHeaderTitle,
4
+ HeaderBackContext,
5
+ HeaderHeightContext,
6
+ HeaderShownContext,
7
+ SafeAreaProviderCompat,
8
+ useFrameSize,
9
9
  } from "@react-navigation/elements";
10
10
  import {
11
- NavigationContext,
12
- NavigationRouteContext,
13
- type ParamListBase,
14
- type RouteProp,
15
- StackActions,
16
- type StackNavigationState,
17
- usePreventRemoveContext,
18
- useTheme,
11
+ NavigationContext,
12
+ NavigationRouteContext,
13
+ type ParamListBase,
14
+ type RouteProp,
15
+ StackActions,
16
+ type StackNavigationState,
17
+ usePreventRemoveContext,
18
+ useTheme,
19
19
  } from "@react-navigation/native";
20
20
  import * as React from "react";
21
21
  import {
22
- Animated,
23
- Platform,
24
- StatusBar,
25
- StyleSheet,
26
- useAnimatedValue,
27
- View,
22
+ Animated,
23
+ Platform,
24
+ StatusBar,
25
+ StyleSheet,
26
+ useAnimatedValue,
27
+ View,
28
28
  } from "react-native";
29
29
  import { useSafeAreaInsets } from "react-native-safe-area-context";
30
30
  import {
31
- type ScreenProps,
32
- ScreenStack,
33
- ScreenStackItem,
31
+ type ScreenProps,
32
+ ScreenStack,
33
+ ScreenStackItem,
34
34
  } from "react-native-screens";
35
- import { ScreenTransitionProvider } from "../../../providers/screen-transition-provider";
35
+ import { ScreenTransitionProvider } from "../providers/screen-transition-provider";
36
36
  import type {
37
- NativeStackDescriptor,
38
- NativeStackDescriptorMap,
39
- NativeStackNavigationHelpers,
40
- } from "../../../types/navigator";
37
+ NativeStackDescriptor,
38
+ NativeStackDescriptorMap,
39
+ NativeStackNavigationHelpers,
40
+ } from "../../../types/native-stack.navigator";
41
41
  import { debounce } from "../utils/debounce";
42
42
  import { getModalRouteKeys } from "../utils/getModalRoutesKeys";
43
43
  import { AnimatedHeaderHeightContext } from "../utils/useAnimatedHeaderHeight";
@@ -48,603 +48,603 @@ import { useHeaderConfigProps } from "./useHeaderConfigProps";
48
48
  const ANDROID_DEFAULT_HEADER_HEIGHT = 56;
49
49
 
50
50
  function isFabric() {
51
- return "nativeFabricUIManager" in global;
51
+ return "nativeFabricUIManager" in global;
52
52
  }
53
53
 
54
54
  type SceneViewProps = {
55
- index: number;
56
- focused: boolean;
57
- shouldFreeze: boolean;
58
- descriptor: NativeStackDescriptor;
59
- previousDescriptor?: NativeStackDescriptor;
60
- nextDescriptor?: NativeStackDescriptor;
61
- isPresentationModal?: boolean;
62
- isPreloaded?: boolean;
63
- onWillDisappear: () => void;
64
- onWillAppear: () => void;
65
- onAppear: () => void;
66
- onDisappear: () => void;
67
- onDismissed: ScreenProps["onDismissed"];
68
- onHeaderBackButtonClicked: ScreenProps["onHeaderBackButtonClicked"];
69
- onNativeDismissCancelled: ScreenProps["onDismissed"];
70
- onGestureCancel: ScreenProps["onGestureCancel"];
71
- onSheetDetentChanged: ScreenProps["onSheetDetentChanged"];
55
+ index: number;
56
+ focused: boolean;
57
+ shouldFreeze: boolean;
58
+ descriptor: NativeStackDescriptor;
59
+ previousDescriptor?: NativeStackDescriptor;
60
+ nextDescriptor?: NativeStackDescriptor;
61
+ isPresentationModal?: boolean;
62
+ isPreloaded?: boolean;
63
+ onWillDisappear: () => void;
64
+ onWillAppear: () => void;
65
+ onAppear: () => void;
66
+ onDisappear: () => void;
67
+ onDismissed: ScreenProps["onDismissed"];
68
+ onHeaderBackButtonClicked: ScreenProps["onHeaderBackButtonClicked"];
69
+ onNativeDismissCancelled: ScreenProps["onDismissed"];
70
+ onGestureCancel: ScreenProps["onGestureCancel"];
71
+ onSheetDetentChanged: ScreenProps["onSheetDetentChanged"];
72
72
  };
73
73
 
74
74
  const useNativeDriver = Platform.OS !== "web";
75
75
 
76
76
  const SceneView = ({
77
- index,
78
- focused,
79
- shouldFreeze,
80
- descriptor,
81
- previousDescriptor,
82
- nextDescriptor,
83
- isPresentationModal,
84
- isPreloaded,
85
- onWillDisappear,
86
- onWillAppear,
87
- onAppear,
88
- onDisappear,
89
- onDismissed,
90
- onHeaderBackButtonClicked,
91
- onNativeDismissCancelled,
92
- onGestureCancel,
93
- onSheetDetentChanged,
77
+ index,
78
+ focused,
79
+ shouldFreeze,
80
+ descriptor,
81
+ previousDescriptor,
82
+ nextDescriptor,
83
+ isPresentationModal,
84
+ isPreloaded,
85
+ onWillDisappear,
86
+ onWillAppear,
87
+ onAppear,
88
+ onDisappear,
89
+ onDismissed,
90
+ onHeaderBackButtonClicked,
91
+ onNativeDismissCancelled,
92
+ onGestureCancel,
93
+ onSheetDetentChanged,
94
94
  }: SceneViewProps) => {
95
- const { route, navigation, options, render } = descriptor;
96
-
97
- let {
98
- animation,
99
- animationMatchesGesture,
100
- presentation = isPresentationModal ? "modal" : "card",
101
- fullScreenGestureEnabled,
102
- } = options;
103
-
104
- const {
105
- animationDuration,
106
- animationTypeForReplace = "push",
107
- fullScreenGestureShadowEnabled = true,
108
- nativeGestureEnabled,
109
- nativeGestureDirection = presentation === "card"
110
- ? "horizontal"
111
- : "vertical",
112
- nativeGestureResponseDistance,
113
- header,
114
- headerBackButtonMenuEnabled,
115
- headerShown,
116
- headerBackground,
117
- headerTransparent,
118
- autoHideHomeIndicator,
119
- keyboardHandlingEnabled,
120
- navigationBarColor,
121
- navigationBarTranslucent,
122
- navigationBarHidden,
123
- orientation,
124
- sheetAllowedDetents = [1.0],
125
- sheetLargestUndimmedDetentIndex = -1,
126
- sheetGrabberVisible = false,
127
- sheetCornerRadius = -1.0,
128
- sheetElevation = 24,
129
- sheetExpandsWhenScrolledToEdge = true,
130
- sheetInitialDetentIndex = 0,
131
- statusBarAnimation,
132
- statusBarHidden,
133
- statusBarStyle,
134
- statusBarTranslucent,
135
- statusBarBackgroundColor,
136
- unstable_sheetFooter,
137
- freezeOnBlur,
138
- contentStyle,
139
- enableTransitions,
140
- } = options;
141
-
142
- if (nativeGestureDirection === "vertical" && Platform.OS === "ios") {
143
- // for `vertical` direction to work, we need to set `fullScreenGestureEnabled` to `true`
144
- // so the screen can be dismissed from any point on screen.
145
- // `animationMatchesGesture` needs to be set to `true` so the `animation` set by user can be used,
146
- // otherwise `simple_push` will be used.
147
- // Also, the default animation for this direction seems to be `slide_from_bottom`.
148
- if (fullScreenGestureEnabled === undefined) {
149
- fullScreenGestureEnabled = true;
150
- }
151
-
152
- if (animationMatchesGesture === undefined) {
153
- animationMatchesGesture = true;
154
- }
155
-
156
- if (animation === undefined) {
157
- animation = "slide_from_bottom";
158
- }
159
- }
160
-
161
- // workaround for rn-screens where gestureDirection has to be set on both
162
- // current and previous screen - software-mansion/react-native-screens/pull/1509
163
- const nextGestureDirection = nextDescriptor?.options.nativeGestureDirection;
164
- const gestureDirectionOverride =
165
- nextGestureDirection != null
166
- ? nextGestureDirection
167
- : nativeGestureDirection;
168
-
169
- if (index === 0) {
170
- // first screen should always be treated as `card`, it resolves problems with no header animation
171
- // for navigator with first screen as `modal` and the next as `card`
172
- presentation = "card";
173
- }
174
-
175
- const { colors } = useTheme();
176
- const insets = useSafeAreaInsets();
177
-
178
- // `modal` and `formSheet` presentations do not take whole screen, so should not take the inset.
179
- const isModal = presentation === "modal" || presentation === "formSheet";
180
-
181
- // Modals are fullscreen in landscape only on iPhone
182
- const isIPhone = Platform.OS === "ios" && !(Platform.isPad || Platform.isTV);
183
-
184
- const isParentHeaderShown = React.useContext(HeaderShownContext);
185
- const parentHeaderHeight = React.useContext(HeaderHeightContext);
186
- const parentHeaderBack = React.useContext(HeaderBackContext);
187
-
188
- const isLandscape = useFrameSize((frame) => frame.width > frame.height);
189
-
190
- const topInset =
191
- isParentHeaderShown ||
192
- (Platform.OS === "ios" && isModal) ||
193
- (isIPhone && isLandscape)
194
- ? 0
195
- : insets.top;
196
-
197
- const defaultHeaderHeight = useFrameSize((frame) =>
198
- Platform.select({
199
- // FIXME: Currently screens isn't using Material 3
200
- // So our `getDefaultHeaderHeight` doesn't return the correct value
201
- // So we hardcode the value here for now until screens is updated
202
- android: ANDROID_DEFAULT_HEADER_HEIGHT + topInset,
203
- default: getDefaultHeaderHeight(frame, isModal, topInset),
204
- }),
205
- );
206
-
207
- const { preventedRoutes } = usePreventRemoveContext();
208
-
209
- const [headerHeight, setHeaderHeight] = React.useState(defaultHeaderHeight);
210
-
211
- // eslint-disable-next-line react-hooks/exhaustive-deps
212
- const setHeaderHeightDebounced = React.useCallback(
213
- // Debounce the header height updates to avoid excessive re-renders
214
- debounce(setHeaderHeight, 100),
215
- [],
216
- );
217
-
218
- const hasCustomHeader = header != null;
219
-
220
- let headerHeightCorrectionOffset = 0;
221
-
222
- if (Platform.OS === "android" && !hasCustomHeader) {
223
- const statusBarHeight = StatusBar.currentHeight ?? 0;
224
-
225
- // FIXME: On Android, the native header height is not correctly calculated
226
- // It includes status bar height even if statusbar is not translucent
227
- // And the statusbar value itself doesn't match the actual status bar height
228
- // So we subtract the bogus status bar height and add the actual top inset
229
- headerHeightCorrectionOffset = -statusBarHeight + topInset;
230
- }
231
-
232
- const rawAnimatedHeaderHeight = useAnimatedValue(defaultHeaderHeight);
233
- const animatedHeaderHeight = React.useMemo(
234
- () =>
235
- Animated.add<number>(
236
- rawAnimatedHeaderHeight,
237
- headerHeightCorrectionOffset,
238
- ),
239
- [headerHeightCorrectionOffset, rawAnimatedHeaderHeight],
240
- );
241
-
242
- // During the very first render topInset is > 0 when running
243
- // in non edge-to-edge mode on Android, while on every consecutive render
244
- // topInset === 0, causing header content to jump, as we add padding on the first frame,
245
- // just to remove it in next one. To prevent this, when statusBarTranslucent is set,
246
- // we apply additional padding in header only if its true.
247
- // For more details see: https://github.com/react-navigation/react-navigation/pull/12014
248
- const headerTopInsetEnabled =
249
- typeof statusBarTranslucent === "boolean"
250
- ? statusBarTranslucent
251
- : topInset !== 0;
252
-
253
- const canGoBack = previousDescriptor != null || parentHeaderBack != null;
254
- const backTitle = previousDescriptor
255
- ? getHeaderTitle(previousDescriptor.options, previousDescriptor.route.name)
256
- : parentHeaderBack?.title;
257
-
258
- const headerBack = React.useMemo(() => {
259
- if (canGoBack) {
260
- return {
261
- href: undefined, // No href needed for native
262
- title: backTitle,
263
- };
264
- }
265
-
266
- return undefined;
267
- }, [canGoBack, backTitle]);
268
-
269
- const isRemovePrevented = preventedRoutes[route.key]?.preventRemove;
270
-
271
- const modifiedPresentation = enableTransitions
272
- ? "containedTransparentModal"
273
- : presentation === "card"
274
- ? "push"
275
- : presentation;
276
- const modifiedAnimation = enableTransitions ? "none" : animation;
277
- const modifiedHeaderShown =
278
- enableTransitions || header !== undefined ? false : headerShown;
279
-
280
- const headerConfig = useHeaderConfigProps({
281
- ...options,
282
- route,
283
- headerBackButtonMenuEnabled:
284
- isRemovePrevented !== undefined
285
- ? !isRemovePrevented
286
- : headerBackButtonMenuEnabled,
287
- headerBackTitle:
288
- options.headerBackTitle !== undefined
289
- ? options.headerBackTitle
290
- : undefined,
291
- headerHeight,
292
- headerShown: modifiedHeaderShown,
293
- headerTopInsetEnabled,
294
- headerBack,
295
- });
296
-
297
- return (
298
- <NavigationContext.Provider value={navigation}>
299
- <NavigationRouteContext.Provider value={route}>
300
- <ScreenStackItem
301
- key={route.key}
302
- screenId={route.key}
303
- activityState={isPreloaded ? 0 : 2}
304
- style={StyleSheet.absoluteFill}
305
- aria-hidden={!focused}
306
- customAnimationOnSwipe={animationMatchesGesture}
307
- fullScreenSwipeEnabled={fullScreenGestureEnabled}
308
- fullScreenSwipeShadowEnabled={fullScreenGestureShadowEnabled}
309
- freezeOnBlur={freezeOnBlur}
310
- gestureEnabled={
311
- Platform.OS === "android"
312
- ? // This prop enables handling of system back gestures on Android
313
- // Since we handle them in JS side, we disable this
314
- false
315
- : nativeGestureEnabled
316
- }
317
- homeIndicatorHidden={autoHideHomeIndicator}
318
- hideKeyboardOnSwipe={keyboardHandlingEnabled}
319
- navigationBarColor={navigationBarColor}
320
- navigationBarTranslucent={navigationBarTranslucent}
321
- navigationBarHidden={navigationBarHidden}
322
- replaceAnimation={animationTypeForReplace}
323
- stackPresentation={modifiedPresentation}
324
- stackAnimation={modifiedAnimation}
325
- screenOrientation={orientation}
326
- sheetAllowedDetents={sheetAllowedDetents}
327
- sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
328
- sheetGrabberVisible={sheetGrabberVisible}
329
- sheetInitialDetentIndex={sheetInitialDetentIndex}
330
- sheetCornerRadius={sheetCornerRadius}
331
- sheetElevation={sheetElevation}
332
- sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
333
- statusBarAnimation={statusBarAnimation}
334
- statusBarHidden={statusBarHidden}
335
- statusBarStyle={statusBarStyle}
336
- statusBarColor={statusBarBackgroundColor}
337
- statusBarTranslucent={statusBarTranslucent}
338
- swipeDirection={gestureDirectionOverride}
339
- transitionDuration={animationDuration}
340
- onWillAppear={onWillAppear}
341
- onWillDisappear={onWillDisappear}
342
- onAppear={onAppear}
343
- onDisappear={onDisappear}
344
- onDismissed={onDismissed}
345
- onGestureCancel={onGestureCancel}
346
- onSheetDetentChanged={onSheetDetentChanged}
347
- gestureResponseDistance={nativeGestureResponseDistance}
348
- nativeBackButtonDismissalEnabled={false} // on Android
349
- onHeaderBackButtonClicked={onHeaderBackButtonClicked}
350
- preventNativeDismiss={isRemovePrevented} // on iOS
351
- onNativeDismissCancelled={onNativeDismissCancelled}
352
- // Unfortunately, because of the bug that exists on Fabric, where native event drivers
353
- // for Animated objects are being created after the first notifications about the header height
354
- // from the native side, `onHeaderHeightChange` event does not notify
355
- // `animatedHeaderHeight` about initial values on appearing screens at the moment.
356
- onHeaderHeightChange={Animated.event(
357
- [
358
- {
359
- nativeEvent: {
360
- headerHeight: rawAnimatedHeaderHeight,
361
- },
362
- },
363
- ],
364
- {
365
- useNativeDriver,
366
- listener: (e) => {
367
- if (hasCustomHeader) {
368
- // If we have a custom header, don't use native header height
369
- return;
370
- }
371
-
372
- if (
373
- Platform.OS === "android" &&
374
- (options.headerBackground != null ||
375
- options.headerTransparent)
376
- ) {
377
- // FIXME: On Android, we get 0 if the header is translucent
378
- // So we set a default height in that case
379
- setHeaderHeight(ANDROID_DEFAULT_HEADER_HEIGHT + topInset);
380
- return;
381
- }
382
-
383
- if (
384
- e.nativeEvent &&
385
- typeof e.nativeEvent === "object" &&
386
- "headerHeight" in e.nativeEvent &&
387
- typeof e.nativeEvent.headerHeight === "number"
388
- ) {
389
- const headerHeight =
390
- e.nativeEvent.headerHeight + headerHeightCorrectionOffset;
391
-
392
- // Only debounce if header has large title or search bar
393
- // As it's the only case where the header height can change frequently
394
- const doesHeaderAnimate =
395
- Platform.OS === "ios" &&
396
- (options.headerLargeTitle ||
397
- options.headerSearchBarOptions);
398
-
399
- if (doesHeaderAnimate) {
400
- setHeaderHeightDebounced(headerHeight);
401
- } else {
402
- setHeaderHeight(headerHeight);
403
- }
404
- }
405
- },
406
- },
407
- )}
408
- contentStyle={[
409
- modifiedPresentation !== "transparentModal" &&
410
- modifiedPresentation !== "containedTransparentModal" && {
411
- backgroundColor: colors.background,
412
- },
413
- contentStyle,
414
- ]}
415
- headerConfig={headerConfig}
416
- unstable_sheetFooter={unstable_sheetFooter}
417
- // When ts-expect-error is added, it affects all the props below it
418
- // So we keep any props that need it at the end
419
- // Otherwise invalid props may not be caught by TypeScript
420
- shouldFreeze={shouldFreeze}
421
- >
422
- <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
423
- <HeaderHeightContext.Provider
424
- value={
425
- headerShown !== false ? headerHeight : (parentHeaderHeight ?? 0)
426
- }
427
- >
428
- {headerBackground != null ? (
429
- /**
430
- * To show a custom header background, we render it at the top of the screen below the header
431
- * The header also needs to be positioned absolutely (with `translucent` style)
432
- */
433
- <View
434
- style={[
435
- styles.background,
436
- headerTransparent ? styles.translucent : null,
437
- { height: headerHeight },
438
- ]}
439
- >
440
- {headerBackground()}
441
- </View>
442
- ) : null}
443
- {header != null && headerShown !== false ? (
444
- <View
445
- onLayout={(e) => {
446
- const headerHeight = e.nativeEvent.layout.height;
447
-
448
- setHeaderHeight(headerHeight);
449
- rawAnimatedHeaderHeight.setValue(headerHeight);
450
- }}
451
- style={[
452
- styles.header,
453
- headerTransparent ? styles.absolute : null,
454
- ]}
455
- >
456
- {header({
457
- back: headerBack,
458
- options,
459
- route,
460
- navigation,
461
- })}
462
- </View>
463
- ) : null}
464
- <HeaderShownContext.Provider
465
- value={isParentHeaderShown || headerShown !== false}
466
- >
467
- <HeaderBackContext.Provider value={headerBack}>
468
- <ScreenTransitionProvider
469
- previous={previousDescriptor}
470
- current={descriptor}
471
- next={nextDescriptor}
472
- >
473
- {render()}
474
- </ScreenTransitionProvider>
475
- </HeaderBackContext.Provider>
476
- </HeaderShownContext.Provider>
477
- </HeaderHeightContext.Provider>
478
- </AnimatedHeaderHeightContext.Provider>
479
- </ScreenStackItem>
480
- </NavigationRouteContext.Provider>
481
- </NavigationContext.Provider>
482
- );
95
+ const { route, navigation, options, render } = descriptor;
96
+
97
+ let {
98
+ animation,
99
+ animationMatchesGesture,
100
+ presentation = isPresentationModal ? "modal" : "card",
101
+ fullScreenGestureEnabled,
102
+ } = options;
103
+
104
+ const {
105
+ animationDuration,
106
+ animationTypeForReplace = "push",
107
+ fullScreenGestureShadowEnabled = true,
108
+ nativeGestureEnabled,
109
+ nativeGestureDirection = presentation === "card"
110
+ ? "horizontal"
111
+ : "vertical",
112
+ nativeGestureResponseDistance,
113
+ header,
114
+ headerBackButtonMenuEnabled,
115
+ headerShown,
116
+ headerBackground,
117
+ headerTransparent,
118
+ autoHideHomeIndicator,
119
+ keyboardHandlingEnabled,
120
+ navigationBarColor,
121
+ navigationBarTranslucent,
122
+ navigationBarHidden,
123
+ orientation,
124
+ sheetAllowedDetents = [1.0],
125
+ sheetLargestUndimmedDetentIndex = -1,
126
+ sheetGrabberVisible = false,
127
+ sheetCornerRadius = -1.0,
128
+ sheetElevation = 24,
129
+ sheetExpandsWhenScrolledToEdge = true,
130
+ sheetInitialDetentIndex = 0,
131
+ statusBarAnimation,
132
+ statusBarHidden,
133
+ statusBarStyle,
134
+ statusBarTranslucent,
135
+ statusBarBackgroundColor,
136
+ unstable_sheetFooter,
137
+ freezeOnBlur,
138
+ contentStyle,
139
+ enableTransitions,
140
+ } = options;
141
+
142
+ if (nativeGestureDirection === "vertical" && Platform.OS === "ios") {
143
+ // for `vertical` direction to work, we need to set `fullScreenGestureEnabled` to `true`
144
+ // so the screen can be dismissed from any point on screen.
145
+ // `animationMatchesGesture` needs to be set to `true` so the `animation` set by user can be used,
146
+ // otherwise `simple_push` will be used.
147
+ // Also, the default animation for this direction seems to be `slide_from_bottom`.
148
+ if (fullScreenGestureEnabled === undefined) {
149
+ fullScreenGestureEnabled = true;
150
+ }
151
+
152
+ if (animationMatchesGesture === undefined) {
153
+ animationMatchesGesture = true;
154
+ }
155
+
156
+ if (animation === undefined) {
157
+ animation = "slide_from_bottom";
158
+ }
159
+ }
160
+
161
+ // workaround for rn-screens where gestureDirection has to be set on both
162
+ // current and previous screen - software-mansion/react-native-screens/pull/1509
163
+ const nextGestureDirection = nextDescriptor?.options.nativeGestureDirection;
164
+ const gestureDirectionOverride =
165
+ nextGestureDirection != null
166
+ ? nextGestureDirection
167
+ : nativeGestureDirection;
168
+
169
+ if (index === 0) {
170
+ // first screen should always be treated as `card`, it resolves problems with no header animation
171
+ // for navigator with first screen as `modal` and the next as `card`
172
+ presentation = "card";
173
+ }
174
+
175
+ const { colors } = useTheme();
176
+ const insets = useSafeAreaInsets();
177
+
178
+ // `modal` and `formSheet` presentations do not take whole screen, so should not take the inset.
179
+ const isModal = presentation === "modal" || presentation === "formSheet";
180
+
181
+ // Modals are fullscreen in landscape only on iPhone
182
+ const isIPhone = Platform.OS === "ios" && !(Platform.isPad || Platform.isTV);
183
+
184
+ const isParentHeaderShown = React.useContext(HeaderShownContext);
185
+ const parentHeaderHeight = React.useContext(HeaderHeightContext);
186
+ const parentHeaderBack = React.useContext(HeaderBackContext);
187
+
188
+ const isLandscape = useFrameSize((frame) => frame.width > frame.height);
189
+
190
+ const topInset =
191
+ isParentHeaderShown ||
192
+ (Platform.OS === "ios" && isModal) ||
193
+ (isIPhone && isLandscape)
194
+ ? 0
195
+ : insets.top;
196
+
197
+ const defaultHeaderHeight = useFrameSize((frame) =>
198
+ Platform.select({
199
+ // FIXME: Currently screens isn't using Material 3
200
+ // So our `getDefaultHeaderHeight` doesn't return the correct value
201
+ // So we hardcode the value here for now until screens is updated
202
+ android: ANDROID_DEFAULT_HEADER_HEIGHT + topInset,
203
+ default: getDefaultHeaderHeight(frame, isModal, topInset),
204
+ })
205
+ );
206
+
207
+ const { preventedRoutes } = usePreventRemoveContext();
208
+
209
+ const [headerHeight, setHeaderHeight] = React.useState(defaultHeaderHeight);
210
+
211
+ // eslint-disable-next-line react-hooks/exhaustive-deps
212
+ const setHeaderHeightDebounced = React.useCallback(
213
+ // Debounce the header height updates to avoid excessive re-renders
214
+ debounce(setHeaderHeight, 100),
215
+ []
216
+ );
217
+
218
+ const hasCustomHeader = header != null;
219
+
220
+ let headerHeightCorrectionOffset = 0;
221
+
222
+ if (Platform.OS === "android" && !hasCustomHeader) {
223
+ const statusBarHeight = StatusBar.currentHeight ?? 0;
224
+
225
+ // FIXME: On Android, the native header height is not correctly calculated
226
+ // It includes status bar height even if statusbar is not translucent
227
+ // And the statusbar value itself doesn't match the actual status bar height
228
+ // So we subtract the bogus status bar height and add the actual top inset
229
+ headerHeightCorrectionOffset = -statusBarHeight + topInset;
230
+ }
231
+
232
+ const rawAnimatedHeaderHeight = useAnimatedValue(defaultHeaderHeight);
233
+ const animatedHeaderHeight = React.useMemo(
234
+ () =>
235
+ Animated.add<number>(
236
+ rawAnimatedHeaderHeight,
237
+ headerHeightCorrectionOffset
238
+ ),
239
+ [headerHeightCorrectionOffset, rawAnimatedHeaderHeight]
240
+ );
241
+
242
+ // During the very first render topInset is > 0 when running
243
+ // in non edge-to-edge mode on Android, while on every consecutive render
244
+ // topInset === 0, causing header content to jump, as we add padding on the first frame,
245
+ // just to remove it in next one. To prevent this, when statusBarTranslucent is set,
246
+ // we apply additional padding in header only if its true.
247
+ // For more details see: https://github.com/react-navigation/react-navigation/pull/12014
248
+ const headerTopInsetEnabled =
249
+ typeof statusBarTranslucent === "boolean"
250
+ ? statusBarTranslucent
251
+ : topInset !== 0;
252
+
253
+ const canGoBack = previousDescriptor != null || parentHeaderBack != null;
254
+ const backTitle = previousDescriptor
255
+ ? getHeaderTitle(previousDescriptor.options, previousDescriptor.route.name)
256
+ : parentHeaderBack?.title;
257
+
258
+ const headerBack = React.useMemo(() => {
259
+ if (canGoBack) {
260
+ return {
261
+ href: undefined, // No href needed for native
262
+ title: backTitle,
263
+ };
264
+ }
265
+
266
+ return undefined;
267
+ }, [canGoBack, backTitle]);
268
+
269
+ const isRemovePrevented = preventedRoutes[route.key]?.preventRemove;
270
+
271
+ const modifiedPresentation = enableTransitions
272
+ ? "containedTransparentModal"
273
+ : presentation === "card"
274
+ ? "push"
275
+ : presentation;
276
+ const modifiedAnimation = enableTransitions ? "none" : animation;
277
+ const modifiedHeaderShown =
278
+ enableTransitions || header !== undefined ? false : headerShown;
279
+
280
+ const headerConfig = useHeaderConfigProps({
281
+ ...options,
282
+ route,
283
+ headerBackButtonMenuEnabled:
284
+ isRemovePrevented !== undefined
285
+ ? !isRemovePrevented
286
+ : headerBackButtonMenuEnabled,
287
+ headerBackTitle:
288
+ options.headerBackTitle !== undefined
289
+ ? options.headerBackTitle
290
+ : undefined,
291
+ headerHeight,
292
+ headerShown: modifiedHeaderShown,
293
+ headerTopInsetEnabled,
294
+ headerBack,
295
+ });
296
+
297
+ return (
298
+ <NavigationContext.Provider value={navigation}>
299
+ <NavigationRouteContext.Provider value={route}>
300
+ <ScreenStackItem
301
+ key={route.key}
302
+ screenId={route.key}
303
+ activityState={isPreloaded ? 0 : 2}
304
+ style={StyleSheet.absoluteFill}
305
+ aria-hidden={!focused}
306
+ customAnimationOnSwipe={animationMatchesGesture}
307
+ fullScreenSwipeEnabled={fullScreenGestureEnabled}
308
+ fullScreenSwipeShadowEnabled={fullScreenGestureShadowEnabled}
309
+ freezeOnBlur={freezeOnBlur}
310
+ gestureEnabled={
311
+ Platform.OS === "android"
312
+ ? // This prop enables handling of system back gestures on Android
313
+ // Since we handle them in JS side, we disable this
314
+ false
315
+ : nativeGestureEnabled
316
+ }
317
+ homeIndicatorHidden={autoHideHomeIndicator}
318
+ hideKeyboardOnSwipe={keyboardHandlingEnabled}
319
+ navigationBarColor={navigationBarColor}
320
+ navigationBarTranslucent={navigationBarTranslucent}
321
+ navigationBarHidden={navigationBarHidden}
322
+ replaceAnimation={animationTypeForReplace}
323
+ stackPresentation={modifiedPresentation}
324
+ stackAnimation={modifiedAnimation}
325
+ screenOrientation={orientation}
326
+ sheetAllowedDetents={sheetAllowedDetents}
327
+ sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
328
+ sheetGrabberVisible={sheetGrabberVisible}
329
+ sheetInitialDetentIndex={sheetInitialDetentIndex}
330
+ sheetCornerRadius={sheetCornerRadius}
331
+ sheetElevation={sheetElevation}
332
+ sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
333
+ statusBarAnimation={statusBarAnimation}
334
+ statusBarHidden={statusBarHidden}
335
+ statusBarStyle={statusBarStyle}
336
+ statusBarColor={statusBarBackgroundColor}
337
+ statusBarTranslucent={statusBarTranslucent}
338
+ swipeDirection={gestureDirectionOverride}
339
+ transitionDuration={animationDuration}
340
+ onWillAppear={onWillAppear}
341
+ onWillDisappear={onWillDisappear}
342
+ onAppear={onAppear}
343
+ onDisappear={onDisappear}
344
+ onDismissed={onDismissed}
345
+ onGestureCancel={onGestureCancel}
346
+ onSheetDetentChanged={onSheetDetentChanged}
347
+ gestureResponseDistance={nativeGestureResponseDistance}
348
+ nativeBackButtonDismissalEnabled={false} // on Android
349
+ onHeaderBackButtonClicked={onHeaderBackButtonClicked}
350
+ preventNativeDismiss={isRemovePrevented} // on iOS
351
+ onNativeDismissCancelled={onNativeDismissCancelled}
352
+ // Unfortunately, because of the bug that exists on Fabric, where native event drivers
353
+ // for Animated objects are being created after the first notifications about the header height
354
+ // from the native side, `onHeaderHeightChange` event does not notify
355
+ // `animatedHeaderHeight` about initial values on appearing screens at the moment.
356
+ onHeaderHeightChange={Animated.event(
357
+ [
358
+ {
359
+ nativeEvent: {
360
+ headerHeight: rawAnimatedHeaderHeight,
361
+ },
362
+ },
363
+ ],
364
+ {
365
+ useNativeDriver,
366
+ listener: (e) => {
367
+ if (hasCustomHeader) {
368
+ // If we have a custom header, don't use native header height
369
+ return;
370
+ }
371
+
372
+ if (
373
+ Platform.OS === "android" &&
374
+ (options.headerBackground != null ||
375
+ options.headerTransparent)
376
+ ) {
377
+ // FIXME: On Android, we get 0 if the header is translucent
378
+ // So we set a default height in that case
379
+ setHeaderHeight(ANDROID_DEFAULT_HEADER_HEIGHT + topInset);
380
+ return;
381
+ }
382
+
383
+ if (
384
+ e.nativeEvent &&
385
+ typeof e.nativeEvent === "object" &&
386
+ "headerHeight" in e.nativeEvent &&
387
+ typeof e.nativeEvent.headerHeight === "number"
388
+ ) {
389
+ const headerHeight =
390
+ e.nativeEvent.headerHeight + headerHeightCorrectionOffset;
391
+
392
+ // Only debounce if header has large title or search bar
393
+ // As it's the only case where the header height can change frequently
394
+ const doesHeaderAnimate =
395
+ Platform.OS === "ios" &&
396
+ (options.headerLargeTitle ||
397
+ options.headerSearchBarOptions);
398
+
399
+ if (doesHeaderAnimate) {
400
+ setHeaderHeightDebounced(headerHeight);
401
+ } else {
402
+ setHeaderHeight(headerHeight);
403
+ }
404
+ }
405
+ },
406
+ }
407
+ )}
408
+ contentStyle={[
409
+ modifiedPresentation !== "transparentModal" &&
410
+ modifiedPresentation !== "containedTransparentModal" && {
411
+ backgroundColor: colors.background,
412
+ },
413
+ contentStyle,
414
+ ]}
415
+ headerConfig={headerConfig}
416
+ unstable_sheetFooter={unstable_sheetFooter}
417
+ // When ts-expect-error is added, it affects all the props below it
418
+ // So we keep any props that need it at the end
419
+ // Otherwise invalid props may not be caught by TypeScript
420
+ shouldFreeze={shouldFreeze}
421
+ >
422
+ <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
423
+ <HeaderHeightContext.Provider
424
+ value={
425
+ headerShown !== false ? headerHeight : parentHeaderHeight ?? 0
426
+ }
427
+ >
428
+ {headerBackground != null ? (
429
+ /**
430
+ * To show a custom header background, we render it at the top of the screen below the header
431
+ * The header also needs to be positioned absolutely (with `translucent` style)
432
+ */
433
+ <View
434
+ style={[
435
+ styles.background,
436
+ headerTransparent ? styles.translucent : null,
437
+ { height: headerHeight },
438
+ ]}
439
+ >
440
+ {headerBackground()}
441
+ </View>
442
+ ) : null}
443
+ {header != null && headerShown !== false ? (
444
+ <View
445
+ onLayout={(e) => {
446
+ const headerHeight = e.nativeEvent.layout.height;
447
+
448
+ setHeaderHeight(headerHeight);
449
+ rawAnimatedHeaderHeight.setValue(headerHeight);
450
+ }}
451
+ style={[
452
+ styles.header,
453
+ headerTransparent ? styles.absolute : null,
454
+ ]}
455
+ >
456
+ {header({
457
+ back: headerBack,
458
+ options,
459
+ route,
460
+ navigation,
461
+ })}
462
+ </View>
463
+ ) : null}
464
+ <HeaderShownContext.Provider
465
+ value={isParentHeaderShown || headerShown !== false}
466
+ >
467
+ <HeaderBackContext.Provider value={headerBack}>
468
+ <ScreenTransitionProvider
469
+ previous={previousDescriptor}
470
+ current={descriptor}
471
+ next={nextDescriptor}
472
+ >
473
+ {render()}
474
+ </ScreenTransitionProvider>
475
+ </HeaderBackContext.Provider>
476
+ </HeaderShownContext.Provider>
477
+ </HeaderHeightContext.Provider>
478
+ </AnimatedHeaderHeightContext.Provider>
479
+ </ScreenStackItem>
480
+ </NavigationRouteContext.Provider>
481
+ </NavigationContext.Provider>
482
+ );
483
483
  };
484
484
 
485
485
  type Props = {
486
- state: StackNavigationState<ParamListBase>;
487
- navigation: NativeStackNavigationHelpers;
488
- descriptors: NativeStackDescriptorMap;
489
- describe: (
490
- route: RouteProp<ParamListBase>,
491
- placeholder: boolean,
492
- ) => NativeStackDescriptor;
486
+ state: StackNavigationState<ParamListBase>;
487
+ navigation: NativeStackNavigationHelpers;
488
+ descriptors: NativeStackDescriptorMap;
489
+ describe: (
490
+ route: RouteProp<ParamListBase>,
491
+ placeholder: boolean
492
+ ) => NativeStackDescriptor;
493
493
  };
494
494
 
495
495
  export function NativeStackView({
496
- state,
497
- navigation,
498
- descriptors,
499
- describe,
496
+ state,
497
+ navigation,
498
+ descriptors,
499
+ describe,
500
500
  }: Props) {
501
- const { setNextDismissedKey } = useDismissedRouteError(state);
502
-
503
- useInvalidPreventRemoveError(descriptors);
504
-
505
- const modalRouteKeys = getModalRouteKeys(state.routes, descriptors);
506
-
507
- const preloadedDescriptors =
508
- state.preloadedRoutes.reduce<NativeStackDescriptorMap>((acc, route) => {
509
- acc[route.key] = acc[route.key] || describe(route, true);
510
- return acc;
511
- }, {});
512
-
513
- return (
514
- <SafeAreaProviderCompat>
515
- <ScreenStack style={styles.container}>
516
- {state.routes.concat(state.preloadedRoutes).map((route, index) => {
517
- const descriptor =
518
- descriptors[route.key] ?? preloadedDescriptors[route.key];
519
- const isFocused = state.index === index;
520
- const isBelowFocused = state.index - 1 === index;
521
- const previousKey = state.routes[index - 1]?.key;
522
- const nextKey = state.routes[index + 1]?.key;
523
- const previousDescriptor = previousKey
524
- ? descriptors[previousKey]
525
- : undefined;
526
- const nextDescriptor = nextKey ? descriptors[nextKey] : undefined;
527
-
528
- const isModal = modalRouteKeys.includes(route.key);
529
-
530
- const isPreloaded =
531
- preloadedDescriptors[route.key] !== undefined &&
532
- descriptors[route.key] === undefined;
533
-
534
- // On Fabric, when screen is frozen, animated and reanimated values are not updated
535
- // due to component being unmounted. To avoid this, we don't freeze the previous screen there
536
- const shouldFreeze = isFabric()
537
- ? !isPreloaded && !isFocused && !isBelowFocused
538
- : !isPreloaded && !isFocused;
539
-
540
- return (
541
- <SceneView
542
- key={route.key}
543
- index={index}
544
- focused={isFocused}
545
- shouldFreeze={shouldFreeze}
546
- descriptor={descriptor}
547
- previousDescriptor={previousDescriptor}
548
- nextDescriptor={nextDescriptor}
549
- isPresentationModal={isModal}
550
- isPreloaded={isPreloaded}
551
- onWillDisappear={() => {
552
- navigation.emit({
553
- type: "transitionStart",
554
- data: { closing: true },
555
- target: route.key,
556
- });
557
- }}
558
- onWillAppear={() => {
559
- navigation.emit({
560
- type: "transitionStart",
561
- data: { closing: false },
562
- target: route.key,
563
- });
564
- }}
565
- onAppear={() => {
566
- navigation.emit({
567
- type: "transitionEnd",
568
- data: { closing: false },
569
- target: route.key,
570
- });
571
- }}
572
- onDisappear={() => {
573
- navigation.emit({
574
- type: "transitionEnd",
575
- data: { closing: true },
576
- target: route.key,
577
- });
578
- }}
579
- onDismissed={(event) => {
580
- navigation.dispatch({
581
- ...StackActions.pop(event.nativeEvent.dismissCount),
582
- source: route.key,
583
- target: state.key,
584
- });
585
-
586
- setNextDismissedKey(route.key);
587
- }}
588
- onHeaderBackButtonClicked={() => {
589
- navigation.dispatch({
590
- ...StackActions.pop(),
591
- source: route.key,
592
- target: state.key,
593
- });
594
- }}
595
- onNativeDismissCancelled={(event) => {
596
- navigation.dispatch({
597
- ...StackActions.pop(event.nativeEvent.dismissCount),
598
- source: route.key,
599
- target: state.key,
600
- });
601
- }}
602
- onGestureCancel={() => {
603
- navigation.emit({
604
- type: "gestureCancel",
605
- target: route.key,
606
- });
607
- }}
608
- onSheetDetentChanged={(event) => {
609
- navigation.emit({
610
- type: "sheetDetentChange",
611
- target: route.key,
612
- data: {
613
- index: event.nativeEvent.index,
614
- stable: event.nativeEvent.isStable,
615
- },
616
- });
617
- }}
618
- />
619
- );
620
- })}
621
- </ScreenStack>
622
- </SafeAreaProviderCompat>
623
- );
501
+ const { setNextDismissedKey } = useDismissedRouteError(state);
502
+
503
+ useInvalidPreventRemoveError(descriptors);
504
+
505
+ const modalRouteKeys = getModalRouteKeys(state.routes, descriptors);
506
+
507
+ const preloadedDescriptors =
508
+ state.preloadedRoutes.reduce<NativeStackDescriptorMap>((acc, route) => {
509
+ acc[route.key] = acc[route.key] || describe(route, true);
510
+ return acc;
511
+ }, {});
512
+
513
+ return (
514
+ <SafeAreaProviderCompat>
515
+ <ScreenStack style={styles.container}>
516
+ {state.routes.concat(state.preloadedRoutes).map((route, index) => {
517
+ const descriptor =
518
+ descriptors[route.key] ?? preloadedDescriptors[route.key];
519
+ const isFocused = state.index === index;
520
+ const isBelowFocused = state.index - 1 === index;
521
+ const previousKey = state.routes[index - 1]?.key;
522
+ const nextKey = state.routes[index + 1]?.key;
523
+ const previousDescriptor = previousKey
524
+ ? descriptors[previousKey]
525
+ : undefined;
526
+ const nextDescriptor = nextKey ? descriptors[nextKey] : undefined;
527
+
528
+ const isModal = modalRouteKeys.includes(route.key);
529
+
530
+ const isPreloaded =
531
+ preloadedDescriptors[route.key] !== undefined &&
532
+ descriptors[route.key] === undefined;
533
+
534
+ // On Fabric, when screen is frozen, animated and reanimated values are not updated
535
+ // due to component being unmounted. To avoid this, we don't freeze the previous screen there
536
+ const shouldFreeze = isFabric()
537
+ ? !isPreloaded && !isFocused && !isBelowFocused
538
+ : !isPreloaded && !isFocused;
539
+
540
+ return (
541
+ <SceneView
542
+ key={route.key}
543
+ index={index}
544
+ focused={isFocused}
545
+ shouldFreeze={shouldFreeze}
546
+ descriptor={descriptor}
547
+ previousDescriptor={previousDescriptor}
548
+ nextDescriptor={nextDescriptor}
549
+ isPresentationModal={isModal}
550
+ isPreloaded={isPreloaded}
551
+ onWillDisappear={() => {
552
+ navigation.emit({
553
+ type: "transitionStart",
554
+ data: { closing: true },
555
+ target: route.key,
556
+ });
557
+ }}
558
+ onWillAppear={() => {
559
+ navigation.emit({
560
+ type: "transitionStart",
561
+ data: { closing: false },
562
+ target: route.key,
563
+ });
564
+ }}
565
+ onAppear={() => {
566
+ navigation.emit({
567
+ type: "transitionEnd",
568
+ data: { closing: false },
569
+ target: route.key,
570
+ });
571
+ }}
572
+ onDisappear={() => {
573
+ navigation.emit({
574
+ type: "transitionEnd",
575
+ data: { closing: true },
576
+ target: route.key,
577
+ });
578
+ }}
579
+ onDismissed={(event) => {
580
+ navigation.dispatch({
581
+ ...StackActions.pop(event.nativeEvent.dismissCount),
582
+ source: route.key,
583
+ target: state.key,
584
+ });
585
+
586
+ setNextDismissedKey(route.key);
587
+ }}
588
+ onHeaderBackButtonClicked={() => {
589
+ navigation.dispatch({
590
+ ...StackActions.pop(),
591
+ source: route.key,
592
+ target: state.key,
593
+ });
594
+ }}
595
+ onNativeDismissCancelled={(event) => {
596
+ navigation.dispatch({
597
+ ...StackActions.pop(event.nativeEvent.dismissCount),
598
+ source: route.key,
599
+ target: state.key,
600
+ });
601
+ }}
602
+ onGestureCancel={() => {
603
+ navigation.emit({
604
+ type: "gestureCancel",
605
+ target: route.key,
606
+ });
607
+ }}
608
+ onSheetDetentChanged={(event) => {
609
+ navigation.emit({
610
+ type: "sheetDetentChange",
611
+ target: route.key,
612
+ data: {
613
+ index: event.nativeEvent.index,
614
+ stable: event.nativeEvent.isStable,
615
+ },
616
+ });
617
+ }}
618
+ />
619
+ );
620
+ })}
621
+ </ScreenStack>
622
+ </SafeAreaProviderCompat>
623
+ );
624
624
  }
625
625
 
626
626
  const styles = StyleSheet.create({
627
- container: {
628
- flex: 1,
629
- },
630
- header: {
631
- zIndex: 1,
632
- },
633
- absolute: {
634
- position: "absolute",
635
- top: 0,
636
- start: 0,
637
- end: 0,
638
- },
639
- translucent: {
640
- position: "absolute",
641
- top: 0,
642
- start: 0,
643
- end: 0,
644
- zIndex: 1,
645
- elevation: 1,
646
- },
647
- background: {
648
- overflow: "hidden",
649
- },
627
+ container: {
628
+ flex: 1,
629
+ },
630
+ header: {
631
+ zIndex: 1,
632
+ },
633
+ absolute: {
634
+ position: "absolute",
635
+ top: 0,
636
+ start: 0,
637
+ end: 0,
638
+ },
639
+ translucent: {
640
+ position: "absolute",
641
+ top: 0,
642
+ start: 0,
643
+ end: 0,
644
+ zIndex: 1,
645
+ elevation: 1,
646
+ },
647
+ background: {
648
+ overflow: "hidden",
649
+ },
650
650
  });