@hanzogui/sheet 2.0.0-rc.41-hanzoai.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 (375) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/LICENSE +21 -0
  3. package/controller/index.cjs +2 -0
  4. package/controller/index.d.ts +5 -0
  5. package/controller/index.js +2 -0
  6. package/controller/index.native.cjs +2 -0
  7. package/controller/index.native.js +2 -0
  8. package/dist/cjs/GestureDetectorWrapper.cjs +54 -0
  9. package/dist/cjs/GestureDetectorWrapper.native.js +58 -0
  10. package/dist/cjs/GestureDetectorWrapper.native.js.map +1 -0
  11. package/dist/cjs/GestureSheetContext.cjs +54 -0
  12. package/dist/cjs/GestureSheetContext.native.js +58 -0
  13. package/dist/cjs/GestureSheetContext.native.js.map +1 -0
  14. package/dist/cjs/Sheet.cjs +119 -0
  15. package/dist/cjs/Sheet.native.js +122 -0
  16. package/dist/cjs/Sheet.native.js.map +1 -0
  17. package/dist/cjs/SheetContext.cjs +34 -0
  18. package/dist/cjs/SheetContext.native.js +37 -0
  19. package/dist/cjs/SheetContext.native.js.map +1 -0
  20. package/dist/cjs/SheetController.cjs +73 -0
  21. package/dist/cjs/SheetController.native.js +79 -0
  22. package/dist/cjs/SheetController.native.js.map +1 -0
  23. package/dist/cjs/SheetImplementationCustom.cjs +589 -0
  24. package/dist/cjs/SheetImplementationCustom.native.js +615 -0
  25. package/dist/cjs/SheetImplementationCustom.native.js.map +1 -0
  26. package/dist/cjs/SheetScrollView.cjs +216 -0
  27. package/dist/cjs/SheetScrollView.native.js +223 -0
  28. package/dist/cjs/SheetScrollView.native.js.map +1 -0
  29. package/dist/cjs/constants.cjs +34 -0
  30. package/dist/cjs/constants.native.js +37 -0
  31. package/dist/cjs/constants.native.js.map +1 -0
  32. package/dist/cjs/contexts.cjs +44 -0
  33. package/dist/cjs/contexts.native.js +47 -0
  34. package/dist/cjs/contexts.native.js.map +1 -0
  35. package/dist/cjs/controller.cjs +31 -0
  36. package/dist/cjs/controller.native.js +34 -0
  37. package/dist/cjs/controller.native.js.map +1 -0
  38. package/dist/cjs/createSheet.cjs +190 -0
  39. package/dist/cjs/createSheet.native.js +200 -0
  40. package/dist/cjs/createSheet.native.js.map +1 -0
  41. package/dist/cjs/gestureState.cjs +41 -0
  42. package/dist/cjs/gestureState.native.js +44 -0
  43. package/dist/cjs/gestureState.native.js.map +1 -0
  44. package/dist/cjs/helpers.cjs +35 -0
  45. package/dist/cjs/helpers.native.js +39 -0
  46. package/dist/cjs/helpers.native.js.map +1 -0
  47. package/dist/cjs/index.cjs +30 -0
  48. package/dist/cjs/index.native.js +33 -0
  49. package/dist/cjs/index.native.js.map +1 -0
  50. package/dist/cjs/nativeSheet.cjs +96 -0
  51. package/dist/cjs/nativeSheet.native.js +106 -0
  52. package/dist/cjs/nativeSheet.native.js.map +1 -0
  53. package/dist/cjs/setupGestureHandler.cjs +52 -0
  54. package/dist/cjs/setupGestureHandler.native.js +55 -0
  55. package/dist/cjs/setupGestureHandler.native.js.map +1 -0
  56. package/dist/cjs/types.cjs +18 -0
  57. package/dist/cjs/types.native.js +21 -0
  58. package/dist/cjs/types.native.js.map +1 -0
  59. package/dist/cjs/useGestureHandlerPan.cjs +206 -0
  60. package/dist/cjs/useGestureHandlerPan.native.js +213 -0
  61. package/dist/cjs/useGestureHandlerPan.native.js.map +1 -0
  62. package/dist/cjs/useKeyboardControllerSheet.cjs +40 -0
  63. package/dist/cjs/useKeyboardControllerSheet.native.js +132 -0
  64. package/dist/cjs/useKeyboardControllerSheet.native.js.map +1 -0
  65. package/dist/cjs/useSheet.cjs +29 -0
  66. package/dist/cjs/useSheet.native.js +34 -0
  67. package/dist/cjs/useSheet.native.js.map +1 -0
  68. package/dist/cjs/useSheetController.cjs +52 -0
  69. package/dist/cjs/useSheetController.native.js +55 -0
  70. package/dist/cjs/useSheetController.native.js.map +1 -0
  71. package/dist/cjs/useSheetOffscreenSize.cjs +63 -0
  72. package/dist/cjs/useSheetOffscreenSize.native.js +70 -0
  73. package/dist/cjs/useSheetOffscreenSize.native.js.map +1 -0
  74. package/dist/cjs/useSheetOpenState.cjs +52 -0
  75. package/dist/cjs/useSheetOpenState.native.js +58 -0
  76. package/dist/cjs/useSheetOpenState.native.js.map +1 -0
  77. package/dist/cjs/useSheetProviderProps.cjs +181 -0
  78. package/dist/cjs/useSheetProviderProps.native.js +196 -0
  79. package/dist/cjs/useSheetProviderProps.native.js.map +1 -0
  80. package/dist/cjs/useSheetScrollViewGestures.cjs +166 -0
  81. package/dist/cjs/useSheetScrollViewGestures.native.js +159 -0
  82. package/dist/cjs/useSheetScrollViewGestures.native.js.map +1 -0
  83. package/dist/esm/GestureDetectorWrapper.mjs +29 -0
  84. package/dist/esm/GestureDetectorWrapper.mjs.map +1 -0
  85. package/dist/esm/GestureDetectorWrapper.native.js +30 -0
  86. package/dist/esm/GestureDetectorWrapper.native.js.map +1 -0
  87. package/dist/esm/GestureSheetContext.mjs +28 -0
  88. package/dist/esm/GestureSheetContext.mjs.map +1 -0
  89. package/dist/esm/GestureSheetContext.native.js +29 -0
  90. package/dist/esm/GestureSheetContext.native.js.map +1 -0
  91. package/dist/esm/Sheet.mjs +89 -0
  92. package/dist/esm/Sheet.mjs.map +1 -0
  93. package/dist/esm/Sheet.native.js +89 -0
  94. package/dist/esm/Sheet.native.js.map +1 -0
  95. package/dist/esm/SheetContext.mjs +6 -0
  96. package/dist/esm/SheetContext.mjs.map +1 -0
  97. package/dist/esm/SheetContext.native.js +6 -0
  98. package/dist/esm/SheetContext.native.js.map +1 -0
  99. package/dist/esm/SheetController.mjs +37 -0
  100. package/dist/esm/SheetController.mjs.map +1 -0
  101. package/dist/esm/SheetController.native.js +40 -0
  102. package/dist/esm/SheetController.native.js.map +1 -0
  103. package/dist/esm/SheetImplementationCustom.mjs +552 -0
  104. package/dist/esm/SheetImplementationCustom.mjs.map +1 -0
  105. package/dist/esm/SheetImplementationCustom.native.js +572 -0
  106. package/dist/esm/SheetImplementationCustom.native.js.map +1 -0
  107. package/dist/esm/SheetScrollView.mjs +180 -0
  108. package/dist/esm/SheetScrollView.mjs.map +1 -0
  109. package/dist/esm/SheetScrollView.native.js +184 -0
  110. package/dist/esm/SheetScrollView.native.js.map +1 -0
  111. package/dist/esm/constants.mjs +6 -0
  112. package/dist/esm/constants.mjs.map +1 -0
  113. package/dist/esm/constants.native.js +6 -0
  114. package/dist/esm/constants.native.js.map +1 -0
  115. package/dist/esm/contexts.mjs +7 -0
  116. package/dist/esm/contexts.mjs.map +1 -0
  117. package/dist/esm/contexts.native.js +7 -0
  118. package/dist/esm/contexts.native.js.map +1 -0
  119. package/dist/esm/controller.mjs +4 -0
  120. package/dist/esm/controller.mjs.map +1 -0
  121. package/dist/esm/controller.native.js +4 -0
  122. package/dist/esm/controller.native.js.map +1 -0
  123. package/dist/esm/createSheet.mjs +165 -0
  124. package/dist/esm/createSheet.mjs.map +1 -0
  125. package/dist/esm/createSheet.native.js +172 -0
  126. package/dist/esm/createSheet.native.js.map +1 -0
  127. package/dist/esm/gestureState.mjs +13 -0
  128. package/dist/esm/gestureState.mjs.map +1 -0
  129. package/dist/esm/gestureState.native.js +13 -0
  130. package/dist/esm/gestureState.native.js.map +1 -0
  131. package/dist/esm/helpers.mjs +10 -0
  132. package/dist/esm/helpers.mjs.map +1 -0
  133. package/dist/esm/helpers.native.js +11 -0
  134. package/dist/esm/helpers.native.js.map +1 -0
  135. package/dist/esm/index.js +12 -0
  136. package/dist/esm/index.js.map +1 -0
  137. package/dist/esm/index.mjs +12 -0
  138. package/dist/esm/index.mjs.map +1 -0
  139. package/dist/esm/index.native.js +12 -0
  140. package/dist/esm/index.native.js.map +1 -0
  141. package/dist/esm/nativeSheet.mjs +70 -0
  142. package/dist/esm/nativeSheet.mjs.map +1 -0
  143. package/dist/esm/nativeSheet.native.js +77 -0
  144. package/dist/esm/nativeSheet.native.js.map +1 -0
  145. package/dist/esm/setupGestureHandler.mjs +26 -0
  146. package/dist/esm/setupGestureHandler.mjs.map +1 -0
  147. package/dist/esm/setupGestureHandler.native.js +26 -0
  148. package/dist/esm/setupGestureHandler.native.js.map +1 -0
  149. package/dist/esm/types.mjs +2 -0
  150. package/dist/esm/types.mjs.map +1 -0
  151. package/dist/esm/types.native.js +2 -0
  152. package/dist/esm/types.native.js.map +1 -0
  153. package/dist/esm/useGestureHandlerPan.mjs +181 -0
  154. package/dist/esm/useGestureHandlerPan.mjs.map +1 -0
  155. package/dist/esm/useGestureHandlerPan.native.js +185 -0
  156. package/dist/esm/useGestureHandlerPan.native.js.map +1 -0
  157. package/dist/esm/useKeyboardControllerSheet.mjs +15 -0
  158. package/dist/esm/useKeyboardControllerSheet.mjs.map +1 -0
  159. package/dist/esm/useKeyboardControllerSheet.native.js +104 -0
  160. package/dist/esm/useKeyboardControllerSheet.native.js.map +1 -0
  161. package/dist/esm/useSheet.mjs +4 -0
  162. package/dist/esm/useSheet.mjs.map +1 -0
  163. package/dist/esm/useSheet.native.js +6 -0
  164. package/dist/esm/useSheet.native.js.map +1 -0
  165. package/dist/esm/useSheetController.mjs +15 -0
  166. package/dist/esm/useSheetController.mjs.map +1 -0
  167. package/dist/esm/useSheetController.native.js +15 -0
  168. package/dist/esm/useSheetController.native.js.map +1 -0
  169. package/dist/esm/useSheetOffscreenSize.mjs +38 -0
  170. package/dist/esm/useSheetOffscreenSize.mjs.map +1 -0
  171. package/dist/esm/useSheetOffscreenSize.native.js +42 -0
  172. package/dist/esm/useSheetOffscreenSize.native.js.map +1 -0
  173. package/dist/esm/useSheetOpenState.mjs +27 -0
  174. package/dist/esm/useSheetOpenState.mjs.map +1 -0
  175. package/dist/esm/useSheetOpenState.native.js +30 -0
  176. package/dist/esm/useSheetOpenState.native.js.map +1 -0
  177. package/dist/esm/useSheetProviderProps.mjs +145 -0
  178. package/dist/esm/useSheetProviderProps.mjs.map +1 -0
  179. package/dist/esm/useSheetProviderProps.native.js +157 -0
  180. package/dist/esm/useSheetProviderProps.native.js.map +1 -0
  181. package/dist/esm/useSheetScrollViewGestures.mjs +141 -0
  182. package/dist/esm/useSheetScrollViewGestures.mjs.map +1 -0
  183. package/dist/esm/useSheetScrollViewGestures.native.js +131 -0
  184. package/dist/esm/useSheetScrollViewGestures.native.js.map +1 -0
  185. package/dist/jsx/GestureDetectorWrapper.mjs +29 -0
  186. package/dist/jsx/GestureDetectorWrapper.mjs.map +1 -0
  187. package/dist/jsx/GestureDetectorWrapper.native.js +58 -0
  188. package/dist/jsx/GestureDetectorWrapper.native.js.map +1 -0
  189. package/dist/jsx/GestureSheetContext.mjs +28 -0
  190. package/dist/jsx/GestureSheetContext.mjs.map +1 -0
  191. package/dist/jsx/GestureSheetContext.native.js +58 -0
  192. package/dist/jsx/GestureSheetContext.native.js.map +1 -0
  193. package/dist/jsx/Sheet.mjs +89 -0
  194. package/dist/jsx/Sheet.mjs.map +1 -0
  195. package/dist/jsx/Sheet.native.js +122 -0
  196. package/dist/jsx/Sheet.native.js.map +1 -0
  197. package/dist/jsx/SheetContext.mjs +6 -0
  198. package/dist/jsx/SheetContext.mjs.map +1 -0
  199. package/dist/jsx/SheetContext.native.js +37 -0
  200. package/dist/jsx/SheetContext.native.js.map +1 -0
  201. package/dist/jsx/SheetController.mjs +37 -0
  202. package/dist/jsx/SheetController.mjs.map +1 -0
  203. package/dist/jsx/SheetController.native.js +79 -0
  204. package/dist/jsx/SheetController.native.js.map +1 -0
  205. package/dist/jsx/SheetImplementationCustom.mjs +552 -0
  206. package/dist/jsx/SheetImplementationCustom.mjs.map +1 -0
  207. package/dist/jsx/SheetImplementationCustom.native.js +615 -0
  208. package/dist/jsx/SheetImplementationCustom.native.js.map +1 -0
  209. package/dist/jsx/SheetScrollView.mjs +180 -0
  210. package/dist/jsx/SheetScrollView.mjs.map +1 -0
  211. package/dist/jsx/SheetScrollView.native.js +223 -0
  212. package/dist/jsx/SheetScrollView.native.js.map +1 -0
  213. package/dist/jsx/constants.mjs +6 -0
  214. package/dist/jsx/constants.mjs.map +1 -0
  215. package/dist/jsx/constants.native.js +37 -0
  216. package/dist/jsx/constants.native.js.map +1 -0
  217. package/dist/jsx/contexts.mjs +7 -0
  218. package/dist/jsx/contexts.mjs.map +1 -0
  219. package/dist/jsx/contexts.native.js +47 -0
  220. package/dist/jsx/contexts.native.js.map +1 -0
  221. package/dist/jsx/controller.mjs +4 -0
  222. package/dist/jsx/controller.mjs.map +1 -0
  223. package/dist/jsx/controller.native.js +34 -0
  224. package/dist/jsx/controller.native.js.map +1 -0
  225. package/dist/jsx/createSheet.mjs +165 -0
  226. package/dist/jsx/createSheet.mjs.map +1 -0
  227. package/dist/jsx/createSheet.native.js +200 -0
  228. package/dist/jsx/createSheet.native.js.map +1 -0
  229. package/dist/jsx/gestureState.mjs +13 -0
  230. package/dist/jsx/gestureState.mjs.map +1 -0
  231. package/dist/jsx/gestureState.native.js +44 -0
  232. package/dist/jsx/gestureState.native.js.map +1 -0
  233. package/dist/jsx/helpers.mjs +10 -0
  234. package/dist/jsx/helpers.mjs.map +1 -0
  235. package/dist/jsx/helpers.native.js +39 -0
  236. package/dist/jsx/helpers.native.js.map +1 -0
  237. package/dist/jsx/index.js +12 -0
  238. package/dist/jsx/index.js.map +1 -0
  239. package/dist/jsx/index.mjs +12 -0
  240. package/dist/jsx/index.mjs.map +1 -0
  241. package/dist/jsx/index.native.js +33 -0
  242. package/dist/jsx/index.native.js.map +1 -0
  243. package/dist/jsx/nativeSheet.mjs +70 -0
  244. package/dist/jsx/nativeSheet.mjs.map +1 -0
  245. package/dist/jsx/nativeSheet.native.js +106 -0
  246. package/dist/jsx/nativeSheet.native.js.map +1 -0
  247. package/dist/jsx/setupGestureHandler.mjs +26 -0
  248. package/dist/jsx/setupGestureHandler.mjs.map +1 -0
  249. package/dist/jsx/setupGestureHandler.native.js +55 -0
  250. package/dist/jsx/setupGestureHandler.native.js.map +1 -0
  251. package/dist/jsx/types.mjs +2 -0
  252. package/dist/jsx/types.mjs.map +1 -0
  253. package/dist/jsx/types.native.js +21 -0
  254. package/dist/jsx/types.native.js.map +1 -0
  255. package/dist/jsx/useGestureHandlerPan.mjs +181 -0
  256. package/dist/jsx/useGestureHandlerPan.mjs.map +1 -0
  257. package/dist/jsx/useGestureHandlerPan.native.js +213 -0
  258. package/dist/jsx/useGestureHandlerPan.native.js.map +1 -0
  259. package/dist/jsx/useKeyboardControllerSheet.mjs +15 -0
  260. package/dist/jsx/useKeyboardControllerSheet.mjs.map +1 -0
  261. package/dist/jsx/useKeyboardControllerSheet.native.js +132 -0
  262. package/dist/jsx/useKeyboardControllerSheet.native.js.map +1 -0
  263. package/dist/jsx/useSheet.mjs +4 -0
  264. package/dist/jsx/useSheet.mjs.map +1 -0
  265. package/dist/jsx/useSheet.native.js +34 -0
  266. package/dist/jsx/useSheet.native.js.map +1 -0
  267. package/dist/jsx/useSheetController.mjs +15 -0
  268. package/dist/jsx/useSheetController.mjs.map +1 -0
  269. package/dist/jsx/useSheetController.native.js +55 -0
  270. package/dist/jsx/useSheetController.native.js.map +1 -0
  271. package/dist/jsx/useSheetOffscreenSize.mjs +38 -0
  272. package/dist/jsx/useSheetOffscreenSize.mjs.map +1 -0
  273. package/dist/jsx/useSheetOffscreenSize.native.js +70 -0
  274. package/dist/jsx/useSheetOffscreenSize.native.js.map +1 -0
  275. package/dist/jsx/useSheetOpenState.mjs +27 -0
  276. package/dist/jsx/useSheetOpenState.mjs.map +1 -0
  277. package/dist/jsx/useSheetOpenState.native.js +58 -0
  278. package/dist/jsx/useSheetOpenState.native.js.map +1 -0
  279. package/dist/jsx/useSheetProviderProps.mjs +145 -0
  280. package/dist/jsx/useSheetProviderProps.mjs.map +1 -0
  281. package/dist/jsx/useSheetProviderProps.native.js +196 -0
  282. package/dist/jsx/useSheetProviderProps.native.js.map +1 -0
  283. package/dist/jsx/useSheetScrollViewGestures.mjs +141 -0
  284. package/dist/jsx/useSheetScrollViewGestures.mjs.map +1 -0
  285. package/dist/jsx/useSheetScrollViewGestures.native.js +159 -0
  286. package/dist/jsx/useSheetScrollViewGestures.native.js.map +1 -0
  287. package/next.md +78 -0
  288. package/package.json +96 -0
  289. package/setup-gesture-handler/index.cjs +2 -0
  290. package/setup-gesture-handler/index.js +2 -0
  291. package/setup-gesture-handler/index.native.cjs +2 -0
  292. package/setup-gesture-handler/index.native.js +2 -0
  293. package/setup-gesture-handler.cjs +1 -0
  294. package/src/GestureDetectorWrapper.tsx +41 -0
  295. package/src/GestureSheetContext.tsx +62 -0
  296. package/src/Sheet.tsx +114 -0
  297. package/src/SheetContext.tsx +11 -0
  298. package/src/SheetController.tsx +47 -0
  299. package/src/SheetImplementationCustom.tsx +879 -0
  300. package/src/SheetScrollView.tsx +195 -0
  301. package/src/constants.tsx +5 -0
  302. package/src/contexts.ts +9 -0
  303. package/src/controller.ts +9 -0
  304. package/src/createSheet.tsx +296 -0
  305. package/src/gestureState.ts +24 -0
  306. package/src/helpers.tsx +31 -0
  307. package/src/index.ts +11 -0
  308. package/src/nativeSheet.tsx +89 -0
  309. package/src/setupGestureHandler.ts +34 -0
  310. package/src/types.tsx +181 -0
  311. package/src/useGestureHandlerPan.tsx +364 -0
  312. package/src/useKeyboardControllerSheet.native.ts +136 -0
  313. package/src/useKeyboardControllerSheet.ts +26 -0
  314. package/src/useSheet.tsx +3 -0
  315. package/src/useSheetController.tsx +31 -0
  316. package/src/useSheetOffscreenSize.tsx +49 -0
  317. package/src/useSheetOpenState.tsx +33 -0
  318. package/src/useSheetProviderProps.tsx +223 -0
  319. package/src/useSheetScrollViewGestures.native.ts +163 -0
  320. package/src/useSheetScrollViewGestures.ts +194 -0
  321. package/tsconfig.json +56 -0
  322. package/types/GestureDetectorWrapper.d.ts +14 -0
  323. package/types/GestureDetectorWrapper.d.ts.map +1 -0
  324. package/types/GestureSheetContext.d.ts +36 -0
  325. package/types/GestureSheetContext.d.ts.map +1 -0
  326. package/types/Sheet.d.ts +183 -0
  327. package/types/Sheet.d.ts.map +1 -0
  328. package/types/SheetContext.d.ts +43 -0
  329. package/types/SheetContext.d.ts.map +1 -0
  330. package/types/SheetController.d.ts +6 -0
  331. package/types/SheetController.d.ts.map +1 -0
  332. package/types/SheetImplementationCustom.d.ts +36 -0
  333. package/types/SheetImplementationCustom.d.ts.map +1 -0
  334. package/types/SheetScrollView.d.ts +40 -0
  335. package/types/SheetScrollView.d.ts.map +1 -0
  336. package/types/constants.d.ts +5 -0
  337. package/types/constants.d.ts.map +1 -0
  338. package/types/contexts.d.ts +6 -0
  339. package/types/contexts.d.ts.map +1 -0
  340. package/types/controller.d.ts +3 -0
  341. package/types/controller.d.ts.map +1 -0
  342. package/types/createSheet.d.ts +194 -0
  343. package/types/createSheet.d.ts.map +1 -0
  344. package/types/gestureState.d.ts +11 -0
  345. package/types/gestureState.d.ts.map +1 -0
  346. package/types/helpers.d.ts +2 -0
  347. package/types/helpers.d.ts.map +1 -0
  348. package/types/index.d.ts +12 -0
  349. package/types/index.d.ts.map +1 -0
  350. package/types/nativeSheet.d.ts +10 -0
  351. package/types/nativeSheet.d.ts.map +1 -0
  352. package/types/setupGestureHandler.d.ts +11 -0
  353. package/types/setupGestureHandler.d.ts.map +1 -0
  354. package/types/types.d.ts +147 -0
  355. package/types/types.d.ts.map +1 -0
  356. package/types/useGestureHandlerPan.d.ts +44 -0
  357. package/types/useGestureHandlerPan.d.ts.map +1 -0
  358. package/types/useKeyboardControllerSheet.d.ts +7 -0
  359. package/types/useKeyboardControllerSheet.d.ts.map +1 -0
  360. package/types/useKeyboardControllerSheet.native.d.ts +13 -0
  361. package/types/useKeyboardControllerSheet.native.d.ts.map +1 -0
  362. package/types/useSheet.d.ts +2 -0
  363. package/types/useSheet.d.ts.map +1 -0
  364. package/types/useSheetController.d.ts +20 -0
  365. package/types/useSheetController.d.ts.map +1 -0
  366. package/types/useSheetOffscreenSize.d.ts +3 -0
  367. package/types/useSheetOffscreenSize.d.ts.map +1 -0
  368. package/types/useSheetOpenState.d.ts +9 -0
  369. package/types/useSheetOpenState.d.ts.map +1 -0
  370. package/types/useSheetProviderProps.d.ts +36 -0
  371. package/types/useSheetProviderProps.d.ts.map +1 -0
  372. package/types/useSheetScrollViewGestures.d.ts +12 -0
  373. package/types/useSheetScrollViewGestures.d.ts.map +1 -0
  374. package/types/useSheetScrollViewGestures.native.d.ts +21 -0
  375. package/types/useSheetScrollViewGestures.native.d.ts.map +1 -0
@@ -0,0 +1,879 @@
1
+ import { ProvideAdaptContext, useAdaptContext } from '@hanzogui/adapt'
2
+ import { AnimatePresence } from '@hanzogui/animate-presence'
3
+ import { useComposedRefs } from '@hanzogui/compose-refs'
4
+ import { isWeb, useIsomorphicLayoutEffect } from '@hanzogui/constants'
5
+ import {
6
+ LayoutMeasurementController,
7
+ View as HanzoguiView,
8
+ useConfiguration,
9
+ useDidFinishSSR,
10
+ useEvent,
11
+ useThemeName,
12
+ } from '@hanzogui/core'
13
+ import { getSafeArea } from '@hanzogui/native'
14
+ import { needsPortalRepropagation, Portal } from '@hanzogui/portal'
15
+ import React, { useState } from 'react'
16
+ import type {
17
+ Animated,
18
+ GestureResponderEvent,
19
+ LayoutChangeEvent,
20
+ PanResponderGestureState,
21
+ } from 'react-native'
22
+ import { Dimensions, PanResponder, View } from 'react-native'
23
+ import { ParentSheetContext, SheetInsideSheetContext } from './contexts'
24
+ import { GestureDetectorWrapper } from './GestureDetectorWrapper'
25
+ import { GestureSheetProvider } from './GestureSheetContext'
26
+ import { resisted } from './helpers'
27
+ import { SheetProvider } from './SheetContext'
28
+ import type { SheetProps, SnapPointsMode } from './types'
29
+ import { useGestureHandlerPan } from './useGestureHandlerPan'
30
+ import { useKeyboardControllerSheet } from './useKeyboardControllerSheet'
31
+ import { useSheetOpenState } from './useSheetOpenState'
32
+ import { useSheetProviderProps } from './useSheetProviderProps'
33
+
34
+ const hiddenSize = 10_000.1
35
+
36
+ // safe area top inset, cached per-session (device-constant value)
37
+ let _cachedSafeAreaTop: number | undefined
38
+ function getSafeAreaTopInset(): number {
39
+ if (_cachedSafeAreaTop !== undefined) return _cachedSafeAreaTop
40
+ // use @hanzogui/native abstraction - returns 0 when not enabled
41
+ _cachedSafeAreaTop = getSafeArea().getInsets().top
42
+ return _cachedSafeAreaTop
43
+ }
44
+
45
+ let sheetHiddenStyleSheet: HTMLStyleElement | null = null
46
+
47
+ // on web we are always relative to window, on to screen
48
+ const relativeDimensionTo = isWeb ? 'window' : 'screen'
49
+
50
+ export const SheetImplementationCustom = React.forwardRef<View, SheetProps>(
51
+ function SheetImplementationCustom(props, forwardedRef) {
52
+ const parentSheet = React.useContext(ParentSheetContext)
53
+
54
+ const {
55
+ transition,
56
+ transitionConfig: transitionConfigProp,
57
+ modal = false,
58
+ zIndex = parentSheet.zIndex + 1,
59
+ moveOnKeyboardChange = false,
60
+ unmountChildrenWhenHidden = false,
61
+ portalProps,
62
+ containerComponent: ContainerComponent = React.Fragment,
63
+ onAnimationComplete,
64
+ } = props
65
+
66
+ const state = useSheetOpenState(props)
67
+ const [overlayComponent, setOverlayComponent] = React.useState<React.ReactNode>(null)
68
+
69
+ const providerProps = useSheetProviderProps(props, state, {
70
+ onOverlayComponent: setOverlayComponent,
71
+ })
72
+ const {
73
+ frameSize,
74
+ setFrameSize,
75
+ snapPoints,
76
+ snapPointsMode,
77
+ hasFit,
78
+ position,
79
+ setPosition,
80
+ scrollBridge,
81
+ screenSize,
82
+ setMaxContentSize,
83
+ maxSnapPoint,
84
+ } = providerProps
85
+ const { open, controller, isHidden } = state
86
+ const openRef = React.useRef(open)
87
+ openRef.current = open
88
+
89
+ const sheetRef = React.useRef<View>(undefined as unknown as View)
90
+ const ref = useComposedRefs(forwardedRef, sheetRef, providerProps.contentRef as any)
91
+
92
+ // TODO this can be extracted into a helper getAnimationConfig(animationProp as array | string)
93
+ const { animationDriver } = useConfiguration()
94
+
95
+ if (!animationDriver) {
96
+ throw new Error(`Sheet requires an animation driver to be set`)
97
+ }
98
+
99
+ const transitionConfig = (() => {
100
+ // explicit transitionConfig prop always takes precedence
101
+ if (transitionConfigProp) {
102
+ return transitionConfigProp
103
+ }
104
+
105
+ const [animationProp, animationPropConfig] = !transition
106
+ ? []
107
+ : Array.isArray(transition)
108
+ ? transition
109
+ : ([transition] as const)
110
+
111
+ // look up named animation config from driver if available
112
+ if (animationProp && animationDriver.animations?.[animationProp as string]) {
113
+ return {
114
+ ...animationDriver.animations[animationProp as string],
115
+ ...animationPropConfig,
116
+ }
117
+ }
118
+
119
+ return null
120
+ })()
121
+
122
+ /**
123
+ * This is a hacky workaround for native:
124
+ */
125
+ const [isShowingInnerSheet, setIsShowingInnerSheet] = React.useState(false)
126
+ // when using Gorhom portal (no teleport), inner sheets need to hide parent
127
+ const shouldHideParentSheet =
128
+ !isWeb && modal && isShowingInnerSheet && needsPortalRepropagation()
129
+
130
+ const sheetInsideSheet = React.useContext(SheetInsideSheetContext)
131
+ const onInnerSheet = React.useCallback((hasChild: boolean) => {
132
+ setIsShowingInnerSheet(hasChild)
133
+ }, [])
134
+
135
+ // FIX: Store stable frameSize to prevent recalculation during exit animation
136
+ const stableFrameSize = React.useRef(frameSize)
137
+
138
+ React.useEffect(() => {
139
+ // Only update stable size when sheet is open
140
+ if (open && frameSize) {
141
+ stableFrameSize.current = frameSize
142
+ }
143
+ }, [open, frameSize])
144
+
145
+ // use stableFrameSize when closing to prevent position jumps during exit animation
146
+ // but when opening, always use the current frameSize so positions update correctly
147
+ const effectiveFrameSize = open ? frameSize : stableFrameSize.current || frameSize
148
+
149
+ const positions = React.useMemo(
150
+ () =>
151
+ snapPoints.map((point) =>
152
+ getYPositions(snapPointsMode, point, screenSize, effectiveFrameSize)
153
+ ),
154
+ [screenSize, effectiveFrameSize, snapPoints, snapPointsMode]
155
+ )
156
+
157
+ // keyboard state tracking — just tracks height/visibility, no position animation.
158
+ // Position animation is handled via keyboard-adjusted positions below,
159
+ // matching the react-native-actions-sheet pattern.
160
+ const {
161
+ keyboardHeight,
162
+ isKeyboardVisible,
163
+ dismissKeyboard,
164
+ pauseKeyboardHandler,
165
+ flushPendingHide,
166
+ } = useKeyboardControllerSheet({
167
+ enabled: !isWeb && Boolean(moveOnKeyboardChange),
168
+ })
169
+
170
+ const [isDragging, setIsDragging_] = React.useState(false)
171
+
172
+ // synchronous dragging ref — set BEFORE async state commits.
173
+ // RNGH onBegin fires before keyboard hide event reaches JS,
174
+ // so the ref is true by the time activePositions memo re-evaluates.
175
+ // Also controls pauseKeyboardHandler to freeze keyboard state during drag.
176
+ const isDraggingRef = React.useRef(false)
177
+ const setIsDragging = React.useCallback(
178
+ (val: boolean) => {
179
+ isDraggingRef.current = val
180
+ pauseKeyboardHandler.current = val
181
+ setIsDragging_(val)
182
+ // when drag ends, flush any keyboard hide that was suppressed during drag
183
+ // so isKeyboardVisible/keyboardHeight reflect actual state
184
+ if (!val) {
185
+ flushPendingHide()
186
+ }
187
+ },
188
+ [pauseKeyboardHandler, flushPendingHide]
189
+ )
190
+
191
+ // keyboard-adjusted positions: shift snap points up by keyboard height
192
+ // when keyboard is visible. This drives both gesture snap calculation
193
+ // and animation targets — keyboard never dismissed during drag.
194
+ // Capped at safe area top inset so the sheet never goes above the notch/status bar
195
+ // (matching the react-native-actions-sheet pattern).
196
+ //
197
+ // IMPORTANT: frozen during drag to prevent gesture handler recreation.
198
+ // When user drags, TextInput may blur → keyboard dismisses → positions would revert,
199
+ // causing the gesture useMemo to recreate and cancel the active drag.
200
+ // The post-drag reconciliation effect handles animating to correct position after drag ends.
201
+ const activePositionsRef = React.useRef(positions)
202
+ const activePositions = React.useMemo(() => {
203
+ // during drag, return frozen positions to prevent gesture handler recreation.
204
+ // check both state (for re-render trigger) and ref (for synchronous check
205
+ // when keyboard hide event fires before isDragging state commits)
206
+ if (isDragging || isDraggingRef.current) return activePositionsRef.current
207
+
208
+ let result: number[]
209
+ if (!isKeyboardVisible || keyboardHeight <= 0) {
210
+ result = positions
211
+ } else {
212
+ const safeAreaTop = isWeb ? 0 : getSafeAreaTopInset()
213
+ result = positions.map((p) => {
214
+ // don't adjust the off-screen/close position (from dismissOnSnapToBottom's 0% snap)
215
+ // — it must stay at screenSize so the user can drag between real snap points
216
+ // without accidentally closing the sheet
217
+ if (screenSize && p >= screenSize) return p
218
+ return Math.max(safeAreaTop, p - keyboardHeight)
219
+ })
220
+ }
221
+ activePositionsRef.current = result
222
+ return result
223
+ }, [positions, isKeyboardVisible, keyboardHeight, screenSize, isDragging])
224
+
225
+ const { useAnimatedNumber, useAnimatedNumberStyle, useAnimatedNumberReaction } =
226
+ animationDriver
227
+ const AnimatedView = (animationDriver.View ?? HanzoguiView) as typeof Animated.View
228
+
229
+ useIsomorphicLayoutEffect(() => {
230
+ if (!(sheetInsideSheet && open)) return
231
+ sheetInsideSheet(true)
232
+ return () => {
233
+ sheetInsideSheet(false)
234
+ }
235
+ }, [sheetInsideSheet, open])
236
+
237
+ const nextParentContext = React.useMemo(
238
+ () => ({
239
+ zIndex,
240
+ }),
241
+ [zIndex]
242
+ )
243
+
244
+ const isMounted = useDidFinishSSR()
245
+ const startPosition = isMounted && screenSize ? screenSize : hiddenSize
246
+ const animatedNumber = useAnimatedNumber(startPosition)
247
+ const at = React.useRef(startPosition)
248
+ const hasntMeasured = at.current === hiddenSize
249
+ const [disableAnimation, setDisableAnimation] = useState(hasntMeasured)
250
+
251
+ // use skipNextAnimation signal from controller (set when adapt handoff occurs)
252
+ const skipAdaptAnimation = React.useRef(false)
253
+ if (controller?.skipNextAnimation) {
254
+ skipAdaptAnimation.current = true
255
+ }
256
+
257
+ const hasScrollView = React.useRef(false)
258
+
259
+ // safety fallback timer for sheet close opacity
260
+ const opacityFallbackTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)
261
+
262
+ useAnimatedNumberReaction(
263
+ {
264
+ value: animatedNumber,
265
+ hostRef: sheetRef,
266
+ },
267
+ React.useCallback(
268
+ (value) => {
269
+ at.current = value
270
+ scrollBridge.paneY = value
271
+ // update isAtTop for scroll enable/disable
272
+ // activePositions[0] is the top snap point (keyboard-adjusted minY)
273
+ const minY = activePositions[0]
274
+ const wasAtTop = scrollBridge.isAtTop
275
+ const nowAtTop = value <= minY + 5
276
+ if (wasAtTop !== nowAtTop) {
277
+ scrollBridge.isAtTop = nowAtTop
278
+ // when reaching top, enable scroll; when leaving top, disable scroll
279
+ // this preemptively sets scroll state before any gestures start
280
+ if (nowAtTop) {
281
+ // if scroll drifted during drag (e.g. fast swipe from position 1),
282
+ // reset it to 0 before enabling free scroll
283
+ if (scrollBridge.y > 0) {
284
+ scrollBridge.forceScrollTo?.(0)
285
+ scrollBridge.y = 0
286
+ }
287
+ scrollBridge.scrollLockY = undefined
288
+ scrollBridge.setScrollEnabled?.(true)
289
+ } else {
290
+ scrollBridge.scrollLockY = 0
291
+ scrollBridge.setScrollEnabled?.(false)
292
+ }
293
+ }
294
+ },
295
+ [animationDriver, activePositions]
296
+ )
297
+ )
298
+
299
+ function stopSpring() {
300
+ animatedNumber.stop()
301
+ if (scrollBridge.onFinishAnimate) {
302
+ scrollBridge.onFinishAnimate()
303
+ scrollBridge.onFinishAnimate = undefined
304
+ }
305
+ }
306
+
307
+ const animateTo = useEvent((position: number, animationOverride?: any) => {
308
+ if (frameSize === 0) return
309
+
310
+ let toValue = isHidden || position === -1 ? screenSize : activePositions[position]
311
+
312
+ if (at.current === toValue) return
313
+
314
+ at.current = toValue
315
+ stopSpring()
316
+
317
+ const isOpenAnimation = position !== -1 && !isHidden
318
+
319
+ // clear any pending fallback timer
320
+ if (opacityFallbackTimer.current) {
321
+ clearTimeout(opacityFallbackTimer.current)
322
+ opacityFallbackTimer.current = null
323
+ }
324
+
325
+ const animationCompleteCallback = () => {
326
+ if (opacityFallbackTimer.current) {
327
+ clearTimeout(opacityFallbackTimer.current)
328
+ opacityFallbackTimer.current = null
329
+ }
330
+ // use openRef (live) not open (stale closure) — if the sheet
331
+ // was reopened before this callback fires (e.g. cancelled close
332
+ // animation), we must not hide it
333
+ if (!isOpenAnimation && !openRef.current) {
334
+ setOpacity(0)
335
+ }
336
+ onAnimationComplete?.({ open: isOpenAnimation })
337
+ // also notify the SheetController so a parent (e.g. Dialog adapt)
338
+ // can hold the sheet's children mounted until the slide-out is done
339
+ controller?.onAnimationComplete?.({ open: isOpenAnimation })
340
+ }
341
+
342
+ // safety fallback: if animation callback never fires, still hide the sheet
343
+ if (!isOpenAnimation) {
344
+ opacityFallbackTimer.current = setTimeout(() => {
345
+ opacityFallbackTimer.current = null
346
+ // check live open state via ref — sheet may have reopened (e.g. adapt handoff)
347
+ if (!openRef.current) {
348
+ setOpacity(0)
349
+ }
350
+ }, 1000)
351
+ }
352
+
353
+ // skip animation when adapting from dialog to sheet
354
+ if (skipAdaptAnimation.current) {
355
+ skipAdaptAnimation.current = false
356
+ animatedNumber.setValue(
357
+ toValue,
358
+ { type: 'timing', duration: 0 },
359
+ animationCompleteCallback
360
+ )
361
+ return
362
+ }
363
+
364
+ animatedNumber.setValue(
365
+ toValue,
366
+ animationOverride || {
367
+ type: 'spring',
368
+ ...transitionConfig,
369
+ },
370
+ animationCompleteCallback
371
+ )
372
+ })
373
+
374
+ useIsomorphicLayoutEffect(() => {
375
+ // we need to do a *three* step process for the css driver
376
+ // first render off screen for ssr safety (hiddenSize)
377
+ // then render to bottom of screen without animation (screenSize)
378
+ // then add the animation as it animates from screenSize to position
379
+
380
+ if (hasntMeasured && screenSize && frameSize) {
381
+ at.current = screenSize
382
+ animatedNumber.setValue(
383
+ screenSize,
384
+ {
385
+ type: 'timing',
386
+ duration: 0,
387
+ },
388
+ () => {
389
+ // imperfect but struggling to render properly here
390
+ setTimeout(() => {
391
+ setDisableAnimation(false)
392
+ }, 10)
393
+ }
394
+ )
395
+ return
396
+ }
397
+
398
+ if (disableAnimation) {
399
+ return
400
+ }
401
+
402
+ if (!frameSize || !screenSize || isHidden || (hasntMeasured && !open)) {
403
+ return
404
+ }
405
+
406
+ // finally, animate
407
+ animateTo(position)
408
+
409
+ // reset scroll bridge
410
+ if (position === -1) {
411
+ scrollBridge.scrollLock = false
412
+ scrollBridge.scrollStartY = -1
413
+ }
414
+
415
+ // set initial isAtTop state when sheet opens
416
+ // position 0 = top snap point, so isAtTop = true
417
+ if (open && position >= 0) {
418
+ const isTopPosition = position === 0
419
+ scrollBridge.isAtTop = isTopPosition
420
+ if (isTopPosition) {
421
+ scrollBridge.scrollLockY = undefined
422
+ scrollBridge.setScrollEnabled?.(true)
423
+ } else {
424
+ scrollBridge.scrollLockY = 0
425
+ scrollBridge.setScrollEnabled?.(false)
426
+ }
427
+ }
428
+ }, [hasntMeasured, disableAnimation, isHidden, frameSize, screenSize, open, position])
429
+
430
+ const disableDrag = props.disableDrag ?? controller?.disableDrag
431
+ const themeName = useThemeName()
432
+ const [blockPan, setBlockPan] = React.useState(false)
433
+
434
+ const panResponder = React.useMemo(() => {
435
+ if (disableDrag) return
436
+ if (!frameSize) return
437
+ if (isShowingInnerSheet) return
438
+
439
+ const minY = positions[0]
440
+ scrollBridge.paneMinY = minY
441
+ let startY = at.current
442
+
443
+ function setPanning(val: boolean) {
444
+ setIsDragging(val)
445
+
446
+ // make unselectable:
447
+ if (process.env.TAMAGUI_TARGET === 'web') {
448
+ if (!sheetHiddenStyleSheet) {
449
+ sheetHiddenStyleSheet = document.createElement('style')
450
+ if (typeof document.head !== 'undefined') {
451
+ document.head.appendChild(sheetHiddenStyleSheet)
452
+ }
453
+ }
454
+ if (!val) {
455
+ sheetHiddenStyleSheet.innerText = ''
456
+ } else {
457
+ sheetHiddenStyleSheet.innerText =
458
+ ':root * { user-select: none !important; -webkit-user-select: none !important; }'
459
+ }
460
+ }
461
+ }
462
+
463
+ const release = ({ vy }: { dragAt: number; vy: number }) => {
464
+ scrollBridge.setParentDragging(false)
465
+ if (scrollBridge.scrollLock) {
466
+ return
467
+ }
468
+
469
+ isExternalDrag = false
470
+ previouslyScrolling = false
471
+ setPanning(false)
472
+ // use the actual current animated position rather than dragAt + startY.
473
+ // after mid-gesture handoffs (pan→scroll→pan), startY can be stale
474
+ // causing the computed position to be wildly wrong (triggering dismiss).
475
+ const currentPos = at.current
476
+ // vy goes up to about 4 at most (+ is down, - is up)
477
+ const end = currentPos + frameSize * vy * 0.2
478
+
479
+ let closestPoint = 0
480
+ let dist = Number.POSITIVE_INFINITY
481
+
482
+ for (let i = 0; i < positions.length; i++) {
483
+ const position = positions[i]
484
+ const curDist = end > position ? end - position : position - end
485
+ if (curDist < dist) {
486
+ dist = curDist
487
+ closestPoint = i
488
+ }
489
+ }
490
+
491
+ // have to call both because state may not change but need to snap back
492
+ setPosition(closestPoint)
493
+ animateTo(closestPoint)
494
+ }
495
+
496
+ const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {
497
+ release({
498
+ vy: state.vy,
499
+ dragAt: state.dy,
500
+ })
501
+ }
502
+
503
+ let previouslyScrolling = false
504
+
505
+ const onMoveShouldSet = (
506
+ e: GestureResponderEvent,
507
+ { dy }: PanResponderGestureState
508
+ ): boolean => {
509
+ function getShouldSet() {
510
+ // if dragging handle always allow:
511
+ if (e.target === providerProps.handleRef.current) {
512
+ return true
513
+ }
514
+
515
+ if (scrollBridge.hasScrollableContent === true) {
516
+ if (scrollBridge.scrollLock) {
517
+ return false
518
+ }
519
+
520
+ const isScrolled = scrollBridge.y !== 0
521
+
522
+ // Update the dragging direction
523
+ const isDraggingUp = dy < 0
524
+
525
+ // we can treat near top instead of exactly to avoid trouble with springs
526
+ const isNearTop = scrollBridge.paneY - 5 <= scrollBridge.paneMinY
527
+ if (isScrolled) {
528
+ previouslyScrolling = true
529
+ return false
530
+ }
531
+ // prevent drag once at top and pulling up
532
+ if (isNearTop) {
533
+ if (hasScrollView.current && isDraggingUp) {
534
+ return false
535
+ }
536
+ }
537
+ }
538
+
539
+ // we could do some detection of other touchables and cancel here..
540
+ return Math.abs(dy) > 10
541
+ }
542
+
543
+ const granted = getShouldSet()
544
+
545
+ if (granted) {
546
+ scrollBridge.setParentDragging(true)
547
+ }
548
+
549
+ return granted
550
+ }
551
+
552
+ const grant = () => {
553
+ setPanning(true)
554
+ stopSpring()
555
+ startY = at.current
556
+ }
557
+
558
+ let isExternalDrag = false
559
+
560
+ scrollBridge.drag = (dy) => {
561
+ if (!isExternalDrag) {
562
+ isExternalDrag = true
563
+ grant()
564
+ }
565
+ const to = dy + startY
566
+ animatedNumber.setValue(resisted(to, minY), { type: 'direct' })
567
+ }
568
+
569
+ scrollBridge.release = release
570
+
571
+ // direct snap to position without release calculation (for handoff cases)
572
+ scrollBridge.snapToPosition = (positionIndex: number) => {
573
+ isExternalDrag = false
574
+ previouslyScrolling = false
575
+ setPanning(false)
576
+ setPosition(positionIndex)
577
+ animateTo(positionIndex)
578
+ }
579
+
580
+ return PanResponder.create({
581
+ onMoveShouldSetPanResponder: onMoveShouldSet,
582
+ onPanResponderGrant: grant,
583
+ onPanResponderMove: (_e, { dy }) => {
584
+ const toFull = dy + startY
585
+ const to = resisted(toFull, minY)
586
+
587
+ // handles the case where you hand off back and forth more than once
588
+ const isAtTop = to <= minY
589
+ if (isAtTop) {
590
+ scrollBridge.setParentDragging(false)
591
+ } else {
592
+ scrollBridge.setParentDragging(true)
593
+ }
594
+
595
+ animatedNumber.setValue(to, { type: 'direct' })
596
+ },
597
+ onPanResponderEnd: finish,
598
+ onPanResponderTerminate: finish,
599
+ onPanResponderRelease: finish,
600
+ })
601
+ }, [disableDrag, isShowingInnerSheet, animateTo, frameSize, positions, setPosition])
602
+
603
+ // animate to keyboard-adjusted position when keyboard state changes
604
+ React.useEffect(() => {
605
+ if (isDragging || isHidden || !open || disableAnimation) return
606
+ if (!frameSize || !screenSize) return
607
+ // use timing animation to match iOS keyboard animation (~250ms)
608
+ animateTo(position, { type: 'timing', duration: 250 })
609
+ }, [isKeyboardVisible, keyboardHeight])
610
+
611
+ // reconcile position after drag ends — if keyboard dismissed during drag
612
+ // (e.g., input blur), activePositions reverted but onEnd used frozen positions
613
+ // for snap index. This effect ensures the sheet animates to the correct
614
+ // non-keyboard-adjusted position for the chosen snap index.
615
+ const wasDragging = React.useRef(false)
616
+ React.useEffect(() => {
617
+ if (isDragging) {
618
+ wasDragging.current = true
619
+ return
620
+ }
621
+ if (!wasDragging.current) return
622
+ wasDragging.current = false
623
+ // drag just ended — reconcile position with latest activePositions
624
+ if (!frameSize || !screenSize || isHidden || !open) return
625
+ animateTo(position)
626
+ }, [isDragging])
627
+
628
+ // dismiss keyboard when sheet closes
629
+ React.useEffect(() => {
630
+ if (!open && isKeyboardVisible) {
631
+ dismissKeyboard()
632
+ }
633
+ }, [open])
634
+
635
+ // gesture handler hook for RNGH-based gesture coordination
636
+ const { panGesture, panGestureRef, gestureHandlerEnabled } = useGestureHandlerPan({
637
+ positions: activePositions,
638
+ frameSize,
639
+ setPosition,
640
+ animateTo,
641
+ stopSpring,
642
+ scrollBridge,
643
+ setIsDragging,
644
+ getCurrentPosition: () => at.current,
645
+ resisted,
646
+ disableDrag,
647
+ isShowingInnerSheet,
648
+ setAnimatedPosition: (val: number) => {
649
+ // directly set the animated value for smooth dragging
650
+ at.current = val
651
+ animatedNumber.setValue(val, { type: 'direct' })
652
+ },
653
+ pauseKeyboardHandler,
654
+ })
655
+
656
+ const handleAnimationViewLayout = useEvent((e: LayoutChangeEvent) => {
657
+ // don't update frameSize during exit animation to prevent position jumps
658
+ if (!open && stableFrameSize.current !== 0) {
659
+ return
660
+ }
661
+
662
+ // avoid bugs where it grows forever for whatever reason
663
+ // For inline mode (non-modal), don't cap at window height - use actual layout
664
+ const layoutHeight = e.nativeEvent?.layout.height
665
+ const next = modal
666
+ ? Math.min(layoutHeight, Dimensions.get(relativeDimensionTo).height)
667
+ : layoutHeight
668
+ if (!next) return
669
+ setFrameSize(next)
670
+ })
671
+
672
+ const handleMaxContentViewLayout = React.useCallback((e: LayoutChangeEvent) => {
673
+ // avoid bugs where it grows forever for whatever reason
674
+ const next = Math.min(
675
+ e.nativeEvent?.layout.height,
676
+ Dimensions.get(relativeDimensionTo).height
677
+ )
678
+ if (!next) return
679
+ setMaxContentSize(next)
680
+ }, [])
681
+
682
+ const getAnimatedNumberStyle = React.useCallback(
683
+ (val: number) => {
684
+ 'worklet'
685
+ const translateY = frameSize === 0 ? hiddenSize : val
686
+
687
+ return {
688
+ transform: [{ translateY }],
689
+ }
690
+ },
691
+ [frameSize]
692
+ )
693
+
694
+ const animatedStyle = useAnimatedNumberStyle(animatedNumber, getAnimatedNumberStyle)
695
+
696
+ // we need to set this *after* fully closed to 0, to avoid it overlapping
697
+ // the page when resizing quickly on web for example
698
+ const [opacity, setOpacity] = React.useState(open ? 1 : 0)
699
+ if (open && opacity === 0) {
700
+ setOpacity(1)
701
+ // cancel any pending close fallback — sheet is reopening
702
+ if (opacityFallbackTimer.current) {
703
+ clearTimeout(opacityFallbackTimer.current)
704
+ opacityFallbackTimer.current = null
705
+ }
706
+ }
707
+
708
+ const forcedContentHeight = hasFit
709
+ ? undefined
710
+ : snapPointsMode === 'percent'
711
+ ? // Use dvh for modal (viewport-relative), % for inline (container-relative)
712
+ `${maxSnapPoint}${isWeb ? (modal ? 'dvh' : '%') : '%'}`
713
+ : maxSnapPoint
714
+
715
+ const setHasScrollView = React.useCallback((val: boolean) => {
716
+ hasScrollView.current = val
717
+ }, [])
718
+ // const id = useId()
719
+ // const { AdaptProvider, when, children } = useAdaptParent({
720
+ // scope: `${id}Sheet`,
721
+ // portal: true,
722
+ // })
723
+
724
+ let contents = (
725
+ <LayoutMeasurementController disable={!open}>
726
+ <ParentSheetContext.Provider value={nextParentContext}>
727
+ <SheetProvider {...providerProps} setHasScrollView={setHasScrollView}>
728
+ <GestureSheetProvider
729
+ isDragging={isDragging}
730
+ blockPan={blockPan}
731
+ setBlockPan={setBlockPan}
732
+ panGesture={panGesture}
733
+ panGestureRef={panGestureRef}
734
+ >
735
+ <AnimatePresence custom={{ open }}>
736
+ {shouldHideParentSheet || !open ? null : overlayComponent}
737
+ </AnimatePresence>
738
+
739
+ {snapPointsMode !== 'percent' && (
740
+ <View
741
+ style={{
742
+ opacity: 0,
743
+ position: 'absolute',
744
+ top: 0,
745
+ left: 0,
746
+ right: 0,
747
+ bottom: 0,
748
+ pointerEvents: 'none',
749
+ }}
750
+ onLayout={handleMaxContentViewLayout}
751
+ />
752
+ )}
753
+
754
+ <AnimatedView
755
+ ref={ref}
756
+ onLayout={handleAnimationViewLayout}
757
+ // @ts-ignore for CSS driver this is necessary to attach the transition
758
+ // also motion driver at least though i suspect all drivers?
759
+ transition={isDragging || disableAnimation ? null : transition}
760
+ // @ts-ignore
761
+ disableClassName
762
+ style={[
763
+ {
764
+ position: 'absolute',
765
+ zIndex,
766
+ width: '100%',
767
+ height: forcedContentHeight,
768
+ minHeight: forcedContentHeight,
769
+ opacity: !shouldHideParentSheet ? opacity : 0,
770
+ ...((shouldHideParentSheet || !open) && {
771
+ pointerEvents: 'none',
772
+ }),
773
+ },
774
+ animatedStyle,
775
+ ]}
776
+ >
777
+ {/* wrap children with plain RN View for panResponder - hanzogui views no longer handle responder events on web */}
778
+ {gestureHandlerEnabled && panGesture ? (
779
+ <GestureDetectorWrapper gesture={panGesture} style={{ flex: 1 }}>
780
+ {props.children}
781
+ </GestureDetectorWrapper>
782
+ ) : (
783
+ <View
784
+ {...panResponder?.panHandlers}
785
+ style={{ flex: 1, width: '100%', height: '100%' }}
786
+ >
787
+ {props.children}
788
+ </View>
789
+ )}
790
+ </AnimatedView>
791
+ </GestureSheetProvider>
792
+ </SheetProvider>
793
+ </ParentSheetContext.Provider>
794
+ </LayoutMeasurementController>
795
+ )
796
+
797
+ if (process.env.TAMAGUI_TARGET === 'native' && needsPortalRepropagation()) {
798
+ // TODO alongside sheet scope="" need to pass scope here
799
+ const adaptContext = useAdaptContext()
800
+ contents = (
801
+ <ProvideAdaptContext {...adaptContext}>
802
+ {/* @ts-ignore */}
803
+ {contents}
804
+ </ProvideAdaptContext>
805
+ )
806
+ }
807
+
808
+ // start mounted so we get an accurate measurement the first time
809
+ const shouldMountChildren = unmountChildrenWhenHidden ? !!opacity : true
810
+
811
+ if (modal) {
812
+ const modalContents = (
813
+ <Portal stackZIndex={zIndex} {...portalProps}>
814
+ {shouldMountChildren && <ContainerComponent>{contents}</ContainerComponent>}
815
+ </Portal>
816
+ )
817
+
818
+ if (isWeb) {
819
+ return modalContents
820
+ }
821
+
822
+ // on native we don't support multiple modals yet... fix for now is to hide outer one
823
+ return (
824
+ <SheetInsideSheetContext.Provider value={onInnerSheet}>
825
+ {modalContents}
826
+ </SheetInsideSheetContext.Provider>
827
+ )
828
+ }
829
+
830
+ return contents
831
+ }
832
+ )
833
+
834
+ function getYPositions(
835
+ mode: SnapPointsMode,
836
+ point: string | number,
837
+ screenSize?: number,
838
+ frameSize?: number
839
+ ) {
840
+ if (!screenSize || !frameSize) {
841
+ return 0
842
+ }
843
+
844
+ if (mode === 'mixed') {
845
+ if (typeof point === 'number') {
846
+ return screenSize - Math.min(screenSize, Math.max(0, point))
847
+ }
848
+ if (point === 'fit') {
849
+ return screenSize - Math.min(screenSize, frameSize)
850
+ }
851
+ if (point.endsWith('%')) {
852
+ const pct = Math.min(100, Math.max(0, Number(point.slice(0, -1)))) / 100
853
+ if (Number.isNaN(pct)) {
854
+ console.warn('Invalid snapPoint percentage string')
855
+ return 0
856
+ }
857
+ return Math.round(screenSize - pct * screenSize)
858
+ }
859
+ console.warn('Invalid snapPoint unknown value')
860
+ return 0
861
+ }
862
+
863
+ if (mode === 'fit') {
864
+ if (point === 0) return screenSize
865
+ return screenSize - Math.min(screenSize, frameSize)
866
+ }
867
+
868
+ if (mode === 'constant' && typeof point === 'number') {
869
+ return screenSize - Math.min(screenSize, Math.max(0, point))
870
+ }
871
+
872
+ const pct = Math.min(100, Math.max(0, Number(point))) / 100
873
+ if (Number.isNaN(pct)) {
874
+ console.warn('Invalid snapPoint percentage')
875
+ return 0
876
+ }
877
+
878
+ return Math.round(screenSize - pct * screenSize)
879
+ }