@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
@@ -11,17 +11,14 @@ import androidx.compose.foundation.interaction.collectIsPressedAsState
11
11
  import androidx.compose.foundation.layout.Arrangement
12
12
  import androidx.compose.foundation.layout.Box
13
13
  import androidx.compose.foundation.layout.Row
14
- import androidx.compose.foundation.layout.defaultMinSize
15
14
  import androidx.compose.foundation.layout.fillMaxWidth
16
15
  import androidx.compose.foundation.layout.height
17
16
  import androidx.compose.foundation.layout.padding
18
17
  import androidx.compose.foundation.layout.size
19
18
  import androidx.compose.foundation.shape.RoundedCornerShape
20
19
  import androidx.compose.runtime.Composable
21
- import androidx.compose.runtime.CompositionLocalProvider
22
20
  import androidx.compose.runtime.getValue
23
21
  import androidx.compose.runtime.remember
24
- import androidx.compose.runtime.staticCompositionLocalOf
25
22
  import androidx.compose.ui.Alignment
26
23
  import androidx.compose.ui.Modifier
27
24
  import androidx.compose.ui.draw.alpha
@@ -127,13 +124,12 @@ fun getTextColor(loading: Boolean, type: ButtonType): Color {
127
124
  }
128
125
 
129
126
  @Composable
130
- fun RenderTitle(size: Size, title: String = "", type: ButtonType) {
127
+ fun RenderTitle(size: Size, title: String = "", textColor: Color) {
131
128
  val style = remember(size) { getStyle(size) }
132
- val color = TextColor.current
133
129
  Text(
134
130
  style = style,
135
131
  text = title,
136
- color = color,
132
+ color = textColor,
137
133
  overflow = TextOverflow.Ellipsis,
138
134
  maxLines = 1
139
135
  )
@@ -145,21 +141,20 @@ fun RenderIcon(
145
141
  isIconLeft: Boolean,
146
142
  useTintColor: Boolean = true,
147
143
  icon: String = "",
148
- forceLoading: Boolean = false
144
+ forceLoading: Boolean = false,
145
+ bgColor: Color? = null,
146
+ textColor: Color? = null,
149
147
  ) {
150
- val bgColor = BackgroundColor.current
151
148
  val iconSize = remember(size) { getIconSize(size) }
152
149
  val margin = remember(size) { getIconSpace(size) }
153
- val color = if (useTintColor) TextColor.current else Color.Unspecified
154
-
155
- val showLoading = forceLoading
150
+ val color = if (useTintColor) textColor else Color.Unspecified
156
151
 
157
152
  val modifier = Modifier.padding(
158
153
  start = if (isIconLeft) 0.dp else margin,
159
154
  end = if (isIconLeft) margin else 0.dp
160
155
  )
161
156
 
162
- if (showLoading) {
157
+ if (forceLoading) {
163
158
  Box(modifier) {
164
159
  LottieAnimation(
165
160
  modifier = Modifier.size(iconSize),
@@ -195,9 +190,9 @@ fun getTypeStyle(
195
190
  type: ButtonType,
196
191
  color: Color? = AppTheme.current.colors.primary,
197
192
  size: Size,
193
+ bgColor: Color,
198
194
  ): Modifier {
199
195
  val theme = AppTheme.current
200
- val bgColor = BackgroundColor.current
201
196
  val radius = remember(size) { size.value.radius }
202
197
  val modifier = Modifier.background(bgColor)
203
198
 
@@ -304,45 +299,41 @@ fun Button(
304
299
  .clip(RoundedCornerShape(radius))
305
300
  }
306
301
 
307
- CompositionLocalProvider(
308
- IsLoading provides loading,
309
- BackgroundColor provides getButtonBackgroundColor(loading, type),
310
- TextColor provides getTextColor(loading, type)
302
+ val bgColor = getButtonBackgroundColor(loading, type)
303
+ val textColor = getTextColor(loading, type)
304
+
305
+ Row(
306
+ modifier = clickableModifier
307
+ .padding(horizontal = animatedPadding)
308
+ .clip(RoundedCornerShape(radius))
309
+ .then(getTypeStyle(type, size = size, bgColor = bgColor))
310
+ .conditional(IsShowBaseLineDebug) {
311
+ border(1.dp, Colors.blue_03)
312
+ }
313
+ .padding(horizontal = sizeSpecs.padding)
314
+ .height(sizeSpecs.height),
315
+ horizontalArrangement = Arrangement.Center,
316
+ verticalAlignment = Alignment.CenterVertically,
311
317
  ) {
312
- Row(
313
- modifier = clickableModifier
314
- .padding(horizontal = animatedPadding)
315
- .clip(RoundedCornerShape(radius))
316
- .then(getTypeStyle(type, size = size))
317
- .conditional(IsShowBaseLineDebug) {
318
- border(1.dp, Colors.blue_03)
319
- }
320
- .padding(horizontal = sizeSpecs.padding)
321
- .height(sizeSpecs.height),
322
- horizontalArrangement = Arrangement.Center,
323
- verticalAlignment = Alignment.CenterVertically,
324
- ) {
325
- RenderIcon(
326
- size = size,
327
- isIconLeft = true,
328
- useTintColor = useTintColor,
329
- icon = iconLeft,
330
- forceLoading = loading && loadingOnLeft
331
- )
332
- RenderTitle(size, title, type = type)
333
- RenderIcon(
334
- size = size,
335
- isIconLeft = false,
336
- useTintColor = useTintColor,
337
- icon = iconRight,
338
- forceLoading = loading && !loadingOnLeft
339
- )
340
- }
318
+ RenderIcon(
319
+ size = size,
320
+ isIconLeft = true,
321
+ useTintColor = useTintColor,
322
+ icon = iconLeft,
323
+ forceLoading = loading && loadingOnLeft,
324
+ bgColor = bgColor,
325
+ textColor = textColor
326
+ )
327
+ RenderTitle(size, title, textColor = textColor)
328
+ RenderIcon(
329
+ size = size,
330
+ isIconLeft = false,
331
+ useTintColor = useTintColor,
332
+ icon = iconRight,
333
+ forceLoading = loading && !loadingOnLeft,
334
+ bgColor = bgColor,
335
+ textColor = textColor
336
+ )
341
337
  }
342
338
  }
343
339
 
344
-
345
- private val IsLoading = staticCompositionLocalOf<Boolean> { false }
346
- private val BackgroundColor = staticCompositionLocalOf<Color> { Color.Transparent }
347
- private val TextColor = staticCompositionLocalOf<Color> { Color.Transparent }
348
-
@@ -5,14 +5,17 @@ import androidx.compose.foundation.layout.Box
5
5
  import androidx.compose.foundation.layout.size
6
6
  import androidx.compose.runtime.Composable
7
7
  import androidx.compose.runtime.remember
8
- import androidx.compose.ui.Alignment
9
8
  import androidx.compose.ui.Modifier
10
9
  import androidx.compose.ui.graphics.Color
10
+ import androidx.compose.ui.graphics.ColorFilter
11
11
  import androidx.compose.ui.layout.ContentScale
12
12
  import androidx.compose.ui.semantics.contentDescription
13
13
  import androidx.compose.ui.semantics.semantics
14
14
  import androidx.compose.ui.unit.Dp
15
15
  import androidx.compose.ui.unit.dp
16
+ import coil3.compose.AsyncImage
17
+ import coil3.compose.LocalPlatformContext
18
+ import coil3.request.ImageRequest
16
19
  import vn.momo.kits.application.IsShowBaseLineDebug
17
20
  import vn.momo.kits.const.AppTheme
18
21
  import vn.momo.kits.const.Colors
@@ -27,6 +30,9 @@ fun Icon(
27
30
  color: Color? = AppTheme.current.colors.text.default,
28
31
  modifier: Modifier = Modifier,
29
32
  ) {
33
+ // decode image without downscaling it
34
+ val context = LocalPlatformContext.current
35
+
30
36
  val iconUrl = remember(source) {
31
37
  if (source.contains("https")) {
32
38
  source
@@ -35,10 +41,14 @@ fun Icon(
35
41
  }
36
42
  }
37
43
 
38
- val iconColor = remember(source, color) {
44
+ val iconColor = remember(color) {
39
45
  if (noThemeIcons.contains(source)) null else color
40
46
  }
41
47
 
48
+ val colorFilter = remember(iconColor) {
49
+ iconColor?.let { ColorFilter.tint(it) }
50
+ }
51
+
42
52
  val contentDesc = remember(iconUrl) { "img|$iconUrl" }
43
53
 
44
54
  Box(
@@ -49,15 +59,18 @@ fun Icon(
49
59
  }
50
60
  .semantics { contentDescription = contentDesc }
51
61
  ) {
52
- Image(
53
- source = iconUrl,
62
+ AsyncImage(
54
63
  modifier = Modifier.matchParentSize(),
55
- options = Options(
56
- contentScale = ContentScale.Fit,
57
- tintColor = iconColor,
58
- alignment = Alignment.Center,
59
- ),
60
- loading = false,
64
+ model = ImageRequest.Builder(context)
65
+ .data(iconUrl)
66
+ .size(
67
+ coil3.size.Dimension.Undefined,
68
+ coil3.size.Dimension.Undefined
69
+ )
70
+ .build(),
71
+ contentDescription = null,
72
+ contentScale = ContentScale.Fit,
73
+ colorFilter = colorFilter,
61
74
  )
62
75
  }
63
76
  }
@@ -9,8 +9,6 @@ import androidx.compose.runtime.remember
9
9
  import androidx.compose.runtime.setValue
10
10
  import androidx.compose.ui.Alignment
11
11
  import androidx.compose.ui.Modifier
12
- import androidx.compose.ui.draw.clipToBounds
13
- import androidx.compose.ui.graphics.Color
14
12
  import androidx.compose.ui.graphics.ColorFilter
15
13
  import androidx.compose.ui.graphics.DefaultAlpha
16
14
  import androidx.compose.ui.graphics.painter.Painter
@@ -24,12 +22,11 @@ import vn.momo.kits.application.IsShowBaseLineDebug
24
22
  import vn.momo.kits.const.AppTheme
25
23
  import vn.momo.kits.const.Colors
26
24
  import vn.momo.kits.modifier.conditional
27
- import vn.momo.kits.platform.NativeImage
28
25
 
29
26
  data class Options(
30
27
  val alignment: Alignment = Alignment.TopStart,
31
28
  val contentScale: ContentScale = ContentScale.Crop,
32
- val tintColor: Color? = null,
29
+ val colorFilter: ColorFilter? = null,
33
30
  val alpha: Float = DefaultAlpha,
34
31
  )
35
32
 
@@ -99,14 +96,15 @@ fun Image(
99
96
  options: Options? = null,
100
97
  loading: Boolean = true,
101
98
  ) {
102
- val imageOptions = remember(options) { options ?: Options() }
99
+ val imageOptions = remember(options) {
100
+ options ?: Options()
101
+ }
103
102
 
104
103
  var imageState by remember { mutableStateOf(ImageState.Loading) }
105
104
  val density = LocalDensity.current
106
105
 
107
106
  BoxWithConstraints(
108
107
  modifier = modifier
109
- .clipToBounds()
110
108
  .conditional(IsShowBaseLineDebug) {
111
109
  border(1.dp, Colors.blue_03)
112
110
  }
@@ -115,6 +113,7 @@ fun Image(
115
113
  val urlToLoad = remember(source, maxWidth, maxHeight, density) {
116
114
  when (source) {
117
115
  is String -> {
116
+ // Check cache first
118
117
  val cacheKey = "$source|${maxWidth}|${density.density}"
119
118
  urlCache[cacheKey] ?: run {
120
119
  val processedUrl = processImageUrl(source, maxWidth, density)
@@ -126,13 +125,17 @@ fun Image(
126
125
  }
127
126
  }
128
127
 
129
- NativeImage(
130
- source = urlToLoad,
131
- options = imageOptions,
132
- loading = loading,
128
+ AsyncImage(
129
+ modifier = Modifier.matchParentSize(),
130
+ model = urlToLoad,
131
+ contentDescription = null,
132
+ contentScale = imageOptions.contentScale,
133
+ alignment = imageOptions.alignment,
134
+ colorFilter = imageOptions.colorFilter,
135
+ alpha = imageOptions.alpha,
133
136
  onLoading = { imageState = ImageState.Loading },
134
137
  onSuccess = { imageState = ImageState.Success },
135
- onError = { imageState = ImageState.Error },
138
+ onError = { imageState = ImageState.Error },
136
139
  )
137
140
 
138
141
  when (imageState) {
@@ -145,7 +148,7 @@ fun Image(
145
148
  modifier = Modifier.align(Alignment.Center)
146
149
  )
147
150
  }
148
- ImageState.Success -> Unit
151
+ ImageState.Success -> {}
149
152
  }
150
153
  }
151
154
  }
@@ -43,11 +43,11 @@ import androidx.compose.ui.unit.TextUnit
43
43
  import androidx.compose.ui.unit.dp
44
44
  import androidx.compose.ui.unit.sp
45
45
  import androidx.compose.ui.zIndex
46
+ import vn.momo.kits.application.IsShowBaseLineDebug
46
47
  import vn.momo.kits.const.AppTheme
48
+ import vn.momo.kits.const.Colors
47
49
  import vn.momo.kits.const.Radius
48
50
  import vn.momo.kits.const.Spacing
49
- import vn.momo.kits.application.IsShowBaseLineDebug
50
- import vn.momo.kits.const.Colors
51
51
  import vn.momo.kits.const.Typography
52
52
  import vn.momo.kits.const.getFont
53
53
  import vn.momo.kits.const.scaleSize
@@ -141,7 +141,7 @@ fun getBorderColor(isFocused: Boolean, error: String, disabled: Boolean): Color
141
141
  }
142
142
 
143
143
  @Composable
144
- fun RenderRightIcon(loading: Boolean, icon: String, color: Color, onClick: () -> Unit) {
144
+ fun RenderRightIcon(loading: Boolean, icon: String, color: Color, onClick: () -> Unit, modifier: Modifier = Modifier) {
145
145
  if (loading) {
146
146
  Box {
147
147
  CircularProgressIndicator(
@@ -157,7 +157,7 @@ fun RenderRightIcon(loading: Boolean, icon: String, color: Color, onClick: () ->
157
157
  source = icon,
158
158
  color = color,
159
159
  size = 24.dp,
160
- modifier = Modifier.clickable(
160
+ modifier = modifier.clickable(
161
161
  onClick = onClick,
162
162
  interactionSource = remember { MutableInteractionSource() },
163
163
  indication = null
@@ -224,6 +224,7 @@ fun Input(
224
224
  fontWeight: InputFontWeight = InputFontWeight.REGULAR,
225
225
  keyboardType: KeyboardType = KeyboardType.Text,
226
226
  modifier: Modifier = Modifier,
227
+ inputModifier: Modifier = Modifier,
227
228
  ) {
228
229
  // Consolidated state management
229
230
  var inputState by remember { mutableStateOf(InputState()) }
@@ -253,10 +254,6 @@ fun Input(
253
254
  if (disabled) theme.colors.text.disable else floatingIconColor
254
255
  }
255
256
 
256
- val testId = remember(disabled, floatingValue) {
257
- if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
258
- }
259
-
260
257
  val fontSize = 14.sp
261
258
  val lineHeight = 24.sp
262
259
  val scaleFontSize = scaleSize(fontSize)
@@ -298,8 +295,7 @@ fun Input(
298
295
  Column(modifier = modifier
299
296
  .conditional(IsShowBaseLineDebug) {
300
297
  border(1.dp, Colors.blue_03)
301
- }
302
- .setAutomationId(testId)) {
298
+ }) {
303
299
  BasicTextField(
304
300
  enabled = !disabled,
305
301
  readOnly = readOnly,
@@ -308,7 +304,7 @@ fun Input(
308
304
  textStyle = textStyle,
309
305
  visualTransformation = visualTransformation,
310
306
  keyboardOptions = keyboardOptionsConfig,
311
- modifier = Modifier
307
+ modifier = inputModifier
312
308
  .height(scaleSize(size.values.height.value, 1.1f).dp)
313
309
  .onFocusChanged { focusState ->
314
310
  val wasFocused = inputState.isFocused
@@ -417,7 +413,7 @@ fun Input(
417
413
  },
418
414
  interactionSource = remember { MutableInteractionSource() },
419
415
  indication = null
420
- )
416
+ ).setAutomationId("ic_clear")
421
417
  )
422
418
  }
423
419
  }
@@ -430,7 +426,12 @@ fun Input(
430
426
  onRightIconPressed()
431
427
  inputState = inputState.copy(passHidden = !inputState.passHidden)
432
428
  }
433
- RenderRightIcon(loading, iconName, iconTintColor, togglePassword)
429
+ RenderRightIcon(
430
+ loading = loading,
431
+ icon = iconName,
432
+ color = iconTintColor,
433
+ onClick = togglePassword,
434
+ modifier = Modifier.setAutomationId("ic_show_hide"))
434
435
  }
435
436
  else -> {
436
437
  RenderRightIcon(loading, icon, iconTintColor, onRightIconPressed)
@@ -31,11 +31,11 @@ import androidx.compose.ui.text.TextStyle
31
31
  import androidx.compose.ui.text.input.KeyboardType
32
32
  import androidx.compose.ui.unit.Dp
33
33
  import androidx.compose.ui.unit.dp
34
+ import vn.momo.kits.application.IsShowBaseLineDebug
34
35
  import vn.momo.kits.const.AppTheme
35
36
  import vn.momo.kits.const.Colors
36
37
  import vn.momo.kits.const.Radius
37
38
  import vn.momo.kits.const.Spacing
38
- import vn.momo.kits.application.IsShowBaseLineDebug
39
39
  import vn.momo.kits.const.Typography
40
40
  import vn.momo.kits.const.scaleSize
41
41
  import vn.momo.kits.modifier.conditional
@@ -98,6 +98,7 @@ fun InputPhoneNumber(
98
98
  onBlur: () -> Unit = {},
99
99
  loading: Boolean = false,
100
100
  modifier: Modifier = Modifier,
101
+ inputModifier: Modifier = Modifier,
101
102
  ) {
102
103
  // Consolidated state management
103
104
  var inputState by remember { mutableStateOf(InputState()) }
@@ -113,23 +114,20 @@ fun InputPhoneNumber(
113
114
  }
114
115
 
115
116
  val (textColor, placeholderColor, iconTintColor) = colors
116
-
117
- val testId = "input_phone_number"
118
-
119
117
  val textStyle = scaleSize(size.values.textStyle.copy(color = textColor))
120
118
 
119
+
121
120
  Column(modifier = modifier
122
121
  .conditional(IsShowBaseLineDebug) {
123
122
  border(1.dp, Colors.blue_03)
124
- }
125
- .setAutomationId(testId)) {
123
+ }) {
126
124
  BasicTextField(
127
125
  singleLine = true,
128
126
  value = text.value,
129
127
  textStyle = textStyle,
130
128
  keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
131
129
  cursorBrush = SolidColor(AppTheme.current.colors.primary),
132
- modifier = Modifier
130
+ modifier = inputModifier
133
131
  .height(scaleSize(size.values.height.value, 1.1f).dp)
134
132
  .onFocusChanged { focusState ->
135
133
  val wasFocused = inputState.isFocused
@@ -218,6 +216,7 @@ fun InputPhoneNumber(
218
216
  indication = null
219
217
  )
220
218
  .padding(horizontal = Spacing.S)
219
+ .setAutomationId("ic_clear")
221
220
  )
222
221
  }
223
222
  }