@lodev09/react-native-true-sheet 3.5.1-beta.4 → 3.5.1-beta.5

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.
@@ -66,12 +66,11 @@ interface TrueSheetViewControllerDelegate {
66
66
  // =============================================================================
67
67
 
68
68
  /**
69
- * Manages the bottom sheet using CoordinatorLayout + BottomSheetBehavior.
69
+ * Controls the presentation and behavior of a bottom sheet.
70
70
  *
71
- * This approach keeps the sheet in the same activity window (no separate dialog window),
72
- * which allows touch events to pass through to underlying views when the sheet is not
73
- * covering them. This solves the touch lag issue when sheets are presented over
74
- * interactive components like Maps.
71
+ * Uses CoordinatorLayout with BottomSheetBehavior to manage the sheet within the activity window,
72
+ * enabling touch pass-through to underlying views. Handles detent configuration, drag interactions,
73
+ * keyboard avoidance, dimmed backgrounds, back button, and lifecycle events for stacked sheets.
75
74
  */
76
75
  @SuppressLint("ClickableViewAccessibility", "ViewConstructor")
77
76
  class TrueSheetViewController(private val reactContext: ThemedReactContext) :
@@ -89,6 +88,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
89
88
  private const val DEFAULT_CORNER_RADIUS = 16 // dp
90
89
  private const val TRANSLATE_ANIMATION_DURATION = 200L
91
90
  private const val DISMISS_DURATION = 200L
91
+ private const val MODAL_FADE_DURATION = 150L
92
92
  }
93
93
 
94
94
  // =============================================================================
@@ -190,6 +190,9 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
190
190
  if (isPresented) sheetView?.setupGrabber()
191
191
  }
192
192
 
193
+ val isDimmedAtCurrentDetent: Boolean
194
+ get() = dimmed && currentDetentIndex >= dimmedDetentIndex
195
+
193
196
  // =============================================================================
194
197
  // MARK: - Computed Properties
195
198
  // =============================================================================
@@ -336,9 +339,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
336
339
  backCallback = object : OnBackPressedCallback(true) {
337
340
  override fun handleOnBackPressed() {
338
341
  delegate?.viewControllerDidBackPress()
339
- if (dismissible) {
340
- dismiss(animated = true)
341
- }
342
+ dismissOrCollapseToLowest()
342
343
  }
343
344
  }
344
345
 
@@ -366,26 +367,26 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
366
367
  // =============================================================================
367
368
 
368
369
  override fun dimViewDidTap() {
369
- val hostView = delegate as? TrueSheetView
370
- if (hostView == null) {
371
- RNLog.e(reactContext, "TrueSheet: Expected delegate to be TrueSheetView")
372
- return
373
- }
370
+ val hostView = delegate as? TrueSheetView ?: return
371
+
372
+ val children = TrueSheetStackManager.getSheetsAbove(hostView)
373
+ val topmostChild = children.firstOrNull()?.viewController
374
374
 
375
- // If there's a child sheet on top, handle it instead
376
- val topmostChild = TrueSheetStackManager.getSheetsAbove(hostView).firstOrNull()
377
- if (topmostChild != null) {
378
- if (topmostChild.viewController.dismissible) {
379
- topmostChild.viewController.dismiss(animated = true)
375
+ // If topmost child is dimmed, only handle that child
376
+ if (topmostChild?.isDimmedAtCurrentDetent == true) {
377
+ if (topmostChild.dismissible) {
378
+ topmostChild.dismiss(animated = true)
380
379
  }
381
380
  return
382
381
  }
383
382
 
384
- if (dismissible) {
385
- dismiss(animated = true)
386
- } else if (parentSheetView == null && currentDetentIndex > 0) {
387
- setStateForDetentIndex(0)
383
+ // Pass through to parent - dismiss all if possible
384
+ val allDismissible = dismissible && children.all { it.viewController.dismissible }
385
+ if (allDismissible) {
386
+ children.forEach { it.viewController.dismiss(animated = true) }
388
387
  }
388
+
389
+ dismissOrCollapseToLowest()
389
390
  }
390
391
 
391
392
  // =============================================================================
@@ -535,14 +536,28 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
535
536
  private fun hideForModal() {
536
537
  isSheetVisible = false
537
538
  wasHiddenByModal = true
538
- dimViews.forEach { it.alpha = 0f }
539
- setSheetVisibility(false)
540
- parentSheetView?.viewController?.hideForModal()
539
+
540
+ val sheet = sheetView ?: run {
541
+ setSheetVisibility(false)
542
+ parentSheetView?.viewController?.hideForModal()
543
+ return
544
+ }
545
+
546
+ dimViews.forEach { it.animate().alpha(0f).setDuration(MODAL_FADE_DURATION).start() }
547
+ sheet.animate()
548
+ .alpha(0f)
549
+ .setDuration(MODAL_FADE_DURATION)
550
+ .withEndAction {
551
+ setSheetVisibility(false)
552
+ parentSheetView?.viewController?.hideForModal()
553
+ }
554
+ .start()
541
555
  }
542
556
 
543
557
  private fun showAfterModal() {
544
558
  isSheetVisible = true
545
559
  setSheetVisibility(true)
560
+ sheetView?.alpha = 1f
546
561
  updateDimAmount(animated = true)
547
562
  }
548
563
 
@@ -659,6 +674,14 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
659
674
  }
660
675
  }
661
676
 
677
+ private fun dismissOrCollapseToLowest() {
678
+ if (dismissible) {
679
+ dismiss(animated = true)
680
+ } else if (parentSheetView == null && isDimmedAtCurrentDetent && dimmedDetentIndex > 0) {
681
+ setStateForDetentIndex(dimmedDetentIndex - 1)
682
+ }
683
+ }
684
+
662
685
  private fun animateDismiss() {
663
686
  val sheet = sheetView ?: run {
664
687
  finishDismiss()
@@ -2,11 +2,13 @@ package com.lodev09.truesheet.core
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.graphics.Color
5
+ import android.graphics.Outline
5
6
  import android.graphics.drawable.ShapeDrawable
6
7
  import android.graphics.drawable.shapes.RoundRectShape
7
8
  import android.util.TypedValue
8
9
  import android.view.Gravity
9
10
  import android.view.View
11
+ import android.view.ViewOutlineProvider
10
12
  import android.widget.FrameLayout
11
13
  import androidx.coordinatorlayout.widget.CoordinatorLayout
12
14
  import com.facebook.react.uimanager.PixelUtil.dpToPx
@@ -113,6 +115,12 @@ class TrueSheetBottomSheetView(private val reactContext: ThemedReactContext) : F
113
115
  background = ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
114
116
  paint.color = color
115
117
  }
118
+
119
+ outlineProvider = object : ViewOutlineProvider() {
120
+ override fun getOutline(view: View, outline: Outline) {
121
+ outline.setRoundRect(0, 0, view.width, view.height, effectiveRadius)
122
+ }
123
+ }
116
124
  clipToOutline = true
117
125
  }
118
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.5.1-beta.4",
3
+ "version": "3.5.1-beta.5",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",