@lodev09/react-native-true-sheet 3.0.0-beta.7 → 3.0.0-beta.8

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 (35) hide show
  1. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +51 -49
  2. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +10 -18
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +76 -20
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +21 -0
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +1 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +81 -147
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +303 -409
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +2 -4
  10. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +116 -0
  11. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +33 -5
  12. package/ios/TrueSheetContainerView.h +20 -2
  13. package/ios/TrueSheetContainerView.mm +61 -14
  14. package/ios/TrueSheetContentView.h +4 -2
  15. package/ios/TrueSheetContentView.mm +29 -72
  16. package/ios/TrueSheetFooterView.mm +2 -2
  17. package/ios/TrueSheetHeaderView.h +29 -0
  18. package/ios/TrueSheetHeaderView.mm +60 -0
  19. package/ios/TrueSheetView.mm +178 -232
  20. package/ios/TrueSheetViewController.h +1 -2
  21. package/ios/TrueSheetViewController.mm +126 -236
  22. package/ios/utils/LayoutUtil.h +2 -1
  23. package/ios/utils/LayoutUtil.mm +14 -1
  24. package/lib/module/TrueSheet.js +10 -2
  25. package/lib/module/TrueSheet.js.map +1 -1
  26. package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  27. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  28. package/lib/typescript/src/TrueSheet.types.d.ts +9 -9
  29. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  30. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
  31. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
  32. package/package.json +4 -1
  33. package/src/TrueSheet.tsx +10 -0
  34. package/src/TrueSheet.types.ts +10 -11
  35. package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
@@ -6,29 +6,25 @@ import androidx.core.view.isNotEmpty
6
6
  import com.facebook.react.uimanager.ThemedReactContext
7
7
  import com.facebook.react.views.view.ReactViewGroup
8
8
 
9
- /**
10
- * Delegate interface for container view changes
11
- */
12
9
  interface TrueSheetContainerViewDelegate {
13
10
  fun containerViewContentDidChangeSize(width: Int, height: Int)
11
+ fun containerViewHeaderDidChangeSize(width: Int, height: Int)
14
12
  fun containerViewFooterDidChangeSize(width: Int, height: Int)
15
13
  }
16
14
 
17
15
  /**
18
- * Container view that manages the bottom sheet content and holds content and footer views.
19
- * Simplified to be a lightweight content manager - events are now handled via dialog delegate.
16
+ * Container view that manages the sheet's content, header, and footer views.
17
+ * Size changes are forwarded to the delegate for sheet reconfiguration.
20
18
  */
21
19
  @SuppressLint("ViewConstructor")
22
- class TrueSheetContainerView(private val reactContext: ThemedReactContext) :
20
+ class TrueSheetContainerView(reactContext: ThemedReactContext) :
23
21
  ReactViewGroup(reactContext),
24
22
  TrueSheetContentViewDelegate,
23
+ TrueSheetHeaderViewDelegate,
25
24
  TrueSheetFooterViewDelegate {
26
25
 
27
26
  var delegate: TrueSheetContainerViewDelegate? = null
28
27
 
29
- /**
30
- * Reference to content view (first child)
31
- */
32
28
  val contentView: TrueSheetContentView?
33
29
  get() = if (isNotEmpty() && getChildAt(0) is TrueSheetContentView) {
34
30
  getChildAt(0) as TrueSheetContentView
@@ -36,30 +32,30 @@ class TrueSheetContainerView(private val reactContext: ThemedReactContext) :
36
32
  null
37
33
  }
38
34
 
39
- /**
40
- * Reference to footer view (second child)
41
- */
42
- val footerView: TrueSheetFooterView?
43
- get() = if (childCount > 1 && getChildAt(1) is TrueSheetFooterView) {
44
- getChildAt(1) as TrueSheetFooterView
45
- } else {
46
- null
35
+ val headerView: TrueSheetHeaderView?
36
+ get() {
37
+ for (i in 0 until childCount) {
38
+ val child = getChildAt(i)
39
+ if (child is TrueSheetHeaderView) return child
40
+ }
41
+ return null
47
42
  }
48
43
 
49
- /**
50
- * The content view height
51
- */
52
- val contentHeight: Int
53
- get() = contentView?.height ?: 0
44
+ val footerView: TrueSheetFooterView?
45
+ get() {
46
+ for (i in 0 until childCount) {
47
+ val child = getChildAt(i)
48
+ if (child is TrueSheetFooterView) return child
49
+ }
50
+ return null
51
+ }
54
52
 
55
- /**
56
- * The footer view height
57
- */
58
- val footerHeight: Int
59
- get() = footerView?.height ?: 0
53
+ var contentHeight: Int = 0
54
+ var headerHeight: Int = 0
55
+ var footerHeight: Int = 0
60
56
 
61
57
  init {
62
- // Container should not clip children to allow footer to position absolutely
58
+ // Allow footer to position outside container bounds
63
59
  clipChildren = false
64
60
  clipToPadding = false
65
61
  }
@@ -67,42 +63,48 @@ class TrueSheetContainerView(private val reactContext: ThemedReactContext) :
67
63
  override fun addView(child: View?, index: Int) {
68
64
  super.addView(child, index)
69
65
 
70
- // Set up delegate when content view is added
71
- if (child is TrueSheetContentView) {
72
- child.delegate = this
73
- }
74
-
75
- // Set up delegate when footer view is added
76
- if (child is TrueSheetFooterView) {
77
- child.delegate = this
66
+ when (child) {
67
+ is TrueSheetContentView -> child.delegate = this
68
+ is TrueSheetHeaderView -> child.delegate = this
69
+ is TrueSheetFooterView -> child.delegate = this
78
70
  }
79
71
  }
80
72
 
81
- override fun removeView(view: View?) {
82
- // Clean up delegate when content view is removed
83
- if (view is TrueSheetContentView) {
84
- view.delegate = null
85
- }
73
+ override fun removeViewAt(index: Int) {
74
+ val view = getChildAt(index)
75
+
76
+ when (view) {
77
+ is TrueSheetContentView -> view.delegate = null
78
+
79
+ is TrueSheetHeaderView -> {
80
+ view.delegate = null
81
+ headerViewDidChangeSize(0, 0)
82
+ }
86
83
 
87
- // Clean up delegate when footer view is removed
88
- if (view is TrueSheetFooterView) {
89
- view.delegate = null
84
+ is TrueSheetFooterView -> view.delegate = null
90
85
  }
91
86
 
92
- super.removeView(view)
87
+ super.removeViewAt(index)
93
88
  }
94
89
 
95
- // ==================== TrueSheetContentViewDelegate Implementation ====================
90
+ // ==================== Delegate Implementations ====================
96
91
 
97
92
  override fun contentViewDidChangeSize(width: Int, height: Int) {
98
- // Forward content size changes to controller for sheet resizing
93
+ contentHeight = height
99
94
  delegate?.containerViewContentDidChangeSize(width, height)
100
95
  }
101
96
 
102
- // ==================== TrueSheetFooterViewDelegate Implementation ====================
97
+ override fun headerViewDidChangeSize(width: Int, height: Int) {
98
+ headerHeight = height
99
+ delegate?.containerViewHeaderDidChangeSize(width, height)
100
+ }
103
101
 
104
102
  override fun footerViewDidChangeSize(width: Int, height: Int) {
105
- // Forward footer size changes to host view for repositioning
103
+ footerHeight = height
106
104
  delegate?.containerViewFooterDidChangeSize(width, height)
107
105
  }
106
+
107
+ companion object {
108
+ const val TAG_NAME = "TrueSheet"
109
+ }
108
110
  }
@@ -22,25 +22,17 @@ class TrueSheetContentView(context: ThemedReactContext) : ReactViewGroup(context
22
22
  private var lastWidth = 0
23
23
  private var lastHeight = 0
24
24
 
25
- override fun onLayout(
26
- changed: Boolean,
27
- left: Int,
28
- top: Int,
29
- right: Int,
30
- bottom: Int
31
- ) {
32
- super.onLayout(changed, left, top, right, bottom)
25
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
26
+ super.onSizeChanged(w, h, oldw, oldh)
33
27
 
34
- // Notify delegate when content size changes
35
- val newWidth = right - left
36
- val newHeight = bottom - top
37
-
38
- if (newWidth != lastWidth || newHeight != lastHeight) {
39
- lastWidth = newWidth
40
- lastHeight = newHeight
41
-
42
- // Notify delegate of size change
43
- delegate?.contentViewDidChangeSize(newWidth, newHeight)
28
+ if (w != lastWidth || h != lastHeight) {
29
+ lastWidth = w
30
+ lastHeight = h
31
+ delegate?.contentViewDidChangeSize(w, h)
44
32
  }
45
33
  }
34
+
35
+ companion object {
36
+ const val TAG_NAME = "TrueSheet"
37
+ }
46
38
  }
@@ -1,7 +1,13 @@
1
1
  package com.lodev09.truesheet
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.view.MotionEvent
5
+ import android.view.View
6
+ import com.facebook.react.uimanager.JSPointerDispatcher
7
+ import com.facebook.react.uimanager.JSTouchDispatcher
8
+ import com.facebook.react.uimanager.RootView
4
9
  import com.facebook.react.uimanager.ThemedReactContext
10
+ import com.facebook.react.uimanager.events.EventDispatcher
5
11
  import com.facebook.react.views.view.ReactViewGroup
6
12
 
7
13
  /**
@@ -15,33 +21,83 @@ interface TrueSheetFooterViewDelegate {
15
21
  * Footer view that holds the footer content
16
22
  * This is the second child of TrueSheetContainerView
17
23
  * Positioned absolutely at the bottom of the sheet
24
+ *
25
+ * Implements RootView to handle touch events when positioned outside parent bounds.
18
26
  */
19
27
  @SuppressLint("ViewConstructor")
20
- class TrueSheetFooterView(context: ThemedReactContext) : ReactViewGroup(context) {
28
+ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
29
+ ReactViewGroup(reactContext),
30
+ RootView {
31
+
21
32
  var delegate: TrueSheetFooterViewDelegate? = null
33
+ var eventDispatcher: EventDispatcher? = null
22
34
 
23
35
  private var lastWidth = 0
24
36
  private var lastHeight = 0
25
37
 
26
- override fun onLayout(
27
- changed: Boolean,
28
- left: Int,
29
- top: Int,
30
- right: Int,
31
- bottom: Int
32
- ) {
33
- super.onLayout(changed, left, top, right, bottom)
34
-
35
- // Notify delegate when footer size changes
36
- val newWidth = right - left
37
- val newHeight = bottom - top
38
-
39
- if (newWidth != lastWidth || newHeight != lastHeight) {
40
- lastWidth = newWidth
41
- lastHeight = newHeight
42
-
43
- // Notify delegate of size change
44
- delegate?.footerViewDidChangeSize(newWidth, newHeight)
38
+ private val jsTouchDispatcher = JSTouchDispatcher(this)
39
+ private var jsPointerDispatcher: JSPointerDispatcher? = null
40
+
41
+ init {
42
+ jsPointerDispatcher = JSPointerDispatcher(this)
43
+ }
44
+
45
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
46
+ super.onSizeChanged(w, h, oldw, oldh)
47
+
48
+ if (w != lastWidth || h != lastHeight) {
49
+ lastWidth = w
50
+ lastHeight = h
51
+ delegate?.footerViewDidChangeSize(w, h)
45
52
  }
46
53
  }
54
+
55
+ // ==================== RootView Implementation ====================
56
+
57
+ override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
58
+ eventDispatcher?.let { dispatcher ->
59
+ jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
60
+ jsPointerDispatcher?.handleMotionEvent(event, dispatcher, true)
61
+ }
62
+ return super.onInterceptTouchEvent(event)
63
+ }
64
+
65
+ override fun onTouchEvent(event: MotionEvent): Boolean {
66
+ eventDispatcher?.let { dispatcher ->
67
+ jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
68
+ jsPointerDispatcher?.handleMotionEvent(event, dispatcher, false)
69
+ }
70
+ super.onTouchEvent(event)
71
+ return true
72
+ }
73
+
74
+ override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
75
+ eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, true) }
76
+ return super.onHoverEvent(event)
77
+ }
78
+
79
+ override fun onHoverEvent(event: MotionEvent): Boolean {
80
+ eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, false) }
81
+ return super.onHoverEvent(event)
82
+ }
83
+
84
+ override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
85
+ eventDispatcher?.let { dispatcher ->
86
+ jsTouchDispatcher.onChildStartedNativeGesture(ev, dispatcher)
87
+ jsPointerDispatcher?.onChildStartedNativeGesture(childView, ev, dispatcher)
88
+ }
89
+ }
90
+
91
+ override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
92
+ eventDispatcher?.let { jsTouchDispatcher.onChildEndedNativeGesture(ev, it) }
93
+ jsPointerDispatcher?.onChildEndedNativeGesture()
94
+ }
95
+
96
+ override fun handleException(t: Throwable) {
97
+ reactContext.reactApplicationContext.handleException(RuntimeException(t))
98
+ }
99
+
100
+ companion object {
101
+ const val TAG_NAME = "TrueSheet"
102
+ }
47
103
  }
@@ -0,0 +1,38 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import android.annotation.SuppressLint
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.views.view.ReactViewGroup
6
+
7
+ /**
8
+ * Delegate interface for header view size changes
9
+ */
10
+ interface TrueSheetHeaderViewDelegate {
11
+ fun headerViewDidChangeSize(width: Int, height: Int)
12
+ }
13
+
14
+ /**
15
+ * Header view that holds the header content
16
+ * Positioned at the top of the sheet content area
17
+ */
18
+ @SuppressLint("ViewConstructor")
19
+ class TrueSheetHeaderView(context: ThemedReactContext) : ReactViewGroup(context) {
20
+ var delegate: TrueSheetHeaderViewDelegate? = null
21
+
22
+ private var lastWidth = 0
23
+ private var lastHeight = 0
24
+
25
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
26
+ super.onSizeChanged(w, h, oldw, oldh)
27
+
28
+ if (w != lastWidth || h != lastHeight) {
29
+ lastWidth = w
30
+ lastHeight = h
31
+ delegate?.headerViewDidChangeSize(w, h)
32
+ }
33
+ }
34
+
35
+ companion object {
36
+ const val TAG_NAME = "TrueSheet"
37
+ }
38
+ }
@@ -0,0 +1,21 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.uimanager.ViewGroupManager
6
+
7
+ /**
8
+ * ViewManager for TrueSheetHeaderView
9
+ * Manages the header area of the sheet
10
+ */
11
+ @ReactModule(name = TrueSheetHeaderViewManager.REACT_CLASS)
12
+ class TrueSheetHeaderViewManager : ViewGroupManager<TrueSheetHeaderView>() {
13
+
14
+ override fun getName(): String = REACT_CLASS
15
+
16
+ override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetHeaderView = TrueSheetHeaderView(reactContext)
17
+
18
+ companion object {
19
+ const val REACT_CLASS = "TrueSheetHeaderView"
20
+ }
21
+ }
@@ -39,6 +39,7 @@ class TrueSheetPackage : TurboReactPackage() {
39
39
  TrueSheetViewManager(),
40
40
  TrueSheetContainerViewManager(),
41
41
  TrueSheetContentViewManager(),
42
+ TrueSheetHeaderViewManager(),
42
43
  TrueSheetFooterViewManager()
43
44
  )
44
45
  }