@momo-kits/native-kits 0.300.4 → 0.300.5-debug
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/build.gradle.kts +13 -0
- package/compose/build.gradle.kts +197 -0
- package/compose/build.gradle.kts.backup +197 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +20 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +153 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +1071 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +81 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +115 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +478 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +361 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +308 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +330 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +92 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +560 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +501 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +236 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +180 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +17 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +287 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +137 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +116 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +215 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +404 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +732 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +233 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +217 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +377 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +455 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +103 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +413 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +363 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +133 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +135 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +118 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +44 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +62 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +42 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +34 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +217 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
- package/gradle/libs.versions.toml +68 -0
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/gradle.properties +26 -0
- package/gradlew +252 -0
- package/gradlew.bat +94 -0
- package/ios/native-kits.podspec +1 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/ios-demo/README.md +120 -0
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.CubicBezierEasing
|
|
5
|
+
import androidx.compose.animation.core.tween
|
|
6
|
+
import androidx.compose.foundation.background
|
|
7
|
+
import androidx.compose.foundation.border
|
|
8
|
+
import androidx.compose.foundation.gestures.detectDragGestures
|
|
9
|
+
import androidx.compose.foundation.layout.Box
|
|
10
|
+
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
11
|
+
import androidx.compose.foundation.layout.Column
|
|
12
|
+
import androidx.compose.foundation.layout.Row
|
|
13
|
+
import androidx.compose.foundation.layout.Spacer
|
|
14
|
+
import androidx.compose.foundation.layout.fillMaxHeight
|
|
15
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
16
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
17
|
+
import androidx.compose.foundation.layout.height
|
|
18
|
+
import androidx.compose.foundation.layout.heightIn
|
|
19
|
+
import androidx.compose.foundation.layout.offset
|
|
20
|
+
import androidx.compose.foundation.layout.padding
|
|
21
|
+
import androidx.compose.foundation.layout.size
|
|
22
|
+
import androidx.compose.foundation.layout.width
|
|
23
|
+
import androidx.compose.foundation.layout.absolutePadding
|
|
24
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
25
|
+
import androidx.compose.runtime.Composable
|
|
26
|
+
import androidx.compose.runtime.DisposableEffect
|
|
27
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
28
|
+
import androidx.compose.runtime.remember
|
|
29
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
30
|
+
import androidx.compose.ui.Alignment
|
|
31
|
+
import androidx.compose.ui.Modifier
|
|
32
|
+
import androidx.compose.ui.graphics.Brush
|
|
33
|
+
import androidx.compose.ui.graphics.Color
|
|
34
|
+
import androidx.compose.ui.input.pointer.pointerInput
|
|
35
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
36
|
+
import androidx.compose.ui.unit.IntOffset
|
|
37
|
+
import androidx.compose.ui.unit.dp
|
|
38
|
+
import kotlinx.coroutines.launch
|
|
39
|
+
import vn.momo.kits.components.Divider
|
|
40
|
+
import vn.momo.kits.components.Icon
|
|
41
|
+
import vn.momo.kits.components.Text
|
|
42
|
+
import vn.momo.kits.const.AppTheme
|
|
43
|
+
import vn.momo.kits.const.Colors
|
|
44
|
+
import vn.momo.kits.const.Radius
|
|
45
|
+
import vn.momo.kits.const.Spacing
|
|
46
|
+
import vn.momo.kits.application.LocalContext
|
|
47
|
+
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
48
|
+
import vn.momo.kits.const.AppNavigationBar
|
|
49
|
+
import vn.momo.kits.const.Typography
|
|
50
|
+
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
51
|
+
import vn.momo.kits.modifier.conditional
|
|
52
|
+
import vn.momo.kits.modifier.noFeedbackClickable
|
|
53
|
+
import vn.momo.kits.platform.BackHandler
|
|
54
|
+
import vn.momo.kits.platform.getScreenHeight
|
|
55
|
+
import vn.momo.kits.layout.getScreenLayout
|
|
56
|
+
|
|
57
|
+
// iPhone Duo inner display: center the sheet instead of spanning the width (RN BottomSheet).
|
|
58
|
+
private val DUO_REGULAR_MIN_WIDTH = 600.dp
|
|
59
|
+
|
|
60
|
+
@Composable
|
|
61
|
+
internal fun BottomSheet(
|
|
62
|
+
content: @Composable () -> Unit,
|
|
63
|
+
header: BottomHeader,
|
|
64
|
+
isSurface: Boolean = false,
|
|
65
|
+
barrierDismissible: Boolean = true,
|
|
66
|
+
draggable: Boolean = true,
|
|
67
|
+
useBottomInset: Boolean = true,
|
|
68
|
+
footerComponent: (@Composable () -> Unit)? = null,
|
|
69
|
+
onDismiss: (() -> Unit)?
|
|
70
|
+
) {
|
|
71
|
+
val layout = getScreenLayout()
|
|
72
|
+
val isDuo = layout.isIPhoneDuoDevice
|
|
73
|
+
val isDuoCentered = isDuo && layout.width >= DUO_REGULAR_MIN_WIDTH
|
|
74
|
+
// the screen is the outer display on iPhone Duo, even when unfolded
|
|
75
|
+
val screenHeightDp = if (isDuo) layout.height else getScreenHeight()
|
|
76
|
+
val screenHeightPx = with(LocalDensity.current) { screenHeightDp.toPx() }
|
|
77
|
+
val sheetOffset = remember { Animatable(screenHeightPx) }
|
|
78
|
+
|
|
79
|
+
val backgroundAlpha = remember { Animatable(0f) }
|
|
80
|
+
val dynamicAlpha = ((1f - (sheetOffset.value / screenHeightPx)).coerceIn(0f, 1f)) * 0.3f
|
|
81
|
+
val alpha = backgroundAlpha.value + dynamicAlpha
|
|
82
|
+
|
|
83
|
+
val sheetCloseOffset = with(LocalDensity.current) { 100.dp.toPx() }
|
|
84
|
+
|
|
85
|
+
val coroutineScope = rememberCoroutineScope()
|
|
86
|
+
|
|
87
|
+
val maxApi = LocalMaxApi.current
|
|
88
|
+
val context = LocalContext.current
|
|
89
|
+
|
|
90
|
+
DisposableEffect(Unit) {
|
|
91
|
+
ScreenTracker.trackPopupDisplayed(
|
|
92
|
+
maxApi = maxApi,
|
|
93
|
+
context = context,
|
|
94
|
+
parentScreenName = ScreenTracker.getLastScreenName()
|
|
95
|
+
)
|
|
96
|
+
onDispose { }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
suspend fun openEvent(){
|
|
100
|
+
backgroundAlpha.animateTo(
|
|
101
|
+
targetValue = 0.3f,
|
|
102
|
+
animationSpec = tween(
|
|
103
|
+
durationMillis = 100,
|
|
104
|
+
easing = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
sheetOffset.animateTo(
|
|
108
|
+
targetValue = 0f,
|
|
109
|
+
animationSpec = tween(
|
|
110
|
+
durationMillis = 350,
|
|
111
|
+
easing = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fun closeEvent(){
|
|
117
|
+
coroutineScope.launch {
|
|
118
|
+
sheetOffset.animateTo(
|
|
119
|
+
targetValue = screenHeightPx,
|
|
120
|
+
animationSpec = tween(
|
|
121
|
+
durationMillis = 200,
|
|
122
|
+
easing = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
backgroundAlpha.animateTo(
|
|
126
|
+
targetValue = 0f,
|
|
127
|
+
animationSpec = tween(
|
|
128
|
+
durationMillis = 100,
|
|
129
|
+
easing = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
LaunchedEffect(Unit) {
|
|
137
|
+
openEvent()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
DisposableEffect(Unit) {
|
|
141
|
+
OverplayComponentRegistry.bindClose { closeEvent() }
|
|
142
|
+
onDispose {
|
|
143
|
+
onDismiss?.invoke()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
BackHandler(true){
|
|
148
|
+
closeEvent()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
BoxWithConstraints(
|
|
152
|
+
modifier = Modifier
|
|
153
|
+
.fillMaxSize()
|
|
154
|
+
.background(Color.Black.copy(alpha = alpha))
|
|
155
|
+
.noFeedbackClickable {
|
|
156
|
+
if(barrierDismissible) closeEvent()
|
|
157
|
+
}
|
|
158
|
+
) {
|
|
159
|
+
val parentHeight = with(LocalDensity.current) { constraints.maxHeight.toDp() }
|
|
160
|
+
val maxHeight = if (isDuo) {
|
|
161
|
+
parentHeight - maxOf(layout.duoTopInset, Spacing.XL)
|
|
162
|
+
} else {
|
|
163
|
+
parentHeight - 90.dp
|
|
164
|
+
}
|
|
165
|
+
// landscape side buttons span the full height; in portrait the side status bar only covers the top
|
|
166
|
+
val sideInset = isDuo && !isDuoCentered && layout.width > layout.height
|
|
167
|
+
|
|
168
|
+
Box(
|
|
169
|
+
modifier = Modifier
|
|
170
|
+
.align(Alignment.BottomCenter)
|
|
171
|
+
.offset { IntOffset(x = 0, y = sheetOffset.value.toInt()) }
|
|
172
|
+
.then(
|
|
173
|
+
if (isDuoCentered) {
|
|
174
|
+
// keeps the portrait width in landscape, like system sheets
|
|
175
|
+
Modifier.width(
|
|
176
|
+
minOf(
|
|
177
|
+
minOf(layout.width, layout.height) - Spacing.L * 2,
|
|
178
|
+
layout.width - maxOf(layout.insetLeft, layout.insetRight, Spacing.L) * 2,
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
} else {
|
|
182
|
+
Modifier.fillMaxWidth()
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
.heightIn(max = maxHeight)
|
|
186
|
+
.background(
|
|
187
|
+
color = if (isSurface) AppTheme.current.colors.background.surface else AppTheme.current.colors.background.default,
|
|
188
|
+
shape = RoundedCornerShape(topStart = Radius.M, topEnd = Radius.M)
|
|
189
|
+
)
|
|
190
|
+
.conditional(IsShowBaseLineDebug) {
|
|
191
|
+
border(1.dp, Colors.blue_03)
|
|
192
|
+
}
|
|
193
|
+
.noFeedbackClickable { },
|
|
194
|
+
contentAlignment = Alignment.BottomCenter
|
|
195
|
+
) {
|
|
196
|
+
val bottomInset = if (useBottomInset) {
|
|
197
|
+
(AppNavigationBar.current - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
198
|
+
} else 0.dp
|
|
199
|
+
Column(
|
|
200
|
+
Modifier
|
|
201
|
+
.padding(bottom = bottomInset)
|
|
202
|
+
.conditional(sideInset) {
|
|
203
|
+
absolutePadding(left = layout.insetLeft, right = layout.insetRight)
|
|
204
|
+
}
|
|
205
|
+
) {
|
|
206
|
+
Box(
|
|
207
|
+
modifier = Modifier
|
|
208
|
+
.height(72.dp)
|
|
209
|
+
.fillMaxWidth()
|
|
210
|
+
.conditional(draggable) {
|
|
211
|
+
pointerInput(Unit) {
|
|
212
|
+
detectDragGestures(
|
|
213
|
+
onDrag = { change, dragAmount ->
|
|
214
|
+
change.consume()
|
|
215
|
+
coroutineScope.launch {
|
|
216
|
+
val newOffset = (sheetOffset.value + dragAmount.y).coerceAtLeast(0f)
|
|
217
|
+
sheetOffset.snapTo(newOffset)
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
onDragEnd = {
|
|
221
|
+
coroutineScope.launch {
|
|
222
|
+
if (sheetOffset.value > sheetCloseOffset) {
|
|
223
|
+
closeEvent()
|
|
224
|
+
} else {
|
|
225
|
+
sheetOffset.animateTo(0f)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
) {
|
|
233
|
+
Column(
|
|
234
|
+
modifier = Modifier
|
|
235
|
+
.fillMaxSize()
|
|
236
|
+
.padding(horizontal = Spacing.M),
|
|
237
|
+
horizontalAlignment = Alignment.CenterHorizontally
|
|
238
|
+
) {
|
|
239
|
+
Spacer(Modifier.height(8.dp))
|
|
240
|
+
Box(
|
|
241
|
+
modifier = Modifier
|
|
242
|
+
.height(4.dp)
|
|
243
|
+
.width(40.dp)
|
|
244
|
+
.background(
|
|
245
|
+
color = Colors.black_06,
|
|
246
|
+
shape = RoundedCornerShape(Radius.S)
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
Spacer(Modifier.height(4.dp))
|
|
250
|
+
Box(Modifier.fillMaxWidth().height(56.dp), contentAlignment = Alignment.Center){
|
|
251
|
+
when (header) {
|
|
252
|
+
is BottomHeader.Title -> {
|
|
253
|
+
Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
|
|
254
|
+
Box(Modifier.size(24.dp))
|
|
255
|
+
Box(Modifier.fillMaxHeight().weight(1f), contentAlignment = Alignment.Center){
|
|
256
|
+
Text(
|
|
257
|
+
text = header.data,
|
|
258
|
+
color = Colors.black_17,
|
|
259
|
+
style = Typography.headerDefaultBold
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
Box(Modifier
|
|
263
|
+
.size(24.dp)
|
|
264
|
+
.noFeedbackClickable {
|
|
265
|
+
closeEvent()
|
|
266
|
+
},
|
|
267
|
+
contentAlignment = Alignment.Center
|
|
268
|
+
){
|
|
269
|
+
Icon(source = "navigation_close")
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
is BottomHeader.Custom -> {
|
|
274
|
+
header.content()
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
Divider()
|
|
281
|
+
if (footerComponent != null) {
|
|
282
|
+
Box(Modifier.weight(1f, fill = false)) {
|
|
283
|
+
content()
|
|
284
|
+
}
|
|
285
|
+
BottomSheetFooter(footerComponent)
|
|
286
|
+
} else if (isDuo) {
|
|
287
|
+
// content shrinks so a tall sheet keeps its header
|
|
288
|
+
Box(Modifier.weight(1f, fill = false)) {
|
|
289
|
+
content()
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
content()
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
@Composable
|
|
300
|
+
private fun BottomSheetFooter(footerComponent: @Composable () -> Unit) {
|
|
301
|
+
val shadowBrush = remember {
|
|
302
|
+
Brush.verticalGradient(
|
|
303
|
+
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.05f))
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
Box {
|
|
308
|
+
Box(
|
|
309
|
+
Modifier
|
|
310
|
+
.fillMaxWidth()
|
|
311
|
+
.background(AppTheme.current.colors.background.surface)
|
|
312
|
+
.conditional(IsShowBaseLineDebug) {
|
|
313
|
+
border(1.dp, Colors.blue_03)
|
|
314
|
+
}
|
|
315
|
+
.padding(vertical = Spacing.S)
|
|
316
|
+
) {
|
|
317
|
+
footerComponent()
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
Box(
|
|
321
|
+
modifier = Modifier
|
|
322
|
+
.fillMaxWidth()
|
|
323
|
+
.height(6.dp)
|
|
324
|
+
.offset(x = 0.dp, y = (-6).dp)
|
|
325
|
+
.background(shadowBrush)
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
sealed class BottomHeader {
|
|
331
|
+
data class Title(
|
|
332
|
+
val data: String = "Bottom Sheet Title",
|
|
333
|
+
) : BottomHeader()
|
|
334
|
+
|
|
335
|
+
data class Custom(
|
|
336
|
+
val content: @Composable () -> Unit
|
|
337
|
+
) : BottomHeader()
|
|
338
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
interface HostBackTarget {
|
|
4
|
+
fun canPop(): Boolean
|
|
5
|
+
|
|
6
|
+
fun onBack()
|
|
7
|
+
|
|
8
|
+
fun backStarted()
|
|
9
|
+
fun backProgressed(progress: Float)
|
|
10
|
+
fun backCompleted()
|
|
11
|
+
fun backCancelled()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
object HostBackGestureBridge {
|
|
15
|
+
private val targets = mutableListOf<HostBackTarget>()
|
|
16
|
+
private var gestureTarget: HostBackTarget? = null
|
|
17
|
+
|
|
18
|
+
var shouldUseFloatingArrowBack: Boolean = false
|
|
19
|
+
|
|
20
|
+
fun checkCanPop(): Boolean = targets.isNotEmpty()
|
|
21
|
+
|
|
22
|
+
fun canPopInner(): Boolean = top()?.canPop() == true
|
|
23
|
+
|
|
24
|
+
fun pop() {
|
|
25
|
+
top()?.onBack()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fun started() {
|
|
29
|
+
val target = top() ?: return
|
|
30
|
+
gestureTarget = target
|
|
31
|
+
target.backStarted()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fun progressed(progress: Float) {
|
|
35
|
+
gestureTarget?.backProgressed(progress.coerceIn(0f, 1f))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fun completed() {
|
|
39
|
+
(gestureTarget ?: top())?.backCompleted()
|
|
40
|
+
gestureTarget = null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fun cancelled() {
|
|
44
|
+
gestureTarget?.backCancelled()
|
|
45
|
+
gestureTarget = null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fun attach(target: HostBackTarget) {
|
|
49
|
+
targets += target
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fun detach(target: HostBackTarget) {
|
|
53
|
+
targets -= target
|
|
54
|
+
if (gestureTarget === target) gestureTarget = null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private fun top(): HostBackTarget? = targets.lastOrNull()
|
|
58
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.CubicBezierEasing
|
|
5
|
+
import androidx.compose.animation.core.tween
|
|
6
|
+
import androidx.compose.foundation.background
|
|
7
|
+
import androidx.compose.foundation.border
|
|
8
|
+
import androidx.compose.foundation.clickable
|
|
9
|
+
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
10
|
+
import androidx.compose.foundation.layout.Box
|
|
11
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
12
|
+
import androidx.compose.foundation.layout.padding
|
|
13
|
+
import androidx.compose.foundation.layout.wrapContentSize
|
|
14
|
+
import androidx.compose.runtime.*
|
|
15
|
+
import androidx.compose.ui.Alignment
|
|
16
|
+
import androidx.compose.ui.Modifier
|
|
17
|
+
import androidx.compose.ui.draw.alpha
|
|
18
|
+
import androidx.compose.ui.draw.scale
|
|
19
|
+
import androidx.compose.ui.graphics.Color
|
|
20
|
+
import androidx.compose.ui.unit.dp
|
|
21
|
+
import kotlinx.coroutines.launch
|
|
22
|
+
import vn.momo.kits.application.LocalContext
|
|
23
|
+
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
24
|
+
import vn.momo.kits.const.Colors
|
|
25
|
+
import vn.momo.kits.modifier.conditional
|
|
26
|
+
import vn.momo.kits.modifier.noFeedbackClickable
|
|
27
|
+
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
28
|
+
import vn.momo.kits.platform.BackHandler
|
|
29
|
+
import vn.momo.kits.layout.getScreenLayout
|
|
30
|
+
|
|
31
|
+
@Composable
|
|
32
|
+
internal fun ModalScreen(
|
|
33
|
+
content: @Composable () -> Unit,
|
|
34
|
+
barrierDismissible: Boolean = true,
|
|
35
|
+
onDismiss: (() -> Unit)? = null
|
|
36
|
+
) {
|
|
37
|
+
val navigator = LocalNavigator.current
|
|
38
|
+
|
|
39
|
+
val alpha = remember { Animatable(0f) }
|
|
40
|
+
val scale = remember { Animatable(0.8f) }
|
|
41
|
+
|
|
42
|
+
val coroutineScope = rememberCoroutineScope()
|
|
43
|
+
|
|
44
|
+
val maxApi = LocalMaxApi.current
|
|
45
|
+
val context = LocalContext.current
|
|
46
|
+
|
|
47
|
+
DisposableEffect(Unit) {
|
|
48
|
+
ScreenTracker.trackPopupDisplayed(
|
|
49
|
+
maxApi = maxApi,
|
|
50
|
+
context = context,
|
|
51
|
+
parentScreenName = ScreenTracker.getLastScreenName()
|
|
52
|
+
)
|
|
53
|
+
onDispose { }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun openEvent() {
|
|
57
|
+
coroutineScope.launch {
|
|
58
|
+
launch {
|
|
59
|
+
alpha.animateTo(
|
|
60
|
+
targetValue = 1f,
|
|
61
|
+
animationSpec = tween(durationMillis = 250)
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
launch {
|
|
65
|
+
scale.animateTo(
|
|
66
|
+
targetValue = 1f,
|
|
67
|
+
animationSpec = tween(
|
|
68
|
+
durationMillis = 250,
|
|
69
|
+
easing = CubicBezierEasing(0.2f, 0.0f, 0f, 1f)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun closeEvent() {
|
|
77
|
+
coroutineScope.launch {
|
|
78
|
+
alpha.animateTo(
|
|
79
|
+
targetValue = 0f,
|
|
80
|
+
animationSpec = tween(durationMillis = 200)
|
|
81
|
+
)
|
|
82
|
+
scale.animateTo(
|
|
83
|
+
targetValue = 0.8f,
|
|
84
|
+
animationSpec = tween(durationMillis = 200)
|
|
85
|
+
)
|
|
86
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
LaunchedEffect(Unit) {
|
|
91
|
+
openEvent()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
DisposableEffect(Unit) {
|
|
95
|
+
OverplayComponentRegistry.bindClose { closeEvent() }
|
|
96
|
+
onDispose {
|
|
97
|
+
onDismiss?.invoke()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
BackHandler(enabled = true) {
|
|
102
|
+
closeEvent()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
val layout = getScreenLayout()
|
|
106
|
+
|
|
107
|
+
Box(
|
|
108
|
+
modifier = Modifier
|
|
109
|
+
.fillMaxSize()
|
|
110
|
+
.background(Color.Black.copy(alpha = 0.6f * alpha.value))
|
|
111
|
+
.noFeedbackClickable {
|
|
112
|
+
if(barrierDismissible) closeEvent()
|
|
113
|
+
}
|
|
114
|
+
// center below the side status bar and above the home indicator
|
|
115
|
+
.conditional(layout.isIPhoneDuoDevice) {
|
|
116
|
+
padding(top = layout.duoTopInset, bottom = layout.insetBottom)
|
|
117
|
+
},
|
|
118
|
+
contentAlignment = Alignment.Center
|
|
119
|
+
) {
|
|
120
|
+
Box(
|
|
121
|
+
modifier = Modifier
|
|
122
|
+
.scale(scale.value)
|
|
123
|
+
.alpha(alpha.value)
|
|
124
|
+
.wrapContentSize()
|
|
125
|
+
.conditional(IsShowBaseLineDebug) {
|
|
126
|
+
border(1.dp, Colors.blue_03)
|
|
127
|
+
}
|
|
128
|
+
.clickable(
|
|
129
|
+
indication = null,
|
|
130
|
+
interactionSource = remember { MutableInteractionSource() }
|
|
131
|
+
) {},
|
|
132
|
+
contentAlignment = Alignment.Center
|
|
133
|
+
) {
|
|
134
|
+
content()
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.gestures.ScrollableState
|
|
4
|
+
import androidx.compose.runtime.*
|
|
5
|
+
import androidx.compose.ui.graphics.Color
|
|
6
|
+
import vn.momo.kits.navigation.bottomtab.setBottomTabOption
|
|
7
|
+
import vn.momo.kits.navigation.component.*
|
|
8
|
+
|
|
9
|
+
class Navigation(
|
|
10
|
+
val id: Int = -1,
|
|
11
|
+
val bottomTabIndex: Int = -1,
|
|
12
|
+
val initOptions: NavigationOptions? = null,
|
|
13
|
+
private val registry: DynamicScreenRegistry? = null
|
|
14
|
+
) {
|
|
15
|
+
private val _options = mutableStateOf(initOptions ?: NavigationOptions())
|
|
16
|
+
val currentOptions: State<NavigationOptions> get() = _options
|
|
17
|
+
val options: NavigationOptions get() = _options.value
|
|
18
|
+
|
|
19
|
+
private val _isBottomTabRoot = mutableStateOf(false)
|
|
20
|
+
internal val isBottomTabRoot: Boolean get() = _isBottomTabRoot.value
|
|
21
|
+
internal fun markAsBottomTabRoot() { _isBottomTabRoot.value = true }
|
|
22
|
+
|
|
23
|
+
fun setOptions(
|
|
24
|
+
onBackHandler: (() -> Unit)? = null,
|
|
25
|
+
hiddenBack: Boolean? = null,
|
|
26
|
+
headerBackProps: HeaderBackProps? = null,
|
|
27
|
+
headerTitle: HeaderTitle? = null,
|
|
28
|
+
titlePosition: TitlePosition? = null,
|
|
29
|
+
headerRight: HeaderRight? = null,
|
|
30
|
+
headerType: HeaderType? = null,
|
|
31
|
+
scrollData: ScrollData? = null,
|
|
32
|
+
backgroundColor: Color? = null,
|
|
33
|
+
// AI-GENERATED START: custom screen background
|
|
34
|
+
backgroundComponent: (@Composable () -> Unit)? = null,
|
|
35
|
+
// AI-GENERATED END: custom screen background
|
|
36
|
+
tintColor: Color? = null,
|
|
37
|
+
footerComponent: (@Composable () -> Unit)? = null,
|
|
38
|
+
footerTransparent: Boolean? = null,
|
|
39
|
+
footerUseMargin: Boolean? = null,
|
|
40
|
+
floatingButtonProps: FloatingButtonProps? = null,
|
|
41
|
+
keyboardOptions: KeyboardOptions? = null
|
|
42
|
+
) {
|
|
43
|
+
updateOptions(
|
|
44
|
+
options.copy(
|
|
45
|
+
onBackHandler = onBackHandler ?: options.onBackHandler,
|
|
46
|
+
hiddenBack = hiddenBack ?: options.hiddenBack,
|
|
47
|
+
headerBackProps = headerBackProps ?: options.headerBackProps,
|
|
48
|
+
headerTitle = headerTitle ?: options.headerTitle,
|
|
49
|
+
titlePosition = titlePosition ?: options.titlePosition,
|
|
50
|
+
headerRight = headerRight ?: options.headerRight,
|
|
51
|
+
headerType = headerType ?: options.headerType,
|
|
52
|
+
scrollData = scrollData ?: options.scrollData,
|
|
53
|
+
backgroundColor = backgroundColor ?: options.backgroundColor,
|
|
54
|
+
// AI-GENERATED START: custom screen background
|
|
55
|
+
backgroundComponent = backgroundComponent ?: options.backgroundComponent,
|
|
56
|
+
// AI-GENERATED END: custom screen background
|
|
57
|
+
tintColor = tintColor ?: options.tintColor,
|
|
58
|
+
footerComponent = footerComponent ?: options.footerComponent,
|
|
59
|
+
footerTransparent = footerTransparent ?: options.footerTransparent,
|
|
60
|
+
footerUseMargin = footerUseMargin ?: options.footerUseMargin,
|
|
61
|
+
floatingButtonProps = floatingButtonProps ?: options.floatingButtonProps,
|
|
62
|
+
keyboardOptions = keyboardOptions ?: options.keyboardOptions,
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fun setOptions(newOptions: NavigationOptions) {
|
|
68
|
+
updateOptions(newOptions)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private fun updateOptions(updated: NavigationOptions) {
|
|
72
|
+
_options.value = updated
|
|
73
|
+
if (bottomTabIndex != -1) setBottomTabOption(bottomTabIndex, updated)
|
|
74
|
+
if (id != -1) registry?.setOptions(id, updated)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
val LocalNavigation = staticCompositionLocalOf<Navigation> {
|
|
79
|
+
error("No NavigationStack provided")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@Stable
|
|
83
|
+
data class NavigationOptions(
|
|
84
|
+
val screenName: String? = null,
|
|
85
|
+
val onBackHandler: (() -> Unit)? = null,
|
|
86
|
+
val hiddenBack: Boolean = false,
|
|
87
|
+
val headerBackProps: HeaderBackProps = HeaderBackProps(),
|
|
88
|
+
val headerTitle: HeaderTitle = HeaderTitle.Default("Stack"),
|
|
89
|
+
val titlePosition: TitlePosition = TitlePosition.LEFT,
|
|
90
|
+
val headerRight: HeaderRight = HeaderRight.Toolkit(),
|
|
91
|
+
val headerType: HeaderType = HeaderType.Default(),
|
|
92
|
+
val scrollData: ScrollData = ScrollData(),
|
|
93
|
+
val backgroundColor: Color? = null,
|
|
94
|
+
// AI-GENERATED START: custom screen background (SwiftUI `NavigationOptions.background`)
|
|
95
|
+
/** Drawn instead of `backgroundColor` over the whole screen: under the header, outside the keyboard padding. */
|
|
96
|
+
val backgroundComponent: @Composable (() -> Unit)? = null,
|
|
97
|
+
// AI-GENERATED END: custom screen background (SwiftUI `NavigationOptions.background`)
|
|
98
|
+
val tintColor: Color? = null,
|
|
99
|
+
val footerComponent: @Composable (() -> Unit)? = null,
|
|
100
|
+
val footerTransparent: Boolean = false,
|
|
101
|
+
val footerUseMargin: Boolean = true,
|
|
102
|
+
val floatingButtonProps: FloatingButtonProps? = null,
|
|
103
|
+
val keyboardOptions: KeyboardOptions = KeyboardOptions()
|
|
104
|
+
) {
|
|
105
|
+
internal fun hasFooter() : Boolean = footerComponent != null
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
data class KeyboardOptions(
|
|
109
|
+
val keyboardShouldPersistTaps: Boolean = false,
|
|
110
|
+
val useAvoidKeyboard: Boolean = true
|
|
111
|
+
)
|
|
112
|
+
data class ScrollData(
|
|
113
|
+
val scrollable: Boolean = true,
|
|
114
|
+
val scrollState: ScrollableState? = null,
|
|
115
|
+
val scrollToTopCallback: (() -> Unit)? = null,
|
|
116
|
+
)
|