@lodev09/react-native-true-sheet 3.6.10 → 3.6.11
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.
- package/README.md +22 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +5 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +5 -2
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +1 -9
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +24 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ The true native bottom sheet experience for your React Native Apps. 💩
|
|
|
31
31
|
|
|
32
32
|
- React Native >= 0.76 (Expo SDK 52+)
|
|
33
33
|
- New Architecture enabled (default in RN 0.76+)
|
|
34
|
+
- Xcode 26.2 (strongly recommended for better library functionality)
|
|
34
35
|
|
|
35
36
|
### Expo
|
|
36
37
|
|
|
@@ -45,6 +46,27 @@ yarn add @lodev09/react-native-true-sheet
|
|
|
45
46
|
cd ios && pod install
|
|
46
47
|
```
|
|
47
48
|
|
|
49
|
+
### EAS Build (iOS)
|
|
50
|
+
|
|
51
|
+
When using [EAS Build](https://docs.expo.dev/build/introduction/) to build your iOS app, you must configure your `eas.json` to use a build image that includes Xcode 26.2. Use `"image": "latest"` or choose from the [available build images](https://docs.expo.dev/build-reference/infrastructure/#ios-server-images):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"build": {
|
|
56
|
+
"production": {
|
|
57
|
+
"ios": {
|
|
58
|
+
"image": "latest"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"development": {
|
|
62
|
+
"ios": {
|
|
63
|
+
"image": "latest"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
48
70
|
## Documentation
|
|
49
71
|
|
|
50
72
|
- [Example](example)
|
|
@@ -3,9 +3,11 @@ package com.lodev09.truesheet
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.view.View
|
|
5
5
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.facebook.react.uimanager.events.EventDispatcher
|
|
6
7
|
import com.facebook.react.views.view.ReactViewGroup
|
|
7
8
|
|
|
8
9
|
interface TrueSheetContainerViewDelegate {
|
|
10
|
+
val eventDispatcher: EventDispatcher?
|
|
9
11
|
fun containerViewContentDidChangeSize(width: Int, height: Int)
|
|
10
12
|
fun containerViewHeaderDidChangeSize(width: Int, height: Int)
|
|
11
13
|
fun containerViewFooterDidChangeSize(width: Int, height: Int)
|
|
@@ -32,6 +34,9 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
|
|
|
32
34
|
var headerHeight: Int = 0
|
|
33
35
|
var footerHeight: Int = 0
|
|
34
36
|
|
|
37
|
+
override val eventDispatcher: EventDispatcher?
|
|
38
|
+
get() = delegate?.eventDispatcher
|
|
39
|
+
|
|
35
40
|
init {
|
|
36
41
|
// Allow footer to position outside container bounds
|
|
37
42
|
clipChildren = false
|
|
@@ -11,10 +11,11 @@ import com.facebook.react.uimanager.events.EventDispatcher
|
|
|
11
11
|
import com.facebook.react.views.view.ReactViewGroup
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Delegate interface for footer view size changes
|
|
14
|
+
* Delegate interface for footer view size changes and event dispatching
|
|
15
15
|
*/
|
|
16
16
|
interface TrueSheetFooterViewDelegate {
|
|
17
17
|
fun footerViewDidChangeSize(width: Int, height: Int)
|
|
18
|
+
val eventDispatcher: EventDispatcher?
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -30,7 +31,9 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
30
31
|
RootView {
|
|
31
32
|
|
|
32
33
|
var delegate: TrueSheetFooterViewDelegate? = null
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
private val eventDispatcher: EventDispatcher?
|
|
36
|
+
get() = delegate?.eventDispatcher
|
|
34
37
|
|
|
35
38
|
private var lastWidth = 0
|
|
36
39
|
private var lastHeight = 0
|
|
@@ -42,7 +42,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
42
42
|
private val containerView: TrueSheetContainerView?
|
|
43
43
|
get() = viewController.getChildAt(0) as? TrueSheetContainerView
|
|
44
44
|
|
|
45
|
-
var eventDispatcher: EventDispatcher? = null
|
|
45
|
+
override var eventDispatcher: EventDispatcher? = null
|
|
46
46
|
|
|
47
47
|
// Initial present configuration (set by ViewManager before mount)
|
|
48
48
|
var initialDetentIndex: Int = -1
|
|
@@ -384,10 +384,6 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
384
384
|
override fun viewControllerWillPresent(index: Int, position: Float, detent: Float) {
|
|
385
385
|
val surfaceId = UIManagerHelper.getSurfaceId(this)
|
|
386
386
|
eventDispatcher?.dispatchEvent(WillPresentEvent(surfaceId, id, index, position, detent))
|
|
387
|
-
|
|
388
|
-
// Enable touch event dispatching to React Native while sheet is visible
|
|
389
|
-
viewController.eventDispatcher = eventDispatcher
|
|
390
|
-
containerView?.footerView?.eventDispatcher = eventDispatcher
|
|
391
387
|
}
|
|
392
388
|
|
|
393
389
|
override fun viewControllerDidPresent(index: Int, position: Float, detent: Float) {
|
|
@@ -398,10 +394,6 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
398
394
|
override fun viewControllerWillDismiss() {
|
|
399
395
|
val surfaceId = UIManagerHelper.getSurfaceId(this)
|
|
400
396
|
eventDispatcher?.dispatchEvent(WillDismissEvent(surfaceId, id))
|
|
401
|
-
|
|
402
|
-
// Disable touch event dispatching when sheet is dismissing
|
|
403
|
-
viewController.eventDispatcher = null
|
|
404
|
-
containerView?.footerView?.eventDispatcher = null
|
|
405
397
|
}
|
|
406
398
|
|
|
407
399
|
override fun viewControllerDidDismiss(hadParent: Boolean) {
|
|
@@ -45,6 +45,7 @@ import com.lodev09.truesheet.utils.ScreenUtils
|
|
|
45
45
|
data class DetentInfo(val index: Int, val position: Float)
|
|
46
46
|
|
|
47
47
|
interface TrueSheetViewControllerDelegate {
|
|
48
|
+
val eventDispatcher: EventDispatcher?
|
|
48
49
|
fun viewControllerWillPresent(index: Int, position: Float, detent: Float)
|
|
49
50
|
fun viewControllerDidPresent(index: Int, position: Float, detent: Float)
|
|
50
51
|
fun viewControllerWillDismiss()
|
|
@@ -155,9 +156,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
// Touch Dispatchers
|
|
158
|
-
internal var eventDispatcher: EventDispatcher? = null
|
|
159
159
|
private val jsTouchDispatcher = JSTouchDispatcher(this)
|
|
160
|
-
private
|
|
160
|
+
private val jsPointerDispatcher = JSPointerDispatcher(this)
|
|
161
|
+
|
|
162
|
+
private val eventDispatcher
|
|
163
|
+
get() = delegate?.eventDispatcher
|
|
161
164
|
|
|
162
165
|
// Detent Configuration
|
|
163
166
|
override var maxSheetHeight: Int? = null
|
|
@@ -284,14 +287,6 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
284
287
|
private val dimViews: List<TrueSheetDimView>
|
|
285
288
|
get() = listOfNotNull(dimView, parentDimView)
|
|
286
289
|
|
|
287
|
-
// =============================================================================
|
|
288
|
-
// MARK: - Initialization
|
|
289
|
-
// =============================================================================
|
|
290
|
-
|
|
291
|
-
init {
|
|
292
|
-
jsPointerDispatcher = JSPointerDispatcher(this)
|
|
293
|
-
}
|
|
294
|
-
|
|
295
290
|
// =============================================================================
|
|
296
291
|
// MARK: - Sheet Creation & Cleanup
|
|
297
292
|
// =============================================================================
|
|
@@ -1068,32 +1063,26 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1068
1063
|
}
|
|
1069
1064
|
}
|
|
1070
1065
|
|
|
1071
|
-
override fun handleException(t: Throwable) {
|
|
1072
|
-
reactContext.reactApplicationContext.handleException(RuntimeException(t))
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
1066
|
// =============================================================================
|
|
1076
|
-
// MARK: - Touch
|
|
1067
|
+
// MARK: - RootView Touch Handling
|
|
1077
1068
|
// =============================================================================
|
|
1078
1069
|
|
|
1079
1070
|
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
|
1080
|
-
// Footer needs special handling since it's positioned absolutely
|
|
1081
1071
|
val footer = containerView?.footerView
|
|
1082
|
-
if (footer != null && footer.
|
|
1072
|
+
if (footer != null && footer.isShown) {
|
|
1083
1073
|
val footerLocation = ScreenUtils.getScreenLocation(footer)
|
|
1084
|
-
val
|
|
1085
|
-
val
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
touchScreenY <= footerLocation[1] + footer.height
|
|
1074
|
+
val touchX = event.rawX.toInt()
|
|
1075
|
+
val touchY = event.rawY.toInt()
|
|
1076
|
+
|
|
1077
|
+
if (touchX >= footerLocation[0] &&
|
|
1078
|
+
touchX <= footerLocation[0] + footer.width &&
|
|
1079
|
+
touchY >= footerLocation[1] &&
|
|
1080
|
+
touchY <= footerLocation[1] + footer.height
|
|
1092
1081
|
) {
|
|
1093
1082
|
val localEvent = MotionEvent.obtain(event)
|
|
1094
1083
|
localEvent.setLocation(
|
|
1095
|
-
(
|
|
1096
|
-
(
|
|
1084
|
+
(touchX - footerLocation[0]).toFloat(),
|
|
1085
|
+
(touchY - footerLocation[1]).toFloat()
|
|
1097
1086
|
)
|
|
1098
1087
|
val handled = footer.dispatchTouchEvent(localEvent)
|
|
1099
1088
|
localEvent.recycle()
|
|
@@ -1106,7 +1095,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1106
1095
|
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
|
1107
1096
|
eventDispatcher?.let {
|
|
1108
1097
|
jsTouchDispatcher.handleTouchEvent(event, it, reactContext)
|
|
1109
|
-
jsPointerDispatcher
|
|
1098
|
+
jsPointerDispatcher.handleMotionEvent(event, it, true)
|
|
1110
1099
|
}
|
|
1111
1100
|
return super.onInterceptTouchEvent(event)
|
|
1112
1101
|
}
|
|
@@ -1114,35 +1103,35 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1114
1103
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
1115
1104
|
eventDispatcher?.let {
|
|
1116
1105
|
jsTouchDispatcher.handleTouchEvent(event, it, reactContext)
|
|
1117
|
-
jsPointerDispatcher
|
|
1106
|
+
jsPointerDispatcher.handleMotionEvent(event, it, false)
|
|
1118
1107
|
}
|
|
1119
1108
|
super.onTouchEvent(event)
|
|
1120
1109
|
return true
|
|
1121
1110
|
}
|
|
1122
1111
|
|
|
1123
1112
|
override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
|
|
1124
|
-
eventDispatcher?.let { jsPointerDispatcher
|
|
1113
|
+
eventDispatcher?.let { jsPointerDispatcher.handleMotionEvent(event, it, true) }
|
|
1125
1114
|
return super.onHoverEvent(event)
|
|
1126
1115
|
}
|
|
1127
1116
|
|
|
1128
1117
|
override fun onHoverEvent(event: MotionEvent): Boolean {
|
|
1129
|
-
eventDispatcher?.let { jsPointerDispatcher
|
|
1118
|
+
eventDispatcher?.let { jsPointerDispatcher.handleMotionEvent(event, it, false) }
|
|
1130
1119
|
return super.onHoverEvent(event)
|
|
1131
1120
|
}
|
|
1132
1121
|
|
|
1133
1122
|
override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
|
|
1134
1123
|
eventDispatcher?.let {
|
|
1135
1124
|
jsTouchDispatcher.onChildStartedNativeGesture(ev, it)
|
|
1136
|
-
jsPointerDispatcher
|
|
1125
|
+
jsPointerDispatcher.onChildStartedNativeGesture(childView, ev, it)
|
|
1137
1126
|
}
|
|
1138
1127
|
}
|
|
1139
1128
|
|
|
1140
1129
|
override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
|
|
1141
1130
|
eventDispatcher?.let { jsTouchDispatcher.onChildEndedNativeGesture(ev, it) }
|
|
1142
|
-
jsPointerDispatcher
|
|
1131
|
+
jsPointerDispatcher.onChildEndedNativeGesture()
|
|
1143
1132
|
}
|
|
1144
1133
|
|
|
1145
|
-
override fun
|
|
1146
|
-
|
|
1134
|
+
override fun handleException(t: Throwable) {
|
|
1135
|
+
reactContext.reactApplicationContext.handleException(RuntimeException(t))
|
|
1147
1136
|
}
|
|
1148
1137
|
}
|
package/package.json
CHANGED