react-native-screen-transitions 3.11.1 → 3.11.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 (275) hide show
  1. package/lib/commonjs/native-stack/views/NativeStackView.native.js +1 -1
  2. package/lib/commonjs/native-stack/views/NativeStackView.native.js.map +1 -1
  3. package/lib/commonjs/shared/components/boundary/components/boundary-lifecycle.js +36 -0
  4. package/lib/commonjs/shared/components/boundary/components/boundary-lifecycle.js.map +1 -0
  5. package/lib/commonjs/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.js +1 -13
  6. package/lib/commonjs/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.js.map +1 -1
  7. package/lib/commonjs/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.js +9 -2
  8. package/lib/commonjs/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.js.map +1 -1
  9. package/lib/commonjs/shared/components/boundary/hooks/use-boundary-measurement.js +3 -2
  10. package/lib/commonjs/shared/components/boundary/hooks/use-boundary-measurement.js.map +1 -1
  11. package/lib/commonjs/shared/components/boundary/hooks/use-measurer.js +9 -2
  12. package/lib/commonjs/shared/components/boundary/hooks/use-measurer.js.map +1 -1
  13. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/components/host.js +5 -12
  14. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/components/host.js.map +1 -1
  15. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.js +25 -43
  16. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.js.map +1 -1
  17. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.js +13 -0
  18. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.js.map +1 -0
  19. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.js +8 -31
  20. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.js.map +1 -1
  21. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.js +14 -19
  22. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.js.map +1 -1
  23. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.js +8 -0
  24. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.js.map +1 -1
  25. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.js +19 -47
  26. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.js.map +1 -1
  27. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/index.js.map +1 -1
  28. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.js +1 -1
  29. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.js.map +1 -1
  30. package/lib/commonjs/shared/components/boundary/providers/boundary-root.provider.js +19 -17
  31. package/lib/commonjs/shared/components/boundary/providers/boundary-root.provider.js.map +1 -1
  32. package/lib/commonjs/shared/components/boundary/utils/refresh-signals.js +19 -5
  33. package/lib/commonjs/shared/components/boundary/utils/refresh-signals.js.map +1 -1
  34. package/lib/commonjs/shared/components/screen-container/layers/backdrop.js +11 -7
  35. package/lib/commonjs/shared/components/screen-container/layers/backdrop.js.map +1 -1
  36. package/lib/commonjs/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.js +31 -0
  37. package/lib/commonjs/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.js.map +1 -0
  38. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-close-completion.js +26 -0
  39. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-close-completion.js.map +1 -0
  40. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-close-transition-intent.js +60 -86
  41. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-close-transition-intent.js.map +1 -1
  42. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-transition-start-controller.js +1 -5
  43. package/lib/commonjs/shared/components/screen-lifecycle/hooks/use-transition-start-controller.js.map +1 -1
  44. package/lib/commonjs/shared/components/screen-lifecycle/index.js +9 -6
  45. package/lib/commonjs/shared/components/screen-lifecycle/index.js.map +1 -1
  46. package/lib/commonjs/shared/hooks/navigation/use-navigation-helpers.js +28 -6
  47. package/lib/commonjs/shared/hooks/navigation/use-navigation-helpers.js.map +1 -1
  48. package/lib/commonjs/shared/providers/helpers/measured-bounds-writes.js +1 -2
  49. package/lib/commonjs/shared/providers/helpers/measured-bounds-writes.js.map +1 -1
  50. package/lib/commonjs/shared/providers/screen/gestures/hooks/use-screen-gesture-config.js +9 -2
  51. package/lib/commonjs/shared/providers/screen/gestures/hooks/use-screen-gesture-config.js.map +1 -1
  52. package/lib/commonjs/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.js +4 -5
  53. package/lib/commonjs/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.js.map +1 -1
  54. package/lib/commonjs/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.js +2 -3
  55. package/lib/commonjs/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.js.map +1 -1
  56. package/lib/commonjs/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.js +4 -5
  57. package/lib/commonjs/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.js.map +1 -1
  58. package/lib/commonjs/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.js +2 -3
  59. package/lib/commonjs/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.js.map +1 -1
  60. package/lib/commonjs/shared/providers/screen/gestures/shared/policy.js +9 -5
  61. package/lib/commonjs/shared/providers/screen/gestures/shared/policy.js.map +1 -1
  62. package/lib/commonjs/shared/providers/screen/styles/helpers/create-interpolator-scope.js +40 -0
  63. package/lib/commonjs/shared/providers/screen/styles/helpers/create-interpolator-scope.js.map +1 -0
  64. package/lib/commonjs/shared/providers/screen/styles/hooks/use-interpolated-style-maps.js +5 -10
  65. package/lib/commonjs/shared/providers/screen/styles/hooks/use-interpolated-style-maps.js.map +1 -1
  66. package/lib/commonjs/shared/providers/stack/blank-stack-state/blank-stack-controller.js +5 -1
  67. package/lib/commonjs/shared/providers/stack/blank-stack-state/blank-stack-controller.js.map +1 -1
  68. package/lib/commonjs/shared/stores/bounds/internals/links.js +1 -1
  69. package/lib/commonjs/shared/stores/bounds/internals/links.js.map +1 -1
  70. package/lib/commonjs/shared/stores/system.store.js +1 -2
  71. package/lib/commonjs/shared/stores/system.store.js.map +1 -1
  72. package/lib/commonjs/shared/utils/animation/animate-to-progress.js +0 -22
  73. package/lib/commonjs/shared/utils/animation/animate-to-progress.js.map +1 -1
  74. package/lib/commonjs/shared/utils/navigation/close-action-replay.js +22 -0
  75. package/lib/commonjs/shared/utils/navigation/close-action-replay.js.map +1 -0
  76. package/lib/module/native-stack/views/NativeStackView.native.js +1 -1
  77. package/lib/module/native-stack/views/NativeStackView.native.js.map +1 -1
  78. package/lib/module/shared/components/boundary/components/boundary-lifecycle.js +32 -0
  79. package/lib/module/shared/components/boundary/components/boundary-lifecycle.js.map +1 -0
  80. package/lib/module/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.js +1 -13
  81. package/lib/module/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.js.map +1 -1
  82. package/lib/module/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.js +9 -2
  83. package/lib/module/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.js.map +1 -1
  84. package/lib/module/shared/components/boundary/hooks/use-boundary-measurement.js +3 -2
  85. package/lib/module/shared/components/boundary/hooks/use-boundary-measurement.js.map +1 -1
  86. package/lib/module/shared/components/boundary/hooks/use-measurer.js +9 -2
  87. package/lib/module/shared/components/boundary/hooks/use-measurer.js.map +1 -1
  88. package/lib/module/shared/components/boundary/portal/components/boundary-portal/components/host.js +5 -12
  89. package/lib/module/shared/components/boundary/portal/components/boundary-portal/components/host.js.map +1 -1
  90. package/lib/module/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.js +27 -45
  91. package/lib/module/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.js.map +1 -1
  92. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.js +8 -0
  93. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.js.map +1 -0
  94. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.js +8 -32
  95. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.js.map +1 -1
  96. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.js +15 -20
  97. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.js.map +1 -1
  98. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.js +8 -0
  99. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.js.map +1 -1
  100. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.js +20 -48
  101. package/lib/module/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.js.map +1 -1
  102. package/lib/module/shared/components/boundary/portal/components/boundary-portal/index.js.map +1 -1
  103. package/lib/module/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.js +1 -1
  104. package/lib/module/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.js.map +1 -1
  105. package/lib/module/shared/components/boundary/providers/boundary-root.provider.js +20 -18
  106. package/lib/module/shared/components/boundary/providers/boundary-root.provider.js.map +1 -1
  107. package/lib/module/shared/components/boundary/utils/refresh-signals.js +19 -5
  108. package/lib/module/shared/components/boundary/utils/refresh-signals.js.map +1 -1
  109. package/lib/module/shared/components/screen-container/layers/backdrop.js +12 -8
  110. package/lib/module/shared/components/screen-container/layers/backdrop.js.map +1 -1
  111. package/lib/module/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.js +25 -0
  112. package/lib/module/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.js.map +1 -0
  113. package/lib/module/shared/components/screen-lifecycle/hooks/use-close-completion.js +21 -0
  114. package/lib/module/shared/components/screen-lifecycle/hooks/use-close-completion.js.map +1 -0
  115. package/lib/module/shared/components/screen-lifecycle/hooks/use-close-transition-intent.js +60 -85
  116. package/lib/module/shared/components/screen-lifecycle/hooks/use-close-transition-intent.js.map +1 -1
  117. package/lib/module/shared/components/screen-lifecycle/hooks/use-transition-start-controller.js +1 -5
  118. package/lib/module/shared/components/screen-lifecycle/hooks/use-transition-start-controller.js.map +1 -1
  119. package/lib/module/shared/components/screen-lifecycle/index.js +9 -6
  120. package/lib/module/shared/components/screen-lifecycle/index.js.map +1 -1
  121. package/lib/module/shared/hooks/navigation/use-navigation-helpers.js +29 -7
  122. package/lib/module/shared/hooks/navigation/use-navigation-helpers.js.map +1 -1
  123. package/lib/module/shared/providers/helpers/measured-bounds-writes.js +1 -2
  124. package/lib/module/shared/providers/helpers/measured-bounds-writes.js.map +1 -1
  125. package/lib/module/shared/providers/screen/gestures/hooks/use-screen-gesture-config.js +9 -2
  126. package/lib/module/shared/providers/screen/gestures/hooks/use-screen-gesture-config.js.map +1 -1
  127. package/lib/module/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.js +4 -5
  128. package/lib/module/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.js.map +1 -1
  129. package/lib/module/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.js +2 -3
  130. package/lib/module/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.js.map +1 -1
  131. package/lib/module/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.js +4 -5
  132. package/lib/module/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.js.map +1 -1
  133. package/lib/module/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.js +2 -3
  134. package/lib/module/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.js.map +1 -1
  135. package/lib/module/shared/providers/screen/gestures/shared/policy.js +9 -5
  136. package/lib/module/shared/providers/screen/gestures/shared/policy.js.map +1 -1
  137. package/lib/module/shared/providers/screen/styles/helpers/create-interpolator-scope.js +35 -0
  138. package/lib/module/shared/providers/screen/styles/helpers/create-interpolator-scope.js.map +1 -0
  139. package/lib/module/shared/providers/screen/styles/hooks/use-interpolated-style-maps.js +5 -10
  140. package/lib/module/shared/providers/screen/styles/hooks/use-interpolated-style-maps.js.map +1 -1
  141. package/lib/module/shared/providers/stack/blank-stack-state/blank-stack-controller.js +5 -1
  142. package/lib/module/shared/providers/stack/blank-stack-state/blank-stack-controller.js.map +1 -1
  143. package/lib/module/shared/stores/bounds/internals/links.js +1 -1
  144. package/lib/module/shared/stores/bounds/internals/links.js.map +1 -1
  145. package/lib/module/shared/stores/system.store.js +1 -2
  146. package/lib/module/shared/stores/system.store.js.map +1 -1
  147. package/lib/module/shared/utils/animation/animate-to-progress.js +0 -22
  148. package/lib/module/shared/utils/animation/animate-to-progress.js.map +1 -1
  149. package/lib/module/shared/utils/navigation/close-action-replay.js +16 -0
  150. package/lib/module/shared/utils/navigation/close-action-replay.js.map +1 -0
  151. package/lib/typescript/native-stack/views/NativeStackView.native.d.ts.map +1 -1
  152. package/lib/typescript/shared/components/boundary/components/boundary-lifecycle.d.ts +18 -0
  153. package/lib/typescript/shared/components/boundary/components/boundary-lifecycle.d.ts.map +1 -0
  154. package/lib/typescript/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.d.ts +1 -2
  155. package/lib/typescript/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.d.ts.map +1 -1
  156. package/lib/typescript/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.d.ts.map +1 -1
  157. package/lib/typescript/shared/components/boundary/hooks/use-boundary-measurement.d.ts +3 -2
  158. package/lib/typescript/shared/components/boundary/hooks/use-boundary-measurement.d.ts.map +1 -1
  159. package/lib/typescript/shared/components/boundary/hooks/use-measurer.d.ts +3 -2
  160. package/lib/typescript/shared/components/boundary/hooks/use-measurer.d.ts.map +1 -1
  161. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/components/host.d.ts.map +1 -1
  162. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.d.ts +5 -1
  163. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.d.ts.map +1 -1
  164. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.d.ts +4 -0
  165. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.d.ts.map +1 -0
  166. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.d.ts +4 -17
  167. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.d.ts.map +1 -1
  168. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.d.ts +3 -1
  169. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.d.ts.map +1 -1
  170. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.d.ts.map +1 -1
  171. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.d.ts +5 -9
  172. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.d.ts.map +1 -1
  173. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.d.ts +2 -1
  174. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.d.ts.map +1 -1
  175. package/lib/typescript/shared/components/boundary/providers/boundary-root.provider.d.ts +2 -1
  176. package/lib/typescript/shared/components/boundary/providers/boundary-root.provider.d.ts.map +1 -1
  177. package/lib/typescript/shared/components/boundary/types.d.ts +6 -0
  178. package/lib/typescript/shared/components/boundary/types.d.ts.map +1 -1
  179. package/lib/typescript/shared/components/boundary/utils/refresh-signals.d.ts +1 -0
  180. package/lib/typescript/shared/components/boundary/utils/refresh-signals.d.ts.map +1 -1
  181. package/lib/typescript/shared/components/screen-container/layers/backdrop.d.ts.map +1 -1
  182. package/lib/typescript/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.d.ts +27 -0
  183. package/lib/typescript/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.d.ts.map +1 -0
  184. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-close-completion.d.ts +7 -0
  185. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-close-completion.d.ts.map +1 -0
  186. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-close-transition-intent.d.ts +2 -7
  187. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-close-transition-intent.d.ts.map +1 -1
  188. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-transition-start-controller.d.ts +1 -3
  189. package/lib/typescript/shared/components/screen-lifecycle/hooks/use-transition-start-controller.d.ts.map +1 -1
  190. package/lib/typescript/shared/components/screen-lifecycle/index.d.ts.map +1 -1
  191. package/lib/typescript/shared/hooks/navigation/use-navigation-helpers.d.ts +1 -0
  192. package/lib/typescript/shared/hooks/navigation/use-navigation-helpers.d.ts.map +1 -1
  193. package/lib/typescript/shared/providers/screen/gestures/hooks/use-screen-gesture-config.d.ts.map +1 -1
  194. package/lib/typescript/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.d.ts +1 -1
  195. package/lib/typescript/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.d.ts.map +1 -1
  196. package/lib/typescript/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.d.ts.map +1 -1
  197. package/lib/typescript/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.d.ts +1 -1
  198. package/lib/typescript/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.d.ts.map +1 -1
  199. package/lib/typescript/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.d.ts.map +1 -1
  200. package/lib/typescript/shared/providers/screen/gestures/shared/policy.d.ts +2 -1
  201. package/lib/typescript/shared/providers/screen/gestures/shared/policy.d.ts.map +1 -1
  202. package/lib/typescript/shared/providers/screen/gestures/types.d.ts +2 -0
  203. package/lib/typescript/shared/providers/screen/gestures/types.d.ts.map +1 -1
  204. package/lib/typescript/shared/providers/screen/styles/helpers/create-interpolator-scope.d.ts +9 -0
  205. package/lib/typescript/shared/providers/screen/styles/helpers/create-interpolator-scope.d.ts.map +1 -0
  206. package/lib/typescript/shared/providers/screen/styles/hooks/use-interpolated-style-maps.d.ts.map +1 -1
  207. package/lib/typescript/shared/providers/stack/blank-stack-state/blank-stack-controller.d.ts.map +1 -1
  208. package/lib/typescript/shared/stores/system.store.d.ts +1 -2
  209. package/lib/typescript/shared/stores/system.store.d.ts.map +1 -1
  210. package/lib/typescript/shared/utils/animation/animate-to-progress.d.ts +2 -3
  211. package/lib/typescript/shared/utils/animation/animate-to-progress.d.ts.map +1 -1
  212. package/lib/typescript/shared/utils/navigation/close-action-replay.d.ts +4 -0
  213. package/lib/typescript/shared/utils/navigation/close-action-replay.d.ts.map +1 -0
  214. package/package.json +1 -1
  215. package/src/native-stack/views/NativeStackView.native.tsx +3 -1
  216. package/src/shared/components/boundary/components/boundary-lifecycle.tsx +53 -0
  217. package/src/shared/components/boundary/hooks/lifecycles/use-initial-destination-measurement.ts +0 -14
  218. package/src/shared/components/boundary/hooks/lifecycles/use-refresh-boundary.ts +13 -2
  219. package/src/shared/components/boundary/hooks/use-boundary-measurement.ts +7 -2
  220. package/src/shared/components/boundary/hooks/use-measurer.ts +11 -1
  221. package/src/shared/components/boundary/portal/components/boundary-portal/components/host.tsx +13 -11
  222. package/src/shared/components/boundary/portal/components/boundary-portal/components/portal-boundary-host.tsx +44 -55
  223. package/src/shared/components/boundary/portal/components/boundary-portal/helpers/local-measurement.ts +10 -0
  224. package/src/shared/components/boundary/portal/components/boundary-portal/helpers/offset-style.ts +11 -55
  225. package/src/shared/components/boundary/portal/components/boundary-portal/hooks/use-active-portal-boundary-host.ts +20 -24
  226. package/src/shared/components/boundary/portal/components/boundary-portal/hooks/use-boundary-portal-attachment.ts +11 -0
  227. package/src/shared/components/boundary/portal/components/boundary-portal/hooks/use-host-measurement.ts +20 -67
  228. package/src/shared/components/boundary/portal/components/boundary-portal/index.tsx +1 -0
  229. package/src/shared/components/boundary/portal/components/boundary-portal/stores/portal-boundary-host.store.ts +3 -2
  230. package/src/shared/components/boundary/providers/boundary-root.provider.tsx +29 -20
  231. package/src/shared/components/boundary/types.ts +9 -0
  232. package/src/shared/components/boundary/utils/refresh-signals.ts +39 -6
  233. package/src/shared/components/screen-container/layers/backdrop.tsx +11 -7
  234. package/src/shared/components/screen-lifecycle/hooks/helpers/close-interception-rules.ts +64 -0
  235. package/src/shared/components/screen-lifecycle/hooks/use-close-completion.ts +28 -0
  236. package/src/shared/components/screen-lifecycle/hooks/use-close-transition-intent.ts +67 -108
  237. package/src/shared/components/screen-lifecycle/hooks/use-transition-start-controller.ts +0 -12
  238. package/src/shared/components/screen-lifecycle/index.tsx +8 -4
  239. package/src/shared/hooks/navigation/use-navigation-helpers.ts +39 -7
  240. package/src/shared/providers/helpers/measured-bounds-writes.ts +1 -1
  241. package/src/shared/providers/screen/gestures/hooks/use-screen-gesture-config.ts +9 -1
  242. package/src/shared/providers/screen/gestures/pan/behavior/pan-lifecycle.ts +4 -6
  243. package/src/shared/providers/screen/gestures/pan/behavior/use-pan-behavior.ts +1 -3
  244. package/src/shared/providers/screen/gestures/pinch/behavior/pinch-lifecycle.ts +4 -6
  245. package/src/shared/providers/screen/gestures/pinch/behavior/use-pinch-behavior.ts +2 -8
  246. package/src/shared/providers/screen/gestures/shared/policy.ts +17 -6
  247. package/src/shared/providers/screen/gestures/types.ts +2 -0
  248. package/src/shared/providers/screen/styles/helpers/create-interpolator-scope.ts +45 -0
  249. package/src/shared/providers/screen/styles/hooks/use-interpolated-style-maps.tsx +8 -12
  250. package/src/shared/providers/stack/blank-stack-state/blank-stack-controller.ts +5 -1
  251. package/src/shared/stores/bounds/internals/links.ts +1 -1
  252. package/src/shared/stores/system.store.ts +1 -2
  253. package/src/shared/utils/animation/animate-to-progress.ts +1 -22
  254. package/src/shared/utils/navigation/close-action-replay.ts +25 -0
  255. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.js +0 -30
  256. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.js.map +0 -1
  257. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.js +0 -47
  258. package/lib/commonjs/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.js.map +0 -1
  259. package/lib/commonjs/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.js +0 -21
  260. package/lib/commonjs/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.js.map +0 -1
  261. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.js +0 -25
  262. package/lib/module/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.js.map +0 -1
  263. package/lib/module/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.js +0 -40
  264. package/lib/module/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.js.map +0 -1
  265. package/lib/module/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.js +0 -16
  266. package/lib/module/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.js.map +0 -1
  267. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.d.ts +0 -9
  268. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.d.ts.map +0 -1
  269. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.d.ts +0 -9
  270. package/lib/typescript/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.d.ts.map +0 -1
  271. package/lib/typescript/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.d.ts +0 -2
  272. package/lib/typescript/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.d.ts.map +0 -1
  273. package/src/shared/components/boundary/portal/components/boundary-portal/helpers/active-pair.ts +0 -36
  274. package/src/shared/components/boundary/portal/components/boundary-portal/stores/host-bounds.store.ts +0 -45
  275. package/src/shared/providers/screen/animation/helpers/accessors/use-build-bounds-accessor.tsx +0 -15
@@ -8,7 +8,7 @@ import {
8
8
  } from "react";
9
9
  import type { View } from "react-native";
10
10
  import type { AnimatedRef } from "react-native-reanimated";
11
- import { useAnimatedRef } from "react-native-reanimated";
11
+ import { useAnimatedRef, useSharedValue } from "react-native-reanimated";
12
12
  import { useDescriptorsStore } from "../../../providers/screen/descriptors";
13
13
  import {
14
14
  useComposedSlotStyles,
@@ -19,7 +19,7 @@ import { createBoundTag } from "../../../stores/bounds/helpers/link-pairs.helper
19
19
  import type { BoundTag } from "../../../stores/bounds/types";
20
20
  import createProvider from "../../../utils/create-provider";
21
21
  import { logger } from "../../../utils/logger";
22
- import { useBoundaryMeasurement } from "../hooks/use-boundary-measurement";
22
+ import { BoundaryLifecycle } from "../components/boundary-lifecycle";
23
23
  import {
24
24
  type BoundaryPortalRuntime,
25
25
  resolveBoundaryPortal,
@@ -27,6 +27,8 @@ import {
27
27
  import type {
28
28
  BoundaryConfigProps,
29
29
  BoundaryId,
30
+ BoundaryLocalMeasurement,
31
+ BoundaryLocalMeasurementValue,
30
32
  BoundaryOwnProps,
31
33
  } from "../types";
32
34
 
@@ -44,6 +46,7 @@ export type BoundaryRootRenderState = {
44
46
  boundTag: BoundTag;
45
47
  currentScreenKey: string;
46
48
  handoffEnabled: boolean;
49
+ localMeasurement: BoundaryLocalMeasurementValue;
47
50
  measurementRef: AnimatedRef<View>;
48
51
  portalRuntime: BoundaryPortalRuntime;
49
52
  ref: AnimatedRef<View>;
@@ -96,7 +99,9 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
96
99
  (s) => s.derivations.currentScreenKey,
97
100
  );
98
101
  const isCurrentScreenClosing = useBlankStackStore(
99
- (store) => store?.scenesByKey[currentScreenKey]?.activity === "closing",
102
+ (store) =>
103
+ portalRuntime.handoff &&
104
+ store?.scenesByKey[currentScreenKey]?.activity === "closing",
100
105
  );
101
106
  const retainedBoundTagRef = useRef(requestedBoundTag);
102
107
  const shouldRetainClosingBoundTag =
@@ -110,10 +115,6 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
110
115
  }
111
116
 
112
117
  const boundTag = retainedBoundTagRef.current;
113
- const hasConfiguredInterpolator = useDescriptorsStore(
114
- (s) => s.derivations.hasConfiguredInterpolator,
115
- );
116
- const runtimeEnabled = enabled && hasConfiguredInterpolator;
117
118
  // Associated slot styles attach whenever the boundary is enabled,
118
119
  // independent of whether an interpolator is configured for this transition.
119
120
  const shouldAttachAssociatedStyles = enabled;
@@ -123,6 +124,9 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
123
124
  const associatedStackingStyles = useSlotStackingStyles(boundTag.tag);
124
125
  const rootRef = useAnimatedRef<View>();
125
126
  const measurementRef = useAnimatedRef<View>();
127
+ const localMeasurement = useSharedValue<BoundaryLocalMeasurement | null>(
128
+ null,
129
+ );
126
130
 
127
131
  useLayoutEffect(() => {
128
132
  if (__DEV__ && targetCount > 1) {
@@ -137,18 +141,6 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
137
141
 
138
142
  useImperativeHandle(forwardedRef, () => rootRef.current as any, [rootRef]);
139
143
 
140
- useBoundaryMeasurement({
141
- boundTag,
142
- enabled,
143
- runtimeEnabled,
144
- currentScreenKey,
145
- measuredRef,
146
- style: hasTarget ? targetStyle : style,
147
- handoff: portalRuntime.handoff,
148
- escapeClipping: portalRuntime.escapeClipping,
149
- config,
150
- });
151
-
152
144
  const shouldRenderBoundaryRootThroughPortal =
153
145
  shouldEscapeBoundaryRootToScreenHost && !hasTarget;
154
146
  const handoffEnabled = enabled && portalRuntime.handoff;
@@ -173,6 +165,7 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
173
165
  boundTag,
174
166
  currentScreenKey,
175
167
  handoffEnabled,
168
+ localMeasurement,
176
169
  measurementRef,
177
170
  portalRuntime,
178
171
  ref: rootRef,
@@ -185,6 +178,7 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
185
178
  currentScreenKey,
186
179
  handoffEnabled,
187
180
  hasTarget,
181
+ localMeasurement,
188
182
  measurementRef,
189
183
  portalRuntime,
190
184
  rootRef,
@@ -194,7 +188,22 @@ export const { BoundaryRootProvider, useBoundaryRootStore } = createProvider(
194
188
 
195
189
  return {
196
190
  value,
197
- children: children(value),
191
+ children: (
192
+ <>
193
+ {children(value)}
194
+ <BoundaryLifecycle
195
+ boundTag={boundTag}
196
+ config={config}
197
+ currentScreenKey={currentScreenKey}
198
+ enabled={enabled}
199
+ escapeClipping={portalRuntime.escapeClipping}
200
+ handoff={portalRuntime.handoff}
201
+ localMeasurement={localMeasurement}
202
+ measuredRef={measuredRef}
203
+ style={hasTarget ? targetStyle : style}
204
+ />
205
+ </>
206
+ ),
198
207
  };
199
208
  },
200
209
  );
@@ -1,3 +1,4 @@
1
+ import type { MeasuredDimensions, SharedValue } from "react-native-reanimated";
1
2
  import type { ScreenPairKey } from "../../stores/bounds/types";
2
3
  import type { BoundsOptions } from "../../utils/bounds/types/options";
3
4
 
@@ -60,3 +61,11 @@ export type MeasureTarget =
60
61
  };
61
62
 
62
63
  export type MeasureBoundary = (target: MeasureTarget) => void;
64
+
65
+ export type BoundaryLocalMeasurement = {
66
+ bounds: MeasuredDimensions;
67
+ pairKey: ScreenPairKey;
68
+ };
69
+
70
+ export type BoundaryLocalMeasurementValue =
71
+ SharedValue<BoundaryLocalMeasurement | null>;
@@ -34,6 +34,7 @@ export const getRefreshBoundarySignal = (params: {
34
34
  linkId: string;
35
35
  group?: string;
36
36
  shouldRefresh: boolean;
37
+ settled?: boolean;
37
38
  closing: boolean;
38
39
  linkState?: LinkPairsState;
39
40
  }): RefreshBoundarySignal | null => {
@@ -46,13 +47,14 @@ export const getRefreshBoundarySignal = (params: {
46
47
  linkId,
47
48
  group,
48
49
  shouldRefresh,
50
+ settled = false,
49
51
  closing,
50
52
  linkState,
51
53
  } = params;
52
54
 
53
55
  if (!enabled) return null;
54
56
 
55
- if (!shouldRefresh) {
57
+ if (!shouldRefresh && (!group || !settled)) {
56
58
  return null;
57
59
  }
58
60
 
@@ -95,16 +97,33 @@ export const getRefreshBoundarySignal = (params: {
95
97
  // Source side:
96
98
  // When the activeId changes, trigger a refresh to ensure the source bounds are captured.
97
99
  if (sourcePairKey) {
98
- const activeId = linkState?.[sourcePairKey]?.groups?.[group]?.activeId;
100
+ const pair = linkState?.[sourcePairKey];
101
+ const groupState = pair?.groups?.[group];
102
+ const activeId = groupState?.activeId;
99
103
 
100
104
  if (activeId !== linkId) {
101
105
  return null;
102
106
  }
103
107
 
108
+ // The opening member is captured by the initial handshake. A settled
109
+ // refresh is only needed after selection moves to another member.
110
+ if (
111
+ !shouldRefresh &&
112
+ (groupState?.initialId === undefined ||
113
+ activeId === groupState.initialId ||
114
+ !!pair?.links?.[linkId]?.source)
115
+ ) {
116
+ return null;
117
+ }
118
+
104
119
  return buildRefreshSignal(
105
120
  "source",
106
121
  sourcePairKey,
107
- [group, linkId, closing ? "closing" : "settled"].join("|"),
122
+ [
123
+ group,
124
+ linkId,
125
+ shouldRefresh ? (closing ? "closing" : "settled") : "retarget",
126
+ ].join("|"),
108
127
  );
109
128
  }
110
129
 
@@ -114,8 +133,9 @@ export const getRefreshBoundarySignal = (params: {
114
133
 
115
134
  // Destination side:
116
135
  // When the activeId changes, trigger a refresh to ensure the destination bounds are captured.
117
- const activeId =
118
- linkState?.[refreshDestinationPairKey]?.groups?.[group]?.activeId;
136
+ const pair = linkState?.[refreshDestinationPairKey];
137
+ const groupState = pair?.groups?.[group];
138
+ const activeId = groupState?.activeId;
119
139
 
120
140
  // Destination retargeting should only measure a concrete member that already
121
141
  // participates in the pair. Missing members fall back to initialId at resolve.
@@ -123,9 +143,22 @@ export const getRefreshBoundarySignal = (params: {
123
143
  return null;
124
144
  }
125
145
 
146
+ if (
147
+ !shouldRefresh &&
148
+ (groupState?.initialId === undefined ||
149
+ activeId === groupState.initialId ||
150
+ !!pair?.links?.[linkId]?.destination)
151
+ ) {
152
+ return null;
153
+ }
154
+
126
155
  return buildRefreshSignal(
127
156
  "destination",
128
157
  refreshDestinationPairKey,
129
- [group, linkId, closing ? "closing" : "settled"].join("|"),
158
+ [
159
+ group,
160
+ linkId,
161
+ shouldRefresh ? (closing ? "closing" : "settled") : "retarget",
162
+ ].join("|"),
130
163
  );
131
164
  };
@@ -1,6 +1,6 @@
1
1
  import { type ComponentType, memo, useCallback, useMemo } from "react";
2
2
  import { Pressable, StyleSheet } from "react-native";
3
- import Animated, { runOnUI } from "react-native-reanimated";
3
+ import Animated, { runOnJS, runOnUI } from "react-native-reanimated";
4
4
  import { DefaultSnapSpec } from "../../../configs/specs";
5
5
  import { useNavigationHelpers } from "../../../hooks/navigation/use-navigation-helpers";
6
6
  import { useDescriptorsStore } from "../../../providers/screen/descriptors";
@@ -23,7 +23,7 @@ export const BackdropLayer = memo(function BackdropLayer({
23
23
  backdropBehavior: BackdropBehavior;
24
24
  isBackdropActive: boolean;
25
25
  }) {
26
- const { dismissScreen } = useNavigationHelpers();
26
+ const { isRemovePrevented, requestDismiss } = useNavigationHelpers();
27
27
 
28
28
  const routeKey = useDescriptorsStore(
29
29
  (store) => store.derivations.currentScreenKey,
@@ -34,9 +34,10 @@ export const BackdropLayer = memo(function BackdropLayer({
34
34
  const rawSnapPoints = useDescriptorsStore(
35
35
  (store) => store.options.snapPoints,
36
36
  );
37
- const canDismiss = useDescriptorsStore(
37
+ const isGestureDismissEnabled = useDescriptorsStore(
38
38
  (store) => store.options.gestureEnabled !== false,
39
39
  );
40
+ const canDismiss = isGestureDismissEnabled && !isRemovePrevented;
40
41
  const transitionSpec = useDescriptorsStore(
41
42
  (store) => store.options.transitionSpec,
42
43
  );
@@ -56,14 +57,14 @@ export const BackdropLayer = memo(function BackdropLayer({
56
57
 
57
58
  const handleBackdropPress = useCallback(() => {
58
59
  if (backdropBehavior === "dismiss") {
59
- dismissScreen();
60
+ requestDismiss();
60
61
  return;
61
62
  }
62
63
 
63
64
  if (backdropBehavior === "collapse") {
64
65
  // No snap points → fallback to dismiss
65
66
  if (!rawSnapPoints || rawSnapPoints.length === 0) {
66
- dismissScreen();
67
+ requestDismiss();
67
68
  return;
68
69
  }
69
70
 
@@ -108,8 +109,11 @@ export const BackdropLayer = memo(function BackdropLayer({
108
109
  animations,
109
110
  targetProgress,
110
111
  animationProgress,
111
- onAnimationFinish: shouldDismiss ? dismissScreen : undefined,
112
112
  });
113
+
114
+ if (shouldDismiss) {
115
+ runOnJS(requestDismiss)();
116
+ }
113
117
  })();
114
118
  }
115
119
  }, [
@@ -121,7 +125,7 @@ export const BackdropLayer = memo(function BackdropLayer({
121
125
  rawSnapPoints,
122
126
  canDismiss,
123
127
  transitionSpec,
124
- dismissScreen,
128
+ requestDismiss,
125
129
  routeKey,
126
130
  ]);
127
131
 
@@ -0,0 +1,64 @@
1
+ interface CloseInterceptionState {
2
+ enabled: boolean;
3
+ ownsAction: boolean;
4
+ ancestorDismissing: boolean;
5
+ routeIndex: number;
6
+ focusedIndex: number;
7
+ }
8
+
9
+ interface NavigationRouteLike {
10
+ key: string;
11
+ state?: NavigationStateLike;
12
+ }
13
+
14
+ interface NavigationStateLike {
15
+ key?: string;
16
+ routes: NavigationRouteLike[];
17
+ }
18
+
19
+ interface NavigationActionLike {
20
+ source?: unknown;
21
+ target?: unknown;
22
+ }
23
+
24
+ const containsRouteKey = (
25
+ routes: NavigationRouteLike[],
26
+ routeKey: string,
27
+ ): boolean =>
28
+ routes.some(
29
+ (route) =>
30
+ route.key === routeKey ||
31
+ (route.state ? containsRouteKey(route.state.routes, routeKey) : false),
32
+ );
33
+
34
+ export const doesNavigatorOwnCloseAction = ({
35
+ state,
36
+ action,
37
+ }: {
38
+ state: NavigationStateLike;
39
+ action: NavigationActionLike;
40
+ }): boolean => {
41
+ if (typeof action.target === "string") {
42
+ return action.target === state.key;
43
+ }
44
+
45
+ if (typeof action.source === "string") {
46
+ return containsRouteKey(state.routes, action.source);
47
+ }
48
+
49
+ return true;
50
+ };
51
+
52
+ /** Only the focused removable route owns a stack close transition. */
53
+ export const shouldInterceptClose = ({
54
+ enabled,
55
+ ownsAction,
56
+ ancestorDismissing,
57
+ routeIndex,
58
+ focusedIndex,
59
+ }: CloseInterceptionState) =>
60
+ enabled &&
61
+ ownsAction &&
62
+ !ancestorDismissing &&
63
+ routeIndex > 0 &&
64
+ routeIndex === focusedIndex;
@@ -0,0 +1,28 @@
1
+ import {
2
+ runOnJS,
3
+ type SharedValue,
4
+ useAnimatedReaction,
5
+ } from "react-native-reanimated";
6
+
7
+ export const useCloseCompletion = ({
8
+ closing,
9
+ animationProgress,
10
+ onComplete,
11
+ }: {
12
+ closing: SharedValue<number>;
13
+ animationProgress: SharedValue<number>;
14
+ onComplete: () => void;
15
+ }) => {
16
+ useAnimatedReaction(
17
+ () => {
18
+ "worklet";
19
+ return !!closing.get() && animationProgress.get() <= 0;
20
+ },
21
+ (complete, previouslyComplete) => {
22
+ "worklet";
23
+ if (complete && !previouslyComplete) {
24
+ runOnJS(onComplete)();
25
+ }
26
+ },
27
+ );
28
+ };
@@ -1,6 +1,7 @@
1
- /** biome-ignore-all lint/correctness/useHookAtTopLevel: STACK_TYPE is stable per navigator */
2
1
  import { useLayoutEffect, useMemo, useRef } from "react";
2
+ import { useNavigationHelpers } from "../../../hooks/navigation/use-navigation-helpers";
3
3
  import useStableCallback from "../../../hooks/use-stable-callback";
4
+ import { hasTransitionsEnabled } from "../../../providers/screen/animation/helpers/has-transitions-enabled";
4
5
  import {
5
6
  type BaseDescriptor,
6
7
  useDescriptorsStore,
@@ -8,68 +9,34 @@ import {
8
9
  import { useBlankStackStore } from "../../../providers/stack/blank-stack.provider";
9
10
  import { useStackCoreStore } from "../../../providers/stack/core.provider";
10
11
  import { GestureStore } from "../../../stores/gesture.store";
11
- import {
12
- LifecycleTransitionRequestKind,
13
- type SystemStoreActions,
14
- type SystemStoreMap,
15
- } from "../../../stores/system.store";
16
12
  import { StackType } from "../../../types/stack.types";
13
+ import {
14
+ dispatchCloseAction,
15
+ isCloseActionReplay,
16
+ } from "../../../utils/navigation/close-action-replay";
17
+ import {
18
+ doesNavigatorOwnCloseAction,
19
+ shouldInterceptClose,
20
+ } from "./helpers/close-interception-rules";
17
21
  import { resetStoresForScreen } from "./helpers/reset-stores-for-screen";
18
22
 
19
- interface CloseHookParams {
20
- current: BaseDescriptor;
21
- requestLifecycleTransition: SystemStoreActions["requestLifecycleTransition"];
22
- resetStores: () => void;
23
- }
24
-
25
- const useBlankStackClose = ({
26
- current,
27
- requestLifecycleTransition,
28
- resetStores,
29
- }: CloseHookParams) => {
23
+ export function useCloseTransitionIntent(current: BaseDescriptor): {
24
+ completeClose: () => void;
25
+ } {
26
+ const routeKey = current.route.key;
27
+ const { STACK_TYPE: stackType, TRANSITIONS_ALWAYS_ON: transitionsAlwaysOn } =
28
+ useStackCoreStore((store) => store.flags);
30
29
  const handleCloseRoute = useBlankStackStore(
31
30
  (store) => store?.handleCloseRoute,
32
31
  );
33
- const isClosing = useBlankStackStore(
34
- (store) => store?.scenesByKey[current.route.key]?.activity === "closing",
32
+ const isBlankStackClosing = useBlankStackStore(
33
+ (store) => store?.scenesByKey[routeKey]?.activity === "closing",
35
34
  );
36
-
37
- useLayoutEffect(() => {
38
- if (!isClosing) {
39
- return;
40
- }
41
-
42
- requestLifecycleTransition(
43
- LifecycleTransitionRequestKind.BlankStackClose,
44
- 0,
45
- );
46
- }, [isClosing, requestLifecycleTransition]);
47
-
48
- const handleBlankStackCloseEnd = useStableCallback((finished: boolean) => {
49
- if (!finished) return;
50
- if (!handleCloseRoute) {
51
- throw new Error("Blank stack close handler was not found.");
52
- }
53
- handleCloseRoute({ route: current.route });
54
- requestAnimationFrame(() => {
55
- resetStores();
56
- });
57
- });
58
-
59
- return { handleBlankStackCloseEnd };
60
- };
61
-
62
- /**
63
- * Native stack close - listens to beforeRemove navigation event.
64
- */
65
- const useNativeStackClose = ({
66
- current,
67
- requestLifecycleTransition,
68
- resetStores,
69
- }: CloseHookParams) => {
70
- const parentScreenKey = useDescriptorsStore(
71
- (store) => store.derivations.parentScreenKey,
35
+ const ancestorKeys = useDescriptorsStore(
36
+ (store) => store.derivations.ancestorKeys,
72
37
  );
38
+ const parentScreenKey = ancestorKeys[0];
39
+ const { dismissScreen, requestDismiss } = useNavigationHelpers();
73
40
  const pendingActionRef = useRef<any>(null);
74
41
 
75
42
  const nearestAncestorDismissing = useMemo(() => {
@@ -78,38 +45,62 @@ const useNativeStackClose = ({
78
45
  return GestureStore.peekBag(parentScreenKey)?.dismissing ?? null;
79
46
  }, [parentScreenKey]);
80
47
 
81
- const handleNativeCloseEnd = useStableCallback((finished: boolean) => {
82
- if (!finished || !pendingActionRef.current) {
83
- pendingActionRef.current = null;
84
- return;
48
+ useLayoutEffect(() => {
49
+ if (isBlankStackClosing) {
50
+ requestDismiss();
85
51
  }
52
+ }, [isBlankStackClosing, requestDismiss]);
86
53
 
87
- current.navigation.dispatch(pendingActionRef.current);
54
+ const completeClose = useStableCallback(() => {
55
+ const pendingAction = pendingActionRef.current;
88
56
  pendingActionRef.current = null;
89
- requestAnimationFrame(() => {
90
- resetStores();
91
- });
57
+
58
+ if (pendingAction) {
59
+ dispatchCloseAction(pendingAction, (action) => {
60
+ current.navigation.dispatch(action);
61
+ });
62
+ } else if (stackType !== StackType.NATIVE && handleCloseRoute) {
63
+ handleCloseRoute({ route: current.route });
64
+ } else {
65
+ dismissScreen();
66
+ }
67
+
68
+ resetStoresForScreen(routeKey);
92
69
  });
93
70
 
94
- const handleBeforeRemove = useStableCallback((e: any) => {
95
- const options = current.options as { enableTransitions?: boolean };
96
- const isEnabled = options.enableTransitions;
97
- const navigation = current.navigation;
98
- const routeKey = current.route.key;
99
- const state = navigation.getState();
71
+ const handleBeforeRemove = useStableCallback((event: any) => {
72
+ if (isCloseActionReplay(event.data.action)) {
73
+ return;
74
+ }
75
+
76
+ const state = current.navigation.getState();
100
77
  const routeIndex = state.routes.findIndex(
101
78
  (route) => route.key === routeKey,
102
79
  );
103
- const isFirstScreen = routeIndex <= 0;
80
+ const action = event.data.action;
81
+ const ownsAction = doesNavigatorOwnCloseAction({
82
+ state,
83
+ action,
84
+ });
85
+ const shouldIntercept = shouldInterceptClose({
86
+ enabled: hasTransitionsEnabled(current.options, transitionsAlwaysOn),
87
+ ownsAction,
88
+ ancestorDismissing: !!nearestAncestorDismissing?.get(),
89
+ routeIndex,
90
+ focusedIndex: state.index,
91
+ });
92
+
93
+ if (!shouldIntercept) {
94
+ return;
95
+ }
104
96
 
105
- if (!isEnabled || nearestAncestorDismissing?.get() || isFirstScreen) {
106
- resetStores();
97
+ pendingActionRef.current ??= event.data.action;
98
+ if (!requestDismiss()) {
99
+ pendingActionRef.current = null;
107
100
  return;
108
101
  }
109
102
 
110
- e.preventDefault();
111
- pendingActionRef.current = e.data.action;
112
- requestLifecycleTransition(LifecycleTransitionRequestKind.NativeClose, 0);
103
+ event.preventDefault();
113
104
  });
114
105
 
115
106
  // biome-ignore lint/correctness/useExhaustiveDependencies: navigation listener should only rebind when the navigator instance changes
@@ -117,37 +108,5 @@ const useNativeStackClose = ({
117
108
  return current.navigation.addListener?.("beforeRemove", handleBeforeRemove);
118
109
  }, [current.navigation]);
119
110
 
120
- return { handleNativeCloseEnd };
121
- };
122
-
123
- /**
124
- * Handles close transition intent and returns finish callbacks for cleanup.
125
- */
126
- export function useCloseTransitionIntent(
127
- current: BaseDescriptor,
128
- system: SystemStoreMap,
129
- ): {
130
- handleBlankStackCloseEnd?: (finished: boolean) => void;
131
- handleNativeCloseEnd?: (finished: boolean) => void;
132
- } {
133
- const routeKey = current.route.key;
134
- const stackType = useStackCoreStore((store) => store.flags.STACK_TYPE);
135
- const isNativeStack = stackType === StackType.NATIVE;
136
- const { requestLifecycleTransition } = system.actions;
137
-
138
- const resetStores = useStableCallback(() => {
139
- resetStoresForScreen(routeKey);
140
- });
141
-
142
- const closeParams: CloseHookParams = {
143
- current,
144
- requestLifecycleTransition,
145
- resetStores,
146
- };
147
-
148
- if (isNativeStack) {
149
- return useNativeStackClose(closeParams);
150
- }
151
-
152
- return useBlankStackClose(closeParams);
111
+ return { completeClose };
153
112
  }
@@ -12,14 +12,10 @@ export const useTransitionStartController = ({
12
12
  current,
13
13
  animations,
14
14
  system,
15
- onBlankStackCloseFinish,
16
- onNativeCloseFinish,
17
15
  }: {
18
16
  current: BaseDescriptor;
19
17
  animations: AnimationStoreMap;
20
18
  system: SystemStoreMap;
21
- onBlankStackCloseFinish?: (finished: boolean) => void;
22
- onNativeCloseFinish?: (finished: boolean) => void;
23
19
  }) => {
24
20
  const {
25
21
  targetProgress,
@@ -53,13 +49,6 @@ export const useTransitionStartController = ({
53
49
  return;
54
50
  }
55
51
 
56
- const onAnimationFinish =
57
- kind === LifecycleTransitionRequestKind.BlankStackClose
58
- ? onBlankStackCloseFinish
59
- : kind === LifecycleTransitionRequestKind.NativeClose
60
- ? onNativeCloseFinish
61
- : undefined;
62
-
63
52
  animateToProgress({
64
53
  target,
65
54
  spec: transitionSpec,
@@ -69,7 +58,6 @@ export const useTransitionStartController = ({
69
58
  animations,
70
59
  targetProgress,
71
60
  animationProgress,
72
- onAnimationFinish,
73
61
  isDragging,
74
62
  });
75
63
 
@@ -2,6 +2,7 @@ import { useDescriptorsStore } from "../../providers/screen/descriptors";
2
2
  import { AnimationStore } from "../../stores/animation.store";
3
3
  import { SystemStore } from "../../stores/system.store";
4
4
  import { useScreenHistory } from "./hooks/history/use-screen-history";
5
+ import { useCloseCompletion } from "./hooks/use-close-completion";
5
6
  import { useCloseTransitionIntent } from "./hooks/use-close-transition-intent";
6
7
  import { useOpenTransitionIntent } from "./hooks/use-open-transition-intent";
7
8
  import { useTransitionStartController } from "./hooks/use-transition-start-controller";
@@ -21,8 +22,7 @@ export const ScreenLifecycle = ({ children }: Props) => {
21
22
  const animations = AnimationStore.getBag(current.route.key);
22
23
  const system = SystemStore.getBag(current.route.key);
23
24
 
24
- const { handleBlankStackCloseEnd, handleNativeCloseEnd } =
25
- useCloseTransitionIntent(current, system);
25
+ const { completeClose } = useCloseTransitionIntent(current);
26
26
 
27
27
  useOpenTransitionIntent(current, animations, system);
28
28
 
@@ -30,8 +30,12 @@ export const ScreenLifecycle = ({ children }: Props) => {
30
30
  current,
31
31
  animations,
32
32
  system,
33
- onBlankStackCloseFinish: handleBlankStackCloseEnd,
34
- onNativeCloseFinish: handleNativeCloseEnd,
33
+ });
34
+
35
+ useCloseCompletion({
36
+ closing: animations.closing,
37
+ animationProgress: system.animationProgress,
38
+ onComplete: completeClose,
35
39
  });
36
40
 
37
41
  useScreenHistory(current, previous, animations);