react-native-screen-transitions 3.4.0-alpha.5 → 3.4.0-alpha.7

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 (234) hide show
  1. package/README.md +1058 -11
  2. package/lib/commonjs/blank-stack/navigators/create-blank-stack-navigator.js +27 -45
  3. package/lib/commonjs/blank-stack/navigators/create-blank-stack-navigator.js.map +1 -1
  4. package/lib/commonjs/component-stack/navigators/create-component-stack-navigator.js +1 -1
  5. package/lib/commonjs/shared/components/create-boundary-component/components/boundary-target.js +39 -0
  6. package/lib/commonjs/shared/components/create-boundary-component/components/boundary-target.js.map +1 -0
  7. package/lib/commonjs/shared/components/create-boundary-component/create-boundary-component.js +232 -0
  8. package/lib/commonjs/shared/components/create-boundary-component/create-boundary-component.js.map +1 -0
  9. package/lib/commonjs/shared/components/create-boundary-component/hooks/helpers/measurement-rules.js +2 -4
  10. package/lib/commonjs/shared/components/create-boundary-component/hooks/helpers/measurement-rules.js.map +1 -1
  11. package/lib/commonjs/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.js +4 -3
  12. package/lib/commonjs/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.js.map +1 -1
  13. package/lib/commonjs/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.js +2 -1
  14. package/lib/commonjs/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.js.map +1 -1
  15. package/lib/commonjs/shared/components/create-boundary-component/index.js +20 -214
  16. package/lib/commonjs/shared/components/create-boundary-component/index.js.map +1 -1
  17. package/lib/commonjs/shared/components/create-boundary-component/providers/boundary-owner.provider.js +63 -0
  18. package/lib/commonjs/shared/components/create-boundary-component/providers/boundary-owner.provider.js.map +1 -0
  19. package/lib/commonjs/shared/components/create-transition-aware-component.js +29 -7
  20. package/lib/commonjs/shared/components/create-transition-aware-component.js.map +1 -1
  21. package/lib/commonjs/shared/components/overlay/variations/float-overlay.js +1 -1
  22. package/lib/commonjs/shared/components/screen-container/hooks/use-backdrop-pointer-events.js.map +1 -1
  23. package/lib/commonjs/shared/components/screen-container/index.js +12 -8
  24. package/lib/commonjs/shared/components/screen-container/index.js.map +1 -1
  25. package/lib/commonjs/shared/components/screen-container/layers/backdrop.js +8 -10
  26. package/lib/commonjs/shared/components/screen-container/layers/backdrop.js.map +1 -1
  27. package/lib/commonjs/shared/components/screen-container/layers/content.js +7 -10
  28. package/lib/commonjs/shared/components/screen-container/layers/content.js.map +1 -1
  29. package/lib/commonjs/shared/components/screen-container/layers/maybe-masked-navigation-container.js +4 -4
  30. package/lib/commonjs/shared/components/screen-container/layers/maybe-masked-navigation-container.js.map +1 -1
  31. package/lib/commonjs/shared/components/screen-container/layers/surface-container.js +4 -4
  32. package/lib/commonjs/shared/components/screen-container/layers/surface-container.js.map +1 -1
  33. package/lib/commonjs/shared/constants.js +4 -1
  34. package/lib/commonjs/shared/constants.js.map +1 -1
  35. package/lib/commonjs/shared/providers/screen/animation/helpers/hydrate-transition-state.js +33 -1
  36. package/lib/commonjs/shared/providers/screen/animation/helpers/hydrate-transition-state.js.map +1 -1
  37. package/lib/commonjs/shared/providers/screen/animation/helpers/pipeline.js +2 -0
  38. package/lib/commonjs/shared/providers/screen/animation/helpers/pipeline.js.map +1 -1
  39. package/lib/commonjs/shared/providers/screen/animation/helpers/use-build-transition-state.js +1 -0
  40. package/lib/commonjs/shared/providers/screen/animation/helpers/use-build-transition-state.js.map +1 -1
  41. package/lib/commonjs/shared/providers/screen/screen-composer.js +1 -1
  42. package/lib/commonjs/shared/providers/screen/screen-composer.js.map +1 -1
  43. package/lib/commonjs/shared/providers/screen/styles/helpers/build-resolved-style-map.js +144 -0
  44. package/lib/commonjs/shared/providers/screen/styles/helpers/build-resolved-style-map.js.map +1 -0
  45. package/lib/commonjs/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.js +28 -0
  46. package/lib/commonjs/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.js.map +1 -0
  47. package/lib/commonjs/shared/providers/screen/styles/helpers/split-normalized-style-maps.js +39 -0
  48. package/lib/commonjs/shared/providers/screen/styles/helpers/split-normalized-style-maps.js.map +1 -0
  49. package/lib/commonjs/shared/providers/screen/styles/index.js +25 -0
  50. package/lib/commonjs/shared/providers/screen/styles/index.js.map +1 -0
  51. package/lib/commonjs/shared/providers/screen/{styles.provider.js → styles/styles.provider.js} +47 -39
  52. package/lib/commonjs/shared/providers/screen/styles/styles.provider.js.map +1 -0
  53. package/lib/commonjs/shared/utils/bounds/helpers/compute-bounds-styles.js +1 -1
  54. package/lib/commonjs/shared/utils/bounds/helpers/compute-bounds-styles.js.map +1 -1
  55. package/lib/commonjs/shared/utils/bounds/helpers/style-composers.js +21 -10
  56. package/lib/commonjs/shared/utils/bounds/helpers/style-composers.js.map +1 -1
  57. package/lib/commonjs/shared/utils/bounds/zoom/build.js +57 -31
  58. package/lib/commonjs/shared/utils/bounds/zoom/build.js.map +1 -1
  59. package/lib/module/blank-stack/navigators/create-blank-stack-navigator.js +27 -45
  60. package/lib/module/blank-stack/navigators/create-blank-stack-navigator.js.map +1 -1
  61. package/lib/module/component-stack/navigators/create-component-stack-navigator.js +1 -1
  62. package/lib/module/shared/components/create-boundary-component/components/boundary-target.js +34 -0
  63. package/lib/module/shared/components/create-boundary-component/components/boundary-target.js.map +1 -0
  64. package/lib/module/shared/components/create-boundary-component/create-boundary-component.js +227 -0
  65. package/lib/module/shared/components/create-boundary-component/create-boundary-component.js.map +1 -0
  66. package/lib/module/shared/components/create-boundary-component/hooks/helpers/measurement-rules.js +2 -4
  67. package/lib/module/shared/components/create-boundary-component/hooks/helpers/measurement-rules.js.map +1 -1
  68. package/lib/module/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.js +4 -3
  69. package/lib/module/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.js.map +1 -1
  70. package/lib/module/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.js +2 -1
  71. package/lib/module/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.js.map +1 -1
  72. package/lib/module/shared/components/create-boundary-component/index.js +16 -213
  73. package/lib/module/shared/components/create-boundary-component/index.js.map +1 -1
  74. package/lib/module/shared/components/create-boundary-component/providers/boundary-owner.provider.js +56 -0
  75. package/lib/module/shared/components/create-boundary-component/providers/boundary-owner.provider.js.map +1 -0
  76. package/lib/module/shared/components/create-transition-aware-component.js +30 -8
  77. package/lib/module/shared/components/create-transition-aware-component.js.map +1 -1
  78. package/lib/module/shared/components/overlay/variations/float-overlay.js +1 -1
  79. package/lib/module/shared/components/overlay/variations/float-overlay.js.map +1 -1
  80. package/lib/module/shared/components/screen-container/hooks/use-backdrop-pointer-events.js.map +1 -1
  81. package/lib/module/shared/components/screen-container/index.js +12 -8
  82. package/lib/module/shared/components/screen-container/index.js.map +1 -1
  83. package/lib/module/shared/components/screen-container/layers/backdrop.js +8 -10
  84. package/lib/module/shared/components/screen-container/layers/backdrop.js.map +1 -1
  85. package/lib/module/shared/components/screen-container/layers/content.js +7 -10
  86. package/lib/module/shared/components/screen-container/layers/content.js.map +1 -1
  87. package/lib/module/shared/components/screen-container/layers/maybe-masked-navigation-container.js +4 -4
  88. package/lib/module/shared/components/screen-container/layers/maybe-masked-navigation-container.js.map +1 -1
  89. package/lib/module/shared/components/screen-container/layers/surface-container.js +4 -4
  90. package/lib/module/shared/components/screen-container/layers/surface-container.js.map +1 -1
  91. package/lib/module/shared/constants.js +4 -1
  92. package/lib/module/shared/constants.js.map +1 -1
  93. package/lib/module/shared/providers/screen/animation/helpers/hydrate-transition-state.js +32 -1
  94. package/lib/module/shared/providers/screen/animation/helpers/hydrate-transition-state.js.map +1 -1
  95. package/lib/module/shared/providers/screen/animation/helpers/pipeline.js +2 -0
  96. package/lib/module/shared/providers/screen/animation/helpers/pipeline.js.map +1 -1
  97. package/lib/module/shared/providers/screen/animation/helpers/use-build-transition-state.js +1 -0
  98. package/lib/module/shared/providers/screen/animation/helpers/use-build-transition-state.js.map +1 -1
  99. package/lib/module/shared/providers/screen/screen-composer.js +1 -1
  100. package/lib/module/shared/providers/screen/screen-composer.js.map +1 -1
  101. package/lib/module/shared/providers/screen/styles/helpers/build-resolved-style-map.js +139 -0
  102. package/lib/module/shared/providers/screen/styles/helpers/build-resolved-style-map.js.map +1 -0
  103. package/lib/module/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.js +23 -0
  104. package/lib/module/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.js.map +1 -0
  105. package/lib/module/shared/providers/screen/styles/helpers/split-normalized-style-maps.js +34 -0
  106. package/lib/module/shared/providers/screen/styles/helpers/split-normalized-style-maps.js.map +1 -0
  107. package/lib/module/shared/providers/screen/styles/index.js +4 -0
  108. package/lib/module/shared/providers/screen/styles/index.js.map +1 -0
  109. package/lib/module/shared/providers/screen/{styles.provider.js → styles/styles.provider.js} +48 -40
  110. package/lib/module/shared/providers/screen/styles/styles.provider.js.map +1 -0
  111. package/lib/module/shared/utils/bounds/helpers/compute-bounds-styles.js +2 -2
  112. package/lib/module/shared/utils/bounds/helpers/compute-bounds-styles.js.map +1 -1
  113. package/lib/module/shared/utils/bounds/helpers/style-composers.js +21 -10
  114. package/lib/module/shared/utils/bounds/helpers/style-composers.js.map +1 -1
  115. package/lib/module/shared/utils/bounds/zoom/build.js +56 -29
  116. package/lib/module/shared/utils/bounds/zoom/build.js.map +1 -1
  117. package/lib/typescript/blank-stack/navigators/create-blank-stack-navigator.d.ts +9 -15
  118. package/lib/typescript/blank-stack/navigators/create-blank-stack-navigator.d.ts.map +1 -1
  119. package/lib/typescript/blank-stack/types.d.ts +6 -4
  120. package/lib/typescript/blank-stack/types.d.ts.map +1 -1
  121. package/lib/typescript/component-stack/navigators/create-component-stack-navigator.d.ts +1 -1
  122. package/lib/typescript/shared/components/create-boundary-component/components/boundary-target.d.ts +209 -0
  123. package/lib/typescript/shared/components/create-boundary-component/components/boundary-target.d.ts.map +1 -0
  124. package/lib/typescript/shared/components/create-boundary-component/create-boundary-component.d.ts +8 -0
  125. package/lib/typescript/shared/components/create-boundary-component/create-boundary-component.d.ts.map +1 -0
  126. package/lib/typescript/shared/components/create-boundary-component/hooks/helpers/measurement-rules.d.ts.map +1 -1
  127. package/lib/typescript/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.d.ts +2 -8
  128. package/lib/typescript/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.d.ts.map +1 -1
  129. package/lib/typescript/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.d.ts +0 -1
  130. package/lib/typescript/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.d.ts.map +1 -1
  131. package/lib/typescript/shared/components/create-boundary-component/index.d.ts +216 -12
  132. package/lib/typescript/shared/components/create-boundary-component/index.d.ts.map +1 -1
  133. package/lib/typescript/shared/components/create-boundary-component/providers/boundary-owner.provider.d.ts +35 -0
  134. package/lib/typescript/shared/components/create-boundary-component/providers/boundary-owner.provider.d.ts.map +1 -0
  135. package/lib/typescript/shared/components/create-transition-aware-component.d.ts.map +1 -1
  136. package/lib/typescript/shared/components/screen-container/hooks/use-backdrop-pointer-events.d.ts +1 -1
  137. package/lib/typescript/shared/components/screen-container/hooks/use-backdrop-pointer-events.d.ts.map +1 -1
  138. package/lib/typescript/shared/components/screen-container/index.d.ts.map +1 -1
  139. package/lib/typescript/shared/components/screen-container/layers/backdrop.d.ts +5 -1
  140. package/lib/typescript/shared/components/screen-container/layers/backdrop.d.ts.map +1 -1
  141. package/lib/typescript/shared/components/screen-container/layers/content.d.ts +3 -1
  142. package/lib/typescript/shared/components/screen-container/layers/content.d.ts.map +1 -1
  143. package/lib/typescript/shared/components/screen-container/layers/maybe-masked-navigation-container.d.ts.map +1 -1
  144. package/lib/typescript/shared/constants.d.ts +1 -0
  145. package/lib/typescript/shared/constants.d.ts.map +1 -1
  146. package/lib/typescript/shared/index.d.ts +209 -2
  147. package/lib/typescript/shared/index.d.ts.map +1 -1
  148. package/lib/typescript/shared/providers/screen/animation/helpers/hydrate-transition-state.d.ts +16 -0
  149. package/lib/typescript/shared/providers/screen/animation/helpers/hydrate-transition-state.d.ts.map +1 -1
  150. package/lib/typescript/shared/providers/screen/animation/helpers/pipeline.d.ts.map +1 -1
  151. package/lib/typescript/shared/providers/screen/animation/helpers/use-build-transition-state.d.ts +1 -0
  152. package/lib/typescript/shared/providers/screen/animation/helpers/use-build-transition-state.d.ts.map +1 -1
  153. package/lib/typescript/shared/providers/screen/styles/helpers/build-resolved-style-map.d.ts +11 -0
  154. package/lib/typescript/shared/providers/screen/styles/helpers/build-resolved-style-map.d.ts.map +1 -0
  155. package/lib/typescript/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.d.ts +7 -0
  156. package/lib/typescript/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.d.ts.map +1 -0
  157. package/lib/typescript/shared/providers/screen/styles/helpers/split-normalized-style-maps.d.ts +6 -0
  158. package/lib/typescript/shared/providers/screen/styles/helpers/split-normalized-style-maps.d.ts.map +1 -0
  159. package/lib/typescript/shared/providers/screen/styles/index.d.ts +2 -0
  160. package/lib/typescript/shared/providers/screen/styles/index.d.ts.map +1 -0
  161. package/lib/typescript/shared/providers/screen/{styles.provider.d.ts → styles/styles.provider.d.ts} +3 -5
  162. package/lib/typescript/shared/providers/screen/styles/styles.provider.d.ts.map +1 -0
  163. package/lib/typescript/shared/types/animation.types.d.ts +16 -9
  164. package/lib/typescript/shared/types/animation.types.d.ts.map +1 -1
  165. package/lib/typescript/shared/types/index.d.ts +1 -1
  166. package/lib/typescript/shared/types/index.d.ts.map +1 -1
  167. package/lib/typescript/shared/types/screen.types.d.ts +4 -5
  168. package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
  169. package/lib/typescript/shared/utils/bounds/helpers/compute-bounds-styles.d.ts +1 -11
  170. package/lib/typescript/shared/utils/bounds/helpers/compute-bounds-styles.d.ts.map +1 -1
  171. package/lib/typescript/shared/utils/bounds/helpers/style-composers.d.ts.map +1 -1
  172. package/lib/typescript/shared/utils/bounds/zoom/build.d.ts +1 -1
  173. package/lib/typescript/shared/utils/bounds/zoom/build.d.ts.map +1 -1
  174. package/package.json +1 -1
  175. package/src/blank-stack/navigators/create-blank-stack-navigator.tsx +37 -80
  176. package/src/blank-stack/types.ts +7 -4
  177. package/src/component-stack/navigators/create-component-stack-navigator.tsx +1 -1
  178. package/src/shared/components/create-boundary-component/components/boundary-target.tsx +45 -0
  179. package/src/shared/components/create-boundary-component/create-boundary-component.tsx +282 -0
  180. package/src/shared/components/create-boundary-component/hooks/helpers/measurement-rules.ts +2 -7
  181. package/src/shared/components/create-boundary-component/hooks/use-boundary-measure-and-store.ts +6 -10
  182. package/src/shared/components/create-boundary-component/hooks/use-pending-destination-retry-measurement.ts +3 -2
  183. package/src/shared/components/create-boundary-component/index.tsx +16 -252
  184. package/src/shared/components/create-boundary-component/providers/boundary-owner.provider.tsx +109 -0
  185. package/src/shared/components/create-transition-aware-component.tsx +33 -5
  186. package/src/shared/components/overlay/variations/float-overlay.tsx +1 -1
  187. package/src/shared/components/screen-container/hooks/use-backdrop-pointer-events.ts +1 -2
  188. package/src/shared/components/screen-container/index.tsx +12 -6
  189. package/src/shared/components/screen-container/layers/backdrop.tsx +13 -7
  190. package/src/shared/components/screen-container/layers/content.tsx +47 -43
  191. package/src/shared/components/screen-container/layers/maybe-masked-navigation-container.tsx +6 -4
  192. package/src/shared/components/screen-container/layers/surface-container.tsx +4 -4
  193. package/src/shared/constants.ts +3 -0
  194. package/src/shared/index.ts +0 -1
  195. package/src/shared/providers/screen/animation/helpers/hydrate-transition-state.ts +49 -1
  196. package/src/shared/providers/screen/animation/helpers/pipeline.ts +2 -0
  197. package/src/shared/providers/screen/animation/helpers/use-build-transition-state.ts +2 -0
  198. package/src/shared/providers/screen/screen-composer.tsx +1 -1
  199. package/src/shared/providers/screen/styles/helpers/build-resolved-style-map.ts +185 -0
  200. package/src/shared/providers/screen/styles/helpers/resolve-interpolated-style-output.ts +31 -0
  201. package/src/shared/providers/screen/styles/helpers/split-normalized-style-maps.ts +44 -0
  202. package/src/shared/providers/screen/styles/index.tsx +5 -0
  203. package/src/shared/providers/screen/styles/styles.provider.tsx +173 -0
  204. package/src/shared/types/animation.types.ts +18 -10
  205. package/src/shared/types/index.ts +0 -1
  206. package/src/shared/types/screen.types.ts +5 -5
  207. package/src/shared/utils/bounds/helpers/compute-bounds-styles.ts +2 -1
  208. package/src/shared/utils/bounds/helpers/style-composers.ts +11 -0
  209. package/src/shared/utils/bounds/zoom/build.ts +94 -59
  210. package/lib/commonjs/shared/components/screen-container/deferred-visibility-host.js +0 -43
  211. package/lib/commonjs/shared/components/screen-container/deferred-visibility-host.js.map +0 -1
  212. package/lib/commonjs/shared/hooks/animation/use-associated-style.js +0 -234
  213. package/lib/commonjs/shared/hooks/animation/use-associated-style.js.map +0 -1
  214. package/lib/commonjs/shared/providers/screen/helpers/resolve-interpolated-style-output.js +0 -50
  215. package/lib/commonjs/shared/providers/screen/helpers/resolve-interpolated-style-output.js.map +0 -1
  216. package/lib/commonjs/shared/providers/screen/styles.provider.js.map +0 -1
  217. package/lib/module/shared/components/screen-container/deferred-visibility-host.js +0 -38
  218. package/lib/module/shared/components/screen-container/deferred-visibility-host.js.map +0 -1
  219. package/lib/module/shared/hooks/animation/use-associated-style.js +0 -229
  220. package/lib/module/shared/hooks/animation/use-associated-style.js.map +0 -1
  221. package/lib/module/shared/providers/screen/helpers/resolve-interpolated-style-output.js +0 -44
  222. package/lib/module/shared/providers/screen/helpers/resolve-interpolated-style-output.js.map +0 -1
  223. package/lib/module/shared/providers/screen/styles.provider.js.map +0 -1
  224. package/lib/typescript/shared/components/screen-container/deferred-visibility-host.d.ts +0 -13
  225. package/lib/typescript/shared/components/screen-container/deferred-visibility-host.d.ts.map +0 -1
  226. package/lib/typescript/shared/hooks/animation/use-associated-style.d.ts +0 -32
  227. package/lib/typescript/shared/hooks/animation/use-associated-style.d.ts.map +0 -1
  228. package/lib/typescript/shared/providers/screen/helpers/resolve-interpolated-style-output.d.ts +0 -14
  229. package/lib/typescript/shared/providers/screen/helpers/resolve-interpolated-style-output.d.ts.map +0 -1
  230. package/lib/typescript/shared/providers/screen/styles.provider.d.ts.map +0 -1
  231. package/src/shared/components/screen-container/deferred-visibility-host.tsx +0 -37
  232. package/src/shared/hooks/animation/use-associated-style.ts +0 -297
  233. package/src/shared/providers/screen/helpers/resolve-interpolated-style-output.ts +0 -61
  234. package/src/shared/providers/screen/styles.provider.tsx +0 -164
package/README.md CHANGED
@@ -1,14 +1,76 @@
1
1
  # react-native-screen-transitions
2
2
 
3
- Gesture-driven screen transitions, shared bounds, presets, and custom animation hooks for React Native and Expo.
3
+ Customizable screen transitions for React Native. Build gesture-driven, shared element, and fully custom animations with a simple API.
4
4
 
5
- ## Install
5
+ | iOS | Android |
6
+ | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
7
+ | <video src="https://github.com/user-attachments/assets/c0d17b8f-7268-421c-9051-e242f8ddca76" width="300" height="600" controls></video> | <video src="https://github.com/user-attachments/assets/3f8d5fb1-96d2-4fe3-860d-62f6fb5a687e" width="300" controls></video> |
8
+
9
+ ## Features
10
+
11
+ - **Full Animation Control** – Define exactly how screens enter, exit, and respond to gestures
12
+ - **Bounds API + Navigation Zoom** – Build shared element and fullscreen zoom transitions with one bounds helper
13
+ - **Auto Snap Points** – Use `snapPoints: ["auto"]` and read measured content layout inside your interpolator
14
+ - **Gesture-Aware Scrollables** – Transition-aware `ScrollView` and `FlatList` coordinate with dismiss and snap gestures
15
+ - **Backdrop + Surface Slots** – Animate screen content, backdrops, surfaces, and per-element slots from one interpolator
16
+ - **Ready-Made Presets** – Instagram, Apple Music, X (Twitter) style transitions included
17
+
18
+ ## What's New In 3.4
19
+
20
+ 3.4 introduces a newer, more explicit path for shared transitions and snap-driven layouts.
21
+ Use the notes below as the source of truth when migrating examples or generating docs.
22
+
23
+ ### Added / Expanded
24
+
25
+ - **Auto snap sizing** with `snapPoints: ["auto"]` and `current.layouts.content`
26
+ - **Compound bounds components** via `Transition.Boundary.View`, `Transition.Boundary.Trigger`, and `Transition.Boundary.Target`
27
+ - **`Transition.createBoundaryComponent`** for building custom boundary wrappers, including `alreadyAnimated` support
28
+ - **Navigation-style bounds zoom** through `bounds({ id }).navigation.zoom()`
29
+ - **`navigationMaskEnabled`** for library-managed masked navigation transitions
30
+ - **Ancestor targeting** in `useScreenGesture()` and `useScreenAnimation()`
31
+ - **Gesture release tuning** with `gestureReleaseVelocityScale` and `gestureReleaseVelocityMax`
32
+ - **Surface slot support** through `surfaceComponent` and the interpolator `surface` slot
33
+ - **Animated `props` support across all slots** via `{ style, props }` slot returns
34
+ - **Optional first-screen animation** with `experimental_animateOnInitialMount`
35
+ - **`logicallySettled`** for choreography that should finish before a spring is fully at rest
36
+
37
+ ### Deprecated / Replaced
38
+
39
+ - **`sharedBoundTag` on transition-aware components is deprecated for new work.** Prefer `Transition.Boundary.*` for new shared transition flows.
40
+ - **`Transition.MaskedView` is deprecated for new work.** Prefer `Transition.Boundary.*` with `bounds({ id }).navigation.zoom()` and `navigationMaskEnabled` for library-managed shared navigation transitions.
41
+ - **`createComponentStackNavigator` is deprecated.** Prefer blank stack for embedded and independent flows.
42
+ - **`expandViaScrollView` was renamed to `sheetScrollGestureBehavior`.**
43
+ - **Flat interpolator keys are deprecated.** Use `content`, `backdrop`, and `surface` instead of `contentStyle`, `backdropStyle`, and `overlayStyle`.
44
+ - **Legacy interpolator accessors are deprecated.** Use `current.layouts` and `current.snapIndex` instead of top-level `layouts` and `snapIndex`.
45
+ - **If you saw older alpha docs using `backgroundComponent` / `background`, use `surfaceComponent` / `surface`.**
46
+
47
+ ### Removed
48
+
49
+ - Deprecated screen overlay mode and legacy overlay animation props were removed.
50
+
51
+ ## When to Use This Library
52
+
53
+ | Use Case | This Library | Alternative |
54
+ |----------|--------------|-------------|
55
+ | Custom transitions (slide, zoom, fade variations) | Yes | `@react-navigation/stack` works too |
56
+ | Shared element transitions | **Yes** | Limited options elsewhere |
57
+ | Multi-stop sheets (bottom, top, side) with snap points | **Yes** | Dedicated sheet libraries |
58
+ | Gesture-driven animations (drag to dismiss, elastic) | **Yes** | Requires custom implementation |
59
+ | Instagram/Apple Music/Twitter-style transitions | **Yes** | Custom implementation |
60
+ | Simple push/pop with platform defaults | Overkill | `@react-navigation/native-stack` |
61
+ | Maximum raw performance on low-end devices | Not ideal | `@react-navigation/native-stack` |
62
+
63
+ **Choose this library when** you need custom animations, shared elements, or gesture-driven transitions that go beyond platform defaults.
64
+
65
+ **Choose native-stack when** you want platform-native transitions with zero configuration and maximum performance on low-end Android devices.
66
+
67
+ ## Installation
6
68
 
7
69
  ```bash
8
70
  npm install react-native-screen-transitions
9
71
  ```
10
72
 
11
- Peer dependencies:
73
+ ### Peer Dependencies
12
74
 
13
75
  ```bash
14
76
  npm install react-native-reanimated react-native-gesture-handler \
@@ -17,15 +79,19 @@ npm install react-native-reanimated react-native-gesture-handler \
17
79
  react-native-safe-area-context
18
80
  ```
19
81
 
20
- ## Quickstart
82
+ ---
83
+
84
+ ## Quick Start
85
+
86
+ ### 1. Create a Stack
21
87
 
22
88
  ```tsx
23
- import Transition from "react-native-screen-transitions";
24
89
  import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";
90
+ import Transition from "react-native-screen-transitions";
25
91
 
26
92
  const Stack = createBlankStackNavigator();
27
93
 
28
- export function AppStack() {
94
+ function App() {
29
95
  return (
30
96
  <Stack.Navigator>
31
97
  <Stack.Screen name="Home" component={HomeScreen} />
@@ -41,9 +107,990 @@ export function AppStack() {
41
107
  }
42
108
  ```
43
109
 
44
- ## Docs
110
+ ### 2. With Expo Router
111
+
112
+ ```tsx
113
+ import { withLayoutContext } from "expo-router";
114
+ import {
115
+ createBlankStackNavigator,
116
+ type BlankStackNavigationOptions,
117
+ } from "react-native-screen-transitions/blank-stack";
118
+
119
+ const { Navigator } = createBlankStackNavigator();
120
+
121
+ export const Stack = withLayoutContext<
122
+ BlankStackNavigationOptions,
123
+ typeof Navigator
124
+ >(Navigator);
125
+ ```
126
+
127
+ ### 3. Static Config
128
+
129
+ Blank stack-specific navigator props follow React Navigation's custom navigator pattern.
130
+
131
+ For the dynamic API, pass them to `<Stack.Navigator>`:
132
+
133
+ ```tsx
134
+ const Stack = createBlankStackNavigator();
135
+
136
+ function App() {
137
+ return (
138
+ <Stack.Navigator independent enableNativeScreens={false}>
139
+ <Stack.Screen name="Home" component={HomeScreen} />
140
+ <Stack.Screen name="Detail" component={DetailScreen} />
141
+ </Stack.Navigator>
142
+ );
143
+ }
144
+ ```
145
+
146
+ For the static API, keep them in the same config object:
147
+
148
+ ```tsx
149
+ import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";
150
+
151
+ const Stack = createBlankStackNavigator({
152
+ initialRouteName: "Home",
153
+ screens: {
154
+ Home: HomeScreen,
155
+ Detail: DetailScreen,
156
+ },
157
+ independent: true,
158
+ enableNativeScreens: false,
159
+ });
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Presets
165
+
166
+ Use built-in presets for common transitions:
167
+
168
+ ```tsx
169
+ <Stack.Screen
170
+ name="Detail"
171
+ options={{
172
+ ...Transition.Presets.SlideFromBottom(),
173
+ }}
174
+ />
175
+ ```
176
+
177
+ | Preset | Description |
178
+ | -------------------------------------- | --------------------------------------- |
179
+ | `SlideFromTop()` | Slides in from top |
180
+ | `SlideFromBottom()` | Slides in from bottom (modal-style) |
181
+ | `ZoomIn()` | Scales in with fade |
182
+ | `DraggableCard()` | Multi-directional drag with scaling |
183
+ | `ElasticCard()` | Elastic drag with overlay |
184
+ | `SharedIGImage({ sharedBoundTag })` | Legacy Instagram-style shared image preset |
185
+ | `SharedAppleMusic({ sharedBoundTag })` | Legacy Apple Music-style shared element preset |
186
+ | `SharedXImage({ sharedBoundTag })` | Legacy X (Twitter)-style image transition preset |
187
+
188
+ ---
189
+
190
+ ## Custom Animations
191
+
192
+ ### The Basics
193
+
194
+ Every screen has a `progress` value that goes from 0 → 1 → 2:
195
+
196
+ ```
197
+ 0 ─────────── 1 ─────────── 2
198
+ entering visible exiting
199
+ ```
200
+
201
+ When navigating from A to B:
202
+ - **Screen B**: progress goes `0 → 1` (entering)
203
+ - **Screen A**: progress goes `1 → 2` (exiting)
204
+
205
+ ### Simple Fade
206
+
207
+ ```tsx
208
+ options={{
209
+ screenStyleInterpolator: ({ progress }) => {
210
+ "worklet";
211
+ return {
212
+ content: {
213
+ style: {
214
+ opacity: interpolate(progress, [0, 1, 2], [0, 1, 0]),
215
+ },
216
+ },
217
+ };
218
+ },
219
+ }}
220
+ ```
221
+
222
+ ### Slide from Right
223
+
224
+ ```tsx
225
+ options={{
226
+ screenStyleInterpolator: ({ progress, current: { layouts: { screen } } }) => {
227
+ "worklet";
228
+ return {
229
+ content: {
230
+ style: {
231
+ transform: [{
232
+ translateX: interpolate(
233
+ progress,
234
+ [0, 1, 2],
235
+ [screen.width, 0, -screen.width * 0.3]
236
+ ),
237
+ }],
238
+ },
239
+ },
240
+ };
241
+ },
242
+ }}
243
+ ```
244
+
245
+ ### Slide from Bottom
246
+
247
+ ```tsx
248
+ options={{
249
+ screenStyleInterpolator: ({ progress, current: { layouts: { screen } } }) => {
250
+ "worklet";
251
+ return {
252
+ content: {
253
+ style: {
254
+ transform: [{
255
+ translateY: interpolate(progress, [0, 1], [screen.height, 0]),
256
+ }],
257
+ },
258
+ },
259
+ };
260
+ },
261
+ }}
262
+ ```
263
+
264
+ ### Return Styles
265
+
266
+ Your interpolator can return:
267
+
268
+ ```tsx
269
+ return {
270
+ content: { style: { ... }, props: { ... } }, // Main screen slot
271
+ backdrop: { style: { ... }, props: { ... } }, // Backdrop / blur / dimming
272
+ surface: { style: { ... }, props: { ... } }, // Custom surface layer
273
+ ["my-id"]: { style: { ... }, props: { ... } }, // Specific element via styleId
274
+ };
275
+ ```
276
+
277
+ Every slot supports animated `style` and animated `props`.
278
+ Use the shorthand style-only form when you only need styles, or the explicit
279
+ `{ style, props }` form when the wrapped component exposes animatable props.
280
+
281
+ Return `null`, `undefined`, or `{}` when you want an interpolator frame to apply no transition styles:
282
+
283
+ ```tsx
284
+ screenStyleInterpolator: ({ bounds }) => {
285
+ "worklet";
286
+
287
+ const snapshot = bounds.getSnapshot("hero");
288
+ if (!snapshot) return null;
289
+
290
+ return {
291
+ content: {
292
+ style: { opacity: 1 },
293
+ },
294
+ };
295
+ };
296
+ ```
297
+
298
+ ### Animation Specs
299
+
300
+ Control timing with spring configs:
301
+
302
+ ```tsx
303
+ options={{
304
+ screenStyleInterpolator: myInterpolator,
305
+ transitionSpec: {
306
+ open: { stiffness: 1000, damping: 500, mass: 3 }, // Screen enters
307
+ close: { stiffness: 1000, damping: 500, mass: 3 }, // Screen exits
308
+ expand: { stiffness: 300, damping: 30 }, // Snap point increases
309
+ collapse: { stiffness: 300, damping: 30 }, // Snap point decreases
310
+ },
311
+ }}
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Gestures
317
+
318
+ Enable swipe-to-dismiss:
319
+
320
+ ```tsx
321
+ options={{
322
+ gestureEnabled: true,
323
+ gestureDirection: "vertical",
324
+ ...Transition.Presets.SlideFromBottom(),
325
+ }}
326
+ ```
327
+
328
+ ### Gesture Options
329
+
330
+ | Option | Description |
331
+ | ------------------------- | ------------------------------------------------------------------------ |
332
+ | `gestureEnabled` | Enable swipe-to-dismiss (snap sheets: `false` blocks dismiss-to-0 only) |
333
+ | `gestureDirection` | Direction(s) for swipe gesture |
334
+ | `gestureActivationArea` | Where gesture can start |
335
+ | `gestureResponseDistance` | Pixel threshold for activation |
336
+ | `gestureVelocityImpact` | How much velocity affects dismissal (default: 0.3) |
337
+ | `gestureDrivesProgress` | Whether gesture controls animation progress (default: true) |
338
+ | `snapVelocityImpact` | How much velocity affects snap targeting (default: 0.1, lower = iOS-like)|
339
+ | `gestureReleaseVelocityScale` | Multiplier for release velocity used by post-release spring animations |
340
+ | `gestureReleaseVelocityMax` | Max absolute normalized release velocity used by spring animations |
341
+ | `sheetScrollGestureBehavior` | Nested scroll handoff mode: `"expand-and-collapse"` or `"collapse-only"` |
342
+ | `gestureSnapLocked` | Lock gesture-based snap movement to current snap point |
343
+ | `backdropBehavior` | Touch handling for backdrop area |
344
+ | `backdropComponent` | Custom backdrop component (replaces default backdrop + press behavior) |
345
+
346
+ ### Gesture Direction
347
+
348
+ ```tsx
349
+ gestureDirection: "horizontal" // swipe left to dismiss
350
+ gestureDirection: "horizontal-inverted" // swipe right to dismiss
351
+ gestureDirection: "vertical" // swipe down to dismiss
352
+ gestureDirection: "vertical-inverted" // swipe up to dismiss
353
+ gestureDirection: "bidirectional" // any direction
354
+
355
+ // Or combine multiple:
356
+ gestureDirection: ["horizontal", "vertical"]
357
+ ```
358
+
359
+ ### Gesture Activation Area
360
+
361
+ ```tsx
362
+ // Simple - same for all edges
363
+ gestureActivationArea: "edge" // only from screen edges
364
+ gestureActivationArea: "screen" // anywhere on screen
365
+
366
+ // Per-side configuration
367
+ gestureActivationArea: {
368
+ left: "edge",
369
+ right: "screen",
370
+ top: "edge",
371
+ bottom: "screen",
372
+ }
373
+ ```
374
+
375
+ ### With ScrollViews
376
+
377
+ Use transition-aware scrollables so gestures work correctly:
378
+
379
+ ```tsx
380
+ <Transition.ScrollView>
381
+ {/* content */}
382
+ </Transition.ScrollView>
383
+
384
+ <Transition.FlatList data={items} renderItem={...} />
385
+ ```
386
+
387
+ Gesture rules with scrollables:
388
+ - **vertical** – only activates when scrolled to top
389
+ - **vertical-inverted** – only activates when scrolled to bottom
390
+ - **horizontal** – only activates at left/right scroll edges
391
+
392
+ ---
393
+
394
+ ## Snap Points
395
+
396
+ Create multi-stop sheets that snap to defined positions. Works with any gesture direction (bottom sheets, top sheets, side sheets), and supports intrinsic content sizing with `"auto"` snap points.
397
+
398
+ ### Basic Configuration
399
+
400
+ ```tsx
401
+ // Bottom sheet (most common)
402
+ <Stack.Screen
403
+ name="Sheet"
404
+ options={{
405
+ gestureEnabled: true,
406
+ gestureDirection: "vertical",
407
+ snapPoints: [0.5, 1], // 50% and 100% of screen
408
+ initialSnapIndex: 0, // Start at 50%
409
+ backdropBehavior: "dismiss", // Tap backdrop to dismiss
410
+ ...Transition.Presets.SlideFromBottom(),
411
+ }}
412
+ />
413
+
414
+ // Side sheet (same API, different direction)
415
+ <Stack.Screen
416
+ name="SidePanel"
417
+ options={{
418
+ gestureEnabled: true,
419
+ gestureDirection: "horizontal",
420
+ snapPoints: [0.3, 0.7, 1], // 30%, 70%, 100% of screen width
421
+ initialSnapIndex: 1,
422
+ // Add a horizontal screenStyleInterpolator for drawer-style motion
423
+ }}
424
+ />
425
+
426
+ // Auto-sized sheet
427
+ <Stack.Screen
428
+ name="Composer"
429
+ options={{
430
+ gestureEnabled: true,
431
+ gestureDirection: "vertical",
432
+ snapPoints: ["auto", 1],
433
+ initialSnapIndex: 0,
434
+ backdropBehavior: "collapse",
435
+ ...Transition.Presets.SlideFromBottom(),
436
+ }}
437
+ />
438
+ ```
439
+
440
+ ### Options
441
+
442
+ | Option | Description |
443
+ | ------------------ | -------------------------------------------------------------------- |
444
+ | `snapPoints` | Array of fractions (0-1) or `"auto"` values where sheet can rest |
445
+ | `initialSnapIndex` | Index of initial snap point (default: 0) |
446
+ | `gestureSnapLocked` | Locks gesture snapping to current point (programmatic `snapTo` still works) |
447
+ | `sheetScrollGestureBehavior` | Nested scroll handoff mode for snap sheets |
448
+ | `backdropBehavior` | Touch handling: `"block"`, `"passthrough"`, `"dismiss"`, `"collapse"`|
449
+ | `backdropComponent` | Custom backdrop component; replaces default backdrop + tap handling |
450
+
451
+ ### Auto Snap Points
452
+
453
+ When you use `"auto"`, the library measures the content height and exposes it in `current.layouts.content`:
454
+
455
+ ```tsx
456
+ screenStyleInterpolator: ({ current }) => {
457
+ "worklet";
458
+
459
+ const contentHeight = current.layouts.content?.height ?? 0;
460
+
461
+ return {
462
+ content: {
463
+ style: {
464
+ opacity: interpolate(current.snapIndex, [0, 1], [0.8, 1]),
465
+ },
466
+ },
467
+ "sheet-height-debug": {
468
+ style: {
469
+ opacity: contentHeight > 0 ? 1 : 0,
470
+ },
471
+ },
472
+ };
473
+ }
474
+ ```
475
+
476
+ #### backdropBehavior Values
477
+
478
+ | Value | Description |
479
+ | --------------- | ---------------------------------------------------------------- |
480
+ | `"block"` | Backdrop catches all touches (default) |
481
+ | `"passthrough"` | Touches pass through to content behind |
482
+ | `"dismiss"` | Tapping backdrop dismisses the screen |
483
+ | `"collapse"` | Tapping backdrop collapses to next lower snap point, then dismisses |
484
+
485
+ #### Custom Backdrop Component
486
+
487
+ Use `backdropComponent` when you want full control over backdrop visuals and interactions.
488
+
489
+ - When provided, it replaces the default backdrop entirely (including default tap behavior)
490
+ - You are responsible for dismiss/collapse actions inside the custom component
491
+ - `backdropBehavior` still controls container-level pointer event behavior
492
+
493
+ ```tsx
494
+ import { router } from "expo-router";
495
+ import { Pressable } from "react-native";
496
+ import Animated, { interpolate, useAnimatedStyle } from "react-native-reanimated";
497
+ import { useScreenAnimation } from "react-native-screen-transitions";
498
+
499
+ function SheetBackdrop() {
500
+ const animation = useScreenAnimation();
501
+
502
+ const style = useAnimatedStyle(() => ({
503
+ opacity: interpolate(animation.value.current.progress, [0, 1], [0, 0.4]),
504
+ backgroundColor: "#000",
505
+ }));
506
+
507
+ return (
508
+ <Pressable style={{ flex: 1 }} onPress={() => router.back()}>
509
+ <Animated.View style={[{ flex: 1 }, style]} />
510
+ </Pressable>
511
+ );
512
+ }
513
+
514
+ <Stack.Screen
515
+ name="Sheet"
516
+ options={{
517
+ snapPoints: [0.5, 1],
518
+ backdropBehavior: "dismiss",
519
+ backdropComponent: SheetBackdrop,
520
+ }}
521
+ />
522
+ ```
523
+
524
+ ### Programmatic Control
525
+
526
+ Control snap points from anywhere in your app:
527
+
528
+ ```tsx
529
+ import { snapTo } from "react-native-screen-transitions";
530
+
531
+ function BottomSheet() {
532
+ // Expand to full height (index 1)
533
+ const expand = () => snapTo(1);
534
+
535
+ // Collapse to half height (index 0)
536
+ const collapse = () => snapTo(0);
537
+
538
+ return (
539
+ <View>
540
+ <Button title="Expand" onPress={expand} />
541
+ <Button title="Collapse" onPress={collapse} />
542
+ </View>
543
+ );
544
+ }
545
+ ```
546
+
547
+ The animated snap point index is available via `current.snapIndex` in `ScreenInterpolationProps`:
548
+
549
+ ```tsx
550
+ screenStyleInterpolator: ({ current }) => {
551
+ // snapIndex interpolates between snap point indices
552
+ // e.g., 0.5 means halfway between snap point 0 and 1
553
+ return {
554
+ content: {
555
+ style: {
556
+ opacity: interpolate(current.snapIndex, [0, 1], [0.5, 1]),
557
+ },
558
+ },
559
+ };
560
+ }
561
+ ```
562
+
563
+ ### ScrollView Behavior
564
+
565
+ With `Transition.ScrollView` inside a snap-enabled sheet:
566
+ - **`sheetScrollGestureBehavior: "expand-and-collapse"`**: At boundary, swipe up expands and swipe down collapses (or dismisses at min if enabled)
567
+ - **`sheetScrollGestureBehavior: "collapse-only"`**: Expand works only via deadspace; collapse/dismiss via scroll still works at boundary
568
+ - **Scrolled into content**: Normal scroll behavior
569
+
570
+ ### Snap Animation Specs
571
+
572
+ Customize snap animations separately from enter/exit:
573
+
574
+ ```tsx
575
+ transitionSpec: {
576
+ open: { stiffness: 1000, damping: 500, mass: 3 }, // Screen enter
577
+ close: { stiffness: 1000, damping: 500, mass: 3 }, // Screen exit
578
+ expand: { stiffness: 300, damping: 30 }, // Snap up
579
+ collapse: { stiffness: 300, damping: 30 }, // Snap down
580
+ }
581
+ ```
582
+
583
+ ---
584
+
585
+ ## Shared Elements (Bounds API)
586
+
587
+ Animate elements between screens by tagging them. In 3.4, the recommended and forward-compatible API is `Transition.Boundary.*` for explicit bounds ownership.
588
+
589
+ `sharedBoundTag` on transition-aware components is deprecated and retained for legacy flows and presets.
590
+
591
+ ### 1. Tag the Source
592
+
593
+ ```tsx
594
+ <Transition.Boundary.Trigger
595
+ id="avatar"
596
+ onPress={() => navigation.navigate("Profile")}
597
+ >
598
+ <Image source={avatar} style={{ width: 50, height: 50 }} />
599
+ </Transition.Boundary.Trigger>
600
+ ```
601
+
602
+ If the boundary owner is larger than the visual element you want to match,
603
+ wrap the measured descendant in `Transition.Boundary.Target`:
604
+
605
+ ```tsx
606
+ <Transition.Boundary.Trigger
607
+ id="avatar"
608
+ onPress={() => navigation.navigate("Profile")}
609
+ style={styles.card}
610
+ >
611
+ <Transition.Boundary.Target>
612
+ <Image source={avatar} style={styles.image} />
613
+ </Transition.Boundary.Target>
614
+
615
+ <View style={styles.copy}>
616
+ <Text style={styles.title}>Profile</Text>
617
+ </View>
618
+ </Transition.Boundary.Trigger>
619
+ ```
620
+
621
+ ### 2. Tag the Destination
622
+
623
+ ```tsx
624
+ <Transition.Boundary.View id="avatar">
625
+ <Image source={avatar} style={{ width: 200, height: 200 }} />
626
+ </Transition.Boundary.View>
627
+ ```
628
+
629
+ ### 3. Use in Interpolator
630
+
631
+ ```tsx
632
+ screenStyleInterpolator: ({ bounds }) => {
633
+ "worklet";
634
+ return {
635
+ avatar: bounds({ id: "avatar", method: "transform" }),
636
+ };
637
+ };
638
+ ```
639
+
640
+ ### Navigation Zoom
641
+
642
+ For fullscreen, navigation-style shared transitions:
643
+
644
+ ```tsx
645
+ screenStyleInterpolator: ({ bounds }) => {
646
+ "worklet";
647
+ return bounds({ id: "avatar" }).navigation.zoom({
648
+ target: "fullscreen",
649
+ });
650
+ };
651
+ ```
652
+
653
+ ### Bounds Options
654
+
655
+ | Option | Values | Description |
656
+ | ----------- | ---------------------------------- | ----------------------------- |
657
+ | `id` | string | The boundary id to match |
658
+ | `group` | string | Optional group key for paged/detail flows |
659
+ | `method` | `"transform"` `"size"` `"content"` | How to animate |
660
+ | `space` | `"relative"` `"absolute"` | Coordinate space |
661
+ | `scaleMode` | `"match"` `"none"` `"uniform"` | Aspect ratio handling |
662
+ | `raw` | boolean | Return raw values |
663
+
664
+ ---
665
+
666
+ ## Overlays
667
+
668
+ Persistent UI that animates with the stack:
669
+
670
+ ```tsx
671
+ const TabBar = ({ focusedIndex, progress }) => {
672
+ const style = useAnimatedStyle(() => ({
673
+ transform: [{ translateY: interpolate(progress.value, [0, 1], [100, 0]) }],
674
+ }));
675
+ return <Animated.View style={[styles.tabBar, style]} />;
676
+ };
677
+
678
+ <Stack.Screen
679
+ name="Home"
680
+ options={{
681
+ overlay: TabBar,
682
+ overlayShown: true,
683
+ }}
684
+ />
685
+ ```
686
+
687
+ ### Overlay Props
688
+
689
+ | Prop | Description |
690
+ | -------------- | ------------------------------ |
691
+ | `focusedRoute` | Currently focused route |
692
+ | `focusedIndex` | Index of focused screen |
693
+ | `routes` | All routes in the stack |
694
+ | `progress` | Stack progress (derived value) |
695
+ | `navigation` | Navigation prop |
696
+ | `meta` | Custom metadata from options |
697
+
698
+ ---
699
+
700
+ ## Transition Components
701
+
702
+ | Component | Description |
703
+ | ----------------------- | -------------------------------------- |
704
+ | `Transition.View` | Animated view; `sharedBoundTag` usage is legacy/deprecated |
705
+ | `Transition.Pressable` | Pressable; `sharedBoundTag` usage is legacy/deprecated |
706
+ | `Transition.ScrollView` | ScrollView with gesture coordination |
707
+ | `Transition.FlatList` | FlatList with gesture coordination |
708
+ | `Transition.Boundary.View` | Explicit bounds destination/source registration |
709
+ | `Transition.Boundary.Trigger` | Pressable boundary owner that captures source bounds on press |
710
+ | `Transition.Boundary.Target` | Optional nested measurement target inside a boundary owner |
711
+ | `Transition.MaskedView` | Deprecated legacy reveal helper (requires native) |
712
+
713
+ Helper exports:
714
+
715
+ - `Transition.createBoundaryComponent(Component, { alreadyAnimated?: boolean })`
716
+ - `Transition.createTransitionAwareComponent(Component, { isScrollable?: boolean, alreadyAnimated?: boolean })`
717
+
718
+ ---
719
+
720
+ ## Hooks
721
+
722
+ ### useScreenAnimation
723
+
724
+ Access animation state inside a screen:
725
+
726
+ ```tsx
727
+ import { useScreenAnimation } from "react-native-screen-transitions";
728
+
729
+ function DetailScreen() {
730
+ const animation = useScreenAnimation();
731
+ const parentAnimation = useScreenAnimation("parent");
732
+
733
+ const style = useAnimatedStyle(() => ({
734
+ opacity: parentAnimation.value.current.progress,
735
+ }));
736
+
737
+ return <Animated.View style={style}>...</Animated.View>;
738
+ }
739
+ ```
740
+
741
+ ### useScreenState
742
+
743
+ Get navigation state without animation values:
744
+
745
+ ```tsx
746
+ import { useScreenState } from "react-native-screen-transitions";
747
+
748
+ function DetailScreen() {
749
+ const { index, focusedRoute, routes, navigation } = useScreenState();
750
+ // ...
751
+ }
752
+ ```
753
+
754
+ ### useHistory
755
+
756
+ Access navigation history across the app:
757
+
758
+ ```tsx
759
+ import { useHistory } from "react-native-screen-transitions";
760
+
761
+ function MyComponent() {
762
+ const { getRecent, getPath } = useHistory();
763
+
764
+ const recentScreens = getRecent(5); // Last 5 screens
765
+ const path = getPath(fromKey, toKey); // Path between screens
766
+ }
767
+ ```
768
+
769
+ ### useScreenGesture
770
+
771
+ Coordinate your own pan gestures with the navigation gesture:
772
+
773
+ ```tsx
774
+ import { useScreenGesture } from "react-native-screen-transitions";
775
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
776
+
777
+ function MyScreen() {
778
+ const screenGesture = useScreenGesture();
779
+ const parentGesture = useScreenGesture("parent");
780
+
781
+ const myPanGesture = Gesture.Pan()
782
+ .simultaneousWithExternalGesture(screenGesture, parentGesture)
783
+ .onUpdate((e) => {
784
+ // Your gesture logic
785
+ });
786
+
787
+ return (
788
+ <GestureDetector gesture={myPanGesture}>
789
+ <View />
790
+ </GestureDetector>
791
+ );
792
+ }
793
+ ```
794
+
795
+ Use this when you have custom pan gestures that need to work alongside screen dismiss gestures.
796
+ You can target `"self"`, `"parent"`, `"root"`, or `{ ancestor: number }`.
797
+
798
+ ---
799
+
800
+ ## Advanced Animation Props
801
+
802
+ The full `screenStyleInterpolator` receives these props:
803
+
804
+ | Prop | Description |
805
+ | ---------------- | -------------------------------------------------------- |
806
+ | `progress` | Combined progress (0-2) |
807
+ | `stackProgress` | Accumulated progress across entire stack |
808
+ | `focused` | Whether this screen is the topmost in the stack |
809
+ | `current` | Current screen state |
810
+ | `previous` | Previous screen state |
811
+ | `next` | Next screen state |
812
+ | `active` | Screen driving the transition |
813
+ | `inactive` | Screen NOT driving the transition |
814
+ | `insets` | Safe area insets |
815
+ | `bounds` | Shared element bounds function |
816
+
817
+ Prefer `current.snapIndex`, `current.layouts.screen`, and `current.layouts.content` for new code.
818
+
819
+ ### Screen State Properties
820
+
821
+ Each screen state (`current`, `previous`, `next`, `active`, `inactive`) contains:
822
+
823
+ | Property | Description |
824
+ | ----------- | ---------------------------------------- |
825
+ | `progress` | Animation progress (0 or 1) |
826
+ | `closing` | Whether closing (0 or 1) |
827
+ | `entering` | Whether entering (0 or 1) |
828
+ | `animating` | Whether animating (0 or 1) |
829
+ | `logicallySettled` | Whether choreography can treat the screen as done |
830
+ | `snapIndex` | Animated snap point index for this screen |
831
+ | `layouts` | Screen and measured content layouts |
832
+ | `gesture` | Gesture values (x, y, `normX`, `normY`, etc.) |
833
+ | `meta` | Custom metadata from options |
834
+
835
+ ### Using `meta` for Conditional Logic
836
+
837
+ Pass custom data between screens:
838
+
839
+ ```tsx
840
+ // Screen A
841
+ options={{ meta: { hideTabBar: true } }}
842
+
843
+ // Screen B reads it
844
+ screenStyleInterpolator: (props) => {
845
+ "worklet";
846
+ const hideTabBar = props.inactive?.meta?.hideTabBar;
847
+ // ...
848
+ };
849
+ ```
850
+
851
+ ### Animate Individual Elements
852
+
853
+ Use `styleId` to target specific elements:
854
+
855
+ ```tsx
856
+ // In options
857
+ screenStyleInterpolator: ({ progress }) => {
858
+ "worklet";
859
+ return {
860
+ "hero-image": {
861
+ style: {
862
+ opacity: interpolate(progress, [0, 1], [0, 1]),
863
+ },
864
+ },
865
+ };
866
+ };
867
+
868
+ // In component
869
+ <Transition.View styleId="hero-image">
870
+ <Image source={...} />
871
+ </Transition.View>
872
+ ```
873
+
874
+ ---
875
+
876
+ ## Stack Types
877
+
878
+ Blank stack and native stack are the primary APIs. Component stack remains available as a deprecated compatibility API.
879
+
880
+ | Stack | Best For |
881
+ | ------------------- | --------------------------------------------------------- |
882
+ | **Blank Stack** | Most apps. Full control, all features. |
883
+ | **Native Stack** | When you need native screen primitives. |
884
+ | **Component Stack** | Legacy embedded-flow API. Prefer blank stack instead. |
885
+
886
+ ### Blank Stack
887
+
888
+ The default choice. Uses `react-native-screens` for native screen containers, with animations powered by Reanimated worklets running on the UI thread (not the JS thread).
889
+
890
+ ```tsx
891
+ import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";
892
+ ```
893
+
894
+ ### Native Stack
895
+
896
+ Extends `@react-navigation/native-stack`. Requires `enableTransitions: true`.
897
+
898
+ ```tsx
899
+ import { createNativeStackNavigator } from "react-native-screen-transitions/native-stack";
900
+
901
+ <Stack.Screen
902
+ name="Detail"
903
+ options={{
904
+ enableTransitions: true,
905
+ ...Transition.Presets.SlideFromBottom(),
906
+ }}
907
+ />
908
+ ```
909
+
910
+ ### Component Stack (Deprecated)
911
+
912
+ > **Note:** Prefer blank stack for new work. It now covers the embedded and independent flow use case.
913
+
914
+ Standalone navigator, not connected to React Navigation. Kept for compatibility with older integrations.
915
+
916
+ ```tsx
917
+ import { createComponentStackNavigator } from "react-native-screen-transitions/component-stack";
918
+
919
+ const Stack = createComponentStackNavigator();
920
+
921
+ <Stack.Navigator initialRouteName="step1">
922
+ <Stack.Screen name="step1" component={Step1} />
923
+ <Stack.Screen name="step2" component={Step2} />
924
+ </Stack.Navigator>
925
+ ```
926
+
927
+ ---
928
+
929
+ ## Caveats & Trade-offs
930
+
931
+ ### Native Stack
932
+
933
+ The Native Stack uses transparent modal presentation to intercept transitions. This has trade-offs:
934
+
935
+ - **Delayed touch events** – Exiting screens may have briefly delayed touch response
936
+ - **beforeRemove listeners** – Relies on navigation lifecycle events
937
+ - **Rapid navigation** – Some edge cases with very fast navigation sequences
938
+
939
+ For most apps, Blank Stack avoids these issues entirely.
940
+
941
+ ### Component Stack (Experimental)
942
+
943
+ - **No deep linking** – Routes aren't part of your URL structure
944
+ - **Isolated state** – Doesn't affect parent navigation
945
+ - **Touch pass-through** – Uses `pointerEvents="box-none"` by default
946
+
947
+ ---
948
+
949
+ ## Experimental Features
950
+
951
+ ### High Refresh Rate
952
+
953
+ Force maximum refresh rate during transitions (for 90Hz/120Hz displays):
954
+
955
+ ```tsx
956
+ options={{
957
+ experimental_enableHighRefreshRate: true,
958
+ }}
959
+ ```
960
+
961
+ ### Animate On Initial Mount
962
+
963
+ Animate the first screen in a navigator instead of snapping it directly to the settled state:
964
+
965
+ ```tsx
966
+ options={{
967
+ experimental_animateOnInitialMount: true,
968
+ }}
969
+ ```
970
+
971
+ ---
972
+
973
+ ## Legacy Masked View Setup (Deprecated)
974
+
975
+ `Transition.MaskedView` and `sharedBoundTag` are deprecated for new work.
976
+
977
+ Prefer `Transition.Boundary.*` for explicit shared-element ownership, and prefer `bounds({ id }).navigation.zoom()` with `navigationMaskEnabled` when you want library-managed navigation-style masked transitions.
978
+
979
+ This section is kept for compatibility with legacy presets such as `SharedIGImage` and `SharedAppleMusic`.
980
+
981
+ > **Note**: Requires native code. Will not work in Expo Go.
982
+
983
+ ### Installation
984
+
985
+ ```bash
986
+ # Expo
987
+ npx expo install @react-native-masked-view/masked-view
988
+
989
+ # Bare React Native
990
+ npm install @react-native-masked-view/masked-view
991
+ cd ios && pod install
992
+ ```
993
+
994
+ ### Full Example
995
+
996
+ **1. Source Screen** – Tag pressable elements:
997
+
998
+ ```tsx
999
+ // app/index.tsx
1000
+ import { router } from "expo-router";
1001
+ import { View } from "react-native";
1002
+ import Transition from "react-native-screen-transitions";
1003
+
1004
+ export default function HomeScreen() {
1005
+ return (
1006
+ <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
1007
+ <Transition.Pressable
1008
+ sharedBoundTag="album-art"
1009
+ style={{
1010
+ width: 200,
1011
+ height: 200,
1012
+ backgroundColor: "#1DB954",
1013
+ borderRadius: 12,
1014
+ }}
1015
+ onPress={() => {
1016
+ router.push({
1017
+ pathname: "/details",
1018
+ params: { sharedBoundTag: "album-art" },
1019
+ });
1020
+ }}
1021
+ />
1022
+ </View>
1023
+ );
1024
+ }
1025
+ ```
1026
+
1027
+ **2. Destination Screen** – Wrap with MaskedView and match the tag:
1028
+
1029
+ ```tsx
1030
+ // app/details.tsx
1031
+ import { useLocalSearchParams } from "expo-router";
1032
+ import Transition from "react-native-screen-transitions";
1033
+
1034
+ export default function DetailsScreen() {
1035
+ const { sharedBoundTag } = useLocalSearchParams<{ sharedBoundTag: string }>();
1036
+
1037
+ return (
1038
+ <Transition.MaskedView style={{ flex: 1, backgroundColor: "#121212" }}>
1039
+ <Transition.View
1040
+ sharedBoundTag={sharedBoundTag}
1041
+ style={{
1042
+ backgroundColor: "#1DB954",
1043
+ width: 400,
1044
+ height: 400,
1045
+ alignSelf: "center",
1046
+ borderRadius: 12,
1047
+ }}
1048
+ />
1049
+ {/* Additional screen content */}
1050
+ </Transition.MaskedView>
1051
+ );
1052
+ }
1053
+ ```
1054
+
1055
+ **3. Layout** – Apply the preset with dynamic tag:
1056
+
1057
+ ```tsx
1058
+ // app/_layout.tsx
1059
+ import Transition from "react-native-screen-transitions";
1060
+ import { Stack } from "./stack";
1061
+
1062
+ export default function RootLayout() {
1063
+ return (
1064
+ <Stack>
1065
+ <Stack.Screen name="index" />
1066
+ <Stack.Screen
1067
+ name="details"
1068
+ options={({ route }) => ({
1069
+ ...Transition.Presets.SharedAppleMusic({
1070
+ sharedBoundTag: route.params?.sharedBoundTag ?? "",
1071
+ }),
1072
+ })}
1073
+ />
1074
+ </Stack>
1075
+ );
1076
+ }
1077
+ ```
1078
+
1079
+ ### How It Works
1080
+
1081
+ 1. `Transition.Pressable` measures its bounds on press and stores them with the tag
1082
+ 2. `Transition.View` on the destination registers as the target for that tag
1083
+ 3. `Transition.MaskedView` clips content to the animating shared element bounds
1084
+ 4. The preset interpolates position, size, and mask for a seamless expand/collapse effect
1085
+
1086
+ ---
1087
+
1088
+ ## Support
1089
+
1090
+ This package is developed in my spare time.
1091
+
1092
+ If you'd like to fuel the next release, [buy me a coffee](https://buymeacoffee.com/trpfsu)
1093
+
1094
+ ## License
45
1095
 
46
- - Docs site: `https://eds2002.github.io/react-native-screen-transitions/`
47
- - Stable docs line: `3.x`
48
- - Unreleased docs line: `Next`
49
- - Repository: `https://github.com/eds2002/react-native-screen-transitions`
1096
+ MIT