react-native-screen-transitions 3.0.0-rc.1 → 3.0.0-rc.3

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 (233) hide show
  1. package/README.md +421 -371
  2. package/lib/commonjs/blank-stack/components/{Overlay.js → overlay.js} +11 -12
  3. package/lib/commonjs/blank-stack/components/overlay.js.map +1 -0
  4. package/lib/commonjs/blank-stack/components/{Screens.js → screens.js} +8 -10
  5. package/lib/commonjs/blank-stack/components/screens.js.map +1 -0
  6. package/lib/commonjs/blank-stack/components/stack-view.js +95 -0
  7. package/lib/commonjs/blank-stack/components/stack-view.js.map +1 -0
  8. package/lib/commonjs/blank-stack/hooks/use-overlay-animation.js +2 -3
  9. package/lib/commonjs/blank-stack/hooks/use-overlay-animation.js.map +1 -1
  10. package/lib/commonjs/blank-stack/index.js +1 -8
  11. package/lib/commonjs/blank-stack/index.js.map +1 -1
  12. package/lib/commonjs/blank-stack/navigators/{createBlankStackNavigator.js → create-blank-stack-navigator.js} +3 -3
  13. package/lib/commonjs/blank-stack/navigators/create-blank-stack-navigator.js.map +1 -0
  14. package/lib/commonjs/blank-stack/utils/with-stack-navigation/helpers/are-descriptors-equal.js.map +1 -0
  15. package/lib/{module/blank-stack/utils/with-stack-navigation/_utils → commonjs/blank-stack/utils/with-stack-navigation/helpers}/calculate-active-screens-limit.js.map +1 -1
  16. package/lib/commonjs/blank-stack/utils/with-stack-navigation/helpers/compose-descriptors.js +15 -0
  17. package/lib/commonjs/blank-stack/utils/with-stack-navigation/helpers/compose-descriptors.js.map +1 -0
  18. package/lib/commonjs/blank-stack/utils/with-stack-navigation/helpers/have-same-route-keys.js.map +1 -0
  19. package/lib/commonjs/blank-stack/utils/with-stack-navigation/helpers/routes-are-identical.js.map +1 -0
  20. package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-closing-route-keys.js +1 -12
  21. package/lib/commonjs/blank-stack/utils/with-stack-navigation/hooks/use-closing-route-keys.js.map +1 -0
  22. package/lib/commonjs/blank-stack/utils/with-stack-navigation/hooks/use-previous.js.map +1 -0
  23. package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-stack-navigation-state.js +4 -4
  24. package/lib/commonjs/blank-stack/utils/with-stack-navigation/hooks/use-stack-navigation-state.js.map +1 -0
  25. package/lib/commonjs/blank-stack/utils/with-stack-navigation/index.js +50 -56
  26. package/lib/commonjs/blank-stack/utils/with-stack-navigation/index.js.map +1 -1
  27. package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_types.js → types.js} +1 -1
  28. package/lib/commonjs/blank-stack/utils/with-stack-navigation/types.js.map +1 -0
  29. package/lib/commonjs/shared/configs/presets.js +8 -2
  30. package/lib/commonjs/shared/configs/presets.js.map +1 -1
  31. package/lib/commonjs/shared/hooks/animation/use-screen-animation.js +42 -21
  32. package/lib/commonjs/shared/hooks/animation/use-screen-animation.js.map +1 -1
  33. package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
  34. package/lib/commonjs/shared/providers/flags.provider.js +25 -0
  35. package/lib/commonjs/shared/providers/flags.provider.js.map +1 -0
  36. package/lib/commonjs/shared/providers/register-bounds.provider.js +71 -45
  37. package/lib/commonjs/shared/providers/register-bounds.provider.js.map +1 -1
  38. package/lib/commonjs/shared/stores/bounds.store.js +91 -47
  39. package/lib/commonjs/shared/stores/bounds.store.js.map +1 -1
  40. package/lib/commonjs/shared/utils/bounds/helpers/is-bounds-equal.js +1 -1
  41. package/lib/commonjs/shared/utils/bounds/helpers/is-bounds-equal.js.map +1 -1
  42. package/lib/commonjs/shared/utils/bounds/index.js +4 -5
  43. package/lib/commonjs/shared/utils/bounds/index.js.map +1 -1
  44. package/lib/commonjs/shared/utils/create-provider.js +20 -1
  45. package/lib/commonjs/shared/utils/create-provider.js.map +1 -1
  46. package/lib/commonjs/shared/utils/reset-stores-for-screen.js +2 -0
  47. package/lib/commonjs/shared/utils/reset-stores-for-screen.js.map +1 -1
  48. package/lib/module/blank-stack/components/{Overlay.js → overlay.js} +11 -12
  49. package/lib/module/blank-stack/components/overlay.js.map +1 -0
  50. package/lib/module/blank-stack/components/{Screens.js → screens.js} +8 -10
  51. package/lib/module/blank-stack/components/screens.js.map +1 -0
  52. package/lib/module/blank-stack/components/stack-view.js +90 -0
  53. package/lib/module/blank-stack/components/stack-view.js.map +1 -0
  54. package/lib/module/blank-stack/hooks/use-overlay-animation.js +2 -3
  55. package/lib/module/blank-stack/hooks/use-overlay-animation.js.map +1 -1
  56. package/lib/module/blank-stack/index.js +1 -2
  57. package/lib/module/blank-stack/index.js.map +1 -1
  58. package/lib/module/blank-stack/navigators/{createBlankStackNavigator.js → create-blank-stack-navigator.js} +2 -2
  59. package/lib/module/blank-stack/navigators/create-blank-stack-navigator.js.map +1 -0
  60. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/are-descriptors-equal.js.map +1 -0
  61. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/calculate-active-screens-limit.js.map +1 -0
  62. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/compose-descriptors.js +10 -0
  63. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/compose-descriptors.js.map +1 -0
  64. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/have-same-route-keys.js.map +1 -0
  65. package/lib/module/blank-stack/utils/with-stack-navigation/helpers/routes-are-identical.js.map +1 -0
  66. package/lib/module/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-closing-route-keys.js +1 -12
  67. package/lib/module/blank-stack/utils/with-stack-navigation/hooks/use-closing-route-keys.js.map +1 -0
  68. package/lib/module/blank-stack/utils/with-stack-navigation/hooks/use-previous.js.map +1 -0
  69. package/lib/module/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-stack-navigation-state.js +4 -4
  70. package/lib/module/blank-stack/utils/with-stack-navigation/hooks/use-stack-navigation-state.js.map +1 -0
  71. package/lib/module/blank-stack/utils/with-stack-navigation/index.js +49 -55
  72. package/lib/module/blank-stack/utils/with-stack-navigation/index.js.map +1 -1
  73. package/lib/module/blank-stack/utils/with-stack-navigation/types.js +4 -0
  74. package/lib/module/blank-stack/utils/with-stack-navigation/types.js.map +1 -0
  75. package/lib/module/shared/configs/presets.js +8 -2
  76. package/lib/module/shared/configs/presets.js.map +1 -1
  77. package/lib/module/shared/hooks/animation/use-screen-animation.js +42 -21
  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/providers/flags.provider.js +19 -0
  81. package/lib/module/shared/providers/flags.provider.js.map +1 -0
  82. package/lib/module/shared/providers/register-bounds.provider.js +71 -45
  83. package/lib/module/shared/providers/register-bounds.provider.js.map +1 -1
  84. package/lib/module/shared/stores/bounds.store.js +91 -47
  85. package/lib/module/shared/stores/bounds.store.js.map +1 -1
  86. package/lib/module/shared/utils/bounds/helpers/is-bounds-equal.js +1 -1
  87. package/lib/module/shared/utils/bounds/helpers/is-bounds-equal.js.map +1 -1
  88. package/lib/module/shared/utils/bounds/index.js +4 -5
  89. package/lib/module/shared/utils/bounds/index.js.map +1 -1
  90. package/lib/module/shared/utils/create-provider.js +20 -1
  91. package/lib/module/shared/utils/create-provider.js.map +1 -1
  92. package/lib/module/shared/utils/reset-stores-for-screen.js +2 -0
  93. package/lib/module/shared/utils/reset-stores-for-screen.js.map +1 -1
  94. package/lib/typescript/blank-stack/components/{Overlay.d.ts → overlay.d.ts} +1 -1
  95. package/lib/typescript/blank-stack/components/overlay.d.ts.map +1 -0
  96. package/lib/typescript/blank-stack/components/{Screens.d.ts → screens.d.ts} +1 -1
  97. package/lib/typescript/blank-stack/components/{Screens.d.ts.map → screens.d.ts.map} +1 -1
  98. package/lib/typescript/blank-stack/components/stack-view.d.ts +3 -0
  99. package/lib/typescript/blank-stack/components/stack-view.d.ts.map +1 -0
  100. package/lib/typescript/blank-stack/index.d.ts +1 -2
  101. package/lib/typescript/blank-stack/index.d.ts.map +1 -1
  102. package/lib/typescript/blank-stack/navigators/{createBlankStackNavigator.d.ts → create-blank-stack-navigator.d.ts} +1 -1
  103. package/lib/typescript/blank-stack/navigators/create-blank-stack-navigator.d.ts.map +1 -0
  104. package/lib/typescript/blank-stack/types.d.ts +23 -105
  105. package/lib/typescript/blank-stack/types.d.ts.map +1 -1
  106. package/lib/typescript/blank-stack/utils/with-stack-navigation/helpers/are-descriptors-equal.d.ts.map +1 -0
  107. package/lib/typescript/blank-stack/utils/with-stack-navigation/helpers/calculate-active-screens-limit.d.ts.map +1 -0
  108. package/lib/typescript/blank-stack/utils/with-stack-navigation/helpers/compose-descriptors.d.ts.map +1 -0
  109. package/lib/typescript/blank-stack/utils/with-stack-navigation/helpers/have-same-route-keys.d.ts.map +1 -0
  110. package/lib/typescript/blank-stack/utils/with-stack-navigation/helpers/routes-are-identical.d.ts.map +1 -0
  111. package/lib/typescript/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-closing-route-keys.d.ts.map +1 -1
  112. package/lib/typescript/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-previous.d.ts.map +1 -1
  113. package/lib/typescript/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-stack-navigation-state.d.ts +1 -1
  114. package/lib/typescript/blank-stack/utils/with-stack-navigation/hooks/use-stack-navigation-state.d.ts.map +1 -0
  115. package/lib/typescript/blank-stack/utils/with-stack-navigation/index.d.ts +3 -5
  116. package/lib/typescript/blank-stack/utils/with-stack-navigation/index.d.ts.map +1 -1
  117. package/lib/typescript/blank-stack/utils/with-stack-navigation/{_types.d.ts → types.d.ts} +1 -1
  118. package/lib/typescript/blank-stack/utils/with-stack-navigation/types.d.ts.map +1 -0
  119. package/lib/typescript/native-stack/types.d.ts +7 -1
  120. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  121. package/lib/typescript/shared/configs/index.d.ts.map +1 -1
  122. package/lib/typescript/shared/configs/presets.d.ts.map +1 -1
  123. package/lib/typescript/shared/hooks/animation/use-screen-animation.d.ts.map +1 -1
  124. package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts.map +1 -1
  125. package/lib/typescript/shared/index.d.ts +32 -32
  126. package/lib/typescript/shared/index.d.ts.map +1 -1
  127. package/lib/typescript/shared/providers/flags.provider.d.ts +10 -0
  128. package/lib/typescript/shared/providers/flags.provider.d.ts.map +1 -0
  129. package/lib/typescript/shared/providers/register-bounds.provider.d.ts.map +1 -1
  130. package/lib/typescript/shared/stores/bounds.store.d.ts +23 -11
  131. package/lib/typescript/shared/stores/bounds.store.d.ts.map +1 -1
  132. package/lib/typescript/shared/types/bounds.types.d.ts +2 -2
  133. package/lib/typescript/shared/types/bounds.types.d.ts.map +1 -1
  134. package/lib/typescript/shared/types/core.types.d.ts +0 -4
  135. package/lib/typescript/shared/types/core.types.d.ts.map +1 -1
  136. package/lib/typescript/shared/utils/bounds/index.d.ts.map +1 -1
  137. package/lib/typescript/shared/utils/create-provider.d.ts +2 -2
  138. package/lib/typescript/shared/utils/create-provider.d.ts.map +1 -1
  139. package/lib/typescript/shared/utils/reset-stores-for-screen.d.ts.map +1 -1
  140. package/package.json +2 -1
  141. package/src/blank-stack/components/{Overlay.tsx → overlay.tsx} +9 -12
  142. package/src/blank-stack/components/{Screens.tsx → screens.tsx} +7 -9
  143. package/src/blank-stack/components/stack-view.tsx +104 -0
  144. package/src/blank-stack/hooks/use-overlay-animation.tsx +11 -11
  145. package/src/blank-stack/index.ts +1 -2
  146. package/src/blank-stack/navigators/{createBlankStackNavigator.tsx → create-blank-stack-navigator.tsx} +1 -1
  147. package/src/blank-stack/types.ts +31 -109
  148. package/src/blank-stack/utils/with-stack-navigation/{_utils → helpers}/compose-descriptors.ts +1 -8
  149. package/src/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-closing-route-keys.tsx +1 -12
  150. package/src/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-stack-navigation-state.tsx +5 -5
  151. package/src/blank-stack/utils/with-stack-navigation/index.tsx +43 -63
  152. package/src/native-stack/types.ts +8 -1
  153. package/src/shared/__tests__/bounds.store.test.ts +398 -167
  154. package/src/shared/__tests__/determine-dismissal.test.ts +2 -12
  155. package/src/shared/__tests__/geometry.test.ts +1 -1
  156. package/src/shared/__tests__/gesture.velocity.test.ts +2 -10
  157. package/src/shared/configs/presets.ts +8 -2
  158. package/src/shared/hooks/animation/use-screen-animation.tsx +65 -31
  159. package/src/shared/hooks/gestures/use-build-gestures.tsx +4 -1
  160. package/src/shared/providers/flags.provider.tsx +21 -0
  161. package/src/shared/providers/register-bounds.provider.tsx +85 -54
  162. package/src/shared/stores/bounds.store.ts +90 -54
  163. package/src/shared/types/bounds.types.ts +2 -2
  164. package/src/shared/types/core.types.ts +4 -6
  165. package/src/shared/utils/bounds/helpers/is-bounds-equal.ts +1 -1
  166. package/src/shared/utils/bounds/index.ts +7 -10
  167. package/src/shared/utils/create-provider.tsx +35 -1
  168. package/src/shared/utils/reset-stores-for-screen.ts +2 -0
  169. package/lib/commonjs/blank-stack/components/Overlay.js.map +0 -1
  170. package/lib/commonjs/blank-stack/components/Screens.js.map +0 -1
  171. package/lib/commonjs/blank-stack/components/StackView.js +0 -93
  172. package/lib/commonjs/blank-stack/components/StackView.js.map +0 -1
  173. package/lib/commonjs/blank-stack/navigators/createBlankStackNavigator.js.map +0 -1
  174. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js.map +0 -1
  175. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js.map +0 -1
  176. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js.map +0 -1
  177. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_types.js.map +0 -1
  178. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js.map +0 -1
  179. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.js.map +0 -1
  180. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js +0 -25
  181. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js.map +0 -1
  182. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js.map +0 -1
  183. package/lib/commonjs/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js.map +0 -1
  184. package/lib/module/blank-stack/components/Overlay.js.map +0 -1
  185. package/lib/module/blank-stack/components/Screens.js.map +0 -1
  186. package/lib/module/blank-stack/components/StackView.js +0 -88
  187. package/lib/module/blank-stack/components/StackView.js.map +0 -1
  188. package/lib/module/blank-stack/navigators/createBlankStackNavigator.js.map +0 -1
  189. package/lib/module/blank-stack/utils/with-stack-navigation/_hooks/use-closing-route-keys.js.map +0 -1
  190. package/lib/module/blank-stack/utils/with-stack-navigation/_hooks/use-previous.js.map +0 -1
  191. package/lib/module/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.js.map +0 -1
  192. package/lib/module/blank-stack/utils/with-stack-navigation/_types.js +0 -4
  193. package/lib/module/blank-stack/utils/with-stack-navigation/_types.js.map +0 -1
  194. package/lib/module/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.js.map +0 -1
  195. package/lib/module/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js +0 -20
  196. package/lib/module/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.js.map +0 -1
  197. package/lib/module/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.js.map +0 -1
  198. package/lib/module/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.js.map +0 -1
  199. package/lib/typescript/blank-stack/components/Overlay.d.ts.map +0 -1
  200. package/lib/typescript/blank-stack/components/StackView.d.ts +0 -2
  201. package/lib/typescript/blank-stack/components/StackView.d.ts.map +0 -1
  202. package/lib/typescript/blank-stack/navigators/createBlankStackNavigator.d.ts.map +0 -1
  203. package/lib/typescript/blank-stack/utils/with-stack-navigation/_hooks/use-stack-navigation-state.d.ts.map +0 -1
  204. package/lib/typescript/blank-stack/utils/with-stack-navigation/_types.d.ts.map +0 -1
  205. package/lib/typescript/blank-stack/utils/with-stack-navigation/_utils/are-descriptors-equal.d.ts.map +0 -1
  206. package/lib/typescript/blank-stack/utils/with-stack-navigation/_utils/calculate-active-screens-limit.d.ts.map +0 -1
  207. package/lib/typescript/blank-stack/utils/with-stack-navigation/_utils/compose-descriptors.d.ts.map +0 -1
  208. package/lib/typescript/blank-stack/utils/with-stack-navigation/_utils/have-same-route-keys.d.ts.map +0 -1
  209. package/lib/typescript/blank-stack/utils/with-stack-navigation/_utils/routes-are-identical.d.ts.map +0 -1
  210. package/src/blank-stack/components/StackView.tsx +0 -108
  211. /package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_utils → helpers}/are-descriptors-equal.js +0 -0
  212. /package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_utils → helpers}/calculate-active-screens-limit.js +0 -0
  213. /package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_utils → helpers}/have-same-route-keys.js +0 -0
  214. /package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_utils → helpers}/routes-are-identical.js +0 -0
  215. /package/lib/commonjs/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-previous.js +0 -0
  216. /package/lib/module/blank-stack/utils/with-stack-navigation/{_utils → helpers}/are-descriptors-equal.js +0 -0
  217. /package/lib/module/blank-stack/utils/with-stack-navigation/{_utils → helpers}/calculate-active-screens-limit.js +0 -0
  218. /package/lib/module/blank-stack/utils/with-stack-navigation/{_utils → helpers}/have-same-route-keys.js +0 -0
  219. /package/lib/module/blank-stack/utils/with-stack-navigation/{_utils → helpers}/routes-are-identical.js +0 -0
  220. /package/lib/module/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-previous.js +0 -0
  221. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_utils → helpers}/are-descriptors-equal.d.ts +0 -0
  222. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_utils → helpers}/calculate-active-screens-limit.d.ts +0 -0
  223. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_utils → helpers}/compose-descriptors.d.ts +0 -0
  224. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_utils → helpers}/have-same-route-keys.d.ts +0 -0
  225. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_utils → helpers}/routes-are-identical.d.ts +0 -0
  226. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-closing-route-keys.d.ts +0 -0
  227. /package/lib/typescript/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-previous.d.ts +0 -0
  228. /package/src/blank-stack/utils/with-stack-navigation/{_utils → helpers}/are-descriptors-equal.ts +0 -0
  229. /package/src/blank-stack/utils/with-stack-navigation/{_utils → helpers}/calculate-active-screens-limit.ts +0 -0
  230. /package/src/blank-stack/utils/with-stack-navigation/{_utils → helpers}/have-same-route-keys.ts +0 -0
  231. /package/src/blank-stack/utils/with-stack-navigation/{_utils → helpers}/routes-are-identical.ts +0 -0
  232. /package/src/blank-stack/utils/with-stack-navigation/{_hooks → hooks}/use-previous.tsx +0 -0
  233. /package/src/blank-stack/utils/with-stack-navigation/{_types.ts → types.ts} +0 -0
@@ -1,185 +1,416 @@
1
1
  import { beforeEach, describe, expect, it } from "bun:test";
2
- import { resolveActiveBound } from "../stores/bounds/_utils";
3
- import type { ScreenTransitionState } from "../types/animation";
4
-
5
- type Dim = {
6
- x: number;
7
- y: number;
8
- pageX: number;
9
- pageY: number;
10
- width: number;
11
- height: number;
12
- };
13
-
14
- const getDimensions = (x = 0, y = 0, w = 100, h = 100): Dim => ({
2
+ import { BoundStore, type Snapshot } from "../stores/bounds.store";
3
+
4
+ // Helper to create mock bounds
5
+ const createBounds = (
6
+ x = 0,
7
+ y = 0,
8
+ width = 100,
9
+ height = 100,
10
+ ): Snapshot["bounds"] => ({
15
11
  x,
16
12
  y,
17
13
  pageX: x,
18
14
  pageY: y,
19
- width: w,
20
- height: h,
15
+ width,
16
+ height,
21
17
  });
22
18
 
23
- const mockState = (
24
- routeKey: string,
25
- ids: string[] = [],
26
- ): ScreenTransitionState => {
27
- const bounds: Record<
28
- string,
29
- { bounds: Dim; styles: Record<string, unknown> }
30
- > = {};
31
- ids.forEach((id, i) => {
32
- bounds[id] = { bounds: getDimensions(i * 10, i * 10), styles: {} };
33
- });
34
- return {
35
- progress: 1,
36
- closing: 0,
37
- animating: 1,
38
- gesture: {
39
- x: 0,
40
- y: 0,
41
- normalizedX: 0,
42
- normalizedY: 0,
43
- isDismissing: 0,
44
- isDragging: 0,
45
- },
46
- bounds,
47
- // @ts-expect-error partial route
48
- route: { key: routeKey },
49
- };
50
- };
51
-
52
- let cache: Record<string, string>;
53
- let lastActiveByRoute: Record<string, string>;
19
+ // Reset registry before each test
54
20
  beforeEach(() => {
55
- cache = {};
56
- lastActiveByRoute = {};
21
+ globalThis.resetMutableRegistry();
22
+ });
23
+
24
+ // =============================================================================
25
+ // Unit Tests - registerSnapshot
26
+ // =============================================================================
27
+
28
+ describe("BoundStore.registerSnapshot", () => {
29
+ it("registers new tag with bounds and styles", () => {
30
+ const bounds = createBounds(10, 20, 200, 300);
31
+ const styles = { backgroundColor: "red" };
32
+
33
+ BoundStore.registerSnapshot("card", "screen-a", bounds, styles);
34
+
35
+ const snapshot = BoundStore.getSnapshot("card", "screen-a");
36
+ expect(snapshot).not.toBeNull();
37
+ expect(snapshot?.bounds).toEqual(bounds);
38
+ expect(snapshot?.styles).toEqual(styles);
39
+ });
40
+
41
+ it("adds snapshot to existing tag", () => {
42
+ const boundsA = createBounds(0, 0, 100, 100);
43
+ const boundsB = createBounds(50, 50, 150, 150);
44
+
45
+ BoundStore.registerSnapshot("card", "screen-a", boundsA);
46
+ BoundStore.registerSnapshot("card", "screen-b", boundsB);
47
+
48
+ expect(BoundStore.getSnapshot("card", "screen-a")?.bounds).toEqual(
49
+ boundsA,
50
+ );
51
+ expect(BoundStore.getSnapshot("card", "screen-b")?.bounds).toEqual(
52
+ boundsB,
53
+ );
54
+ });
55
+
56
+ it("stores ancestorKeys correctly", () => {
57
+ const bounds = createBounds();
58
+ const ancestors = ["stack-a", "tab-nav"];
59
+
60
+ BoundStore.registerSnapshot("card", "screen-a", bounds, {}, ancestors);
61
+
62
+ // Verify ancestor matching works
63
+ const viaAncestor = BoundStore.getSnapshot("card", "stack-a");
64
+ expect(viaAncestor).not.toBeNull();
65
+ expect(viaAncestor?.bounds).toEqual(bounds);
66
+ });
67
+
68
+ it("updates existing snapshot on re-measurement", () => {
69
+ const initialBounds = createBounds(0, 0, 100, 100);
70
+ const updatedBounds = createBounds(10, 10, 200, 200);
71
+
72
+ BoundStore.registerSnapshot("card", "screen-a", initialBounds);
73
+ BoundStore.registerSnapshot("card", "screen-a", updatedBounds);
74
+
75
+ const snapshot = BoundStore.getSnapshot("card", "screen-a");
76
+ expect(snapshot?.bounds).toEqual(updatedBounds);
77
+ });
78
+ });
79
+
80
+ // =============================================================================
81
+ // Unit Tests - setLinkSource / setLinkDestination
82
+ // =============================================================================
83
+
84
+ describe("BoundStore.setLinkSource", () => {
85
+ it("creates new tag if it does not exist", () => {
86
+ const bounds = createBounds();
87
+
88
+ BoundStore.setLinkSource("card", "screen-a", bounds);
89
+
90
+ const link = BoundStore.getActiveLink("card");
91
+ expect(link).not.toBeNull();
92
+ expect(link?.source.screenKey).toBe("screen-a");
93
+ });
94
+
95
+ it("pushes link with source and null destination", () => {
96
+ const bounds = createBounds();
97
+
98
+ BoundStore.setLinkSource("card", "screen-a", bounds);
99
+
100
+ const link = BoundStore.getActiveLink("card");
101
+ expect(link?.source.screenKey).toBe("screen-a");
102
+ expect(link?.destination).toBeNull();
103
+ });
104
+
105
+ it("multiple sources create multiple links", () => {
106
+ const boundsA = createBounds(0, 0);
107
+ const boundsB = createBounds(100, 100);
108
+
109
+ BoundStore.setLinkSource("card", "screen-a", boundsA);
110
+ BoundStore.setLinkSource("card", "screen-b", boundsB);
111
+
112
+ // Most recent link should be from screen-b
113
+ const link = BoundStore.getActiveLink("card");
114
+ expect(link?.source.screenKey).toBe("screen-b");
115
+ });
57
116
  });
58
117
 
59
- const getPairCache = (from: string, to: string) =>
60
- cache[`${from}|${to}`] ?? null;
61
- const setPairCache = (from: string, to: string, id: string) => {
62
- cache[`${from}|${to}`] = id;
63
- };
64
- const getRouteActive = (routeKey: string) =>
65
- lastActiveByRoute[routeKey] ?? null;
66
-
67
- describe("Bounds.getActiveBound - requested id priority and acceptance", () => {
68
- it("selects requested id when present only on current (opening)", () => {
69
- const A = "A-1";
70
- const B = "B-1";
71
- const current = mockState(A, ["container"]);
72
- const previous = mockState(B, ["icon"]);
73
-
74
- // Opening: fromKey is previous.route.key (B)
75
- lastActiveByRoute[B] = "container";
76
- const active = resolveActiveBound({
77
- current,
78
- previous,
79
- getPairCache,
80
- setPairCache,
81
- getRouteActive,
82
- });
83
-
84
- expect(active).toBe("container");
85
- expect(getPairCache(B, A)).toBeNull();
86
- });
87
-
88
- it("selects requested id when present only on other (closing)", () => {
89
- const A = "A-2";
90
- const B = "B-2";
91
- const current = mockState(A, ["icon"]);
92
- const next = mockState(B, ["container"]);
93
-
94
- // Closing: fromKey is current.route.key (A)
95
- lastActiveByRoute[A] = "container";
96
- const active = resolveActiveBound({
97
- current,
98
- next,
99
- getPairCache,
100
- setPairCache,
101
- getRouteActive,
102
- });
103
- expect(active).toBe("container");
104
- expect(getPairCache(A, B)).toBeNull();
118
+ describe("BoundStore.setLinkDestination", () => {
119
+ it("fills topmost link with null destination", () => {
120
+ const srcBounds = createBounds(0, 0);
121
+ const dstBounds = createBounds(100, 100);
122
+
123
+ BoundStore.setLinkSource("card", "screen-a", srcBounds);
124
+ BoundStore.setLinkDestination("card", "screen-b", dstBounds);
125
+
126
+ const link = BoundStore.getActiveLink("card");
127
+ expect(link?.source.screenKey).toBe("screen-a");
128
+ expect(link?.destination?.screenKey).toBe("screen-b");
129
+ });
130
+
131
+ it("ignores if no pending links", () => {
132
+ const bounds = createBounds();
133
+
134
+ // No source set, destination should be ignored
135
+ BoundStore.setLinkDestination("card", "screen-b", bounds);
136
+
137
+ const link = BoundStore.getActiveLink("card");
138
+ expect(link).toBeNull();
139
+ });
140
+
141
+ it("fills correct link when multiple pending", () => {
142
+ const boundsA = createBounds(0, 0);
143
+ const boundsB = createBounds(50, 50);
144
+ const boundsC = createBounds(100, 100);
145
+
146
+ // Two sources, one destination
147
+ BoundStore.setLinkSource("card", "screen-a", boundsA);
148
+ BoundStore.setLinkSource("card", "screen-b", boundsB);
149
+ BoundStore.setLinkDestination("card", "screen-c", boundsC);
150
+
151
+ // Most recent link (from screen-b) should have destination
152
+ const link = BoundStore.getActiveLink("card");
153
+ expect(link?.source.screenKey).toBe("screen-b");
154
+ expect(link?.destination?.screenKey).toBe("screen-c");
105
155
  });
106
156
  });
107
157
 
108
- describe("Bounds.getActiveBound - hint behavior (guarded writes)", () => {
109
- it("writes cache only when both sides have the id", () => {
110
- const A = "A-3";
111
- const B = "B-3";
112
- // Both have the same id measured
113
- const current = mockState(A, ["container"]);
114
- const previous = mockState(B, ["container"]);
115
-
116
- // Opening: fromKey is previous.route.key (B)
117
- lastActiveByRoute[B] = "container";
118
- const active = resolveActiveBound({
119
- current,
120
- previous,
121
- getPairCache,
122
- setPairCache,
123
- getRouteActive,
124
- });
125
- expect(active).toBe("container");
126
- expect(getPairCache(B, A)).toBe("container");
127
- });
128
-
129
- it("requested id overrides existing cache and updates it when both sides measured", () => {
130
- const A = "A-4";
131
- const B = "B-4";
132
- // Both sides have icon and container
133
- // Pre-seed a conflicting cache
134
- setPairCache(B, A, "icon");
135
-
136
- const current = mockState(A, ["icon", "container"]);
137
- const previous = mockState(B, ["icon", "container"]);
138
-
139
- // Opening: fromKey is previous.route.key (B)
140
- lastActiveByRoute[B] = "container";
141
- const active = resolveActiveBound({
142
- current,
143
- previous,
144
- getPairCache,
145
- setPairCache,
146
- getRouteActive,
147
- });
148
- expect(active).toBe("container");
149
- expect(getPairCache(B, A)).toBe("container");
158
+ // =============================================================================
159
+ // Unit Tests - getSnapshot
160
+ // =============================================================================
161
+
162
+ describe("BoundStore.getSnapshot", () => {
163
+ it("returns null for unknown tag", () => {
164
+ const result = BoundStore.getSnapshot("unknown", "screen-a");
165
+ expect(result).toBeNull();
166
+ });
167
+
168
+ it("returns bounds and styles for direct key match", () => {
169
+ const bounds = createBounds(10, 20, 300, 400);
170
+ const styles = { borderRadius: 8 };
171
+
172
+ BoundStore.registerSnapshot("card", "screen-a", bounds, styles);
173
+
174
+ const result = BoundStore.getSnapshot("card", "screen-a");
175
+ expect(result).toEqual({ bounds, styles });
176
+ });
177
+
178
+ it("returns bounds via ancestor match", () => {
179
+ const bounds = createBounds();
180
+ const ancestors = ["stack-a", "root"];
181
+
182
+ BoundStore.registerSnapshot("card", "screen-a", bounds, {}, ancestors);
183
+
184
+ // Query by ancestor key
185
+ const result = BoundStore.getSnapshot("card", "stack-a");
186
+ expect(result).not.toBeNull();
187
+ expect(result?.bounds).toEqual(bounds);
188
+ });
189
+
190
+ it("prefers direct match over ancestor match", () => {
191
+ const directBounds = createBounds(0, 0, 100, 100);
192
+ const ancestorBounds = createBounds(200, 200, 50, 50);
193
+
194
+ // Register with ancestor that matches another screen's key
195
+ BoundStore.registerSnapshot(
196
+ "card",
197
+ "screen-a",
198
+ ancestorBounds,
199
+ {},
200
+ ["stack-a"],
201
+ );
202
+ BoundStore.registerSnapshot("card", "stack-a", directBounds);
203
+
204
+ // Direct match should win
205
+ const result = BoundStore.getSnapshot("card", "stack-a");
206
+ expect(result?.bounds).toEqual(directBounds);
150
207
  });
151
208
  });
152
209
 
153
- describe("Bounds.getActiveBound - set intersection and fallbacks", () => {
154
- it("falls back to intersection when no request or cache", () => {
155
- const A = "A-5";
156
- const B = "B-5";
157
- const current = mockState(A, ["alpha", "beta"]);
158
- const previous = mockState(B, ["beta", "gamma"]);
159
-
160
- const active = resolveActiveBound({
161
- current,
162
- previous,
163
- getPairCache,
164
- setPairCache,
165
- getRouteActive,
166
- });
167
- expect(active).toBe("beta");
168
- });
169
-
170
- it("when other has a single bound, selects it (no request/cache)", () => {
171
- const A = "A-6";
172
- const B = "B-6";
173
- const current = mockState(A, ["alpha"]);
174
- const previous = mockState(B, ["only"]);
175
-
176
- const active = resolveActiveBound({
177
- current,
178
- previous,
179
- getPairCache,
180
- setPairCache,
181
- getRouteActive,
182
- });
183
- expect(active).toBe("only");
210
+ // =============================================================================
211
+ // Unit Tests - getActiveLink
212
+ // =============================================================================
213
+
214
+ describe("BoundStore.getActiveLink", () => {
215
+ it("returns null for unknown tag", () => {
216
+ const result = BoundStore.getActiveLink("unknown");
217
+ expect(result).toBeNull();
218
+ });
219
+
220
+ it("returns null for empty linkStack", () => {
221
+ // Register snapshot but no links
222
+ BoundStore.registerSnapshot("card", "screen-a", createBounds());
223
+
224
+ const result = BoundStore.getActiveLink("card");
225
+ expect(result).toBeNull();
226
+ });
227
+
228
+ it("returns most recent link when no screenKey provided", () => {
229
+ BoundStore.setLinkSource("card", "screen-a", createBounds());
230
+ BoundStore.setLinkDestination("card", "screen-b", createBounds());
231
+ BoundStore.setLinkSource("card", "screen-b", createBounds());
232
+ BoundStore.setLinkDestination("card", "screen-c", createBounds());
233
+
234
+ const link = BoundStore.getActiveLink("card");
235
+ expect(link?.source.screenKey).toBe("screen-b");
236
+ expect(link?.destination?.screenKey).toBe("screen-c");
237
+ });
238
+
239
+ it("infers isClosing when screenKey matches source", () => {
240
+ BoundStore.setLinkSource("card", "screen-a", createBounds());
241
+ BoundStore.setLinkDestination("card", "screen-b", createBounds());
242
+
243
+ // Query from source screen = closing (going back)
244
+ const linkFromSource = BoundStore.getActiveLink("card", "screen-a");
245
+ expect(linkFromSource?.isClosing).toBe(true);
246
+ expect(linkFromSource?.source.screenKey).toBe("screen-a");
247
+
248
+ // Query from destination screen = opening
249
+ const linkFromDest = BoundStore.getActiveLink("card", "screen-b");
250
+ expect(linkFromDest?.isClosing).toBe(false);
251
+ expect(linkFromDest?.destination?.screenKey).toBe("screen-b");
252
+ });
253
+
254
+ it("ancestor matching works in link lookup", () => {
255
+ const ancestors = ["stack-a"];
256
+
257
+ BoundStore.setLinkSource(
258
+ "card",
259
+ "screen-a",
260
+ createBounds(),
261
+ {},
262
+ ancestors,
263
+ );
264
+ BoundStore.setLinkDestination("card", "screen-b", createBounds());
265
+
266
+ // Query by ancestor key (matches source)
267
+ const link = BoundStore.getActiveLink("card", "stack-a");
268
+ expect(link).not.toBeNull();
269
+ expect(link?.source.screenKey).toBe("screen-a");
270
+ expect(link?.isClosing).toBe(true); // Ancestor of source = closing
271
+ });
272
+
273
+ it("returns null when screenKey does not match any link", () => {
274
+ BoundStore.setLinkSource("card", "screen-a", createBounds());
275
+ BoundStore.setLinkDestination("card", "screen-b", createBounds());
276
+
277
+ const link = BoundStore.getActiveLink("card", "screen-x");
278
+ expect(link).toBeNull();
279
+ });
280
+ });
281
+
282
+ // =============================================================================
283
+ // Scenario Tests - Navigation Flows
284
+ // =============================================================================
285
+
286
+ describe("Scenario: Simple push/pop navigation", () => {
287
+ it("captures source on press, destination on layout, reverses on pop", () => {
288
+ const srcBounds = createBounds(50, 100, 200, 200);
289
+ const dstBounds = createBounds(0, 0, 400, 400);
290
+
291
+ // 1. User presses card on Screen A (source captured)
292
+ BoundStore.setLinkSource("card", "screen-a", srcBounds);
293
+
294
+ // 2. Screen B mounts, measures card (destination captured)
295
+ BoundStore.setLinkDestination("card", "screen-b", dstBounds);
296
+
297
+ // Verify link is complete - query from destination (opening)
298
+ const openingLink = BoundStore.getActiveLink("card", "screen-b");
299
+ expect(openingLink?.isClosing).toBe(false);
300
+ expect(openingLink?.source.bounds).toEqual(srcBounds);
301
+ expect(openingLink?.destination?.bounds).toEqual(dstBounds);
302
+
303
+ // 3. Query from source (closing - going back)
304
+ const closingLink = BoundStore.getActiveLink("card", "screen-a");
305
+ expect(closingLink?.isClosing).toBe(true);
306
+ expect(closingLink?.source.screenKey).toBe("screen-a");
307
+ expect(closingLink?.destination?.screenKey).toBe("screen-b");
308
+ });
309
+ });
310
+
311
+ describe("Scenario: Multiple bounds, only one matches", () => {
312
+ it("establishes link only for matching bound", () => {
313
+ // Screen A has header, card, footer
314
+ BoundStore.registerSnapshot("header", "screen-a", createBounds(0, 0));
315
+ BoundStore.registerSnapshot("card", "screen-a", createBounds(0, 100));
316
+ BoundStore.registerSnapshot("footer", "screen-a", createBounds(0, 500));
317
+
318
+ // Only card triggers navigation
319
+ BoundStore.setLinkSource("card", "screen-a", createBounds(0, 100));
320
+
321
+ // Screen B only has card
322
+ BoundStore.setLinkDestination("card", "screen-b", createBounds(0, 0));
323
+
324
+ // Card link exists
325
+ expect(BoundStore.getActiveLink("card")).not.toBeNull();
326
+
327
+ // Header and footer have no links (only snapshots)
328
+ expect(BoundStore.getActiveLink("header")).toBeNull();
329
+ expect(BoundStore.getActiveLink("footer")).toBeNull();
330
+ });
331
+ });
332
+
333
+ describe("Scenario: Nested navigator with ancestor keys", () => {
334
+ it("supports cross-stack bounds via ancestor matching", () => {
335
+ // Tab Navigator structure:
336
+ // - Stack A (key: "stack-a") -> Screen A1 (key: "a1", ancestors: ["stack-a"])
337
+ // - Stack B (key: "stack-b") -> Screen B1 (key: "b1", ancestors: ["stack-b"])
338
+
339
+ const boundsA = createBounds(10, 10, 80, 80);
340
+ const boundsB = createBounds(20, 20, 100, 100);
341
+
342
+ // Register snapshot in Stack A
343
+ BoundStore.registerSnapshot("profile", "a1", boundsA, {}, ["stack-a"]);
344
+
345
+ // Register snapshot in Stack B
346
+ BoundStore.registerSnapshot("profile", "b1", boundsB, {}, ["stack-b"]);
347
+
348
+ // Query by stack key should return correct bounds
349
+ const fromStackA = BoundStore.getSnapshot("profile", "stack-a");
350
+ expect(fromStackA?.bounds).toEqual(boundsA);
351
+
352
+ const fromStackB = BoundStore.getSnapshot("profile", "stack-b");
353
+ expect(fromStackB?.bounds).toEqual(boundsB);
354
+ });
355
+
356
+ it("getActiveLink respects ancestor chain", () => {
357
+ // Navigation from Stack A to detail screen
358
+ BoundStore.setLinkSource(
359
+ "profile",
360
+ "a1",
361
+ createBounds(10, 10),
362
+ {},
363
+ ["stack-a"],
364
+ );
365
+ BoundStore.setLinkDestination("profile", "detail", createBounds(0, 0));
366
+
367
+ // Query by ancestor should find the link
368
+ const link = BoundStore.getActiveLink("profile", "stack-a");
369
+ expect(link?.source.screenKey).toBe("a1");
370
+ expect(link?.isClosing).toBe(true); // Ancestor matches source = closing
371
+ });
372
+ });
373
+
374
+ describe("Scenario: Rapid navigation A → B → C → pop → pop", () => {
375
+ it("link stack grows and getActiveLink finds correct link for each screen", () => {
376
+ // A → B
377
+ BoundStore.setLinkSource("card", "screen-a", createBounds(0, 0));
378
+ BoundStore.setLinkDestination("card", "screen-b", createBounds(100, 100));
379
+
380
+ // B → C
381
+ BoundStore.setLinkSource("card", "screen-b", createBounds(100, 100));
382
+ BoundStore.setLinkDestination("card", "screen-c", createBounds(200, 200));
383
+
384
+ // Most recent link is B → C
385
+ const latest = BoundStore.getActiveLink("card");
386
+ expect(latest?.source.screenKey).toBe("screen-b");
387
+ expect(latest?.destination?.screenKey).toBe("screen-c");
388
+
389
+ // Query from C (destination of B→C) = opening
390
+ const fromC = BoundStore.getActiveLink("card", "screen-c");
391
+ expect(fromC?.isClosing).toBe(false);
392
+ expect(fromC?.destination?.screenKey).toBe("screen-c");
393
+
394
+ // Query from B - B is source of B→C link, so isClosing=true
395
+ const fromB = BoundStore.getActiveLink("card", "screen-b");
396
+ expect(fromB?.isClosing).toBe(true);
397
+ expect(fromB?.source.screenKey).toBe("screen-b");
398
+ });
399
+ });
400
+
401
+ describe("Scenario: Global bounds (fullscreen target)", () => {
402
+ it("getActiveLink with no screenKey returns most recent for fullscreen", () => {
403
+ // Source exists, destination will be fullscreen (no specific screenKey needed)
404
+ BoundStore.setLinkSource("image", "gallery", createBounds(50, 50, 100, 100));
405
+ BoundStore.setLinkDestination(
406
+ "image",
407
+ "fullscreen-viewer",
408
+ createBounds(0, 0, 400, 800),
409
+ );
410
+
411
+ // Fullscreen target can get link without knowing screenKey
412
+ const link = BoundStore.getActiveLink("image");
413
+ expect(link).not.toBeNull();
414
+ expect(link?.destination?.screenKey).toBe("fullscreen-viewer");
184
415
  });
185
416
  });
@@ -1,15 +1,5 @@
1
- import { describe, expect, it, mock } from "bun:test";
2
-
3
- mock.module("react-native", () => ({}));
4
- mock.module("react-native-gesture-handler", () => ({}));
5
- mock.module("react-native-reanimated", () => ({
6
- clamp: (value: number, lower: number, upper: number) =>
7
- Math.min(Math.max(value, lower), upper),
8
- }));
9
-
10
- const { determineDismissal } = await import(
11
- "../utils/gesture/determine-dismissal"
12
- );
1
+ import { describe, expect, it } from "bun:test";
2
+ import { determineDismissal } from "../utils/gesture/determine-dismissal";
13
3
 
14
4
  describe("determineDismissal", () => {
15
5
  const dimensions = { width: 320, height: 640 };
@@ -2,7 +2,7 @@ import { describe, expect, it } from "bun:test";
2
2
  import {
3
3
  computeContentTransformGeometry,
4
4
  computeRelativeGeometry,
5
- } from "../utils/bounds/_utils/geometry";
5
+ } from "../utils/bounds/helpers/geometry";
6
6
 
7
7
  describe("computeRelativeGeometry", () => {
8
8
  it("calculates correct relative geometry when entering", () => {
@@ -1,13 +1,5 @@
1
- import { describe, expect, it, mock } from "bun:test";
2
-
3
- mock.module("react-native", () => ({}));
4
- mock.module("react-native-gesture-handler", () => ({}));
5
- mock.module("react-native-reanimated", () => ({
6
- clamp: (value: number, lower: number, upper: number) =>
7
- Math.min(Math.max(value, lower), upper),
8
- }));
9
-
10
- const { velocity } = await import("../utils/gesture/velocity");
1
+ import { describe, expect, it } from "bun:test";
2
+ import { velocity } from "../utils/gesture/velocity";
11
3
 
12
4
  type Directions = {
13
5
  horizontal: boolean;