@swmansion/react-native-bottom-sheet 0.9.0-next.2 → 0.9.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.
- package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetView.kt +118 -65
- package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetViewManager.kt +33 -28
- package/ios/BottomSheetComponentView.mm +4 -0
- package/ios/BottomSheetContentView.h +1 -0
- package/ios/BottomSheetContentView.mm +10 -0
- package/ios/RNSBottomSheetHostingView.swift +49 -32
- package/lib/module/BottomSheet.js +8 -0
- package/lib/module/BottomSheet.js.map +1 -1
- package/lib/module/BottomSheetNativeComponent.ts +1 -0
- package/lib/module/BottomSheetProvider.js +2 -0
- package/lib/module/BottomSheetProvider.js.map +1 -1
- package/lib/module/ModalBottomSheet.js +3 -0
- package/lib/module/ModalBottomSheet.js.map +1 -1
- package/lib/module/bottomSheetUtils.js +5 -0
- package/lib/module/bottomSheetUtils.js.map +1 -1
- package/lib/typescript/src/BottomSheet.d.ts +21 -1
- package/lib/typescript/src/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetNativeComponent.d.ts +1 -0
- package/lib/typescript/src/BottomSheetNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetProvider.d.ts +1 -0
- package/lib/typescript/src/BottomSheetProvider.d.ts.map +1 -1
- package/lib/typescript/src/ModalBottomSheet.d.ts +2 -0
- package/lib/typescript/src/ModalBottomSheet.d.ts.map +1 -1
- package/lib/typescript/src/bottomSheetUtils.d.ts +3 -0
- package/lib/typescript/src/bottomSheetUtils.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/BottomSheet.tsx +22 -0
- package/src/BottomSheetNativeComponent.ts +1 -0
- package/src/BottomSheetProvider.tsx +1 -0
- package/src/ModalBottomSheet.tsx +2 -0
- package/src/bottomSheetUtils.ts +3 -0
|
@@ -17,8 +17,8 @@ import androidx.dynamicanimation.animation.SpringForce
|
|
|
17
17
|
import com.facebook.react.bridge.Arguments
|
|
18
18
|
import com.facebook.react.uimanager.PointerEvents
|
|
19
19
|
import com.facebook.react.uimanager.StateWrapper
|
|
20
|
-
import com.facebook.react.views.view.ReactViewGroup
|
|
21
20
|
import com.facebook.react.uimanager.events.NativeGestureUtil
|
|
21
|
+
import com.facebook.react.views.view.ReactViewGroup
|
|
22
22
|
import kotlin.math.abs
|
|
23
23
|
|
|
24
24
|
private enum class DetentKind {
|
|
@@ -27,11 +27,14 @@ private enum class DetentKind {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
private data class RawDetentSpec(val value: Float, val kind: DetentKind, val programmatic: Boolean)
|
|
30
|
+
|
|
30
31
|
private data class DetentSpec(val height: Float, val programmatic: Boolean)
|
|
31
32
|
|
|
32
33
|
interface BottomSheetViewListener {
|
|
33
34
|
fun onIndexChange(index: Int)
|
|
35
|
+
|
|
34
36
|
fun onSettle(index: Int)
|
|
37
|
+
|
|
35
38
|
fun onPositionChange(position: Double)
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -54,6 +57,8 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
54
57
|
updateInteractionState()
|
|
55
58
|
updateScrim()
|
|
56
59
|
}
|
|
60
|
+
|
|
61
|
+
var disableScrollableNegotiation: Boolean = false
|
|
57
62
|
private var pendingIndex: Int? = null
|
|
58
63
|
private var hasLaidOut = false
|
|
59
64
|
private var isPanning = false
|
|
@@ -75,15 +80,14 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
75
80
|
private var lastTouchY = 0f
|
|
76
81
|
private var activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
77
82
|
private var scrimPressed = false
|
|
83
|
+
private var scrimTouchActive = false
|
|
78
84
|
private var scrimColor = Color.TRANSPARENT
|
|
79
85
|
private var scrimProgress = 0f
|
|
80
86
|
private var maxDetentHeight = Float.NaN
|
|
81
87
|
private var contentHeightMarker: View? = null
|
|
82
88
|
|
|
83
89
|
private val contentHeightMarkerLayoutListener =
|
|
84
|
-
View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
|
85
|
-
refreshDetentsFromLayout()
|
|
86
|
-
}
|
|
90
|
+
View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> refreshDetentsFromLayout() }
|
|
87
91
|
|
|
88
92
|
init {
|
|
89
93
|
clipChildren = false
|
|
@@ -197,16 +201,17 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
197
201
|
// MARK: - Prop setters
|
|
198
202
|
|
|
199
203
|
fun setDetents(raw: List<Map<String, Any>>) {
|
|
200
|
-
rawDetentSpecs =
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
"
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
rawDetentSpecs =
|
|
205
|
+
raw.mapNotNull { dict ->
|
|
206
|
+
val value = (dict["value"] as? Number)?.toDouble() ?: return@mapNotNull null
|
|
207
|
+
val kind =
|
|
208
|
+
when ((dict["kind"] as? String)?.lowercase()) {
|
|
209
|
+
"content" -> DetentKind.CONTENT
|
|
210
|
+
else -> DetentKind.POINTS
|
|
211
|
+
}
|
|
212
|
+
val programmatic = dict["programmatic"] as? Boolean ?: false
|
|
213
|
+
RawDetentSpec(value = (value * density).toFloat(), kind = kind, programmatic = programmatic)
|
|
214
|
+
}
|
|
210
215
|
refreshDetentsFromLayout()
|
|
211
216
|
}
|
|
212
217
|
|
|
@@ -322,6 +327,12 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
322
327
|
return maxHeight - snapHeight
|
|
323
328
|
}
|
|
324
329
|
|
|
330
|
+
private val minDetentTranslationY: Float
|
|
331
|
+
get() = detentSpecs.indices.minOfOrNull(::translationY) ?: 0f
|
|
332
|
+
|
|
333
|
+
private val maxDetentTranslationY: Float
|
|
334
|
+
get() = detentSpecs.indices.maxOfOrNull(::translationY) ?: 0f
|
|
335
|
+
|
|
325
336
|
private val closedIndex: Int?
|
|
326
337
|
get() = detentSpecs.indexOfFirst { it.height == 0f }.takeIf { it >= 0 }
|
|
327
338
|
|
|
@@ -376,12 +387,13 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
376
387
|
|
|
377
388
|
private fun startChoreographer() {
|
|
378
389
|
if (choreographerCallback != null) return
|
|
379
|
-
val callback =
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
390
|
+
val callback =
|
|
391
|
+
object : Choreographer.FrameCallback {
|
|
392
|
+
override fun doFrame(frameTimeNanos: Long) {
|
|
393
|
+
emitPosition()
|
|
394
|
+
choreographerCallback?.let { Choreographer.getInstance().postFrameCallback(it) }
|
|
395
|
+
}
|
|
383
396
|
}
|
|
384
|
-
}
|
|
385
397
|
choreographerCallback = callback
|
|
386
398
|
Choreographer.getInstance().postFrameCallback(callback)
|
|
387
399
|
}
|
|
@@ -406,25 +418,29 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
406
418
|
activeAnimationEmitsSettle = emitSettle
|
|
407
419
|
activeAnimation?.cancel()
|
|
408
420
|
|
|
409
|
-
val spring =
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
421
|
+
val spring =
|
|
422
|
+
SpringAnimation(sheetContainer, DynamicAnimation.TRANSLATION_Y, targetTy).apply {
|
|
423
|
+
spring =
|
|
424
|
+
SpringForce(targetTy).apply {
|
|
425
|
+
dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
|
|
426
|
+
stiffness = SpringForce.STIFFNESS_MEDIUM
|
|
427
|
+
}
|
|
428
|
+
setMinValue(minDetentTranslationY)
|
|
429
|
+
setMaxValue(maxDetentTranslationY)
|
|
430
|
+
setStartVelocity(velocity)
|
|
431
|
+
addEndListener { _, canceled, _, _ ->
|
|
432
|
+
if (canceled) {
|
|
433
|
+
return@addEndListener
|
|
434
|
+
}
|
|
435
|
+
stopChoreographer()
|
|
436
|
+
emitPosition()
|
|
437
|
+
activeAnimation = null
|
|
438
|
+
activeAnimationEmitsSettle = false
|
|
439
|
+
updateInteractionState()
|
|
440
|
+
if (emitIndexChange) listener?.onIndexChange(index)
|
|
441
|
+
if (emitSettle) listener?.onSettle(index)
|
|
418
442
|
}
|
|
419
|
-
stopChoreographer()
|
|
420
|
-
emitPosition()
|
|
421
|
-
activeAnimation = null
|
|
422
|
-
activeAnimationEmitsSettle = false
|
|
423
|
-
updateInteractionState()
|
|
424
|
-
if (emitIndexChange) listener?.onIndexChange(index)
|
|
425
|
-
if (emitSettle) listener?.onSettle(index)
|
|
426
443
|
}
|
|
427
|
-
}
|
|
428
444
|
|
|
429
445
|
activeAnimation = spring
|
|
430
446
|
startChoreographer()
|
|
@@ -439,11 +455,13 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
439
455
|
|
|
440
456
|
if (velocity < -flickThreshold) {
|
|
441
457
|
return draggable.firstOrNull { it.value.height > currentHeight }?.index
|
|
442
|
-
?: draggable.lastOrNull()?.index
|
|
458
|
+
?: draggable.lastOrNull()?.index
|
|
459
|
+
?: targetIndex
|
|
443
460
|
}
|
|
444
461
|
if (velocity > flickThreshold) {
|
|
445
462
|
return draggable.lastOrNull { it.value.height < currentHeight }?.index
|
|
446
|
-
?: draggable.firstOrNull()?.index
|
|
463
|
+
?: draggable.firstOrNull()?.index
|
|
464
|
+
?: targetIndex
|
|
447
465
|
}
|
|
448
466
|
|
|
449
467
|
return draggable.minByOrNull { abs(it.value.height - currentHeight) }?.index ?: targetIndex
|
|
@@ -458,7 +476,9 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
458
476
|
initialTouchX = ev.x
|
|
459
477
|
initialTouchY = ev.y
|
|
460
478
|
lastTouchY = ev.y
|
|
479
|
+
activePointerId = ev.getPointerId(0)
|
|
461
480
|
scrimPressed = true
|
|
481
|
+
scrimTouchActive = true
|
|
462
482
|
return true
|
|
463
483
|
}
|
|
464
484
|
return false
|
|
@@ -481,6 +501,9 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
481
501
|
val dy = y - initialTouchY
|
|
482
502
|
|
|
483
503
|
if (abs(dy) > touchSlop && abs(dy) > abs(dx) && draggableMinTy < draggableMaxTy) {
|
|
504
|
+
if (disableScrollableNegotiation && findScrollableAtTouch() != null) {
|
|
505
|
+
return false
|
|
506
|
+
}
|
|
484
507
|
if (!isAtMaxDraggable) {
|
|
485
508
|
lastTouchY = y
|
|
486
509
|
requestDisallowInterceptTouchEvent(false)
|
|
@@ -499,18 +522,20 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
499
522
|
}
|
|
500
523
|
}
|
|
501
524
|
}
|
|
502
|
-
MotionEvent.ACTION_UP,
|
|
525
|
+
MotionEvent.ACTION_UP,
|
|
526
|
+
MotionEvent.ACTION_CANCEL -> {
|
|
503
527
|
initialTouchX = 0f
|
|
504
528
|
initialTouchY = 0f
|
|
505
529
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
506
530
|
scrimPressed = false
|
|
531
|
+
scrimTouchActive = false
|
|
507
532
|
}
|
|
508
533
|
}
|
|
509
534
|
return false
|
|
510
535
|
}
|
|
511
536
|
|
|
512
537
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
513
|
-
if (
|
|
538
|
+
if (scrimTouchActive) {
|
|
514
539
|
when (event.actionMasked) {
|
|
515
540
|
MotionEvent.ACTION_MOVE -> {
|
|
516
541
|
val sheetTop = sheetContainer.top + sheetContainer.translationY
|
|
@@ -521,14 +546,22 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
521
546
|
}
|
|
522
547
|
MotionEvent.ACTION_UP -> {
|
|
523
548
|
val closeIndex = closedIndex
|
|
549
|
+
val shouldDismiss = scrimPressed && isScrimVisible()
|
|
524
550
|
scrimPressed = false
|
|
525
|
-
|
|
551
|
+
scrimTouchActive = false
|
|
552
|
+
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
553
|
+
if (shouldDismiss && closeIndex != null) {
|
|
526
554
|
snapToIndex(closeIndex, 0f)
|
|
527
555
|
}
|
|
528
556
|
return true
|
|
529
557
|
}
|
|
530
558
|
MotionEvent.ACTION_CANCEL -> {
|
|
531
559
|
scrimPressed = false
|
|
560
|
+
scrimTouchActive = false
|
|
561
|
+
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
562
|
+
return true
|
|
563
|
+
}
|
|
564
|
+
MotionEvent.ACTION_POINTER_UP -> {
|
|
532
565
|
return true
|
|
533
566
|
}
|
|
534
567
|
}
|
|
@@ -549,15 +582,17 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
549
582
|
emitPosition()
|
|
550
583
|
return true
|
|
551
584
|
}
|
|
552
|
-
MotionEvent.ACTION_UP,
|
|
585
|
+
MotionEvent.ACTION_UP,
|
|
586
|
+
MotionEvent.ACTION_CANCEL -> {
|
|
553
587
|
isPanning = false
|
|
554
588
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
555
|
-
val velocity =
|
|
556
|
-
tracker
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
589
|
+
val velocity =
|
|
590
|
+
velocityTracker?.let { tracker ->
|
|
591
|
+
tracker.computeCurrentVelocity(1000)
|
|
592
|
+
val v = tracker.yVelocity
|
|
593
|
+
tracker.recycle()
|
|
594
|
+
v
|
|
595
|
+
} ?: 0f
|
|
561
596
|
velocityTracker = null
|
|
562
597
|
val maxHeight = detentSpecs.maxOfOrNull { it.height } ?: resolvedMaxDetentHeight()
|
|
563
598
|
val currentHeight = maxHeight - sheetContainer.translationY
|
|
@@ -602,29 +637,45 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
602
637
|
// could never collapse by dragging down when a ScrollView is at the top.
|
|
603
638
|
|
|
604
639
|
private fun isScrollViewAtTop(): Boolean {
|
|
605
|
-
val scrollView =
|
|
606
|
-
if (!isTouchInsideView(scrollView)) return true
|
|
640
|
+
val scrollView = findScrollableAtTouch() ?: return true
|
|
607
641
|
val inverted = isViewInverted(scrollView)
|
|
608
642
|
return if (inverted) !scrollView.canScrollVertically(1) else !scrollView.canScrollVertically(-1)
|
|
609
643
|
}
|
|
610
644
|
|
|
611
|
-
private fun
|
|
612
|
-
val
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
645
|
+
private fun findScrollableAtTouch(): View? {
|
|
646
|
+
val containerX = initialTouchX - sheetContainer.left - sheetContainer.translationX
|
|
647
|
+
val containerY = initialTouchY - sheetContainer.top - sheetContainer.translationY
|
|
648
|
+
if (
|
|
649
|
+
containerX < 0f ||
|
|
650
|
+
containerX >= sheetContainer.width ||
|
|
651
|
+
containerY < 0f ||
|
|
652
|
+
containerY >= sheetContainer.height
|
|
653
|
+
) {
|
|
654
|
+
return null
|
|
655
|
+
}
|
|
656
|
+
return findScrollableAtPoint(sheetContainer, containerX, containerY)
|
|
619
657
|
}
|
|
620
658
|
|
|
621
|
-
private fun
|
|
622
|
-
if (view.
|
|
659
|
+
private fun findScrollableAtPoint(view: View, x: Float, y: Float): View? {
|
|
660
|
+
if (!view.isShown) return null
|
|
661
|
+
|
|
623
662
|
if (view is ViewGroup) {
|
|
624
|
-
for (i in
|
|
625
|
-
|
|
663
|
+
for (i in view.childCount - 1 downTo 0) {
|
|
664
|
+
val child = view.getChildAt(i)
|
|
665
|
+
val childX = x - child.left - child.translationX
|
|
666
|
+
val childY = y - child.top - child.translationY
|
|
667
|
+
if (childX < 0f || childX >= child.width || childY < 0f || childY >= child.height) {
|
|
668
|
+
continue
|
|
669
|
+
}
|
|
670
|
+
findScrollableAtPoint(child, childX, childY)?.let {
|
|
671
|
+
return it
|
|
672
|
+
}
|
|
626
673
|
}
|
|
627
674
|
}
|
|
675
|
+
|
|
676
|
+
if (view.canScrollVertically(1) || view.canScrollVertically(-1)) {
|
|
677
|
+
return view
|
|
678
|
+
}
|
|
628
679
|
return null
|
|
629
680
|
}
|
|
630
681
|
|
|
@@ -662,6 +713,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
662
713
|
lastTouchY = 0f
|
|
663
714
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
664
715
|
scrimPressed = false
|
|
716
|
+
scrimTouchActive = false
|
|
665
717
|
sheetContainer.translationY = 0f
|
|
666
718
|
scrimProgress = 0f
|
|
667
719
|
sheetContainer.removeAllViews()
|
|
@@ -678,15 +730,16 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
678
730
|
|
|
679
731
|
// When settled at the closed detent, dynamic content updates can briefly
|
|
680
732
|
// produce stale non-zero positions. Keep scrim hidden in this state.
|
|
681
|
-
if (
|
|
733
|
+
if (
|
|
734
|
+
closedIndex != null && targetIndex == closedIndex && activeAnimation == null && !isPanning
|
|
735
|
+
) {
|
|
682
736
|
scrimProgress = 0f
|
|
683
737
|
invalidate()
|
|
684
738
|
return
|
|
685
739
|
}
|
|
686
740
|
|
|
687
741
|
val threshold = firstNonZeroDetentHeight
|
|
688
|
-
scrimProgress =
|
|
689
|
-
if (threshold <= 0f) 0f else (position / threshold).coerceIn(0f, 1f)
|
|
742
|
+
scrimProgress = if (threshold <= 0f) 0f else (position / threshold).coerceIn(0f, 1f)
|
|
690
743
|
invalidate()
|
|
691
744
|
}
|
|
692
745
|
|
package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetViewManager.kt
CHANGED
|
@@ -14,8 +14,7 @@ import com.facebook.react.viewmanagers.BottomSheetViewManagerInterface
|
|
|
14
14
|
|
|
15
15
|
@ReactModule(name = BottomSheetViewManager.NAME)
|
|
16
16
|
class BottomSheetViewManager :
|
|
17
|
-
ViewGroupManager<BottomSheetView>(),
|
|
18
|
-
BottomSheetViewManagerInterface<BottomSheetView> {
|
|
17
|
+
ViewGroupManager<BottomSheetView>(), BottomSheetViewManagerInterface<BottomSheetView> {
|
|
19
18
|
|
|
20
19
|
companion object {
|
|
21
20
|
const val NAME = "BottomSheetView"
|
|
@@ -29,37 +28,37 @@ class BottomSheetViewManager :
|
|
|
29
28
|
|
|
30
29
|
override fun createViewInstance(context: ThemedReactContext): BottomSheetView {
|
|
31
30
|
val view = BottomSheetView(context)
|
|
32
|
-
view.listener =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
view.listener =
|
|
32
|
+
object : BottomSheetViewListener {
|
|
33
|
+
override fun onIndexChange(index: Int) {
|
|
34
|
+
val event =
|
|
35
|
+
com.facebook.react.bridge.Arguments.createMap().apply { putInt("index", index) }
|
|
36
|
+
val reactContext = view.context as? ThemedReactContext ?: return
|
|
37
|
+
reactContext
|
|
38
|
+
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
39
|
+
.receiveEvent(view.id, "topIndexChange", event)
|
|
36
40
|
}
|
|
37
|
-
val reactContext = view.context as? ThemedReactContext ?: return
|
|
38
|
-
reactContext
|
|
39
|
-
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
40
|
-
.receiveEvent(view.id, "topIndexChange", event)
|
|
41
|
-
}
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
override fun onSettle(index: Int) {
|
|
43
|
+
val event =
|
|
44
|
+
com.facebook.react.bridge.Arguments.createMap().apply { putInt("index", index) }
|
|
45
|
+
val reactContext = view.context as? ThemedReactContext ?: return
|
|
46
|
+
reactContext
|
|
47
|
+
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
48
|
+
.receiveEvent(view.id, "topSettle", event)
|
|
46
49
|
}
|
|
47
|
-
val reactContext = view.context as? ThemedReactContext ?: return
|
|
48
|
-
reactContext
|
|
49
|
-
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
50
|
-
.receiveEvent(view.id, "topSettle", event)
|
|
51
|
-
}
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
override fun onPositionChange(position: Double) {
|
|
52
|
+
val event =
|
|
53
|
+
com.facebook.react.bridge.Arguments.createMap().apply {
|
|
54
|
+
putDouble("position", position)
|
|
55
|
+
}
|
|
56
|
+
val reactContext = view.context as? ThemedReactContext ?: return
|
|
57
|
+
reactContext
|
|
58
|
+
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
59
|
+
.receiveEvent(view.id, "topPositionChange", event)
|
|
56
60
|
}
|
|
57
|
-
val reactContext = view.context as? ThemedReactContext ?: return
|
|
58
|
-
reactContext
|
|
59
|
-
.getJSModule(com.facebook.react.uimanager.events.RCTEventEmitter::class.java)
|
|
60
|
-
.receiveEvent(view.id, "topPositionChange", event)
|
|
61
61
|
}
|
|
62
|
-
}
|
|
63
62
|
return view
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -69,7 +68,8 @@ class BottomSheetViewManager :
|
|
|
69
68
|
|
|
70
69
|
override fun getChildCount(parent: BottomSheetView): Int = parent.sheetChildCount
|
|
71
70
|
|
|
72
|
-
override fun getChildAt(parent: BottomSheetView, index: Int): View? =
|
|
71
|
+
override fun getChildAt(parent: BottomSheetView, index: Int): View? =
|
|
72
|
+
parent.getSheetChildAt(index)
|
|
73
73
|
|
|
74
74
|
override fun removeViewAt(parent: BottomSheetView, index: Int) {
|
|
75
75
|
parent.removeSheetChildAt(index)
|
|
@@ -131,6 +131,11 @@ class BottomSheetViewManager :
|
|
|
131
131
|
view.modal = modal
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
@ReactProp(name = "disableScrollableNegotiation")
|
|
135
|
+
override fun setDisableScrollableNegotiation(view: BottomSheetView, value: Boolean) {
|
|
136
|
+
view.disableScrollableNegotiation = value
|
|
137
|
+
}
|
|
138
|
+
|
|
134
139
|
@ReactProp(name = "scrimColor", customType = "Color")
|
|
135
140
|
override fun setScrimColor(view: BottomSheetView, scrimColor: Int?) {
|
|
136
141
|
view.setScrimColor(scrimColor)
|
|
@@ -76,6 +76,10 @@ using namespace facebook::react;
|
|
|
76
76
|
_sheetView.modal = newViewProps.modal;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
if (newViewProps.disableScrollableNegotiation != oldViewProps.disableScrollableNegotiation) {
|
|
80
|
+
_sheetView.disableScrollableNegotiation = newViewProps.disableScrollableNegotiation;
|
|
81
|
+
}
|
|
82
|
+
|
|
79
83
|
if (newViewProps.scrimColor != oldViewProps.scrimColor) {
|
|
80
84
|
[_sheetView setScrimColor:RCTUIColorFromSharedColor(newViewProps.scrimColor)];
|
|
81
85
|
}
|
|
@@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
15
15
|
@property (nonatomic, weak, nullable) id<BottomSheetContentViewDelegate> delegate;
|
|
16
16
|
@property (nonatomic) BOOL animateIn;
|
|
17
17
|
@property (nonatomic) BOOL modal;
|
|
18
|
+
@property (nonatomic) BOOL disableScrollableNegotiation;
|
|
18
19
|
@property (nonatomic, readonly) UIView *sheetContainer;
|
|
19
20
|
|
|
20
21
|
- (void)setDetents:(NSArray<NSDictionary *> *)raw;
|
|
@@ -40,6 +40,16 @@
|
|
|
40
40
|
return _impl.sheetContainer;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
- (BOOL)disableScrollableNegotiation
|
|
44
|
+
{
|
|
45
|
+
return _impl.disableScrollableNegotiation;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (void)setDisableScrollableNegotiation:(BOOL)disableScrollableNegotiation
|
|
49
|
+
{
|
|
50
|
+
_impl.disableScrollableNegotiation = disableScrollableNegotiation;
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
- (BOOL)modal
|
|
44
54
|
{
|
|
45
55
|
return _impl.modal;
|
|
@@ -28,13 +28,17 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
28
28
|
public var modal: Bool = false {
|
|
29
29
|
didSet { updateScrim() }
|
|
30
30
|
}
|
|
31
|
+
|
|
31
32
|
public var scrimColor: UIColor? = .clear {
|
|
32
33
|
didSet { scrimView.backgroundColor = scrimColor }
|
|
33
34
|
}
|
|
35
|
+
|
|
34
36
|
public var maxDetentHeight: CGFloat = .nan {
|
|
35
37
|
didSet { refreshDetentsFromLayout() }
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
public var disableScrollableNegotiation: Bool = false
|
|
41
|
+
|
|
38
42
|
private var rawDetentSpecs: [RawDetentSpec] = []
|
|
39
43
|
private var detentSpecs: [DetentSpec] = [] {
|
|
40
44
|
didSet {
|
|
@@ -58,7 +62,7 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
58
62
|
private var isContentInteractionDisabled = false
|
|
59
63
|
private weak var contentHeightMarker: UIView?
|
|
60
64
|
|
|
61
|
-
public
|
|
65
|
+
override public init(frame: CGRect) {
|
|
62
66
|
super.init(frame: frame)
|
|
63
67
|
backgroundColor = .clear
|
|
64
68
|
clipsToBounds = false
|
|
@@ -83,19 +87,20 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
83
87
|
sheetContainer.addGestureRecognizer(panGesture)
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
@available(*, unavailable)
|
|
91
|
+
public required init?(coder _: NSCoder) {
|
|
87
92
|
fatalError("init(coder:) has not been implemented")
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
/// RCTSurfaceTouchHandler dispatches touch events to JS independently of the
|
|
96
|
+
/// pan gesture (it fires in touchesBegan: regardless of its recognizer state).
|
|
97
|
+
/// We cache it here and toggle isEnabled in handlePan(.began) to force a
|
|
98
|
+
/// touchesCancelled dispatch to JS, preventing Pressable from firing onPress
|
|
99
|
+
/// during a sheet drag. This is the iOS equivalent of Android's
|
|
100
|
+
/// NativeGestureUtil.notifyNativeGestureStarted.
|
|
96
101
|
private weak var surfaceTouchHandler: UIGestureRecognizer?
|
|
97
102
|
|
|
98
|
-
public
|
|
103
|
+
override public func didMoveToWindow() {
|
|
99
104
|
super.didMoveToWindow()
|
|
100
105
|
surfaceTouchHandler = nil
|
|
101
106
|
guard window != nil else { return }
|
|
@@ -111,7 +116,7 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
public
|
|
119
|
+
override public func layoutSubviews() {
|
|
115
120
|
super.layoutSubviews()
|
|
116
121
|
guard bounds.width > 0, bounds.height > 0 else { return }
|
|
117
122
|
|
|
@@ -151,7 +156,7 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
151
156
|
return sheetContainer.frame
|
|
152
157
|
}
|
|
153
158
|
|
|
154
|
-
public
|
|
159
|
+
override public func point(inside point: CGPoint, with _: UIEvent?) -> Bool {
|
|
155
160
|
if presentedSheetFrame.contains(point) {
|
|
156
161
|
return true
|
|
157
162
|
}
|
|
@@ -159,10 +164,10 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
159
164
|
return isScrimVisible && bounds.contains(point)
|
|
160
165
|
}
|
|
161
166
|
|
|
162
|
-
public
|
|
167
|
+
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
163
168
|
guard self.point(inside: point, with: event) else { return nil }
|
|
164
169
|
|
|
165
|
-
if isScrimVisible
|
|
170
|
+
if isScrimVisible, !presentedSheetFrame.contains(point) {
|
|
166
171
|
let scrimPoint = convert(point, to: scrimView)
|
|
167
172
|
return scrimView.hitTest(scrimPoint, with: event)
|
|
168
173
|
}
|
|
@@ -449,18 +454,6 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
449
454
|
return scrollView.alwaysBounceVertical || scrollView.contentSize.height > visibleHeight
|
|
450
455
|
}
|
|
451
456
|
|
|
452
|
-
private func firstScrollView(in view: UIView) -> UIScrollView? {
|
|
453
|
-
for subview in view.subviews {
|
|
454
|
-
if let scrollView = subview as? UIScrollView, isVerticallyScrollable(scrollView) {
|
|
455
|
-
return scrollView
|
|
456
|
-
}
|
|
457
|
-
if let found = firstScrollView(in: subview) {
|
|
458
|
-
return found
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
return nil
|
|
462
|
-
}
|
|
463
|
-
|
|
464
457
|
private func isViewInverted(_ view: UIView) -> Bool {
|
|
465
458
|
var current: UIView? = view
|
|
466
459
|
while let v = current, v !== sheetContainer {
|
|
@@ -470,7 +463,23 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
470
463
|
return false
|
|
471
464
|
}
|
|
472
465
|
|
|
473
|
-
|
|
466
|
+
private func scrollView(containing location: CGPoint, in view: UIView) -> UIScrollView? {
|
|
467
|
+
for subview in view.subviews.reversed() {
|
|
468
|
+
let locationInSubview = view.convert(location, to: subview)
|
|
469
|
+
guard subview.bounds.contains(locationInSubview) else { continue }
|
|
470
|
+
|
|
471
|
+
if let found = scrollView(containing: locationInSubview, in: subview) {
|
|
472
|
+
return found
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if let scrollView = subview as? UIScrollView, isVerticallyScrollable(scrollView) {
|
|
476
|
+
return scrollView
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return nil
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
474
483
|
guard gestureRecognizer === panGesture else { return true }
|
|
475
484
|
|
|
476
485
|
let velocity = panGesture.velocity(in: self)
|
|
@@ -479,6 +488,13 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
479
488
|
let draggable = detentSpecs.enumerated().filter { !$0.element.programmatic }
|
|
480
489
|
guard draggable.count > 1 else { return false }
|
|
481
490
|
|
|
491
|
+
if disableScrollableNegotiation {
|
|
492
|
+
let locationInContainer = panGesture.location(in: sheetContainer)
|
|
493
|
+
if scrollView(containing: locationInContainer, in: sheetContainer) != nil {
|
|
494
|
+
return false
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
482
498
|
let maxDraggableIndex = draggable.last?.offset ?? 0
|
|
483
499
|
// Below max: allow drag in either direction to reach other detents.
|
|
484
500
|
guard targetIndex >= maxDraggableIndex else { return true }
|
|
@@ -488,9 +504,10 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
488
504
|
return false
|
|
489
505
|
}
|
|
490
506
|
|
|
491
|
-
|
|
492
|
-
let
|
|
493
|
-
|
|
507
|
+
let locationInContainer = panGesture.location(in: sheetContainer)
|
|
508
|
+
guard let scrollView = scrollView(containing: locationInContainer, in: sheetContainer) else {
|
|
509
|
+
return true
|
|
510
|
+
}
|
|
494
511
|
let inverted = isViewInverted(scrollView)
|
|
495
512
|
if inverted {
|
|
496
513
|
let maxOffsetY = scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom
|
|
@@ -539,7 +556,7 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
539
556
|
return
|
|
540
557
|
}
|
|
541
558
|
|
|
542
|
-
if hasLaidOut
|
|
559
|
+
if hasLaidOut, !isPanning {
|
|
543
560
|
targetIndex = max(0, min(detentSpecs.count - 1, targetIndex))
|
|
544
561
|
|
|
545
562
|
if let animator = activeAnimator {
|
|
@@ -593,8 +610,8 @@ extension RNSBottomSheetHostingView: UIGestureRecognizerDelegate {
|
|
|
593
610
|
}
|
|
594
611
|
|
|
595
612
|
public func gestureRecognizer(
|
|
596
|
-
_
|
|
597
|
-
shouldRecognizeSimultaneouslyWith
|
|
613
|
+
_: UIGestureRecognizer,
|
|
614
|
+
shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer
|
|
598
615
|
) -> Bool {
|
|
599
616
|
return false
|
|
600
617
|
}
|
|
@@ -6,6 +6,12 @@ import BottomSheetNativeComponent from './BottomSheetNativeComponent';
|
|
|
6
6
|
import { Portal } from "./BottomSheetProvider.js";
|
|
7
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
export { programmatic } from "./bottomSheetUtils.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for the inline bottom-sheet component.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Native bottom sheet that renders inline within the current screen layout. */
|
|
9
15
|
export const BottomSheet = ({
|
|
10
16
|
children,
|
|
11
17
|
style,
|
|
@@ -16,6 +22,7 @@ export const BottomSheet = ({
|
|
|
16
22
|
onSettle,
|
|
17
23
|
onPositionChange,
|
|
18
24
|
modal = false,
|
|
25
|
+
disableScrollableNegotiation = false,
|
|
19
26
|
scrimColor
|
|
20
27
|
}) => {
|
|
21
28
|
const {
|
|
@@ -75,6 +82,7 @@ export const BottomSheet = ({
|
|
|
75
82
|
index: index,
|
|
76
83
|
animateIn: animateIn,
|
|
77
84
|
modal: modal,
|
|
85
|
+
disableScrollableNegotiation: disableScrollableNegotiation,
|
|
78
86
|
scrimColor: scrimColor,
|
|
79
87
|
onIndexChange: handleIndexChange,
|
|
80
88
|
onSettle: handleSettle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","modal","scrimColor","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","handleIndexChange","event","nativeEvent","handleSettle","handlePositionChange","position","sheet","absoluteFill","pointerEvents","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":";;AAEA,SAASA,UAAU,EAAEC,IAAI,EAAEC,mBAAmB,QAAQ,cAAc;AACpE,SAASC,iBAAiB,QAAQ,gCAAgC;AAElE,OAAOC,0BAA0B,MAAM,8BAA8B;AACrE,SAASC,MAAM,QAAQ,0BAAuB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAG/C,SAASC,YAAY,QAAQ,uBAAoB;
|
|
1
|
+
{"version":3,"names":["StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","modal","disableScrollableNegotiation","scrimColor","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","handleIndexChange","event","nativeEvent","handleSettle","handlePositionChange","position","sheet","absoluteFill","pointerEvents","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -17,6 +17,7 @@ export interface NativeProps extends ViewProps {
|
|
|
17
17
|
index: CodegenTypes.Int32;
|
|
18
18
|
animateIn: boolean;
|
|
19
19
|
modal: boolean;
|
|
20
|
+
disableScrollableNegotiation?: boolean;
|
|
20
21
|
scrimColor?: ColorValue;
|
|
21
22
|
onIndexChange?: CodegenTypes.DirectEventHandler<
|
|
22
23
|
Readonly<{ index: CodegenTypes.Int32 }>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createContext","useContext","useEffect","useId","useReducer","useState","StyleSheet","View","jsx","_jsx","jsxs","_jsxs","PortalContext","PortalHost","context","forceRender","x","subscribe","Array","from","getPortals","entries","map","key","element","style","absoluteFill","pointerEvents","children","BottomSheetProvider","portals","Map","subscribers","Set","notify","forEach","subscriber","addPortal","set","removePortal","delete","callback","add","Provider","value","Portal","Error","id"],"sourceRoot":"../../src","sources":["BottomSheetProvider.tsx"],"mappings":";;AAAA,SACEA,aAAa,EACbC,UAAU,EACVC,SAAS,EACTC,KAAK,EACLC,UAAU,EACVC,QAAQ,QACH,OAAO;AAEd,SAASC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAShD,MAAMC,aAAa,gBAAGZ,aAAa,CAA2B,IAAI,CAAC;AAEnE,MAAMa,UAAU,GAAGA,CAAA,KAAM;EACvB,MAAMC,OAAO,GAAGb,UAAU,CAACW,aAAa,CAAE;EAC1C,MAAM,GAAGG,WAAW,CAAC,GAAGX,UAAU,CAAEY,CAAS,IAAKA,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;EAC3Dd,SAAS,CAAC,MAAM;IACd,OAAOY,OAAO,CAACG,SAAS,CAACF,WAAW,CAAC;EACvC,CAAC,EAAE,CAACD,OAAO,CAAC,CAAC;EAEb,OAAOI,KAAK,CAACC,IAAI,CAACL,OAAO,CAACM,UAAU,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC,CAACC,GAAG,EAAEC,OAAO,CAAC,kBACnEf,IAAA,CAACF,IAAI;IAAWkB,KAAK,EAAEnB,UAAU,CAACoB,YAAa;IAACC,aAAa,EAAC,UAAU;IAAAC,QAAA,EACrEJ;EAAO,GADCD,GAEL,CACP,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"names":["createContext","useContext","useEffect","useId","useReducer","useState","StyleSheet","View","jsx","_jsx","jsxs","_jsxs","PortalContext","PortalHost","context","forceRender","x","subscribe","Array","from","getPortals","entries","map","key","element","style","absoluteFill","pointerEvents","children","BottomSheetProvider","portals","Map","subscribers","Set","notify","forEach","subscriber","addPortal","set","removePortal","delete","callback","add","Provider","value","Portal","Error","id"],"sourceRoot":"../../src","sources":["BottomSheetProvider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { BottomSheet } from "./BottomSheet.js";
|
|
4
|
+
|
|
5
|
+
/** Props for the modal bottom-sheet variant rendered through the provider portal. */
|
|
4
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
/** Bottom sheet presented above the current UI with a scrim. */
|
|
5
8
|
export const ModalBottomSheet = props => /*#__PURE__*/_jsx(BottomSheet, {
|
|
6
9
|
...props,
|
|
7
10
|
modal: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["BottomSheet","jsx","_jsx","ModalBottomSheet","props","modal"],"sourceRoot":"../../src","sources":["ModalBottomSheet.tsx"],"mappings":";;AAAA,SAASA,WAAW,QAA+B,kBAAe;
|
|
1
|
+
{"version":3,"names":["BottomSheet","jsx","_jsx","ModalBottomSheet","props","modal"],"sourceRoot":"../../src","sources":["ModalBottomSheet.tsx"],"mappings":";;AAAA,SAASA,WAAW,QAA+B,kBAAe;;AAElE;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAIA;AACA,OAAO,MAAMC,gBAAgB,GAAIC,KAA4B,iBAC3DF,IAAA,CAACF,WAAW;EAAA,GAAKI,KAAK;EAAEC,KAAK;AAAA,CAAE,CAChC","ignoreList":[]}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
/** A detent value in points, or `'content'` to size to the measured content height. */
|
|
4
|
+
|
|
5
|
+
/** A draggable detent or an object form that can mark a detent as programmatic-only. */
|
|
6
|
+
|
|
7
|
+
/** Marks a detent as reachable only via controlled `index` updates, not dragging. */
|
|
3
8
|
export const programmatic = value => ({
|
|
4
9
|
value,
|
|
5
10
|
programmatic: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["programmatic","value","detentValue","detent","isDetentProgrammatic","VELOCITY_THRESHOLD","findSnapTarget","currentTranslate","velocityY","currentIndex","allPositions","draggablePositions","filter","position","isDraggable","effectivePositions","length","targetIndex","minDistance","Infinity","distance","Math","abs","translateY","index","lowerPosition","sort","a","b","undefined","upperPosition","resolveDetent","contentHeight","maxHeight","detentValueInput","min","Error","clampIndex","detentCount","max"],"sourceRoot":"../../src","sources":["bottomSheetUtils.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["programmatic","value","detentValue","detent","isDetentProgrammatic","VELOCITY_THRESHOLD","findSnapTarget","currentTranslate","velocityY","currentIndex","allPositions","draggablePositions","filter","position","isDraggable","effectivePositions","length","targetIndex","minDistance","Infinity","distance","Math","abs","translateY","index","lowerPosition","sort","a","b","undefined","upperPosition","resolveDetent","contentHeight","maxHeight","detentValueInput","min","Error","clampIndex","detentCount","max"],"sourceRoot":"../../src","sources":["bottomSheetUtils.ts"],"mappings":";;AAAA;;AAGA;;AAKA;AACA,OAAO,MAAMA,YAAY,GAAIC,KAAkB,KAAc;EAC3DA,KAAK;EACLD,YAAY,EAAE;AAChB,CAAC,CAAC;AAEF,OAAO,MAAME,WAAW,GAAIC,MAAc,IAAkB;EAC1D,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAIA,MAAM,KAAK,IAAI,EAAE,OAAOA,MAAM,CAACF,KAAK;EACtE,OAAOE,MAAM;AACf,CAAC;AAED,OAAO,MAAMC,oBAAoB,GAAID,MAAc,IAAc;EAC/D,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAIA,MAAM,KAAK,IAAI,EAAE;IACjD,OAAOA,MAAM,CAACH,YAAY,KAAK,IAAI;EACrC;EACA,OAAO,KAAK;AACd,CAAC;AAED,MAAMK,kBAAkB,GAAG,GAAG;AAE9B,OAAO,MAAMC,cAAc,GAAGA,CAC5BC,gBAAwB,EACxBC,SAAiB,EACjBC,YAAoB,EACpBC,YAA2E,KACxE;EACH,MAAMC,kBAAkB,GAAGD,YAAY,CAACE,MAAM,CAC3CC,QAAQ,IAAKA,QAAQ,CAACC,WACzB,CAAC;EACD,MAAMC,kBAAkB,GACtBJ,kBAAkB,CAACK,MAAM,GAAG,CAAC,GAAGL,kBAAkB,GAAGD,YAAY;EAEnE,IAAIO,WAAW,GAAGR,YAAY;EAC9B,IAAIS,WAAW,GAAGC,QAAQ;EAE1B,KAAK,MAAMN,QAAQ,IAAIE,kBAAkB,EAAE;IACzC,MAAMK,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAACf,gBAAgB,GAAGM,QAAQ,CAACU,UAAU,CAAC;IACjE,IAAIH,QAAQ,GAAGF,WAAW,EAAE;MAC1BA,WAAW,GAAGE,QAAQ;MACtBH,WAAW,GAAGJ,QAAQ,CAACW,KAAK;IAC9B;EACF;EAEA,IAAIH,IAAI,CAACC,GAAG,CAACd,SAAS,CAAC,GAAGH,kBAAkB,EAAE;IAC5C,IAAIG,SAAS,GAAG,CAAC,EAAE;MACjB,MAAMiB,aAAa,GAAGV,kBAAkB,CACrCH,MAAM,CAAEC,QAAQ,IAAKA,QAAQ,CAACU,UAAU,GAAGhB,gBAAgB,GAAG,CAAC,CAAC,CAChEmB,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKD,CAAC,CAACJ,UAAU,GAAGK,CAAC,CAACL,UAAU,CAAC,CAAC,CAAC,CAAC;MACjD,IAAIE,aAAa,KAAKI,SAAS,EAAEZ,WAAW,GAAGQ,aAAa,CAACD,KAAK;IACpE,CAAC,MAAM;MACL,MAAMM,aAAa,GAAGf,kBAAkB,CACrCH,MAAM,CAAEC,QAAQ,IAAKA,QAAQ,CAACU,UAAU,GAAGhB,gBAAgB,GAAG,CAAC,CAAC,CAChEmB,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKA,CAAC,CAACL,UAAU,GAAGI,CAAC,CAACJ,UAAU,CAAC,CAAC,CAAC,CAAC;MACjD,IAAIO,aAAa,KAAKD,SAAS,EAAEZ,WAAW,GAAGa,aAAa,CAACN,KAAK;IACpE;EACF;EACA,OAAOP,WAAW;AACpB,CAAC;AAED,OAAO,MAAMc,aAAa,GAAGA,CAC3B5B,MAAc,EACd6B,aAAqB,EACrBC,SAAiB,KACd;EACH,MAAMC,gBAAgB,GAAGhC,WAAW,CAACC,MAAM,CAAC;EAC5C,IAAI,OAAO+B,gBAAgB,KAAK,QAAQ,EAAE,OAAOA,gBAAgB;EACjE,IAAIA,gBAAgB,KAAK,SAAS,EAAE;IAClC,OAAOF,aAAa,GAAG,CAAC,GAAGX,IAAI,CAACc,GAAG,CAACH,aAAa,EAAEC,SAAS,CAAC,GAAGA,SAAS;EAC3E;EACA,MAAM,IAAIG,KAAK,CAAC,qBAAqBF,gBAAgB,KAAK,CAAC;AAC7D,CAAC;AAED,OAAO,MAAMG,UAAU,GAAGA,CAACb,KAAa,EAAEc,WAAmB,KAAK;EAChE,IAAIA,WAAW,IAAI,CAAC,EAAE,OAAO,CAAC;EAC9B,OAAOjB,IAAI,CAACc,GAAG,CAACd,IAAI,CAACkB,GAAG,CAACf,KAAK,EAAE,CAAC,CAAC,EAAEc,WAAW,GAAG,CAAC,CAAC;AACtD,CAAC","ignoreList":[]}
|
|
@@ -3,17 +3,37 @@ import type { StyleProp, ViewStyle } from 'react-native';
|
|
|
3
3
|
import { type Detent } from './bottomSheetUtils';
|
|
4
4
|
export type { Detent, DetentValue } from './bottomSheetUtils';
|
|
5
5
|
export { programmatic } from './bottomSheetUtils';
|
|
6
|
+
/**
|
|
7
|
+
* Props for the inline bottom-sheet component.
|
|
8
|
+
*/
|
|
6
9
|
export interface BottomSheetProps {
|
|
10
|
+
/** Sheet contents, including any background or scrollable content. */
|
|
7
11
|
children: ReactNode;
|
|
12
|
+
/** Additional style applied to the native sheet host view. */
|
|
8
13
|
style?: StyleProp<ViewStyle>;
|
|
14
|
+
/** Snap points for the sheet. Defaults to `[0, 'content']`. */
|
|
9
15
|
detents?: Detent[];
|
|
16
|
+
/** Zero-based index into `detents`. */
|
|
10
17
|
index: number;
|
|
18
|
+
/** Whether the sheet should animate in on first layout. */
|
|
11
19
|
animateIn?: boolean;
|
|
20
|
+
/** Called after a user-driven snap changes the active index. */
|
|
12
21
|
onIndexChange?: (index: number) => void;
|
|
22
|
+
/** Called when a snap animation settles, including programmatic changes. */
|
|
13
23
|
onSettle?: (index: number) => void;
|
|
24
|
+
/** Called as the sheet position changes, in points from the bottom. */
|
|
14
25
|
onPositionChange?: (position: number) => void;
|
|
26
|
+
/** Internal flag used by `ModalBottomSheet`. */
|
|
15
27
|
modal?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Escape hatch that disables sheet/list gesture negotiation.
|
|
30
|
+
* If a gesture starts inside a nested scrollable, that scrollable keeps it
|
|
31
|
+
* even when it cannot scroll any further.
|
|
32
|
+
*/
|
|
33
|
+
disableScrollableNegotiation?: boolean;
|
|
34
|
+
/** Scrim color used by `ModalBottomSheet`. */
|
|
16
35
|
scrimColor?: string;
|
|
17
36
|
}
|
|
18
|
-
|
|
37
|
+
/** Native bottom sheet that renders inline within the current screen layout. */
|
|
38
|
+
export declare const BottomSheet: ({ children, style, detents, index, animateIn, onIndexChange, onSettle, onPositionChange, modal, disableScrollableNegotiation, scrimColor, }: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
39
|
//# sourceMappingURL=BottomSheet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,GAAI
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,QAAQ,EAAE,SAAS,CAAC;IACpB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gFAAgF;AAChF,eAAO,MAAM,WAAW,GAAI,6IAYzB,gBAAgB,4CAwFlB,CAAC"}
|
|
@@ -10,6 +10,7 @@ export interface NativeProps extends ViewProps {
|
|
|
10
10
|
index: CodegenTypes.Int32;
|
|
11
11
|
animateIn: boolean;
|
|
12
12
|
modal: boolean;
|
|
13
|
+
disableScrollableNegotiation?: boolean;
|
|
13
14
|
scrimColor?: ColorValue;
|
|
14
15
|
onIndexChange?: CodegenTypes.DirectEventHandler<Readonly<{
|
|
15
16
|
index: CodegenTypes.Int32;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CAC5C,CAAC;CACH;;AAED,wBAAsE"}
|
|
1
|
+
{"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CAC5C,CAAC;CACH;;AAED,wBAAsE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetProvider.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetProvider.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA0BvC,eAAO,MAAM,mBAAmB,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,4CAgCxE,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,SAkB3D,CAAC"}
|
|
1
|
+
{"version":3,"file":"BottomSheetProvider.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetProvider.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA0BvC,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,4CAgCxE,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,SAkB3D,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type BottomSheetProps } from './BottomSheet';
|
|
2
|
+
/** Props for the modal bottom-sheet variant rendered through the provider portal. */
|
|
2
3
|
export interface ModalBottomSheetProps extends Omit<BottomSheetProps, 'modal'> {
|
|
3
4
|
}
|
|
5
|
+
/** Bottom sheet presented above the current UI with a scrim. */
|
|
4
6
|
export declare const ModalBottomSheet: (props: ModalBottomSheetProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
7
|
//# sourceMappingURL=ModalBottomSheet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModalBottomSheet.d.ts","sourceRoot":"","sources":["../../../src/ModalBottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;CAAG;AAE5C,eAAO,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CAE5D,CAAC"}
|
|
1
|
+
{"version":3,"file":"ModalBottomSheet.d.ts","sourceRoot":"","sources":["../../../src/ModalBottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,qFAAqF;AACrF,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;CAAG;AAE5C,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CAE5D,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/** A detent value in points, or `'content'` to size to the measured content height. */
|
|
1
2
|
export type DetentValue = number | 'content';
|
|
3
|
+
/** A draggable detent or an object form that can mark a detent as programmatic-only. */
|
|
2
4
|
export type Detent = DetentValue | {
|
|
3
5
|
value: DetentValue;
|
|
4
6
|
programmatic?: boolean;
|
|
5
7
|
};
|
|
8
|
+
/** Marks a detent as reachable only via controlled `index` updates, not dragging. */
|
|
6
9
|
export declare const programmatic: (value: DetentValue) => Detent;
|
|
7
10
|
export declare const detentValue: (detent: Detent) => DetentValue;
|
|
8
11
|
export declare const isDetentProgrammatic: (detent: Detent) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottomSheetUtils.d.ts","sourceRoot":"","sources":["../../../src/bottomSheetUtils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,MAAM,MAAM,MAAM,GACd,WAAW,GACX;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,KAAG,MAGhD,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,WAG5C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,OAKrD,CAAC;AAIF,eAAO,MAAM,cAAc,GACzB,kBAAkB,MAAM,EACxB,WAAW,MAAM,EACjB,cAAc,MAAM,EACpB,cAAc;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAAE,WAiC5E,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,WAAW,MAAM,WAQlB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,aAAa,MAAM,WAG5D,CAAC"}
|
|
1
|
+
{"version":3,"file":"bottomSheetUtils.d.ts","sourceRoot":"","sources":["../../../src/bottomSheetUtils.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,wFAAwF;AACxF,MAAM,MAAM,MAAM,GACd,WAAW,GACX;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnD,qFAAqF;AACrF,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,KAAG,MAGhD,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,WAG5C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,OAKrD,CAAC;AAIF,eAAO,MAAM,cAAc,GACzB,kBAAkB,MAAM,EACxB,WAAW,MAAM,EACjB,cAAc,MAAM,EACpB,cAAc;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAAE,WAiC5E,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,WAAW,MAAM,WAQlB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,aAAa,MAAM,WAG5D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swmansion/react-native-bottom-sheet",
|
|
3
|
-
"version": "0.9.0
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Provides bottom-sheet components for React Native.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"scripts": {
|
|
36
36
|
"example": "yarn workspace @swmansion/react-native-bottom-sheet-example",
|
|
37
37
|
"clean": "del-cli lib",
|
|
38
|
-
"prepare": "bob build",
|
|
38
|
+
"prepare": "lefthook install && bob build",
|
|
39
39
|
"typecheck": "tsc",
|
|
40
40
|
"lint": "eslint \"**/*.{js,ts,tsx}\""
|
|
41
41
|
},
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"eslint": "9.39.2",
|
|
70
70
|
"eslint-config-prettier": "10.1.8",
|
|
71
71
|
"eslint-plugin-prettier": "5.5.5",
|
|
72
|
+
"lefthook": "2.1.6",
|
|
72
73
|
"prettier": "2.8.8",
|
|
73
74
|
"react": "19.1.0",
|
|
74
75
|
"react-native": "0.81.5",
|
package/src/BottomSheet.tsx
CHANGED
|
@@ -9,19 +9,39 @@ import { type Detent } from './bottomSheetUtils';
|
|
|
9
9
|
export type { Detent, DetentValue } from './bottomSheetUtils';
|
|
10
10
|
export { programmatic } from './bottomSheetUtils';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Props for the inline bottom-sheet component.
|
|
14
|
+
*/
|
|
12
15
|
export interface BottomSheetProps {
|
|
16
|
+
/** Sheet contents, including any background or scrollable content. */
|
|
13
17
|
children: ReactNode;
|
|
18
|
+
/** Additional style applied to the native sheet host view. */
|
|
14
19
|
style?: StyleProp<ViewStyle>;
|
|
20
|
+
/** Snap points for the sheet. Defaults to `[0, 'content']`. */
|
|
15
21
|
detents?: Detent[];
|
|
22
|
+
/** Zero-based index into `detents`. */
|
|
16
23
|
index: number;
|
|
24
|
+
/** Whether the sheet should animate in on first layout. */
|
|
17
25
|
animateIn?: boolean;
|
|
26
|
+
/** Called after a user-driven snap changes the active index. */
|
|
18
27
|
onIndexChange?: (index: number) => void;
|
|
28
|
+
/** Called when a snap animation settles, including programmatic changes. */
|
|
19
29
|
onSettle?: (index: number) => void;
|
|
30
|
+
/** Called as the sheet position changes, in points from the bottom. */
|
|
20
31
|
onPositionChange?: (position: number) => void;
|
|
32
|
+
/** Internal flag used by `ModalBottomSheet`. */
|
|
21
33
|
modal?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Escape hatch that disables sheet/list gesture negotiation.
|
|
36
|
+
* If a gesture starts inside a nested scrollable, that scrollable keeps it
|
|
37
|
+
* even when it cannot scroll any further.
|
|
38
|
+
*/
|
|
39
|
+
disableScrollableNegotiation?: boolean;
|
|
40
|
+
/** Scrim color used by `ModalBottomSheet`. */
|
|
22
41
|
scrimColor?: string;
|
|
23
42
|
}
|
|
24
43
|
|
|
44
|
+
/** Native bottom sheet that renders inline within the current screen layout. */
|
|
25
45
|
export const BottomSheet = ({
|
|
26
46
|
children,
|
|
27
47
|
style,
|
|
@@ -32,6 +52,7 @@ export const BottomSheet = ({
|
|
|
32
52
|
onSettle,
|
|
33
53
|
onPositionChange,
|
|
34
54
|
modal = false,
|
|
55
|
+
disableScrollableNegotiation = false,
|
|
35
56
|
scrimColor,
|
|
36
57
|
}: BottomSheetProps) => {
|
|
37
58
|
const { height: windowHeight } = useWindowDimensions();
|
|
@@ -101,6 +122,7 @@ export const BottomSheet = ({
|
|
|
101
122
|
index={index}
|
|
102
123
|
animateIn={animateIn}
|
|
103
124
|
modal={modal}
|
|
125
|
+
disableScrollableNegotiation={disableScrollableNegotiation}
|
|
104
126
|
scrimColor={scrimColor}
|
|
105
127
|
onIndexChange={handleIndexChange}
|
|
106
128
|
onSettle={handleSettle}
|
|
@@ -17,6 +17,7 @@ export interface NativeProps extends ViewProps {
|
|
|
17
17
|
index: CodegenTypes.Int32;
|
|
18
18
|
animateIn: boolean;
|
|
19
19
|
modal: boolean;
|
|
20
|
+
disableScrollableNegotiation?: boolean;
|
|
20
21
|
scrimColor?: ColorValue;
|
|
21
22
|
onIndexChange?: CodegenTypes.DirectEventHandler<
|
|
22
23
|
Readonly<{ index: CodegenTypes.Int32 }>
|
|
@@ -32,6 +32,7 @@ const PortalHost = () => {
|
|
|
32
32
|
));
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
/** Provides the portal host required for modal bottom sheets. */
|
|
35
36
|
export const BottomSheetProvider = ({ children }: { children: ReactNode }) => {
|
|
36
37
|
const [context] = useState<PortalContextType>(() => {
|
|
37
38
|
const portals = new Map<string, ReactNode>();
|
package/src/ModalBottomSheet.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { BottomSheet, type BottomSheetProps } from './BottomSheet';
|
|
2
2
|
|
|
3
|
+
/** Props for the modal bottom-sheet variant rendered through the provider portal. */
|
|
3
4
|
export interface ModalBottomSheetProps
|
|
4
5
|
extends Omit<BottomSheetProps, 'modal'> {}
|
|
5
6
|
|
|
7
|
+
/** Bottom sheet presented above the current UI with a scrim. */
|
|
6
8
|
export const ModalBottomSheet = (props: ModalBottomSheetProps) => (
|
|
7
9
|
<BottomSheet {...props} modal />
|
|
8
10
|
);
|
package/src/bottomSheetUtils.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
/** A detent value in points, or `'content'` to size to the measured content height. */
|
|
1
2
|
export type DetentValue = number | 'content';
|
|
2
3
|
|
|
4
|
+
/** A draggable detent or an object form that can mark a detent as programmatic-only. */
|
|
3
5
|
export type Detent =
|
|
4
6
|
| DetentValue
|
|
5
7
|
| { value: DetentValue; programmatic?: boolean };
|
|
6
8
|
|
|
9
|
+
/** Marks a detent as reachable only via controlled `index` updates, not dragging. */
|
|
7
10
|
export const programmatic = (value: DetentValue): Detent => ({
|
|
8
11
|
value,
|
|
9
12
|
programmatic: true,
|