@tamagui/sheet 2.7.7 → 3.0.0-beta.1091.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/dist/cjs/GestureSheetContext.cjs +28 -37
  2. package/dist/cjs/GestureSheetContext.native.cjs +48 -0
  3. package/dist/cjs/GestureSheetContext.native.js +29 -37
  4. package/dist/cjs/GestureSheetContext.native.js.map +1 -1
  5. package/dist/cjs/Sheet.cjs +220 -99
  6. package/dist/cjs/Sheet.native.cjs +245 -0
  7. package/dist/cjs/Sheet.native.js +223 -98
  8. package/dist/cjs/Sheet.native.js.map +1 -1
  9. package/dist/cjs/SheetContext.cjs +43 -22
  10. package/dist/cjs/SheetContext.native.cjs +57 -0
  11. package/dist/cjs/SheetContext.native.js +44 -22
  12. package/dist/cjs/SheetContext.native.js.map +1 -1
  13. package/dist/cjs/SheetController.cjs +49 -56
  14. package/dist/cjs/SheetController.native.cjs +71 -0
  15. package/dist/cjs/SheetController.native.js +52 -58
  16. package/dist/cjs/SheetController.native.js.map +1 -1
  17. package/dist/cjs/SheetDragSurface.cjs +50 -0
  18. package/dist/cjs/SheetDragSurface.native.cjs +61 -0
  19. package/dist/cjs/SheetDragSurface.native.js +63 -0
  20. package/dist/cjs/SheetDragSurface.native.js.map +1 -0
  21. package/dist/cjs/SheetImplementationCustom.cjs +664 -610
  22. package/dist/cjs/SheetImplementationCustom.native.cjs +748 -0
  23. package/dist/cjs/SheetImplementationCustom.native.js +704 -649
  24. package/dist/cjs/SheetImplementationCustom.native.js.map +1 -1
  25. package/dist/cjs/SheetScrollView.cjs +291 -312
  26. package/dist/cjs/SheetScrollView.native.cjs +326 -0
  27. package/dist/cjs/SheetScrollView.native.js +299 -319
  28. package/dist/cjs/SheetScrollView.native.js.map +1 -1
  29. package/dist/cjs/constants.cjs +21 -21
  30. package/dist/cjs/constants.native.cjs +36 -0
  31. package/dist/cjs/constants.native.js +21 -20
  32. package/dist/cjs/constants.native.js.map +1 -1
  33. package/dist/cjs/contexts.cjs +19 -28
  34. package/dist/cjs/contexts.native.cjs +37 -0
  35. package/dist/cjs/contexts.native.js +19 -27
  36. package/dist/cjs/contexts.native.js.map +1 -1
  37. package/dist/cjs/controller.cjs +16 -18
  38. package/dist/cjs/controller.native.cjs +31 -0
  39. package/dist/cjs/controller.native.js +16 -17
  40. package/dist/cjs/controller.native.js.map +1 -1
  41. package/dist/cjs/gestureState.cjs +28 -30
  42. package/dist/cjs/gestureState.native.cjs +53 -0
  43. package/dist/cjs/gestureState.native.js +29 -30
  44. package/dist/cjs/gestureState.native.js.map +1 -1
  45. package/dist/cjs/helpers.cjs +20 -24
  46. package/dist/cjs/helpers.native.cjs +34 -0
  47. package/dist/cjs/helpers.native.js +21 -24
  48. package/dist/cjs/helpers.native.js.map +1 -1
  49. package/dist/cjs/index.cjs +14 -21
  50. package/dist/cjs/index.native.cjs +36 -0
  51. package/dist/cjs/index.native.js +15 -21
  52. package/dist/cjs/index.native.js.map +1 -1
  53. package/dist/cjs/keyboardAvoidance.cjs +55 -79
  54. package/dist/cjs/keyboardAvoidance.native.cjs +74 -0
  55. package/dist/cjs/keyboardAvoidance.native.js +55 -78
  56. package/dist/cjs/keyboardAvoidance.native.js.map +1 -1
  57. package/dist/cjs/nativeSheet.cjs +17 -86
  58. package/dist/cjs/nativeSheet.native.cjs +94 -0
  59. package/dist/cjs/nativeSheet.native.js +73 -86
  60. package/dist/cjs/nativeSheet.native.js.map +1 -1
  61. package/dist/cjs/stableViewportHeight.cjs +27 -0
  62. package/dist/cjs/stableViewportHeight.native.cjs +29 -0
  63. package/dist/cjs/stableViewportHeight.native.js +31 -0
  64. package/dist/cjs/stableViewportHeight.native.js.map +1 -0
  65. package/dist/cjs/types.cjs +9 -11
  66. package/dist/cjs/types.native.cjs +18 -0
  67. package/dist/cjs/types.native.js +9 -10
  68. package/dist/cjs/types.native.js.map +1 -1
  69. package/dist/cjs/useGestureHandlerPan.cjs +244 -257
  70. package/dist/cjs/useGestureHandlerPan.native.cjs +272 -0
  71. package/dist/cjs/useGestureHandlerPan.native.js +253 -265
  72. package/dist/cjs/useGestureHandlerPan.native.js.map +1 -1
  73. package/dist/cjs/useKeyboardControllerSheet.cjs +82 -88
  74. package/dist/cjs/useKeyboardControllerSheet.native.cjs +92 -0
  75. package/dist/cjs/useKeyboardControllerSheet.native.js +73 -111
  76. package/dist/cjs/useKeyboardControllerSheet.native.js.map +1 -1
  77. package/dist/cjs/useSafeAreaInsets.cjs +19 -26
  78. package/dist/cjs/useSafeAreaInsets.native.cjs +50 -0
  79. package/dist/cjs/useSafeAreaInsets.native.js +29 -25
  80. package/dist/cjs/useSafeAreaInsets.native.js.map +1 -1
  81. package/dist/cjs/useSheetController.cjs +26 -39
  82. package/dist/cjs/useSheetController.native.cjs +41 -0
  83. package/dist/cjs/useSheetController.native.js +27 -39
  84. package/dist/cjs/useSheetController.native.js.map +1 -1
  85. package/dist/cjs/useSheetOffscreenSize.cjs +43 -53
  86. package/dist/cjs/useSheetOffscreenSize.native.cjs +59 -0
  87. package/dist/cjs/useSheetOffscreenSize.native.js +47 -56
  88. package/dist/cjs/useSheetOffscreenSize.native.js.map +1 -1
  89. package/dist/cjs/useSheetOpenState.cjs +68 -40
  90. package/dist/cjs/useSheetOpenState.native.cjs +87 -0
  91. package/dist/cjs/useSheetOpenState.native.js +73 -42
  92. package/dist/cjs/useSheetOpenState.native.js.map +1 -1
  93. package/dist/cjs/useSheetProviderProps.cjs +145 -164
  94. package/dist/cjs/useSheetProviderProps.native.cjs +175 -0
  95. package/dist/cjs/useSheetProviderProps.native.js +155 -174
  96. package/dist/cjs/useSheetProviderProps.native.js.map +1 -1
  97. package/dist/cjs/useSheetScrollViewGestures.cjs +171 -180
  98. package/dist/cjs/useSheetScrollViewGestures.native.cjs +149 -0
  99. package/dist/cjs/useSheetScrollViewGestures.native.js +135 -147
  100. package/dist/cjs/useSheetScrollViewGestures.native.js.map +1 -1
  101. package/dist/cjs/webViewport.cjs +46 -48
  102. package/dist/cjs/webViewport.native.cjs +78 -0
  103. package/dist/cjs/webViewport.native.js +49 -50
  104. package/dist/cjs/webViewport.native.js.map +1 -1
  105. package/dist/esm/GestureSheetContext.mjs +15 -20
  106. package/dist/esm/GestureSheetContext.mjs.map +1 -1
  107. package/dist/esm/GestureSheetContext.native.js +17 -22
  108. package/dist/esm/GestureSheetContext.native.js.map +1 -1
  109. package/dist/esm/Sheet.mjs +207 -83
  110. package/dist/esm/Sheet.mjs.map +1 -1
  111. package/dist/esm/Sheet.native.js +210 -83
  112. package/dist/esm/Sheet.native.js.map +1 -1
  113. package/dist/esm/SheetContext.mjs +21 -5
  114. package/dist/esm/SheetContext.mjs.map +1 -1
  115. package/dist/esm/SheetContext.native.js +21 -5
  116. package/dist/esm/SheetContext.native.js.map +1 -1
  117. package/dist/esm/SheetController.mjs +34 -30
  118. package/dist/esm/SheetController.mjs.map +1 -1
  119. package/dist/esm/SheetController.native.js +38 -34
  120. package/dist/esm/SheetController.native.js.map +1 -1
  121. package/dist/esm/SheetDragSurface.mjs +25 -0
  122. package/dist/esm/SheetDragSurface.mjs.map +1 -0
  123. package/dist/esm/SheetDragSurface.native.js +34 -0
  124. package/dist/esm/SheetDragSurface.native.js.map +1 -0
  125. package/dist/esm/SheetImplementationCustom.mjs +647 -586
  126. package/dist/esm/SheetImplementationCustom.mjs.map +1 -1
  127. package/dist/esm/SheetImplementationCustom.native.js +684 -618
  128. package/dist/esm/SheetImplementationCustom.native.js.map +1 -1
  129. package/dist/esm/SheetScrollView.mjs +278 -288
  130. package/dist/esm/SheetScrollView.mjs.map +1 -1
  131. package/dist/esm/SheetScrollView.native.js +287 -297
  132. package/dist/esm/SheetScrollView.native.js.map +1 -1
  133. package/dist/esm/constants.mjs +5 -3
  134. package/dist/esm/constants.mjs.map +1 -1
  135. package/dist/esm/constants.native.js +5 -3
  136. package/dist/esm/constants.native.js.map +1 -1
  137. package/dist/esm/contexts.mjs +3 -3
  138. package/dist/esm/contexts.mjs.map +1 -1
  139. package/dist/esm/contexts.native.js +3 -3
  140. package/dist/esm/contexts.native.js.map +1 -1
  141. package/dist/esm/controller.mjs +2 -2
  142. package/dist/esm/controller.native.js +2 -2
  143. package/dist/esm/gestureState.mjs +13 -11
  144. package/dist/esm/gestureState.mjs.map +1 -1
  145. package/dist/esm/gestureState.native.js +14 -12
  146. package/dist/esm/gestureState.native.js.map +1 -1
  147. package/dist/esm/helpers.mjs +7 -6
  148. package/dist/esm/helpers.mjs.map +1 -1
  149. package/dist/esm/helpers.native.js +8 -7
  150. package/dist/esm/helpers.native.js.map +1 -1
  151. package/dist/esm/index.js +21 -14
  152. package/dist/esm/index.mjs +21 -14
  153. package/dist/esm/index.native.js +21 -14
  154. package/dist/esm/keyboardAvoidance.mjs +40 -61
  155. package/dist/esm/keyboardAvoidance.mjs.map +1 -1
  156. package/dist/esm/keyboardAvoidance.native.js +40 -61
  157. package/dist/esm/keyboardAvoidance.native.js.map +1 -1
  158. package/dist/esm/nativeSheet.mjs +4 -70
  159. package/dist/esm/nativeSheet.mjs.map +1 -1
  160. package/dist/esm/nativeSheet.native.js +60 -70
  161. package/dist/esm/nativeSheet.native.js.map +1 -1
  162. package/dist/esm/stableViewportHeight.mjs +8 -0
  163. package/dist/esm/stableViewportHeight.mjs.map +1 -0
  164. package/dist/esm/stableViewportHeight.native.js +8 -0
  165. package/dist/esm/stableViewportHeight.native.js.map +1 -0
  166. package/dist/esm/types.mjs +0 -2
  167. package/dist/esm/types.native.js +0 -2
  168. package/dist/esm/useGestureHandlerPan.mjs +232 -239
  169. package/dist/esm/useGestureHandlerPan.mjs.map +1 -1
  170. package/dist/esm/useGestureHandlerPan.native.js +241 -248
  171. package/dist/esm/useGestureHandlerPan.native.js.map +1 -1
  172. package/dist/esm/useKeyboardControllerSheet.mjs +71 -71
  173. package/dist/esm/useKeyboardControllerSheet.mjs.map +1 -1
  174. package/dist/esm/useKeyboardControllerSheet.native.js +66 -94
  175. package/dist/esm/useKeyboardControllerSheet.native.js.map +1 -1
  176. package/dist/esm/useSafeAreaInsets.mjs +3 -1
  177. package/dist/esm/useSafeAreaInsets.mjs.map +1 -1
  178. package/dist/esm/useSafeAreaInsets.native.js +15 -3
  179. package/dist/esm/useSafeAreaInsets.native.js.map +1 -1
  180. package/dist/esm/useSheetController.mjs +14 -12
  181. package/dist/esm/useSheetController.mjs.map +1 -1
  182. package/dist/esm/useSheetController.native.js +14 -12
  183. package/dist/esm/useSheetController.native.js.map +1 -1
  184. package/dist/esm/useSheetOffscreenSize.mjs +30 -35
  185. package/dist/esm/useSheetOffscreenSize.mjs.map +1 -1
  186. package/dist/esm/useSheetOffscreenSize.native.js +34 -39
  187. package/dist/esm/useSheetOffscreenSize.native.js.map +1 -1
  188. package/dist/esm/useSheetOpenState.mjs +50 -22
  189. package/dist/esm/useSheetOpenState.mjs.map +1 -1
  190. package/dist/esm/useSheetOpenState.native.js +55 -25
  191. package/dist/esm/useSheetOpenState.native.js.map +1 -1
  192. package/dist/esm/useSheetProviderProps.mjs +130 -138
  193. package/dist/esm/useSheetProviderProps.mjs.map +1 -1
  194. package/dist/esm/useSheetProviderProps.native.js +140 -149
  195. package/dist/esm/useSheetProviderProps.native.js.map +1 -1
  196. package/dist/esm/useSheetScrollViewGestures.mjs +159 -162
  197. package/dist/esm/useSheetScrollViewGestures.mjs.map +1 -1
  198. package/dist/esm/useSheetScrollViewGestures.native.js +123 -130
  199. package/dist/esm/useSheetScrollViewGestures.native.js.map +1 -1
  200. package/dist/esm/webViewport.mjs +26 -25
  201. package/dist/esm/webViewport.mjs.map +1 -1
  202. package/dist/esm/webViewport.native.js +29 -28
  203. package/dist/esm/webViewport.native.js.map +1 -1
  204. package/dist/jsx/GestureSheetContext.mjs +15 -20
  205. package/dist/jsx/GestureSheetContext.mjs.map +1 -1
  206. package/dist/jsx/GestureSheetContext.native.cjs +48 -0
  207. package/dist/jsx/GestureSheetContext.native.js +29 -37
  208. package/dist/jsx/GestureSheetContext.native.js.map +1 -1
  209. package/dist/jsx/Sheet.mjs +207 -83
  210. package/dist/jsx/Sheet.mjs.map +1 -1
  211. package/dist/jsx/Sheet.native.cjs +245 -0
  212. package/dist/jsx/Sheet.native.js +223 -98
  213. package/dist/jsx/Sheet.native.js.map +1 -1
  214. package/dist/jsx/SheetContext.mjs +21 -5
  215. package/dist/jsx/SheetContext.mjs.map +1 -1
  216. package/dist/jsx/SheetContext.native.cjs +57 -0
  217. package/dist/jsx/SheetContext.native.js +44 -22
  218. package/dist/jsx/SheetContext.native.js.map +1 -1
  219. package/dist/jsx/SheetController.mjs +34 -30
  220. package/dist/jsx/SheetController.mjs.map +1 -1
  221. package/dist/jsx/SheetController.native.cjs +71 -0
  222. package/dist/jsx/SheetController.native.js +52 -58
  223. package/dist/jsx/SheetController.native.js.map +1 -1
  224. package/dist/jsx/SheetDragSurface.mjs +25 -0
  225. package/dist/jsx/SheetDragSurface.mjs.map +1 -0
  226. package/dist/jsx/SheetDragSurface.native.cjs +61 -0
  227. package/dist/jsx/SheetDragSurface.native.js +63 -0
  228. package/dist/jsx/SheetDragSurface.native.js.map +1 -0
  229. package/dist/jsx/SheetImplementationCustom.mjs +647 -586
  230. package/dist/jsx/SheetImplementationCustom.mjs.map +1 -1
  231. package/dist/jsx/SheetImplementationCustom.native.cjs +748 -0
  232. package/dist/jsx/SheetImplementationCustom.native.js +704 -649
  233. package/dist/jsx/SheetImplementationCustom.native.js.map +1 -1
  234. package/dist/jsx/SheetScrollView.mjs +278 -288
  235. package/dist/jsx/SheetScrollView.mjs.map +1 -1
  236. package/dist/jsx/SheetScrollView.native.cjs +326 -0
  237. package/dist/jsx/SheetScrollView.native.js +299 -319
  238. package/dist/jsx/SheetScrollView.native.js.map +1 -1
  239. package/dist/jsx/constants.mjs +5 -3
  240. package/dist/jsx/constants.mjs.map +1 -1
  241. package/dist/jsx/constants.native.cjs +36 -0
  242. package/dist/jsx/constants.native.js +21 -20
  243. package/dist/jsx/constants.native.js.map +1 -1
  244. package/dist/jsx/contexts.mjs +3 -3
  245. package/dist/jsx/contexts.mjs.map +1 -1
  246. package/dist/jsx/contexts.native.cjs +37 -0
  247. package/dist/jsx/contexts.native.js +19 -27
  248. package/dist/jsx/contexts.native.js.map +1 -1
  249. package/dist/jsx/controller.mjs +2 -2
  250. package/dist/jsx/controller.native.cjs +31 -0
  251. package/dist/jsx/controller.native.js +16 -17
  252. package/dist/jsx/controller.native.js.map +1 -1
  253. package/dist/jsx/gestureState.mjs +13 -11
  254. package/dist/jsx/gestureState.mjs.map +1 -1
  255. package/dist/jsx/gestureState.native.cjs +53 -0
  256. package/dist/jsx/gestureState.native.js +29 -30
  257. package/dist/jsx/gestureState.native.js.map +1 -1
  258. package/dist/jsx/helpers.mjs +7 -6
  259. package/dist/jsx/helpers.mjs.map +1 -1
  260. package/dist/jsx/helpers.native.cjs +34 -0
  261. package/dist/jsx/helpers.native.js +21 -24
  262. package/dist/jsx/helpers.native.js.map +1 -1
  263. package/dist/jsx/index.js +21 -14
  264. package/dist/jsx/index.mjs +21 -14
  265. package/dist/jsx/index.native.cjs +36 -0
  266. package/dist/jsx/index.native.js +15 -21
  267. package/dist/jsx/index.native.js.map +1 -1
  268. package/dist/jsx/keyboardAvoidance.mjs +40 -61
  269. package/dist/jsx/keyboardAvoidance.mjs.map +1 -1
  270. package/dist/jsx/keyboardAvoidance.native.cjs +74 -0
  271. package/dist/jsx/keyboardAvoidance.native.js +55 -78
  272. package/dist/jsx/keyboardAvoidance.native.js.map +1 -1
  273. package/dist/jsx/nativeSheet.mjs +4 -70
  274. package/dist/jsx/nativeSheet.mjs.map +1 -1
  275. package/dist/jsx/nativeSheet.native.cjs +94 -0
  276. package/dist/jsx/nativeSheet.native.js +73 -86
  277. package/dist/jsx/nativeSheet.native.js.map +1 -1
  278. package/dist/jsx/stableViewportHeight.mjs +8 -0
  279. package/dist/jsx/stableViewportHeight.mjs.map +1 -0
  280. package/dist/jsx/stableViewportHeight.native.cjs +29 -0
  281. package/dist/jsx/stableViewportHeight.native.js +31 -0
  282. package/dist/jsx/stableViewportHeight.native.js.map +1 -0
  283. package/dist/jsx/types.mjs +0 -2
  284. package/dist/jsx/types.native.cjs +18 -0
  285. package/dist/jsx/types.native.js +9 -10
  286. package/dist/jsx/types.native.js.map +1 -1
  287. package/dist/jsx/useGestureHandlerPan.mjs +232 -239
  288. package/dist/jsx/useGestureHandlerPan.mjs.map +1 -1
  289. package/dist/jsx/useGestureHandlerPan.native.cjs +272 -0
  290. package/dist/jsx/useGestureHandlerPan.native.js +253 -265
  291. package/dist/jsx/useGestureHandlerPan.native.js.map +1 -1
  292. package/dist/jsx/useKeyboardControllerSheet.mjs +71 -71
  293. package/dist/jsx/useKeyboardControllerSheet.mjs.map +1 -1
  294. package/dist/jsx/useKeyboardControllerSheet.native.cjs +92 -0
  295. package/dist/jsx/useKeyboardControllerSheet.native.js +73 -111
  296. package/dist/jsx/useKeyboardControllerSheet.native.js.map +1 -1
  297. package/dist/jsx/useSafeAreaInsets.mjs +3 -1
  298. package/dist/jsx/useSafeAreaInsets.mjs.map +1 -1
  299. package/dist/jsx/useSafeAreaInsets.native.cjs +50 -0
  300. package/dist/jsx/useSafeAreaInsets.native.js +29 -25
  301. package/dist/jsx/useSafeAreaInsets.native.js.map +1 -1
  302. package/dist/jsx/useSheetController.mjs +14 -12
  303. package/dist/jsx/useSheetController.mjs.map +1 -1
  304. package/dist/jsx/useSheetController.native.cjs +41 -0
  305. package/dist/jsx/useSheetController.native.js +27 -39
  306. package/dist/jsx/useSheetController.native.js.map +1 -1
  307. package/dist/jsx/useSheetOffscreenSize.mjs +30 -35
  308. package/dist/jsx/useSheetOffscreenSize.mjs.map +1 -1
  309. package/dist/jsx/useSheetOffscreenSize.native.cjs +59 -0
  310. package/dist/jsx/useSheetOffscreenSize.native.js +47 -56
  311. package/dist/jsx/useSheetOffscreenSize.native.js.map +1 -1
  312. package/dist/jsx/useSheetOpenState.mjs +50 -22
  313. package/dist/jsx/useSheetOpenState.mjs.map +1 -1
  314. package/dist/jsx/useSheetOpenState.native.cjs +87 -0
  315. package/dist/jsx/useSheetOpenState.native.js +73 -42
  316. package/dist/jsx/useSheetOpenState.native.js.map +1 -1
  317. package/dist/jsx/useSheetProviderProps.mjs +130 -138
  318. package/dist/jsx/useSheetProviderProps.mjs.map +1 -1
  319. package/dist/jsx/useSheetProviderProps.native.cjs +175 -0
  320. package/dist/jsx/useSheetProviderProps.native.js +155 -174
  321. package/dist/jsx/useSheetProviderProps.native.js.map +1 -1
  322. package/dist/jsx/useSheetScrollViewGestures.mjs +159 -162
  323. package/dist/jsx/useSheetScrollViewGestures.mjs.map +1 -1
  324. package/dist/jsx/useSheetScrollViewGestures.native.cjs +149 -0
  325. package/dist/jsx/useSheetScrollViewGestures.native.js +135 -147
  326. package/dist/jsx/useSheetScrollViewGestures.native.js.map +1 -1
  327. package/dist/jsx/webViewport.mjs +26 -25
  328. package/dist/jsx/webViewport.mjs.map +1 -1
  329. package/dist/jsx/webViewport.native.cjs +78 -0
  330. package/dist/jsx/webViewport.native.js +49 -50
  331. package/dist/jsx/webViewport.native.js.map +1 -1
  332. package/package.json +38 -40
  333. package/src/Sheet.tsx +314 -77
  334. package/src/SheetContext.tsx +57 -7
  335. package/src/SheetController.tsx +7 -6
  336. package/src/SheetDragSurface.native.tsx +42 -0
  337. package/src/SheetDragSurface.tsx +40 -0
  338. package/src/SheetImplementationCustom.tsx +364 -181
  339. package/src/SheetScrollView.tsx +36 -20
  340. package/src/constants.tsx +3 -3
  341. package/src/helpers.tsx +0 -14
  342. package/src/index.ts +3 -6
  343. package/src/{nativeSheet.tsx → nativeSheet.native.tsx} +9 -20
  344. package/src/nativeSheet.ts +19 -0
  345. package/src/stableViewportHeight.native.ts +9 -0
  346. package/src/stableViewportHeight.ts +15 -0
  347. package/src/types.tsx +122 -92
  348. package/src/useKeyboardControllerSheet.native.ts +10 -39
  349. package/src/useSafeAreaInsets.native.ts +20 -13
  350. package/src/useSheetController.tsx +15 -7
  351. package/src/useSheetOpenState.tsx +50 -4
  352. package/src/useSheetProviderProps.tsx +4 -27
  353. package/src/useSheetScrollViewGestures.ts +2 -2
  354. package/types/GestureSheetContext.d.ts +1 -1
  355. package/types/GestureSheetContext.d.ts.map +1 -1
  356. package/types/Sheet.d.ts +247 -151
  357. package/types/Sheet.d.ts.map +1 -1
  358. package/types/SheetContext.d.ts +28 -42
  359. package/types/SheetContext.d.ts.map +1 -1
  360. package/types/SheetController.d.ts +4 -2
  361. package/types/SheetController.d.ts.map +1 -1
  362. package/types/SheetDragSurface.d.ts +11 -0
  363. package/types/SheetDragSurface.d.ts.map +1 -0
  364. package/types/SheetDragSurface.native.d.ts +11 -0
  365. package/types/SheetDragSurface.native.d.ts.map +1 -0
  366. package/types/SheetImplementationCustom.d.ts +4 -36
  367. package/types/SheetImplementationCustom.d.ts.map +1 -1
  368. package/types/SheetScrollView.d.ts +21 -38
  369. package/types/SheetScrollView.d.ts.map +1 -1
  370. package/types/constants.d.ts +3 -2
  371. package/types/constants.d.ts.map +1 -1
  372. package/types/index.d.ts +1 -3
  373. package/types/index.d.ts.map +1 -1
  374. package/types/nativeSheet.d.ts +8 -8
  375. package/types/nativeSheet.d.ts.map +1 -1
  376. package/types/nativeSheet.native.d.ts +5 -0
  377. package/types/nativeSheet.native.d.ts.map +1 -0
  378. package/types/stableViewportHeight.d.ts +12 -0
  379. package/types/stableViewportHeight.d.ts.map +1 -0
  380. package/types/stableViewportHeight.native.d.ts +6 -0
  381. package/types/stableViewportHeight.native.d.ts.map +1 -0
  382. package/types/types.d.ts +43 -17
  383. package/types/types.d.ts.map +1 -1
  384. package/types/useKeyboardControllerSheet.native.d.ts +6 -6
  385. package/types/useKeyboardControllerSheet.native.d.ts.map +1 -1
  386. package/types/useSafeAreaInsets.native.d.ts +4 -12
  387. package/types/useSafeAreaInsets.native.d.ts.map +1 -1
  388. package/types/useSheetController.d.ts +6 -6
  389. package/types/useSheetController.d.ts.map +1 -1
  390. package/types/useSheetOffscreenSize.d.ts.map +1 -1
  391. package/types/useSheetOpenState.d.ts +3 -2
  392. package/types/useSheetOpenState.d.ts.map +1 -1
  393. package/types/useSheetProviderProps.d.ts +5 -8
  394. package/types/useSheetProviderProps.d.ts.map +1 -1
  395. package/types/useSheetScrollViewGestures.d.ts +2 -2
  396. package/types/useSheetScrollViewGestures.d.ts.map +1 -1
  397. package/.turbo/turbo-build.log +0 -2
  398. package/controller/index.cjs +0 -2
  399. package/controller/index.d.ts +0 -5
  400. package/controller/index.js +0 -2
  401. package/controller/index.native.cjs +0 -2
  402. package/controller/index.native.js +0 -2
  403. package/dist/cjs/GestureDetectorWrapper.cjs +0 -54
  404. package/dist/cjs/GestureDetectorWrapper.native.js +0 -58
  405. package/dist/cjs/GestureDetectorWrapper.native.js.map +0 -1
  406. package/dist/cjs/createSheet.cjs +0 -194
  407. package/dist/cjs/createSheet.native.js +0 -204
  408. package/dist/cjs/createSheet.native.js.map +0 -1
  409. package/dist/cjs/setupGestureHandler.cjs +0 -55
  410. package/dist/cjs/setupGestureHandler.native.js +0 -60
  411. package/dist/cjs/setupGestureHandler.native.js.map +0 -1
  412. package/dist/cjs/useSheet.cjs +0 -29
  413. package/dist/cjs/useSheet.native.js +0 -34
  414. package/dist/cjs/useSheet.native.js.map +0 -1
  415. package/dist/esm/GestureDetectorWrapper.mjs +0 -29
  416. package/dist/esm/GestureDetectorWrapper.mjs.map +0 -1
  417. package/dist/esm/GestureDetectorWrapper.native.js +0 -30
  418. package/dist/esm/GestureDetectorWrapper.native.js.map +0 -1
  419. package/dist/esm/controller.mjs.map +0 -1
  420. package/dist/esm/controller.native.js.map +0 -1
  421. package/dist/esm/createSheet.mjs +0 -168
  422. package/dist/esm/createSheet.mjs.map +0 -1
  423. package/dist/esm/createSheet.native.js +0 -176
  424. package/dist/esm/createSheet.native.js.map +0 -1
  425. package/dist/esm/index.js.map +0 -1
  426. package/dist/esm/index.mjs.map +0 -1
  427. package/dist/esm/index.native.js.map +0 -1
  428. package/dist/esm/setupGestureHandler.mjs +0 -29
  429. package/dist/esm/setupGestureHandler.mjs.map +0 -1
  430. package/dist/esm/setupGestureHandler.native.js +0 -31
  431. package/dist/esm/setupGestureHandler.native.js.map +0 -1
  432. package/dist/esm/types.mjs.map +0 -1
  433. package/dist/esm/types.native.js.map +0 -1
  434. package/dist/esm/useSheet.mjs +0 -4
  435. package/dist/esm/useSheet.mjs.map +0 -1
  436. package/dist/esm/useSheet.native.js +0 -6
  437. package/dist/esm/useSheet.native.js.map +0 -1
  438. package/dist/jsx/GestureDetectorWrapper.mjs +0 -29
  439. package/dist/jsx/GestureDetectorWrapper.mjs.map +0 -1
  440. package/dist/jsx/GestureDetectorWrapper.native.js +0 -58
  441. package/dist/jsx/GestureDetectorWrapper.native.js.map +0 -1
  442. package/dist/jsx/controller.mjs.map +0 -1
  443. package/dist/jsx/createSheet.mjs +0 -168
  444. package/dist/jsx/createSheet.mjs.map +0 -1
  445. package/dist/jsx/createSheet.native.js +0 -204
  446. package/dist/jsx/createSheet.native.js.map +0 -1
  447. package/dist/jsx/index.js.map +0 -1
  448. package/dist/jsx/index.mjs.map +0 -1
  449. package/dist/jsx/setupGestureHandler.mjs +0 -29
  450. package/dist/jsx/setupGestureHandler.mjs.map +0 -1
  451. package/dist/jsx/setupGestureHandler.native.js +0 -60
  452. package/dist/jsx/setupGestureHandler.native.js.map +0 -1
  453. package/dist/jsx/types.mjs.map +0 -1
  454. package/dist/jsx/useSheet.mjs +0 -4
  455. package/dist/jsx/useSheet.mjs.map +0 -1
  456. package/dist/jsx/useSheet.native.js +0 -34
  457. package/dist/jsx/useSheet.native.js.map +0 -1
  458. package/next.md +0 -78
  459. package/setup-gesture-handler/index.cjs +0 -2
  460. package/setup-gesture-handler/index.js +0 -2
  461. package/setup-gesture-handler/index.native.cjs +0 -2
  462. package/setup-gesture-handler/index.native.js +0 -2
  463. package/setup-gesture-handler.cjs +0 -1
  464. package/src/GestureDetectorWrapper.tsx +0 -38
  465. package/src/createSheet.tsx +0 -309
  466. package/src/setupGestureHandler.ts +0 -43
  467. package/src/useSheet.tsx +0 -3
  468. package/test/keyboardAvoidance.test.ts +0 -269
  469. package/tsconfig.json +0 -57
  470. package/types/GestureDetectorWrapper.d.ts +0 -14
  471. package/types/GestureDetectorWrapper.d.ts.map +0 -1
  472. package/types/createSheet.d.ts +0 -195
  473. package/types/createSheet.d.ts.map +0 -1
  474. package/types/setupGestureHandler.d.ts +0 -11
  475. package/types/setupGestureHandler.d.ts.map +0 -1
  476. package/types/useSheet.d.ts +0 -2
  477. package/types/useSheet.d.ts.map +0 -1
@@ -1,27 +1,35 @@
1
1
  import { ProvideAdaptContext, useAdaptContext } from '@tamagui/adapt'
2
2
  import { AnimatePresence } from '@tamagui/animate-presence'
3
+ // leaf subpath: the grammar itself belongs to the drivers, not to every sheet
4
+ import { getTransitionResolver } from '@tamagui/animation-helpers/transitionResolver'
3
5
  import { useComposedRefs } from '@tamagui/compose-refs'
4
6
  import { isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
5
7
  import {
6
8
  LayoutMeasurementController,
7
9
  View as TamaguiView,
8
- useConfiguration,
10
+ useAnimationDriver,
11
+ useAnimatedNumber,
12
+ useAnimatedNumberStyle,
9
13
  useDidFinishSSR,
10
14
  useEvent,
11
15
  useThemeName,
16
+ createRefComponent,
17
+ formatDiagnostic,
12
18
  } from '@tamagui/core'
13
19
  import { needsPortalRepropagation, Portal } from '@tamagui/portal'
14
20
  import React, { useState } from 'react'
21
+ import type { PanResponderConfig } from '@tamagui/react-native-pan-responder'
15
22
  import type {
16
- Animated,
17
23
  GestureResponderEvent,
18
24
  LayoutChangeEvent,
19
25
  PanResponderGestureState,
20
- } from 'react-native'
21
- import { Dimensions, PanResponder, View } from 'react-native'
26
+ View,
27
+ } from '@tamagui/react-native-types'
22
28
  import { ParentSheetContext, SheetInsideSheetContext } from './contexts'
23
- import { GestureDetectorWrapper } from './GestureDetectorWrapper'
29
+ import { SHEET_OVERLAY_MARKER } from './constants'
24
30
  import { getGestureHandlerState } from './gestureState'
31
+ import { SheetDragSurface } from './SheetDragSurface'
32
+ import { getStableViewportHeight } from './stableViewportHeight'
25
33
  import { GestureSheetProvider } from './GestureSheetContext'
26
34
  import { resisted } from './helpers'
27
35
  import {
@@ -32,12 +40,20 @@ import {
32
40
  import {
33
41
  getWebKeyboardResizeHeight,
34
42
  getMaxViewportHeight,
35
- getStableLayoutViewportHeight,
36
43
  getWebVisualViewportOffsetTop,
37
44
  MIN_KEYBOARD_HEIGHT,
38
45
  } from './webViewport'
39
- import { SheetProvider } from './SheetContext'
40
- import type { SheetProps, SnapPointsMode } from './types'
46
+ import {
47
+ SheetAnimatedPositionContext,
48
+ SheetOverlayLayerContext,
49
+ SheetProvider,
50
+ } from './SheetContext'
51
+ import type {
52
+ SheetProps,
53
+ SheetTransitionCause,
54
+ SheetTransitionEvent,
55
+ SnapPointsMode,
56
+ } from './types'
41
57
  import { useGestureHandlerPan } from './useGestureHandlerPan'
42
58
  import { useKeyboardControllerSheet } from './useKeyboardControllerSheet'
43
59
  import { SafeAreaInsetsContext, useSafeAreaInsets } from './useSafeAreaInsets'
@@ -56,23 +72,12 @@ const rnghRootStyleClosed = { width: '100%', height: 0 } as const
56
72
 
57
73
  let sheetHiddenStyleSheet: HTMLStyleElement | null = null
58
74
 
59
- // on web we are always relative to window, on to screen
60
- const relativeDimensionTo = isWeb ? 'window' : 'screen'
61
-
62
- // height of the viewport the sheet positions against. on web this MUST be the
63
- // stable layout viewport and NOT Dimensions.get('window') — react-native-web's
64
- // Dimensions tracks visualViewport, which shrinks by the soft keyboard. capping
65
- // frameSize / maxContentSize against that shrinking value corrupts the fit-mode
66
- // math (translateY = screenSize - frameSize), detaching the sheet's bottom from
67
- // the screen edge when the keyboard opens. NOTE: window.innerHeight is NOT
68
- // stable on real iOS Safari (it shrinks with the keyboard too), so we use the
69
- // self-correcting baseline from webViewport instead. see getStableLayoutViewportHeight.
70
- function getStableViewportHeight(): number {
71
- if (isWeb && typeof window !== 'undefined') return getStableLayoutViewportHeight()
72
- return Dimensions.get(relativeDimensionTo).height
73
- }
75
+ // stack of open modal sheets on web so escape only closes the top-most one.
76
+ // pushed on open (child sheets mount their effect after the parent, so the
77
+ // deepest sheet sits last), popped on close/unmount.
78
+ const sheetEscapeLayers: object[] = []
74
79
 
75
- export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
80
+ export const SheetImplementationCustom = createRefComponent<View, SheetProps>(
76
81
  function SheetImplementationCustom(props, forwardedRef) {
77
82
  const parentSheet = React.useContext(ParentSheetContext)
78
83
 
@@ -93,18 +98,15 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
93
98
  zIndex = parentSheet.zIndex + 1,
94
99
  moveOnKeyboardChange = false,
95
100
  unmountChildrenWhenHidden = false,
96
- disableTransparencyHide = false,
101
+ disableHideWhenClosed = false,
97
102
  portalProps,
98
103
  containerComponent: ContainerComponent = React.Fragment,
99
- onAnimationComplete,
104
+ onTransition,
100
105
  } = props
101
106
 
102
107
  const state = useSheetOpenState(props)
103
- const [overlayComponent, setOverlayComponent] = React.useState<React.ReactNode>(null)
104
108
 
105
- const providerProps = useSheetProviderProps(props, state, {
106
- onOverlayComponent: setOverlayComponent,
107
- })
109
+ const providerProps = useSheetProviderProps(props, state)
108
110
  const {
109
111
  frameSize,
110
112
  setFrameSize,
@@ -126,12 +128,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
126
128
  const sheetRef = React.useRef<View>(undefined as unknown as View)
127
129
  const ref = useComposedRefs(forwardedRef, sheetRef, providerProps.contentRef as any)
128
130
 
129
- // TODO this can be extracted into a helper getAnimationConfig(animationProp as array | string)
130
- const { animationDriver } = useConfiguration()
131
-
132
- if (!animationDriver) {
133
- throw new Error(`Sheet requires an animation driver to be set`)
134
- }
131
+ const animationDriver = useAnimationDriver()
135
132
 
136
133
  const transitionConfig = (() => {
137
134
  // explicit transitionConfig prop always takes precedence
@@ -139,21 +136,32 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
139
136
  return transitionConfigProp
140
137
  }
141
138
 
142
- const [animationProp, animationPropConfig] = !transition
143
- ? []
144
- : Array.isArray(transition)
145
- ? transition
146
- : ([transition] as const)
147
-
148
- // look up named animation config from driver if available
149
- if (animationProp && animationDriver.animations?.[animationProp as string]) {
150
- return {
151
- ...animationDriver.animations[animationProp as string],
152
- ...animationPropConfig,
153
- }
139
+ // the sheet drives its position through an animated number rather than a
140
+ // style prop, so it resolves the authored transition itself. it goes
141
+ // through the same grammar every driver and the compiler use, so a config
142
+ // entry never means one thing here and another in a style prop. the raw
143
+ // config is the wrong thing to spread: presets are authored as
144
+ // `{ duration, bounce }` in milliseconds, and motion reads `duration` in
145
+ // seconds.
146
+ const resolved = transition
147
+ ? getTransitionResolver()?.resolve(transition, {
148
+ animations: animationDriver.animations,
149
+ })
150
+ : null
151
+ const timing = resolved?.all?.timing
152
+ if (!timing) return null
153
+ if (timing.kind === 'timing') {
154
+ return { type: 'timing', duration: timing.durationMs }
155
+ }
156
+ // stiffness/damping/mass is the spelling every spring driver takes, and
157
+ // the resolver derives it from `{ duration, bounce }` when that is what
158
+ // the config was written in
159
+ return {
160
+ type: 'spring',
161
+ stiffness: timing.stiffness,
162
+ damping: timing.damping,
163
+ mass: timing.mass,
154
164
  }
155
-
156
- return null
157
165
  })()
158
166
 
159
167
  /**
@@ -334,8 +342,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
334
342
  ? preKeyboardFrameSize.current
335
343
  : 0
336
344
 
337
- const { useAnimatedNumber, useAnimatedNumberStyle } = animationDriver
338
- const AnimatedView = (animationDriver.View ?? TamaguiView) as typeof Animated.View
345
+ const AnimatedView = (animationDriver.View ?? TamaguiView) as React.ComponentType<any>
339
346
 
340
347
  useIsomorphicLayoutEffect(() => {
341
348
  if (!(sheetInsideSheet && open)) return
@@ -367,8 +374,31 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
367
374
 
368
375
  const hasScrollView = React.useRef(false)
369
376
 
370
- // safety fallback timer for sheet close opacity
371
- const opacityFallbackTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)
377
+ // snap index of the last animated move, so a transition can be classified
378
+ // as open (from closed), snap (between snap points), or close.
379
+ const lastPositionIndexRef = React.useRef(-1)
380
+ // the in-flight transition, so a superseding move reports it interrupted.
381
+ const pendingTransitionRef = React.useRef<{
382
+ cause: SheetTransitionCause
383
+ position: number
384
+ } | null>(null)
385
+
386
+ const emitTransition = useEvent(
387
+ (
388
+ phase: 'start' | 'end',
389
+ event: { cause: SheetTransitionCause; position: number },
390
+ finished?: boolean
391
+ ) => {
392
+ const e: SheetTransitionEvent = {
393
+ phase,
394
+ cause: event.cause,
395
+ position: event.position,
396
+ }
397
+ if (phase === 'end') e.finished = finished
398
+ onTransition?.(e)
399
+ controller?.onTransition?.(e)
400
+ }
401
+ )
372
402
 
373
403
  const syncAnimatedPosition = useEvent((value: number) => {
374
404
  at.current = value
@@ -440,21 +470,54 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
440
470
  const closeTarget = isWeb
441
471
  ? Math.max(effScreenSize, getMaxViewportHeight())
442
472
  : effScreenSize
443
- let toValue = isHidden || position === -1 ? closeTarget : activePositions[position]
444
-
445
- if (at.current === toValue) return
473
+ // dismissOnSnapToBottom appends an offscreen snap point. Gesture release
474
+ // calls setPosition(dismissIndex) and animateTo(dismissIndex) in the same
475
+ // event, before React commits open=false and turns the provider position
476
+ // into -1. Treat that synthetic snap as close here so its in-flight
477
+ // callback owns display-none hiding and the Adapt presence handoff.
478
+ const isDismissPosition =
479
+ dismissOnSnapToBottom && position === activePositions.length - 1
480
+ const isOpenAnimation = position !== -1 && !isHidden && !isDismissPosition
481
+ const toValue = isOpenAnimation ? activePositions[position] : closeTarget
482
+
483
+ if (at.current === toValue) {
484
+ // a drag can land exactly on the synthetic dismiss point. there is no
485
+ // remaining distance to animate, but it is still a completed close and
486
+ // must release the same lifecycle consumers as an animated dismissal.
487
+ if (isDismissPosition) {
488
+ if (pendingTransitionRef.current) {
489
+ emitTransition('end', pendingTransitionRef.current, false)
490
+ pendingTransitionRef.current = null
491
+ }
492
+ stopSpring()
493
+ const event = { cause: 'close' as const, position: toValue }
494
+ lastPositionIndexRef.current = -1
495
+ emitTransition('start', event)
496
+ syncAnimatedPosition(toValue)
497
+ setIsFullyClosed(true)
498
+ emitTransition('end', event, true)
499
+ }
500
+ return
501
+ }
446
502
 
447
503
  at.current = toValue
448
- stopSpring()
449
-
450
- const isOpenAnimation = position !== -1 && !isHidden
451
504
 
452
- // clear any pending fallback timer
453
- if (opacityFallbackTimer.current) {
454
- clearTimeout(opacityFallbackTimer.current)
455
- opacityFallbackTimer.current = null
505
+ const cause: SheetTransitionCause = !isOpenAnimation
506
+ ? 'close'
507
+ : lastPositionIndexRef.current < 0
508
+ ? 'open'
509
+ : 'snap'
510
+ lastPositionIndexRef.current = isOpenAnimation ? position : -1
511
+ const event = { cause, position: toValue }
512
+
513
+ // a new move supersedes any in-flight one: report it interrupted
514
+ if (pendingTransitionRef.current) {
515
+ emitTransition('end', pendingTransitionRef.current, false)
516
+ pendingTransitionRef.current = null
456
517
  }
457
518
 
519
+ stopSpring()
520
+
458
521
  const animationCompleteCallback = () => {
459
522
  // a newer animateTo supersedes this one: drivers still fire the owed
460
523
  // completion callback when a new setValue replaces an in-flight one.
@@ -462,34 +525,22 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
462
525
  // this stale toValue would make the next animateTo to this position
463
526
  // no-op (at === toValue) while the dom sits somewhere else — on web
464
527
  // that leaves a reopened sheet parked offscreen at its close target.
528
+ // it would also null out the superseding move's pending transition
529
+ // and double-emit a completed end for an already-interrupted event.
465
530
  if (at.current !== toValue) return
466
531
  syncAnimatedPosition(toValue)
467
- if (opacityFallbackTimer.current) {
468
- clearTimeout(opacityFallbackTimer.current)
469
- opacityFallbackTimer.current = null
470
- }
471
- // use openRef (live) not open (stale closure) — if the sheet
472
- // was reopened before this callback fires (e.g. cancelled close
473
- // animation), we must not hide it
532
+ pendingTransitionRef.current = null
533
+ // use openRef (live) not open (stale closure) — if the sheet was
534
+ // reopened before this callback fires (e.g. cancelled close animation),
535
+ // we must not hide it
474
536
  if (!isOpenAnimation && !openRef.current) {
475
- setOpacity(0)
537
+ setIsFullyClosed(true)
476
538
  }
477
- onAnimationComplete?.({ open: isOpenAnimation })
478
- // also notify the SheetController so a parent (e.g. Dialog adapt)
479
- // can hold the sheet's children mounted until the slide-out is done
480
- controller?.onAnimationComplete?.({ open: isOpenAnimation })
539
+ emitTransition('end', event, true)
481
540
  }
482
541
 
483
- // safety fallback: if animation callback never fires, still hide the sheet
484
- if (!isOpenAnimation) {
485
- opacityFallbackTimer.current = setTimeout(() => {
486
- opacityFallbackTimer.current = null
487
- // check live open state via ref — sheet may have reopened (e.g. adapt handoff)
488
- if (!openRef.current) {
489
- setOpacity(0)
490
- }
491
- }, 1000)
492
- }
542
+ pendingTransitionRef.current = event
543
+ emitTransition('start', event)
493
544
 
494
545
  // skip animation when adapting from dialog to sheet
495
546
  if (skipAdaptAnimation.current) {
@@ -502,14 +553,32 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
502
553
  return
503
554
  }
504
555
 
505
- animatedNumber.setValue(
506
- toValue,
507
- animationOverride || {
508
- type: 'spring',
509
- ...transitionConfig,
510
- },
511
- animationCompleteCallback
512
- )
556
+ const resolvedConfig = animationOverride || {
557
+ type: 'spring',
558
+ ...transitionConfig,
559
+ }
560
+
561
+ // the sheet position spring moves hundreds of px. the spring drivers'
562
+ // default rest detection is tuned for tiny values (react-native Animated:
563
+ // 0.001px thresholds; reanimated 4: relative energyThreshold 6e-9), so for
564
+ // a sheet-sized move completion would fire 1.4-1.7s after the animation is
565
+ // visually done. these px-sized rest thresholds make close-complete prompt
566
+ // (~0.5-0.8s), which is what now drives display:none hiding and the Adapt
567
+ // presence release (no timers). user config still wins via spread order;
568
+ // each driver ignores the other driver's keys.
569
+ const springConfig =
570
+ !resolvedConfig.type || resolvedConfig.type === 'spring'
571
+ ? {
572
+ // react-native Animated (absolute px)
573
+ restDisplacementThreshold: 1,
574
+ restSpeedThreshold: 10,
575
+ // reanimated 4 (relative energy): ~0.3% of travel amplitude
576
+ energyThreshold: 1e-5,
577
+ ...resolvedConfig,
578
+ }
579
+ : resolvedConfig
580
+
581
+ animatedNumber.setValue(toValue, springConfig, animationCompleteCallback)
513
582
  })
514
583
 
515
584
  useIsomorphicLayoutEffect(() => {
@@ -587,10 +656,12 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
587
656
  const themeName = useThemeName()
588
657
  const [blockPan, setBlockPan] = React.useState(false)
589
658
 
590
- const panResponder = React.useMemo(() => {
591
- if (disableDrag) return
592
- if (!frameSize) return
593
- if (isShowingInnerSheet) return
659
+ // the drag surface turns this into a PanResponder. it is built here because
660
+ // the handlers close over the sheet's live drag state and the scroll bridge.
661
+ const panConfig = React.useMemo((): PanResponderConfig | null => {
662
+ if (disableDrag) return null
663
+ if (!frameSize) return null
664
+ if (isShowingInnerSheet) return null
594
665
 
595
666
  // use keyboard-adjusted positions (matches the RNGH path): when the
596
667
  // keyboard is open the sheet sits at activePositions[0], so clamping drags
@@ -674,7 +745,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
674
745
  // touch is on the ScrollView node — the web scroll-view gesture hook
675
746
  // owns it and drives drag/release through scrollBridge directly (it
676
747
  // re-baselines via scrollBridge.startPanDrag on each pan handoff). if
677
- // we also granted here, RNW's PanResponder would set the animated
748
+ // we also granted here, the PanResponder would set the animated
678
749
  // position from a second, differently-based offset every move and the
679
750
  // sheet would jitter/jump. defer entirely to the hook.
680
751
  if (scrollBridge.scrollNodeTouched) {
@@ -757,7 +828,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
757
828
  animateTo(positionIndex)
758
829
  }
759
830
 
760
- return PanResponder.create({
831
+ return {
761
832
  onMoveShouldSetPanResponder: onMoveShouldSet,
762
833
  // once we own the drag, don't yield it to another responder
763
834
  // (re-renders during the drag were cooperatively terminating it under
@@ -781,7 +852,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
781
852
  onPanResponderEnd: finish,
782
853
  onPanResponderTerminate: finish,
783
854
  onPanResponderRelease: finish,
784
- })
855
+ }
785
856
  }, [
786
857
  disableDrag,
787
858
  isShowingInnerSheet,
@@ -833,6 +904,32 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
833
904
  }
834
905
  }, [open])
835
906
 
907
+ React.useEffect(() => {
908
+ if (!isWeb || !modal || !open || shouldHideParentSheet) return
909
+
910
+ const layer = {}
911
+ sheetEscapeLayers.push(layer)
912
+
913
+ const onKeyDown = (event: KeyboardEvent) => {
914
+ if (event.key === 'Escape') {
915
+ // only the top-most open modal sheet responds so a nested sheet
916
+ // doesn't take its parent down with it
917
+ if (sheetEscapeLayers[sheetEscapeLayers.length - 1] === layer) {
918
+ state.setOpen(false)
919
+ }
920
+ }
921
+ }
922
+
923
+ document.addEventListener('keydown', onKeyDown)
924
+ return () => {
925
+ const index = sheetEscapeLayers.indexOf(layer)
926
+ if (index > -1) {
927
+ sheetEscapeLayers.splice(index, 1)
928
+ }
929
+ document.removeEventListener('keydown', onKeyDown)
930
+ }
931
+ }, [modal, open, shouldHideParentSheet, state.setOpen])
932
+
836
933
  // gesture handler hook for RNGH-based gesture coordination
837
934
  const { panGesture, panGestureRef, gestureHandlerEnabled } = useGestureHandlerPan({
838
935
  positions: activePositions,
@@ -923,17 +1020,32 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
923
1020
 
924
1021
  const animatedStyle = useAnimatedNumberStyle(animatedNumber, getAnimatedNumberStyle)
925
1022
 
926
- // we need to set this *after* fully closed to 0, to avoid it overlapping
927
- // the page when resizing quickly on web for example
928
- const [opacity, setOpacity] = React.useState(open ? 1 : 0)
929
- if (open && opacity === 0) {
930
- setOpacity(1)
931
- // cancel any pending close fallback — sheet is reopening
932
- if (opacityFallbackTimer.current) {
933
- clearTimeout(opacityFallbackTimer.current)
934
- opacityFallbackTimer.current = null
935
- }
1023
+ // a fully-closed sheet is hidden with display:none (set from the
1024
+ // close-complete transition event) so it never overlaps the page when
1025
+ // resizing quickly on web. it starts NOT hidden — the frame must be laid
1026
+ // out to measure its size (display:none has no layout box, so hiding before
1027
+ // the first measurement would leave frameSize/screenSize at 0). it un-hides
1028
+ // synchronously in render on re-open, before layout, keeping the retained
1029
+ // frame size. the closed-but-never-opened frame stays off screen via its
1030
+ // translateY, so leaving it laid out is not visible.
1031
+ const [isFullyClosed, setIsFullyClosed] = React.useState(false)
1032
+ if (open && isFullyClosed) {
1033
+ setIsFullyClosed(false)
1034
+ }
1035
+ // whether the sheet is visually active: open, or still animating out.
1036
+ // isFullyClosed only flips true from the close-animation-complete callback,
1037
+ // so it stays false for a mounted-but-never-opened sheet - track first open
1038
+ // separately so a closed sheet is inactive from mount. drives the portal
1039
+ // host's visibility (see Portal.tsx on why closed hosts must be hidden).
1040
+ const hasEverOpened = React.useRef(open)
1041
+ if (open) {
1042
+ hasEverOpened.current = true
936
1043
  }
1044
+ const isVisuallyActive = open || (hasEverOpened.current && !isFullyClosed)
1045
+ // shouldHideParentSheet (a nested sheet on native gorhom) hides the parent
1046
+ // immediately; disableHideWhenClosed opts the closed wrapper out of hiding
1047
+ // but never overrides the nested-sheet hide.
1048
+ const applyHidden = shouldHideParentSheet || (isFullyClosed && !disableHideWhenClosed)
937
1049
 
938
1050
  const forcedContentHeight = hasFit
939
1051
  ? undefined
@@ -945,12 +1057,25 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
945
1057
  const setHasScrollView = React.useCallback((val: boolean) => {
946
1058
  hasScrollView.current = val
947
1059
  }, [])
948
- // const id = useId()
949
- // const { AdaptProvider, when, children } = useAdaptParent({
950
- // scope: `${id}Sheet`,
951
- // portal: true,
952
- // })
953
1060
 
1061
+ // publish the live animated position so user code can build drag-linked
1062
+ // effects (e.g. an overlay fade) via Sheet.useAnimatedPosition(). positions
1063
+ // are the resolved px offsets matching snapPoints order; minY is topmost.
1064
+ const animatedPositionValue = React.useMemo(
1065
+ () => ({
1066
+ value: animatedNumber,
1067
+ screenSize: effScreenSize,
1068
+ frameSize,
1069
+ snapOffsets: activePositions,
1070
+ minY: activePositions[0] ?? 0,
1071
+ }),
1072
+ [animatedNumber, effScreenSize, frameSize, activePositions]
1073
+ )
1074
+
1075
+ const { overlayChildren, animatedChildren } = React.useMemo(
1076
+ () => partitionSheetChildren(props.children),
1077
+ [props.children]
1078
+ )
954
1079
  let contents = (
955
1080
  <LayoutMeasurementController disable={!open}>
956
1081
  <ParentSheetContext.Provider value={nextParentContext}>
@@ -968,66 +1093,55 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
968
1093
  panGesture={panGesture}
969
1094
  panGestureRef={panGestureRef}
970
1095
  >
971
- <AnimatePresence custom={{ open }}>
972
- {shouldHideParentSheet || !open ? null : overlayComponent}
973
- </AnimatePresence>
974
-
975
- {snapPointsMode !== 'percent' && (
976
- <View
977
- style={{
978
- opacity: 0,
979
- position: 'absolute',
980
- top: 0,
981
- left: 0,
982
- right: 0,
983
- bottom: 0,
984
- pointerEvents: 'none',
985
- }}
986
- onLayout={handleMaxContentViewLayout}
987
- />
988
- )}
989
-
990
- <AnimatedView
991
- ref={ref}
992
- onLayout={handleAnimationViewLayout}
993
- // @ts-ignore for CSS driver this is necessary to attach the transition
994
- // also motion driver at least though i suspect all drivers?
995
- transition={isDragging || disableAnimation ? null : transition}
996
- // @ts-ignore
997
- disableClassName
998
- style={[
999
- {
1000
- position: 'absolute',
1001
- zIndex,
1002
- width: '100%',
1003
- height: forcedContentHeight,
1004
- minHeight: forcedContentHeight,
1005
- opacity: shouldHideParentSheet
1006
- ? 0
1007
- : disableTransparencyHide
1008
- ? 1
1009
- : opacity,
1010
- ...((shouldHideParentSheet || !open) && {
1011
- pointerEvents: 'none',
1012
- }),
1013
- },
1014
- animatedStyle,
1015
- ]}
1016
- >
1017
- {/* wrap children with plain RN View for panResponder - tamagui views no longer handle responder events on web */}
1018
- {gestureHandlerEnabled && panGesture ? (
1019
- <GestureDetectorWrapper gesture={panGesture} style={{ flex: 1 }}>
1020
- {props.children}
1021
- </GestureDetectorWrapper>
1022
- ) : (
1023
- <View
1024
- {...panResponder?.panHandlers}
1025
- style={{ flex: 1, width: '100%', height: '100%' }}
1026
- >
1027
- {props.children}
1028
- </View>
1096
+ <SheetAnimatedPositionContext.Provider value={animatedPositionValue}>
1097
+ <SheetOverlayLayerContext.Provider value>
1098
+ <AnimatePresence custom={{ open }}>
1099
+ {shouldHideParentSheet || !open ? null : overlayChildren}
1100
+ </AnimatePresence>
1101
+ </SheetOverlayLayerContext.Provider>
1102
+
1103
+ {snapPointsMode !== 'percent' && (
1104
+ <TamaguiView
1105
+ opacity={0}
1106
+ position="absolute"
1107
+ inset={0}
1108
+ pointerEvents="none"
1109
+ onLayout={handleMaxContentViewLayout}
1110
+ />
1029
1111
  )}
1030
- </AnimatedView>
1112
+
1113
+ <AnimatedView
1114
+ ref={ref}
1115
+ onLayout={handleAnimationViewLayout}
1116
+ // @ts-ignore for CSS driver this is necessary to attach the transition
1117
+ // also motion driver at least though i suspect all drivers?
1118
+ transition={isDragging || disableAnimation ? null : transition}
1119
+ // @ts-ignore
1120
+ disableClassName
1121
+ style={[
1122
+ {
1123
+ position: 'absolute',
1124
+ zIndex,
1125
+ width: '100%',
1126
+ height: forcedContentHeight,
1127
+ minHeight: forcedContentHeight,
1128
+ ...(applyHidden && { display: 'none' }),
1129
+ ...((shouldHideParentSheet || !open) && {
1130
+ pointerEvents: 'none',
1131
+ }),
1132
+ },
1133
+ animatedStyle,
1134
+ ]}
1135
+ >
1136
+ <SheetDragSurface
1137
+ gestureHandlerEnabled={gestureHandlerEnabled}
1138
+ panGesture={panGesture}
1139
+ panConfig={panConfig}
1140
+ >
1141
+ {animatedChildren}
1142
+ </SheetDragSurface>
1143
+ </AnimatedView>
1144
+ </SheetAnimatedPositionContext.Provider>
1031
1145
  </GestureSheetProvider>
1032
1146
  </SheetProvider>
1033
1147
  </ParentSheetContext.Provider>
@@ -1035,7 +1149,6 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
1035
1149
  )
1036
1150
 
1037
1151
  if (process.env.TAMAGUI_TARGET === 'native' && needsPortalRepropagation()) {
1038
- // TODO alongside sheet scope="" need to pass scope here
1039
1152
  const adaptContext = useAdaptContext()
1040
1153
  contents = (
1041
1154
  <ProvideAdaptContext {...adaptContext}>
@@ -1051,7 +1164,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
1051
1164
  }
1052
1165
 
1053
1166
  // start mounted so we get an accurate measurement the first time
1054
- const shouldMountChildren = unmountChildrenWhenHidden ? !!opacity : true
1167
+ const shouldMountChildren = unmountChildrenWhenHidden ? !isFullyClosed : true
1055
1168
 
1056
1169
  if (modal) {
1057
1170
  // a modal sheet is teleported through <Portal> to the root portal host.
@@ -1071,7 +1184,7 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
1071
1184
  <ContainerComponent>{contents}</ContainerComponent>
1072
1185
  ) : null
1073
1186
  const modalContents = (
1074
- <Portal stackZIndex={zIndex} {...portalProps}>
1187
+ <Portal stackZIndex={zIndex} hidden={!isVisuallyActive} {...portalProps}>
1075
1188
  {mountedContents && RNGHRoot ? (
1076
1189
  <RNGHRoot style={open ? rnghRootStyleOpen : rnghRootStyleClosed}>
1077
1190
  {mountedContents}
@@ -1098,6 +1211,49 @@ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
1098
1211
  }
1099
1212
  )
1100
1213
 
1214
+ type SheetPartStaticConfig = {
1215
+ [SHEET_OVERLAY_MARKER]?: boolean
1216
+ parentStaticConfig?: SheetPartStaticConfig
1217
+ }
1218
+
1219
+ export function isSheetOverlayComponent(type: unknown) {
1220
+ let staticConfig = (type as { staticConfig?: SheetPartStaticConfig } | null)
1221
+ ?.staticConfig
1222
+
1223
+ while (staticConfig) {
1224
+ if (staticConfig[SHEET_OVERLAY_MARKER]) {
1225
+ return true
1226
+ }
1227
+ staticConfig = staticConfig.parentStaticConfig
1228
+ }
1229
+
1230
+ return false
1231
+ }
1232
+
1233
+ function partitionSheetChildren(children: React.ReactNode) {
1234
+ const overlayChildren: React.ReactNode[] = []
1235
+ const animatedChildren: React.ReactNode[] = []
1236
+
1237
+ React.Children.forEach(children, (child) => {
1238
+ if (!React.isValidElement(child)) {
1239
+ animatedChildren.push(child)
1240
+ return
1241
+ }
1242
+
1243
+ if (isSheetOverlayComponent(child.type)) {
1244
+ overlayChildren.push(child)
1245
+ return
1246
+ }
1247
+
1248
+ animatedChildren.push(child)
1249
+ })
1250
+
1251
+ return {
1252
+ overlayChildren,
1253
+ animatedChildren,
1254
+ }
1255
+ }
1256
+
1101
1257
  function getYPositions(
1102
1258
  mode: SnapPointsMode,
1103
1259
  point: string | number,
@@ -1118,12 +1274,30 @@ function getYPositions(
1118
1274
  if (point.endsWith('%')) {
1119
1275
  const pct = Math.min(100, Math.max(0, Number(point.slice(0, -1)))) / 100
1120
1276
  if (Number.isNaN(pct)) {
1121
- console.warn('Invalid snapPoint percentage string')
1277
+ console.warn(
1278
+ formatDiagnostic(
1279
+ 'TAMAGUI_SHEET_SNAP_POINT',
1280
+ 'Sheet',
1281
+ 'snapPoints contains an invalid percentage string',
1282
+ 'Use "fit", a pixel number, or a percentage such as "50%"',
1283
+ 'snapPoint',
1284
+ point
1285
+ )
1286
+ )
1122
1287
  return 0
1123
1288
  }
1124
1289
  return Math.round(screenSize - pct * screenSize)
1125
1290
  }
1126
- console.warn('Invalid snapPoint unknown value')
1291
+ console.warn(
1292
+ formatDiagnostic(
1293
+ 'TAMAGUI_SHEET_SNAP_POINT',
1294
+ 'Sheet',
1295
+ 'snapPoints contains an unsupported mixed-mode value',
1296
+ 'Use "fit", a pixel number, or a percentage such as "50%"',
1297
+ 'snapPoint',
1298
+ point
1299
+ )
1300
+ )
1127
1301
  return 0
1128
1302
  }
1129
1303
 
@@ -1138,7 +1312,16 @@ function getYPositions(
1138
1312
 
1139
1313
  const pct = Math.min(100, Math.max(0, Number(point))) / 100
1140
1314
  if (Number.isNaN(pct)) {
1141
- console.warn('Invalid snapPoint percentage')
1315
+ console.warn(
1316
+ formatDiagnostic(
1317
+ 'TAMAGUI_SHEET_SNAP_POINT',
1318
+ 'Sheet',
1319
+ 'snapPoints contains a value that cannot be converted to a percentage',
1320
+ 'Use a numeric percentage such as 50',
1321
+ 'snapPoint',
1322
+ point
1323
+ )
1324
+ )
1142
1325
  return 0
1143
1326
  }
1144
1327