@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,102 +1,128 @@
1
1
  package com.lodev09.truesheet.utils
2
2
 
3
- import android.annotation.SuppressLint
4
- import android.content.Context
3
+ import android.content.res.Configuration
4
+ import android.graphics.Point
5
5
  import android.os.Build
6
- import android.util.DisplayMetrics
7
6
  import android.view.View
8
7
  import android.view.WindowInsets
9
8
  import android.view.WindowManager
10
9
  import com.facebook.react.bridge.ReactContext
10
+ import kotlin.math.min
11
11
 
12
12
  /**
13
- * Utility object for screen dimension calculations
13
+ * Data class for top/bottom insets
14
14
  */
15
- object ScreenUtils {
16
- @SuppressLint("DiscouragedApi")
17
- private fun getIdentifierHeight(context: ReactContext, name: String): Int =
18
- context.resources.getDimensionPixelSize(
19
- context.resources.getIdentifier(name, "dimen", "android")
20
- ).takeIf { it > 0 } ?: 0
15
+ data class Insets(val top: Int, val bottom: Int)
21
16
 
17
+ /**
18
+ * Utility object for screen dimension calculations.
19
+ * Inset calculation approach inspired by react-native-safe-area-context.
20
+ *
21
+ * Note: This library requires React Native 0.76+ which has minSdk API 24.
22
+ */
23
+ object ScreenUtils {
22
24
  /**
23
- * Get the status bar height
24
- *
25
- * @param context React context
26
- * @return Status bar height in pixels
25
+ * Get root window insets for API 30+ (Android R)
27
26
  */
28
- fun getStatusBarHeight(context: ReactContext): Int {
29
- // Modern approach using WindowInsets (API 30+)
27
+ private fun getInsetsR(rootView: View): Insets? {
30
28
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
31
- val windowManager = context.getSystemService(WindowManager::class.java)
32
- val windowMetrics = windowManager?.currentWindowMetrics
33
- val insets = windowMetrics?.windowInsets?.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
34
- if (insets != null) {
35
- return insets.top
36
- }
29
+ val insets = rootView.rootWindowInsets?.getInsets(
30
+ WindowInsets.Type.statusBars() or
31
+ WindowInsets.Type.displayCutout() or
32
+ WindowInsets.Type.navigationBars()
33
+ ) ?: return null
34
+ return Insets(
35
+ top = insets.top,
36
+ bottom = insets.bottom
37
+ )
37
38
  }
39
+ return null
40
+ }
38
41
 
39
- // Fallback to legacy approach for older APIs
40
- return getIdentifierHeight(context, "status_bar_height")
42
+ /**
43
+ * Get root window insets for API 24-29
44
+ */
45
+ @Suppress("DEPRECATION")
46
+ private fun getInsetsLegacy(rootView: View): Insets? {
47
+ val insets = rootView.rootWindowInsets ?: return null
48
+ return Insets(
49
+ top = insets.systemWindowInsetTop,
50
+ // Use min to avoid including soft keyboard
51
+ bottom = min(insets.systemWindowInsetBottom, insets.stableInsetBottom)
52
+ )
41
53
  }
42
54
 
43
55
  /**
44
- * Calculate the screen height
56
+ * Get safe area insets from ReactContext using the activity's decor view.
45
57
  *
46
- * @param context React context
47
- * @param edgeToEdge Whether edge-to-edge mode is enabled
48
- * @return Screen height in pixels
58
+ * @param reactContext The ReactContext to get insets from
59
+ * @return Insets with top (status bar) and bottom (navigation bar) values in pixels
49
60
  */
50
- @SuppressLint("InternalInsetResource", "DiscouragedApi")
51
- fun getScreenHeight(context: ReactContext, edgeToEdge: Boolean): Int {
52
- val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
53
- val displayMetrics = DisplayMetrics()
54
-
55
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
56
- context.display?.getRealMetrics(displayMetrics)
61
+ fun getInsets(reactContext: ReactContext): Insets {
62
+ val activity = reactContext.currentActivity ?: return Insets(0, 0)
63
+ val decorView = activity.window?.decorView ?: return Insets(0, 0)
64
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
65
+ getInsetsR(decorView)
57
66
  } else {
58
- windowManager.defaultDisplay.getMetrics(displayMetrics)
59
- }
60
-
61
- val screenHeight = displayMetrics.heightPixels
62
- val statusBarHeight = getStatusBarHeight(context)
67
+ getInsetsLegacy(decorView)
68
+ } ?: Insets(0, 0)
69
+ }
63
70
 
64
- val hasNavigationBar = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
65
- context.getSystemService(WindowManager::class.java)
66
- ?.currentWindowMetrics
67
- ?.windowInsets
68
- ?.isVisible(WindowInsets.Type.navigationBars()) ?: false
71
+ /**
72
+ * Get the real physical device screen height, including system bars.
73
+ * This is consistent across all API levels.
74
+ *
75
+ * @param reactContext The ReactContext to get context from
76
+ * @return Real screen height in pixels
77
+ */
78
+ @Suppress("DEPRECATION")
79
+ fun getRealScreenHeight(reactContext: ReactContext): Int {
80
+ val windowManager = reactContext.getSystemService(WindowManager::class.java)
81
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
82
+ windowManager.currentWindowMetrics.bounds.height()
69
83
  } else {
70
- context.resources.getIdentifier("navigation_bar_height", "dimen", "android") > 0
84
+ val size = Point()
85
+ windowManager.defaultDisplay.getRealSize(size)
86
+ size.y
71
87
  }
88
+ }
72
89
 
73
- val navigationBarHeight = if (hasNavigationBar) {
74
- getIdentifierHeight(context, "navigation_bar_height")
75
- } else {
76
- 0
77
- }
90
+ /**
91
+ * Get the screen width using the same method as React Native's useWindowDimensions.
92
+ *
93
+ * @param reactContext The ReactContext to get resources from
94
+ * @return Screen width in pixels
95
+ */
96
+ fun getScreenWidth(reactContext: ReactContext): Int = reactContext.resources.displayMetrics.widthPixels
78
97
 
79
- return if (edgeToEdge) {
80
- // getRealMetrics includes navigation bar height
81
- // windowManager.defaultDisplay.getMetrics doesn't
82
- when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
83
- true -> screenHeight
84
- false -> screenHeight + navigationBarHeight
85
- }
86
- } else {
87
- screenHeight - statusBarHeight - navigationBarHeight
88
- }
89
- }
98
+ /**
99
+ * Calculate the screen height using the same method as React Native's useWindowDimensions.
100
+ * This returns the window height which automatically accounts for edge-to-edge mode.
101
+ *
102
+ * @param reactContext The ReactContext to get resources from
103
+ * @return Screen height in pixels
104
+ */
105
+ fun getScreenHeight(reactContext: ReactContext): Int = reactContext.resources.displayMetrics.heightPixels
90
106
 
91
107
  /**
92
- * Get the Y coordinate of a view in screen coordinates
108
+ * Get the location of a view in screen coordinates
93
109
  *
94
- * @param view The view to get screen Y coordinate for
95
- * @return Y coordinate in screen space
110
+ * @param view The view to get screen location for
111
+ * @return IntArray with [x, y] coordinates in screen space
96
112
  */
97
- fun getScreenY(view: View): Int {
113
+ fun getScreenLocation(view: View): IntArray {
98
114
  val location = IntArray(2)
99
115
  view.getLocationOnScreen(location)
100
- return location[1]
116
+ return location
117
+ }
118
+
119
+ /**
120
+ * Returns true if the device is a phone in portrait orientation.
121
+ */
122
+ fun isPortraitPhone(reactContext: ReactContext): Boolean {
123
+ val config = reactContext.resources.configuration
124
+ val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT
125
+ val isPhone = config.smallestScreenWidthDp < 600
126
+ return isPortrait && isPhone
101
127
  }
102
128
  }
@@ -0,0 +1,31 @@
1
+ package com.lodev09.truesheet.utils
2
+
3
+ import android.view.MotionEvent
4
+
5
+ /**
6
+ * Guards a nested RootView against dispatching the same [MotionEvent] to JS twice.
7
+ *
8
+ * An event that no child consumes reaches both `onInterceptTouchEvent` and `onTouchEvent`,
9
+ * so dispatching from both starts a second JS touch stream for the same gesture.
10
+ *
11
+ * A plain root can live with that, but the sheet's roots are nested: touches that hit no
12
+ * React child resolve to the root's own tag, and the second stream then finds that view
13
+ * already holding the responder, so React only asks its ancestors - handing the touch to
14
+ * touchables outside the sheet.
15
+ */
16
+ internal class TouchEventDeduper {
17
+ private var downTime = Long.MIN_VALUE
18
+ private var eventTime = Long.MIN_VALUE
19
+ private var action = -1
20
+
21
+ fun shouldDispatch(event: MotionEvent): Boolean {
22
+ if (event.downTime == downTime && event.eventTime == eventTime && event.action == action) {
23
+ return false
24
+ }
25
+
26
+ downTime = event.downTime
27
+ eventTime = event.eventTime
28
+ action = event.action
29
+ return true
30
+ }
31
+ }
@@ -0,0 +1,42 @@
1
+ package com.lodev09.truesheet.utils
2
+
3
+ import android.view.View
4
+ import android.view.ViewGroup
5
+ import android.view.ViewParent
6
+ import android.widget.ScrollView
7
+ import androidx.core.widget.NestedScrollView
8
+ import com.facebook.react.uimanager.ThemedReactContext
9
+
10
+ fun View.isDescendantOf(ancestor: View): Boolean {
11
+ if (!isAttachedToWindow) return false
12
+ var current: View? = this
13
+ while (current != null) {
14
+ if (current === ancestor) return true
15
+ current = (current.parent as? View)
16
+ }
17
+ return false
18
+ }
19
+
20
+ fun ViewGroup.smoothScrollTo(x: Int, y: Int) {
21
+ when (this) {
22
+ is ScrollView -> smoothScrollTo(x, y)
23
+ is NestedScrollView -> smoothScrollTo(x, y)
24
+ }
25
+ }
26
+
27
+ /**
28
+ * The content view hosting this view — the activity's, or a Modal dialog's.
29
+ * Window-level views (sheet coordinators, overlays) attach here.
30
+ */
31
+ fun View.findRootContainerView(reactContext: ThemedReactContext): ViewGroup? {
32
+ var current: ViewParent? = parent
33
+
34
+ while (current != null) {
35
+ if (current is ViewGroup && current.id == android.R.id.content) {
36
+ return current
37
+ }
38
+ current = current.parent
39
+ }
40
+
41
+ return reactContext.currentActivity?.findViewById(android.R.id.content)
42
+ }
@@ -0,0 +1,63 @@
1
+ cmake_minimum_required(VERSION 3.13)
2
+ set(CMAKE_VERBOSE_MAKEFILE ON)
3
+
4
+ set(LIB_LITERAL TrueSheetSpec)
5
+ set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL})
6
+
7
+ set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
8
+ set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp)
9
+ set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni)
10
+ set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL})
11
+
12
+ file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp)
13
+ file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp)
14
+
15
+ add_library(
16
+ ${LIB_TARGET_NAME}
17
+ SHARED
18
+ ${LIB_CUSTOM_SRCS}
19
+ ${LIB_CODEGEN_SRCS}
20
+ )
21
+
22
+ target_include_directories(
23
+ ${LIB_TARGET_NAME}
24
+ PUBLIC
25
+ .
26
+ ${LIB_COMMON_DIR}
27
+ ${LIB_ANDROID_GENERATED_JNI_DIR}
28
+ ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
29
+ )
30
+
31
+ target_link_libraries(
32
+ ${LIB_TARGET_NAME}
33
+ ReactAndroid::reactnative
34
+ ReactAndroid::jsi
35
+ fbjni::fbjni
36
+ )
37
+
38
+ target_include_directories(
39
+ ${CMAKE_PROJECT_NAME}
40
+ PUBLIC
41
+ ${CMAKE_CURRENT_SOURCE_DIR}
42
+ )
43
+
44
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
45
+ target_compile_reactnative_options(${LIB_TARGET_NAME} PUBLIC)
46
+ else()
47
+ target_compile_options(
48
+ ${LIB_TARGET_NAME}
49
+ PRIVATE
50
+ -fexceptions
51
+ -frtti
52
+ -std=c++20
53
+ -Wall
54
+ )
55
+ endif()
56
+
57
+ target_compile_options(
58
+ ${LIB_TARGET_NAME}
59
+ PRIVATE
60
+ -Wpedantic
61
+ -Wno-gnu-zero-variadic-macro-arguments
62
+ -Wno-dollar-in-identifier-extension
63
+ )
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/JavaTurboModule.h>
4
+ #include <ReactCommon/TurboModule.h>
5
+ #include <jsi/jsi.h>
6
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h>
7
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h>
8
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h>
9
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h>
10
+
11
+ namespace facebook {
12
+ namespace react {
13
+
14
+ JSI_EXPORT
15
+ std::shared_ptr<TurboModule> TrueSheetSpec_ModuleProvider(
16
+ const std::string &moduleName,
17
+ const JavaTurboModule::InitParams &params);
18
+
19
+ } // namespace react
20
+ } // namespace facebook
@@ -0,0 +1,96 @@
1
+ //
2
+ // Created by Jovanni Lo (@lodev09)
3
+ // Copyright (c) 2024-present. All rights reserved.
4
+ //
5
+ // This source code is licensed under the MIT license found in the
6
+ // LICENSE file in the root directory of this source tree.
7
+ //
8
+
9
+ #include <fbjni/fbjni.h>
10
+ #include <react/fabric/StateWrapperImpl.h>
11
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h>
12
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetInsets.h>
13
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetViewState.h>
14
+ #include <react/renderer/core/ConcreteState.h>
15
+
16
+ namespace facebook::react {
17
+
18
+ static std::shared_ptr<const State> getStateFromWrapper(jni::alias_ref<jobject> stateWrapper) {
19
+ static const auto stateWrapperImplClass =
20
+ jni::findClassStatic(StateWrapperImpl::StateWrapperImplJavaDescriptor);
21
+ if (!stateWrapper->isInstanceOf(stateWrapperImplClass)) {
22
+ return nullptr;
23
+ }
24
+
25
+ auto impl = jni::static_ref_cast<StateWrapperImpl::jhybridobject>(stateWrapper);
26
+ return impl->cthis()->getState();
27
+ }
28
+
29
+ // Kotlin's StateWrapper.updateState is hardcoded async. This bridges to
30
+ // ConcreteState::updateState with unstable_Immediate so the commit — and, when
31
+ // called from the UI thread, the mount — run synchronously, letting Yoga resize
32
+ // the container in the same frame as the sheet (parity with iOS).
33
+ static jboolean updateStateImmediate(
34
+ jni::alias_ref<jclass> /*clazz*/,
35
+ jni::alias_ref<jobject> stateWrapper,
36
+ jfloat containerWidth,
37
+ jfloat containerHeight) {
38
+ auto state = getStateFromWrapper(stateWrapper);
39
+ if (!state) {
40
+ return JNI_FALSE;
41
+ }
42
+
43
+ auto concreteState = std::static_pointer_cast<const ConcreteState<TrueSheetViewState>>(state);
44
+
45
+ // Copy the latest data so fields this bridge doesn't set survive the update
46
+ TrueSheetViewState newState = concreteState->getData();
47
+ newState.containerWidth = containerWidth;
48
+ newState.containerHeight = containerHeight;
49
+ concreteState->updateState(std::move(newState), EventQueue::UpdateMode::unstable_Immediate);
50
+
51
+ return JNI_TRUE;
52
+ }
53
+
54
+ // Same synchronous bridge for the footer's bottom inset — the footer must be
55
+ // padded (and resized) before detents are configured, otherwise the behavior
56
+ // is set up against the unpadded footer height and the auto detent lands an
57
+ // inset short.
58
+ static jboolean updateFooterStateImmediate(
59
+ jni::alias_ref<jclass> /*clazz*/,
60
+ jni::alias_ref<jobject> stateWrapper,
61
+ jfloat bottomInset) {
62
+ auto state = getStateFromWrapper(stateWrapper);
63
+ if (!state) {
64
+ return JNI_FALSE;
65
+ }
66
+
67
+ auto concreteState =
68
+ std::static_pointer_cast<const ConcreteState<TrueSheetFooterViewState>>(state);
69
+
70
+ // Copy the latest data so fields this bridge doesn't set survive the update
71
+ TrueSheetFooterViewState newState = concreteState->getData();
72
+ newState.bottomInset = bottomInset;
73
+ newState.initialized = true;
74
+ concreteState->updateState(std::move(newState), EventQueue::UpdateMode::unstable_Immediate);
75
+
76
+ return JNI_TRUE;
77
+ }
78
+
79
+ // Publishes the precalculated bottom safe-area inset so a late-mounted
80
+ // footer's first layout is already padded (see TrueSheetFooterViewShadowNode).
81
+ static void setBottomSafeArea(jni::alias_ref<jclass> /*clazz*/, jfloat insetDp) {
82
+ TrueSheetInsets::setBottomSafeArea(insetDp);
83
+ }
84
+
85
+ } // namespace facebook::react
86
+
87
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
88
+ return facebook::jni::initialize(vm, [] {
89
+ facebook::jni::findClassStatic("com/lodev09/truesheet/TrueSheetStateUpdater")
90
+ ->registerNatives({
91
+ makeNativeMethod("nativeUpdateState", facebook::react::updateStateImmediate),
92
+ makeNativeMethod("nativeUpdateFooterState", facebook::react::updateFooterStateImmediate),
93
+ makeNativeMethod("nativeSetBottomSafeArea", facebook::react::setBottomSafeArea),
94
+ });
95
+ });
96
+ }
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+
3
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h>
4
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
5
+
6
+ namespace facebook::react {
7
+
8
+ /*
9
+ * Descriptor for <TrueSheetContentView> component.
10
+ */
11
+ class TrueSheetContentViewComponentDescriptor final
12
+ : public ConcreteComponentDescriptor<TrueSheetContentViewShadowNode> {
13
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
14
+ };
15
+
16
+ } // namespace facebook::react
@@ -0,0 +1,68 @@
1
+ #include "TrueSheetContentViewShadowNode.h"
2
+
3
+ #include <limits>
4
+
5
+ #include <react/renderer/components/view/conversions.h>
6
+ #include <react/renderer/core/LayoutConstraints.h>
7
+ #include <react/renderer/core/LayoutContext.h>
8
+
9
+ namespace facebook::react {
10
+
11
+ using namespace yoga;
12
+
13
+ extern const char TrueSheetContentViewComponentName[] = "TrueSheetContentView";
14
+
15
+ // measure() lays out a clone of this node, which re-enters layout() on the
16
+ // clone — guard so the measurement pass doesn't measure again recursively.
17
+ static thread_local bool gIsMeasuringNaturalHeight = false;
18
+
19
+ void TrueSheetContentViewShadowNode::layout(LayoutContext layoutContext) {
20
+ ConcreteViewShadowNode::layout(layoutContext);
21
+ updateNaturalHeightIfNeeded(layoutContext);
22
+ }
23
+
24
+ // The content's committed height follows the container instead of its own
25
+ // content when it can grow/shrink along the main axis or uses a percent
26
+ // height. Reporting that height as the natural height would echo the sheet's
27
+ // own size back as a content size change — e.g. flex: 1 content tracking a
28
+ // drag frame by frame.
29
+ static bool isHeightContainerDerived(const yoga::Style &style) {
30
+ return style.flexGrow().unwrapOrDefault(0) > 0 ||
31
+ style.flexShrink().unwrapOrDefault(0) > 0 ||
32
+ style.dimension(Dimension::Height).isPercent();
33
+ }
34
+
35
+ // The natural height is the height the content wants when unbounded — the
36
+ // source for the auto detent. When the content's height derives from the
37
+ // container, the committed layout doesn't reflect it — lay out a clone of the
38
+ // subtree with an unconstrained height instead. Yoga respects the user's
39
+ // styles: an explicit-height ScrollView keeps its height while a flexible one
40
+ // expands to its content — no ScrollView discovery involved.
41
+ void TrueSheetContentViewShadowNode::updateNaturalHeightIfNeeded(
42
+ const LayoutContext &layoutContext) {
43
+ if (gIsMeasuringNaturalHeight) {
44
+ return;
45
+ }
46
+
47
+ auto stateData = getStateData();
48
+ auto size = getLayoutMetrics().frame.size;
49
+
50
+ Float naturalHeight = size.height;
51
+ if (isHeightContainerDerived(getConcreteProps().yogaStyle)) {
52
+ auto constraints = LayoutConstraints{};
53
+ constraints.minimumSize = {size.width, 0};
54
+ constraints.maximumSize = {size.width, std::numeric_limits<Float>::infinity()};
55
+ constraints.layoutDirection = getLayoutMetrics().layoutDirection;
56
+
57
+ gIsMeasuringNaturalHeight = true;
58
+ naturalHeight = measure(layoutContext, constraints).height;
59
+ gIsMeasuringNaturalHeight = false;
60
+ }
61
+
62
+ if (stateData.naturalHeight != naturalHeight) {
63
+ stateData.naturalHeight = naturalHeight;
64
+ setStateData(std::move(stateData));
65
+ }
66
+ }
67
+
68
+ } // namespace facebook::react
@@ -0,0 +1,33 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <react/renderer/components/TrueSheetSpec/EventEmitters.h>
5
+ #include <react/renderer/components/TrueSheetSpec/Props.h>
6
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h>
7
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
8
+
9
+ namespace facebook::react {
10
+
11
+ JSI_EXPORT extern const char TrueSheetContentViewComponentName[];
12
+
13
+ /*
14
+ * `ShadowNode` for <TrueSheetContentView> component.
15
+ */
16
+ class JSI_EXPORT TrueSheetContentViewShadowNode final
17
+ : public ConcreteViewShadowNode<
18
+ TrueSheetContentViewComponentName,
19
+ TrueSheetContentViewProps,
20
+ TrueSheetContentViewEventEmitter,
21
+ TrueSheetContentViewState> {
22
+ using ConcreteViewShadowNode::ConcreteViewShadowNode;
23
+
24
+ public:
25
+ #pragma mark - LayoutableShadowNode
26
+
27
+ void layout(LayoutContext layoutContext) override;
28
+
29
+ private:
30
+ void updateNaturalHeightIfNeeded(const LayoutContext &layoutContext);
31
+ };
32
+
33
+ } // namespace facebook::react
@@ -0,0 +1,11 @@
1
+ #include "TrueSheetContentViewState.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ #ifdef ANDROID
6
+ folly::dynamic TrueSheetContentViewState::getDynamic() const {
7
+ return folly::dynamic::object("naturalHeight", naturalHeight);
8
+ }
9
+ #endif
10
+
11
+ } // namespace facebook::react
@@ -0,0 +1,39 @@
1
+ #pragma once
2
+
3
+ #include <react/renderer/graphics/Float.h>
4
+
5
+ #ifdef ANDROID
6
+ #include <folly/dynamic.h>
7
+ #include <react/renderer/mapbuffer/MapBuffer.h>
8
+ #include <react/renderer/mapbuffer/MapBufferBuilder.h>
9
+ #endif
10
+
11
+ namespace facebook::react {
12
+
13
+ /*
14
+ * State for <TrueSheetContentView> component.
15
+ * `naturalHeight` is measured by the shadow node during layout — the height
16
+ * the content wants when unbounded (see TrueSheetContentViewShadowNode).
17
+ */
18
+ class TrueSheetContentViewState final {
19
+ public:
20
+ TrueSheetContentViewState() = default;
21
+
22
+ #ifdef ANDROID
23
+ TrueSheetContentViewState(
24
+ TrueSheetContentViewState const &previousState,
25
+ folly::dynamic data)
26
+ : naturalHeight(previousState.naturalHeight) {}
27
+ #endif
28
+
29
+ Float naturalHeight{0};
30
+
31
+ #ifdef ANDROID
32
+ folly::dynamic getDynamic() const;
33
+ MapBuffer getMapBuffer() const {
34
+ return MapBufferBuilder::EMPTY();
35
+ }
36
+ #endif
37
+ };
38
+
39
+ } // namespace facebook::react
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h>
4
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
5
+
6
+ namespace facebook::react {
7
+
8
+ /*
9
+ * Descriptor for <TrueSheetFooterView> component.
10
+ */
11
+ class TrueSheetFooterViewComponentDescriptor final
12
+ : public ConcreteComponentDescriptor<TrueSheetFooterViewShadowNode> {
13
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
14
+
15
+ void adopt(ShadowNode &shadowNode) const override {
16
+ auto &concreteShadowNode =
17
+ static_cast<TrueSheetFooterViewShadowNode &>(shadowNode);
18
+ concreteShadowNode.adjustLayoutWithState();
19
+
20
+ ConcreteComponentDescriptor::adopt(shadowNode);
21
+ }
22
+ };
23
+
24
+ } // namespace facebook::react