@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.
Files changed (143) hide show
  1. package/build.gradle.kts +11 -0
  2. package/compose/build.gradle.kts +189 -0
  3. package/compose/build.gradle.kts.backup +189 -0
  4. package/compose/compose.podspec +47 -0
  5. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -0
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +151 -0
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +831 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +82 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +356 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +475 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +266 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +264 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +328 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +323 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +199 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +552 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +498 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +234 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +16 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +282 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +51 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +299 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +129 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +106 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +211 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +398 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +595 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +40 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +184 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +357 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +83 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +75 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +326 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +364 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +33 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +135 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +71 -0
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +105 -0
  128. package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +47 -0
  129. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +40 -0
  130. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
  131. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +36 -0
  132. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -0
  133. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  134. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +213 -0
  135. package/gradle/libs.versions.toml +71 -0
  136. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  137. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  138. package/gradle.properties +26 -0
  139. package/gradlew +252 -0
  140. package/gradlew.bat +94 -0
  141. package/ios-demo/README.md +120 -0
  142. package/package.json +1 -1
  143. 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
+ }