@momo-kits/native-kits 0.156.6-dialog.1-debug → 0.156.6-newcompose.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 (39) hide show
  1. package/compose/build.gradle.kts +1 -4
  2. package/compose/build.gradle.kts.backup +0 -3
  3. package/compose/compose.podspec +11 -5
  4. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -162
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +12 -0
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +19 -17
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +198 -0
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +42 -51
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +23 -10
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +15 -12
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +14 -13
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +6 -7
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +576 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -4
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +1 -1
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +1 -0
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -0
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +1 -49
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +152 -48
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +14 -1
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +29 -12
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +4 -2
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +2 -1
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +4 -1
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +1 -22
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  27. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +2 -178
  28. package/gradle/libs.versions.toml +1 -1
  29. package/gradle.properties +1 -1
  30. package/ios/Application/FloatingButton.swift +1 -1
  31. package/ios/Badge/BadgeRibbon.swift +2 -2
  32. package/ios/Image/Image.swift +5 -1
  33. package/ios/Input/Input.swift +2 -2
  34. package/ios/Input/InputPhoneNumber.swift +7 -3
  35. package/ios/Popup/PopupDisplay.swift +6 -12
  36. package/local.properties +1 -1
  37. package/package.json +1 -1
  38. package/publish.sh +26 -1
  39. package/compose/MoMoComposeKits.podspec +0 -54
@@ -18,10 +18,8 @@ import androidx.compose.runtime.remember
18
18
  import androidx.compose.runtime.staticCompositionLocalOf
19
19
  import androidx.compose.ui.unit.Dp
20
20
  import androidx.compose.ui.unit.dp
21
- import androidx.compose.ui.window.DialogProperties
22
21
  import androidx.navigation.compose.NavHost
23
22
  import androidx.navigation.compose.composable
24
- import androidx.navigation.compose.dialog
25
23
  import androidx.navigation.compose.rememberNavController
26
24
  import androidx.navigation.toRoute
27
25
  import vn.momo.kits.application.AppConfig
@@ -32,11 +30,9 @@ import vn.momo.kits.application.MiniAppContext
32
30
  import vn.momo.kits.const.AppNavigationBar
33
31
  import vn.momo.kits.const.AppStatusBar
34
32
  import vn.momo.kits.const.AppTheme
35
- import vn.momo.kits.const.AppThemeController
36
33
  import vn.momo.kits.const.Theme
37
34
  import vn.momo.kits.const.ThemeAssets
38
35
  import vn.momo.kits.const.defaultTheme
39
- import vn.momo.kits.platform.ConfigureDialogWindow
40
36
  import vn.momo.kits.utils.getAppStatusBarHeight
41
37
  import vn.momo.maxapi.IMaxApi
42
38
 
@@ -83,7 +79,6 @@ fun NavigationContainer(
83
79
  LocalNavigator provides navigator,
84
80
  LocalMaxApi provides maxApi,
85
81
  AppTheme provides theme.value,
86
- AppThemeController provides { theme.value = it },
87
82
  AppStatusBar provides statusBarHeight,
88
83
  AppNavigationBar provides navigationBarHeight,
89
84
  ApplicationContext provides mergedContext,
@@ -95,7 +90,6 @@ fun NavigationContainer(
95
90
  }
96
91
 
97
92
  NavHost(navController, startDestination = startDestination) {
98
- // ── Stack screens (push/replace/reset) ──────────────────────────
99
93
  composable<DynamicScreenRoute>(
100
94
  enterTransition = {
101
95
  slideInHorizontally(
@@ -124,7 +118,6 @@ fun NavigationContainer(
124
118
  }
125
119
  }
126
120
 
127
- // ── Present screens (vertical slide dialog) ──────────────────────
128
121
  composable<DynamicDialogRoute>(
129
122
  enterTransition = {
130
123
  slideInVertically (
@@ -152,48 +145,6 @@ fun NavigationContainer(
152
145
  )
153
146
  }
154
147
  }
155
-
156
- // ── Bottom Sheet dialog ──────────────────────────────────────────
157
- dialog<DynamicBottomSheetRoute>(
158
- dialogProperties = DialogProperties(
159
- dismissOnBackPress = false,
160
- dismissOnClickOutside = false,
161
- usePlatformDefaultWidth = false
162
- )
163
- ) { backStackEntry ->
164
- val route = backStackEntry.toRoute<DynamicBottomSheetRoute>()
165
- val screen = DynamicScreenRegistry.getScreen(route.id)
166
- ConfigureDialogWindow()
167
- screen?.content?.invoke()
168
- }
169
-
170
- // ── Modal dialog ─────────────────────────────────────────────────
171
- dialog<DynamicModalRoute>(
172
- dialogProperties = DialogProperties(
173
- dismissOnBackPress = false,
174
- dismissOnClickOutside = false,
175
- usePlatformDefaultWidth = false,
176
- )
177
- ) { backStackEntry ->
178
- val route = backStackEntry.toRoute<DynamicModalRoute>()
179
- val screen = DynamicScreenRegistry.getScreen(route.id)
180
- ConfigureDialogWindow()
181
- screen?.content?.invoke()
182
- }
183
-
184
- // ── Snack Bar dialog ─────────────────────────────────────────────
185
- dialog<DynamicSnackBarRoute>(
186
- dialogProperties = DialogProperties(
187
- dismissOnBackPress = false,
188
- dismissOnClickOutside = false,
189
- usePlatformDefaultWidth = false
190
- )
191
- ) { backStackEntry ->
192
- val route = backStackEntry.toRoute<DynamicSnackBarRoute>()
193
- val screen = DynamicScreenRegistry.getScreen(route.id)
194
- ConfigureDialogWindow()
195
- screen?.content?.invoke()
196
- }
197
148
  }
198
149
  }
199
150
 
@@ -207,3 +158,4 @@ fun NavigationContainer(
207
158
  val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
208
159
  error("No MaxApi provided")
209
160
  }
161
+
@@ -3,6 +3,8 @@ package vn.momo.kits.navigation
3
3
  import androidx.compose.foundation.layout.Box
4
4
  import androidx.compose.foundation.layout.fillMaxSize
5
5
  import androidx.compose.runtime.Composable
6
+ import androidx.compose.runtime.MutableState
7
+ import androidx.compose.runtime.mutableStateOf
6
8
  import androidx.compose.runtime.staticCompositionLocalOf
7
9
  import androidx.compose.ui.Alignment
8
10
  import androidx.compose.ui.Modifier
@@ -70,18 +72,31 @@ class Navigator(
70
72
  fun pop(count: Int = 1, callBack: (() -> Unit)? = null) {
71
73
  scope.launch {
72
74
  repeat(count) {
73
- dismissEntry()
75
+ if (OverplayComponentRegistry.getOverplayType() == OverplayComponentType.SNACK_BAR){
76
+ dismissScreen()
77
+ OverplayComponentRegistry.hardClearAfterDismiss()
78
+ }
79
+ else if (OverplayComponentRegistry.isOverplayShowing()){
80
+ dismissOverplay()
81
+ } else {
82
+ dismissScreen()
83
+ }
74
84
  }
75
85
  callBack?.invoke()
76
86
  }
77
87
  }
88
+ private suspend fun dismissOverplay(isDelay: Boolean = true) {
89
+ OverplayComponentRegistry.clear()
90
+ if (isDelay) delay(300L)
91
+ OverplayComponentRegistry.hardClearAfterDismiss()
92
+ }
78
93
 
79
- private suspend fun dismissEntry() {
80
- if (navController.previousBackStackEntry != null) {
94
+ private suspend fun dismissScreen() {
95
+ if (navController.previousBackStackEntry != null){
81
96
  navController.popBackStack()
82
97
  delay(300L)
83
- DynamicScreenRegistry.getLatestScreen()?.let {
84
- DynamicScreenRegistry.unregisterScreen(it.id)
98
+ DynamicScreenRegistry.getLatestScreen()?.let { it1 ->
99
+ DynamicScreenRegistry.unregisterScreen(it1.id)
85
100
  }
86
101
  } else {
87
102
  maxApi?.dismiss { }
@@ -107,14 +122,8 @@ class Navigator(
107
122
  barrierDismissible: Boolean = true,
108
123
  onDismiss: (() -> Unit)? = null
109
124
  ){
110
- val route = DynamicScreenRegistry.register({
111
- ModalScreen(
112
- content = content,
113
- barrierDismissible = barrierDismissible,
114
- onDismiss = onDismiss
115
- )
116
- }, null)
117
- navController.navigate(DynamicModalRoute(route.id))
125
+ val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
126
+ OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.MODAL, false, barrierDismissible, onDismiss)
118
127
  }
119
128
 
120
129
  fun showBottomSheet(
@@ -124,42 +133,32 @@ class Navigator(
124
133
  onDismiss: (() -> Unit)? = null,
125
134
  bottomSheetHeader: BottomHeader? = null
126
135
  ){
127
- val route = DynamicScreenRegistry.register({
128
- BottomSheet(
129
- content = content,
130
- header = bottomSheetHeader ?: Title(),
131
- isSurface = isSurface,
132
- barrierDismissible = barrierDismissible,
133
- onDismiss = onDismiss
134
- )
135
- }, null)
136
- navController.navigate(DynamicBottomSheetRoute(route.id))
136
+ val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
137
+ OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
137
138
  }
138
139
 
139
140
  fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
140
- val capturedSnackBar = snackBar
141
- val capturedOnDismiss = onDismiss
142
- val route = DynamicScreenRegistry.register({
143
- Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
144
- SnackBar(capturedSnackBar, capturedOnDismiss)
145
- }
146
- }, null)
147
- navController.navigate(DynamicSnackBarRoute(route.id))
141
+ val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
142
+ scope.launch {
143
+ OverplayComponentRegistry.registerOverplay(
144
+ id = id,
145
+ content = {
146
+ SnackBar(snackBar, onDismiss)
147
+ },
148
+ type = OverplayComponentType.SNACK_BAR,
149
+ onDismiss = onDismiss
150
+ )
151
+ }
148
152
  }
149
153
 
150
154
  fun hideSnackBar() {
151
155
  scope.launch {
152
- if (navController.previousBackStackEntry != null) {
153
- navController.popBackStack()
154
- delay(250L)
155
- DynamicScreenRegistry.getLatestScreen()?.let {
156
- DynamicScreenRegistry.unregisterScreen(it.id)
157
- }
158
- }
156
+ OverplayComponentRegistry.clear()
157
+ delay(250L)
158
+ OverplayComponentRegistry.hardClearAfterDismiss()
159
159
  }
160
160
  }
161
161
 
162
-
163
162
  fun dispose(){
164
163
  scope.cancel()
165
164
  }
@@ -175,15 +174,6 @@ data class DynamicScreenRoute(val id: Int)
175
174
  @Serializable
176
175
  data class DynamicDialogRoute(val id: Int)
177
176
 
178
- @Serializable
179
- data class DynamicBottomSheetRoute(val id: Int)
180
-
181
- @Serializable
182
- data class DynamicModalRoute(val id: Int)
183
-
184
- @Serializable
185
- data class DynamicSnackBarRoute(val id: Int)
186
-
187
177
  data class DynamicScreen(
188
178
  val id: Int,
189
179
  val content: @Composable () -> Unit,
@@ -225,3 +215,117 @@ object DynamicScreenRegistry {
225
215
  screens[id]?.options = options
226
216
  }
227
217
  }
218
+
219
+
220
+ sealed class OverplayComponentParams {
221
+ class Modal(
222
+ val onDismiss: (() -> Unit)? = null,
223
+ val barrierDismissible: Boolean = true
224
+ ) : OverplayComponentParams()
225
+
226
+ class BottomSheet(
227
+ val isSurface: Boolean = false,
228
+ val onDismiss: (() -> Unit)? = null,
229
+ val barrierDismissible: Boolean = true,
230
+ val bottomSheetHeader: BottomHeader? = null,
231
+ ) : OverplayComponentParams()
232
+
233
+ class SnackBar() : OverplayComponentParams()
234
+ }
235
+
236
+ data class OverplayComponent(
237
+ val id: Int,
238
+ val type: OverplayComponentType? = null,
239
+ val content: @Composable () -> Unit,
240
+ val params: OverplayComponentParams? = null
241
+ )
242
+
243
+ enum class OverplayComponentType {
244
+ MODAL, BOTTOM_SHEET, SNACK_BAR
245
+ }
246
+
247
+ object OverplayComponentRegistry {
248
+ private var currentOverlayComponent : MutableState<OverplayComponent?> = mutableStateOf(null)
249
+ private var requestClose: (() -> Unit)? = null
250
+ internal fun bindClose(handler: (() -> Unit)?) {
251
+ requestClose = handler
252
+ }
253
+
254
+ fun registerOverplay(
255
+ id: Int,
256
+ content: @Composable () -> Unit,
257
+ type: OverplayComponentType,
258
+ isSurface: Boolean = false,
259
+ barrierDismissible: Boolean = true,
260
+ onDismiss: (() -> Unit)?,
261
+ bottomSheetHeader: BottomHeader? = null,
262
+ ){
263
+ val params = when(type){
264
+ OverplayComponentType.MODAL -> OverplayComponentParams.Modal(onDismiss, barrierDismissible)
265
+ OverplayComponentType.BOTTOM_SHEET -> OverplayComponentParams.BottomSheet(isSurface, onDismiss, barrierDismissible, bottomSheetHeader)
266
+ OverplayComponentType.SNACK_BAR -> OverplayComponentParams.SnackBar()
267
+ }
268
+
269
+ currentOverlayComponent.value = OverplayComponent(
270
+ id = id,
271
+ type = type,
272
+ content = content,
273
+ params = params
274
+ )
275
+ }
276
+
277
+ fun isOverplayShowing(): Boolean = currentOverlayComponent.value != null
278
+
279
+ fun getOverplayType(): OverplayComponentType? = currentOverlayComponent.value?.type
280
+
281
+ fun currentRootId(): Int? = currentOverlayComponent.value?.id
282
+
283
+ fun clear(){
284
+ if (requestClose != null) {
285
+ requestClose?.invoke()
286
+ } else {
287
+ currentOverlayComponent.value = null
288
+ }
289
+ }
290
+
291
+ internal fun hardClearAfterDismiss() {
292
+ currentOverlayComponent.value = null
293
+ requestClose = null
294
+ }
295
+
296
+ @Composable
297
+ fun OverlayComponent(){
298
+ val overplay = currentOverlayComponent.value ?: return
299
+
300
+ when (val params = overplay.params) {
301
+ is OverplayComponentParams.BottomSheet -> {
302
+ BottomSheet(
303
+ content = overplay.content,
304
+ header = params.bottomSheetHeader ?: Title(),
305
+ isSurface = params.isSurface,
306
+ barrierDismissible = params.barrierDismissible,
307
+ onDismiss = params.onDismiss
308
+ )
309
+ }
310
+
311
+ is OverplayComponentParams.Modal -> {
312
+ ModalScreen(
313
+ content = overplay.content,
314
+ barrierDismissible = params.barrierDismissible,
315
+ onDismiss = params.onDismiss
316
+ )
317
+ }
318
+
319
+ is OverplayComponentParams.SnackBar -> {
320
+ Box(
321
+ modifier = Modifier.fillMaxSize(),
322
+ contentAlignment = Alignment.BottomCenter
323
+ ) {
324
+ overplay.content()
325
+ }
326
+ }
327
+
328
+ null -> {}
329
+ }
330
+ }
331
+ }
@@ -138,6 +138,8 @@ internal fun StackScreen(
138
138
  Box(Modifier.zIndex(7f)){
139
139
  FloatingContent()
140
140
  }
141
+
142
+ OverplayView(bottomTabIndex = bottomTabIndex, id = id)
141
143
  }
142
144
  }
143
145
  }
@@ -237,7 +239,18 @@ fun FooterContent(){
237
239
  }
238
240
  }
239
241
 
240
-
242
+ @Composable
243
+ fun OverplayView(bottomTabIndex: Int, id: Int){
244
+ val overplayType = OverplayComponentRegistry.getOverplayType()
245
+
246
+ if (overplayType != null) {
247
+ Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 8f).fillMaxSize()){
248
+ if (bottomTabIndex != -1) return@Box
249
+ if (OverplayComponentRegistry.currentRootId() != id) return@Box
250
+ OverplayComponentRegistry.OverlayComponent()
251
+ }
252
+ }
253
+ }
241
254
 
242
255
  @Composable
243
256
  fun Footer(footerComponent: @Composable (() -> Unit)?, bottomPadding: Dp) {
@@ -40,13 +40,15 @@ import vn.momo.kits.const.Colors
40
40
  import vn.momo.kits.const.Radius
41
41
  import vn.momo.kits.const.Spacing
42
42
  import vn.momo.kits.application.IsShowBaseLineDebug
43
+ import vn.momo.kits.components.BadgeDot
44
+ import vn.momo.kits.components.DotSize
43
45
  import vn.momo.kits.const.Typography
44
46
  import vn.momo.kits.modifier.conditional
45
47
  import vn.momo.kits.modifier.noFeedbackClickable
46
48
  import vn.momo.kits.platform.getScreenDimensions
47
49
 
48
50
  val floatingButtonWidth = 75.dp
49
- const val BOTTOM_TAB_BAR_HEIGHT = 56
51
+ const val BOTTOM_TAB_BAR_HEIGHT = 64
50
52
 
51
53
  @Composable
52
54
  fun BottomTabBar(
@@ -142,6 +144,18 @@ fun RowScope.renderTabBarItem(
142
144
 
143
145
  @Composable
144
146
  fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
147
+ fun isNumber(label: String): Boolean {
148
+ val numberRegex = "^\\d+$".toRegex()
149
+ return numberRegex.matches(label)
150
+ }
151
+ fun formatLabel(label: String): String? {
152
+ if (isNumber(label) && label.toInt() == 0) {
153
+ return null
154
+ }
155
+ return label
156
+ }
157
+ val badgeLabel = item.badgeLabel?.let { formatLabel(it) }
158
+
145
159
  Box(modifier = Modifier
146
160
  .fillMaxSize()
147
161
  .padding(horizontal = Spacing.XXS)
@@ -156,31 +170,34 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
156
170
  Column(
157
171
  modifier = Modifier
158
172
  .fillMaxSize()
159
- .padding(horizontal = Spacing.XXS)
173
+ .padding(horizontal = Spacing.S, vertical = Spacing.S)
160
174
  .noFeedbackClickable {
161
175
  onClick()
162
176
  },
163
177
  horizontalAlignment = Alignment.CenterHorizontally,
164
- verticalArrangement = Arrangement.Bottom
178
+ verticalArrangement = Arrangement.Center
165
179
  ) {
166
180
  Icon(
167
181
  source = item.icon,
168
- modifier = Modifier.weight(1f),
182
+ size = 28.dp,
183
+ modifier = Modifier.padding(Spacing.XS),
169
184
  color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint)
170
185
  Text(
171
186
  text = item.label,
172
187
  color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint,
173
- style = Typography.labelXsMedium,
188
+ style = if (selected) Typography.labelXsMedium else Typography.descriptionXsRegular,
174
189
  maxLines = 1,
175
190
  overflow = TextOverflow.Ellipsis
176
191
  )
177
192
  }
178
- if(item.badgeLabel != null){
179
- Box(modifier = Modifier
180
- .offset(x = 44.dp, y = (-32).dp)
181
- ){
182
- Badge(item.badgeLabel)
183
- }
193
+ if (badgeLabel != null) {
194
+ if (badgeLabel.isEmpty())
195
+ BadgeDot(
196
+ size = DotSize.Small,
197
+ modifier = Modifier.offset(x = 50.dp, y = (-48).dp)
198
+ )
199
+ else
200
+ Badge(badgeLabel, modifier = Modifier.offset(x = 44.dp, y = (-42).dp))
184
201
  }
185
202
  }
186
203
  }
@@ -190,7 +207,7 @@ fun FloatingButton(data: BottomTabFloatingButton) {
190
207
  Column(
191
208
  modifier = Modifier
192
209
  .width(floatingButtonWidth)
193
- .padding(horizontal = Spacing.XXS)
210
+ .padding(horizontal = Spacing.XXS, vertical = Spacing.S)
194
211
  .conditional(IsShowBaseLineDebug) {
195
212
  border(1.dp, Colors.blue_03)
196
213
  }
@@ -35,6 +35,7 @@ import vn.momo.kits.application.IsShowBaseLineDebug
35
35
  import vn.momo.kits.const.Spacing
36
36
  import vn.momo.kits.modifier.activeOpacityClickable
37
37
  import vn.momo.kits.modifier.conditional
38
+ import vn.momo.kits.modifier.setAutomationId
38
39
  import vn.momo.kits.navigation.LocalHeaderRightWidthPx
39
40
  import vn.momo.kits.navigation.LocalNavigator
40
41
  import vn.momo.kits.navigation.LocalOptions
@@ -119,14 +120,15 @@ fun Header(onBackHandler: (() -> Unit)? = null) {
119
120
  }
120
121
 
121
122
  @Composable
122
- fun BackButton(borderColor: Color, backgroundButton: Color, tintIconColor: Color, onBackHandler: () -> Unit){
123
+ private fun BackButton(borderColor: Color, backgroundButton: Color, tintIconColor: Color, onBackHandler: () -> Unit){
123
124
  Box(
124
125
  modifier = Modifier
125
126
  .size(28.dp)
126
127
  .background(backgroundButton, RoundedCornerShape(100))
127
128
  .border(width = 0.2.dp, color = borderColor, shape = RoundedCornerShape(100))
128
129
  .activeOpacityClickable(onClick = onBackHandler)
129
- .padding(Spacing.XS),
130
+ .padding(Spacing.XS)
131
+ .setAutomationId("btn_navigation_back"),
130
132
  contentAlignment = Alignment.Center
131
133
  ) {
132
134
  Icon(
@@ -10,6 +10,7 @@ import androidx.compose.ui.unit.sp
10
10
  import androidx.compose.ui.zIndex
11
11
  import vn.momo.kits.components.Text
12
12
  import vn.momo.kits.const.Typography
13
+ import vn.momo.kits.modifier.setAutomationId
13
14
 
14
15
  @Composable
15
16
  fun HeaderTitle(
@@ -17,7 +18,7 @@ fun HeaderTitle(
17
18
  color: Color? = null,
18
19
  ) {
19
20
  Text(
20
- modifier = Modifier.fillMaxWidth().zIndex(1f),
21
+ modifier = Modifier.fillMaxWidth().zIndex(1f).setAutomationId("title_navigation_header"),
21
22
  text = title,
22
23
  textAlign = TextAlign.Start,
23
24
  style = Typography.actionSBold.copy(
@@ -29,7 +29,7 @@ import vn.momo.kits.const.AppNavigationBar
29
29
  import vn.momo.kits.navigation.LocalFooterHeightPx
30
30
  import vn.momo.kits.navigation.LocalNavigator
31
31
  import vn.momo.kits.navigation.LocalOptions
32
-
32
+ import vn.momo.kits.navigation.OverplayComponentRegistry
33
33
 
34
34
  sealed class SnackBar(open val duration: Long? = null) {
35
35
  data class Custom(
@@ -102,6 +102,9 @@ fun SnackBar(
102
102
  }
103
103
 
104
104
  DisposableEffect(Unit) {
105
+ OverplayComponentRegistry.bindClose {
106
+ closeEvent()
107
+ }
105
108
  onDispose {
106
109
  onDismiss?.invoke()
107
110
  }
@@ -5,7 +5,6 @@ import androidx.compose.ui.Modifier
5
5
  import androidx.compose.ui.graphics.Color
6
6
  import androidx.compose.ui.graphics.NativePaint
7
7
  import androidx.compose.ui.unit.Dp
8
- import vn.momo.kits.components.Options
9
8
 
10
9
  data class ScreenDimension(
11
10
  val width: Int,
@@ -40,24 +39,4 @@ expect fun LottieAnimation(
40
39
 
41
40
  expect fun NativePaint.setColor(
42
41
  color: Color = Color.Black
43
- )
44
- @Composable
45
- expect fun NativeImage(
46
- source: Any,
47
- options: Options,
48
- loading: Boolean,
49
- onLoading: () -> Unit = {},
50
- onSuccess: () -> Unit = {},
51
- onError: () -> Unit = {},
52
- )
53
-
54
- /**
55
- * Configures the current Dialog window's system-bar behaviour.
56
- *
57
- * @param decorFitsSystemWindows When `false` (the default) the dialog window
58
- * extends behind the status bar and navigation bar so that a full-screen
59
- * scrim/background covers the entire display uniformly.
60
- * Pass `true` to restore the default platform inset handling.
61
- */
62
- @Composable
63
- expect fun ConfigureDialogWindow(decorFitsSystemWindows: Boolean = false)
42
+ )
@@ -0,0 +1,15 @@
1
+ package vn.momo.kits.utils
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import vn.momo.kits.application.LocalComponentInformation
5
+
6
+ @Composable
7
+ fun getComponentId(
8
+ componentName: String? = null,
9
+ accessibilityLabel: String? = null,
10
+ ): String {
11
+ val componentInformation = LocalComponentInformation.current
12
+ if (accessibilityLabel != null) return accessibilityLabel
13
+ if (componentInformation?.componentId != null) return componentInformation.componentId
14
+ return ""
15
+ }