@momo-kits/native-kits 0.0.2-alpha.1 → 0.0.2-alpha.1-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 +11 -0
- package/compose/build.gradle.kts +189 -0
- package/compose/build.gradle.kts.backup +189 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -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 +151 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -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 +293 -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 +831 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -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 +82 -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 +356 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -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 +475 -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 +266 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -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 +264 -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 +328 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -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 +323 -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 +199 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +552 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -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 +498 -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 +234 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -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 +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -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 +282 -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 +51 -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 +299 -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 +129 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +211 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +398 -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 +595 -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 +184 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -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 +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +357 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +83 -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 +75 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +326 -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 +364 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +33 -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 +71 -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 +105 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +47 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +40 -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 +36 -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 +213 -0
- package/gradle/libs.versions.toml +71 -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-demo/README.md +120 -0
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
4
|
+
import androidx.compose.foundation.layout.Box
|
|
5
|
+
import androidx.compose.foundation.layout.Column
|
|
6
|
+
import androidx.compose.foundation.layout.Row
|
|
7
|
+
import androidx.compose.foundation.layout.Spacer
|
|
8
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
9
|
+
import androidx.compose.foundation.layout.height
|
|
10
|
+
import androidx.compose.foundation.layout.width
|
|
11
|
+
import androidx.compose.foundation.layout.widthIn
|
|
12
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
13
|
+
import androidx.compose.runtime.Composable
|
|
14
|
+
import androidx.compose.ui.Alignment
|
|
15
|
+
import androidx.compose.ui.Modifier
|
|
16
|
+
import androidx.compose.ui.draw.clip
|
|
17
|
+
import androidx.compose.ui.graphics.Color
|
|
18
|
+
import androidx.compose.ui.text.style.TextOverflow
|
|
19
|
+
import androidx.compose.ui.unit.dp
|
|
20
|
+
import vn.momo.kits.components.Icon
|
|
21
|
+
import vn.momo.kits.components.Skeleton
|
|
22
|
+
import vn.momo.kits.components.Text
|
|
23
|
+
import vn.momo.kits.const.Spacing
|
|
24
|
+
import vn.momo.kits.const.Typography
|
|
25
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
26
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
27
|
+
|
|
28
|
+
@Composable
|
|
29
|
+
internal fun HeaderJourney(
|
|
30
|
+
data: HeaderTitle,
|
|
31
|
+
tintIconColor: Color,
|
|
32
|
+
) {
|
|
33
|
+
if (data !is HeaderTitle.Journey) return
|
|
34
|
+
if (data.isLoading) return TitleJourneyShimmer()
|
|
35
|
+
|
|
36
|
+
val maxWidth = getScreenDimensions().width.dp - 172.dp
|
|
37
|
+
val tint = parseHeaderTint(data.tintColor) ?: tintIconColor
|
|
38
|
+
val iconTint = parseHeaderTint(data.iconColor) ?: tint
|
|
39
|
+
|
|
40
|
+
Column(
|
|
41
|
+
modifier = Modifier
|
|
42
|
+
.widthIn(max = maxWidth)
|
|
43
|
+
.activeOpacityClickable(enabled = data.onPress != null, onClick = { data.onPress?.invoke() }),
|
|
44
|
+
verticalArrangement = Arrangement.Center,
|
|
45
|
+
) {
|
|
46
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
47
|
+
Text(
|
|
48
|
+
text = data.start,
|
|
49
|
+
color = tint,
|
|
50
|
+
style = Typography.actionXsBold,
|
|
51
|
+
maxLines = 1,
|
|
52
|
+
overflow = TextOverflow.Ellipsis,
|
|
53
|
+
modifier = Modifier.weight(1f, fill = false),
|
|
54
|
+
)
|
|
55
|
+
Spacer(Modifier.width(Spacing.S))
|
|
56
|
+
if (data.icon.isNotBlank()) {
|
|
57
|
+
Icon(source = data.icon, size = 16.dp, color = iconTint)
|
|
58
|
+
} else {
|
|
59
|
+
Spacer(Modifier.width(16.dp))
|
|
60
|
+
}
|
|
61
|
+
Spacer(Modifier.width(Spacing.S))
|
|
62
|
+
if (!data.end.isNullOrEmpty()) {
|
|
63
|
+
Text(
|
|
64
|
+
text = data.end,
|
|
65
|
+
color = tint,
|
|
66
|
+
style = Typography.actionXsBold,
|
|
67
|
+
maxLines = 1,
|
|
68
|
+
overflow = TextOverflow.Ellipsis,
|
|
69
|
+
modifier = Modifier.weight(1f, fill = false),
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
Spacer(Modifier.width(Spacing.XS))
|
|
73
|
+
Icon(source = "16_arrow_chevron_down_small", size = 16.dp, color = tint)
|
|
74
|
+
}
|
|
75
|
+
if (!data.description.isNullOrEmpty()) {
|
|
76
|
+
Text(
|
|
77
|
+
text = data.description,
|
|
78
|
+
color = tint,
|
|
79
|
+
style = Typography.descriptionXsRegular,
|
|
80
|
+
maxLines = 1,
|
|
81
|
+
overflow = TextOverflow.Ellipsis,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Composable
|
|
88
|
+
private fun TitleJourneyShimmer() {
|
|
89
|
+
Column(modifier = Modifier.fillMaxWidth()) {
|
|
90
|
+
Box(modifier = Modifier.height(18.dp).width(120.dp).clip(RoundedCornerShape(8.dp))) { Skeleton() }
|
|
91
|
+
Spacer(Modifier.height(Spacing.XXS))
|
|
92
|
+
Box(modifier = Modifier.height(12.dp).width(120.dp).clip(RoundedCornerShape(8.dp))) { Skeleton() }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
internal fun parseHeaderTint(value: String?): Color? {
|
|
97
|
+
val raw = value?.trim()?.removePrefix("#") ?: return null
|
|
98
|
+
val hex = when (raw.length) {
|
|
99
|
+
3 -> "FF" + raw.map { "$it$it" }.joinToString("")
|
|
100
|
+
6 -> "FF$raw"
|
|
101
|
+
8 -> raw
|
|
102
|
+
else -> return null
|
|
103
|
+
}
|
|
104
|
+
val v = hex.toLongOrNull(16) ?: return null
|
|
105
|
+
return Color(v)
|
|
106
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.Box
|
|
4
|
+
import androidx.compose.foundation.layout.Column
|
|
5
|
+
import androidx.compose.foundation.layout.Row
|
|
6
|
+
import androidx.compose.foundation.layout.Spacer
|
|
7
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
8
|
+
import androidx.compose.foundation.layout.height
|
|
9
|
+
import androidx.compose.foundation.layout.width
|
|
10
|
+
import androidx.compose.foundation.layout.widthIn
|
|
11
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
12
|
+
import androidx.compose.runtime.Composable
|
|
13
|
+
import androidx.compose.ui.Alignment
|
|
14
|
+
import androidx.compose.ui.Modifier
|
|
15
|
+
import androidx.compose.ui.draw.clip
|
|
16
|
+
import androidx.compose.ui.graphics.Color
|
|
17
|
+
import androidx.compose.ui.text.style.TextOverflow
|
|
18
|
+
import androidx.compose.ui.unit.dp
|
|
19
|
+
import vn.momo.kits.components.Icon
|
|
20
|
+
import vn.momo.kits.components.Skeleton
|
|
21
|
+
import vn.momo.kits.components.Text
|
|
22
|
+
import vn.momo.kits.const.Spacing
|
|
23
|
+
import vn.momo.kits.const.Typography
|
|
24
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
25
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
26
|
+
|
|
27
|
+
@Composable
|
|
28
|
+
internal fun HeaderLocation(
|
|
29
|
+
data: HeaderTitle,
|
|
30
|
+
tintIconColor: Color,
|
|
31
|
+
) {
|
|
32
|
+
if (data !is HeaderTitle.Location) return
|
|
33
|
+
if (data.isLoading) return TitleLocationShimmer()
|
|
34
|
+
|
|
35
|
+
val maxWidth = getScreenDimensions().width.dp - 172.dp
|
|
36
|
+
val tint = parseHeaderTint(data.tintColor) ?: tintIconColor
|
|
37
|
+
|
|
38
|
+
Column(
|
|
39
|
+
modifier = Modifier
|
|
40
|
+
.widthIn(max = maxWidth)
|
|
41
|
+
.activeOpacityClickable(enabled = data.onPress != null, onClick = { data.onPress?.invoke() }),
|
|
42
|
+
horizontalAlignment = Alignment.Start,
|
|
43
|
+
) {
|
|
44
|
+
if (!data.description.isNullOrEmpty()) {
|
|
45
|
+
Text(
|
|
46
|
+
text = data.description,
|
|
47
|
+
color = tint,
|
|
48
|
+
style = Typography.descriptionXsRegular,
|
|
49
|
+
maxLines = 1,
|
|
50
|
+
overflow = TextOverflow.Ellipsis,
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
54
|
+
Text(
|
|
55
|
+
text = data.location,
|
|
56
|
+
color = tint,
|
|
57
|
+
style = Typography.actionXsBold,
|
|
58
|
+
maxLines = 1,
|
|
59
|
+
overflow = TextOverflow.Ellipsis,
|
|
60
|
+
modifier = Modifier.weight(1f, fill = false),
|
|
61
|
+
)
|
|
62
|
+
Spacer(Modifier.width(Spacing.XS))
|
|
63
|
+
Icon(source = "16_arrow_chevron_down_small", size = 16.dp, color = tint)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Composable
|
|
69
|
+
private fun TitleLocationShimmer() {
|
|
70
|
+
Column(modifier = Modifier.fillMaxWidth()) {
|
|
71
|
+
Box(modifier = Modifier.height(12.dp).width(120.dp).clip(RoundedCornerShape(8.dp))) { Skeleton() }
|
|
72
|
+
Spacer(Modifier.height(Spacing.XXS))
|
|
73
|
+
Box(modifier = Modifier.height(18.dp).width(120.dp).clip(RoundedCornerShape(8.dp))) { Skeleton() }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import vn.momo.kits.modifier.InternalApi
|
|
4
|
+
|
|
5
|
+
import androidx.compose.foundation.background
|
|
6
|
+
import androidx.compose.foundation.border
|
|
7
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
8
|
+
import androidx.compose.foundation.layout.Box
|
|
9
|
+
import androidx.compose.foundation.layout.Row
|
|
10
|
+
import androidx.compose.foundation.layout.height
|
|
11
|
+
import androidx.compose.foundation.layout.offset
|
|
12
|
+
import androidx.compose.foundation.layout.padding
|
|
13
|
+
import androidx.compose.foundation.layout.size
|
|
14
|
+
import androidx.compose.foundation.layout.width
|
|
15
|
+
import androidx.compose.foundation.shape.CircleShape
|
|
16
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
17
|
+
import androidx.compose.runtime.Composable
|
|
18
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
19
|
+
// AI-GENERATED START: dispose toolkit requests with their UI owner
|
|
20
|
+
import androidx.compose.runtime.DisposableEffect
|
|
21
|
+
import kotlinx.serialization.json.booleanOrNull
|
|
22
|
+
import kotlinx.serialization.json.jsonPrimitive
|
|
23
|
+
import vn.momo.maxapi.contract.navigation.model.DismissTarget
|
|
24
|
+
import vn.momo.maxapi.contract.toolkit.model.ToolAction
|
|
25
|
+
import vn.momo.maxapi.contract.toolkit.model.ToolkitOptions
|
|
26
|
+
import vn.momo.maxapi.contract.toolkit.model.ToolkitToolGroup
|
|
27
|
+
import vn.momo.maxapi.contract.toolkit.model.ToolkitTool
|
|
28
|
+
import vn.momo.maxapi.runtime.ApiResult
|
|
29
|
+
// AI-GENERATED END: dispose toolkit requests with their UI owner
|
|
30
|
+
import androidx.compose.runtime.derivedStateOf
|
|
31
|
+
import androidx.compose.runtime.getValue
|
|
32
|
+
import androidx.compose.runtime.mutableStateOf
|
|
33
|
+
import androidx.compose.runtime.remember
|
|
34
|
+
import androidx.compose.runtime.setValue
|
|
35
|
+
import androidx.compose.ui.Alignment
|
|
36
|
+
import androidx.compose.ui.Modifier
|
|
37
|
+
import androidx.compose.ui.draw.clip
|
|
38
|
+
import androidx.compose.ui.graphics.Color
|
|
39
|
+
import androidx.compose.ui.unit.dp
|
|
40
|
+
import vn.momo.kits.application.LocalContext
|
|
41
|
+
import vn.momo.kits.application.MiniAppContext
|
|
42
|
+
import vn.momo.kits.components.BadgeDot
|
|
43
|
+
import vn.momo.kits.components.DotSize
|
|
44
|
+
import vn.momo.kits.components.Icon
|
|
45
|
+
import vn.momo.kits.const.Colors
|
|
46
|
+
import vn.momo.kits.const.Spacing
|
|
47
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
48
|
+
import vn.momo.kits.navigation.LocalMaxApi
|
|
49
|
+
|
|
50
|
+
@Composable
|
|
51
|
+
@InternalApi
|
|
52
|
+
fun HeaderRight(
|
|
53
|
+
headerRight: HeaderRight,
|
|
54
|
+
tintColor: Color? = null,
|
|
55
|
+
headerColor: HeaderColor
|
|
56
|
+
) {
|
|
57
|
+
when (headerRight) {
|
|
58
|
+
is HeaderRight.None -> {}
|
|
59
|
+
is HeaderRight.Custom -> {
|
|
60
|
+
headerRight.content()
|
|
61
|
+
}
|
|
62
|
+
is HeaderRight.OnBoarding -> {}
|
|
63
|
+
is HeaderRight.Toolkit -> {
|
|
64
|
+
Toolkit(
|
|
65
|
+
headerRight = headerRight,
|
|
66
|
+
tintColor = tintColor,
|
|
67
|
+
headerColor = headerColor
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Composable
|
|
74
|
+
internal fun Toolkit(
|
|
75
|
+
headerRight: HeaderRight.Toolkit,
|
|
76
|
+
tintColor: Color? = null,
|
|
77
|
+
headerColor: HeaderColor
|
|
78
|
+
) {
|
|
79
|
+
val api = LocalMaxApi.current
|
|
80
|
+
val context = LocalContext.current
|
|
81
|
+
|
|
82
|
+
var isFavorite by remember { mutableStateOf(false) }
|
|
83
|
+
val isLoading by remember { mutableStateOf(false) }
|
|
84
|
+
|
|
85
|
+
// AI-GENERATED START: retain custom tool data and typed callback outcomes
|
|
86
|
+
val requests = remember(api, context?.appCode) { ToolkitRequests() }
|
|
87
|
+
DisposableEffect(requests) { onDispose { requests.close() } }
|
|
88
|
+
|
|
89
|
+
LaunchedEffect(requests) {
|
|
90
|
+
val client = api ?: return@LaunchedEffect
|
|
91
|
+
requests.launch<Boolean>({ callback -> client.checkFavorite(context?.appCode, callback) }) { result ->
|
|
92
|
+
if (result is ApiResult.Success) isFavorite = result.value
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fun onPressShortcut() {
|
|
97
|
+
val client = api ?: return
|
|
98
|
+
requests.launch({ callback ->
|
|
99
|
+
client.performToolAction(ToolAction.FAVORITE, context?.appCode, callback)
|
|
100
|
+
}) { result ->
|
|
101
|
+
if (result is ApiResult.Success) {
|
|
102
|
+
result.value.jsonPrimitive.booleanOrNull?.let { isFavorite = it }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fun onPressMore() {
|
|
108
|
+
val client = api ?: return
|
|
109
|
+
val options = ToolkitOptions(
|
|
110
|
+
customToolGroups = headerRight.tools.map { group ->
|
|
111
|
+
ToolkitToolGroup(group.title, group.items.map { tool ->
|
|
112
|
+
ToolkitTool(tool.key, tool.icon, tool.showBadge, tool.name, tool.showRightIcon)
|
|
113
|
+
})
|
|
114
|
+
},
|
|
115
|
+
useSystemTools = headerRight.useSystemTools,
|
|
116
|
+
)
|
|
117
|
+
requests.launch({ callback -> client.showToolkit(options, callback) }) { result ->
|
|
118
|
+
if (result is ApiResult.Success) headerRight.toolCallback?.invoke(result.value.actionKey)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// AI-GENERATED END: retain custom tool data and typed callback outcomes
|
|
122
|
+
|
|
123
|
+
val navButtonConfig = getNavigationButtonConfig(
|
|
124
|
+
headerRight,
|
|
125
|
+
::onPressShortcut,
|
|
126
|
+
::onPressMore
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
val showBadge = headerRight.tools.any { group ->
|
|
130
|
+
group.items.any { it.showBadge }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
val isShowShortcut by remember(headerRight.useShortcut, headerRight.useMore, context) {
|
|
134
|
+
derivedStateOf {
|
|
135
|
+
(headerRight.useShortcut == true) &&
|
|
136
|
+
!(headerRight.useMore == true && context == null)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
val icon by remember(navButtonConfig.icon, isFavorite) {
|
|
141
|
+
derivedStateOf {
|
|
142
|
+
navButtonConfig.icon.takeUnless { it == "star" }
|
|
143
|
+
?: if (isFavorite) "pin_star_checked" else "pin_star"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
Row(
|
|
148
|
+
verticalAlignment = Alignment.CenterVertically
|
|
149
|
+
) {
|
|
150
|
+
if (isShowShortcut) {
|
|
151
|
+
NavigationButton(
|
|
152
|
+
disabled = isLoading,
|
|
153
|
+
icon = icon,
|
|
154
|
+
showBadge = showBadge,
|
|
155
|
+
onClick = navButtonConfig.onPress,
|
|
156
|
+
headerColor = headerColor
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
Row(
|
|
161
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
162
|
+
horizontalArrangement = Arrangement.Center,
|
|
163
|
+
modifier = Modifier
|
|
164
|
+
.padding(start = Spacing.S)
|
|
165
|
+
.border(0.2.dp, headerColor.borderColor, shape = RoundedCornerShape(14.dp))
|
|
166
|
+
.height(28.dp)
|
|
167
|
+
.clip(shape = RoundedCornerShape(14.dp))
|
|
168
|
+
.background(headerColor.backgroundButton)
|
|
169
|
+
) {
|
|
170
|
+
if (context != null) {
|
|
171
|
+
Icon(
|
|
172
|
+
source = "help_center",
|
|
173
|
+
size = 20.dp,
|
|
174
|
+
color = headerColor.tintIconColor,
|
|
175
|
+
modifier = Modifier.padding(4.dp).activeOpacityClickable {
|
|
176
|
+
// AI-GENERATED START: open support through the typed action
|
|
177
|
+
api?.let { client ->
|
|
178
|
+
requests.launch({ callback ->
|
|
179
|
+
client.performToolAction(ToolAction.SUPPORT, context.appCode, callback)
|
|
180
|
+
}) {}
|
|
181
|
+
}
|
|
182
|
+
// AI-GENERATED END: open support through the typed action
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
Box(
|
|
186
|
+
modifier = Modifier
|
|
187
|
+
.width(0.5.dp)
|
|
188
|
+
.height(12.dp)
|
|
189
|
+
.background(tintColor ?: Colors.black_20)
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
Icon(
|
|
193
|
+
source = "16_basic_home",
|
|
194
|
+
size = 20.dp,
|
|
195
|
+
color = headerColor.tintIconColor,
|
|
196
|
+
modifier = Modifier.padding(4.dp).activeOpacityClickable {
|
|
197
|
+
// AI-GENERATED START: preserve dismiss-all without selecting Home
|
|
198
|
+
api?.dismiss(DismissTarget.All) {}
|
|
199
|
+
// AI-GENERATED END: preserve dismiss-all without selecting Home
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@Composable
|
|
209
|
+
internal fun NavigationButton(
|
|
210
|
+
disabled: Boolean,
|
|
211
|
+
icon: String,
|
|
212
|
+
showBadge: Boolean? = false,
|
|
213
|
+
onClick: () -> Unit,
|
|
214
|
+
headerColor: HeaderColor
|
|
215
|
+
) {
|
|
216
|
+
Box(
|
|
217
|
+
modifier = Modifier
|
|
218
|
+
.size(28.dp)
|
|
219
|
+
.activeOpacityClickable(enabled = !disabled, onClick = onClick)
|
|
220
|
+
) {
|
|
221
|
+
Box(
|
|
222
|
+
modifier = Modifier
|
|
223
|
+
.matchParentSize()
|
|
224
|
+
.clip(CircleShape)
|
|
225
|
+
.background(headerColor.backgroundButton)
|
|
226
|
+
.border(0.2.dp, headerColor.borderColor, CircleShape)
|
|
227
|
+
)
|
|
228
|
+
Box(
|
|
229
|
+
modifier = Modifier.matchParentSize(),
|
|
230
|
+
contentAlignment = Alignment.Center
|
|
231
|
+
) {
|
|
232
|
+
Icon(
|
|
233
|
+
source = icon,
|
|
234
|
+
size = 20.dp,
|
|
235
|
+
color = headerColor.tintIconColor
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (showBadge == true) {
|
|
240
|
+
BadgeDot(
|
|
241
|
+
size = DotSize.Small,
|
|
242
|
+
modifier = Modifier
|
|
243
|
+
.align(Alignment.TopEnd)
|
|
244
|
+
.offset(x = -Spacing.XXS, y = -Spacing.XXS)
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private fun getNavigationButtonConfig(
|
|
251
|
+
headerRight: HeaderRight.Toolkit,
|
|
252
|
+
onPressShortcut: () -> Unit,
|
|
253
|
+
onPressMore: () -> Unit
|
|
254
|
+
): NavigationButtonConfig {
|
|
255
|
+
val totalTools = headerRight.tools.sumOf { it.items.size }
|
|
256
|
+
val config = NavigationButtonConfig(icon = "star", onPress = onPressShortcut)
|
|
257
|
+
return if (totalTools > 1 || headerRight.useMore == true) {
|
|
258
|
+
NavigationButtonConfig(
|
|
259
|
+
icon = "navigation_more_icon",
|
|
260
|
+
onPress = onPressMore
|
|
261
|
+
)
|
|
262
|
+
} else if (totalTools == 1 && headerRight.tools.isNotEmpty()) {
|
|
263
|
+
val singleTool = headerRight.tools.first().items.firstOrNull()
|
|
264
|
+
return if (singleTool != null){
|
|
265
|
+
NavigationButtonConfig(
|
|
266
|
+
icon = singleTool.icon,
|
|
267
|
+
onPress = {
|
|
268
|
+
headerRight.toolCallback?.invoke(singleTool.key)
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
} else {
|
|
272
|
+
config
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
config
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
sealed interface HeaderRight {
|
|
280
|
+
data object None : HeaderRight
|
|
281
|
+
data class Custom(
|
|
282
|
+
val content: @Composable () -> Unit
|
|
283
|
+
) : HeaderRight
|
|
284
|
+
data object OnBoarding : HeaderRight
|
|
285
|
+
data class Toolkit(
|
|
286
|
+
val useShortcut: Boolean = false,
|
|
287
|
+
val useMore: Boolean = false,
|
|
288
|
+
val useSystemTools: Boolean = true,
|
|
289
|
+
val tools: List<ToolGroup> = emptyList(),
|
|
290
|
+
val toolCallback: ((String) -> Unit)? = { _ -> }
|
|
291
|
+
) : HeaderRight
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
data class ToolGroup(
|
|
295
|
+
val title: Map<String, String> = emptyMap(),
|
|
296
|
+
val items: List<Tool>
|
|
297
|
+
) {
|
|
298
|
+
fun toMap(): Map<String, Any> {
|
|
299
|
+
return mapOf(
|
|
300
|
+
"title" to title,
|
|
301
|
+
"items" to items.map { it.toMap() }
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
data class Tool(
|
|
306
|
+
val key: String,
|
|
307
|
+
val icon: String,
|
|
308
|
+
val showBadge: Boolean = false,
|
|
309
|
+
val name: Map<String, String> = emptyMap(),
|
|
310
|
+
val showRightIcon: Boolean = true,
|
|
311
|
+
) {
|
|
312
|
+
fun toMap(): Map<String, Any> {
|
|
313
|
+
return mapOf(
|
|
314
|
+
"key" to key,
|
|
315
|
+
"icon" to icon,
|
|
316
|
+
"showBadge" to showBadge,
|
|
317
|
+
"name" to name,
|
|
318
|
+
"showRightIcon" to showRightIcon
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private data class NavigationButtonConfig(
|
|
324
|
+
val icon: String,
|
|
325
|
+
val onPress: () -> Unit
|
|
326
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
4
|
+
import androidx.compose.runtime.Composable
|
|
5
|
+
import androidx.compose.ui.Modifier
|
|
6
|
+
import androidx.compose.ui.graphics.Color
|
|
7
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
8
|
+
import androidx.compose.ui.text.style.TextOverflow
|
|
9
|
+
import androidx.compose.ui.unit.sp
|
|
10
|
+
import androidx.compose.ui.zIndex
|
|
11
|
+
import vn.momo.kits.components.Text
|
|
12
|
+
import vn.momo.kits.const.KitDesignSystem
|
|
13
|
+
import vn.momo.kits.const.Typography
|
|
14
|
+
import vn.momo.kits.modifier.setAutomationId
|
|
15
|
+
|
|
16
|
+
internal val headerFontFamily: String?
|
|
17
|
+
get() = if (KitDesignSystem.isWhiteList) "MoMoTrustDisplay" else null
|
|
18
|
+
|
|
19
|
+
@Composable
|
|
20
|
+
internal fun HeaderTitle(
|
|
21
|
+
title: String = "",
|
|
22
|
+
color: Color? = null,
|
|
23
|
+
modifier: Modifier = Modifier.fillMaxWidth(),
|
|
24
|
+
textAlign: TextAlign = TextAlign.Start,
|
|
25
|
+
) {
|
|
26
|
+
Text(
|
|
27
|
+
modifier = modifier.zIndex(1f).setAutomationId("title_navigation_header"),
|
|
28
|
+
text = title,
|
|
29
|
+
textAlign = textAlign,
|
|
30
|
+
style = Typography.actionSBold.copy(
|
|
31
|
+
fontSize = 15.sp,
|
|
32
|
+
lineHeight = 22.sp,
|
|
33
|
+
),
|
|
34
|
+
fontFamily = headerFontFamily,
|
|
35
|
+
color = color,
|
|
36
|
+
maxLines = 1,
|
|
37
|
+
overflow = TextOverflow.Ellipsis
|
|
38
|
+
)
|
|
39
|
+
}
|