@momo-kits/native-kits 0.152.4-beta.2 → 0.152.4-beta.3
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/CODE_OF_CONDUCT.md +133 -0
- package/CONTRIBUTING.md +114 -0
- package/LICENSE +20 -0
- package/README.md +7 -0
- package/build.gradle.kts +32 -0
- package/compose/MoMoComposeKits.podspec +54 -0
- package/compose/build.gradle.kts +149 -0
- package/compose/src/androidMain/AndroidManifest.xml +2 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +105 -0
- package/compose/src/commonMain/composeResources/files/lottie_circle_loader.json +1 -0
- package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
- package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +57 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +201 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +222 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +48 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +715 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +214 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +236 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +77 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +27 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +334 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +345 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +90 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +131 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +543 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +69 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +143 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +179 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +111 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +384 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +160 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +234 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +232 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +236 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +228 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +364 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +34 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +85 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +95 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +64 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +89 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -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 +84 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +208 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +172 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +199 -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 +237 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +191 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +306 -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 +13 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +191 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +258 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +35 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +59 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +68 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +49 -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 +232 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +111 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +94 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +159 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +232 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScaleSizeScope.kt +17 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +459 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +216 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +180 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +251 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +80 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +31 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +385 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +38 -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 +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +88 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +144 -0
- package/gradle.properties +19 -0
- package/gradlew +240 -0
- package/gradlew.bat +91 -0
- package/ios/Application/ApplicationEnvironment.swift +50 -0
- package/ios/Application/Components.swift +263 -0
- package/ios/Application/ComposeApi.swift +22 -0
- package/ios/Application/FloatingButton.swift +172 -0
- package/ios/Application/HeaderRight.swift +271 -0
- package/ios/Application/Screen.swift +249 -0
- package/ios/Badge/BadgeDot.swift +31 -0
- package/ios/Button/Button.swift +211 -0
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +126 -0
- package/ios/Checkbox/Checkbox.swift +81 -0
- package/ios/Chip/Chip.swift +96 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +172 -0
- package/ios/Colors+Radius+Spacing/Radius.swift +22 -0
- package/ios/Colors+Radius+Spacing/Spacing.swift +12 -0
- package/ios/Extensions/Color++.swift +25 -0
- package/ios/Icon/Icon.swift +51 -0
- package/ios/Image/Image.swift +70 -0
- package/ios/Input/Input.swift +207 -0
- package/ios/Input/InputPhoneNumber.swift +176 -0
- package/ios/Input/InputSearch.swift +238 -0
- package/ios/Input/InputTextArea.swift +242 -0
- package/ios/Lottie/LottieView.swift +86 -0
- package/ios/OTPKeyboard/KeyboardButton.swift +41 -0
- package/ios/OTPKeyboard/OTPKeyboard.swift +145 -0
- package/ios/Popup/PopupDisplay.swift +284 -0
- package/ios/Popup/PopupInput.swift +96 -0
- package/ios/Popup/PopupPromotion.swift +73 -0
- package/ios/PopupView/FullscreenPopup.swift +251 -0
- package/ios/PopupView/Modifiers.swift +158 -0
- package/ios/PopupView/PopupView.swift +289 -0
- package/ios/PopupView/Utils++.swift +281 -0
- package/ios/ScrollIndicator/ScrollIndicator.swift +110 -0
- package/ios/Swipeable/SwipeCell.swift +278 -0
- package/ios/Swipeable/SwipeCellModel.swift +86 -0
- package/ios/Switch/Switch.swift +44 -0
- package/ios/Template/Logo/Logo.swift +75 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +120 -0
- package/ios/Theme.md +18 -0
- package/ios/Typography/Text.swift +140 -0
- package/ios/Typography/Typography.swift +95 -0
- package/ios/native-kits.podspec +18 -0
- package/package.json +6 -7
- package/settings.gradle.kts +25 -0
- package/shared/build.gradle.kts +0 -74
|
@@ -0,0 +1,232 @@
|
|
|
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.gestures.detectDragGestures
|
|
8
|
+
import androidx.compose.foundation.layout.Box
|
|
9
|
+
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
10
|
+
import androidx.compose.foundation.layout.Column
|
|
11
|
+
import androidx.compose.foundation.layout.Row
|
|
12
|
+
import androidx.compose.foundation.layout.Spacer
|
|
13
|
+
import androidx.compose.foundation.layout.fillMaxHeight
|
|
14
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
15
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
16
|
+
import androidx.compose.foundation.layout.height
|
|
17
|
+
import androidx.compose.foundation.layout.heightIn
|
|
18
|
+
import androidx.compose.foundation.layout.offset
|
|
19
|
+
import androidx.compose.foundation.layout.padding
|
|
20
|
+
import androidx.compose.foundation.layout.size
|
|
21
|
+
import androidx.compose.foundation.layout.width
|
|
22
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
23
|
+
import androidx.compose.runtime.Composable
|
|
24
|
+
import androidx.compose.runtime.DisposableEffect
|
|
25
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
26
|
+
import androidx.compose.runtime.remember
|
|
27
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
28
|
+
import androidx.compose.ui.Alignment
|
|
29
|
+
import androidx.compose.ui.Modifier
|
|
30
|
+
import androidx.compose.ui.graphics.Color
|
|
31
|
+
import androidx.compose.ui.input.pointer.pointerInput
|
|
32
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
33
|
+
import androidx.compose.ui.unit.IntOffset
|
|
34
|
+
import androidx.compose.ui.unit.dp
|
|
35
|
+
import kotlinx.coroutines.launch
|
|
36
|
+
import vn.momo.kits.components.Divider
|
|
37
|
+
import vn.momo.kits.components.Icon
|
|
38
|
+
import vn.momo.kits.components.Text
|
|
39
|
+
import vn.momo.kits.const.AppTheme
|
|
40
|
+
import vn.momo.kits.const.Colors
|
|
41
|
+
import vn.momo.kits.const.Radius
|
|
42
|
+
import vn.momo.kits.const.Spacing
|
|
43
|
+
import vn.momo.kits.const.Typography
|
|
44
|
+
import vn.momo.kits.modifier.noFeedbackClickable
|
|
45
|
+
import vn.momo.kits.platform.BackHandler
|
|
46
|
+
import vn.momo.kits.platform.getScreenHeight
|
|
47
|
+
|
|
48
|
+
@Composable
|
|
49
|
+
internal fun BottomSheet(
|
|
50
|
+
content: @Composable () -> Unit,
|
|
51
|
+
header: BottomHeader,
|
|
52
|
+
isSurface: Boolean = false,
|
|
53
|
+
barrierDismissible: Boolean = true,
|
|
54
|
+
onDismiss: (() -> Unit)?
|
|
55
|
+
) {
|
|
56
|
+
val navigator = LocalNavigator.current
|
|
57
|
+
|
|
58
|
+
val screenHeightDp = getScreenHeight()
|
|
59
|
+
val screenHeightPx = with(LocalDensity.current) { screenHeightDp.toPx() }
|
|
60
|
+
val sheetOffset = remember { Animatable(screenHeightPx) }
|
|
61
|
+
|
|
62
|
+
val backgroundAlpha = remember { Animatable(0f) }
|
|
63
|
+
val dynamicAlpha = ((1f - (sheetOffset.value / screenHeightPx)).coerceIn(0f, 1f)) * 0.3f
|
|
64
|
+
val alpha = backgroundAlpha.value + dynamicAlpha
|
|
65
|
+
|
|
66
|
+
val sheetCloseOffset = with(LocalDensity.current) { 100.dp.toPx() }
|
|
67
|
+
|
|
68
|
+
val coroutineScope = rememberCoroutineScope()
|
|
69
|
+
|
|
70
|
+
suspend fun openEvent(){
|
|
71
|
+
backgroundAlpha.animateTo(
|
|
72
|
+
targetValue = 0.3f,
|
|
73
|
+
animationSpec = tween(
|
|
74
|
+
durationMillis = 100,
|
|
75
|
+
easing = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
sheetOffset.animateTo(
|
|
79
|
+
targetValue = 0f,
|
|
80
|
+
animationSpec = tween(
|
|
81
|
+
durationMillis = 350,
|
|
82
|
+
easing = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fun closeEvent(){
|
|
88
|
+
coroutineScope.launch {
|
|
89
|
+
sheetOffset.animateTo(
|
|
90
|
+
targetValue = screenHeightPx,
|
|
91
|
+
animationSpec = tween(
|
|
92
|
+
durationMillis = 200,
|
|
93
|
+
easing = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
backgroundAlpha.animateTo(
|
|
97
|
+
targetValue = 0f,
|
|
98
|
+
animationSpec = tween(
|
|
99
|
+
durationMillis = 100,
|
|
100
|
+
easing = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
navigator.pop()
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
LaunchedEffect(Unit) {
|
|
108
|
+
openEvent()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
DisposableEffect(Unit) {
|
|
112
|
+
OverplayComponentRegistry.bindClose { closeEvent() }
|
|
113
|
+
onDispose {
|
|
114
|
+
onDismiss?.invoke()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
BackHandler(true){
|
|
119
|
+
closeEvent()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
BoxWithConstraints(
|
|
123
|
+
modifier = Modifier
|
|
124
|
+
.fillMaxSize()
|
|
125
|
+
.background(Color.Black.copy(alpha = alpha))
|
|
126
|
+
.noFeedbackClickable {
|
|
127
|
+
if(barrierDismissible) closeEvent()
|
|
128
|
+
}
|
|
129
|
+
) {
|
|
130
|
+
val parentHeight = with(LocalDensity.current) { constraints.maxHeight.toDp() }
|
|
131
|
+
Box(
|
|
132
|
+
modifier = Modifier
|
|
133
|
+
.align(Alignment.BottomCenter)
|
|
134
|
+
.offset { IntOffset(x = 0, y = sheetOffset.value.toInt()) }
|
|
135
|
+
.fillMaxWidth()
|
|
136
|
+
.heightIn(max = parentHeight - 90.dp)
|
|
137
|
+
.background(
|
|
138
|
+
color = if (isSurface) AppTheme.current.colors.background.surface else AppTheme.current.colors.background.default,
|
|
139
|
+
shape = RoundedCornerShape(topStart = Radius.M, topEnd = Radius.M)
|
|
140
|
+
)
|
|
141
|
+
.noFeedbackClickable { },
|
|
142
|
+
contentAlignment = Alignment.BottomCenter
|
|
143
|
+
) {
|
|
144
|
+
Column {
|
|
145
|
+
Box(
|
|
146
|
+
modifier = Modifier
|
|
147
|
+
.height(72.dp)
|
|
148
|
+
.fillMaxWidth()
|
|
149
|
+
.pointerInput(Unit) {
|
|
150
|
+
detectDragGestures(
|
|
151
|
+
onDrag = { change, dragAmount ->
|
|
152
|
+
change.consume()
|
|
153
|
+
coroutineScope.launch {
|
|
154
|
+
val newOffset = (sheetOffset.value + dragAmount.y).coerceAtLeast(0f)
|
|
155
|
+
sheetOffset.snapTo(newOffset)
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
onDragEnd = {
|
|
159
|
+
coroutineScope.launch {
|
|
160
|
+
if (sheetOffset.value > sheetCloseOffset) {
|
|
161
|
+
closeEvent()
|
|
162
|
+
} else {
|
|
163
|
+
sheetOffset.animateTo(0f)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
) {
|
|
170
|
+
Column(
|
|
171
|
+
modifier = Modifier
|
|
172
|
+
.fillMaxSize()
|
|
173
|
+
.padding(horizontal = Spacing.M),
|
|
174
|
+
horizontalAlignment = Alignment.CenterHorizontally
|
|
175
|
+
) {
|
|
176
|
+
Spacer(Modifier.height(8.dp))
|
|
177
|
+
Box(
|
|
178
|
+
modifier = Modifier
|
|
179
|
+
.height(4.dp)
|
|
180
|
+
.width(40.dp)
|
|
181
|
+
.background(
|
|
182
|
+
color = Colors.black_06,
|
|
183
|
+
shape = RoundedCornerShape(Radius.S)
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
Spacer(Modifier.height(4.dp))
|
|
187
|
+
Box(Modifier.fillMaxWidth().height(56.dp), contentAlignment = Alignment.Center){
|
|
188
|
+
when (header) {
|
|
189
|
+
is BottomHeader.Title -> {
|
|
190
|
+
Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
|
|
191
|
+
Box(Modifier.size(24.dp))
|
|
192
|
+
Box(Modifier.fillMaxHeight().weight(1f), contentAlignment = Alignment.Center){
|
|
193
|
+
Text(
|
|
194
|
+
text = header.data,
|
|
195
|
+
color = Colors.black_17,
|
|
196
|
+
style = Typography.headerDefaultBold
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
Box(Modifier
|
|
200
|
+
.size(24.dp)
|
|
201
|
+
.noFeedbackClickable {
|
|
202
|
+
closeEvent()
|
|
203
|
+
},
|
|
204
|
+
contentAlignment = Alignment.Center
|
|
205
|
+
){
|
|
206
|
+
Icon(source = "navigation_close")
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
is BottomHeader.Custom -> {
|
|
211
|
+
header.content()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
Divider()
|
|
218
|
+
content()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
sealed class BottomHeader {
|
|
225
|
+
data class Title(
|
|
226
|
+
val data: String = "Bottom Sheet Title",
|
|
227
|
+
) : BottomHeader()
|
|
228
|
+
|
|
229
|
+
data class Custom(
|
|
230
|
+
val content: @Composable () -> Unit
|
|
231
|
+
) : BottomHeader()
|
|
232
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
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.clickable
|
|
8
|
+
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
9
|
+
import androidx.compose.foundation.layout.Box
|
|
10
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
11
|
+
import androidx.compose.foundation.layout.wrapContentSize
|
|
12
|
+
import androidx.compose.runtime.Composable
|
|
13
|
+
import androidx.compose.runtime.DisposableEffect
|
|
14
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
15
|
+
import androidx.compose.runtime.remember
|
|
16
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
17
|
+
import androidx.compose.ui.Alignment
|
|
18
|
+
import androidx.compose.ui.Modifier
|
|
19
|
+
import androidx.compose.ui.draw.alpha
|
|
20
|
+
import androidx.compose.ui.draw.scale
|
|
21
|
+
import androidx.compose.ui.graphics.Color
|
|
22
|
+
import kotlinx.coroutines.launch
|
|
23
|
+
import vn.momo.kits.modifier.noFeedbackClickable
|
|
24
|
+
import vn.momo.kits.platform.BackHandler
|
|
25
|
+
|
|
26
|
+
@Composable
|
|
27
|
+
internal fun ModalScreen(
|
|
28
|
+
content: @Composable () -> Unit,
|
|
29
|
+
barrierDismissible: Boolean = true,
|
|
30
|
+
onDismiss: (() -> Unit)? = null
|
|
31
|
+
) {
|
|
32
|
+
val navigator = LocalNavigator.current
|
|
33
|
+
|
|
34
|
+
val alpha = remember { Animatable(0f) }
|
|
35
|
+
val scale = remember { Animatable(0.8f) }
|
|
36
|
+
|
|
37
|
+
val coroutineScope = rememberCoroutineScope()
|
|
38
|
+
|
|
39
|
+
fun openEvent() {
|
|
40
|
+
coroutineScope.launch {
|
|
41
|
+
launch {
|
|
42
|
+
alpha.animateTo(
|
|
43
|
+
targetValue = 1f,
|
|
44
|
+
animationSpec = tween(durationMillis = 250)
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
launch {
|
|
48
|
+
scale.animateTo(
|
|
49
|
+
targetValue = 1f,
|
|
50
|
+
animationSpec = tween(
|
|
51
|
+
durationMillis = 250,
|
|
52
|
+
easing = CubicBezierEasing(0.2f, 0.0f, 0f, 1f)
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fun closeEvent() {
|
|
60
|
+
coroutineScope.launch {
|
|
61
|
+
alpha.animateTo(
|
|
62
|
+
targetValue = 0f,
|
|
63
|
+
animationSpec = tween(durationMillis = 200)
|
|
64
|
+
)
|
|
65
|
+
scale.animateTo(
|
|
66
|
+
targetValue = 0.8f,
|
|
67
|
+
animationSpec = tween(durationMillis = 200)
|
|
68
|
+
)
|
|
69
|
+
navigator.pop()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
LaunchedEffect(Unit) {
|
|
74
|
+
openEvent()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
DisposableEffect(Unit) {
|
|
78
|
+
OverplayComponentRegistry.bindClose { closeEvent() }
|
|
79
|
+
onDispose {
|
|
80
|
+
onDismiss?.invoke()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
BackHandler(enabled = true) {
|
|
85
|
+
closeEvent()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Box(
|
|
89
|
+
modifier = Modifier
|
|
90
|
+
.fillMaxSize()
|
|
91
|
+
.background(Color.Black.copy(alpha = 0.6f * alpha.value))
|
|
92
|
+
.noFeedbackClickable {
|
|
93
|
+
if(barrierDismissible) closeEvent()
|
|
94
|
+
},
|
|
95
|
+
contentAlignment = Alignment.Center
|
|
96
|
+
) {
|
|
97
|
+
Box(
|
|
98
|
+
modifier = Modifier
|
|
99
|
+
.scale(scale.value)
|
|
100
|
+
.alpha(alpha.value)
|
|
101
|
+
.wrapContentSize()
|
|
102
|
+
.clickable(
|
|
103
|
+
indication = null,
|
|
104
|
+
interactionSource = remember { MutableInteractionSource() }
|
|
105
|
+
) {},
|
|
106
|
+
contentAlignment = Alignment.Center
|
|
107
|
+
) {
|
|
108
|
+
content()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.gestures.ScrollableState
|
|
4
|
+
import androidx.compose.runtime.Composable
|
|
5
|
+
import androidx.compose.runtime.Stable
|
|
6
|
+
import androidx.compose.runtime.State
|
|
7
|
+
import androidx.compose.runtime.mutableStateOf
|
|
8
|
+
import androidx.compose.runtime.staticCompositionLocalOf
|
|
9
|
+
import androidx.compose.ui.graphics.Color
|
|
10
|
+
import vn.momo.kits.navigation.bottomtab.setBottomTabOption
|
|
11
|
+
import vn.momo.kits.navigation.component.FloatingButtonProps
|
|
12
|
+
import vn.momo.kits.navigation.component.HeaderRight
|
|
13
|
+
import vn.momo.kits.navigation.component.HeaderTitle
|
|
14
|
+
import vn.momo.kits.navigation.component.HeaderType
|
|
15
|
+
|
|
16
|
+
class Navigation(
|
|
17
|
+
val id: Int = -1,
|
|
18
|
+
val bottomTabIndex: Int = -1,
|
|
19
|
+
val initOptions: NavigationOptions? = null
|
|
20
|
+
) {
|
|
21
|
+
private val _options = mutableStateOf(initOptions ?: NavigationOptions())
|
|
22
|
+
val currentOptions: State<NavigationOptions> get() = _options
|
|
23
|
+
val options: NavigationOptions get() = _options.value
|
|
24
|
+
|
|
25
|
+
fun setOptions(
|
|
26
|
+
onBackHandler: (() -> Unit)? = null,
|
|
27
|
+
hiddenBack: Boolean? = null,
|
|
28
|
+
headerTitle: HeaderTitle? = null,
|
|
29
|
+
headerRight: HeaderRight? = null,
|
|
30
|
+
headerType: HeaderType? = null,
|
|
31
|
+
scrollData: ScrollData? = null,
|
|
32
|
+
backgroundColor: Color? = null,
|
|
33
|
+
tintColor: Color? = null,
|
|
34
|
+
footerComponent: (@Composable () -> Unit)? = null,
|
|
35
|
+
floatingButtonProps: FloatingButtonProps? = null,
|
|
36
|
+
keyboardOptions: KeyboardOptions? = null
|
|
37
|
+
) {
|
|
38
|
+
updateOptions(
|
|
39
|
+
options.copy(
|
|
40
|
+
onBackHandler = onBackHandler ?: options.onBackHandler,
|
|
41
|
+
hiddenBack = hiddenBack ?: options.hiddenBack,
|
|
42
|
+
headerTitle = headerTitle ?: options.headerTitle,
|
|
43
|
+
headerRight = headerRight ?: options.headerRight,
|
|
44
|
+
headerType = headerType ?: options.headerType,
|
|
45
|
+
scrollData = scrollData ?: options.scrollData,
|
|
46
|
+
backgroundColor = backgroundColor ?: options.backgroundColor,
|
|
47
|
+
tintColor = tintColor ?: options.tintColor,
|
|
48
|
+
footerComponent = footerComponent ?: options.footerComponent,
|
|
49
|
+
floatingButtonProps = floatingButtonProps ?: options.floatingButtonProps,
|
|
50
|
+
keyboardOptions = keyboardOptions ?: options.keyboardOptions,
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fun setOptions(newOptions: NavigationOptions) {
|
|
56
|
+
updateOptions(newOptions)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private fun updateOptions(updated: NavigationOptions) {
|
|
60
|
+
_options.value = updated
|
|
61
|
+
if (bottomTabIndex != -1) setBottomTabOption(bottomTabIndex, updated)
|
|
62
|
+
if (id != -1) DynamicScreenRegistry.setOptions(id, updated)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
val LocalNavigation = staticCompositionLocalOf<Navigation> {
|
|
67
|
+
error("No NavigationStack provided")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Stable
|
|
71
|
+
data class NavigationOptions(
|
|
72
|
+
val onBackHandler: (() -> Unit)? = null,
|
|
73
|
+
val hiddenBack: Boolean = false,
|
|
74
|
+
val headerTitle: HeaderTitle = HeaderTitle.Default("Stack"),
|
|
75
|
+
val headerRight: HeaderRight = HeaderRight.Toolkit(),
|
|
76
|
+
val headerType: HeaderType = HeaderType.Default(),
|
|
77
|
+
val scrollData: ScrollData = ScrollData(),
|
|
78
|
+
val backgroundColor: Color? = null,
|
|
79
|
+
val tintColor: Color? = null,
|
|
80
|
+
val footerComponent: @Composable (() -> Unit)? = null,
|
|
81
|
+
val floatingButtonProps: FloatingButtonProps? = null,
|
|
82
|
+
val keyboardOptions: KeyboardOptions = KeyboardOptions()
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
data class KeyboardOptions(
|
|
86
|
+
val keyboardShouldPersistTaps: Boolean = false,
|
|
87
|
+
val useAvoidKeyboard: Boolean = true
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
data class ScrollData(
|
|
92
|
+
val scrollable: Boolean = true,
|
|
93
|
+
val scrollState: ScrollableState? = null,
|
|
94
|
+
)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.tween
|
|
4
|
+
import androidx.compose.animation.fadeIn
|
|
5
|
+
import androidx.compose.animation.slideInHorizontally
|
|
6
|
+
import androidx.compose.animation.slideInVertically
|
|
7
|
+
import androidx.compose.animation.slideOutHorizontally
|
|
8
|
+
import androidx.compose.animation.slideOutVertically
|
|
9
|
+
import androidx.compose.foundation.layout.WindowInsets
|
|
10
|
+
import androidx.compose.foundation.layout.asPaddingValues
|
|
11
|
+
import androidx.compose.foundation.layout.systemBars
|
|
12
|
+
import androidx.compose.runtime.Composable
|
|
13
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
14
|
+
import androidx.compose.runtime.DisposableEffect
|
|
15
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
16
|
+
import androidx.compose.runtime.mutableStateOf
|
|
17
|
+
import androidx.compose.runtime.remember
|
|
18
|
+
import androidx.compose.runtime.staticCompositionLocalOf
|
|
19
|
+
import androidx.compose.ui.unit.Dp
|
|
20
|
+
import androidx.compose.ui.unit.dp
|
|
21
|
+
import androidx.navigation.compose.NavHost
|
|
22
|
+
import androidx.navigation.compose.composable
|
|
23
|
+
import androidx.navigation.compose.rememberNavController
|
|
24
|
+
import androidx.navigation.toRoute
|
|
25
|
+
import vn.momo.kits.application.AppConfig
|
|
26
|
+
import vn.momo.kits.application.AppLanguage
|
|
27
|
+
import vn.momo.kits.application.ApplicationContext
|
|
28
|
+
import vn.momo.kits.application.KitConfig
|
|
29
|
+
import vn.momo.kits.application.MiniAppContext
|
|
30
|
+
import vn.momo.kits.const.AppNavigationBar
|
|
31
|
+
import vn.momo.kits.const.AppStatusBar
|
|
32
|
+
import vn.momo.kits.const.AppTheme
|
|
33
|
+
import vn.momo.kits.const.AppThemeController
|
|
34
|
+
import vn.momo.kits.const.Theme
|
|
35
|
+
import vn.momo.kits.const.ThemeAssets
|
|
36
|
+
import vn.momo.kits.const.defaultTheme
|
|
37
|
+
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
38
|
+
import vn.momo.maxapi.IMaxApi
|
|
39
|
+
|
|
40
|
+
@Composable
|
|
41
|
+
fun NavigationContainer(
|
|
42
|
+
initialScreen: @Composable () -> Unit,
|
|
43
|
+
options: NavigationOptions? = null,
|
|
44
|
+
initialTheme: Theme = defaultTheme,
|
|
45
|
+
applicationContext: MiniAppContext? = null,
|
|
46
|
+
maxApi: IMaxApi? = null,
|
|
47
|
+
setNavigator: ((Navigator) -> Unit)? = null,
|
|
48
|
+
statusBarHeight: Dp? = null,
|
|
49
|
+
config: KitConfig? = null,
|
|
50
|
+
language: String? = null,
|
|
51
|
+
){
|
|
52
|
+
val navController = rememberNavController()
|
|
53
|
+
val navigator = remember { Navigator(navController = navController, maxApi = maxApi) }
|
|
54
|
+
val statusBarHeight = statusBarHeight ?: getAppStatusBarHeight()
|
|
55
|
+
val navigationBarHeight = if (AppNavigationBar.current == 0.dp) {
|
|
56
|
+
WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
|
|
57
|
+
} else {
|
|
58
|
+
AppNavigationBar.current
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
val theme = remember { mutableStateOf(initialTheme) }
|
|
62
|
+
|
|
63
|
+
LaunchedEffect(Unit) {
|
|
64
|
+
val headerBar = config?.headerBar
|
|
65
|
+
if (headerBar != null && theme.value.assets.headerBackground == null) {
|
|
66
|
+
theme.value = theme.value.copy(
|
|
67
|
+
assets = ThemeAssets(
|
|
68
|
+
headerBackground = headerBar
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
val startDestination = DynamicScreenRegistry.register(initialScreen, options)
|
|
75
|
+
|
|
76
|
+
CompositionLocalProvider(
|
|
77
|
+
LocalNavigator provides navigator,
|
|
78
|
+
LocalMaxApi provides maxApi,
|
|
79
|
+
AppTheme provides theme.value,
|
|
80
|
+
AppThemeController provides { theme.value = it },
|
|
81
|
+
AppStatusBar provides statusBarHeight,
|
|
82
|
+
AppNavigationBar provides navigationBarHeight,
|
|
83
|
+
ApplicationContext provides applicationContext,
|
|
84
|
+
AppConfig provides config,
|
|
85
|
+
AppLanguage provides language
|
|
86
|
+
) {
|
|
87
|
+
LaunchedEffect(Unit) {
|
|
88
|
+
setNavigator?.invoke(navigator)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
NavHost(navController, startDestination = startDestination) {
|
|
92
|
+
composable<DynamicScreenRoute>(
|
|
93
|
+
enterTransition = {
|
|
94
|
+
slideInHorizontally(
|
|
95
|
+
animationSpec = tween(300),
|
|
96
|
+
initialOffsetX = { it }
|
|
97
|
+
)
|
|
98
|
+
},
|
|
99
|
+
exitTransition = null,
|
|
100
|
+
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
101
|
+
popExitTransition = {
|
|
102
|
+
slideOutHorizontally(
|
|
103
|
+
animationSpec = tween(300),
|
|
104
|
+
targetOffsetX = { it }
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
) { backStackEntry ->
|
|
108
|
+
val route = backStackEntry.toRoute<DynamicScreenRoute>()
|
|
109
|
+
val screen = DynamicScreenRegistry.getScreen(route.id)
|
|
110
|
+
|
|
111
|
+
if (screen != null){
|
|
112
|
+
StackScreen(
|
|
113
|
+
id = route.id,
|
|
114
|
+
content = screen.content,
|
|
115
|
+
navigationOptions = screen.options
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
composable<DynamicDialogRoute>(
|
|
121
|
+
enterTransition = {
|
|
122
|
+
slideInVertically (
|
|
123
|
+
animationSpec = tween(300),
|
|
124
|
+
initialOffsetY = { it }
|
|
125
|
+
)
|
|
126
|
+
},
|
|
127
|
+
exitTransition = null,
|
|
128
|
+
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
129
|
+
popExitTransition = {
|
|
130
|
+
slideOutVertically (
|
|
131
|
+
animationSpec = tween(300),
|
|
132
|
+
targetOffsetY = { it }
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
) { backStackEntry ->
|
|
136
|
+
val route = backStackEntry.toRoute<DynamicDialogRoute>()
|
|
137
|
+
val screen = DynamicScreenRegistry.getScreen(route.id)
|
|
138
|
+
|
|
139
|
+
if (screen != null){
|
|
140
|
+
StackScreen(
|
|
141
|
+
id = route.id,
|
|
142
|
+
content = screen.content,
|
|
143
|
+
navigationOptions = screen.options
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
DisposableEffect(Unit) {
|
|
151
|
+
onDispose {
|
|
152
|
+
navigator.dispose()
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
|
|
158
|
+
error("No MaxApi provided")
|
|
159
|
+
}
|