@lodev09/react-native-true-sheet 4.0.0-beta.2 → 4.0.0-beta.20
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 +25 -4
- package/android/build.gradle +22 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +50 -16
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +302 -184
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +5 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +21 -110
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +116 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +2 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +18 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +119 -50
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +360 -163
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +54 -12
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +22 -9
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +84 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +104 -39
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +3 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +15 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +15 -2
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +0 -12
- package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +19 -7
- package/android/src/main/jni/TrueSheetSpec.h +1 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +1 -9
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +110 -30
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +30 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +2 -2
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +9 -8
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +9 -3
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +3 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +4 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +43 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +33 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +7 -40
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +3 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +4 -5
- package/ios/TrueSheetContainerView.h +27 -7
- package/ios/TrueSheetContainerView.mm +31 -11
- package/ios/TrueSheetContentView.h +43 -15
- package/ios/TrueSheetContentView.mm +211 -189
- package/ios/TrueSheetFooterView.h +6 -0
- package/ios/TrueSheetFooterView.mm +93 -17
- package/ios/TrueSheetModule.h +2 -7
- package/ios/TrueSheetModule.mm +7 -16
- package/ios/TrueSheetOverlayView.h +32 -0
- package/ios/TrueSheetOverlayView.mm +161 -0
- package/ios/TrueSheetView.mm +212 -55
- package/ios/TrueSheetViewController.h +31 -3
- package/ios/TrueSheetViewController.mm +393 -94
- package/ios/core/TrueSheetBlurView.h +0 -2
- package/ios/core/TrueSheetBlurView.mm +3 -36
- package/ios/core/TrueSheetDetentCalculator.h +7 -1
- package/ios/core/TrueSheetDetentCalculator.mm +27 -4
- package/ios/core/TrueSheetGrabberView.mm +13 -3
- package/ios/core/TrueSheetKeyboardObserver.mm +2 -0
- package/ios/core/TrueSheetOverlayContainerView.h +31 -0
- package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
- package/ios/events/TrueSheetLifecycleEvents.h +2 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +8 -0
- package/ios/tvos/TrueSheetStubs.mm +12 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.h +1 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.mm +24 -2
- package/lib/module/TrueSheet.js +173 -39
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +218 -243
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/TrueSheetBackground.js +15 -0
- package/lib/module/TrueSheetBackground.js.map +1 -0
- package/lib/module/TrueSheetOverlay.js +30 -0
- package/lib/module/TrueSheetOverlay.js.map +1 -0
- package/lib/module/TrueSheetOverlay.web.js +35 -0
- package/lib/module/TrueSheetOverlay.web.js.map +1 -0
- package/lib/module/TrueSheetPeek.web.js +20 -15
- package/lib/module/TrueSheetPeek.web.js.map +1 -1
- package/lib/module/detentBackgrounds.js +21 -0
- package/lib/module/detentBackgrounds.js.map +1 -0
- package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +14 -10
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +18 -2
- package/lib/module/mocks/index.js.map +1 -1
- package/lib/module/mocks/navigationExpoRouter.js.map +1 -1
- package/lib/module/navigation/base-types.js +2 -0
- package/lib/module/navigation/base-types.js.map +1 -0
- package/lib/module/navigation/createTrueSheetRouter.js +0 -9
- package/lib/module/navigation/createTrueSheetRouter.js.map +1 -1
- package/lib/module/navigation/expo-router/base-types.js +2 -0
- package/lib/module/navigation/expo-router/base-types.js.map +1 -0
- package/lib/module/navigation/expo-router/index.js +10 -7
- package/lib/module/navigation/expo-router/index.js.map +1 -1
- package/lib/module/navigation/expo-router/types.js +4 -0
- package/lib/module/navigation/expo-router/types.js.map +1 -0
- package/lib/module/navigation/index.js.map +1 -1
- package/lib/module/navigation/screen/useSheetScreenState.js +1 -0
- package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -1
- package/lib/module/web/constants.js +1 -1
- package/lib/module/web/constants.js.map +1 -1
- package/lib/module/web/layout.js +168 -0
- package/lib/module/web/layout.js.map +1 -0
- package/lib/module/web/vaul/constants.js +4 -0
- package/lib/module/web/vaul/constants.js.map +1 -1
- package/lib/module/web/vaul/context.js.map +1 -1
- package/lib/module/web/vaul/helpers.js +1 -0
- package/lib/module/web/vaul/helpers.js.map +1 -1
- package/lib/module/web/vaul/index.js +44 -6
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/module/web/vaul/use-snap-points.js +6 -8
- package/lib/module/web/vaul/use-snap-points.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts +6 -0
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +135 -34
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetBackground.d.ts +3 -0
- package/lib/typescript/src/TrueSheetBackground.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts +8 -4
- package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -1
- package/lib/typescript/src/detentBackgrounds.d.ts +10 -0
- package/lib/typescript/src/detentBackgrounds.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +11 -7
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +4 -0
- package/lib/typescript/src/mocks/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +3 -3
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/base-types.d.ts +9 -0
- package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +2 -13
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/index.d.ts +8 -6
- package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
- package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/index.d.ts +3 -4
- package/lib/typescript/src/navigation/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +2 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +41 -5
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/lib/typescript/src/web/constants.d.ts +1 -1
- package/lib/typescript/src/web/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/layout.d.ts +19 -0
- package/lib/typescript/src/web/layout.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/context.d.ts +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/helpers.d.ts +1 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/index.d.ts +7 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
- package/package.json +17 -8
- package/react-native.config.js +1 -0
- package/src/TrueSheet.tsx +206 -48
- package/src/TrueSheet.types.ts +142 -35
- package/src/TrueSheet.web.tsx +270 -290
- package/src/TrueSheetBackground.tsx +17 -0
- package/src/TrueSheetOverlay.tsx +24 -0
- package/src/TrueSheetOverlay.web.tsx +33 -0
- package/src/TrueSheetPeek.web.tsx +25 -23
- package/src/detentBackgrounds.ts +24 -0
- package/src/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +14 -10
- package/src/index.ts +1 -0
- package/src/mocks/index.ts +17 -2
- package/src/mocks/navigationExpoRouter.ts +6 -5
- package/src/navigation/base-types.ts +20 -0
- package/src/navigation/createTrueSheetRouter.ts +5 -33
- package/src/navigation/expo-router/base-types.ts +18 -0
- package/src/navigation/expo-router/index.ts +28 -30
- package/src/navigation/expo-router/types.ts +116 -0
- package/src/navigation/index.ts +6 -7
- package/src/navigation/screen/useSheetScreenState.ts +2 -0
- package/src/navigation/types.ts +75 -22
- package/src/web/constants.ts +1 -1
- package/src/web/layout.ts +196 -0
- package/src/web/vaul/constants.ts +4 -0
- package/src/web/vaul/context.ts +1 -0
- package/src/web/vaul/helpers.ts +5 -0
- package/src/web/vaul/index.tsx +67 -5
- package/src/web/vaul/use-snap-points.ts +6 -14
|
@@ -1,26 +1,50 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
+
import android.os.Build
|
|
4
5
|
import android.text.Editable
|
|
5
6
|
import android.text.TextWatcher
|
|
6
7
|
import android.view.View
|
|
7
8
|
import android.view.ViewGroup
|
|
9
|
+
import android.view.ViewTreeObserver
|
|
8
10
|
import android.widget.EditText
|
|
9
|
-
import android.widget.ScrollView
|
|
10
|
-
import androidx.core.widget.NestedScrollView
|
|
11
11
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
12
|
-
import com.facebook.react.bridge.WritableNativeMap
|
|
13
12
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
14
|
-
import com.facebook.react.uimanager.StateWrapper
|
|
15
13
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
16
14
|
import com.facebook.react.views.view.ReactViewGroup
|
|
17
15
|
import com.lodev09.truesheet.core.TrueSheetKeyboardObserver
|
|
18
16
|
import com.lodev09.truesheet.core.TrueSheetKeyboardObserverDelegate
|
|
17
|
+
import com.lodev09.truesheet.utils.ScreenUtils
|
|
19
18
|
import com.lodev09.truesheet.utils.isDescendantOf
|
|
20
|
-
import com.lodev09.truesheet.utils.smoothScrollBy
|
|
21
19
|
import com.lodev09.truesheet.utils.smoothScrollTo
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* What the sheet insets the bottom of the scroll content for — the safe area
|
|
23
|
+
* while it can scroll, and/or an absolute footer floating over it.
|
|
24
|
+
*/
|
|
25
|
+
enum class TrueSheetContentInsetAdjustment(val safeArea: Boolean, val footer: Boolean) {
|
|
26
|
+
AUTOMATIC(safeArea = true, footer = true),
|
|
27
|
+
SAFE_AREA(safeArea = true, footer = false),
|
|
28
|
+
FOOTER(safeArea = false, footer = true),
|
|
29
|
+
NEVER(safeArea = false, footer = false);
|
|
30
|
+
|
|
31
|
+
companion object {
|
|
32
|
+
fun fromString(value: String?): TrueSheetContentInsetAdjustment =
|
|
33
|
+
when (value) {
|
|
34
|
+
"safe-area" -> SAFE_AREA
|
|
35
|
+
"footer" -> FOOTER
|
|
36
|
+
"never" -> NEVER
|
|
37
|
+
else -> AUTOMATIC
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
data class ScrollableOptions(
|
|
43
|
+
val keyboardScrollOffset: Float = 0f,
|
|
44
|
+
val keyboardOffset: Float = 0f,
|
|
45
|
+
val scrollingExpandsSheet: Boolean = true,
|
|
46
|
+
val contentInsetAdjustment: TrueSheetContentInsetAdjustment = TrueSheetContentInsetAdjustment.AUTOMATIC
|
|
47
|
+
)
|
|
24
48
|
|
|
25
49
|
/**
|
|
26
50
|
* Delegate interface for content view size changes
|
|
@@ -32,10 +56,34 @@ interface TrueSheetContentViewDelegate {
|
|
|
32
56
|
|
|
33
57
|
/**
|
|
34
58
|
* Keyboard occlusion adjustment below the content — positive for an absolute
|
|
35
|
-
* footer
|
|
36
|
-
* negative for a relative footer sitting behind the keyboard shielding
|
|
59
|
+
* footer floating over the viewport's bottom edge (extends the caret reveal),
|
|
60
|
+
* negative for a relative footer sitting behind the keyboard shielding that
|
|
61
|
+
* much of its overlap (reduces the keyboard padding).
|
|
37
62
|
*/
|
|
38
63
|
val footerKeyboardOcclusion: Int
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Layout height of an absolute footer floating over the content, including
|
|
67
|
+
* its absorbed safe-area inset — 0 for a relative footer.
|
|
68
|
+
*/
|
|
69
|
+
val absoluteFooterHeight: Int
|
|
70
|
+
|
|
71
|
+
// Includes the controller's translation during sheet transitions.
|
|
72
|
+
val absoluteFooterTop: Int
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* false when an absolute footer stays behind the keyboard instead of rising
|
|
76
|
+
* above it.
|
|
77
|
+
*/
|
|
78
|
+
val footerAvoidsKeyboard: Boolean
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A relative footer sits below the content and absorbs the bottom safe-area
|
|
82
|
+
* inset — the scrollable doesn't reach the sheet's bottom edge, so no
|
|
83
|
+
* content inset is applied (mirrors iOS, where UIKit resolves this
|
|
84
|
+
* geometrically via the scroll view's safe area).
|
|
85
|
+
*/
|
|
86
|
+
val hasRelativeFooter: Boolean
|
|
39
87
|
}
|
|
40
88
|
|
|
41
89
|
/**
|
|
@@ -45,44 +93,42 @@ interface TrueSheetContentViewDelegate {
|
|
|
45
93
|
@SuppressLint("ViewConstructor")
|
|
46
94
|
class TrueSheetContentView(private val reactContext: ThemedReactContext) : ReactViewGroup(reactContext) {
|
|
47
95
|
var delegate: TrueSheetContentViewDelegate? = null
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
private var lastWidth = 0
|
|
51
|
-
private var lastHeight = 0
|
|
52
|
-
|
|
53
|
-
private var pinnedScrollView: ViewGroup? = null
|
|
54
|
-
private var observedScrollChild: View? = null
|
|
55
|
-
private var originalScrollViewPaddingBottom: Int = 0
|
|
56
|
-
private var bottomInset: Int = 0
|
|
57
|
-
private var scrollableBounded = false
|
|
58
|
-
private var isReportPending = false
|
|
59
|
-
|
|
60
|
-
// Content growth is invisible to layout once the viewport is bounded, so track
|
|
61
|
-
// the scroll content size directly to keep the auto detent height in sync.
|
|
62
|
-
private val scrollChildLayoutListener =
|
|
63
|
-
View.OnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom ->
|
|
64
|
-
if (bottom - top != oldBottom - oldTop) {
|
|
65
|
-
reportSizeIfChanged()
|
|
66
|
-
}
|
|
67
|
-
}
|
|
96
|
+
|
|
97
|
+
private var detectedScrollView: ViewGroup? = null
|
|
68
98
|
|
|
69
99
|
/**
|
|
70
|
-
* Content height
|
|
71
|
-
*
|
|
72
|
-
* Falls back to the view height
|
|
100
|
+
* Content height measured unconstrained by the shadow node — the height the
|
|
101
|
+
* content wants regardless of container bounds (see
|
|
102
|
+
* TrueSheetContentViewShadowNode). Falls back to the view height before the
|
|
103
|
+
* first state update.
|
|
73
104
|
*/
|
|
74
105
|
val naturalHeight: Int
|
|
75
|
-
get()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
106
|
+
get() = if (lastNaturalHeight > 0) lastNaturalHeight else height
|
|
107
|
+
|
|
108
|
+
private var lastNaturalHeight = 0
|
|
109
|
+
|
|
110
|
+
fun updateNaturalHeight(heightDp: Double) {
|
|
111
|
+
val heightPx = heightDp.toFloat().dpToPx().toInt()
|
|
112
|
+
if (heightPx == lastNaturalHeight) return
|
|
113
|
+
lastNaturalHeight = heightPx
|
|
114
|
+
delegate?.contentViewDidChangeSize(width, heightPx)
|
|
115
|
+
}
|
|
84
116
|
|
|
85
117
|
private var keyboardScrollOffset: Float = 0f
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Adjustment added to the keyboard bottom inset applied to the detected
|
|
121
|
+
* scrollable — negative values reduce the inset (e.g. to cancel out safe-area
|
|
122
|
+
* padding already baked into the content's paddingBottom).
|
|
123
|
+
*/
|
|
124
|
+
private var keyboardOffset: Float = 0f
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* How much of keyboardOffset actually landed in the applied inset — the
|
|
128
|
+
* caret reveal compensates by this so it still targets the real keyboard edge.
|
|
129
|
+
*/
|
|
130
|
+
private var appliedKeyboardOffset = 0
|
|
131
|
+
|
|
86
132
|
private var keyboardObserver: TrueSheetKeyboardObserver? = null
|
|
87
133
|
|
|
88
134
|
private var watchedEditText: EditText? = null
|
|
@@ -92,178 +138,207 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
|
|
|
92
138
|
set(value) {
|
|
93
139
|
field = value
|
|
94
140
|
keyboardScrollOffset = value?.keyboardScrollOffset?.dpToPx() ?: 0f
|
|
141
|
+
keyboardOffset = value?.keyboardOffset?.dpToPx() ?: 0f
|
|
142
|
+
updateContentInset()
|
|
95
143
|
}
|
|
96
144
|
|
|
97
145
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
146
|
+
* Bottom safe-area inset applied to the scrollable's content padding while
|
|
147
|
+
* the content can scroll — Android counterpart of iOS's
|
|
148
|
+
* `contentInsetAdjustmentBehavior="automatic"`. Already zero when the
|
|
149
|
+
* sheet's `insetAdjustment` is `'never'`.
|
|
101
150
|
*/
|
|
102
|
-
var
|
|
151
|
+
var bottomInset: Int = 0
|
|
103
152
|
set(value) {
|
|
104
153
|
if (field == value) return
|
|
105
154
|
field = value
|
|
106
|
-
|
|
107
|
-
setScrollableBounded(value)
|
|
108
|
-
}
|
|
155
|
+
updateContentInset()
|
|
109
156
|
}
|
|
110
157
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
158
|
+
private var baseBottomInset = 0
|
|
159
|
+
private var keyboardBottomInset = 0
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Height of the absolute footer the scroll content is padded by (see
|
|
163
|
+
* ScrollableOptions.contentInsetAdjustment), applied on top of the
|
|
164
|
+
* safe-area or keyboard inset.
|
|
165
|
+
*/
|
|
166
|
+
private var footerBottomInset = 0
|
|
167
|
+
|
|
168
|
+
private val scrollableLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
|
|
169
|
+
updateContentInset()
|
|
114
170
|
}
|
|
115
171
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
checkScrollViewChanged()
|
|
172
|
+
private val scrollContentLayoutListener = View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
|
173
|
+
updateContentInset()
|
|
119
174
|
}
|
|
120
175
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
176
|
+
override fun onAttachedToWindow() {
|
|
177
|
+
super.onAttachedToWindow()
|
|
178
|
+
viewTreeObserver.addOnGlobalLayoutListener(scrollableLayoutListener)
|
|
125
179
|
}
|
|
126
180
|
|
|
127
|
-
override fun
|
|
128
|
-
|
|
129
|
-
|
|
181
|
+
override fun onDetachedFromWindow() {
|
|
182
|
+
viewTreeObserver.removeOnGlobalLayoutListener(scrollableLayoutListener)
|
|
183
|
+
super.onDetachedFromWindow()
|
|
130
184
|
}
|
|
131
185
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
post {
|
|
142
|
-
isReportPending = false
|
|
143
|
-
reportSizeNow()
|
|
144
|
-
}
|
|
145
|
-
return
|
|
186
|
+
/**
|
|
187
|
+
* React tag of the user-provided scrollable (see the `scrollableRef` prop).
|
|
188
|
+
* Setting a new handle clears the currently resolved ScrollView.
|
|
189
|
+
*/
|
|
190
|
+
var scrollableHandle: Int = -1
|
|
191
|
+
set(value) {
|
|
192
|
+
if (field == value) return
|
|
193
|
+
field = value
|
|
194
|
+
clearScrollable()
|
|
146
195
|
}
|
|
147
196
|
|
|
148
|
-
|
|
197
|
+
override fun addView(child: View?, index: Int) {
|
|
198
|
+
super.addView(child, index)
|
|
199
|
+
checkScrollViewChanged()
|
|
149
200
|
}
|
|
150
201
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
lastWidth = width
|
|
155
|
-
lastHeight = newHeight
|
|
156
|
-
delegate?.contentViewDidChangeSize(width, newHeight)
|
|
157
|
-
}
|
|
202
|
+
override fun removeViewAt(index: Int) {
|
|
203
|
+
super.removeViewAt(index)
|
|
204
|
+
checkScrollViewChanged()
|
|
158
205
|
}
|
|
159
206
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
* for auto detents — otherwise content lays out naturally like a regular view.
|
|
164
|
-
*/
|
|
165
|
-
private fun setScrollableBounded(bounded: Boolean) {
|
|
166
|
-
if (scrollableBounded == bounded) return
|
|
167
|
-
scrollableBounded = bounded
|
|
168
|
-
|
|
169
|
-
stateWrapper?.let {
|
|
170
|
-
val newState = WritableNativeMap()
|
|
171
|
-
newState.putBoolean("scrollableBounded", bounded)
|
|
172
|
-
it.updateState(newState)
|
|
207
|
+
private fun checkScrollViewChanged() {
|
|
208
|
+
if (detectedScrollView == null || detectedScrollView?.isDescendantOf(this) == false) {
|
|
209
|
+
delegate?.contentViewScrollViewDidChange()
|
|
173
210
|
}
|
|
174
211
|
}
|
|
175
212
|
|
|
176
|
-
fun setupScrollable(
|
|
177
|
-
// Check if
|
|
178
|
-
if (
|
|
213
|
+
fun setupScrollable() {
|
|
214
|
+
// Check if the detected scroll view is still valid (still in view hierarchy)
|
|
215
|
+
if (detectedScrollView != null && detectedScrollView?.isDescendantOf(this) == false) {
|
|
179
216
|
clearScrollable()
|
|
180
217
|
}
|
|
181
218
|
|
|
182
|
-
|
|
183
|
-
if (pinnedScrollView != null && this.bottomInset == bottomInset) {
|
|
219
|
+
if (detectedScrollView != null) {
|
|
184
220
|
return
|
|
185
221
|
}
|
|
186
222
|
|
|
187
|
-
val scrollView = findScrollView(
|
|
223
|
+
val scrollView = findScrollView() ?: return
|
|
188
224
|
|
|
189
|
-
|
|
190
|
-
if (pinnedScrollView == null) {
|
|
191
|
-
originalScrollViewPaddingBottom = scrollView.paddingBottom
|
|
192
|
-
pinnedScrollView = scrollView
|
|
225
|
+
detectedScrollView = scrollView
|
|
193
226
|
|
|
194
|
-
|
|
195
|
-
|
|
227
|
+
scrollView.isNestedScrollingEnabled = true
|
|
228
|
+
(scrollView.parent as? SwipeRefreshLayout)?.isNestedScrollingEnabled = false
|
|
196
229
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
230
|
+
scrollView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
|
231
|
+
if (scrollY != oldScrollY) {
|
|
232
|
+
delegate?.contentViewDidScroll()
|
|
201
233
|
}
|
|
234
|
+
}
|
|
202
235
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
reportSizeIfChanged()
|
|
236
|
+
// Restore the inset before ReactScrollView's listener clamps the offset.
|
|
237
|
+
scrollView.getChildAt(0)?.let { child ->
|
|
238
|
+
if (scrollView is View.OnLayoutChangeListener) child.removeOnLayoutChangeListener(scrollView)
|
|
239
|
+
child.addOnLayoutChangeListener(scrollContentLayoutListener)
|
|
240
|
+
if (scrollView is View.OnLayoutChangeListener) child.addOnLayoutChangeListener(scrollView)
|
|
209
241
|
}
|
|
210
242
|
|
|
211
|
-
|
|
243
|
+
updateContentInset()
|
|
244
|
+
}
|
|
212
245
|
|
|
213
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Re-applies the base content inset — the bottom safe-area inset while the
|
|
248
|
+
* content can scroll, no relative footer absorbs it, and
|
|
249
|
+
* `contentInsetAdjustment` includes the safe area.
|
|
250
|
+
*/
|
|
251
|
+
fun updateContentInset() {
|
|
252
|
+
val scrollView = detectedScrollView ?: return
|
|
214
253
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
254
|
+
val enabled = scrollableOptions?.contentInsetAdjustment?.safeArea ?: true
|
|
255
|
+
baseBottomInset = if (enabled && delegate?.hasRelativeFooter != true && canScrollContent(scrollView)) {
|
|
256
|
+
bottomInset
|
|
257
|
+
} else {
|
|
258
|
+
0
|
|
219
259
|
}
|
|
220
|
-
}
|
|
221
260
|
|
|
222
|
-
|
|
223
|
-
val scrollView = pinnedScrollView ?: return
|
|
224
|
-
scrollView.clipToPadding = false
|
|
225
|
-
scrollView.setPadding(
|
|
226
|
-
scrollView.paddingLeft,
|
|
227
|
-
scrollView.paddingTop,
|
|
228
|
-
scrollView.paddingRight,
|
|
229
|
-
paddingBottom
|
|
230
|
-
)
|
|
261
|
+
updateScrollViewInsetForKeyboard(keyboardObserver?.currentHeight ?: 0)
|
|
231
262
|
}
|
|
232
263
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
setScrollViewPaddingBottom(originalScrollViewPaddingBottom)
|
|
238
|
-
observedScrollChild?.removeOnLayoutChangeListener(scrollChildLayoutListener)
|
|
239
|
-
observedScrollChild = null
|
|
240
|
-
setScrollableBounded(false)
|
|
241
|
-
pinnedScrollView = null
|
|
242
|
-
originalScrollViewPaddingBottom = 0
|
|
243
|
-
bottomInset = 0
|
|
244
|
-
reportSizeIfChanged()
|
|
264
|
+
// Fabric's measured height excludes the native inset, avoiding feedback.
|
|
265
|
+
private fun canScrollContent(scrollView: ViewGroup): Boolean {
|
|
266
|
+
val child = scrollView.getChildAt(0) ?: return false
|
|
267
|
+
return child.measuredHeight > scrollView.height - scrollView.paddingTop - scrollView.paddingBottom
|
|
245
268
|
}
|
|
246
269
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
270
|
+
// The keyboard covers the safe-area region, so the larger inset wins over a sum
|
|
271
|
+
private fun applyBottomInset() {
|
|
272
|
+
val safeAreaInset = maxOf(baseBottomInset, keyboardBottomInset)
|
|
273
|
+
footerBottomInset = footerInsetAbove(safeAreaInset)
|
|
274
|
+
setScrollContentInset(safeAreaInset + footerBottomInset)
|
|
250
275
|
}
|
|
251
276
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
277
|
+
// A pinned footer uses its positioned top so overlap follows the sheet's
|
|
278
|
+
// animation, even before the container reaches its final height. A rising
|
|
279
|
+
// footer uses its layout top because the keyboard inset carries its rise.
|
|
280
|
+
// The safe-area inset baked into the footer is already
|
|
281
|
+
// covered by the safe-area or keyboard inset when one applies — only the
|
|
282
|
+
// footer's occlusion above it stacks on top. A pinned footer adds only the
|
|
283
|
+
// overlap not already covered by the safe-area or keyboard inset.
|
|
284
|
+
private fun footerInsetAbove(safeAreaInset: Int): Int {
|
|
285
|
+
if (scrollableOptions?.contentInsetAdjustment?.footer == false) return 0
|
|
286
|
+
val scrollView = detectedScrollView ?: return 0
|
|
287
|
+
val container = parent as? View ?: return 0
|
|
288
|
+
val footerHeight = delegate?.absoluteFooterHeight ?: 0
|
|
289
|
+
if (footerHeight <= 0) return 0
|
|
290
|
+
|
|
291
|
+
var scrollBottom = scrollView.bottom
|
|
292
|
+
var view: View = scrollView.parent as? View ?: return 0
|
|
293
|
+
while (view !== container) {
|
|
294
|
+
scrollBottom += view.top
|
|
295
|
+
view = view.parent as? View ?: return 0
|
|
255
296
|
}
|
|
256
297
|
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
298
|
+
val footerTop = if (delegate?.footerAvoidsKeyboard == false) {
|
|
299
|
+
delegate?.absoluteFooterTop ?: return 0
|
|
300
|
+
} else {
|
|
301
|
+
container.height - footerHeight
|
|
302
|
+
}
|
|
303
|
+
var inset = scrollBottom - footerTop
|
|
304
|
+
if (delegate?.footerAvoidsKeyboard == false) {
|
|
305
|
+
inset -= safeAreaInset
|
|
306
|
+
} else if (safeAreaInset > 0) {
|
|
307
|
+
inset -= footerHeight - maxOf(0, delegate?.footerKeyboardOcclusion ?: 0)
|
|
264
308
|
}
|
|
309
|
+
return maxOf(0, inset)
|
|
310
|
+
}
|
|
265
311
|
|
|
266
|
-
|
|
312
|
+
private fun setScrollContentInset(inset: Int) {
|
|
313
|
+
val scrollView = detectedScrollView ?: return
|
|
314
|
+
val child = scrollView.getChildAt(0) ?: return
|
|
315
|
+
scrollView.clipToPadding = false
|
|
316
|
+
// ScrollView's canScrollVertically ignores bottom padding. Extend the
|
|
317
|
+
// content bounds instead, keeping Fabric's measured height as the baseline.
|
|
318
|
+
child.bottom = child.top + child.measuredHeight + inset
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun clearScrollable() {
|
|
322
|
+
detectedScrollView?.setOnScrollChangeListener(null as View.OnScrollChangeListener?)
|
|
323
|
+
detectedScrollView?.getChildAt(0)?.removeOnLayoutChangeListener(scrollContentLayoutListener)
|
|
324
|
+
detectedScrollView?.isNestedScrollingEnabled = false
|
|
325
|
+
(detectedScrollView?.parent as? SwipeRefreshLayout)?.isNestedScrollingEnabled = true
|
|
326
|
+
setScrollContentInset(0)
|
|
327
|
+
detectedScrollView = null
|
|
328
|
+
baseBottomInset = 0
|
|
329
|
+
keyboardBottomInset = 0
|
|
330
|
+
footerBottomInset = 0
|
|
331
|
+
appliedKeyboardOffset = 0
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Resolves the user-provided `scrollableHandle` within the content subtree —
|
|
336
|
+
* React tags are view ids on Android.
|
|
337
|
+
*/
|
|
338
|
+
fun findScrollView(): ViewGroup? {
|
|
339
|
+
if (detectedScrollView != null) return detectedScrollView
|
|
340
|
+
if (scrollableHandle <= 0) return null
|
|
341
|
+
return findViewById<View>(scrollableHandle) as? ViewGroup
|
|
267
342
|
}
|
|
268
343
|
|
|
269
344
|
// ==================== Keyboard Handling ====================
|
|
@@ -273,8 +348,19 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
|
|
|
273
348
|
|
|
274
349
|
keyboardObserver = TrueSheetKeyboardObserver(this, reactContext).apply {
|
|
275
350
|
delegate = object : TrueSheetKeyboardObserverDelegate {
|
|
276
|
-
|
|
351
|
+
// Drive the inset per keyboard animation frame so the content tracks
|
|
352
|
+
// the keyboard edge instead of jumping to the final inset up front.
|
|
353
|
+
// On hide, the shrinking inset gradually clamps the scroll position
|
|
354
|
+
// back in sync with the keyboard.
|
|
355
|
+
override fun keyboardDidChangeHeight(height: Int) {
|
|
277
356
|
updateScrollViewInsetForKeyboard(height)
|
|
357
|
+
|
|
358
|
+
// Follow the caret frame-by-frame — only API 30+ delivers
|
|
359
|
+
// incremental heights; legacy fires once after the keyboard is
|
|
360
|
+
// already up, where keyboardDidShow's smooth reveal takes over
|
|
361
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !isHiding) {
|
|
362
|
+
scrollToFocusedInput(smooth = false)
|
|
363
|
+
}
|
|
278
364
|
}
|
|
279
365
|
|
|
280
366
|
override fun keyboardDidShow(height: Int) {
|
|
@@ -284,7 +370,6 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
|
|
|
284
370
|
|
|
285
371
|
override fun keyboardWillHide() {
|
|
286
372
|
detachCaretListener()
|
|
287
|
-
updateScrollViewInsetForKeyboard(0)
|
|
288
373
|
}
|
|
289
374
|
|
|
290
375
|
override fun focusDidChange(newFocus: View) {
|
|
@@ -329,30 +414,44 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
|
|
|
329
414
|
}
|
|
330
415
|
|
|
331
416
|
private fun updateScrollViewInsetForKeyboard(keyboardHeight: Int) {
|
|
332
|
-
val scrollView =
|
|
333
|
-
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
417
|
+
val scrollView = detectedScrollView ?: return
|
|
418
|
+
|
|
419
|
+
// Short or nested scroll views can end above the sheet's bottom edge.
|
|
420
|
+
// Their position also accounts for space occupied by a relative footer.
|
|
421
|
+
keyboardBottomInset = if (keyboardHeight > 0) {
|
|
422
|
+
val location = IntArray(2)
|
|
423
|
+
scrollView.getLocationInWindow(location)
|
|
424
|
+
val keyboardTop = ScreenUtils.getRealScreenHeight(reactContext) - keyboardHeight
|
|
425
|
+
val baseInset = maxOf(0, location[1] + scrollView.height - keyboardTop)
|
|
426
|
+
val adjustedInset = maxOf(0, baseInset + keyboardOffset.toInt())
|
|
427
|
+
appliedKeyboardOffset = adjustedInset - baseInset
|
|
428
|
+
if (delegate?.footerAvoidsKeyboard == false) {
|
|
429
|
+
appliedKeyboardOffset += footerInsetAbove(maxOf(baseBottomInset, adjustedInset)) -
|
|
430
|
+
footerInsetAbove(maxOf(baseBottomInset, baseInset))
|
|
431
|
+
}
|
|
432
|
+
adjustedInset
|
|
340
433
|
} else {
|
|
341
|
-
|
|
434
|
+
appliedKeyboardOffset = 0
|
|
435
|
+
0
|
|
342
436
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
scrollView.post { nudgeScrollView() }
|
|
437
|
+
applyBottomInset()
|
|
438
|
+
clampScrollPosition()
|
|
346
439
|
}
|
|
347
440
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
441
|
+
// Content bounds changes don't re-clamp the scroll position until the next layout
|
|
442
|
+
// pass — clamp synchronously so the content follows the shrinking inset on
|
|
443
|
+
// every keyboard frame instead of snapping afterwards
|
|
444
|
+
private fun clampScrollPosition() {
|
|
445
|
+
val scrollView = detectedScrollView ?: return
|
|
446
|
+
val child = scrollView.getChildAt(0) ?: return
|
|
447
|
+
val maxScrollY = maxOf(0, child.height - (scrollView.height - scrollView.paddingTop - scrollView.paddingBottom))
|
|
448
|
+
if (scrollView.scrollY > maxScrollY) {
|
|
449
|
+
scrollView.scrollTo(scrollView.scrollX, maxScrollY)
|
|
450
|
+
}
|
|
352
451
|
}
|
|
353
452
|
|
|
354
|
-
private fun scrollToFocusedInput() {
|
|
355
|
-
val scrollView =
|
|
453
|
+
private fun scrollToFocusedInput(smooth: Boolean = true) {
|
|
454
|
+
val scrollView = detectedScrollView ?: findScrollView() ?: return
|
|
356
455
|
val focusedView = findFocus() ?: return
|
|
357
456
|
|
|
358
457
|
val focusedLocation = IntArray(2)
|
|
@@ -379,17 +478,36 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
|
|
|
379
478
|
caretBottom = viewTop + focusedView.height
|
|
380
479
|
}
|
|
381
480
|
|
|
481
|
+
// An absolute footer floats over the viewport's bottom edge — extend the
|
|
482
|
+
// caret target so it clears the footer, not just the keyboard. Not needed
|
|
483
|
+
// while the footer inset is applied (the visible range already ends above
|
|
484
|
+
// it) or when the footer stays behind the keyboard.
|
|
485
|
+
val footerOcclusion = if (footerBottomInset > 0 || delegate?.footerAvoidsKeyboard == false) {
|
|
486
|
+
0
|
|
487
|
+
} else {
|
|
488
|
+
maxOf(0, delegate?.footerKeyboardOcclusion ?: 0)
|
|
489
|
+
}
|
|
490
|
+
|
|
382
491
|
val offset = keyboardScrollOffset.toInt()
|
|
383
|
-
val
|
|
492
|
+
val appliedInset = maxOf(baseBottomInset, keyboardBottomInset) + footerBottomInset
|
|
493
|
+
val visibleHeight = scrollView.height - scrollView.paddingBottom - appliedInset + appliedKeyboardOffset
|
|
384
494
|
val visibleTop = scrollView.scrollY
|
|
385
495
|
val visibleBottom = scrollView.scrollY + visibleHeight
|
|
386
496
|
|
|
387
|
-
when {
|
|
388
|
-
caretBottom + offset > visibleBottom ->
|
|
389
|
-
|
|
497
|
+
val targetY = when {
|
|
498
|
+
caretBottom + offset + footerOcclusion > visibleBottom ->
|
|
499
|
+
caretBottom + offset + footerOcclusion - visibleHeight
|
|
390
500
|
|
|
391
501
|
caretTop - offset < visibleTop ->
|
|
392
|
-
|
|
502
|
+
(caretTop - offset).coerceAtLeast(0)
|
|
503
|
+
|
|
504
|
+
else -> return
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (smooth) {
|
|
508
|
+
scrollView.smoothScrollTo(0, targetY)
|
|
509
|
+
} else {
|
|
510
|
+
scrollView.scrollTo(0, targetY)
|
|
393
511
|
}
|
|
394
512
|
}
|
|
395
513
|
|
|
@@ -20,7 +20,11 @@ class TrueSheetContentViewManager : ViewGroupManager<TrueSheetContentView>() {
|
|
|
20
20
|
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetContentView = TrueSheetContentView(reactContext)
|
|
21
21
|
|
|
22
22
|
override fun updateState(view: TrueSheetContentView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
|
|
23
|
-
|
|
23
|
+
stateWrapper?.stateData?.let { data ->
|
|
24
|
+
if (data.hasKey("naturalHeight")) {
|
|
25
|
+
view.updateNaturalHeight(data.getDouble("naturalHeight"))
|
|
26
|
+
}
|
|
27
|
+
}
|
|
24
28
|
return null
|
|
25
29
|
}
|
|
26
30
|
|