@lodev09/react-native-true-sheet 3.3.5 → 3.4.0-beta.1
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 +1 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +5 -5
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +192 -120
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +2 -2
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDialogObserver.kt +46 -13
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +72 -0
- package/android/src/main/res/values/styles.xml +2 -3
- package/ios/TrueSheetView.mm +1 -4
- package/ios/TrueSheetViewController.mm +4 -2
- package/package.json +2 -2
- package/android/src/main/res/anim/true_sheet_fade_in.xml +0 -6
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
The true native bottom sheet experience for your React Native Apps. 💩
|
|
10
10
|
|
|
11
|
-
<img alt="React Native True Sheet - IOS" src="docs/static/img/preview-ios.gif" width="
|
|
11
|
+
<img alt="React Native True Sheet - IOS" src="docs/static/img/preview-ios.gif" width="248" height="500" /><img alt="React Native True Sheet - Android" src="docs/static/img/preview-android.gif" width="248" height="500" /><img alt="React Native True Sheet - Web" src="docs/static/img/preview-web.gif" width="248" height="500" />
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
@@ -251,6 +251,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
251
251
|
viewController.dimmed = dimmed
|
|
252
252
|
if (viewController.isPresented) {
|
|
253
253
|
viewController.setupDimmedBackground(viewController.currentDetentIndex)
|
|
254
|
+
viewController.updateDimAmount()
|
|
254
255
|
}
|
|
255
256
|
}
|
|
256
257
|
|
|
@@ -259,6 +260,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
259
260
|
viewController.dimmedDetentIndex = index
|
|
260
261
|
if (viewController.isPresented) {
|
|
261
262
|
viewController.setupDimmedBackground(viewController.currentDetentIndex)
|
|
263
|
+
viewController.updateDimAmount()
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
@@ -366,8 +368,8 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
366
368
|
isSheetUpdatePending = true
|
|
367
369
|
viewController.post {
|
|
368
370
|
isSheetUpdatePending = false
|
|
369
|
-
viewController.
|
|
370
|
-
|
|
371
|
+
viewController.setupSheetDetentsForSizeChange()
|
|
372
|
+
TrueSheetDialogObserver.onSheetSizeChanged(this)
|
|
371
373
|
}
|
|
372
374
|
}
|
|
373
375
|
|
|
@@ -382,9 +384,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
382
384
|
}
|
|
383
385
|
|
|
384
386
|
override fun containerViewFooterDidChangeSize(width: Int, height: Int) {
|
|
385
|
-
|
|
386
|
-
viewController.positionFooter()
|
|
387
|
-
}
|
|
387
|
+
viewController.positionFooter()
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
companion object {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
|
+
import android.animation.ValueAnimator
|
|
3
4
|
import android.annotation.SuppressLint
|
|
4
5
|
import android.graphics.Color
|
|
5
6
|
import android.graphics.drawable.ShapeDrawable
|
|
@@ -28,6 +29,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
|
28
29
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
29
30
|
import com.lodev09.truesheet.core.GrabberOptions
|
|
30
31
|
import com.lodev09.truesheet.core.RNScreensFragmentObserver
|
|
32
|
+
import com.lodev09.truesheet.core.TrueSheetDimView
|
|
31
33
|
import com.lodev09.truesheet.core.TrueSheetGrabberView
|
|
32
34
|
import com.lodev09.truesheet.core.TrueSheetKeyboardObserver
|
|
33
35
|
import com.lodev09.truesheet.core.TrueSheetKeyboardObserverDelegate
|
|
@@ -72,8 +74,9 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
72
74
|
private const val DEFAULT_CORNER_RADIUS = 16 // dp
|
|
73
75
|
|
|
74
76
|
// Animation durations from res/anim/true_sheet_slide_in.xml and true_sheet_slide_out.xml
|
|
75
|
-
private const val PRESENT_ANIMATION_DURATION =
|
|
77
|
+
private const val PRESENT_ANIMATION_DURATION = 250L
|
|
76
78
|
private const val DISMISS_ANIMATION_DURATION = 150L
|
|
79
|
+
private const val TRANSLATE_ANIMATION_DURATION = 100L
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
// ====================================================================
|
|
@@ -87,6 +90,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
87
90
|
// ====================================================================
|
|
88
91
|
|
|
89
92
|
private var dialog: BottomSheetDialog? = null
|
|
93
|
+
private var dimView: TrueSheetDimView? = null
|
|
94
|
+
private var parentDimView: TrueSheetDimView? = null
|
|
90
95
|
|
|
91
96
|
private val behavior: BottomSheetBehavior<FrameLayout>?
|
|
92
97
|
get() = dialog?.behavior
|
|
@@ -144,6 +149,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
144
149
|
get() = ScreenUtils.getScreenHeight(reactContext)
|
|
145
150
|
val screenWidth: Int
|
|
146
151
|
get() = ScreenUtils.getScreenWidth(reactContext)
|
|
152
|
+
val realScreenHeight: Int
|
|
153
|
+
get() = ScreenUtils.getRealScreenHeight(reactContext)
|
|
147
154
|
|
|
148
155
|
var maxSheetHeight: Int? = null
|
|
149
156
|
var detents = mutableListOf(0.5, 1.0)
|
|
@@ -152,7 +159,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
152
159
|
var dimmedDetentIndex = 0
|
|
153
160
|
var grabber: Boolean = true
|
|
154
161
|
var grabberOptions: GrabberOptions? = null
|
|
155
|
-
var sheetCornerRadius: Float =
|
|
162
|
+
var sheetCornerRadius: Float = DEFAULT_CORNER_RADIUS.dpToPx()
|
|
163
|
+
set(value) {
|
|
164
|
+
field = if (value < 0) DEFAULT_CORNER_RADIUS.dpToPx() else value
|
|
165
|
+
setupBackground()
|
|
166
|
+
}
|
|
156
167
|
var sheetBackgroundColor: Int? = null
|
|
157
168
|
var edgeToEdgeFullScreen: Boolean = false
|
|
158
169
|
|
|
@@ -261,6 +272,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
261
272
|
|
|
262
273
|
cleanupKeyboardObserver()
|
|
263
274
|
cleanupModalObserver()
|
|
275
|
+
dimView?.detach()
|
|
276
|
+
dimView = null
|
|
277
|
+
parentDimView?.detach()
|
|
278
|
+
parentDimView = null
|
|
264
279
|
sheetContainer?.removeView(this)
|
|
265
280
|
|
|
266
281
|
dialog = null
|
|
@@ -281,16 +296,18 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
281
296
|
setupGrabber()
|
|
282
297
|
setupKeyboardObserver()
|
|
283
298
|
|
|
299
|
+
val toTop = getExpectedSheetTop(currentDetentIndex)
|
|
300
|
+
setupTransitionTracker(realScreenHeight, toTop, PRESENT_ANIMATION_DURATION)
|
|
301
|
+
animateDimAlpha(show = true)
|
|
302
|
+
|
|
284
303
|
sheetContainer?.post {
|
|
285
|
-
bottomSheetView?.let { emitChangePositionDelegate(it, realtime = false) }
|
|
286
304
|
positionFooter()
|
|
287
305
|
}
|
|
288
306
|
|
|
289
307
|
sheetContainer?.postDelayed({
|
|
290
|
-
val
|
|
291
|
-
val detent = getDetentValueForIndex(detentInfo.index)
|
|
308
|
+
val (index, position, detent) = getDetentInfoWithValue(currentDetentIndex)
|
|
292
309
|
|
|
293
|
-
delegate?.viewControllerDidPresent(
|
|
310
|
+
delegate?.viewControllerDidPresent(index, position, detent)
|
|
294
311
|
parentSheetView?.viewControllerDidBlur()
|
|
295
312
|
delegate?.viewControllerDidFocus()
|
|
296
313
|
|
|
@@ -303,8 +320,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
303
320
|
if (isDismissing) return@setOnCancelListener
|
|
304
321
|
|
|
305
322
|
isDismissing = true
|
|
323
|
+
val fromTop = bottomSheetView?.top ?: getExpectedSheetTop(currentDetentIndex)
|
|
324
|
+
setupTransitionTracker(fromTop, realScreenHeight, DISMISS_ANIMATION_DURATION)
|
|
325
|
+
animateDimAlpha(show = false)
|
|
306
326
|
emitWillDismissEvents()
|
|
307
|
-
emitDismissedPosition()
|
|
308
327
|
}
|
|
309
328
|
|
|
310
329
|
dialog.setOnDismissListener {
|
|
@@ -321,7 +340,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
321
340
|
override fun onSlide(sheetView: View, slideOffset: Float) {
|
|
322
341
|
val behavior = behavior ?: return
|
|
323
342
|
|
|
324
|
-
emitChangePositionDelegate(sheetView
|
|
343
|
+
emitChangePositionDelegate(sheetView.top)
|
|
325
344
|
|
|
326
345
|
when (behavior.state) {
|
|
327
346
|
BottomSheetBehavior.STATE_DRAGGING,
|
|
@@ -331,6 +350,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
331
350
|
}
|
|
332
351
|
|
|
333
352
|
positionFooter(slideOffset)
|
|
353
|
+
updateDimAmount()
|
|
334
354
|
}
|
|
335
355
|
|
|
336
356
|
override fun onStateChanged(sheetView: View, newState: Int) {
|
|
@@ -386,14 +406,25 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
386
406
|
reactContext = reactContext,
|
|
387
407
|
onModalPresented = {
|
|
388
408
|
if (isPresented && isDialogVisible) {
|
|
389
|
-
|
|
409
|
+
isDialogVisible = false
|
|
410
|
+
dialog?.window?.setWindowAnimations(com.lodev09.truesheet.R.style.TrueSheetFadeOutAnimation)
|
|
411
|
+
dialog?.window?.decorView?.visibility = INVISIBLE
|
|
412
|
+
dimView?.visibility = INVISIBLE
|
|
413
|
+
parentDimView?.visibility = INVISIBLE
|
|
390
414
|
wasHiddenByModal = true
|
|
391
415
|
}
|
|
392
416
|
},
|
|
393
417
|
onModalDismissed = {
|
|
394
418
|
// Only show if we were the one hidden by modal, not by sheet stacking
|
|
395
419
|
if (isPresented && wasHiddenByModal) {
|
|
396
|
-
|
|
420
|
+
isDialogVisible = true
|
|
421
|
+
dialog?.window?.decorView?.visibility = VISIBLE
|
|
422
|
+
dimView?.visibility = VISIBLE
|
|
423
|
+
parentDimView?.visibility = VISIBLE
|
|
424
|
+
// Restore animation after visibility change to avoid slide animation
|
|
425
|
+
sheetContainer?.post {
|
|
426
|
+
dialog?.window?.setWindowAnimations(windowAnimation)
|
|
427
|
+
}
|
|
397
428
|
wasHiddenByModal = false
|
|
398
429
|
}
|
|
399
430
|
}
|
|
@@ -424,6 +455,13 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
424
455
|
dismissPromise = null
|
|
425
456
|
}
|
|
426
457
|
|
|
458
|
+
/** Helper to get detent info with its screen fraction value. */
|
|
459
|
+
private fun getDetentInfoWithValue(index: Int): Triple<Int, Float, Float> {
|
|
460
|
+
val detentInfo = getDetentInfoForIndex(index)
|
|
461
|
+
val detent = getDetentValueForIndex(detentInfo.index)
|
|
462
|
+
return Triple(detentInfo.index, detentInfo.position, detent)
|
|
463
|
+
}
|
|
464
|
+
|
|
427
465
|
// ====================================================================
|
|
428
466
|
// MARK: - Dialog Visibility (for stacking)
|
|
429
467
|
// ====================================================================
|
|
@@ -439,35 +477,21 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
439
477
|
|
|
440
478
|
fun getExpectedSheetTop(detentIndex: Int): Int {
|
|
441
479
|
if (detentIndex < 0 || detentIndex >= detents.size) return screenHeight
|
|
442
|
-
|
|
443
|
-
return screenHeight - detentHeight
|
|
480
|
+
return realScreenHeight - getDetentHeight(detents[detentIndex])
|
|
444
481
|
}
|
|
445
482
|
|
|
446
|
-
/**
|
|
447
|
-
fun
|
|
448
|
-
|
|
449
|
-
if (animated) {
|
|
450
|
-
dialog?.window?.setWindowAnimations(com.lodev09.truesheet.R.style.TrueSheetFadeAnimation)
|
|
451
|
-
}
|
|
452
|
-
dialog?.window?.decorView?.visibility = INVISIBLE
|
|
453
|
-
if (emitPosition) {
|
|
454
|
-
emitDismissedPosition()
|
|
455
|
-
}
|
|
456
|
-
}
|
|
483
|
+
/** Translates the sheet when stacking. Pass 0 to reset. */
|
|
484
|
+
fun translateDialog(translationY: Int) {
|
|
485
|
+
val bottomSheet = bottomSheetView ?: return
|
|
457
486
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
// Restore original animation after fade-in completes (100ms)
|
|
467
|
-
sheetContainer?.postDelayed({
|
|
468
|
-
dialog?.window?.setWindowAnimations(windowAnimation)
|
|
469
|
-
}, 100)
|
|
470
|
-
}
|
|
487
|
+
bottomSheet.animate()
|
|
488
|
+
.translationY(translationY.toFloat())
|
|
489
|
+
.setDuration(TRANSLATE_ANIMATION_DURATION)
|
|
490
|
+
.setUpdateListener {
|
|
491
|
+
val effectiveTop = bottomSheet.top + bottomSheet.translationY.toInt()
|
|
492
|
+
emitChangePositionDelegate(effectiveTop)
|
|
493
|
+
}
|
|
494
|
+
.start()
|
|
471
495
|
}
|
|
472
496
|
|
|
473
497
|
// ====================================================================
|
|
@@ -490,11 +514,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
490
514
|
setupSheetDetents()
|
|
491
515
|
setStateForDetentIndex(detentIndex)
|
|
492
516
|
|
|
493
|
-
val
|
|
494
|
-
val detent = getDetentValueForIndex(detentInfo.index)
|
|
517
|
+
val (index, position, detent) = getDetentInfoWithValue(detentIndex)
|
|
495
518
|
|
|
496
519
|
parentSheetView?.viewControllerWillBlur()
|
|
497
|
-
delegate?.viewControllerWillPresent(
|
|
520
|
+
delegate?.viewControllerWillPresent(index, position, detent)
|
|
498
521
|
delegate?.viewControllerWillFocus()
|
|
499
522
|
|
|
500
523
|
if (!animated) {
|
|
@@ -509,8 +532,9 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
509
532
|
if (isDismissing) return
|
|
510
533
|
|
|
511
534
|
isDismissing = true
|
|
535
|
+
val fromTop = bottomSheetView?.top ?: getExpectedSheetTop(currentDetentIndex)
|
|
536
|
+
setupTransitionTracker(fromTop, realScreenHeight, DISMISS_ANIMATION_DURATION)
|
|
512
537
|
emitWillDismissEvents()
|
|
513
|
-
emitDismissedPosition()
|
|
514
538
|
|
|
515
539
|
if (!animated) {
|
|
516
540
|
dialog?.window?.setWindowAnimations(0)
|
|
@@ -528,14 +552,13 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
528
552
|
val behavior = this.behavior ?: return
|
|
529
553
|
|
|
530
554
|
isReconfiguring = true
|
|
531
|
-
val realHeight = ScreenUtils.getRealScreenHeight(reactContext)
|
|
532
555
|
val edgeToEdgeTopInset: Int = if (!edgeToEdgeFullScreen) topInset else 0
|
|
533
556
|
|
|
534
557
|
behavior.apply {
|
|
535
558
|
isFitToContents = false
|
|
536
559
|
maxWidth = DEFAULT_MAX_WIDTH.dpToPx().toInt()
|
|
537
560
|
|
|
538
|
-
val maxAvailableHeight =
|
|
561
|
+
val maxAvailableHeight = realScreenHeight - edgeToEdgeTopInset
|
|
539
562
|
|
|
540
563
|
setPeekHeight(getDetentHeight(detents[0]), isPresented)
|
|
541
564
|
|
|
@@ -547,13 +570,13 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
547
570
|
val maxDetentHeight = getDetentHeight(detents.last())
|
|
548
571
|
|
|
549
572
|
val adjustedHalfExpandedHeight = minOf(halfExpandedDetentHeight, maxAvailableHeight)
|
|
550
|
-
halfExpandedRatio = minOf(adjustedHalfExpandedHeight.toFloat() /
|
|
573
|
+
halfExpandedRatio = minOf(adjustedHalfExpandedHeight.toFloat() / realScreenHeight.toFloat(), MAX_HALF_EXPANDED_RATIO)
|
|
551
574
|
|
|
552
|
-
expandedOffset = maxOf(edgeToEdgeTopInset,
|
|
575
|
+
expandedOffset = maxOf(edgeToEdgeTopInset, realScreenHeight - maxDetentHeight)
|
|
553
576
|
isFitToContents = detents.size < 3 && expandedOffset == 0
|
|
554
577
|
|
|
555
578
|
val offset = if (expandedOffset == 0) topInset else 0
|
|
556
|
-
val newHeight =
|
|
579
|
+
val newHeight = realScreenHeight - expandedOffset - offset
|
|
557
580
|
val newWidth = minOf(screenWidth, maxWidth)
|
|
558
581
|
|
|
559
582
|
if (lastStateWidth != newWidth || lastStateHeight != newHeight) {
|
|
@@ -570,6 +593,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
570
593
|
}
|
|
571
594
|
}
|
|
572
595
|
|
|
596
|
+
fun setupSheetDetentsForSizeChange() {
|
|
597
|
+
setupSheetDetents()
|
|
598
|
+
positionFooter()
|
|
599
|
+
}
|
|
600
|
+
|
|
573
601
|
fun setupGrabber() {
|
|
574
602
|
val bottomSheet = bottomSheetView ?: return
|
|
575
603
|
|
|
@@ -584,10 +612,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
584
612
|
}
|
|
585
613
|
|
|
586
614
|
bottomSheet.addView(grabberView)
|
|
587
|
-
grabberView.bringToFront()
|
|
588
615
|
}
|
|
589
616
|
|
|
590
617
|
private var keyboardObserver: TrueSheetKeyboardObserver? = null
|
|
618
|
+
private var positionAnimator: ValueAnimator? = null
|
|
591
619
|
|
|
592
620
|
fun setupKeyboardObserver() {
|
|
593
621
|
val bottomSheet = bottomSheetView ?: return
|
|
@@ -606,11 +634,51 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
606
634
|
keyboardObserver = null
|
|
607
635
|
}
|
|
608
636
|
|
|
637
|
+
private fun setupTransitionTracker(fromTop: Int, toTop: Int, duration: Long) {
|
|
638
|
+
positionAnimator?.cancel()
|
|
639
|
+
positionAnimator = ValueAnimator.ofInt(fromTop, toTop).apply {
|
|
640
|
+
this.duration = duration
|
|
641
|
+
interpolator = if (fromTop > toTop) {
|
|
642
|
+
android.view.animation.DecelerateInterpolator(2f) // present
|
|
643
|
+
} else {
|
|
644
|
+
android.view.animation.AccelerateInterpolator(2f) // dismiss
|
|
645
|
+
}
|
|
646
|
+
addUpdateListener { animator ->
|
|
647
|
+
emitChangePositionDelegate(animator.animatedValue as Int)
|
|
648
|
+
}
|
|
649
|
+
addListener(object : android.animation.AnimatorListenerAdapter() {
|
|
650
|
+
override fun onAnimationEnd(animation: android.animation.Animator) {
|
|
651
|
+
positionAnimator = null
|
|
652
|
+
}
|
|
653
|
+
})
|
|
654
|
+
start()
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private fun emitChangePositionDelegate(currentTop: Int, realtime: Boolean = true) {
|
|
659
|
+
if (currentTop == lastEmittedPositionPx) return
|
|
660
|
+
|
|
661
|
+
lastEmittedPositionPx = currentTop
|
|
662
|
+
val visibleHeight = realScreenHeight - currentTop
|
|
663
|
+
val position = getPositionDp(visibleHeight)
|
|
664
|
+
val interpolatedIndex = getInterpolatedIndexForPosition(currentTop)
|
|
665
|
+
val detent = getInterpolatedDetentForPosition(currentTop)
|
|
666
|
+
delegate?.viewControllerDidChangePosition(interpolatedIndex, position, detent, realtime)
|
|
667
|
+
}
|
|
668
|
+
|
|
609
669
|
fun setupBackground() {
|
|
610
670
|
val bottomSheet = bottomSheetView ?: return
|
|
611
671
|
|
|
612
|
-
val
|
|
613
|
-
|
|
672
|
+
val outerRadii = floatArrayOf(
|
|
673
|
+
sheetCornerRadius,
|
|
674
|
+
sheetCornerRadius,
|
|
675
|
+
sheetCornerRadius,
|
|
676
|
+
sheetCornerRadius,
|
|
677
|
+
0f,
|
|
678
|
+
0f,
|
|
679
|
+
0f,
|
|
680
|
+
0f
|
|
681
|
+
)
|
|
614
682
|
val backgroundColor = sheetBackgroundColor ?: getDefaultBackgroundColor()
|
|
615
683
|
|
|
616
684
|
bottomSheet.background = ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
|
|
@@ -619,24 +687,46 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
619
687
|
bottomSheet.clipToOutline = true
|
|
620
688
|
}
|
|
621
689
|
|
|
622
|
-
/** Configures dim and touch-through behavior based on detent index. */
|
|
623
690
|
fun setupDimmedBackground(detentIndex: Int) {
|
|
624
691
|
val dialog = this.dialog ?: return
|
|
692
|
+
|
|
625
693
|
dialog.window?.apply {
|
|
626
|
-
val
|
|
694
|
+
val touchOutside = findViewById<View>(com.google.android.material.R.id.touch_outside)
|
|
695
|
+
clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
|
|
696
|
+
|
|
697
|
+
val shouldDimAtDetent = dimmed && detentIndex >= dimmedDetentIndex
|
|
627
698
|
|
|
628
|
-
if (dimmed
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
699
|
+
if (dimmed) {
|
|
700
|
+
val parentDimVisible = (parentSheetView?.viewController?.dimView?.alpha ?: 0f) > 0f
|
|
701
|
+
|
|
702
|
+
if (dimView == null) dimView = TrueSheetDimView(reactContext)
|
|
703
|
+
if (!parentDimVisible) dimView?.attach(null)
|
|
704
|
+
|
|
705
|
+
val parentController = parentSheetView?.viewController
|
|
706
|
+
val parentBottomSheet = parentController?.bottomSheetView
|
|
707
|
+
if (parentBottomSheet != null) {
|
|
708
|
+
if (parentDimView == null) parentDimView = TrueSheetDimView(reactContext)
|
|
709
|
+
parentDimView?.attach(parentBottomSheet, parentController.sheetCornerRadius)
|
|
710
|
+
}
|
|
711
|
+
} else {
|
|
712
|
+
dimView?.detach()
|
|
713
|
+
dimView = null
|
|
714
|
+
parentDimView?.detach()
|
|
715
|
+
parentDimView = null
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (shouldDimAtDetent) {
|
|
719
|
+
touchOutside.setOnTouchListener(null)
|
|
632
720
|
dialog.setCanceledOnTouchOutside(dismissible)
|
|
633
721
|
} else {
|
|
634
|
-
|
|
722
|
+
touchOutside.setOnTouchListener { v, event ->
|
|
635
723
|
event.setLocation(event.rawX - v.x, event.rawY - v.y)
|
|
636
|
-
|
|
724
|
+
(
|
|
725
|
+
parentSheetView?.viewController?.dialog?.window?.decorView
|
|
726
|
+
?: reactContext.currentActivity?.window?.decorView
|
|
727
|
+
)?.dispatchTouchEvent(event)
|
|
637
728
|
false
|
|
638
729
|
}
|
|
639
|
-
clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
|
|
640
730
|
dialog.setCanceledOnTouchOutside(false)
|
|
641
731
|
}
|
|
642
732
|
}
|
|
@@ -646,6 +736,20 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
646
736
|
dialog?.window?.setWindowAnimations(windowAnimation)
|
|
647
737
|
}
|
|
648
738
|
|
|
739
|
+
private fun animateDimAlpha(show: Boolean) {
|
|
740
|
+
if (!dimmed) return
|
|
741
|
+
val duration = if (show) PRESENT_ANIMATION_DURATION else DISMISS_ANIMATION_DURATION
|
|
742
|
+
dimView?.animateAlpha(show, duration, dimmedDetentIndex, currentDetentIndex)
|
|
743
|
+
parentDimView?.animateAlpha(show, duration, dimmedDetentIndex, currentDetentIndex)
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
fun updateDimAmount() {
|
|
747
|
+
if (!dimmed) return
|
|
748
|
+
val sheetTop = bottomSheetView?.top ?: return
|
|
749
|
+
dimView?.interpolateAlpha(sheetTop, dimmedDetentIndex, ::getSheetTopForDetentIndex)
|
|
750
|
+
parentDimView?.interpolateAlpha(sheetTop, dimmedDetentIndex, ::getSheetTopForDetentIndex)
|
|
751
|
+
}
|
|
752
|
+
|
|
649
753
|
/** Positions footer at bottom of sheet, adjusting during drag via slideOffset. */
|
|
650
754
|
fun positionFooter(slideOffset: Float? = null) {
|
|
651
755
|
val footerView = containerView?.footerView ?: return
|
|
@@ -693,37 +797,16 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
693
797
|
* Calculate the visible sheet height from a sheet view.
|
|
694
798
|
* Uses real screen height for consistency across API levels.
|
|
695
799
|
*/
|
|
696
|
-
private fun getVisibleSheetHeight(sheetView: View): Int
|
|
697
|
-
val realHeight = ScreenUtils.getRealScreenHeight(reactContext)
|
|
698
|
-
return realHeight - sheetView.top
|
|
699
|
-
}
|
|
800
|
+
private fun getVisibleSheetHeight(sheetView: View): Int = realScreenHeight - sheetView.top
|
|
700
801
|
|
|
701
802
|
private fun getPositionDp(visibleSheetHeight: Int): Float = (screenHeight - visibleSheetHeight).pxToDp()
|
|
702
803
|
|
|
703
|
-
private fun emitChangePositionDelegate(sheetView: View, realtime: Boolean) {
|
|
704
|
-
if (sheetView.top == lastEmittedPositionPx) return
|
|
705
|
-
|
|
706
|
-
lastEmittedPositionPx = sheetView.top
|
|
707
|
-
val position = getPositionDp(getVisibleSheetHeight(sheetView))
|
|
708
|
-
val interpolatedIndex = getInterpolatedIndexForPosition(sheetView.top)
|
|
709
|
-
val detent = getInterpolatedDetentForPosition(sheetView.top)
|
|
710
|
-
delegate?.viewControllerDidChangePosition(interpolatedIndex, position, detent, realtime)
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
private fun emitDismissedPosition() {
|
|
714
|
-
val position = screenHeight.pxToDp()
|
|
715
|
-
lastEmittedPositionPx = -1
|
|
716
|
-
delegate?.viewControllerDidChangePosition(-1f, position, 0f, false)
|
|
717
|
-
}
|
|
718
|
-
|
|
719
804
|
/**
|
|
720
805
|
* Get the expected sheetTop position for a detent index.
|
|
721
806
|
*/
|
|
722
807
|
private fun getSheetTopForDetentIndex(index: Int): Int {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
val detentHeight = getDetentHeight(detents[index])
|
|
726
|
-
return realHeight - detentHeight
|
|
808
|
+
if (index < 0 || index >= detents.size) return realScreenHeight
|
|
809
|
+
return realScreenHeight - getDetentHeight(detents[index])
|
|
727
810
|
}
|
|
728
811
|
|
|
729
812
|
/** Returns (fromIndex, toIndex, progress) for interpolation, or null if < 2 detents. */
|
|
@@ -731,12 +814,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
731
814
|
val count = detents.size
|
|
732
815
|
if (count == 0) return null
|
|
733
816
|
|
|
734
|
-
val realHeight = ScreenUtils.getRealScreenHeight(reactContext)
|
|
735
817
|
val firstPos = getSheetTopForDetentIndex(0)
|
|
736
818
|
|
|
737
819
|
// Above first detent - interpolating toward closed
|
|
738
820
|
if (positionPx > firstPos) {
|
|
739
|
-
val range =
|
|
821
|
+
val range = realScreenHeight - firstPos
|
|
740
822
|
val progress = if (range > 0) (positionPx - firstPos).toFloat() / range else 0f
|
|
741
823
|
return Triple(-1, 0, progress)
|
|
742
824
|
}
|
|
@@ -847,47 +929,37 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
847
929
|
return maxSheetHeight?.let { minOf(height, it, maxAllowedHeight) } ?: minOf(height, maxAllowedHeight)
|
|
848
930
|
}
|
|
849
931
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
0 -> BottomSheetBehavior.STATE_COLLAPSED
|
|
856
|
-
1 -> BottomSheetBehavior.STATE_EXPANDED
|
|
857
|
-
else -> BottomSheetBehavior.STATE_HIDDEN
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
3 -> when (index) {
|
|
861
|
-
0 -> BottomSheetBehavior.STATE_COLLAPSED
|
|
862
|
-
1 -> BottomSheetBehavior.STATE_HALF_EXPANDED
|
|
863
|
-
2 -> BottomSheetBehavior.STATE_EXPANDED
|
|
864
|
-
else -> BottomSheetBehavior.STATE_HIDDEN
|
|
865
|
-
}
|
|
932
|
+
/** Maps detent index to BottomSheetBehavior state based on detent count. */
|
|
933
|
+
private fun getStateForDetentIndex(index: Int): Int {
|
|
934
|
+
val stateMap = getDetentStateMap() ?: return BottomSheetBehavior.STATE_HIDDEN
|
|
935
|
+
return stateMap.entries.find { it.value == index }?.key ?: BottomSheetBehavior.STATE_HIDDEN
|
|
936
|
+
}
|
|
866
937
|
|
|
867
|
-
|
|
868
|
-
|
|
938
|
+
/** Maps BottomSheetBehavior state to DetentInfo based on detent count. */
|
|
939
|
+
fun getDetentInfoForState(state: Int): DetentInfo? {
|
|
940
|
+
val stateMap = getDetentStateMap() ?: return null
|
|
941
|
+
val index = stateMap[state] ?: return null
|
|
942
|
+
return DetentInfo(index, getPositionForDetentIndex(index))
|
|
943
|
+
}
|
|
869
944
|
|
|
870
|
-
|
|
945
|
+
/** Returns state-to-index mapping based on detent count. */
|
|
946
|
+
private fun getDetentStateMap(): Map<Int, Int>? =
|
|
871
947
|
when (detents.size) {
|
|
872
|
-
1 ->
|
|
873
|
-
BottomSheetBehavior.STATE_COLLAPSED,
|
|
874
|
-
BottomSheetBehavior.STATE_EXPANDED
|
|
875
|
-
|
|
876
|
-
else -> null
|
|
877
|
-
}
|
|
948
|
+
1 -> mapOf(
|
|
949
|
+
BottomSheetBehavior.STATE_COLLAPSED to 0,
|
|
950
|
+
BottomSheetBehavior.STATE_EXPANDED to 0
|
|
951
|
+
)
|
|
878
952
|
|
|
879
|
-
2 ->
|
|
880
|
-
BottomSheetBehavior.STATE_COLLAPSED
|
|
881
|
-
BottomSheetBehavior.STATE_EXPANDED
|
|
882
|
-
|
|
883
|
-
}
|
|
953
|
+
2 -> mapOf(
|
|
954
|
+
BottomSheetBehavior.STATE_COLLAPSED to 0,
|
|
955
|
+
BottomSheetBehavior.STATE_EXPANDED to 1
|
|
956
|
+
)
|
|
884
957
|
|
|
885
|
-
3 ->
|
|
886
|
-
BottomSheetBehavior.STATE_COLLAPSED
|
|
887
|
-
BottomSheetBehavior.STATE_HALF_EXPANDED
|
|
888
|
-
BottomSheetBehavior.STATE_EXPANDED
|
|
889
|
-
|
|
890
|
-
}
|
|
958
|
+
3 -> mapOf(
|
|
959
|
+
BottomSheetBehavior.STATE_COLLAPSED to 0,
|
|
960
|
+
BottomSheetBehavior.STATE_HALF_EXPANDED to 1,
|
|
961
|
+
BottomSheetBehavior.STATE_EXPANDED to 2
|
|
962
|
+
)
|
|
891
963
|
|
|
892
964
|
else -> null
|
|
893
965
|
}
|
|
@@ -929,7 +1001,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
929
1001
|
this.post {
|
|
930
1002
|
setupSheetDetents()
|
|
931
1003
|
positionFooter()
|
|
932
|
-
bottomSheetView?.let { emitChangePositionDelegate(it, realtime = false) }
|
|
1004
|
+
bottomSheetView?.let { emitChangePositionDelegate(it.top, realtime = false) }
|
|
933
1005
|
}
|
|
934
1006
|
}
|
|
935
1007
|
|
|
@@ -27,8 +27,8 @@ class RNScreensFragmentObserver(
|
|
|
27
27
|
val fragmentManager = activity.supportFragmentManager
|
|
28
28
|
|
|
29
29
|
fragmentLifecycleCallback = object : FragmentManager.FragmentLifecycleCallbacks() {
|
|
30
|
-
override fun
|
|
31
|
-
super.
|
|
30
|
+
override fun onFragmentAttached(fm: FragmentManager, fragment: Fragment, context: android.content.Context) {
|
|
31
|
+
super.onFragmentAttached(fm, fragment, context)
|
|
32
32
|
|
|
33
33
|
if (isModalFragment(fragment) && !activeModalFragments.contains(fragment)) {
|
|
34
34
|
activeModalFragments.add(fragment)
|
|
@@ -20,17 +20,8 @@ object TrueSheetDialogObserver {
|
|
|
20
20
|
val parentSheet = presentedSheetStack.lastOrNull()
|
|
21
21
|
?.takeIf { it.viewController.isPresented && it.viewController.isDialogVisible }
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for (sheet in presentedSheetStack) {
|
|
26
|
-
if (!sheet.viewController.isDialogVisible) continue
|
|
27
|
-
if (sheet.viewController.isExpanded) continue
|
|
28
|
-
|
|
29
|
-
val sheetTop = sheet.viewController.currentSheetTop
|
|
30
|
-
if (sheetTop < newSheetTop) {
|
|
31
|
-
sheet.viewController.hideDialog(emitPosition = true)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
23
|
+
val childSheetTop = sheetView.viewController.getExpectedSheetTop(detentIndex)
|
|
24
|
+
updateParentTranslations(childSheetTop)
|
|
34
25
|
|
|
35
26
|
if (!presentedSheetStack.contains(sheetView)) {
|
|
36
27
|
presentedSheetStack.add(sheetView)
|
|
@@ -42,14 +33,35 @@ object TrueSheetDialogObserver {
|
|
|
42
33
|
|
|
43
34
|
/**
|
|
44
35
|
* Called when a sheet has been dismissed.
|
|
45
|
-
*
|
|
36
|
+
* Resets parent sheet translation if this sheet was stacked on it.
|
|
46
37
|
*/
|
|
47
38
|
@JvmStatic
|
|
48
39
|
fun onSheetDidDismiss(sheetView: TrueSheetView, hadParent: Boolean) {
|
|
49
40
|
synchronized(presentedSheetStack) {
|
|
50
41
|
presentedSheetStack.remove(sheetView)
|
|
51
42
|
if (hadParent) {
|
|
52
|
-
presentedSheetStack.lastOrNull()?.viewController?.
|
|
43
|
+
presentedSheetStack.lastOrNull()?.viewController?.translateDialog(0)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Called when a presented sheet's size changes (e.g., after setupSheetDetents).
|
|
50
|
+
* Updates parent sheet translations to match the new sheet position.
|
|
51
|
+
*/
|
|
52
|
+
@JvmStatic
|
|
53
|
+
fun onSheetSizeChanged(sheetView: TrueSheetView) {
|
|
54
|
+
synchronized(presentedSheetStack) {
|
|
55
|
+
val index = presentedSheetStack.indexOf(sheetView)
|
|
56
|
+
if (index <= 0) return
|
|
57
|
+
|
|
58
|
+
// Post to ensure layout is complete before reading position
|
|
59
|
+
sheetView.viewController.post {
|
|
60
|
+
val childMinSheetTop = sheetView.viewController.getExpectedSheetTop(0)
|
|
61
|
+
val childCurrentSheetTop = sheetView.viewController.getExpectedSheetTop(sheetView.viewController.currentDetentIndex)
|
|
62
|
+
// Cap to minimum detent position
|
|
63
|
+
val childSheetTop = maxOf(childMinSheetTop, childCurrentSheetTop)
|
|
64
|
+
updateParentTranslations(childSheetTop, untilIndex = index)
|
|
53
65
|
}
|
|
54
66
|
}
|
|
55
67
|
}
|
|
@@ -80,4 +92,25 @@ object TrueSheetDialogObserver {
|
|
|
80
92
|
presentedSheetStack.clear()
|
|
81
93
|
}
|
|
82
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Translates parent sheets down to match the child sheet's position.
|
|
98
|
+
* @param childSheetTop The top position of the child sheet
|
|
99
|
+
* @param untilIndex If specified, only update sheets up to this index (exclusive)
|
|
100
|
+
*/
|
|
101
|
+
private fun updateParentTranslations(childSheetTop: Int, untilIndex: Int = presentedSheetStack.size) {
|
|
102
|
+
for (i in 0 until untilIndex) {
|
|
103
|
+
val parentSheet = presentedSheetStack[i]
|
|
104
|
+
if (!parentSheet.viewController.isDialogVisible) continue
|
|
105
|
+
if (parentSheet.viewController.isExpanded) continue
|
|
106
|
+
|
|
107
|
+
val parentSheetTop = parentSheet.viewController.getExpectedSheetTop(parentSheet.viewController.currentDetentIndex)
|
|
108
|
+
if (parentSheetTop < childSheetTop) {
|
|
109
|
+
val translationY = childSheetTop - parentSheetTop
|
|
110
|
+
parentSheet.viewController.translateDialog(translationY)
|
|
111
|
+
} else {
|
|
112
|
+
parentSheet.viewController.translateDialog(0)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
83
116
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package com.lodev09.truesheet.core
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.graphics.Color
|
|
5
|
+
import android.graphics.Outline
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.view.ViewGroup
|
|
8
|
+
import android.view.ViewOutlineProvider
|
|
9
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
10
|
+
import com.lodev09.truesheet.utils.ScreenUtils
|
|
11
|
+
|
|
12
|
+
@SuppressLint("ViewConstructor")
|
|
13
|
+
class TrueSheetDimView(private val reactContext: ThemedReactContext) : View(reactContext) {
|
|
14
|
+
|
|
15
|
+
companion object {
|
|
16
|
+
private const val MAX_ALPHA = 0.4f
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private var targetView: ViewGroup? = null
|
|
20
|
+
|
|
21
|
+
init {
|
|
22
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
23
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
24
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
25
|
+
)
|
|
26
|
+
setBackgroundColor(Color.BLACK)
|
|
27
|
+
alpha = 0f
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
fun attach(view: ViewGroup? = null, cornerRadius: Float = 0f) {
|
|
31
|
+
if (parent != null) return
|
|
32
|
+
targetView = view ?: reactContext.currentActivity?.window?.decorView as? ViewGroup
|
|
33
|
+
|
|
34
|
+
if (cornerRadius > 0f) {
|
|
35
|
+
outlineProvider = object : ViewOutlineProvider() {
|
|
36
|
+
override fun getOutline(v: View, outline: Outline) {
|
|
37
|
+
outline.setRoundRect(0, 0, v.width, v.height, cornerRadius)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
clipToOutline = true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
targetView?.addView(this)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fun detach() {
|
|
47
|
+
targetView?.removeView(this)
|
|
48
|
+
targetView = null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fun animateAlpha(show: Boolean, duration: Long, dimmedDetentIndex: Int, currentDetentIndex: Int) {
|
|
52
|
+
val targetAlpha = if (show && currentDetentIndex >= dimmedDetentIndex) MAX_ALPHA else 0f
|
|
53
|
+
animate().alpha(targetAlpha).setDuration(duration).start()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun interpolateAlpha(sheetTop: Int, dimmedDetentIndex: Int, getSheetTopForDetentIndex: (Int) -> Int) {
|
|
57
|
+
val realHeight = ScreenUtils.getRealScreenHeight(reactContext)
|
|
58
|
+
val dimmedDetentTop = getSheetTopForDetentIndex(dimmedDetentIndex)
|
|
59
|
+
val belowDimmedTop = if (dimmedDetentIndex > 0) getSheetTopForDetentIndex(dimmedDetentIndex - 1) else realHeight
|
|
60
|
+
|
|
61
|
+
alpha = when {
|
|
62
|
+
sheetTop <= dimmedDetentTop -> MAX_ALPHA
|
|
63
|
+
|
|
64
|
+
sheetTop >= belowDimmedTop -> 0f
|
|
65
|
+
|
|
66
|
+
else -> {
|
|
67
|
+
val progress = 1f - (sheetTop - dimmedDetentTop).toFloat() / (belowDimmedTop - dimmedDetentTop)
|
|
68
|
+
(progress * MAX_ALPHA).coerceIn(0f, MAX_ALPHA)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
<item name="android:windowExitAnimation">@anim/true_sheet_slide_out</item>
|
|
7
7
|
</style>
|
|
8
8
|
|
|
9
|
-
<!--
|
|
10
|
-
<style name="
|
|
11
|
-
<item name="android:windowEnterAnimation">@anim/true_sheet_fade_in</item>
|
|
9
|
+
<!-- Fade out only - used when hiding sheet for RN Screens modal -->
|
|
10
|
+
<style name="TrueSheetFadeOutAnimation" parent="Animation.AppCompat.Dialog">
|
|
12
11
|
<item name="android:windowExitAnimation">@anim/true_sheet_fade_out</item>
|
|
13
12
|
</style>
|
|
14
13
|
|
package/ios/TrueSheetView.mm
CHANGED
|
@@ -403,10 +403,7 @@ using namespace facebook::react;
|
|
|
403
403
|
|
|
404
404
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
405
405
|
self->_isSheetUpdatePending = NO;
|
|
406
|
-
|
|
407
|
-
[self->_controller.sheetPresentationController animateChanges:^{
|
|
408
|
-
[self->_controller setupSheetDetentsForSizeChange];
|
|
409
|
-
}];
|
|
406
|
+
[self->_controller setupSheetDetentsForSizeChange];
|
|
410
407
|
});
|
|
411
408
|
}
|
|
412
409
|
|
|
@@ -594,8 +594,10 @@
|
|
|
594
594
|
#pragma mark - Sheet Configuration
|
|
595
595
|
|
|
596
596
|
- (void)setupSheetDetentsForSizeChange {
|
|
597
|
-
|
|
598
|
-
|
|
597
|
+
[self.sheetPresentationController animateChanges:^{
|
|
598
|
+
_pendingContentSizeChange = YES;
|
|
599
|
+
[self setupSheetDetents];
|
|
600
|
+
}];
|
|
599
601
|
}
|
|
600
602
|
|
|
601
603
|
- (void)setupSheetDetentsForDetentsChange {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodev09/react-native-true-sheet",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-beta.1",
|
|
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",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"clean": "scripts/clean.sh",
|
|
54
54
|
"prepare": "bob build",
|
|
55
55
|
"release": "release-it",
|
|
56
|
-
"release:beta": "yarn release
|
|
56
|
+
"release:beta": "yarn release --preRelease=beta"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"react-native",
|