react-native-screen-transitions 3.2.0-beta.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/README.md +346 -620
  2. package/lib/commonjs/blank-stack/components/stack-view.js +0 -2
  3. package/lib/commonjs/blank-stack/components/stack-view.js.map +1 -1
  4. package/lib/commonjs/blank-stack/components/stack-view.native.js +0 -2
  5. package/lib/commonjs/blank-stack/components/stack-view.native.js.map +1 -1
  6. package/lib/commonjs/component-stack/components/stack-view.js +16 -20
  7. package/lib/commonjs/component-stack/components/stack-view.js.map +1 -1
  8. package/lib/commonjs/native-stack/views/NativeStackView.native.js +3 -3
  9. package/lib/commonjs/native-stack/views/NativeStackView.native.js.map +1 -1
  10. package/lib/commonjs/shared/components/overlay/variations/float-overlay.js +1 -6
  11. package/lib/commonjs/shared/components/overlay/variations/float-overlay.js.map +1 -1
  12. package/lib/commonjs/shared/components/overlay/variations/overlay-host.js +16 -64
  13. package/lib/commonjs/shared/components/overlay/variations/overlay-host.js.map +1 -1
  14. package/lib/commonjs/shared/components/overlay/variations/screen-overlay.js +5 -8
  15. package/lib/commonjs/shared/components/overlay/variations/screen-overlay.js.map +1 -1
  16. package/lib/commonjs/shared/components/screen-lifecycle.js +29 -0
  17. package/lib/commonjs/shared/components/screen-lifecycle.js.map +1 -0
  18. package/lib/commonjs/shared/constants.js +4 -2
  19. package/lib/commonjs/shared/constants.js.map +1 -1
  20. package/lib/commonjs/shared/hooks/animation/use-screen-animation.js +3 -0
  21. package/lib/commonjs/shared/hooks/animation/use-screen-animation.js.map +1 -1
  22. package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
  23. package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js +127 -0
  24. package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js.map +1 -0
  25. package/lib/commonjs/shared/hooks/lifecycle/use-open-transition.js +35 -0
  26. package/lib/commonjs/shared/hooks/lifecycle/use-open-transition.js.map +1 -0
  27. package/lib/commonjs/shared/hooks/lifecycle/use-screen-events.js +58 -0
  28. package/lib/commonjs/shared/hooks/lifecycle/use-screen-events.js.map +1 -0
  29. package/lib/commonjs/shared/hooks/navigation/use-history.js +24 -0
  30. package/lib/commonjs/shared/hooks/navigation/use-history.js.map +1 -0
  31. package/lib/commonjs/shared/hooks/navigation/use-screen-state.js +45 -0
  32. package/lib/commonjs/shared/hooks/navigation/use-screen-state.js.map +1 -0
  33. package/lib/commonjs/shared/hooks/use-stable-callback-value.js +0 -2
  34. package/lib/commonjs/shared/hooks/use-stable-callback-value.js.map +1 -1
  35. package/lib/commonjs/shared/index.js +14 -0
  36. package/lib/commonjs/shared/index.js.map +1 -1
  37. package/lib/commonjs/shared/providers/screen/keys.provider.js +0 -6
  38. package/lib/commonjs/shared/providers/screen/keys.provider.js.map +1 -1
  39. package/lib/commonjs/shared/providers/screen/screen-composer.js +9 -7
  40. package/lib/commonjs/shared/providers/screen/screen-composer.js.map +1 -1
  41. package/lib/commonjs/shared/providers/screen/styles.provider.js +1 -1
  42. package/lib/commonjs/shared/providers/screen/styles.provider.js.map +1 -1
  43. package/lib/commonjs/shared/providers/stack/direct.provider.js +9 -0
  44. package/lib/commonjs/shared/providers/stack/direct.provider.js.map +1 -1
  45. package/lib/commonjs/shared/providers/stack/managed.provider.js +9 -0
  46. package/lib/commonjs/shared/providers/stack/managed.provider.js.map +1 -1
  47. package/lib/commonjs/shared/stores/animation.store.js +3 -13
  48. package/lib/commonjs/shared/stores/animation.store.js.map +1 -1
  49. package/lib/commonjs/shared/stores/history.store.js +185 -0
  50. package/lib/commonjs/shared/stores/history.store.js.map +1 -0
  51. package/lib/commonjs/shared/types/index.js +3 -3
  52. package/lib/commonjs/shared/types/index.js.map +1 -1
  53. package/lib/commonjs/shared/types/stack.types.js +4 -0
  54. package/lib/commonjs/shared/types/stack.types.js.map +1 -1
  55. package/lib/commonjs/shared/utils/animation/start-screen-transition.js +10 -6
  56. package/lib/commonjs/shared/utils/animation/start-screen-transition.js.map +1 -1
  57. package/lib/commonjs/shared/utils/bounds/index.js +19 -4
  58. package/lib/commonjs/shared/utils/bounds/index.js.map +1 -1
  59. package/lib/module/blank-stack/components/stack-view.js +0 -2
  60. package/lib/module/blank-stack/components/stack-view.js.map +1 -1
  61. package/lib/module/blank-stack/components/stack-view.native.js +0 -2
  62. package/lib/module/blank-stack/components/stack-view.native.js.map +1 -1
  63. package/lib/module/component-stack/components/stack-view.js +16 -20
  64. package/lib/module/component-stack/components/stack-view.js.map +1 -1
  65. package/lib/module/native-stack/views/NativeStackView.native.js +3 -3
  66. package/lib/module/native-stack/views/NativeStackView.native.js.map +1 -1
  67. package/lib/module/shared/components/overlay/variations/float-overlay.js +1 -6
  68. package/lib/module/shared/components/overlay/variations/float-overlay.js.map +1 -1
  69. package/lib/module/shared/components/overlay/variations/overlay-host.js +16 -64
  70. package/lib/module/shared/components/overlay/variations/overlay-host.js.map +1 -1
  71. package/lib/module/shared/components/overlay/variations/screen-overlay.js +5 -8
  72. package/lib/module/shared/components/overlay/variations/screen-overlay.js.map +1 -1
  73. package/lib/module/shared/components/screen-lifecycle.js +24 -0
  74. package/lib/module/shared/components/screen-lifecycle.js.map +1 -0
  75. package/lib/module/shared/constants.js +3 -1
  76. package/lib/module/shared/constants.js.map +1 -1
  77. package/lib/module/shared/hooks/animation/use-screen-animation.js +3 -0
  78. package/lib/module/shared/hooks/animation/use-screen-animation.js.map +1 -1
  79. package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
  80. package/lib/module/shared/hooks/lifecycle/use-close-transition.js +122 -0
  81. package/lib/module/shared/hooks/lifecycle/use-close-transition.js.map +1 -0
  82. package/lib/module/shared/hooks/lifecycle/use-open-transition.js +32 -0
  83. package/lib/module/shared/hooks/lifecycle/use-open-transition.js.map +1 -0
  84. package/lib/module/shared/hooks/lifecycle/use-screen-events.js +54 -0
  85. package/lib/module/shared/hooks/lifecycle/use-screen-events.js.map +1 -0
  86. package/lib/module/shared/hooks/navigation/use-history.js +20 -0
  87. package/lib/module/shared/hooks/navigation/use-history.js.map +1 -0
  88. package/lib/module/shared/hooks/navigation/use-screen-state.js +41 -0
  89. package/lib/module/shared/hooks/navigation/use-screen-state.js.map +1 -0
  90. package/lib/module/shared/hooks/use-stable-callback-value.js +0 -3
  91. package/lib/module/shared/hooks/use-stable-callback-value.js.map +1 -1
  92. package/lib/module/shared/index.js +2 -0
  93. package/lib/module/shared/index.js.map +1 -1
  94. package/lib/module/shared/providers/screen/keys.provider.js +0 -6
  95. package/lib/module/shared/providers/screen/keys.provider.js.map +1 -1
  96. package/lib/module/shared/providers/screen/screen-composer.js +9 -7
  97. package/lib/module/shared/providers/screen/screen-composer.js.map +1 -1
  98. package/lib/module/shared/providers/screen/styles.provider.js +1 -1
  99. package/lib/module/shared/providers/screen/styles.provider.js.map +1 -1
  100. package/lib/module/shared/providers/stack/direct.provider.js +10 -1
  101. package/lib/module/shared/providers/stack/direct.provider.js.map +1 -1
  102. package/lib/module/shared/providers/stack/managed.provider.js +10 -1
  103. package/lib/module/shared/providers/stack/managed.provider.js.map +1 -1
  104. package/lib/module/shared/stores/animation.store.js +4 -14
  105. package/lib/module/shared/stores/animation.store.js.map +1 -1
  106. package/lib/module/shared/stores/history.store.js +181 -0
  107. package/lib/module/shared/stores/history.store.js.map +1 -0
  108. package/lib/module/shared/types/index.js +1 -1
  109. package/lib/module/shared/types/index.js.map +1 -1
  110. package/lib/module/shared/types/stack.types.js +5 -0
  111. package/lib/module/shared/types/stack.types.js.map +1 -1
  112. package/lib/module/shared/utils/animation/start-screen-transition.js +6 -2
  113. package/lib/module/shared/utils/animation/start-screen-transition.js.map +1 -1
  114. package/lib/module/shared/utils/bounds/index.js +19 -4
  115. package/lib/module/shared/utils/bounds/index.js.map +1 -1
  116. package/lib/typescript/blank-stack/components/stack-view.d.ts.map +1 -1
  117. package/lib/typescript/blank-stack/components/stack-view.native.d.ts.map +1 -1
  118. package/lib/typescript/blank-stack/types.d.ts +1 -8
  119. package/lib/typescript/blank-stack/types.d.ts.map +1 -1
  120. package/lib/typescript/component-stack/components/stack-view.d.ts.map +1 -1
  121. package/lib/typescript/component-stack/types.d.ts +1 -8
  122. package/lib/typescript/component-stack/types.d.ts.map +1 -1
  123. package/lib/typescript/native-stack/types.d.ts +2 -3
  124. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  125. package/lib/typescript/native-stack/views/NativeStackView.native.d.ts.map +1 -1
  126. package/lib/typescript/shared/components/overlay/variations/float-overlay.d.ts.map +1 -1
  127. package/lib/typescript/shared/components/overlay/variations/overlay-host.d.ts +1 -6
  128. package/lib/typescript/shared/components/overlay/variations/overlay-host.d.ts.map +1 -1
  129. package/lib/typescript/shared/components/overlay/variations/screen-overlay.d.ts +4 -0
  130. package/lib/typescript/shared/components/overlay/variations/screen-overlay.d.ts.map +1 -1
  131. package/lib/typescript/shared/components/screen-lifecycle.d.ts +12 -0
  132. package/lib/typescript/shared/components/screen-lifecycle.d.ts.map +1 -0
  133. package/lib/typescript/shared/constants.d.ts +2 -1
  134. package/lib/typescript/shared/constants.d.ts.map +1 -1
  135. package/lib/typescript/shared/hooks/animation/use-screen-animation.d.ts.map +1 -1
  136. package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts.map +1 -1
  137. package/lib/typescript/shared/hooks/lifecycle/use-close-transition.d.ts +13 -0
  138. package/lib/typescript/shared/hooks/lifecycle/use-close-transition.d.ts.map +1 -0
  139. package/lib/typescript/shared/hooks/lifecycle/use-open-transition.d.ts +11 -0
  140. package/lib/typescript/shared/hooks/lifecycle/use-open-transition.d.ts.map +1 -0
  141. package/lib/typescript/shared/hooks/lifecycle/use-screen-events.d.ts +7 -0
  142. package/lib/typescript/shared/hooks/lifecycle/use-screen-events.d.ts.map +1 -0
  143. package/lib/typescript/shared/hooks/navigation/use-history.d.ts +37 -0
  144. package/lib/typescript/shared/hooks/navigation/use-history.d.ts.map +1 -0
  145. package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts +40 -0
  146. package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts.map +1 -0
  147. package/lib/typescript/shared/hooks/use-stable-callback-value.d.ts.map +1 -1
  148. package/lib/typescript/shared/index.d.ts +22 -20
  149. package/lib/typescript/shared/index.d.ts.map +1 -1
  150. package/lib/typescript/shared/providers/screen/keys.provider.d.ts +2 -9
  151. package/lib/typescript/shared/providers/screen/keys.provider.d.ts.map +1 -1
  152. package/lib/typescript/shared/providers/screen/screen-composer.d.ts +1 -3
  153. package/lib/typescript/shared/providers/screen/screen-composer.d.ts.map +1 -1
  154. package/lib/typescript/shared/providers/stack/direct.provider.d.ts.map +1 -1
  155. package/lib/typescript/shared/providers/stack/managed.provider.d.ts.map +1 -1
  156. package/lib/typescript/shared/stores/animation.store.d.ts +3 -4
  157. package/lib/typescript/shared/stores/animation.store.d.ts.map +1 -1
  158. package/lib/typescript/shared/stores/history.store.d.ts +82 -0
  159. package/lib/typescript/shared/stores/history.store.d.ts.map +1 -0
  160. package/lib/typescript/shared/types/animation.types.d.ts +10 -6
  161. package/lib/typescript/shared/types/animation.types.d.ts.map +1 -1
  162. package/lib/typescript/shared/types/bounds.types.d.ts +1 -1
  163. package/lib/typescript/shared/types/bounds.types.d.ts.map +1 -1
  164. package/lib/typescript/shared/types/index.d.ts +2 -2
  165. package/lib/typescript/shared/types/index.d.ts.map +1 -1
  166. package/lib/typescript/shared/types/overlay.types.d.ts +21 -0
  167. package/lib/typescript/shared/types/overlay.types.d.ts.map +1 -1
  168. package/lib/typescript/shared/types/screen.types.d.ts +5 -4
  169. package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
  170. package/lib/typescript/shared/types/stack.types.d.ts +10 -0
  171. package/lib/typescript/shared/types/stack.types.d.ts.map +1 -1
  172. package/lib/typescript/shared/utils/animation/start-screen-transition.d.ts.map +1 -1
  173. package/lib/typescript/shared/utils/bounds/index.d.ts.map +1 -1
  174. package/package.json +1 -1
  175. package/src/blank-stack/components/stack-view.native.tsx +0 -2
  176. package/src/blank-stack/components/stack-view.tsx +0 -2
  177. package/src/blank-stack/types.ts +0 -10
  178. package/src/component-stack/components/stack-view.tsx +19 -23
  179. package/src/component-stack/types.ts +0 -10
  180. package/src/native-stack/types.ts +2 -3
  181. package/src/native-stack/views/NativeStackView.native.tsx +2 -3
  182. package/src/shared/__tests__/history.store.test.ts +550 -0
  183. package/src/shared/components/overlay/variations/float-overlay.tsx +2 -8
  184. package/src/shared/components/overlay/variations/overlay-host.tsx +18 -84
  185. package/src/shared/components/overlay/variations/screen-overlay.tsx +6 -15
  186. package/src/shared/components/screen-lifecycle.tsx +32 -0
  187. package/src/shared/constants.ts +4 -1
  188. package/src/shared/hooks/animation/use-screen-animation.tsx +7 -3
  189. package/src/shared/hooks/gestures/use-build-gestures.tsx +0 -2
  190. package/src/shared/hooks/lifecycle/use-close-transition.ts +147 -0
  191. package/src/shared/hooks/lifecycle/use-open-transition.ts +30 -0
  192. package/src/shared/hooks/lifecycle/use-screen-events.ts +62 -0
  193. package/src/shared/hooks/navigation/use-history.ts +63 -0
  194. package/src/shared/hooks/navigation/use-screen-state.tsx +99 -0
  195. package/src/shared/hooks/use-stable-callback-value.ts +0 -1
  196. package/src/shared/index.ts +5 -0
  197. package/src/shared/providers/screen/keys.provider.tsx +1 -25
  198. package/src/shared/providers/screen/screen-composer.tsx +7 -13
  199. package/src/shared/providers/screen/styles.provider.tsx +1 -1
  200. package/src/shared/providers/stack/direct.provider.tsx +11 -1
  201. package/src/shared/providers/stack/managed.provider.tsx +11 -1
  202. package/src/shared/stores/animation.store.ts +6 -20
  203. package/src/shared/stores/history.store.ts +201 -0
  204. package/src/shared/types/animation.types.ts +11 -6
  205. package/src/shared/types/bounds.types.ts +1 -0
  206. package/src/shared/types/index.ts +2 -7
  207. package/src/shared/types/overlay.types.ts +23 -0
  208. package/src/shared/types/screen.types.ts +5 -4
  209. package/src/shared/types/stack.types.ts +17 -1
  210. package/src/shared/utils/animation/start-screen-transition.ts +5 -2
  211. package/src/shared/utils/bounds/index.ts +35 -4
  212. package/lib/commonjs/native-stack/controllers/native-stack-lifecycle.js +0 -90
  213. package/lib/commonjs/native-stack/controllers/native-stack-lifecycle.js.map +0 -1
  214. package/lib/commonjs/shared/controller/managed-lifecycle.js +0 -78
  215. package/lib/commonjs/shared/controller/managed-lifecycle.js.map +0 -1
  216. package/lib/commonjs/shared/types/state.types.js +0 -9
  217. package/lib/commonjs/shared/types/state.types.js.map +0 -1
  218. package/lib/commonjs/shared/utils/read-shared-value.js +0 -17
  219. package/lib/commonjs/shared/utils/read-shared-value.js.map +0 -1
  220. package/lib/module/native-stack/controllers/native-stack-lifecycle.js +0 -83
  221. package/lib/module/native-stack/controllers/native-stack-lifecycle.js.map +0 -1
  222. package/lib/module/shared/controller/managed-lifecycle.js +0 -72
  223. package/lib/module/shared/controller/managed-lifecycle.js.map +0 -1
  224. package/lib/module/shared/types/state.types.js +0 -5
  225. package/lib/module/shared/types/state.types.js.map +0 -1
  226. package/lib/module/shared/utils/read-shared-value.js +0 -14
  227. package/lib/module/shared/utils/read-shared-value.js.map +0 -1
  228. package/lib/typescript/native-stack/controllers/native-stack-lifecycle.d.ts +0 -8
  229. package/lib/typescript/native-stack/controllers/native-stack-lifecycle.d.ts.map +0 -1
  230. package/lib/typescript/shared/controller/managed-lifecycle.d.ts +0 -9
  231. package/lib/typescript/shared/controller/managed-lifecycle.d.ts.map +0 -1
  232. package/lib/typescript/shared/types/state.types.d.ts +0 -3
  233. package/lib/typescript/shared/types/state.types.d.ts.map +0 -1
  234. package/lib/typescript/shared/utils/read-shared-value.d.ts +0 -7
  235. package/lib/typescript/shared/utils/read-shared-value.d.ts.map +0 -1
  236. package/src/native-stack/controllers/native-stack-lifecycle.tsx +0 -96
  237. package/src/shared/controller/managed-lifecycle.tsx +0 -73
  238. package/src/shared/types/state.types.ts +0 -2
  239. package/src/shared/utils/read-shared-value.ts +0 -15
@@ -0,0 +1,99 @@
1
+ import type { Route } from "@react-navigation/native";
2
+ import { useMemo } from "react";
3
+ import { useDerivedValue } from "react-native-reanimated";
4
+ import {
5
+ type BaseDescriptor,
6
+ useKeys,
7
+ } from "../../providers/screen/keys.provider";
8
+ import type { ScreenTransitionConfig } from "../../types/screen.types";
9
+ import type { BaseStackNavigation } from "../../types/stack.types";
10
+ import { useSharedValueState } from "../reanimated/use-shared-value-state";
11
+ import { type StackContextValue, useStack } from "./use-stack";
12
+
13
+ export interface ScreenState<
14
+ TNavigation extends BaseStackNavigation = BaseStackNavigation,
15
+ > {
16
+ /**
17
+ * The index of this screen in the stack.
18
+ */
19
+ index: number;
20
+
21
+ /**
22
+ * Screen options for the currently focused screen.
23
+ */
24
+ options: ScreenTransitionConfig;
25
+
26
+ /**
27
+ * All routes currently in the stack.
28
+ */
29
+ routes: Route<string>[];
30
+
31
+ /**
32
+ * Route of the currently focused screen in the stack.
33
+ */
34
+ focusedRoute: Route<string>;
35
+
36
+ /**
37
+ * Index of the focused route in the stack.
38
+ */
39
+ focusedIndex: number;
40
+
41
+ /**
42
+ * Custom metadata from the focused screen's options.
43
+ */
44
+ meta?: Record<string, unknown>;
45
+
46
+ /**
47
+ * Navigation object for this screen.
48
+ */
49
+ navigation: TNavigation;
50
+ }
51
+
52
+ /**
53
+ * Hook to access screen state information.
54
+ *
55
+ * Use this hook to get navigation state and screen information.
56
+ */
57
+ export function useScreenState<
58
+ TNavigation extends BaseStackNavigation = BaseStackNavigation,
59
+ >(): ScreenState<TNavigation> {
60
+ const { routes, scenes, routeKeys, optimisticFocusedIndex } =
61
+ useStack<StackContextValue>();
62
+ const { current } = useKeys<BaseDescriptor>();
63
+
64
+ const index = useMemo(
65
+ () => routeKeys.indexOf(current.route.key),
66
+ [routeKeys, current.route.key],
67
+ );
68
+
69
+ const focusedIndex = useSharedValueState(
70
+ useDerivedValue(() => {
71
+ const globalIndex = optimisticFocusedIndex.get();
72
+ return Math.max(0, Math.min(globalIndex, routeKeys.length - 1));
73
+ }),
74
+ );
75
+
76
+ const focusedScene = useMemo(() => {
77
+ return scenes[focusedIndex] ?? scenes[scenes.length - 1];
78
+ }, [scenes, focusedIndex]);
79
+
80
+ return useMemo(
81
+ () => ({
82
+ index,
83
+ options: focusedScene?.descriptor?.options ?? {},
84
+ routes,
85
+ focusedRoute: focusedScene?.route ?? current.route,
86
+ focusedIndex,
87
+ meta: focusedScene?.descriptor?.options?.meta,
88
+ navigation: current.navigation as TNavigation,
89
+ }),
90
+ [
91
+ index,
92
+ focusedScene,
93
+ routes,
94
+ focusedIndex,
95
+ current.navigation,
96
+ current.route,
97
+ ],
98
+ );
99
+ }
@@ -10,7 +10,6 @@ import {
10
10
  runOnJS,
11
11
  } from "react-native-reanimated";
12
12
 
13
- // biome-ignore lint/suspicious/noExplicitAny: <Does not matter>
14
13
  type AnyFunction = (...args: Array<any>) => any;
15
14
 
16
15
  function useMutableValue<T>(initialValue: T) {
@@ -20,6 +20,11 @@ export default {
20
20
 
21
21
  export { useScreenAnimation } from "./hooks/animation/use-screen-animation";
22
22
  export { useScreenGesture } from "./hooks/gestures/use-screen-gesture";
23
+ export { useHistory } from "./hooks/navigation/use-history";
24
+ export {
25
+ type ScreenState,
26
+ useScreenState,
27
+ } from "./hooks/navigation/use-screen-state";
23
28
 
24
29
  export type {
25
30
  AnimationConfig,
@@ -1,20 +1,5 @@
1
- import type {
2
- Descriptor,
3
- NavigationProp,
4
- ParamListBase,
5
- RouteProp,
6
- } from "@react-navigation/native";
7
1
  import { createContext, useContext, useMemo } from "react";
8
- import type { ScreenTransitionConfig } from "../../types/screen.types";
9
- import type {
10
- BaseStackDescriptor,
11
- BaseStackNavigation,
12
- BaseStackRoute,
13
- } from "../../types/stack.types";
14
-
15
- // Re-export for backward compatibility
16
- export type { BaseStackNavigation as BaseNavigation };
17
- export type { BaseStackRoute as BaseRoute };
2
+ import type { BaseStackDescriptor } from "../../types/stack.types";
18
3
 
19
4
  /**
20
5
  * Base descriptor interface - minimal contract for all stack types.
@@ -23,15 +8,6 @@ export type { BaseStackRoute as BaseRoute };
23
8
  */
24
9
  export type BaseDescriptor = BaseStackDescriptor;
25
10
 
26
- /**
27
- * React Navigation specific descriptor - extends base with full typing
28
- */
29
- export type TransitionDescriptor = Descriptor<
30
- ScreenTransitionConfig,
31
- NavigationProp<ParamListBase>,
32
- RouteProp<ParamListBase>
33
- >;
34
-
35
11
  interface KeysContextType<TDescriptor extends BaseDescriptor = BaseDescriptor> {
36
12
  previous?: TDescriptor;
37
13
  current: TDescriptor;
@@ -1,6 +1,6 @@
1
1
  import type React from "react";
2
- import type { ComponentType } from "react";
3
2
  import { RootTransitionAware } from "../../components/root-transition-aware";
3
+ import { ScreenLifecycle } from "../../components/screen-lifecycle";
4
4
  import { ScreenGestureProvider } from "../gestures.provider";
5
5
  import { type BaseDescriptor, KeysProvider } from "./keys.provider";
6
6
  import { ScreenStylesProvider } from "./styles.provider";
@@ -10,7 +10,6 @@ type Props<TDescriptor extends BaseDescriptor> = {
10
10
  current: TDescriptor;
11
11
  next?: TDescriptor;
12
12
  children: React.ReactNode;
13
- LifecycleController: ComponentType<any>;
14
13
  };
15
14
 
16
15
  export function ScreenComposer<TDescriptor extends BaseDescriptor>({
@@ -18,21 +17,16 @@ export function ScreenComposer<TDescriptor extends BaseDescriptor>({
18
17
  current,
19
18
  next,
20
19
  children,
21
- LifecycleController,
22
20
  }: Props<TDescriptor>) {
23
21
  return (
24
- <KeysProvider<TDescriptor>
25
- previous={previous}
26
- current={current}
27
- next={next}
28
- >
29
- <ScreenGestureProvider>
30
- <LifecycleController>
22
+ <ScreenLifecycle current={current} previous={previous}>
23
+ <KeysProvider previous={previous} current={current} next={next}>
24
+ <ScreenGestureProvider>
31
25
  <ScreenStylesProvider>
32
26
  <RootTransitionAware>{children}</RootTransitionAware>
33
27
  </ScreenStylesProvider>
34
- </LifecycleController>
35
- </ScreenGestureProvider>
36
- </KeysProvider>
28
+ </ScreenGestureProvider>
29
+ </KeysProvider>
30
+ </ScreenLifecycle>
37
31
  );
38
32
  }
@@ -113,7 +113,7 @@ export function useScreenStyles() {
113
113
  const ctx = useContext(ScreenStylesContext);
114
114
  if (!ctx) {
115
115
  throw new Error(
116
- "useTransitionStyles must be used within a TransitionStylesProvider",
116
+ "useScreenStyles must be used within a ScreenStylesProvider",
117
117
  );
118
118
  }
119
119
  return ctx;
@@ -4,7 +4,7 @@ import type {
4
4
  StackNavigationState,
5
5
  } from "@react-navigation/native";
6
6
  import * as React from "react";
7
- import { useMemo } from "react";
7
+ import { useEffect, useMemo } from "react";
8
8
  import { type DerivedValue, useDerivedValue } from "react-native-reanimated";
9
9
  import type {
10
10
  NativeStackDescriptor,
@@ -16,6 +16,7 @@ import {
16
16
  type StackContextValue,
17
17
  } from "../../hooks/navigation/use-stack";
18
18
  import { AnimationStore } from "../../stores/animation.store";
19
+ import { HistoryStore } from "../../stores/history.store";
19
20
  import { useStackCoreContext } from "./core.provider";
20
21
 
21
22
  export interface DirectStackScene {
@@ -216,6 +217,15 @@ function withDirectStack<TProps extends DirectStackProps>(
216
217
  Component: React.ComponentType<DirectStackContextValue>,
217
218
  ): React.FC<TProps> {
218
219
  return function DirectStackProvider(props: TProps) {
220
+ const navigatorKey = props.state.key;
221
+
222
+ // Clean up history when navigator unmounts
223
+ useEffect(() => {
224
+ return () => {
225
+ HistoryStore.clearNavigator(navigatorKey);
226
+ };
227
+ }, [navigatorKey]);
228
+
219
229
  const { stackContextValue, ...lifecycleValue } = useDirectStackValue(props);
220
230
 
221
231
  return (
@@ -1,6 +1,6 @@
1
1
  import type { Route } from "@react-navigation/native";
2
2
  import * as React from "react";
3
- import { useMemo } from "react";
3
+ import { useEffect, useMemo } from "react";
4
4
  import {
5
5
  type DerivedValue,
6
6
  type SharedValue,
@@ -11,6 +11,7 @@ import {
11
11
  type StackContextValue,
12
12
  } from "../../hooks/navigation/use-stack";
13
13
  import { AnimationStore } from "../../stores/animation.store";
14
+ import { HistoryStore } from "../../stores/history.store";
14
15
  import type {
15
16
  BaseStackDescriptor,
16
17
  BaseStackNavigation,
@@ -211,6 +212,15 @@ function withManagedStack<
211
212
  return function ManagedStackProvider(
212
213
  props: ManagedStackProps<TDescriptor, TNavigation>,
213
214
  ) {
215
+ const navigatorKey = props.state.key;
216
+
217
+ // Clean up history when navigator unmounts
218
+ useEffect(() => {
219
+ return () => {
220
+ HistoryStore.clearNavigator(navigatorKey);
221
+ };
222
+ }, [navigatorKey]);
223
+
214
224
  const { stackContextValue, ...lifecycleValue } = useManagedStackValue<
215
225
  TDescriptor,
216
226
  TNavigation
@@ -1,14 +1,11 @@
1
- import {
2
- cancelAnimation,
3
- makeMutable,
4
- type SharedValue,
5
- } from "react-native-reanimated";
1
+ import { makeMutable, type SharedValue } from "react-native-reanimated";
6
2
  import type { ScreenKey } from "../types/screen.types";
7
3
 
8
4
  export type AnimationStoreMap = {
9
5
  progress: SharedValue<number>;
10
- closing: SharedValue<number>;
11
6
  animating: SharedValue<number>;
7
+ closing: SharedValue<number>;
8
+ entering: SharedValue<number>;
12
9
  };
13
10
 
14
11
  const store: Record<ScreenKey, AnimationStoreMap> = {};
@@ -20,7 +17,8 @@ const ensure = (key: ScreenKey) => {
20
17
  progress: makeMutable(0),
21
18
  closing: makeMutable(0),
22
19
  animating: makeMutable(0),
23
- };
20
+ entering: makeMutable(1),
21
+ } satisfies AnimationStoreMap;
24
22
  store[key] = bag;
25
23
  }
26
24
  return bag;
@@ -28,7 +26,7 @@ const ensure = (key: ScreenKey) => {
28
26
 
29
27
  function getAnimation(
30
28
  key: ScreenKey,
31
- type: "progress" | "closing" | "animating",
29
+ type: keyof AnimationStoreMap,
32
30
  ): SharedValue<number> {
33
31
  return ensure(key)[type];
34
32
  }
@@ -39,23 +37,11 @@ function getAll(key: ScreenKey) {
39
37
 
40
38
  function clear(routeKey: ScreenKey) {
41
39
  "worklet";
42
- const bag = store[routeKey];
43
- if (bag) {
44
- cancelAnimation(bag.progress);
45
- cancelAnimation(bag.closing);
46
- cancelAnimation(bag.animating);
47
- }
48
40
  delete store[routeKey];
49
41
  }
50
42
 
51
- function debugStoreSize() {
52
- console.log("[AnimationStore] Size:", Object.keys(store).length);
53
- console.log("[AnimationStore] Keys:", Object.keys(store));
54
- }
55
-
56
43
  export const AnimationStore = {
57
44
  getAnimation,
58
45
  clear,
59
46
  getAll,
60
- debugStoreSize,
61
47
  };
@@ -0,0 +1,201 @@
1
+ import type { ScreenKey } from "../types/screen.types";
2
+ import type { BaseStackDescriptor } from "../types/stack.types";
3
+
4
+ const HISTORY_LIMIT = 100;
5
+
6
+ interface HistoryEntry {
7
+ descriptor: BaseStackDescriptor;
8
+ navigatorKey: string;
9
+ timestamp: number;
10
+ }
11
+
12
+ // Map preserves insertion order - index 0 = oldest, last = most recent
13
+ const history = new Map<ScreenKey, HistoryEntry>();
14
+ const listeners = new Set<() => void>();
15
+
16
+ // Cached snapshot for useSyncExternalStore
17
+ let cachedSnapshot: ReadonlyMap<ScreenKey, HistoryEntry> = history;
18
+
19
+ function updateSnapshot(): void {
20
+ cachedSnapshot = new Map(history);
21
+ }
22
+
23
+ function notifyListeners(): void {
24
+ updateSnapshot();
25
+ listeners.forEach((listener) => {
26
+ listener();
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Subscribe for useSyncExternalStore compatibility
32
+ */
33
+ function subscribe(listener: () => void): () => void {
34
+ listeners.add(listener);
35
+ return () => listeners.delete(listener);
36
+ }
37
+
38
+ /**
39
+ * Get current snapshot for useSyncExternalStore
40
+ */
41
+ function getSnapshot(): ReadonlyMap<ScreenKey, HistoryEntry> {
42
+ return cachedSnapshot;
43
+ }
44
+
45
+ /**
46
+ * Add or move screen to top (most recent).
47
+ * LRU behavior: if exists, delete and re-add to move to end.
48
+ * @param descriptor - The screen descriptor
49
+ * @param navigatorKey - The navigator's key (for cleanup on unmount)
50
+ * @param historyKey - Optional custom key (defaults to navigatorKey:routeName)
51
+ */
52
+ function focus(
53
+ descriptor: BaseStackDescriptor,
54
+ navigatorKey: string,
55
+ historyKey?: ScreenKey,
56
+ ): void {
57
+ const key = historyKey ?? `${navigatorKey}:${descriptor.route.name}`;
58
+
59
+ // Delete first (if exists) to reset position - this is the LRU "move to top"
60
+ history.delete(key);
61
+
62
+ // Add to end (most recent)
63
+ history.set(key, {
64
+ descriptor,
65
+ navigatorKey,
66
+ timestamp: Date.now(),
67
+ });
68
+
69
+ // Evict oldest if over limit
70
+ while (history.size > HISTORY_LIMIT) {
71
+ const oldestKey = history.keys().next().value;
72
+ if (oldestKey) {
73
+ history.delete(oldestKey);
74
+ }
75
+ }
76
+
77
+ notifyListeners();
78
+ }
79
+
80
+ /**
81
+ * Get most recent entry (for forward nav).
82
+ */
83
+ function getMostRecent(): HistoryEntry | undefined {
84
+ const entries = Array.from(history.values());
85
+ return entries[entries.length - 1];
86
+ }
87
+
88
+ /**
89
+ * Get N most recent entries (most recent first).
90
+ */
91
+ function getRecent(n: number): HistoryEntry[] {
92
+ const entries = Array.from(history.values());
93
+ return entries.slice(-n).reverse();
94
+ }
95
+
96
+ /**
97
+ * Get entry by key.
98
+ */
99
+ function get(key: ScreenKey): HistoryEntry | undefined {
100
+ return history.get(key);
101
+ }
102
+
103
+ /**
104
+ * Check if key exists.
105
+ */
106
+ function has(key: ScreenKey): boolean {
107
+ return history.has(key);
108
+ }
109
+
110
+ /**
111
+ * Get all entries for a navigator (in recency order, most recent first).
112
+ */
113
+ function getByNavigator(navigatorKey: string): HistoryEntry[] {
114
+ const entries: HistoryEntry[] = [];
115
+ for (const entry of history.values()) {
116
+ if (entry.navigatorKey === navigatorKey) {
117
+ entries.push(entry);
118
+ }
119
+ }
120
+ return entries.reverse();
121
+ }
122
+
123
+ /**
124
+ * Get path between two screens (for multi-waypoint interpolation).
125
+ * Returns keys in order from 'from' to 'to'.
126
+ */
127
+ function getPath(fromKey: ScreenKey, toKey: ScreenKey): ScreenKey[] {
128
+ const keys = Array.from(history.keys());
129
+ const fromIndex = keys.indexOf(fromKey);
130
+ const toIndex = keys.indexOf(toKey);
131
+
132
+ if (fromIndex < 0 || toIndex < 0) return [];
133
+
134
+ const start = Math.min(fromIndex, toIndex);
135
+ const end = Math.max(fromIndex, toIndex);
136
+ const path = keys.slice(start, end + 1);
137
+
138
+ // Return in correct direction
139
+ return fromIndex > toIndex ? path.reverse() : path;
140
+ }
141
+
142
+ /**
143
+ * Clear all entries for a navigator (on unmount).
144
+ */
145
+ function clearNavigator(navigatorKey: string): void {
146
+ const keysToRemove: ScreenKey[] = [];
147
+ for (const [key, entry] of history.entries()) {
148
+ if (entry.navigatorKey === navigatorKey) {
149
+ keysToRemove.push(key);
150
+ }
151
+ }
152
+
153
+ if (keysToRemove.length > 0) {
154
+ for (const key of keysToRemove) {
155
+ history.delete(key);
156
+ }
157
+ notifyListeners();
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Get current size of history.
163
+ */
164
+ function size(): number {
165
+ return history.size;
166
+ }
167
+
168
+ /**
169
+ * Convert to array (in recency order, oldest first).
170
+ */
171
+ function toArray(): HistoryEntry[] {
172
+ return Array.from(history.values());
173
+ }
174
+
175
+ /**
176
+ * Clear all history entries (for testing).
177
+ * @internal
178
+ */
179
+ function _reset(): void {
180
+ history.clear();
181
+ listeners.clear();
182
+ cachedSnapshot = new Map();
183
+ }
184
+
185
+ export const HistoryStore = {
186
+ focus,
187
+ getMostRecent,
188
+ getRecent,
189
+ get,
190
+ has,
191
+ getByNavigator,
192
+ getPath,
193
+ clearNavigator,
194
+ size,
195
+ toArray,
196
+ subscribe,
197
+ getSnapshot,
198
+ _reset,
199
+ };
200
+
201
+ export type { HistoryEntry };
@@ -4,10 +4,10 @@ import type {
4
4
  WithTimingConfig,
5
5
  } from "react-native-reanimated";
6
6
  import type { EdgeInsets } from "react-native-safe-area-context";
7
- import type { BaseRoute } from "../providers/screen/keys.provider";
8
7
  import type { BoundsAccessor } from "./bounds.types";
9
8
  import type { GestureValues } from "./gesture.types";
10
9
  import type { Layout } from "./screen.types";
10
+ import type { BaseStackRoute } from "./stack.types";
11
11
 
12
12
  export interface OverlayInterpolationProps {
13
13
  progress: number;
@@ -40,6 +40,15 @@ export type ScreenTransitionState = {
40
40
  */
41
41
  closing: number;
42
42
 
43
+ /**
44
+ * Whether this screen is in the process of entering.
45
+ * - `0`: Screen is closing or inactive
46
+ * - `1`: Screen is opening/entering
47
+ *
48
+ * Use this to trigger different animations when navigating back vs forward.
49
+ */
50
+ entering: number;
51
+
43
52
  /**
44
53
  * Whether this screen is currently animating.
45
54
  * - `0`: No animation in progress
@@ -69,12 +78,8 @@ export type ScreenTransitionState = {
69
78
 
70
79
  /**
71
80
  * The route object for this screen.
72
- *
73
- * @deprecated Use `meta` instead for conditional animation logic.
74
- * Pass route params via options: `options={({ route }) => ({ meta: { id: route.params.id } })}`
75
- * This field may be removed in a future version.
76
81
  */
77
- route: BaseRoute;
82
+ route: BaseStackRoute;
78
83
  };
79
84
 
80
85
  export interface ScreenInterpolationProps {
@@ -36,6 +36,7 @@ export type BoundsAccessor = {
36
36
  interpolateBounds: (
37
37
  id: string,
38
38
  property: keyof MeasuredDimensions,
39
+ fallbackOrTargetKey?: number | string,
39
40
  fallback?: number,
40
41
  ) => number;
41
42
  };
@@ -1,3 +1,4 @@
1
+ export { FALSE, TRUE } from "../constants";
1
2
  export type {
2
3
  AnimationConfig,
3
4
  OverlayInterpolationProps,
@@ -7,14 +8,12 @@ export type {
7
8
  TransitionInterpolatedStyle,
8
9
  TransitionSpec,
9
10
  } from "./animation.types";
10
-
11
11
  export type {
12
12
  BoundEntry,
13
13
  BoundsAccessor,
14
14
  BoundsLink,
15
15
  BoundsMethod,
16
16
  } from "./bounds.types";
17
-
18
17
  export type {
19
18
  ActivationArea,
20
19
  GestureActivationArea,
@@ -22,25 +21,21 @@ export type {
22
21
  GestureValues,
23
22
  SideActivation,
24
23
  } from "./gesture.types";
25
-
26
24
  export type {
27
25
  OverlayMode,
28
26
  OverlayProps,
29
27
  } from "./overlay.types";
30
-
31
28
  export type {
32
29
  Layout,
33
30
  ScreenKey,
34
31
  ScreenTransitionConfig,
35
32
  TransitionAwareProps,
36
33
  } from "./screen.types";
37
-
38
34
  export type {
39
35
  BaseStackDescriptor,
40
36
  BaseStackNavigation,
41
37
  BaseStackRoute,
42
38
  BaseStackScene,
43
39
  BaseStackState,
40
+ DescriptorMap,
44
41
  } from "./stack.types";
45
-
46
- export { FALSE, TRUE } from "./state.types";
@@ -4,7 +4,13 @@ import type {
4
4
  OverlayInterpolationProps,
5
5
  ScreenInterpolationProps,
6
6
  } from "./animation.types";
7
+ import type { ScreenTransitionConfig } from "./screen.types";
7
8
 
9
+ /**
10
+ * @deprecated Overlay mode is no longer needed. Overlays now always render as "float" mode.
11
+ * For per-screen overlays, render an absolute-positioned view directly in your screen component
12
+ * and use `useScreenAnimation()` to access animation values.
13
+ */
8
14
  export type OverlayMode = "float" | "screen";
9
15
 
10
16
  /**
@@ -37,13 +43,30 @@ export type OverlayProps<TNavigation = unknown> = {
37
43
  */
38
44
  navigation: TNavigation;
39
45
 
46
+ /**
47
+ * Screen options for the currently focused screen.
48
+ */
49
+ options: ScreenTransitionConfig;
50
+
51
+ /**
52
+ * Stack progress relative to the overlay's position.
53
+ * This is equivalent to `useScreenAnimation().stackProgress`.
54
+ */
55
+ progress: DerivedValue<number>;
56
+
40
57
  /**
41
58
  * Animation values for the overlay.
59
+ *
60
+ * @deprecated Use `progress` prop or `useScreenAnimation()` instead.
61
+ * This prop will be removed in a future version.
42
62
  */
43
63
  overlayAnimation: DerivedValue<OverlayInterpolationProps>;
44
64
 
45
65
  /**
46
66
  * Animation values for the screen.
67
+ *
68
+ * @deprecated Use `useScreenAnimation()` hook directly instead.
69
+ * This prop will be removed in a future version.
47
70
  */
48
71
  screenAnimation: DerivedValue<ScreenInterpolationProps>;
49
72
  };
@@ -111,10 +111,11 @@ export type ScreenTransitionConfig = {
111
111
 
112
112
  /**
113
113
  * How the overlay is positioned relative to screens.
114
- * - 'float': Single persistent overlay above all screens (like iOS tab bar)
115
- * - 'screen': Per-screen overlay that transitions with content
116
- * - 'container': Wraps all screen content, receives children prop (for MaskedView, custom containers)
117
- * @default 'screen'
114
+ *
115
+ * @deprecated This option is no longer needed. Overlays now always render as "float" mode
116
+ * (single persistent overlay above all screens). For per-screen overlays, render an
117
+ * absolute-positioned view directly in your screen component and use `useScreenAnimation()`
118
+ * to access animation values.
118
119
  */
119
120
  overlayMode?: OverlayMode;
120
121