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

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 (194) hide show
  1. package/README.md +36 -8
  2. package/RNTrueSheet.podspec +20 -0
  3. package/android/build.gradle +26 -14
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +108 -0
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +21 -0
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +46 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +21 -0
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +47 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +21 -0
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +165 -0
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +36 -4
  12. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +257 -303
  13. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +855 -0
  14. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +104 -82
  15. package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +26 -0
  16. package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +20 -0
  17. package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +26 -0
  18. package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +26 -0
  19. package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +26 -0
  20. package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +26 -0
  21. package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +20 -0
  22. package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +32 -0
  23. package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +27 -0
  24. package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +20 -0
  25. package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +26 -0
  26. package/android/src/main/java/com/lodev09/truesheet/{core/Utils.kt → utils/ScreenUtils.kt} +47 -17
  27. package/android/src/main/res/values/styles.xml +8 -0
  28. package/ios/TrueSheetComponentDescriptor.h +24 -0
  29. package/ios/TrueSheetContainerView.h +47 -0
  30. package/ios/TrueSheetContainerView.mm +117 -0
  31. package/ios/TrueSheetContentView.h +37 -0
  32. package/ios/TrueSheetContentView.mm +114 -0
  33. package/ios/TrueSheetFooterView.h +27 -0
  34. package/ios/TrueSheetFooterView.mm +101 -0
  35. package/ios/TrueSheetModule.h +44 -0
  36. package/ios/TrueSheetModule.mm +133 -0
  37. package/ios/TrueSheetView.h +53 -0
  38. package/ios/TrueSheetView.mm +433 -0
  39. package/ios/TrueSheetViewController.h +53 -0
  40. package/ios/TrueSheetViewController.mm +649 -0
  41. package/ios/events/OnDetentChangeEvent.h +28 -0
  42. package/ios/events/OnDetentChangeEvent.mm +30 -0
  43. package/ios/events/OnDidDismissEvent.h +26 -0
  44. package/ios/events/OnDidDismissEvent.mm +25 -0
  45. package/ios/events/OnDidPresentEvent.h +28 -0
  46. package/ios/events/OnDidPresentEvent.mm +30 -0
  47. package/ios/events/OnDragBeginEvent.h +28 -0
  48. package/ios/events/OnDragBeginEvent.mm +30 -0
  49. package/ios/events/OnDragChangeEvent.h +28 -0
  50. package/ios/events/OnDragChangeEvent.mm +30 -0
  51. package/ios/events/OnDragEndEvent.h +28 -0
  52. package/ios/events/OnDragEndEvent.mm +30 -0
  53. package/ios/events/OnMountEvent.h +26 -0
  54. package/ios/events/OnMountEvent.mm +25 -0
  55. package/ios/events/OnPositionChangeEvent.h +29 -0
  56. package/ios/events/OnPositionChangeEvent.mm +32 -0
  57. package/ios/events/OnSizeChangeEvent.h +28 -0
  58. package/ios/events/OnSizeChangeEvent.mm +30 -0
  59. package/ios/events/OnWillDismissEvent.h +26 -0
  60. package/ios/events/OnWillDismissEvent.mm +25 -0
  61. package/ios/events/OnWillPresentEvent.h +28 -0
  62. package/ios/events/OnWillPresentEvent.mm +30 -0
  63. package/ios/utils/GestureUtil.h +25 -0
  64. package/ios/utils/GestureUtil.mm +26 -0
  65. package/ios/utils/LayoutUtil.h +44 -0
  66. package/ios/utils/LayoutUtil.mm +50 -0
  67. package/ios/utils/WindowUtil.h +27 -0
  68. package/ios/utils/WindowUtil.mm +42 -0
  69. package/lib/module/TrueSheet.js +231 -135
  70. package/lib/module/TrueSheet.js.map +1 -1
  71. package/lib/module/TrueSheetGrabber.js +16 -14
  72. package/lib/module/TrueSheetGrabber.js.map +1 -1
  73. package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +8 -0
  74. package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +8 -0
  75. package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +8 -0
  76. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +63 -0
  77. package/lib/module/index.js +1 -0
  78. package/lib/module/index.js.map +1 -1
  79. package/lib/module/reanimated/ReanimatedTrueSheet.js +87 -0
  80. package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -0
  81. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +72 -0
  82. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -0
  83. package/lib/module/reanimated/index.js +6 -0
  84. package/lib/module/reanimated/index.js.map +1 -0
  85. package/lib/module/reanimated/useReanimatedPositionChangeHandler.js +19 -0
  86. package/lib/module/reanimated/useReanimatedPositionChangeHandler.js.map +1 -0
  87. package/lib/module/specs/NativeTrueSheetModule.js +12 -0
  88. package/lib/module/specs/NativeTrueSheetModule.js.map +1 -0
  89. package/lib/typescript/package.json +1 -0
  90. package/lib/typescript/src/TrueSheet.d.ts +79 -0
  91. package/lib/typescript/src/TrueSheet.d.ts.map +1 -0
  92. package/lib/typescript/src/TrueSheet.types.d.ts +260 -0
  93. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -0
  94. package/lib/typescript/{commonjs/src → src}/TrueSheetGrabber.d.ts +1 -1
  95. package/lib/typescript/src/TrueSheetGrabber.d.ts.map +1 -0
  96. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts +6 -0
  97. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -0
  98. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts +6 -0
  99. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -0
  100. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +6 -0
  101. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -0
  102. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +44 -0
  103. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -0
  104. package/lib/typescript/{commonjs/src → src}/index.d.ts +1 -0
  105. package/lib/typescript/src/index.d.ts.map +1 -0
  106. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts +43 -0
  107. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -0
  108. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +57 -0
  109. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -0
  110. package/lib/typescript/src/reanimated/index.d.ts +4 -0
  111. package/lib/typescript/src/reanimated/index.d.ts.map +1 -0
  112. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.d.ts +6 -0
  113. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.d.ts.map +1 -0
  114. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +34 -0
  115. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -0
  116. package/package.json +104 -75
  117. package/react-native.config.js +17 -0
  118. package/src/TrueSheet.tsx +285 -188
  119. package/src/TrueSheet.types.ts +119 -106
  120. package/src/TrueSheetGrabber.tsx +29 -28
  121. package/src/__mocks__/index.js +60 -12
  122. package/src/fabric/TrueSheetContainerViewNativeComponent.ts +8 -0
  123. package/src/fabric/TrueSheetContentViewNativeComponent.ts +8 -0
  124. package/src/fabric/TrueSheetFooterViewNativeComponent.ts +8 -0
  125. package/src/fabric/TrueSheetViewNativeComponent.ts +63 -0
  126. package/src/index.ts +4 -3
  127. package/src/reanimated/ReanimatedTrueSheet.tsx +95 -0
  128. package/src/reanimated/ReanimatedTrueSheetProvider.tsx +92 -0
  129. package/src/reanimated/index.ts +3 -0
  130. package/src/reanimated/useReanimatedPositionChangeHandler.ts +26 -0
  131. package/src/specs/NativeTrueSheetModule.ts +38 -0
  132. package/TrueSheet.podspec +0 -49
  133. package/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt +0 -413
  134. package/android/src/main/java/com/lodev09/truesheet/TrueSheetEvent.kt +0 -22
  135. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewModule.kt +0 -63
  136. package/android/src/main/java/com/lodev09/truesheet/core/KeyboardManager.kt +0 -58
  137. package/android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt +0 -102
  138. package/ios/Extensions/UIBlurEffect+withTint.swift +0 -62
  139. package/ios/Extensions/UIView+pinTo.swift +0 -74
  140. package/ios/Extensions/UIViewController+detentForSize.swift +0 -134
  141. package/ios/TrueSheet-Bridging-Header.h +0 -14
  142. package/ios/TrueSheetEvent.swift +0 -48
  143. package/ios/TrueSheetView.swift +0 -467
  144. package/ios/TrueSheetViewController.swift +0 -275
  145. package/ios/TrueSheetViewManager.m +0 -53
  146. package/ios/TrueSheetViewManager.swift +0 -48
  147. package/ios/Utils/Logger.swift +0 -39
  148. package/ios/Utils/Promise.swift +0 -25
  149. package/lib/commonjs/TrueSheet.js +0 -258
  150. package/lib/commonjs/TrueSheet.js.map +0 -1
  151. package/lib/commonjs/TrueSheet.types.js +0 -6
  152. package/lib/commonjs/TrueSheet.types.js.map +0 -1
  153. package/lib/commonjs/TrueSheetFooter.js +0 -19
  154. package/lib/commonjs/TrueSheetFooter.js.map +0 -1
  155. package/lib/commonjs/TrueSheetGrabber.js +0 -54
  156. package/lib/commonjs/TrueSheetGrabber.js.map +0 -1
  157. package/lib/commonjs/TrueSheetModule.js +0 -19
  158. package/lib/commonjs/TrueSheetModule.js.map +0 -1
  159. package/lib/commonjs/__mocks__/index.js +0 -52
  160. package/lib/commonjs/__mocks__/index.js.map +0 -1
  161. package/lib/commonjs/index.js +0 -39
  162. package/lib/commonjs/index.js.map +0 -1
  163. package/lib/module/TrueSheetFooter.js +0 -14
  164. package/lib/module/TrueSheetFooter.js.map +0 -1
  165. package/lib/module/TrueSheetModule.js +0 -15
  166. package/lib/module/TrueSheetModule.js.map +0 -1
  167. package/lib/module/__mocks__/index.js +0 -21
  168. package/lib/module/__mocks__/index.js.map +0 -1
  169. package/lib/typescript/commonjs/package.json +0 -1
  170. package/lib/typescript/commonjs/src/TrueSheet.d.ts +0 -70
  171. package/lib/typescript/commonjs/src/TrueSheet.d.ts.map +0 -1
  172. package/lib/typescript/commonjs/src/TrueSheet.types.d.ts +0 -241
  173. package/lib/typescript/commonjs/src/TrueSheet.types.d.ts.map +0 -1
  174. package/lib/typescript/commonjs/src/TrueSheetFooter.d.ts +0 -7
  175. package/lib/typescript/commonjs/src/TrueSheetFooter.d.ts.map +0 -1
  176. package/lib/typescript/commonjs/src/TrueSheetGrabber.d.ts.map +0 -1
  177. package/lib/typescript/commonjs/src/TrueSheetModule.d.ts +0 -2
  178. package/lib/typescript/commonjs/src/TrueSheetModule.d.ts.map +0 -1
  179. package/lib/typescript/commonjs/src/index.d.ts.map +0 -1
  180. package/lib/typescript/module/src/TrueSheet.d.ts +0 -70
  181. package/lib/typescript/module/src/TrueSheet.d.ts.map +0 -1
  182. package/lib/typescript/module/src/TrueSheet.types.d.ts +0 -241
  183. package/lib/typescript/module/src/TrueSheet.types.d.ts.map +0 -1
  184. package/lib/typescript/module/src/TrueSheetFooter.d.ts +0 -7
  185. package/lib/typescript/module/src/TrueSheetFooter.d.ts.map +0 -1
  186. package/lib/typescript/module/src/TrueSheetGrabber.d.ts +0 -39
  187. package/lib/typescript/module/src/TrueSheetGrabber.d.ts.map +0 -1
  188. package/lib/typescript/module/src/TrueSheetModule.d.ts +0 -2
  189. package/lib/typescript/module/src/TrueSheetModule.d.ts.map +0 -1
  190. package/lib/typescript/module/src/index.d.ts +0 -4
  191. package/lib/typescript/module/src/index.d.ts.map +0 -1
  192. package/src/TrueSheetFooter.tsx +0 -17
  193. package/src/TrueSheetModule.ts +0 -19
  194. /package/lib/{typescript/module → module}/package.json +0 -0
@@ -1,20 +1,31 @@
1
1
  package com.lodev09.truesheet
2
2
 
3
3
  import android.graphics.Color
4
- import android.util.Log
5
4
  import android.view.WindowManager
6
- import com.facebook.react.bridge.ColorPropConverter
7
5
  import com.facebook.react.bridge.ReadableArray
8
- import com.facebook.react.bridge.ReadableType
9
- import com.facebook.react.common.MapBuilder
6
+ import com.facebook.react.module.annotations.ReactModule
7
+ import com.facebook.react.uimanager.PixelUtil.dpToPx
10
8
  import com.facebook.react.uimanager.ThemedReactContext
11
9
  import com.facebook.react.uimanager.UIManagerHelper
12
10
  import com.facebook.react.uimanager.ViewGroupManager
11
+ import com.facebook.react.uimanager.ViewManagerDelegate
13
12
  import com.facebook.react.uimanager.annotations.ReactProp
14
- import com.lodev09.truesheet.core.Utils
13
+ import com.facebook.react.viewmanagers.TrueSheetViewManagerDelegate
14
+ import com.facebook.react.viewmanagers.TrueSheetViewManagerInterface
15
+ import com.lodev09.truesheet.events.*
15
16
 
16
- class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
17
- override fun getName() = TAG
17
+ /**
18
+ * ViewManager for TrueSheetView - Fabric architecture
19
+ * Main sheet component that manages the bottom sheet dialog
20
+ */
21
+ @ReactModule(name = TrueSheetViewManager.REACT_CLASS)
22
+ class TrueSheetViewManager :
23
+ ViewGroupManager<TrueSheetView>(),
24
+ TrueSheetViewManagerInterface<TrueSheetView> {
25
+
26
+ private val delegate: ViewManagerDelegate<TrueSheetView> = TrueSheetViewManagerDelegate(this)
27
+
28
+ override fun getName(): String = REACT_CLASS
18
29
 
19
30
  override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetView = TrueSheetView(reactContext)
20
31
 
@@ -23,117 +34,128 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
23
34
  view.onDropInstance()
24
35
  }
25
36
 
37
+ override fun onAfterUpdateTransaction(view: TrueSheetView) {
38
+ super.onAfterUpdateTransaction(view)
39
+ view.showOrUpdate()
40
+ }
41
+
26
42
  override fun addEventEmitters(reactContext: ThemedReactContext, view: TrueSheetView) {
27
43
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)
28
- dispatcher?.let {
29
- view.eventDispatcher = it
30
- }
44
+ view.eventDispatcher = dispatcher
31
45
  }
32
46
 
33
- override fun onAfterUpdateTransaction(view: TrueSheetView) {
34
- super.onAfterUpdateTransaction(view)
35
- view.configureIfShowing()
36
- }
47
+ override fun getDelegate(): ViewManagerDelegate<TrueSheetView> = delegate
37
48
 
49
+ /**
50
+ * Export custom direct event types for Fabric
51
+ * Uses Kotlin native collections with decoupled event classes
52
+ */
38
53
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
39
54
  mutableMapOf(
40
- TrueSheetEvent.MOUNT to MapBuilder.of("registrationName", "onMount"),
41
- TrueSheetEvent.PRESENT to MapBuilder.of("registrationName", "onPresent"),
42
- TrueSheetEvent.DISMISS to MapBuilder.of("registrationName", "onDismiss"),
43
- TrueSheetEvent.SIZE_CHANGE to MapBuilder.of("registrationName", "onSizeChange"),
44
- TrueSheetEvent.DRAG_BEGIN to MapBuilder.of("registrationName", "onDragBegin"),
45
- TrueSheetEvent.DRAG_CHANGE to MapBuilder.of("registrationName", "onDragChange"),
46
- TrueSheetEvent.DRAG_END to MapBuilder.of("registrationName", "onDragEnd"),
47
- TrueSheetEvent.CONTAINER_SIZE_CHANGE to MapBuilder.of("registrationName", "onContainerSizeChange")
55
+ MountEvent.EVENT_NAME to hashMapOf("registrationName" to MountEvent.REGISTRATION_NAME),
56
+ WillPresentEvent.EVENT_NAME to hashMapOf("registrationName" to WillPresentEvent.REGISTRATION_NAME),
57
+ DidPresentEvent.EVENT_NAME to hashMapOf("registrationName" to DidPresentEvent.REGISTRATION_NAME),
58
+ WillDismissEvent.EVENT_NAME to hashMapOf("registrationName" to WillDismissEvent.REGISTRATION_NAME),
59
+ DidDismissEvent.EVENT_NAME to hashMapOf("registrationName" to DidDismissEvent.REGISTRATION_NAME),
60
+ DetentChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DetentChangeEvent.REGISTRATION_NAME),
61
+ DragBeginEvent.EVENT_NAME to hashMapOf("registrationName" to DragBeginEvent.REGISTRATION_NAME),
62
+ DragChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DragChangeEvent.REGISTRATION_NAME),
63
+ DragEndEvent.EVENT_NAME to hashMapOf("registrationName" to DragEndEvent.REGISTRATION_NAME),
64
+ PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME),
65
+ SizeChangeEvent.EVENT_NAME to hashMapOf("registrationName" to SizeChangeEvent.REGISTRATION_NAME)
48
66
  )
49
67
 
50
- @ReactProp(name = "edgeToEdge")
51
- fun setEdgeToEdge(view: TrueSheetView, edgeToEdge: Boolean) {
52
- view.setEdgeToEdge(edgeToEdge)
53
- }
68
+ // ==================== Props ====================
54
69
 
55
- @ReactProp(name = "maxHeight")
56
- fun setMaxHeight(view: TrueSheetView, height: Double) {
57
- view.setMaxHeight(Utils.toPixel(height).toInt())
58
- }
70
+ @ReactProp(name = "detents")
71
+ override fun setDetents(view: TrueSheetView, value: ReadableArray?) {
72
+ if (value == null || value.size() == 0) {
73
+ view.setDetents(mutableListOf(0.5, 1.0))
74
+ return
75
+ }
59
76
 
60
- @ReactProp(name = "dismissible")
61
- fun setDismissible(view: TrueSheetView, dismissible: Boolean) {
62
- view.setDismissible(dismissible)
63
- }
77
+ val detents = mutableListOf<Double>()
64
78
 
65
- @ReactProp(name = "dimmed")
66
- fun setDimmed(view: TrueSheetView, dimmed: Boolean) {
67
- view.setDimmed(dimmed)
68
- }
79
+ IntProgression
80
+ .fromClosedRange(0, value.size() - 1, 1)
81
+ .asSequence()
82
+ .map { idx -> value.getDouble(idx) }
83
+ .toCollection(detents)
69
84
 
70
- @ReactProp(name = "initialIndex")
71
- fun setInitialIndex(view: TrueSheetView, index: Int) {
72
- view.initialIndex = index
85
+ view.setDetents(detents)
73
86
  }
74
87
 
75
- @ReactProp(name = "initialIndexAnimated")
76
- fun setInitialIndexAnimated(view: TrueSheetView, animate: Boolean) {
77
- view.initialIndexAnimated = animate
88
+ @ReactProp(name = "background", defaultInt = Color.WHITE)
89
+ override fun setBackground(view: TrueSheetView, color: Int) {
90
+ view.setSheetBackgroundColor(color)
78
91
  }
79
92
 
80
- @ReactProp(name = "keyboardMode")
81
- fun setKeyboardMode(view: TrueSheetView, mode: String) {
82
- val softInputMode = when (mode) {
83
- "pan" -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
84
- else -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
93
+ @ReactProp(name = "cornerRadius", defaultDouble = -1.0)
94
+ override fun setCornerRadius(view: TrueSheetView, radius: Double) {
95
+ if (radius >= 0) {
96
+ view.setCornerRadius(radius.dpToPx())
85
97
  }
86
-
87
- view.setSoftInputMode(softInputMode)
88
98
  }
89
99
 
90
- @ReactProp(name = "dimmedIndex")
91
- fun setDimmedIndex(view: TrueSheetView, index: Int) {
92
- view.setDimmedIndex(index)
100
+ @ReactProp(name = "grabber", defaultBoolean = true)
101
+ override fun setGrabber(view: TrueSheetView, grabber: Boolean) {
102
+ view.setGrabber(grabber)
93
103
  }
94
104
 
95
- @ReactProp(name = "contentHeight")
96
- fun setContentHeight(view: TrueSheetView, height: Double) {
97
- view.setContentHeight(Utils.toPixel(height).toInt())
105
+ @ReactProp(name = "dismissible", defaultBoolean = true)
106
+ override fun setDismissible(view: TrueSheetView, dismissible: Boolean) {
107
+ view.setDismissible(dismissible)
98
108
  }
99
109
 
100
- @ReactProp(name = "footerHeight")
101
- fun setFooterHeight(view: TrueSheetView, height: Double) {
102
- view.setFooterHeight(Utils.toPixel(height).toInt())
110
+ @ReactProp(name = "dimmed", defaultBoolean = true)
111
+ override fun setDimmed(view: TrueSheetView, dimmed: Boolean) {
112
+ view.setDimmed(dimmed)
103
113
  }
104
114
 
105
- @ReactProp(name = "cornerRadius")
106
- fun setCornerRadius(view: TrueSheetView, radius: Double) {
107
- view.setCornerRadius(Utils.toPixel(radius))
115
+ @ReactProp(name = "dimmedIndex", defaultInt = 0)
116
+ override fun setDimmedIndex(view: TrueSheetView, index: Int) {
117
+ view.setDimmedIndex(index)
108
118
  }
109
119
 
110
- @ReactProp(name = "background")
111
- fun setBackground(view: TrueSheetView, colorName: Double) {
112
- val color = runCatching { ColorPropConverter.getColor(colorName, view.context) }.getOrNull() ?: Color.WHITE
113
- view.setBackground(color)
120
+ @ReactProp(name = "initialDetentIndex", defaultInt = -1)
121
+ override fun setInitialDetentIndex(view: TrueSheetView, index: Int) {
122
+ view.initialDetentIndex = index
114
123
  }
115
124
 
116
- @ReactProp(name = "sizes")
117
- fun setSizes(view: TrueSheetView, sizes: ReadableArray) {
118
- val result = ArrayList<Any>()
119
- for (i in 0 until minOf(sizes.size(), 3)) {
120
- when (sizes.getType(i)) {
121
- ReadableType.Number -> result.add(sizes.getDouble(i))
125
+ @ReactProp(name = "initialDetentAnimated", defaultBoolean = true)
126
+ override fun setInitialDetentAnimated(view: TrueSheetView, animate: Boolean) {
127
+ view.initialDetentAnimated = animate
128
+ }
122
129
 
123
- // React Native < 0.77 used String for getString, but 0.77
124
- // changed it to String?. Suppress the error for older APIs.
125
- @Suppress("UNNECESSARY_SAFE_CALL")
126
- ReadableType.String
127
- -> sizes.getString(i)?.let { result.add(it) }
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
+ }
135
+ }
128
136
 
129
- else -> Log.d(TAG, "Invalid type")
130
- }
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
131
142
  }
143
+ view.setSoftInputMode(softInputMode)
144
+ }
145
+
146
+ @ReactProp(name = "blurTint")
147
+ override fun setBlurTint(view: TrueSheetView, tint: String?) {
148
+ // iOS-specific prop - no-op on Android
149
+ view.setBlurTint(tint)
150
+ }
132
151
 
133
- view.setSizes(result.toArray())
152
+ @ReactProp(name = "edgeToEdgeFullScreen", defaultBoolean = false)
153
+ override fun setEdgeToEdgeFullScreen(view: TrueSheetView, edgeToEdgeFullScreen: Boolean) {
154
+ view.setEdgeToEdgeFullScreen(edgeToEdgeFullScreen)
134
155
  }
135
156
 
136
157
  companion object {
137
- const val TAG = "TrueSheetView"
158
+ const val REACT_CLASS = "TrueSheetView"
159
+ const val TAG_NAME = "TrueSheet"
138
160
  }
139
161
  }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired when the active detent changes
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class DetentChangeEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<DetentChangeEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topDetentChange"
24
+ const val REGISTRATION_NAME = "onDetentChange"
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired after the sheet dismissal is complete
9
+ */
10
+ class DidDismissEvent(surfaceId: Int, viewId: Int) : Event<DidDismissEvent>(surfaceId, viewId) {
11
+
12
+ override fun getEventName(): String = EVENT_NAME
13
+
14
+ override fun getEventData(): WritableMap = Arguments.createMap()
15
+
16
+ companion object {
17
+ const val EVENT_NAME = "topDidDismiss"
18
+ const val REGISTRATION_NAME = "onDidDismiss"
19
+ }
20
+ }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired after the sheet presentation is complete
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class DidPresentEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<DidPresentEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topDidPresent"
24
+ const val REGISTRATION_NAME = "onDidPresent"
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired when user starts dragging the sheet
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class DragBeginEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<DragBeginEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topDragBegin"
24
+ const val REGISTRATION_NAME = "onDragBegin"
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired continuously while user is dragging the sheet
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class DragChangeEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<DragChangeEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topDragChange"
24
+ const val REGISTRATION_NAME = "onDragChange"
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired when user stops dragging the sheet
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class DragEndEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<DragEndEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topDragEnd"
24
+ const val REGISTRATION_NAME = "onDragEnd"
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired when the sheet component is mounted and ready
9
+ */
10
+ class MountEvent(surfaceId: Int, viewId: Int) : Event<MountEvent>(surfaceId, viewId) {
11
+
12
+ override fun getEventName(): String = EVENT_NAME
13
+
14
+ override fun getEventData(): WritableMap = Arguments.createMap()
15
+
16
+ companion object {
17
+ const val EVENT_NAME = "topMount"
18
+ const val REGISTRATION_NAME = "onMount"
19
+ }
20
+ }
@@ -0,0 +1,32 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired continuously for position updates during drag and animation
9
+ * Payload: { index: number, position: number, transitioning: boolean }
10
+ */
11
+ class PositionChangeEvent(
12
+ surfaceId: Int,
13
+ viewId: Int,
14
+ private val index: Int,
15
+ private val position: Float,
16
+ private val transitioning: Boolean = false
17
+ ) : Event<PositionChangeEvent>(surfaceId, viewId) {
18
+
19
+ override fun getEventName(): String = EVENT_NAME
20
+
21
+ override fun getEventData(): WritableMap =
22
+ Arguments.createMap().apply {
23
+ putInt("index", index)
24
+ putDouble("position", position.toDouble())
25
+ putBoolean("transitioning", transitioning)
26
+ }
27
+
28
+ companion object {
29
+ const val EVENT_NAME = "topPositionChange"
30
+ const val REGISTRATION_NAME = "onPositionChange"
31
+ }
32
+ }
@@ -0,0 +1,27 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.PixelUtil
6
+ import com.facebook.react.uimanager.events.Event
7
+
8
+ /**
9
+ * Fired when the root view's size changes
10
+ * Payload: { width: number, height: number }
11
+ */
12
+ class SizeChangeEvent(surfaceId: Int, viewId: Int, private val width: Int, private val height: Int) :
13
+ Event<SizeChangeEvent>(surfaceId, viewId) {
14
+
15
+ override fun getEventName(): String = EVENT_NAME
16
+
17
+ override fun getEventData(): WritableMap =
18
+ Arguments.createMap().apply {
19
+ putDouble("width", PixelUtil.toDIPFromPixel(width.toFloat()).toDouble())
20
+ putDouble("height", PixelUtil.toDIPFromPixel(height.toFloat()).toDouble())
21
+ }
22
+
23
+ companion object {
24
+ const val EVENT_NAME = "topSizeChange"
25
+ const val REGISTRATION_NAME = "onSizeChange"
26
+ }
27
+ }
@@ -0,0 +1,20 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired before the sheet is dismissed
9
+ */
10
+ class WillDismissEvent(surfaceId: Int, viewId: Int) : Event<WillDismissEvent>(surfaceId, viewId) {
11
+
12
+ override fun getEventName(): String = EVENT_NAME
13
+
14
+ override fun getEventData(): WritableMap = Arguments.createMap()
15
+
16
+ companion object {
17
+ const val EVENT_NAME = "topWillDismiss"
18
+ const val REGISTRATION_NAME = "onWillDismiss"
19
+ }
20
+ }
@@ -0,0 +1,26 @@
1
+ package com.lodev09.truesheet.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ /**
8
+ * Fired before the sheet is presented
9
+ * Payload: { index: number, position: number }
10
+ */
11
+ class WillPresentEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
12
+ Event<WillPresentEvent>(surfaceId, viewId) {
13
+
14
+ override fun getEventName(): String = EVENT_NAME
15
+
16
+ override fun getEventData(): WritableMap =
17
+ Arguments.createMap().apply {
18
+ putInt("index", index)
19
+ putDouble("position", position.toDouble())
20
+ }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topWillPresent"
24
+ const val REGISTRATION_NAME = "onWillPresent"
25
+ }
26
+ }
@@ -1,24 +1,54 @@
1
- package com.lodev09.truesheet.core
1
+ package com.lodev09.truesheet.utils
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.os.Build
6
6
  import android.util.DisplayMetrics
7
+ import android.view.View
7
8
  import android.view.WindowInsets
8
9
  import android.view.WindowManager
9
- import com.facebook.react.bridge.Promise
10
10
  import com.facebook.react.bridge.ReactContext
11
- import com.facebook.react.uimanager.PixelUtil
12
11
 
13
- object Utils {
12
+ /**
13
+ * Utility object for screen dimension calculations
14
+ */
15
+ object ScreenUtils {
14
16
  @SuppressLint("DiscouragedApi")
15
17
  private fun getIdentifierHeight(context: ReactContext, name: String): Int =
16
18
  context.resources.getDimensionPixelSize(
17
19
  context.resources.getIdentifier(name, "dimen", "android")
18
20
  ).takeIf { it > 0 } ?: 0
19
21
 
22
+ /**
23
+ * Get the status bar height
24
+ *
25
+ * @param context React context
26
+ * @return Status bar height in pixels
27
+ */
28
+ fun getStatusBarHeight(context: ReactContext): Int {
29
+ // Modern approach using WindowInsets (API 30+)
30
+ 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
+ }
37
+ }
38
+
39
+ // Fallback to legacy approach for older APIs
40
+ return getIdentifierHeight(context, "status_bar_height")
41
+ }
42
+
43
+ /**
44
+ * Calculate the screen height
45
+ *
46
+ * @param context React context
47
+ * @param edgeToEdge Whether edge-to-edge mode is enabled
48
+ * @return Screen height in pixels
49
+ */
20
50
  @SuppressLint("InternalInsetResource", "DiscouragedApi")
21
- fun screenHeight(context: ReactContext, edgeToEdge: Boolean): Int {
51
+ fun getScreenHeight(context: ReactContext, edgeToEdge: Boolean): Int {
22
52
  val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
23
53
  val displayMetrics = DisplayMetrics()
24
54
 
@@ -29,7 +59,8 @@ object Utils {
29
59
  }
30
60
 
31
61
  val screenHeight = displayMetrics.heightPixels
32
- val statusBarHeight = getIdentifierHeight(context, "status_bar_height")
62
+ val statusBarHeight = getStatusBarHeight(context)
63
+
33
64
  val hasNavigationBar = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
34
65
  context.getSystemService(WindowManager::class.java)
35
66
  ?.currentWindowMetrics
@@ -57,16 +88,15 @@ object Utils {
57
88
  }
58
89
  }
59
90
 
60
- fun toDIP(value: Float): Float = PixelUtil.toDIPFromPixel(value)
61
- fun toPixel(value: Double): Float = PixelUtil.toPixelFromDIP(value)
62
-
63
- fun withPromise(promise: Promise, closure: () -> Any?) {
64
- try {
65
- val result = closure()
66
- promise.resolve(result)
67
- } catch (e: Throwable) {
68
- e.printStackTrace()
69
- promise.reject("Error", e.message, e.cause)
70
- }
91
+ /**
92
+ * Get the Y coordinate of a view in screen coordinates
93
+ *
94
+ * @param view The view to get screen Y coordinate for
95
+ * @return Y coordinate in screen space
96
+ */
97
+ fun getScreenY(view: View): Int {
98
+ val location = IntArray(2)
99
+ view.getLocationOnScreen(location)
100
+ return location[1]
71
101
  }
72
102
  }
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <!-- Custom BottomSheetDialog style with edge-to-edge enabled -->
4
+ <style name="TrueSheetEdgeToEdgeEnabledDialog" parent="Theme.Design.Light.BottomSheetDialog">
5
+ <item name="android:windowIsFloating">false</item>
6
+ <item name="enableEdgeToEdge">true</item>
7
+ </style>
8
+ </resources>
@@ -0,0 +1,24 @@
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
+ #pragma once
10
+
11
+ #ifdef RCT_NEW_ARCH_ENABLED
12
+
13
+ #include <react/renderer/components/TrueSheetSpec/ComponentDescriptors.h>
14
+
15
+ namespace facebook::react {
16
+
17
+ class TrueSheetComponentDescriptor final : public ConcreteComponentDescriptor<TrueSheetViewComponentDescriptor> {
18
+ public:
19
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
20
+ };
21
+
22
+ } // namespace facebook::react
23
+
24
+ #endif // RCT_NEW_ARCH_ENABLED