@lodev09/react-native-true-sheet 4.0.0-beta.0 → 4.0.0-beta.10

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 (430) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +62 -30
  3. package/RNTrueSheet.podspec +10 -2
  4. package/android/build.gradle +24 -2
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +189 -47
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +7 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +401 -19
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +18 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +145 -21
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +14 -0
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
  12. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +28 -0
  13. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +84 -24
  14. package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +106 -0
  15. package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
  16. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +6 -4
  17. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekView.kt +72 -0
  18. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekViewManager.kt +33 -0
  19. package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +63 -0
  20. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +564 -226
  21. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +1399 -598
  22. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +161 -29
  23. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensEventObserver.kt +63 -0
  24. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +36 -0
  25. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +255 -0
  26. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +375 -0
  27. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +299 -0
  28. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +162 -0
  29. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetGrabberView.kt +180 -0
  30. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetKeyboardObserver.kt +207 -0
  31. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
  32. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +220 -0
  33. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetDragEvents.kt +71 -0
  34. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetFocusEvents.kt +65 -0
  35. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +127 -0
  36. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetStateEvents.kt +56 -0
  37. package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +84 -0
  38. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +93 -67
  39. package/android/src/main/java/com/lodev09/truesheet/utils/TouchEventDeduper.kt +31 -0
  40. package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +42 -0
  41. package/android/src/main/jni/CMakeLists.txt +63 -0
  42. package/android/src/main/jni/TrueSheetSpec.h +20 -0
  43. package/android/src/main/jni/TrueSheetStateUpdater.cpp +96 -0
  44. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +16 -0
  45. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +68 -0
  46. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +33 -0
  47. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +11 -0
  48. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +39 -0
  49. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +24 -0
  50. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +63 -0
  51. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +28 -0
  52. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +11 -0
  53. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +41 -0
  54. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +18 -0
  55. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +16 -0
  56. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +46 -0
  57. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
  58. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
  59. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +36 -0
  60. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +28 -0
  61. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +30 -0
  62. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +45 -0
  63. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +23 -0
  64. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +52 -0
  65. package/ios/TrueSheetContainerView.h +88 -6
  66. package/ios/TrueSheetContainerView.mm +278 -21
  67. package/ios/TrueSheetContentView.h +54 -1
  68. package/ios/TrueSheetContentView.mm +371 -47
  69. package/ios/TrueSheetFooterView.h +33 -2
  70. package/ios/TrueSheetFooterView.mm +187 -35
  71. package/ios/{events/OnWillDismissEvent.h → TrueSheetHeaderView.h} +10 -7
  72. package/ios/TrueSheetHeaderView.mm +64 -0
  73. package/ios/TrueSheetModule.h +2 -7
  74. package/ios/TrueSheetModule.mm +98 -20
  75. package/ios/TrueSheetOverlayView.h +32 -0
  76. package/ios/TrueSheetOverlayView.mm +161 -0
  77. package/ios/TrueSheetPeekView.h +32 -0
  78. package/ios/TrueSheetPeekView.mm +99 -0
  79. package/ios/TrueSheetView.h +7 -15
  80. package/ios/TrueSheetView.mm +775 -215
  81. package/ios/TrueSheetViewController.h +94 -16
  82. package/ios/TrueSheetViewController.mm +1316 -331
  83. package/ios/core/RNScreensEventObserver.h +46 -0
  84. package/ios/core/RNScreensEventObserver.mm +280 -0
  85. package/ios/core/TrueSheetBlurView.h +27 -0
  86. package/ios/core/TrueSheetBlurView.mm +82 -0
  87. package/ios/core/TrueSheetDetentCalculator.h +107 -0
  88. package/ios/core/TrueSheetDetentCalculator.mm +197 -0
  89. package/ios/core/TrueSheetGrabberView.h +72 -0
  90. package/ios/core/TrueSheetGrabberView.mm +188 -0
  91. package/ios/core/TrueSheetKeyboardObserver.h +39 -0
  92. package/ios/core/TrueSheetKeyboardObserver.mm +112 -0
  93. package/ios/core/TrueSheetOverlayContainerView.h +31 -0
  94. package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
  95. package/ios/events/TrueSheetDragEvents.h +39 -0
  96. package/ios/events/TrueSheetDragEvents.mm +62 -0
  97. package/ios/events/{OnPositionChangeEvent.h → TrueSheetFocusEvents.h} +8 -5
  98. package/ios/events/TrueSheetFocusEvents.mm +49 -0
  99. package/ios/events/TrueSheetLifecycleEvents.h +42 -0
  100. package/ios/events/TrueSheetLifecycleEvents.mm +79 -0
  101. package/ios/events/TrueSheetStateEvents.h +35 -0
  102. package/ios/events/TrueSheetStateEvents.mm +49 -0
  103. package/ios/tvos/TrueSheetStubs.mm +166 -0
  104. package/ios/{events/OnMountEvent.h → utils/BlurUtil.h} +5 -7
  105. package/ios/utils/BlurUtil.mm +69 -0
  106. package/ios/utils/GestureUtil.h +7 -0
  107. package/ios/utils/GestureUtil.mm +12 -0
  108. package/ios/utils/PlatformUtil.h +15 -0
  109. package/ios/utils/UIView+FirstResponder.h +15 -0
  110. package/ios/utils/UIView+FirstResponder.mm +26 -0
  111. package/ios/utils/UIView+ScrollEdgeInteraction.h +26 -0
  112. package/ios/utils/UIView+ScrollEdgeInteraction.mm +84 -0
  113. package/ios/utils/WindowUtil.mm +17 -1
  114. package/lib/module/TrueSheet.js +349 -74
  115. package/lib/module/TrueSheet.js.map +1 -1
  116. package/lib/module/TrueSheet.web.js +1270 -0
  117. package/lib/module/TrueSheet.web.js.map +1 -0
  118. package/lib/module/TrueSheetOverlay.js +30 -0
  119. package/lib/module/TrueSheetOverlay.js.map +1 -0
  120. package/lib/module/TrueSheetOverlay.web.js +35 -0
  121. package/lib/module/TrueSheetOverlay.web.js.map +1 -0
  122. package/lib/module/TrueSheetPeek.js +15 -0
  123. package/lib/module/TrueSheetPeek.js.map +1 -0
  124. package/lib/module/TrueSheetPeek.web.js +55 -0
  125. package/lib/module/TrueSheetPeek.web.js.map +1 -0
  126. package/lib/module/TrueSheetProvider.js +28 -0
  127. package/lib/module/TrueSheetProvider.js.map +1 -0
  128. package/lib/module/TrueSheetProvider.web.js +157 -0
  129. package/lib/module/TrueSheetProvider.web.js.map +1 -0
  130. package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  131. package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
  132. package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
  133. package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  134. package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
  135. package/lib/module/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
  136. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +110 -18
  137. package/lib/module/index.js +4 -3
  138. package/lib/module/index.js.map +1 -1
  139. package/lib/module/mocks/index.js +103 -0
  140. package/lib/module/mocks/index.js.map +1 -0
  141. package/lib/module/mocks/navigation.js +95 -0
  142. package/lib/module/mocks/navigation.js.map +1 -0
  143. package/lib/module/mocks/navigationExpoRouter.js +21 -0
  144. package/lib/module/mocks/navigationExpoRouter.js.map +1 -0
  145. package/lib/module/mocks/reanimated.js +91 -0
  146. package/lib/module/mocks/reanimated.js.map +1 -0
  147. package/lib/module/navigation/TrueSheetNavigatorContent.js +73 -0
  148. package/lib/module/navigation/TrueSheetNavigatorContent.js.map +1 -0
  149. package/lib/module/navigation/actions.js +50 -0
  150. package/lib/module/navigation/actions.js.map +1 -0
  151. package/lib/module/navigation/base-types.js +2 -0
  152. package/lib/module/navigation/base-types.js.map +1 -0
  153. package/lib/module/navigation/createTrueSheetRouter.js +157 -0
  154. package/lib/module/navigation/createTrueSheetRouter.js.map +1 -0
  155. package/lib/module/navigation/expo-router/base-types.js +2 -0
  156. package/lib/module/navigation/expo-router/base-types.js.map +1 -0
  157. package/lib/module/navigation/expo-router/index.js +50 -0
  158. package/lib/module/navigation/expo-router/index.js.map +1 -0
  159. package/lib/module/navigation/expo-router/types.js +4 -0
  160. package/lib/module/navigation/expo-router/types.js.map +1 -0
  161. package/lib/module/navigation/index.js +47 -0
  162. package/lib/module/navigation/index.js.map +1 -0
  163. package/lib/module/navigation/navigator.js +10 -0
  164. package/lib/module/navigation/navigator.js.map +1 -0
  165. package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js +56 -0
  166. package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js.map +1 -0
  167. package/lib/module/navigation/screen/TrueSheetScreen.js +49 -0
  168. package/lib/module/navigation/screen/TrueSheetScreen.js.map +1 -0
  169. package/lib/module/navigation/screen/index.js +5 -0
  170. package/lib/module/navigation/screen/index.js.map +1 -0
  171. package/lib/module/navigation/screen/types.js +4 -0
  172. package/lib/module/navigation/screen/types.js.map +1 -0
  173. package/lib/module/navigation/screen/useSheetScreenState.js +69 -0
  174. package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -0
  175. package/lib/module/navigation/types.js +4 -0
  176. package/lib/module/navigation/types.js.map +1 -0
  177. package/lib/module/navigation/useTrueSheetNavigation.js +24 -0
  178. package/lib/module/navigation/useTrueSheetNavigation.js.map +1 -0
  179. package/lib/module/reanimated/ReanimatedTrueSheet.js +15 -9
  180. package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -1
  181. package/lib/module/reanimated/ReanimatedTrueSheet.web.js +81 -0
  182. package/lib/module/reanimated/ReanimatedTrueSheet.web.js.map +1 -0
  183. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +4 -2
  184. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -1
  185. package/lib/module/reanimated/index.js +2 -2
  186. package/lib/module/reanimated/index.js.map +1 -1
  187. package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js +20 -0
  188. package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js.map +1 -0
  189. package/lib/module/specs/NativeTrueSheetModule.js.map +1 -1
  190. package/lib/module/web/constants.js +16 -0
  191. package/lib/module/web/constants.js.map +1 -0
  192. package/lib/module/web/dom.js +10 -0
  193. package/lib/module/web/dom.js.map +1 -0
  194. package/lib/module/web/vaul/README.md +9 -0
  195. package/lib/module/web/vaul/browser.js +30 -0
  196. package/lib/module/web/vaul/browser.js.map +1 -0
  197. package/lib/module/web/vaul/constants.js +19 -0
  198. package/lib/module/web/vaul/constants.js.map +1 -0
  199. package/lib/module/web/vaul/context.js +59 -0
  200. package/lib/module/web/vaul/context.js.map +1 -0
  201. package/lib/module/web/vaul/helpers.js +99 -0
  202. package/lib/module/web/vaul/helpers.js.map +1 -0
  203. package/lib/module/web/vaul/index.js +1342 -0
  204. package/lib/module/web/vaul/index.js.map +1 -0
  205. package/lib/module/web/vaul/style.css +287 -0
  206. package/lib/module/web/vaul/style.css.d.js +2 -0
  207. package/lib/module/web/vaul/style.css.d.js.map +1 -0
  208. package/lib/module/web/vaul/types.js +2 -0
  209. package/lib/module/web/vaul/types.js.map +1 -0
  210. package/lib/module/web/vaul/use-composed-refs.js +34 -0
  211. package/lib/module/web/vaul/use-composed-refs.js.map +1 -0
  212. package/lib/module/web/vaul/use-controllable-state.js +54 -0
  213. package/lib/module/web/vaul/use-controllable-state.js.map +1 -0
  214. package/lib/module/web/vaul/use-position-fixed.js +123 -0
  215. package/lib/module/web/vaul/use-position-fixed.js.map +1 -0
  216. package/lib/module/web/vaul/use-prevent-scroll.js +258 -0
  217. package/lib/module/web/vaul/use-prevent-scroll.js.map +1 -0
  218. package/lib/module/web/vaul/use-scale-background.js +57 -0
  219. package/lib/module/web/vaul/use-scale-background.js.map +1 -0
  220. package/lib/module/web/vaul/use-snap-points.js +305 -0
  221. package/lib/module/web/vaul/use-snap-points.js.map +1 -0
  222. package/lib/typescript/src/TrueSheet.d.ts +57 -14
  223. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  224. package/lib/typescript/src/TrueSheet.types.d.ts +535 -55
  225. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  226. package/lib/typescript/src/TrueSheet.web.d.ts +5 -0
  227. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -0
  228. package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
  229. package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
  230. package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
  231. package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
  232. package/lib/typescript/src/TrueSheetPeek.d.ts +9 -0
  233. package/lib/typescript/src/TrueSheetPeek.d.ts.map +1 -0
  234. package/lib/typescript/src/TrueSheetPeek.web.d.ts +28 -0
  235. package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -0
  236. package/lib/typescript/src/TrueSheetProvider.d.ts +18 -0
  237. package/lib/typescript/src/TrueSheetProvider.d.ts.map +1 -0
  238. package/lib/typescript/src/TrueSheetProvider.web.d.ts +27 -0
  239. package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -0
  240. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -1
  241. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -1
  242. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +2 -0
  243. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -1
  244. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
  245. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
  246. package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
  247. package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
  248. package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts +6 -0
  249. package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts.map +1 -0
  250. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +71 -16
  251. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  252. package/lib/typescript/src/index.d.ts +3 -2
  253. package/lib/typescript/src/index.d.ts.map +1 -1
  254. package/lib/typescript/src/mocks/index.d.ts +47 -0
  255. package/lib/typescript/src/mocks/index.d.ts.map +1 -0
  256. package/lib/typescript/src/mocks/navigation.d.ts +70 -0
  257. package/lib/typescript/src/mocks/navigation.d.ts.map +1 -0
  258. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +22 -0
  259. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -0
  260. package/lib/typescript/src/mocks/reanimated.d.ts +48 -0
  261. package/lib/typescript/src/mocks/reanimated.d.ts.map +1 -0
  262. package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts +5 -0
  263. package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts.map +1 -0
  264. package/lib/typescript/src/navigation/actions.d.ts +71 -0
  265. package/lib/typescript/src/navigation/actions.d.ts.map +1 -0
  266. package/lib/typescript/src/navigation/base-types.d.ts +9 -0
  267. package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
  268. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +3 -0
  269. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -0
  270. package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
  271. package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
  272. package/lib/typescript/src/navigation/expo-router/index.d.ts +37 -0
  273. package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -0
  274. package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
  275. package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
  276. package/lib/typescript/src/navigation/index.d.ts +45 -0
  277. package/lib/typescript/src/navigation/index.d.ts.map +1 -0
  278. package/lib/typescript/src/navigation/navigator.d.ts +7 -0
  279. package/lib/typescript/src/navigation/navigator.d.ts.map +1 -0
  280. package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts +3 -0
  281. package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts.map +1 -0
  282. package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts +3 -0
  283. package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts.map +1 -0
  284. package/lib/typescript/src/navigation/screen/index.d.ts +4 -0
  285. package/lib/typescript/src/navigation/screen/index.d.ts.map +1 -0
  286. package/lib/typescript/src/navigation/screen/types.d.ts +14 -0
  287. package/lib/typescript/src/navigation/screen/types.d.ts.map +1 -0
  288. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +34 -0
  289. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -0
  290. package/lib/typescript/src/navigation/types.d.ts +213 -0
  291. package/lib/typescript/src/navigation/types.d.ts.map +1 -0
  292. package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts +23 -0
  293. package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts.map +1 -0
  294. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -1
  295. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts +41 -0
  296. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts.map +1 -0
  297. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +8 -2
  298. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -1
  299. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts +15 -0
  300. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts.map +1 -0
  301. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +25 -3
  302. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -1
  303. package/lib/typescript/src/web/constants.d.ts +14 -0
  304. package/lib/typescript/src/web/constants.d.ts.map +1 -0
  305. package/lib/typescript/src/web/dom.d.ts +7 -0
  306. package/lib/typescript/src/web/dom.d.ts.map +1 -0
  307. package/lib/typescript/src/web/vaul/browser.d.ts +8 -0
  308. package/lib/typescript/src/web/vaul/browser.d.ts.map +1 -0
  309. package/lib/typescript/src/web/vaul/constants.d.ts +14 -0
  310. package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -0
  311. package/lib/typescript/src/web/vaul/context.d.ts +54 -0
  312. package/lib/typescript/src/web/vaul/context.d.ts.map +1 -0
  313. package/lib/typescript/src/web/vaul/helpers.d.ts +17 -0
  314. package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -0
  315. package/lib/typescript/src/web/vaul/index.d.ts +234 -0
  316. package/lib/typescript/src/web/vaul/index.d.ts.map +1 -0
  317. package/lib/typescript/src/web/vaul/types.d.ts +7 -0
  318. package/lib/typescript/src/web/vaul/types.d.ts.map +1 -0
  319. package/lib/typescript/src/web/vaul/use-composed-refs.d.ts +14 -0
  320. package/lib/typescript/src/web/vaul/use-composed-refs.d.ts.map +1 -0
  321. package/lib/typescript/src/web/vaul/use-controllable-state.d.ts +9 -0
  322. package/lib/typescript/src/web/vaul/use-controllable-state.d.ts.map +1 -0
  323. package/lib/typescript/src/web/vaul/use-position-fixed.d.ts +19 -0
  324. package/lib/typescript/src/web/vaul/use-position-fixed.d.ts.map +1 -0
  325. package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts +18 -0
  326. package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts.map +1 -0
  327. package/lib/typescript/src/web/vaul/use-scale-background.d.ts +2 -0
  328. package/lib/typescript/src/web/vaul/use-scale-background.d.ts.map +1 -0
  329. package/lib/typescript/src/web/vaul/use-snap-points.d.ts +38 -0
  330. package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -0
  331. package/package.json +104 -37
  332. package/react-native.config.js +10 -2
  333. package/src/TrueSheet.tsx +424 -70
  334. package/src/TrueSheet.types.ts +602 -72
  335. package/src/TrueSheet.web.tsx +1437 -0
  336. package/src/TrueSheetOverlay.tsx +24 -0
  337. package/src/TrueSheetOverlay.web.tsx +33 -0
  338. package/src/TrueSheetPeek.tsx +11 -0
  339. package/src/TrueSheetPeek.web.tsx +64 -0
  340. package/src/TrueSheetProvider.tsx +33 -0
  341. package/src/TrueSheetProvider.web.tsx +220 -0
  342. package/src/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  343. package/src/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
  344. package/src/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
  345. package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  346. package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
  347. package/src/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
  348. package/src/fabric/TrueSheetViewNativeComponent.ts +110 -18
  349. package/src/index.ts +3 -2
  350. package/src/mocks/index.ts +96 -0
  351. package/src/mocks/navigation.ts +79 -0
  352. package/src/mocks/navigationExpoRouter.ts +41 -0
  353. package/src/mocks/reanimated.ts +100 -0
  354. package/src/navigation/TrueSheetNavigatorContent.tsx +106 -0
  355. package/src/navigation/actions.ts +78 -0
  356. package/src/navigation/base-types.ts +20 -0
  357. package/src/navigation/createTrueSheetRouter.ts +194 -0
  358. package/src/navigation/expo-router/base-types.ts +18 -0
  359. package/src/navigation/expo-router/index.ts +90 -0
  360. package/src/navigation/expo-router/types.ts +116 -0
  361. package/src/navigation/index.ts +80 -0
  362. package/src/navigation/navigator.ts +18 -0
  363. package/src/navigation/screen/ReanimatedTrueSheetScreen.tsx +61 -0
  364. package/src/navigation/screen/TrueSheetScreen.tsx +54 -0
  365. package/src/navigation/screen/index.ts +3 -0
  366. package/src/navigation/screen/types.ts +19 -0
  367. package/src/navigation/screen/useSheetScreenState.ts +102 -0
  368. package/src/navigation/types.ts +302 -0
  369. package/src/navigation/useTrueSheetNavigation.ts +26 -0
  370. package/src/reanimated/ReanimatedTrueSheet.tsx +12 -7
  371. package/src/reanimated/ReanimatedTrueSheet.web.tsx +75 -0
  372. package/src/reanimated/ReanimatedTrueSheetProvider.tsx +12 -8
  373. package/src/reanimated/useReanimatedPositionChangeHandler.web.ts +31 -0
  374. package/src/specs/NativeTrueSheetModule.ts +28 -3
  375. package/src/web/constants.ts +13 -0
  376. package/src/web/dom.ts +9 -0
  377. package/src/web/vaul/README.md +9 -0
  378. package/src/web/vaul/browser.ts +38 -0
  379. package/src/web/vaul/constants.ts +24 -0
  380. package/src/web/vaul/context.ts +102 -0
  381. package/src/web/vaul/helpers.ts +131 -0
  382. package/src/web/vaul/index.tsx +1785 -0
  383. package/src/web/vaul/style.css +287 -0
  384. package/src/web/vaul/style.css.d.ts +1 -0
  385. package/src/web/vaul/types.ts +7 -0
  386. package/src/web/vaul/use-composed-refs.ts +35 -0
  387. package/src/web/vaul/use-controllable-state.ts +66 -0
  388. package/src/web/vaul/use-position-fixed.ts +147 -0
  389. package/src/web/vaul/use-prevent-scroll.ts +309 -0
  390. package/src/web/vaul/use-scale-background.ts +64 -0
  391. package/src/web/vaul/use-snap-points.ts +455 -0
  392. package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +0 -26
  393. package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +0 -20
  394. package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +0 -26
  395. package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +0 -26
  396. package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +0 -26
  397. package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +0 -26
  398. package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +0 -20
  399. package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +0 -32
  400. package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +0 -27
  401. package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +0 -20
  402. package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +0 -26
  403. package/android/src/main/res/values/styles.xml +0 -8
  404. package/ios/events/OnDetentChangeEvent.h +0 -28
  405. package/ios/events/OnDetentChangeEvent.mm +0 -30
  406. package/ios/events/OnDidDismissEvent.h +0 -26
  407. package/ios/events/OnDidDismissEvent.mm +0 -25
  408. package/ios/events/OnDidPresentEvent.h +0 -28
  409. package/ios/events/OnDidPresentEvent.mm +0 -30
  410. package/ios/events/OnDragBeginEvent.h +0 -28
  411. package/ios/events/OnDragBeginEvent.mm +0 -30
  412. package/ios/events/OnDragChangeEvent.h +0 -28
  413. package/ios/events/OnDragChangeEvent.mm +0 -30
  414. package/ios/events/OnDragEndEvent.h +0 -28
  415. package/ios/events/OnDragEndEvent.mm +0 -30
  416. package/ios/events/OnMountEvent.mm +0 -25
  417. package/ios/events/OnPositionChangeEvent.mm +0 -32
  418. package/ios/events/OnSizeChangeEvent.h +0 -28
  419. package/ios/events/OnSizeChangeEvent.mm +0 -30
  420. package/ios/events/OnWillDismissEvent.mm +0 -25
  421. package/ios/events/OnWillPresentEvent.h +0 -28
  422. package/ios/events/OnWillPresentEvent.mm +0 -30
  423. package/ios/utils/LayoutUtil.h +0 -44
  424. package/ios/utils/LayoutUtil.mm +0 -50
  425. package/lib/module/TrueSheetGrabber.js +0 -51
  426. package/lib/module/TrueSheetGrabber.js.map +0 -1
  427. package/lib/typescript/src/TrueSheetGrabber.d.ts +0 -39
  428. package/lib/typescript/src/TrueSheetGrabber.d.ts.map +0 -1
  429. package/src/TrueSheetGrabber.tsx +0 -82
  430. package/src/__mocks__/index.js +0 -67
@@ -1,10 +1,13 @@
1
1
  package com.lodev09.truesheet
2
2
 
3
- import android.graphics.Color
4
3
  import android.view.WindowManager
5
4
  import com.facebook.react.bridge.ReadableArray
5
+ import com.facebook.react.bridge.ReadableMap
6
6
  import com.facebook.react.module.annotations.ReactModule
7
7
  import com.facebook.react.uimanager.PixelUtil.dpToPx
8
+ import com.facebook.react.uimanager.PointerEvents
9
+ import com.facebook.react.uimanager.ReactStylesDiffMap
10
+ import com.facebook.react.uimanager.StateWrapper
8
11
  import com.facebook.react.uimanager.ThemedReactContext
9
12
  import com.facebook.react.uimanager.UIManagerHelper
10
13
  import com.facebook.react.uimanager.ViewGroupManager
@@ -12,6 +15,8 @@ import com.facebook.react.uimanager.ViewManagerDelegate
12
15
  import com.facebook.react.uimanager.annotations.ReactProp
13
16
  import com.facebook.react.viewmanagers.TrueSheetViewManagerDelegate
14
17
  import com.facebook.react.viewmanagers.TrueSheetViewManagerInterface
18
+ import com.lodev09.truesheet.core.AccessibilityOptions
19
+ import com.lodev09.truesheet.core.GrabberOptions
15
20
  import com.lodev09.truesheet.events.*
16
21
 
17
22
  /**
@@ -36,7 +41,7 @@ class TrueSheetViewManager :
36
41
 
37
42
  override fun onAfterUpdateTransaction(view: TrueSheetView) {
38
43
  super.onAfterUpdateTransaction(view)
39
- view.showOrUpdate()
44
+ view.finalizeUpdates()
40
45
  }
41
46
 
42
47
  override fun addEventEmitters(reactContext: ThemedReactContext, view: TrueSheetView) {
@@ -44,8 +49,27 @@ class TrueSheetViewManager :
44
49
  view.eventDispatcher = dispatcher
45
50
  }
46
51
 
52
+ override fun updateState(view: TrueSheetView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
53
+ view.stateWrapper = stateWrapper
54
+ return null
55
+ }
56
+
47
57
  override fun getDelegate(): ViewManagerDelegate<TrueSheetView> = delegate
48
58
 
59
+ // The codegen delegate drops props outside the spec (pointerEvents comes from the
60
+ // host's style), so apply it here after the delegate pass.
61
+ override fun updateProperties(viewToUpdate: TrueSheetView, props: ReactStylesDiffMap) {
62
+ super.updateProperties(viewToUpdate, props)
63
+ if (props.hasKey("pointerEvents")) {
64
+ setPointerEvents(viewToUpdate, props.getString("pointerEvents"))
65
+ }
66
+ }
67
+
68
+ @ReactProp(name = "pointerEvents")
69
+ fun setPointerEvents(view: TrueSheetView, pointerEventsStr: String?) {
70
+ view.pointerEvents = PointerEvents.parsePointerEvents(pointerEventsStr)
71
+ }
72
+
49
73
  /**
50
74
  * Export custom direct event types for Fabric
51
75
  * Uses Kotlin native collections with decoupled event classes
@@ -57,12 +81,17 @@ class TrueSheetViewManager :
57
81
  DidPresentEvent.EVENT_NAME to hashMapOf("registrationName" to DidPresentEvent.REGISTRATION_NAME),
58
82
  WillDismissEvent.EVENT_NAME to hashMapOf("registrationName" to WillDismissEvent.REGISTRATION_NAME),
59
83
  DidDismissEvent.EVENT_NAME to hashMapOf("registrationName" to DidDismissEvent.REGISTRATION_NAME),
84
+ DismissAttemptEvent.EVENT_NAME to hashMapOf("registrationName" to DismissAttemptEvent.REGISTRATION_NAME),
60
85
  DetentChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DetentChangeEvent.REGISTRATION_NAME),
61
86
  DragBeginEvent.EVENT_NAME to hashMapOf("registrationName" to DragBeginEvent.REGISTRATION_NAME),
62
87
  DragChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DragChangeEvent.REGISTRATION_NAME),
63
88
  DragEndEvent.EVENT_NAME to hashMapOf("registrationName" to DragEndEvent.REGISTRATION_NAME),
64
89
  PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME),
65
- SizeChangeEvent.EVENT_NAME to hashMapOf("registrationName" to SizeChangeEvent.REGISTRATION_NAME)
90
+ WillFocusEvent.EVENT_NAME to hashMapOf("registrationName" to WillFocusEvent.REGISTRATION_NAME),
91
+ FocusEvent.EVENT_NAME to hashMapOf("registrationName" to FocusEvent.REGISTRATION_NAME),
92
+ WillBlurEvent.EVENT_NAME to hashMapOf("registrationName" to WillBlurEvent.REGISTRATION_NAME),
93
+ BlurEvent.EVENT_NAME to hashMapOf("registrationName" to BlurEvent.REGISTRATION_NAME),
94
+ VisibilityChangeEvent.EVENT_NAME to hashMapOf("registrationName" to VisibilityChangeEvent.REGISTRATION_NAME)
66
95
  )
67
96
 
68
97
  // ==================== Props ====================
@@ -85,16 +114,14 @@ class TrueSheetViewManager :
85
114
  view.setDetents(detents)
86
115
  }
87
116
 
88
- @ReactProp(name = "background", defaultInt = Color.WHITE)
89
- override fun setBackground(view: TrueSheetView, color: Int) {
117
+ @ReactProp(name = "backgroundColor", customType = "Color")
118
+ override fun setBackgroundColor(view: TrueSheetView, color: Int?) {
90
119
  view.setSheetBackgroundColor(color)
91
120
  }
92
121
 
93
122
  @ReactProp(name = "cornerRadius", defaultDouble = -1.0)
94
123
  override fun setCornerRadius(view: TrueSheetView, radius: Double) {
95
- if (radius >= 0) {
96
- view.setCornerRadius(radius.dpToPx())
97
- }
124
+ view.setCornerRadius(radius.dpToPx())
98
125
  }
99
126
 
100
127
  @ReactProp(name = "grabber", defaultBoolean = true)
@@ -102,24 +129,73 @@ class TrueSheetViewManager :
102
129
  view.setGrabber(grabber)
103
130
  }
104
131
 
132
+ @ReactProp(name = "grabberOptions")
133
+ override fun setGrabberOptions(view: TrueSheetView, options: ReadableMap?) {
134
+ if (options == null) {
135
+ view.setGrabberOptions(null)
136
+ return
137
+ }
138
+
139
+ val grabberOptions = GrabberOptions(
140
+ width = if (options.hasKey("width")) options.getDouble("width").toFloat() else null,
141
+ height = if (options.hasKey("height")) options.getDouble("height").toFloat() else null,
142
+ topMargin = if (options.hasKey("topMargin")) options.getDouble("topMargin").toFloat() else null,
143
+ cornerRadius = if (options.hasKey("cornerRadius") &&
144
+ options.getDouble("cornerRadius") >= 0
145
+ ) {
146
+ options.getDouble("cornerRadius").toFloat()
147
+ } else {
148
+ null
149
+ },
150
+ color = if (options.hasKey("color") && !options.isNull("color")) options.getInt("color") else null,
151
+ adaptive = if (options.hasKey("adaptive")) options.getBoolean("adaptive") else true
152
+ )
153
+ view.setGrabberOptions(grabberOptions)
154
+ }
155
+
156
+ @ReactProp(name = "accessibilityOptions")
157
+ override fun setAccessibilityOptions(view: TrueSheetView, options: ReadableMap?) {
158
+ if (options == null) {
159
+ view.setAccessibilityOptions(null)
160
+ return
161
+ }
162
+
163
+ val accessibilityOptions = AccessibilityOptions(
164
+ grabberLabel = if (options.hasKey("grabberLabel")) options.getString("grabberLabel") else null,
165
+ expandedValue = if (options.hasKey("expandedValue")) options.getString("expandedValue") else null,
166
+ collapsedValue = if (options.hasKey("collapsedValue")) options.getString("collapsedValue") else null,
167
+ detentValue = if (options.hasKey("detentValue")) options.getString("detentValue") else null,
168
+ expandActionLabel = if (options.hasKey("expandActionLabel")) options.getString("expandActionLabel") else null,
169
+ collapseActionLabel = if (options.hasKey("collapseActionLabel")) options.getString("collapseActionLabel") else null,
170
+ paneTitle = if (options.hasKey("paneTitle")) options.getString("paneTitle") else null
171
+ )
172
+ view.setAccessibilityOptions(accessibilityOptions)
173
+ }
174
+
105
175
  @ReactProp(name = "dismissible", defaultBoolean = true)
106
176
  override fun setDismissible(view: TrueSheetView, dismissible: Boolean) {
107
177
  view.setDismissible(dismissible)
108
178
  }
109
179
 
180
+ @ReactProp(name = "draggable", defaultBoolean = true)
181
+ override fun setDraggable(view: TrueSheetView, draggable: Boolean) {
182
+ view.setDraggable(draggable)
183
+ }
184
+
110
185
  @ReactProp(name = "dimmed", defaultBoolean = true)
111
186
  override fun setDimmed(view: TrueSheetView, dimmed: Boolean) {
112
187
  view.setDimmed(dimmed)
113
188
  }
114
189
 
115
- @ReactProp(name = "dimmedIndex", defaultInt = 0)
116
- override fun setDimmedIndex(view: TrueSheetView, index: Int) {
117
- view.setDimmedIndex(index)
190
+ @ReactProp(name = "dimmedDetentIndex", defaultInt = 0)
191
+ override fun setDimmedDetentIndex(view: TrueSheetView, index: Int) {
192
+ view.setDimmedDetentIndex(index)
118
193
  }
119
194
 
120
195
  @ReactProp(name = "initialDetentIndex", defaultInt = -1)
121
196
  override fun setInitialDetentIndex(view: TrueSheetView, index: Int) {
122
197
  view.initialDetentIndex = index
198
+ view.presentInitialIfNeeded()
123
199
  }
124
200
 
125
201
  @ReactProp(name = "initialDetentAnimated", defaultBoolean = true)
@@ -127,31 +203,87 @@ class TrueSheetViewManager :
127
203
  view.initialDetentAnimated = animate
128
204
  }
129
205
 
130
- @ReactProp(name = "maxHeight", defaultDouble = 0.0)
131
- override fun setMaxHeight(view: TrueSheetView, height: Double) {
132
- if (height > 0) {
133
- view.setMaxHeight(height.dpToPx().toInt())
134
- }
206
+ @ReactProp(name = "maxContentHeight", defaultDouble = 0.0)
207
+ override fun setMaxContentHeight(view: TrueSheetView, height: Double) {
208
+ view.setMaxContentHeight(if (height > 0) height.dpToPx().toInt() else null)
135
209
  }
136
210
 
137
- @ReactProp(name = "keyboardMode")
138
- override fun setKeyboardMode(view: TrueSheetView, mode: String?) {
139
- val softInputMode = when (mode) {
140
- "pan" -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
141
- else -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
142
- }
143
- view.setSoftInputMode(softInputMode)
211
+ @ReactProp(name = "maxContentWidth", defaultDouble = 0.0)
212
+ override fun setMaxContentWidth(view: TrueSheetView, width: Double) {
213
+ view.setMaxContentWidth(if (width > 0) width.dpToPx().toInt() else null)
144
214
  }
145
215
 
146
- @ReactProp(name = "blurTint")
147
- override fun setBlurTint(view: TrueSheetView, tint: String?) {
216
+ @ReactProp(name = "anchor")
217
+ override fun setAnchor(view: TrueSheetView, anchor: String?) {
218
+ view.setAnchor(anchor)
219
+ }
220
+
221
+ @ReactProp(name = "anchorOffset", defaultDouble = 0.0)
222
+ override fun setAnchorOffset(view: TrueSheetView, offset: Double) {
223
+ view.setAnchorOffset(if (offset > 0) offset.dpToPx().toInt() else 0)
224
+ }
225
+
226
+ @ReactProp(name = "backgroundBlur")
227
+ override fun setBackgroundBlur(view: TrueSheetView, tint: String?) {
228
+ // iOS-specific prop - no-op on Android
229
+ }
230
+
231
+ @ReactProp(name = "blurOptions")
232
+ override fun setBlurOptions(view: TrueSheetView, options: ReadableMap?) {
148
233
  // iOS-specific prop - no-op on Android
149
- view.setBlurTint(tint)
150
234
  }
151
235
 
152
- @ReactProp(name = "edgeToEdgeFullScreen", defaultBoolean = false)
153
- override fun setEdgeToEdgeFullScreen(view: TrueSheetView, edgeToEdgeFullScreen: Boolean) {
154
- view.setEdgeToEdgeFullScreen(edgeToEdgeFullScreen)
236
+ @ReactProp(name = "insetAdjustment")
237
+ override fun setInsetAdjustment(view: TrueSheetView, insetAdjustment: String?) {
238
+ view.setInsetAdjustment(insetAdjustment ?: "automatic")
239
+ }
240
+
241
+ @ReactProp(name = "presentation")
242
+ override fun setPresentation(view: TrueSheetView, value: String?) {
243
+ // iOS/web-specific prop - no-op on Android
244
+ }
245
+
246
+ @ReactProp(name = "elevation", defaultDouble = -1.0)
247
+ override fun setElevation(view: TrueSheetView, elevation: Double) {
248
+ view.setSheetElevation(elevation.toFloat())
249
+ }
250
+
251
+ @ReactProp(name = "scrollableHandle", defaultInt = -1)
252
+ override fun setScrollableHandle(view: TrueSheetView, handle: Int) {
253
+ view.setScrollableHandle(handle)
254
+ }
255
+
256
+ @ReactProp(name = "scrollableOptions")
257
+ override fun setScrollableOptions(view: TrueSheetView, options: ReadableMap?) {
258
+ if (options == null) {
259
+ view.setScrollableOptions(null)
260
+ return
261
+ }
262
+
263
+ val scrollableOptions = ScrollableOptions(
264
+ keyboardScrollOffset = if (options.hasKey("keyboardScrollOffset")) options.getDouble("keyboardScrollOffset").toFloat() else 0f,
265
+ keyboardOffset = if (options.hasKey("keyboardOffset")) options.getDouble("keyboardOffset").toFloat() else 0f,
266
+ scrollingExpandsSheet = if (options.hasKey("scrollingExpandsSheet")) options.getBoolean("scrollingExpandsSheet") else true,
267
+ contentInsetAdjustment = !options.hasKey("contentInsetAdjustmentBehavior") ||
268
+ options.getBoolean("contentInsetAdjustmentBehavior")
269
+ )
270
+ view.setScrollableOptions(scrollableOptions)
271
+ }
272
+
273
+ @ReactProp(name = "headerOptions")
274
+ override fun setHeaderOptions(view: TrueSheetView, options: ReadableMap?) {
275
+ val position = if (options != null && options.hasKey("position")) options.getString("position") else null
276
+ view.setAbsoluteHeader(position == "absolute")
277
+ }
278
+
279
+ @ReactProp(name = "footerOptions")
280
+ override fun setFooterOptions(view: TrueSheetView, options: ReadableMap?) {
281
+ val position = if (options != null && options.hasKey("footerPosition")) options.getString("footerPosition") else null
282
+ view.setAbsoluteFooter(position == "absolute")
283
+
284
+ val keyboardOffset =
285
+ if (options != null && options.hasKey("keyboardOffset")) options.getDouble("keyboardOffset").toFloat() else 0f
286
+ view.setFooterKeyboardOffset(keyboardOffset)
155
287
  }
156
288
 
157
289
  companion object {
@@ -0,0 +1,63 @@
1
+ package com.lodev09.truesheet.core
2
+
3
+ import android.view.View
4
+ import com.facebook.react.uimanager.events.Event
5
+ import com.facebook.react.uimanager.events.EventDispatcher
6
+ import com.facebook.react.uimanager.events.EventDispatcherListener
7
+
8
+ private const val RN_SCREENS_VIEW_CLASS = "com.swmansion.rnscreens.Screen"
9
+
10
+ interface RNScreensEventObserverDelegate {
11
+ fun presenterScreenWillDisappear()
12
+ fun presenterScreenWillAppear()
13
+ }
14
+
15
+ /**
16
+ * Observes react-native-screens lifecycle events via EventDispatcherListener.
17
+ * Detects when the presenting screen unmounts while sheet is presented.
18
+ */
19
+ class RNScreensEventObserver : EventDispatcherListener {
20
+ var delegate: RNScreensEventObserverDelegate? = null
21
+
22
+ private var eventDispatcher: EventDispatcher? = null
23
+ var presenterScreenTag: Int = 0
24
+
25
+ fun startObserving(dispatcher: EventDispatcher?) {
26
+ if (eventDispatcher != null || dispatcher == null) return
27
+
28
+ eventDispatcher = dispatcher
29
+ dispatcher.addListener(this)
30
+ }
31
+
32
+ fun stopObserving() {
33
+ eventDispatcher?.removeListener(this)
34
+ eventDispatcher = null
35
+ }
36
+
37
+ fun capturePresenterScreenFromView(view: View?) {
38
+ presenterScreenTag = 0
39
+
40
+ var current: View? = view
41
+ while (current != null) {
42
+ if (isScreenView(current)) {
43
+ presenterScreenTag = current.id
44
+ break
45
+ }
46
+ current = (current.parent as? View)
47
+ }
48
+ }
49
+
50
+ override fun onEventDispatch(event: Event<*>) {
51
+ // Only process events for the presenter screen
52
+ if (presenterScreenTag == 0 || event.viewTag != presenterScreenTag) return
53
+
54
+ when (event.eventName) {
55
+ "topWillDisappear" -> delegate?.presenterScreenWillDisappear()
56
+ "topWillAppear" -> delegate?.presenterScreenWillAppear()
57
+ }
58
+ }
59
+
60
+ companion object {
61
+ private fun isScreenView(view: View): Boolean = view.javaClass.name == RN_SCREENS_VIEW_CLASS
62
+ }
63
+ }
@@ -0,0 +1,36 @@
1
+ package com.lodev09.truesheet.core
2
+
3
+ import android.view.View
4
+ import androidx.coordinatorlayout.widget.CoordinatorLayout
5
+ import com.google.android.material.bottomsheet.BottomSheetBehavior
6
+
7
+ class TrueSheetBottomSheetBehavior<V : View> : BottomSheetBehavior<V>() {
8
+ var scrollingExpandsSheet: Boolean = true
9
+
10
+ override fun onNestedPreScroll(
11
+ coordinatorLayout: CoordinatorLayout,
12
+ child: V,
13
+ target: View,
14
+ dx: Int,
15
+ dy: Int,
16
+ consumed: IntArray,
17
+ type: Int
18
+ ) {
19
+ // dy > 0 = user swiping up = sheet expanding
20
+ // Block expansion from scroll, but allow if sheet is already being dragged
21
+ if (!scrollingExpandsSheet && dy > 0 && state != STATE_DRAGGING) return
22
+ super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
23
+ }
24
+
25
+ override fun onNestedPreFling(
26
+ coordinatorLayout: CoordinatorLayout,
27
+ child: V,
28
+ target: View,
29
+ velocityX: Float,
30
+ velocityY: Float
31
+ ): Boolean {
32
+ // Don't consume flings — let the ScrollView decelerate naturally
33
+ if (!scrollingExpandsSheet) return false
34
+ return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY)
35
+ }
36
+ }
@@ -0,0 +1,255 @@
1
+ package com.lodev09.truesheet.core
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.res.Configuration
5
+ import android.graphics.Color
6
+ import android.graphics.Outline
7
+ import android.graphics.Rect
8
+ import android.graphics.drawable.ShapeDrawable
9
+ import android.graphics.drawable.shapes.RoundRectShape
10
+ import android.view.GestureDetector
11
+ import android.view.Gravity
12
+ import android.view.MotionEvent
13
+ import android.view.View
14
+ import android.view.ViewOutlineProvider
15
+ import android.widget.FrameLayout
16
+ import androidx.coordinatorlayout.widget.CoordinatorLayout
17
+ import androidx.core.view.ViewCompat
18
+ import com.facebook.react.uimanager.PixelUtil.dpToPx
19
+ import com.facebook.react.uimanager.ThemedReactContext
20
+ import com.google.android.material.bottomsheet.BottomSheetBehavior
21
+ import com.lodev09.truesheet.TrueSheetAnchor
22
+ import com.lodev09.truesheet.utils.ScreenUtils
23
+
24
+ interface TrueSheetBottomSheetViewDelegate {
25
+ val isTopmostSheet: Boolean
26
+ val sheetCornerRadius: Float
27
+ val sheetElevation: Float
28
+ val sheetBackgroundColor: Int?
29
+ val maxContentWidth: Int?
30
+ val anchor: TrueSheetAnchor
31
+ val anchorOffset: Int
32
+ val grabber: Boolean
33
+ val grabberOptions: GrabberOptions?
34
+ val accessibilityOptions: AccessibilityOptions?
35
+ val draggable: Boolean
36
+ fun bottomSheetViewDidTapGrabber()
37
+ fun bottomSheetViewDidAccessibilityIncrement()
38
+ fun bottomSheetViewDidAccessibilityDecrement()
39
+ }
40
+
41
+ /**
42
+ * The bottom sheet view that holds the content.
43
+ * This view has BottomSheetBehavior attached via CoordinatorLayout.LayoutParams.
44
+ *
45
+ * Touch dispatching to React Native is handled by TrueSheetViewController,
46
+ * which is the actual RootView containing the React content.
47
+ */
48
+ @SuppressLint("ViewConstructor")
49
+ class TrueSheetBottomSheetView(private val reactContext: ThemedReactContext) : FrameLayout(reactContext) {
50
+
51
+ companion object {
52
+ private const val GRABBER_TAG = "TrueSheetGrabber"
53
+ private const val DEFAULT_CORNER_RADIUS = 16f // dp
54
+ private const val DEFAULT_MAX_WIDTH = 640 // dp
55
+ private const val DEFAULT_ELEVATION = 4f // dp
56
+
57
+ // M3 baseline surfaceContainerLow
58
+ private val COLOR_SURFACE_CONTAINER_LOW_LIGHT = Color.parseColor("#F7F2FA")
59
+ private val COLOR_SURFACE_CONTAINER_LOW_DARK = Color.parseColor("#1D1B20")
60
+ }
61
+
62
+ // =============================================================================
63
+ // MARK: - Properties
64
+ // =============================================================================
65
+
66
+ var delegate: TrueSheetBottomSheetViewDelegate? = null
67
+
68
+ // Behavior reference (set after adding to CoordinatorLayout)
69
+ @Suppress("UNCHECKED_CAST")
70
+ val behavior: TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>?
71
+ get() = (layoutParams as? CoordinatorLayout.LayoutParams)
72
+ ?.behavior as? TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>
73
+
74
+ // =============================================================================
75
+ // MARK: - Initialization
76
+ // =============================================================================
77
+
78
+ init {
79
+ // Allow content to extend beyond bounds (for footer positioning)
80
+ clipChildren = false
81
+ clipToPadding = false
82
+ }
83
+
84
+ override fun setTranslationY(translationY: Float) {
85
+ // This prevents keyboard inset animations from resetting parent sheet translation
86
+ if (translationY == 0f && this.translationY != 0f) {
87
+ return
88
+ }
89
+ super.setTranslationY(translationY)
90
+ }
91
+
92
+ // =============================================================================
93
+ // MARK: - Layout
94
+ // =============================================================================
95
+
96
+ private fun resolveAnchor(): Pair<Int, Int> {
97
+ val anchor = if (ScreenUtils.isPortraitPhone(reactContext)) null else delegate?.anchor
98
+ val gravity = when (anchor) {
99
+ TrueSheetAnchor.LEFT -> Gravity.START
100
+ TrueSheetAnchor.RIGHT -> Gravity.END
101
+ else -> Gravity.CENTER_HORIZONTAL
102
+ } or Gravity.BOTTOM
103
+ val margin = if (anchor == TrueSheetAnchor.LEFT || anchor == TrueSheetAnchor.RIGHT) delegate?.anchorOffset ?: 0 else 0
104
+ return Pair(gravity, margin)
105
+ }
106
+
107
+ /**
108
+ * Creates layout params with BottomSheetBehavior attached.
109
+ */
110
+ fun createLayoutParams(): CoordinatorLayout.LayoutParams {
111
+ val applyMaxWidth = delegate?.maxContentWidth != null && !ScreenUtils.isPortraitPhone(reactContext)
112
+ val effectiveMaxWidth = if (applyMaxWidth) delegate!!.maxContentWidth!! else DEFAULT_MAX_WIDTH.dpToPx().toInt()
113
+ val behavior = TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>().apply {
114
+ isHideable = true
115
+ maxWidth = effectiveMaxWidth
116
+ }
117
+
118
+ val (gravity, margin) = resolveAnchor()
119
+
120
+ return CoordinatorLayout.LayoutParams(
121
+ CoordinatorLayout.LayoutParams.MATCH_PARENT,
122
+ CoordinatorLayout.LayoutParams.MATCH_PARENT
123
+ ).apply {
124
+ this.behavior = behavior
125
+ this.gravity = gravity
126
+ this.marginStart = margin
127
+ this.marginEnd = margin
128
+ }
129
+ }
130
+
131
+ fun updateGravity() {
132
+ val params = layoutParams as? CoordinatorLayout.LayoutParams ?: return
133
+ val (gravity, margin) = resolveAnchor()
134
+
135
+ if (params.gravity == gravity && params.marginStart == margin) return
136
+
137
+ params.gravity = gravity
138
+ params.marginStart = margin
139
+ params.marginEnd = margin
140
+ layoutParams = params
141
+ }
142
+
143
+ // =============================================================================
144
+ // MARK: - Background & Styling
145
+ // =============================================================================
146
+
147
+ fun setupBackground() {
148
+ val radius = delegate?.sheetCornerRadius ?: DEFAULT_CORNER_RADIUS.dpToPx()
149
+ val effectiveRadius = if (radius < 0) DEFAULT_CORNER_RADIUS.dpToPx() else radius
150
+
151
+ val outerRadii = floatArrayOf(
152
+ effectiveRadius,
153
+ effectiveRadius, // top-left
154
+ effectiveRadius,
155
+ effectiveRadius, // top-right
156
+ 0f,
157
+ 0f, // bottom-right
158
+ 0f,
159
+ 0f // bottom-left
160
+ )
161
+
162
+ val color = delegate?.sheetBackgroundColor ?: getDefaultBackgroundColor()
163
+
164
+ background = ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
165
+ paint.color = color
166
+ }
167
+
168
+ outlineProvider = object : ViewOutlineProvider() {
169
+ override fun getOutline(view: View, outline: Outline) {
170
+ outline.setRoundRect(0, 0, view.width, view.height, effectiveRadius)
171
+ }
172
+ }
173
+ clipToOutline = true
174
+ }
175
+
176
+ private fun getDefaultBackgroundColor(): Int {
177
+ val isNight = (
178
+ reactContext.resources.configuration.uiMode and
179
+ Configuration.UI_MODE_NIGHT_MASK
180
+ ) == Configuration.UI_MODE_NIGHT_YES
181
+ return if (isNight) COLOR_SURFACE_CONTAINER_LOW_DARK else COLOR_SURFACE_CONTAINER_LOW_LIGHT
182
+ }
183
+
184
+ fun setupElevation() {
185
+ val value = delegate?.sheetElevation ?: DEFAULT_ELEVATION
186
+ val effectiveElevation = if (value < 0) DEFAULT_ELEVATION else value
187
+ elevation = effectiveElevation.dpToPx()
188
+ }
189
+
190
+ // =============================================================================
191
+ // MARK: - Grabber
192
+ // =============================================================================
193
+
194
+ fun setupGrabber() {
195
+ findViewWithTag<View>(GRABBER_TAG)?.let { removeView(it) }
196
+
197
+ // Content view is the controller, added before the grabber (delegate is the controller)
198
+ val contentView = delegate as? View
199
+
200
+ val isEnabled = delegate?.grabber ?: true
201
+ val isDraggable = delegate?.draggable ?: true
202
+ if (!isEnabled || !isDraggable) {
203
+ contentView?.accessibilityTraversalAfter = View.NO_ID
204
+ return
205
+ }
206
+
207
+ val grabberView = TrueSheetGrabberView(reactContext, delegate?.grabberOptions, delegate?.accessibilityOptions).apply {
208
+ tag = GRABBER_TAG
209
+ id = View.generateViewId()
210
+ onAccessibilityIncrement = { delegate?.bottomSheetViewDidAccessibilityIncrement() }
211
+ onAccessibilityDecrement = { delegate?.bottomSheetViewDidAccessibilityDecrement() }
212
+ }
213
+
214
+ addView(grabberView)
215
+
216
+ // Grabber is added after content for z-ordering, but should be announced first
217
+ contentView?.accessibilityTraversalAfter = grabberView.id
218
+ }
219
+
220
+ fun updateGrabberAccessibilityValue(index: Int, detentCount: Int) {
221
+ findViewWithTag<TrueSheetGrabberView>(GRABBER_TAG)?.updateAccessibilityValue(index, detentCount)
222
+ }
223
+
224
+ fun setupAccessibility() {
225
+ ViewCompat.setAccessibilityPaneTitle(this, delegate?.accessibilityOptions?.paneTitle ?: "Bottom sheet")
226
+ }
227
+
228
+ // =============================================================================
229
+ // MARK: - Grabber Tap Detection
230
+ // =============================================================================
231
+
232
+ private val grabberTapDetector = GestureDetector(
233
+ context,
234
+ object : GestureDetector.SimpleOnGestureListener() {
235
+ override fun onSingleTapUp(e: MotionEvent): Boolean {
236
+ delegate?.bottomSheetViewDidTapGrabber()
237
+ return true
238
+ }
239
+ }
240
+ )
241
+
242
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
243
+ val grabber = findViewWithTag<View>(GRABBER_TAG)
244
+ if (grabber != null) {
245
+ val rect = Rect()
246
+ grabber.getHitRect(rect)
247
+ if (rect.contains(ev.x.toInt(), ev.y.toInt())) {
248
+ if (grabberTapDetector.onTouchEvent(ev)) {
249
+ return true
250
+ }
251
+ }
252
+ }
253
+ return super.dispatchTouchEvent(ev)
254
+ }
255
+ }