@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,413 +0,0 @@
1
- package com.lodev09.truesheet
2
-
3
- import android.annotation.SuppressLint
4
- import android.graphics.Color
5
- import android.graphics.drawable.ShapeDrawable
6
- import android.graphics.drawable.shapes.RoundRectShape
7
- import android.view.View
8
- import android.view.ViewGroup
9
- import android.view.WindowManager
10
- import com.facebook.react.uimanager.ThemedReactContext
11
- import com.google.android.material.bottomsheet.BottomSheetBehavior
12
- import com.google.android.material.bottomsheet.BottomSheetDialog
13
- import com.lodev09.truesheet.core.KeyboardManager
14
- import com.lodev09.truesheet.core.RootSheetView
15
- import com.lodev09.truesheet.core.Utils
16
-
17
- data class SizeInfo(val index: Int, val value: Float)
18
-
19
- @SuppressLint("ClickableViewAccessibility")
20
- class TrueSheetDialog(private val reactContext: ThemedReactContext, private val rootSheetView: RootSheetView) :
21
- BottomSheetDialog(reactContext) {
22
-
23
- private var keyboardManager = KeyboardManager(reactContext)
24
- private var windowAnimation: Int = 0
25
-
26
- // First child of the rootSheetView
27
- private val containerView: ViewGroup?
28
- get() = if (rootSheetView.childCount > 0) {
29
- rootSheetView.getChildAt(0) as? ViewGroup
30
- } else {
31
- null
32
- }
33
-
34
- private val sheetContainerView: ViewGroup?
35
- get() = rootSheetView.parent?.let { it as? ViewGroup }
36
-
37
- /**
38
- * Specify whether the sheet background is dimmed.
39
- * Set to `false` to allow interaction with the background components.
40
- */
41
- var dimmed = true
42
-
43
- /**
44
- * The size index that the sheet should start to dim the background.
45
- * This is ignored if `dimmed` is set to `false`.
46
- */
47
- var dimmedIndex = 0
48
-
49
- /**
50
- * The maximum window height
51
- */
52
- var maxScreenHeight = 0
53
-
54
- var contentHeight = 0
55
- var footerHeight = 0
56
- var maxSheetHeight: Int? = null
57
-
58
- var edgeToEdge: Boolean = false
59
- set(value) {
60
- field = value
61
- maxScreenHeight = Utils.screenHeight(reactContext, value)
62
- }
63
-
64
- var dismissible: Boolean = true
65
- set(value) {
66
- field = value
67
- setCanceledOnTouchOutside(value)
68
- setCancelable(value)
69
-
70
- behavior.isHideable = value
71
- }
72
-
73
- var cornerRadius: Float = 0f
74
- var backgroundColor: Int = Color.WHITE
75
-
76
- // 1st child is the content view
77
- val contentView: ViewGroup?
78
- get() = containerView?.getChildAt(0) as? ViewGroup
79
-
80
- // 2nd child is the footer view
81
- val footerView: ViewGroup?
82
- get() = containerView?.getChildAt(1) as? ViewGroup
83
-
84
- var sizes: Array<Any> = arrayOf("medium", "large")
85
-
86
- init {
87
- setContentView(rootSheetView)
88
-
89
- sheetContainerView?.setBackgroundColor(backgroundColor)
90
- sheetContainerView?.clipToOutline = true
91
-
92
- // Setup window params to adjust layout based on Keyboard state
93
- window?.apply {
94
- // Store current windowAnimation value to toggle later
95
- windowAnimation = attributes.windowAnimations
96
- }
97
-
98
- // Update the usable sheet height
99
- maxScreenHeight = Utils.screenHeight(reactContext, edgeToEdge)
100
- }
101
-
102
- override fun getEdgeToEdgeEnabled(): Boolean = edgeToEdge || super.getEdgeToEdgeEnabled()
103
-
104
- override fun onStart() {
105
- super.onStart()
106
-
107
- if (edgeToEdge) {
108
- window?.apply {
109
- setFlags(
110
- WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
111
- WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
112
- )
113
-
114
- decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
115
- }
116
- }
117
- }
118
-
119
- /**
120
- * Setup background color and corner radius.
121
- */
122
- fun setupBackground() {
123
- val outerRadii = floatArrayOf(
124
- cornerRadius,
125
- cornerRadius,
126
- cornerRadius,
127
- cornerRadius,
128
- 0f,
129
- 0f,
130
- 0f,
131
- 0f
132
- )
133
-
134
- val background = ShapeDrawable(RoundRectShape(outerRadii, null, null))
135
-
136
- // Use current background color
137
- background.paint.color = backgroundColor
138
- sheetContainerView?.background = background
139
- }
140
-
141
- /**
142
- * Setup dimmed sheet.
143
- * `dimmedIndex` will further customize the dimming behavior.
144
- */
145
- fun setupDimmedBackground(sizeIndex: Int) {
146
- window?.apply {
147
- val view = findViewById<View>(com.google.android.material.R.id.touch_outside)
148
-
149
- if (dimmed && sizeIndex >= dimmedIndex) {
150
- // Remove touch listener
151
- view.setOnTouchListener(null)
152
-
153
- // Add the dimmed background
154
- setFlags(
155
- WindowManager.LayoutParams.FLAG_DIM_BEHIND,
156
- WindowManager.LayoutParams.FLAG_DIM_BEHIND
157
- )
158
-
159
- setCanceledOnTouchOutside(dismissible)
160
- } else {
161
- // Override the background touch and pass it to the components outside
162
- view.setOnTouchListener { v, event ->
163
- event.setLocation(event.rawX - v.x, event.rawY - v.y)
164
- reactContext.currentActivity?.dispatchTouchEvent(event)
165
- false
166
- }
167
-
168
- // Remove the dimmed background
169
- clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
170
-
171
- setCanceledOnTouchOutside(false)
172
- }
173
- }
174
- }
175
-
176
- fun resetAnimation() {
177
- window?.apply {
178
- setWindowAnimations(windowAnimation)
179
- }
180
- }
181
-
182
- /**
183
- * Present the sheet.
184
- */
185
- fun present(sizeIndex: Int, animated: Boolean = true) {
186
- setupDimmedBackground(sizeIndex)
187
- if (isShowing) {
188
- setStateForSizeIndex(sizeIndex)
189
- } else {
190
- configure()
191
- setStateForSizeIndex(sizeIndex)
192
-
193
- if (!animated) {
194
- // Disable animation
195
- window?.setWindowAnimations(0)
196
- }
197
-
198
- show()
199
- }
200
- }
201
-
202
- fun positionFooter() {
203
- footerView?.let { footer ->
204
- sheetContainerView?.let { container ->
205
- footer.y = (maxScreenHeight - container.top - footerHeight).toFloat()
206
- }
207
- }
208
- }
209
-
210
- /**
211
- * Set the state based for the given size index.
212
- */
213
- fun setStateForSizeIndex(index: Int) {
214
- behavior.state = getStateForSizeIndex(index)
215
- }
216
-
217
- /**
218
- * Get the height value based on the size config value.
219
- */
220
- private fun getSizeHeight(size: Any): Int {
221
- val height: Int =
222
- when (size) {
223
- is Double -> Utils.toPixel(size).toInt()
224
-
225
- is Int -> Utils.toPixel(size.toDouble()).toInt()
226
-
227
- is String -> {
228
- when (size) {
229
- "auto" -> contentHeight + footerHeight
230
-
231
- "large" -> maxScreenHeight
232
-
233
- "medium" -> (maxScreenHeight * 0.50).toInt()
234
-
235
- "small" -> (maxScreenHeight * 0.25).toInt()
236
-
237
- else -> {
238
- if (size.endsWith('%')) {
239
- val percent = size.trim('%').toDoubleOrNull()
240
- if (percent == null) {
241
- 0
242
- } else {
243
- ((percent / 100) * maxScreenHeight).toInt()
244
- }
245
- } else {
246
- val fixedHeight = size.toDoubleOrNull()
247
- if (fixedHeight == null) {
248
- 0
249
- } else {
250
- Utils.toPixel(fixedHeight).toInt()
251
- }
252
- }
253
- }
254
- }
255
- }
256
-
257
- else -> (maxScreenHeight * 0.5).toInt()
258
- }
259
-
260
- return maxSheetHeight?.let { minOf(height, it, maxScreenHeight) } ?: minOf(height, maxScreenHeight)
261
- }
262
-
263
- /**
264
- * Determines the state based from the given size index.
265
- */
266
- private fun getStateForSizeIndex(index: Int): Int {
267
- return when (sizes.size) {
268
- 1 -> {
269
- return BottomSheetBehavior.STATE_EXPANDED
270
- }
271
-
272
- 2 -> {
273
- when (index) {
274
- 0 -> BottomSheetBehavior.STATE_COLLAPSED
275
- 1 -> BottomSheetBehavior.STATE_EXPANDED
276
- else -> BottomSheetBehavior.STATE_HIDDEN
277
- }
278
- }
279
-
280
- 3 -> {
281
- when (index) {
282
- 0 -> BottomSheetBehavior.STATE_COLLAPSED
283
- 1 -> BottomSheetBehavior.STATE_HALF_EXPANDED
284
- 2 -> BottomSheetBehavior.STATE_EXPANDED
285
- else -> BottomSheetBehavior.STATE_HIDDEN
286
- }
287
- }
288
-
289
- else -> BottomSheetBehavior.STATE_HIDDEN
290
- }
291
- }
292
-
293
- /**
294
- * Handle keyboard state changes and adjust maxScreenHeight (sheet max height) accordingly.
295
- * Also update footer's Y position.
296
- */
297
- fun registerKeyboardManager() {
298
- keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardChangeListener {
299
- override fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?) {
300
- maxScreenHeight = when (isVisible) {
301
- true -> visibleHeight ?: 0
302
- else -> Utils.screenHeight(reactContext, edgeToEdge)
303
- }
304
-
305
- positionFooter()
306
- }
307
- })
308
- }
309
-
310
- fun setOnSizeChangeListener(listener: (w: Int, h: Int) -> Unit) {
311
- rootSheetView.sizeChangeListener = listener
312
- }
313
-
314
- /**
315
- * Remove keyboard listener.
316
- */
317
- fun unregisterKeyboardManager() {
318
- keyboardManager.unregisterKeyboardListener()
319
- }
320
-
321
- /**
322
- * Configure the sheet based from the size preference.
323
- */
324
- fun configure() {
325
- // Configure sheet sizes
326
- behavior.apply {
327
- skipCollapsed = false
328
- isFitToContents = true
329
-
330
- // m3 max width 640dp
331
- maxWidth = Utils.toPixel(640.0).toInt()
332
-
333
- when (sizes.size) {
334
- 1 -> {
335
- maxHeight = getSizeHeight(sizes[0])
336
- skipCollapsed = true
337
-
338
- if (sizes[0] == "auto") {
339
- // Force a layout update
340
- sheetContainerView?.let {
341
- val params = it.layoutParams
342
- params.height = maxHeight
343
- it.layoutParams = params
344
- }
345
- }
346
- }
347
-
348
- 2 -> {
349
- setPeekHeight(getSizeHeight(sizes[0]), isShowing)
350
- maxHeight = getSizeHeight(sizes[1])
351
- }
352
-
353
- 3 -> {
354
- // Enables half expanded
355
- isFitToContents = false
356
-
357
- setPeekHeight(getSizeHeight(sizes[0]), isShowing)
358
-
359
- halfExpandedRatio = minOf(getSizeHeight(sizes[1]).toFloat() / maxScreenHeight.toFloat(), 1.0f)
360
- maxHeight = getSizeHeight(sizes[2])
361
- }
362
- }
363
- }
364
- }
365
-
366
- /**
367
- * Get the SizeInfo data by state.
368
- */
369
- fun getSizeInfoForState(state: Int): SizeInfo? =
370
- when (sizes.size) {
371
- 1 -> {
372
- when (state) {
373
- BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight.toFloat()))
374
- BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight.toFloat()))
375
- else -> null
376
- }
377
- }
378
-
379
- 2 -> {
380
- when (state) {
381
- BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight.toFloat()))
382
- BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight.toFloat()))
383
- else -> null
384
- }
385
- }
386
-
387
- 3 -> {
388
- when (state) {
389
- BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight.toFloat()))
390
-
391
- BottomSheetBehavior.STATE_HALF_EXPANDED -> {
392
- val height = behavior.halfExpandedRatio * maxScreenHeight
393
- SizeInfo(1, Utils.toDIP(height))
394
- }
395
-
396
- BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight.toFloat()))
397
-
398
- else -> null
399
- }
400
- }
401
-
402
- else -> null
403
- }
404
-
405
- /**
406
- * Get SizeInfo data for given size index.
407
- */
408
- fun getSizeInfoForIndex(index: Int) = getSizeInfoForState(getStateForSizeIndex(index)) ?: SizeInfo(0, 0f)
409
-
410
- companion object {
411
- const val TAG = "TrueSheetView"
412
- }
413
- }
@@ -1,22 +0,0 @@
1
- package com.lodev09.truesheet
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
- class TrueSheetEvent(surfaceId: Int, viewId: Int, private val name: String, private val data: WritableMap?) :
8
- Event<TrueSheetEvent>(surfaceId, viewId) {
9
- override fun getEventName() = name
10
- override fun getEventData(): WritableMap = data ?: Arguments.createMap()
11
-
12
- companion object {
13
- const val MOUNT = "topMount"
14
- const val PRESENT = "topPresent"
15
- const val DISMISS = "topDismiss"
16
- const val SIZE_CHANGE = "topSizeChange"
17
- const val DRAG_BEGIN = "topDragBegin"
18
- const val DRAG_CHANGE = "topDragChange"
19
- const val DRAG_END = "topDragEnd"
20
- const val CONTAINER_SIZE_CHANGE = "topContainerSizeChange"
21
- }
22
- }
@@ -1,63 +0,0 @@
1
- package com.lodev09.truesheet
2
-
3
- import android.util.Log
4
- import com.facebook.react.bridge.Promise
5
- import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.bridge.ReactContextBaseJavaModule
7
- import com.facebook.react.bridge.ReactMethod
8
- import com.facebook.react.bridge.UiThreadUtil
9
- import com.facebook.react.module.annotations.ReactModule
10
- import com.facebook.react.uimanager.UIManagerHelper
11
- import com.lodev09.truesheet.core.Utils
12
-
13
- @ReactModule(name = TrueSheetViewModule.TAG)
14
- class TrueSheetViewModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
15
- override fun getName(): String = TAG
16
-
17
- private fun withTrueSheetView(tag: Int, closure: (trueSheetView: TrueSheetView) -> Unit) {
18
- UiThreadUtil.runOnUiThread {
19
- try {
20
- val manager = UIManagerHelper.getUIManagerForReactTag(reactApplicationContext, tag)
21
- val view = manager?.resolveView(tag)
22
- if (view == null) {
23
- Log.d(TAG, "Tag $tag not found")
24
- return@runOnUiThread
25
- }
26
-
27
- if (view is TrueSheetView) {
28
- closure(view)
29
- } else {
30
- Log.d(TAG, "Tag $tag does not match")
31
- }
32
- } catch (e: Exception) {
33
- e.printStackTrace()
34
- }
35
- }
36
- }
37
-
38
- @ReactMethod
39
- fun present(tag: Int, index: Int, promise: Promise) {
40
- withTrueSheetView(tag) {
41
- it.present(index) {
42
- Utils.withPromise(promise) {
43
- return@withPromise null
44
- }
45
- }
46
- }
47
- }
48
-
49
- @ReactMethod
50
- fun dismiss(tag: Int, promise: Promise) {
51
- withTrueSheetView(tag) {
52
- it.dismiss {
53
- Utils.withPromise(promise) {
54
- return@withPromise null
55
- }
56
- }
57
- }
58
- }
59
-
60
- companion object {
61
- const val TAG = "TrueSheetView"
62
- }
63
- }
@@ -1,58 +0,0 @@
1
- package com.lodev09.truesheet.core
2
-
3
- import android.content.Context
4
- import android.view.View
5
- import android.view.ViewTreeObserver.OnGlobalLayoutListener
6
- import android.view.inputmethod.InputMethodManager
7
- import com.facebook.react.bridge.ReactContext
8
-
9
- class KeyboardManager(reactContext: ReactContext) {
10
- interface OnKeyboardChangeListener {
11
- fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?)
12
- }
13
-
14
- private var contentView: View? = null
15
- private var onGlobalLayoutListener: OnGlobalLayoutListener? = null
16
- private var isKeyboardVisible = false
17
-
18
- init {
19
- val activity = reactContext.currentActivity
20
- contentView = activity?.findViewById(android.R.id.content)
21
- }
22
-
23
- fun registerKeyboardListener(listener: OnKeyboardChangeListener?) {
24
- contentView?.apply {
25
- unregisterKeyboardListener()
26
-
27
- onGlobalLayoutListener = object : OnGlobalLayoutListener {
28
- private var previousHeight = 0
29
-
30
- override fun onGlobalLayout() {
31
- val heightDiff = rootView.height - height
32
- if (heightDiff > Utils.toPixel(200.0)) {
33
- // Will ask InputMethodManager.isAcceptingText() to detect if keyboard appeared or not.
34
- val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
35
- if (height != previousHeight && inputManager.isAcceptingText()) {
36
- listener?.onKeyboardStateChange(true, height)
37
-
38
- previousHeight = height
39
- isKeyboardVisible = true
40
- }
41
- } else if (isKeyboardVisible) {
42
- listener?.onKeyboardStateChange(false, null)
43
- previousHeight = 0
44
- isKeyboardVisible = false
45
- }
46
- }
47
- }
48
-
49
- getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener)
50
- }
51
- }
52
-
53
- fun unregisterKeyboardListener() {
54
- onGlobalLayoutListener?.let {
55
- contentView?.getViewTreeObserver()?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
56
- }
57
- }
58
- }
@@ -1,102 +0,0 @@
1
- package com.lodev09.truesheet.core
2
-
3
- import android.annotation.SuppressLint
4
- import android.content.Context
5
- import android.view.MotionEvent
6
- import android.view.View
7
- import com.facebook.react.config.ReactFeatureFlags
8
- import com.facebook.react.uimanager.JSPointerDispatcher
9
- import com.facebook.react.uimanager.JSTouchDispatcher
10
- import com.facebook.react.uimanager.RootView
11
- import com.facebook.react.uimanager.ThemedReactContext
12
- import com.facebook.react.uimanager.events.EventDispatcher
13
- import com.facebook.react.views.view.ReactViewGroup
14
-
15
- /**
16
- * RootSheetView is the ViewGroup which contains all the children of a Modal. It gets all
17
- * child information forwarded from TrueSheetView and uses that to create children. It is
18
- * also responsible for acting as a RootView and handling touch events. It does this the same way
19
- * as ReactRootView.
20
- *
21
- *
22
- * To get layout to work properly, we need to layout all the elements within the Modal as if
23
- * they can fill the entire window. To do that, we need to explicitly set the styleWidth and
24
- * styleHeight on the LayoutShadowNode to be the window size. This is done through the
25
- * UIManagerModule, and will then cause the children to layout as if they can fill the window.
26
- */
27
- class RootSheetView(private val context: Context?) :
28
- ReactViewGroup(context),
29
- RootView {
30
- private var viewWidth = 0
31
- private var viewHeight = 0
32
-
33
- private val jSTouchDispatcher = JSTouchDispatcher(this)
34
- private var jSPointerDispatcher: JSPointerDispatcher? = null
35
-
36
- var sizeChangeListener: ((w: Int, h: Int) -> Unit)? = null
37
- var eventDispatcher: EventDispatcher? = null
38
-
39
- private val reactContext: ThemedReactContext
40
- get() = context as ThemedReactContext
41
-
42
- init {
43
- if (ReactFeatureFlags.dispatchPointerEvents) {
44
- jSPointerDispatcher = JSPointerDispatcher(this)
45
- }
46
- }
47
-
48
- override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
49
- super.onSizeChanged(w, h, oldw, oldh)
50
-
51
- viewWidth = w
52
- viewHeight = h
53
-
54
- sizeChangeListener?.let { it(viewWidth, viewHeight) }
55
- }
56
-
57
- override fun handleException(t: Throwable) {
58
- reactContext.reactApplicationContext.handleException(RuntimeException(t))
59
- }
60
-
61
- override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
62
- eventDispatcher?.let { eventDispatcher ->
63
- jSTouchDispatcher.handleTouchEvent(event, eventDispatcher, reactContext)
64
- jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
65
- }
66
- return super.onInterceptTouchEvent(event)
67
- }
68
-
69
- @SuppressLint("ClickableViewAccessibility")
70
- override fun onTouchEvent(event: MotionEvent): Boolean {
71
- eventDispatcher?.let { eventDispatcher ->
72
- jSTouchDispatcher.handleTouchEvent(event, eventDispatcher, reactContext)
73
- jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
74
- }
75
- super.onTouchEvent(event)
76
- // In case when there is no children interested in handling touch event, we return true from
77
- // the root view in order to receive subsequent events related to that gesture
78
- return true
79
- }
80
-
81
- override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
82
- eventDispatcher?.let { jSPointerDispatcher?.handleMotionEvent(event, it, true) }
83
- return super.onHoverEvent(event)
84
- }
85
-
86
- override fun onHoverEvent(event: MotionEvent): Boolean {
87
- eventDispatcher?.let { jSPointerDispatcher?.handleMotionEvent(event, it, false) }
88
- return super.onHoverEvent(event)
89
- }
90
-
91
- override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
92
- eventDispatcher?.let { eventDispatcher ->
93
- jSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
94
- jSPointerDispatcher?.onChildStartedNativeGesture(childView, ev, eventDispatcher)
95
- }
96
- }
97
-
98
- override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
99
- eventDispatcher?.let { jSTouchDispatcher.onChildEndedNativeGesture(ev, it) }
100
- jSPointerDispatcher?.onChildEndedNativeGesture()
101
- }
102
- }