@lodev09/react-native-true-sheet 4.0.0-beta.25 → 4.0.0-beta.26
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 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +1 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +31 -10
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +3 -3
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +5 -0
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensEventObserver.kt +8 -16
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +9 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +0 -8
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +29 -38
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +6 -2
- package/ios/TrueSheetContainerView.h +1 -0
- package/ios/TrueSheetContainerView.mm +6 -0
- package/ios/TrueSheetContentView.h +1 -0
- package/ios/TrueSheetContentView.mm +2 -0
- package/ios/TrueSheetFooterView.mm +5 -0
- package/ios/TrueSheetView.mm +9 -2
- package/ios/TrueSheetViewController.h +12 -0
- package/ios/TrueSheetViewController.mm +332 -29
- package/ios/core/TrueSheetDetentCalculator.h +11 -0
- package/ios/core/TrueSheetDetentCalculator.mm +17 -5
- package/ios/core/TrueSheetKeyboardObserver.mm +89 -9
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +6 -0
- package/lib/typescript/src/TrueSheet.types.d.ts +31 -0
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +5 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +1 -1
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TrueSheet.types.ts +34 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +6 -0
- package/src/navigation/types.ts +1 -0
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ The true native bottom sheet experience for your React Native Apps. 💩
|
|
|
35
35
|
* 🍞 **`TrueSheetOverlay`** - Render toasts, dialogs, and other [overlays above your sheets](https://sheet.lodev09.com/guides/overlays) — no more `FullWindowOverlay`/`Modal` workarounds
|
|
36
36
|
* 🔍 **Element inspector** - React Native's dev menu inspector now works inside a presented sheet
|
|
37
37
|
* 🎨 **Dim color and opacity** - [Customize the dim](https://sheet.lodev09.com/guides/dimming#dim-color-and-opacity) behind the sheet with `dimColor` and `dimOpacity`
|
|
38
|
+
* 📱 **Foldables** - [Rest the sheet on the hinge](https://sheet.lodev09.com/guides/foldables) of a half-folded iPhone with `foldOptions` (iOS 27.1+)
|
|
38
39
|
|
|
39
40
|
```sh
|
|
40
41
|
npx expo install @lodev09/react-native-true-sheet@beta
|
|
@@ -67,7 +67,7 @@ class TrueSheetOverlayView(private val reactContext: ThemedReactContext) :
|
|
|
67
67
|
|
|
68
68
|
override fun onDetachedFromWindow() {
|
|
69
69
|
viewTreeObserver.removeOnWindowAttachListener(windowAttachListener)
|
|
70
|
-
detachRootView()
|
|
70
|
+
rootContainerView?.post { if (!isAttachedToWindow) detachRootView() }
|
|
71
71
|
super.onDetachedFromWindow()
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -72,6 +72,9 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
72
72
|
// Debounce flag to coalesce rapid layout changes into a single sheet update
|
|
73
73
|
private var isSheetUpdatePending: Boolean = false
|
|
74
74
|
|
|
75
|
+
// didFocus waiting for the slide-back after a child dismissed
|
|
76
|
+
private var isDidFocusPending: Boolean = false
|
|
77
|
+
|
|
75
78
|
// Root container for the coordinator layout (activity or Modal dialog content view)
|
|
76
79
|
internal var rootContainerView: ViewGroup? = null
|
|
77
80
|
|
|
@@ -610,7 +613,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
610
613
|
|
|
611
614
|
// Propagate any additional translation up the stack
|
|
612
615
|
if (additionalTranslation > 0) {
|
|
613
|
-
|
|
616
|
+
viewController.parentSheetView?.addTranslation(additionalTranslation)
|
|
614
617
|
}
|
|
615
618
|
}
|
|
616
619
|
|
|
@@ -642,7 +645,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
642
645
|
|
|
643
646
|
val additionalTranslation = newTranslation - currentTranslation
|
|
644
647
|
if (additionalTranslation > 0) {
|
|
645
|
-
|
|
648
|
+
viewController.parentSheetView?.addTranslation(additionalTranslation, animated = false)
|
|
646
649
|
}
|
|
647
650
|
}
|
|
648
651
|
|
|
@@ -653,7 +656,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
653
656
|
if (viewController.isExpanded) return
|
|
654
657
|
|
|
655
658
|
viewController.translateSheet(viewController.currentTranslationY + amount, animated)
|
|
656
|
-
|
|
659
|
+
viewController.parentSheetView?.addTranslation(amount, animated)
|
|
657
660
|
}
|
|
658
661
|
|
|
659
662
|
/**
|
|
@@ -666,7 +669,25 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
666
669
|
|
|
667
670
|
// Parent should recalculate its translation based on this sheet's position
|
|
668
671
|
val mySheetTop = viewController.detentCalculator.getSheetTopForDetentIndex(viewController.currentDetentIndex)
|
|
669
|
-
|
|
672
|
+
viewController.parentSheetView?.updateTranslationForChild(mySheetTop)
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Resets translation after a child dismissed and emits didFocus once the sheet settles.
|
|
677
|
+
* A sheet presented on top before then cancels the slide-back, so the next blur flushes it.
|
|
678
|
+
*/
|
|
679
|
+
private fun focusAfterResetTranslation() {
|
|
680
|
+
isDidFocusPending = true
|
|
681
|
+
resetTranslation { emitPendingDidFocus() }
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
private fun emitPendingDidFocus() {
|
|
685
|
+
if (!isDidFocusPending) return
|
|
686
|
+
isDidFocusPending = false
|
|
687
|
+
|
|
688
|
+
if (viewController.isPresented && !viewController.isBeingDismissed) {
|
|
689
|
+
viewControllerDidFocus()
|
|
690
|
+
}
|
|
670
691
|
}
|
|
671
692
|
|
|
672
693
|
// ==================== TrueSheetViewControllerDelegate ====================
|
|
@@ -701,6 +722,9 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
701
722
|
}
|
|
702
723
|
|
|
703
724
|
override fun viewControllerDidDismiss(parent: TrueSheetView?) {
|
|
725
|
+
// A slide-back cut short by this sheet's own dismissal never emits; don't carry it over
|
|
726
|
+
isDidFocusPending = false
|
|
727
|
+
|
|
704
728
|
// Detach coordinator from the root container view
|
|
705
729
|
viewController.coordinatorLayout?.let { rootContainerView?.removeView(it) }
|
|
706
730
|
rootContainerView = null
|
|
@@ -715,12 +739,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
715
739
|
// The sheets below stop blending this sheet's dim
|
|
716
740
|
parent?.viewController?.takeIf { it.isPresented }?.updateDimAmount()
|
|
717
741
|
|
|
718
|
-
parent?.
|
|
719
|
-
val parentController = parent.viewController
|
|
720
|
-
if (parentController.isPresented && !parentController.isBeingDismissed) {
|
|
721
|
-
parent.viewControllerDidFocus()
|
|
722
|
-
}
|
|
723
|
-
}
|
|
742
|
+
parent?.focusAfterResetTranslation()
|
|
724
743
|
}
|
|
725
744
|
|
|
726
745
|
override fun viewControllerDidChangeDetent(index: Int, position: Float, detent: Float) {
|
|
@@ -763,6 +782,8 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
763
782
|
}
|
|
764
783
|
|
|
765
784
|
override fun viewControllerWillBlur() {
|
|
785
|
+
emitPendingDidFocus()
|
|
786
|
+
|
|
766
787
|
val surfaceId = UIManagerHelper.getSurfaceId(this)
|
|
767
788
|
eventDispatcher?.dispatchEvent(WillBlurEvent(surfaceId, id))
|
|
768
789
|
}
|
|
@@ -886,6 +886,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
886
886
|
setupSheetDetents()
|
|
887
887
|
setupDimmedBackground()
|
|
888
888
|
setupKeyboardObserver()
|
|
889
|
+
// Before the slide, so an input focused in onWillPresent insets the scrollable
|
|
890
|
+
containerView?.setupKeyboardHandler()
|
|
889
891
|
|
|
890
892
|
displayedBackgroundIndex = detentIndex
|
|
891
893
|
setupBackground(animated = false)
|
|
@@ -1008,11 +1010,9 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1008
1010
|
// Restore isHideable to actual value after present animation
|
|
1009
1011
|
behavior?.isHideable = dismissible
|
|
1010
1012
|
|
|
1011
|
-
containerView?.setupKeyboardHandler()
|
|
1012
|
-
|
|
1013
1013
|
val (index, position, detent) = getDetentInfoWithValue(currentDetentIndex)
|
|
1014
|
-
delegate?.viewControllerDidPresent(index, position, detent)
|
|
1015
1014
|
parentSheetView?.viewControllerDidBlur()
|
|
1015
|
+
delegate?.viewControllerDidPresent(index, position, detent)
|
|
1016
1016
|
delegate?.viewControllerDidFocus()
|
|
1017
1017
|
sheetView?.updateGrabberAccessibilityValue(index, detents.size)
|
|
1018
1018
|
|
|
@@ -253,6 +253,11 @@ class TrueSheetViewManager :
|
|
|
253
253
|
// iOS-specific prop - no-op on Android
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
@ReactProp(name = "foldOptions")
|
|
257
|
+
override fun setFoldOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
258
|
+
// iOS-specific prop - no-op on Android
|
|
259
|
+
}
|
|
260
|
+
|
|
256
261
|
@ReactProp(name = "insetAdjustment")
|
|
257
262
|
override fun setInsetAdjustment(view: TrueSheetView, insetAdjustment: String?) {
|
|
258
263
|
view.setInsetAdjustment(insetAdjustment ?: "automatic")
|
|
@@ -44,22 +44,9 @@ class RNScreensEventObserver : EventDispatcherListener {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
fun capturePresenterScreenFromView(view: View?) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
var current: View? = view
|
|
51
|
-
while (current != null) {
|
|
52
|
-
if (isScreenView(current)) {
|
|
53
|
-
if (presenterScreenTag == 0) {
|
|
54
|
-
presenterScreenTag = current.id
|
|
55
|
-
} else {
|
|
56
|
-
ancestors.add(current.id)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
current = (current.parent as? View)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
ancestorScreenTags = ancestors
|
|
47
|
+
val tags = screenTags(view).toList()
|
|
48
|
+
presenterScreenTag = tags.firstOrNull() ?: 0
|
|
49
|
+
ancestorScreenTags = tags.drop(1).toSet()
|
|
63
50
|
}
|
|
64
51
|
|
|
65
52
|
override fun onEventDispatch(event: Event<*>) {
|
|
@@ -84,5 +71,10 @@ class RNScreensEventObserver : EventDispatcherListener {
|
|
|
84
71
|
|
|
85
72
|
companion object {
|
|
86
73
|
private fun isScreenView(view: View): Boolean = view.javaClass.name == RN_SCREENS_VIEW_CLASS
|
|
74
|
+
|
|
75
|
+
// Tags of the screens enclosing the view, innermost first
|
|
76
|
+
private fun screenTags(view: View?): Sequence<Int> = generateSequence(view) { it.parent as? View }.filter(::isScreenView).map { it.id }
|
|
77
|
+
|
|
78
|
+
fun findPresenterScreenTag(view: View?): Int = screenTags(view).firstOrNull() ?: 0
|
|
87
79
|
}
|
|
88
80
|
}
|
|
@@ -40,6 +40,15 @@ class TrueSheetBottomSheetBehavior<V : View> : BottomSheetBehavior<V>() {
|
|
|
40
40
|
hideFriction = HIDE_FRICTION
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// Material's first layout registers an IME callback that rides the sheet's translationY
|
|
44
|
+
// with the keyboard. TrueSheet positions sheets for the keyboard itself, and the callback
|
|
45
|
+
// overwrites a parent's stack translation when the keyboard rises mid-translation.
|
|
46
|
+
override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
|
|
47
|
+
val handled = super.onLayoutChild(parent, child, layoutDirection)
|
|
48
|
+
ViewCompat.setWindowInsetsAnimationCallback(child, null)
|
|
49
|
+
return handled
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
// With the short threshold, settle at or below the lowest detent like
|
|
44
53
|
// Compose Material3's sheet instead of Material's half-height rule.
|
|
45
54
|
private fun releaseState(child: V, dragged: Boolean, velocityY: Float): Int? {
|
|
@@ -81,14 +81,6 @@ class TrueSheetBottomSheetView(private val reactContext: ThemedReactContext) : F
|
|
|
81
81
|
clipToPadding = false
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
override fun setTranslationY(translationY: Float) {
|
|
85
|
-
// This prevents keyboard inset animations from resetting parent sheet translation
|
|
86
|
-
if (translationY == 0f && this.translationY != 0f) {
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
super.setTranslationY(translationY)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
84
|
// =============================================================================
|
|
93
85
|
// MARK: - Layout
|
|
94
86
|
// =============================================================================
|
|
@@ -12,16 +12,6 @@ object TrueSheetStackManager {
|
|
|
12
12
|
|
|
13
13
|
private val presentedSheetStack = mutableListOf<TrueSheetView>()
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Gets the parent sheet at the given index, if any.
|
|
17
|
-
* Only returns a parent if it's in the same container.
|
|
18
|
-
* Must be called within synchronized block.
|
|
19
|
-
*/
|
|
20
|
-
private fun getParentSheetAt(index: Int, rootContainer: ViewGroup?): TrueSheetView? {
|
|
21
|
-
if (index <= 0) return null
|
|
22
|
-
return presentedSheetStack[index - 1].takeIf { it.rootContainerView == rootContainer }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
15
|
/**
|
|
26
16
|
* Returns the topmost presented and visible sheet, skipping sheets that are dismissing.
|
|
27
17
|
* A dismissing sheet can't parent a new one: its dim would suppress the child's own dim
|
|
@@ -33,6 +23,22 @@ object TrueSheetStackManager {
|
|
|
33
23
|
it.viewController.run { isPresented && isSheetVisible && !isBeingDismissed }
|
|
34
24
|
}
|
|
35
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Returns the topmost sheet hidden by screen navigation that was presented from the same
|
|
28
|
+
* screen as the given sheet. Sheets presented on the covering screen must not parent to it,
|
|
29
|
+
* or the hidden sheet would receive focus and blur events while it can't be seen.
|
|
30
|
+
* Must be called within synchronized block.
|
|
31
|
+
*/
|
|
32
|
+
private fun findScreenHiddenSheet(sheetView: TrueSheetView): TrueSheetView? {
|
|
33
|
+
val screenTag = RNScreensEventObserver.findPresenterScreenTag(sheetView)
|
|
34
|
+
if (screenTag == 0) return null
|
|
35
|
+
|
|
36
|
+
return presentedSheetStack.lastOrNull {
|
|
37
|
+
it.viewController.run { isPresented && wasHiddenByScreen && !isBeingDismissed } &&
|
|
38
|
+
it.screensEventObserver?.presenterScreenTag == screenTag
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
/**
|
|
37
43
|
* Registers a sheet in the stack and returns its parent sheet if any.
|
|
38
44
|
* Only returns a parent if it's in the same container (e.g., same Screen).
|
|
@@ -40,7 +46,8 @@ object TrueSheetStackManager {
|
|
|
40
46
|
@JvmStatic
|
|
41
47
|
fun registerSheet(sheetView: TrueSheetView): TrueSheetView? {
|
|
42
48
|
synchronized(presentedSheetStack) {
|
|
43
|
-
val parentSheet = findTopmostSheet()
|
|
49
|
+
val parentSheet = (findTopmostSheet() ?: findScreenHiddenSheet(sheetView))
|
|
50
|
+
?.takeIf { it.rootContainerView == sheetView.rootContainerView }
|
|
44
51
|
|
|
45
52
|
if (!presentedSheetStack.contains(sheetView)) {
|
|
46
53
|
presentedSheetStack.add(sheetView)
|
|
@@ -62,24 +69,20 @@ object TrueSheetStackManager {
|
|
|
62
69
|
|
|
63
70
|
/**
|
|
64
71
|
* Updates parent sheet translation based on the child sheet's position.
|
|
65
|
-
* Only affects parent sheets in the same container.
|
|
66
72
|
*/
|
|
67
73
|
@JvmStatic
|
|
68
74
|
fun updateParentTranslation(sheetView: TrueSheetView) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
sheetView.viewController.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
val childSheetTop = maxOf(childMinSheetTop, childCurrentSheetTop)
|
|
81
|
-
parentSheet.updateTranslationForChild(childSheetTop)
|
|
82
|
-
}
|
|
75
|
+
val parentSheet = sheetView.viewController.parentSheetView ?: return
|
|
76
|
+
|
|
77
|
+
// Post to ensure layout is complete before reading position
|
|
78
|
+
sheetView.viewController.post {
|
|
79
|
+
val childMinSheetTop = sheetView.viewController.detentCalculator.getSheetTopForDetentIndex(0)
|
|
80
|
+
val childCurrentSheetTop = sheetView.viewController.detentCalculator.getSheetTopForDetentIndex(
|
|
81
|
+
sheetView.viewController.currentDetentIndex
|
|
82
|
+
)
|
|
83
|
+
// Cap to minimum detent position
|
|
84
|
+
val childSheetTop = maxOf(childMinSheetTop, childCurrentSheetTop)
|
|
85
|
+
parentSheet.updateTranslationForChild(childSheetTop)
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -113,18 +116,6 @@ object TrueSheetStackManager {
|
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
/**
|
|
117
|
-
* Gets the parent sheet of the given sheet, if any.
|
|
118
|
-
* Only returns a parent if it's in the same container.
|
|
119
|
-
*/
|
|
120
|
-
@JvmStatic
|
|
121
|
-
fun getParentSheet(sheetView: TrueSheetView): TrueSheetView? {
|
|
122
|
-
synchronized(presentedSheetStack) {
|
|
123
|
-
val index = presentedSheetStack.indexOf(sheetView)
|
|
124
|
-
return getParentSheetAt(index, sheetView.rootContainerView)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
119
|
/**
|
|
129
120
|
* Returns true if the given sheet is the topmost presented sheet in its container.
|
|
130
121
|
*/
|
package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#include "TrueSheetContentViewShadowNode.h"
|
|
2
2
|
|
|
3
|
-
#include <folly/ScopeGuard.h>
|
|
4
3
|
#include <react/renderer/components/view/conversions.h>
|
|
5
4
|
#include <react/renderer/core/ComponentDescriptor.h>
|
|
6
5
|
#include <react/renderer/core/LayoutConstraints.h>
|
|
@@ -95,7 +94,12 @@ void TrueSheetContentViewShadowNode::updateNaturalHeightIfNeeded(const LayoutCon
|
|
|
95
94
|
if (contentChanged_ || !measurement_ || !(measurement_->constraints == constraints) ||
|
|
96
95
|
!(measurement_->context == measurementContext) || measurement_->errata != errata) {
|
|
97
96
|
gIsMeasuringNaturalHeight = true;
|
|
98
|
-
|
|
97
|
+
// Not folly::makeGuard: its terminate() isn't linked into RN < 0.86 on Android.
|
|
98
|
+
struct RestoreMeasurement {
|
|
99
|
+
~RestoreMeasurement() {
|
|
100
|
+
gIsMeasuringNaturalHeight = false;
|
|
101
|
+
}
|
|
102
|
+
} restoreMeasurement;
|
|
99
103
|
auto measurementNode =
|
|
100
104
|
measurement_ ? cloneForMeasurement(*this, *measurementSourceChildren_, measurement_->root->getChildren())
|
|
101
105
|
: cloneForMeasurement(*this, {}, {});
|
|
@@ -287,6 +287,12 @@ using namespace facebook::react;
|
|
|
287
287
|
[self.delegate containerViewScrollViewDidChange];
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
// Footer controls can mount, unmount, or hide deep in its subtree without
|
|
291
|
+
// passing through its own mount hooks or changing its size.
|
|
292
|
+
- (void)contentViewDidMountTransaction {
|
|
293
|
+
[self.delegate containerViewDidMountTransaction];
|
|
294
|
+
}
|
|
295
|
+
|
|
290
296
|
#pragma mark - TrueSheetHeaderViewDelegate
|
|
291
297
|
|
|
292
298
|
- (void)headerViewDidChangeSize:(CGSize)newSize {
|
|
@@ -181,6 +181,8 @@ using namespace facebook::react;
|
|
|
181
181
|
// Layout has settled for the whole tree — the footer overlap (sheet height,
|
|
182
182
|
// scroll view frame) and the keyboard inset are current here
|
|
183
183
|
[self updateBottomInset];
|
|
184
|
+
|
|
185
|
+
[self.delegate contentViewDidMountTransaction];
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
#pragma mark - Scrollable
|
|
@@ -123,6 +123,11 @@ using namespace facebook::react;
|
|
|
123
123
|
|
|
124
124
|
- (void)collectAccessibilityElementsFromView:(UIView *)view into:(NSMutableArray *)elements {
|
|
125
125
|
for (UIView *subview in view.subviews) {
|
|
126
|
+
// Fabric hides `display: none` views instead of unmounting them
|
|
127
|
+
if (subview.hidden) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
126
131
|
if (subview.isAccessibilityElement || subview.accessibilityLabel || subview.accessibilityIdentifier) {
|
|
127
132
|
[elements addObject:subview];
|
|
128
133
|
} else if (subview.accessibilityElements.count > 0) {
|
package/ios/TrueSheetView.mm
CHANGED
|
@@ -284,6 +284,8 @@ using namespace facebook::react;
|
|
|
284
284
|
|
|
285
285
|
_controller.placement = newProps.placement;
|
|
286
286
|
|
|
287
|
+
_controller.foldOptions = newProps.foldOptions;
|
|
288
|
+
|
|
287
289
|
_controller.grabber = newProps.grabber;
|
|
288
290
|
|
|
289
291
|
// Grabber options - check if any non-default values are set
|
|
@@ -866,7 +868,11 @@ using namespace facebook::react;
|
|
|
866
868
|
- (void)containerViewFooterDidChangeSize:(CGSize)newSize {
|
|
867
869
|
[self syncFooterMetrics];
|
|
868
870
|
[self setupSheetDetentsForSizeChange];
|
|
869
|
-
[_controller
|
|
871
|
+
[_controller refreshAccessibilityContainer];
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
- (void)containerViewDidMountTransaction {
|
|
875
|
+
[_controller refreshAccessibilityContainerIfFooterChanged];
|
|
870
876
|
}
|
|
871
877
|
|
|
872
878
|
- (void)containerViewPeekDidChangeSize:(CGSize)newSize {
|
|
@@ -882,11 +888,12 @@ using namespace facebook::react;
|
|
|
882
888
|
|
|
883
889
|
- (void)viewControllerWillPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
|
|
884
890
|
_controller.activeDetentIndex = index;
|
|
891
|
+
// Before emitting, so an input focused in onWillPresent raises a tracked keyboard
|
|
892
|
+
[_containerView setupKeyboardObserverWithViewController:_controller];
|
|
885
893
|
[TrueSheetLifecycleEvents emitWillPresent:_eventEmitter index:index position:position detent:detent];
|
|
886
894
|
}
|
|
887
895
|
|
|
888
896
|
- (void)viewControllerDidPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
|
|
889
|
-
[_containerView setupKeyboardObserverWithViewController:_controller];
|
|
890
897
|
[TrueSheetLifecycleEvents emitDidPresent:_eventEmitter index:index position:position detent:detent];
|
|
891
898
|
|
|
892
899
|
if (_pendingPropsUpdate) {
|
|
@@ -84,6 +84,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
84
84
|
@property (nonatomic, assign) facebook::react::TrueSheetViewBackgroundBlur backgroundBlur;
|
|
85
85
|
@property (nonatomic, assign) facebook::react::TrueSheetViewPresentation presentation;
|
|
86
86
|
@property (nonatomic, assign) facebook::react::TrueSheetViewPlacement placement;
|
|
87
|
+
@property (nonatomic, assign) facebook::react::TrueSheetViewFoldOptionsStruct foldOptions;
|
|
87
88
|
@property (nonatomic, assign) facebook::react::TrueSheetViewInsetAdjustment insetAdjustment;
|
|
88
89
|
@property (nonatomic, assign) BOOL scrollingExpandsSheet;
|
|
89
90
|
@property (nonatomic, assign) CGFloat footerKeyboardOffset;
|
|
@@ -109,6 +110,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
109
110
|
* announced — ahead of the grow/shrink animation, unlike keyboardSheetGrown.
|
|
110
111
|
*/
|
|
111
112
|
@property (nonatomic, assign) CGFloat keyboardHeight;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* How far UIKit grows the sheet for the iPadOS minimized keyboard, which it
|
|
116
|
+
* treats as docked. Taken off every detent so the sheet stays put.
|
|
117
|
+
*/
|
|
118
|
+
@property (nonatomic, assign) CGFloat minimizedKeyboardOverlap;
|
|
119
|
+
|
|
112
120
|
@property (nonatomic, readonly) BOOL isTopmostPresentedController;
|
|
113
121
|
@property (nonatomic, readonly) BOOL isStackedBehindChild;
|
|
114
122
|
@property (nonatomic, weak, nullable) UIView *accessibilityContentView;
|
|
@@ -130,6 +138,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
130
138
|
@property (nonatomic, assign) CGFloat appliedFooterBottomInset;
|
|
131
139
|
|
|
132
140
|
- (void)setupAccessibilityContainer;
|
|
141
|
+
- (void)refreshAccessibilityContainer;
|
|
142
|
+
- (void)refreshAccessibilityContainerIfFooterChanged;
|
|
143
|
+
|
|
133
144
|
- (void)applyActiveDetent;
|
|
134
145
|
- (void)setupActiveDetentWithIndex:(NSInteger)index;
|
|
135
146
|
- (void)resizeToDetentIndex:(NSInteger)index;
|
|
@@ -138,6 +149,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
138
149
|
- (void)setupSheetDetents;
|
|
139
150
|
- (void)setupSheetDetentsForSizeChange;
|
|
140
151
|
- (void)setupSheetDetentsForDetentsChange;
|
|
152
|
+
- (void)invalidateDetents;
|
|
141
153
|
- (void)setupDraggable;
|
|
142
154
|
- (void)setupAnchorViewInView:(UIView *)parentView;
|
|
143
155
|
|