@momo-kits/native-kits 0.162.2-beta.1-debug → 0.162.2-beta.15-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 (131) hide show
  1. package/CLAUDE.md +78 -0
  2. package/compose/build.gradle.kts +12 -8
  3. package/compose/build.gradle.kts.backup +15 -11
  4. package/compose/compose.podspec +1 -1
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +2 -7
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +2 -18
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +6 -24
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +4 -19
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +1 -10
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +2 -2
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +1 -1
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +1 -1
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +6 -17
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +1 -1
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +6 -101
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +5 -19
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +8 -33
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +1 -1
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +22 -25
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +27 -29
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +3 -26
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +27 -26
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +3 -13
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -5
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +3 -11
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +3 -18
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +11 -11
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +3 -11
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -5
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +84 -59
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +13 -71
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +10 -51
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +6 -1
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +4 -21
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +1 -1
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +16 -75
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +5 -26
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +1 -1
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +3 -11
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +16 -40
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +3 -9
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -28
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +2 -13
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -6
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +4 -10
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +3 -28
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +8 -47
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +4 -25
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +2 -11
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +1 -17
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +1 -6
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +50 -111
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +1 -5
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -5
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +1 -12
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +4 -96
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +5 -7
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +2 -12
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +9 -21
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +2 -2
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +9 -14
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +8 -11
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +1 -1
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +7 -32
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -1
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -5
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -2
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +94 -4
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -2
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +2 -2
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +3 -7
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +5 -15
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +33 -26
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +48 -33
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +58 -57
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +28 -25
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +13 -31
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +1 -1
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +6 -24
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +11 -6
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +2 -1
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +9 -6
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +1 -1
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +3 -13
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +3 -2
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +1 -40
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -2
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -8
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +2 -17
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +1 -1
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +3 -3
  94. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +2 -3
  95. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -2
  96. package/gradle/libs.versions.toml +2 -0
  97. package/gradle.properties +1 -1
  98. package/ios/Application/Components.swift +1 -0
  99. package/ios/Application/FloatingButton.swift +1 -0
  100. package/ios/Badge/Badge.swift +1 -0
  101. package/ios/Badge/BadgeRibbon.swift +2 -0
  102. package/ios/Button/Button.swift +1 -1
  103. package/ios/Checkbox/Checkbox.swift +1 -0
  104. package/ios/Information/Information.swift +151 -0
  105. package/ios/Input/Input.swift +1 -0
  106. package/ios/Input/InputPhoneNumber.swift +1 -0
  107. package/ios/Input/InputSearch.swift +3 -0
  108. package/ios/Input/InputTextArea.swift +1 -0
  109. package/ios/OTPKeyboard/KeyboardButton.swift +1 -1
  110. package/ios/Popup/PopupDisplay.swift +6 -0
  111. package/ios/Popup/PopupInput.swift +2 -0
  112. package/ios/Template/TrustBanner/TrustBanner.swift +2 -0
  113. package/ios/Typography/Text.swift +10 -19
  114. package/ios/Typography/Typography.swift +34 -9
  115. package/local.properties +2 -2
  116. package/package.json +1 -1
  117. package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Example.xcscheme +0 -32
  118. package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  119. package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  120. package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/WorkspaceSettings.xcsettings +0 -16
  121. package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
  122. package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
  123. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
  124. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
  125. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
  126. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
  127. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
  128. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios-LottiePrivacyInfo.xcscheme +0 -58
  129. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios.xcscheme +0 -58
  130. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -60
  131. package/ios/Typography/MomoFontScale.swift +0 -36
@@ -1,7 +1,9 @@
1
1
  package vn.momo.kits.components
2
2
 
3
3
  import androidx.compose.foundation.border
4
+ import androidx.compose.foundation.layout.Box
4
5
  import androidx.compose.foundation.layout.BoxWithConstraints
6
+ import androidx.compose.foundation.layout.fillMaxSize
5
7
  import androidx.compose.runtime.Composable
6
8
  import androidx.compose.runtime.getValue
7
9
  import androidx.compose.runtime.mutableStateOf
@@ -17,10 +19,12 @@ import androidx.compose.ui.semantics.contentDescription
17
19
  import androidx.compose.ui.semantics.semantics
18
20
  import androidx.compose.ui.platform.LocalDensity
19
21
  import androidx.compose.ui.unit.dp
20
- import coil3.compose.AsyncImage
22
+ import coil3.compose.AsyncImage as CoilAsyncImage
21
23
  import vn.momo.kits.application.IsShowBaseLineDebug
22
24
  import vn.momo.kits.const.AppTheme
23
25
  import vn.momo.kits.const.Colors
26
+ import vn.momo.kits.gifimage.GifImage
27
+ import vn.momo.kits.gifimage.GifImageState
24
28
  import vn.momo.kits.modifier.conditional
25
29
 
26
30
  data class Options(
@@ -73,6 +77,19 @@ private fun getHostFromUrl(url: String): String? {
73
77
  }
74
78
  }
75
79
 
80
+ private fun isGifUrl(url: String): Boolean {
81
+ val path = url.substringBefore('#').substringBefore('?')
82
+ return path.endsWith(".gif", ignoreCase = true)
83
+ }
84
+
85
+ private fun GifImageState.toImageState(): ImageState {
86
+ return when (this) {
87
+ GifImageState.Success -> ImageState.Success
88
+ GifImageState.Error -> ImageState.Error
89
+ GifImageState.Loading -> ImageState.Loading
90
+ }
91
+ }
92
+
76
93
  // Optimized query parameter appending
77
94
  private fun appendSizeQueryParam(url: String, value: String): String {
78
95
  val fragmentIndex = url.indexOf('#')
@@ -95,12 +112,12 @@ fun Image(
95
112
  modifier: Modifier = Modifier,
96
113
  options: Options? = null,
97
114
  loading: Boolean = true,
115
+ onStateChanged: (ImageState) -> Unit = {},
98
116
  ) {
99
117
  val imageOptions = remember(options) {
100
118
  options ?: Options()
101
119
  }
102
120
 
103
- var imageState by remember { mutableStateOf(ImageState.Loading) }
104
121
  val density = LocalDensity.current
105
122
 
106
123
  BoxWithConstraints(
@@ -121,34 +138,46 @@ fun Image(
121
138
  processedUrl
122
139
  }
123
140
  }
124
- else -> source
141
+ else -> source.toString()
125
142
  }
126
143
  }
127
144
 
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,
136
- onLoading = { imageState = ImageState.Loading },
137
- onSuccess = { imageState = ImageState.Success },
138
- onError = { imageState = ImageState.Error },
139
- )
145
+ var imageState by remember(urlToLoad) { mutableStateOf(ImageState.Loading) }
146
+ fun updateImageState(state: ImageState) {
147
+ imageState = state
148
+ onStateChanged(state)
149
+ }
150
+
151
+ if (isGifUrl(urlToLoad)) {
152
+ GifImage(
153
+ modifier = Modifier.matchParentSize(),
154
+ url = urlToLoad,
155
+ contentDescription = null,
156
+ contentScale = imageOptions.contentScale,
157
+ alignment = imageOptions.alignment,
158
+ colorFilter = imageOptions.colorFilter,
159
+ alpha = imageOptions.alpha,
160
+ onStateChanged = { updateImageState(it.toImageState()) },
161
+ )
162
+ } else {
163
+ CoilAsyncImage(
164
+ modifier = Modifier.matchParentSize(),
165
+ model = urlToLoad,
166
+ contentDescription = null,
167
+ contentScale = imageOptions.contentScale,
168
+ alignment = imageOptions.alignment,
169
+ colorFilter = imageOptions.colorFilter,
170
+ alpha = imageOptions.alpha,
171
+ onLoading = { updateImageState(ImageState.Loading) },
172
+ onSuccess = { updateImageState(ImageState.Success) },
173
+ onError = { updateImageState(ImageState.Error) },
174
+ )
175
+ }
140
176
 
141
177
  when (imageState) {
142
- ImageState.Loading -> if (loading) Skeleton()
143
- ImageState.Error -> {
144
- val theme = AppTheme.current
145
- Icon(
146
- source = "media_fail",
147
- color = theme.colors.text.disable,
148
- modifier = Modifier.align(Alignment.Center)
149
- )
150
- }
151
178
  ImageState.Success -> {}
179
+ ImageState.Error -> ImageError()
180
+ ImageState.Loading -> if (loading) Skeleton()
152
181
  }
153
182
  }
154
183
  }
@@ -156,7 +185,7 @@ fun Image(
156
185
  // Extracted URL processing logic for better performance
157
186
  private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp, density: androidx.compose.ui.unit.Density): String {
158
187
  val host = getHostFromUrl(url)
159
- return if (host != null && supportedDomains.contains(host)) {
188
+ return if (!isGifUrl(url) && host != null && supportedDomains.contains(host)) {
160
189
  val widthPx = with(density) { maxWidth.roundToPx() }
161
190
  val pixelRatio = density.density
162
191
  val pixelFitForWidth = widthPx * pixelRatio
@@ -167,6 +196,20 @@ private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp,
167
196
  }
168
197
  }
169
198
 
199
+ @Composable
200
+ private fun ImageError() {
201
+ val theme = AppTheme.current
202
+ Box(
203
+ modifier = Modifier.fillMaxSize(),
204
+ contentAlignment = Alignment.Center
205
+ ) {
206
+ Icon(
207
+ source = "media_fail",
208
+ color = theme.colors.text.disable,
209
+ )
210
+ }
211
+ }
212
+
170
213
  @Composable
171
214
  fun Image(
172
215
  source: Painter,
@@ -185,4 +228,4 @@ fun Image(
185
228
  colorFilter = colorFilter,
186
229
  alpha = alpha,
187
230
  )
188
- }
231
+ }
@@ -3,11 +3,7 @@ package vn.momo.kits.components
3
3
  import androidx.compose.foundation.background
4
4
  import androidx.compose.foundation.border
5
5
  import androidx.compose.foundation.clickable
6
- import androidx.compose.foundation.layout.Column
7
- import androidx.compose.foundation.layout.Row
8
- import androidx.compose.foundation.layout.height
9
- import androidx.compose.foundation.layout.padding
10
- import androidx.compose.foundation.layout.width
6
+ import androidx.compose.foundation.layout.*
11
7
  import androidx.compose.foundation.shape.RoundedCornerShape
12
8
  import androidx.compose.runtime.Composable
13
9
  import androidx.compose.ui.Modifier
@@ -1,29 +1,17 @@
1
1
  package vn.momo.kits.components
2
2
 
3
+ import vn.momo.kits.modifier.InternalApi
4
+
3
5
  import androidx.compose.foundation.background
4
6
  import androidx.compose.foundation.border
5
7
  import androidx.compose.foundation.clickable
6
8
  import androidx.compose.foundation.interaction.MutableInteractionSource
7
- import androidx.compose.foundation.layout.Box
8
- import androidx.compose.foundation.layout.Column
9
- import androidx.compose.foundation.layout.Row
10
- import androidx.compose.foundation.layout.Spacer
11
- import androidx.compose.foundation.layout.fillMaxWidth
12
- import androidx.compose.foundation.layout.height
13
- import androidx.compose.foundation.layout.offset
14
- import androidx.compose.foundation.layout.padding
15
- import androidx.compose.foundation.layout.size
16
- import androidx.compose.foundation.layout.wrapContentSize
9
+ import androidx.compose.foundation.layout.*
17
10
  import androidx.compose.foundation.shape.RoundedCornerShape
18
11
  import androidx.compose.foundation.text.BasicTextField
19
12
  import androidx.compose.foundation.text.KeyboardOptions
20
13
  import androidx.compose.material3.CircularProgressIndicator
21
- import androidx.compose.runtime.Composable
22
- import androidx.compose.runtime.MutableState
23
- import androidx.compose.runtime.getValue
24
- import androidx.compose.runtime.mutableStateOf
25
- import androidx.compose.runtime.remember
26
- import androidx.compose.runtime.setValue
14
+ import androidx.compose.runtime.*
27
15
  import androidx.compose.ui.Alignment
28
16
  import androidx.compose.ui.Modifier
29
17
  import androidx.compose.ui.focus.onFocusChanged
@@ -44,13 +32,7 @@ import androidx.compose.ui.unit.dp
44
32
  import androidx.compose.ui.unit.sp
45
33
  import androidx.compose.ui.zIndex
46
34
  import vn.momo.kits.application.IsShowBaseLineDebug
47
- import vn.momo.kits.const.AppTheme
48
- import vn.momo.kits.const.Colors
49
- import vn.momo.kits.const.Radius
50
- import vn.momo.kits.const.Spacing
51
- import vn.momo.kits.const.Typography
52
- import vn.momo.kits.const.getFont
53
- import vn.momo.kits.const.scaleSize
35
+ import vn.momo.kits.const.*
54
36
  import vn.momo.kits.modifier.conditional
55
37
  import vn.momo.kits.modifier.setAutomationId
56
38
  import vn.momo.uikits.resources.Res
@@ -88,7 +70,6 @@ enum class InputFontWeight(val value: FontWeight) {
88
70
  )
89
71
  }
90
72
 
91
- // Consolidated input state for better performance
92
73
  data class InputState(
93
74
  val isFocused: Boolean = false,
94
75
  val passHidden: Boolean = false,
@@ -128,6 +109,7 @@ private class PasswordVisualTransformation(
128
109
  }
129
110
 
130
111
  @Composable
112
+ @InternalApi
131
113
  fun getBorderColor(isFocused: Boolean, error: String, disabled: Boolean): Color {
132
114
  val theme = AppTheme.current
133
115
  return remember(isFocused, error, disabled, theme) {
@@ -141,6 +123,7 @@ fun getBorderColor(isFocused: Boolean, error: String, disabled: Boolean): Color
141
123
  }
142
124
 
143
125
  @Composable
126
+ @InternalApi
144
127
  fun RenderRightIcon(loading: Boolean, icon: String, color: Color, onClick: () -> Unit, modifier: Modifier = Modifier) {
145
128
  if (loading) {
146
129
  Box {
@@ -167,6 +150,7 @@ fun RenderRightIcon(loading: Boolean, icon: String, color: Color, onClick: () ->
167
150
  }
168
151
 
169
152
  @Composable
153
+ @InternalApi
170
154
  fun ErrorView(errorMessage: String, errorSpacing: Boolean, hintText: String) {
171
155
  val theme = AppTheme.current
172
156
  val errorColor = remember(theme) { theme.colors.error.primary }
@@ -326,41 +310,14 @@ fun Input(
326
310
  },
327
311
  decorationBox = { innerTextField ->
328
312
  // Floating label
329
- if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
330
- Box(
331
- modifier = Modifier
332
- .wrapContentSize()
333
- .offset(y = (-size.values.height / 2), x = Spacing.S)
334
- .background(theme.colors.background.surface)
335
- .zIndex(10f),
336
- ) {
337
- Row(
338
- modifier = Modifier.padding(horizontal = Spacing.S),
339
- verticalAlignment = Alignment.CenterVertically
340
- ) {
341
- Text(
342
- floatingValue,
343
- style = Typography.labelSMedium,
344
- color = floatingTitleColor
345
- )
346
- if (required) {
347
- Text(
348
- "*",
349
- style = Typography.labelSMedium,
350
- color = theme.colors.error.primary,
351
- )
352
- }
353
- if (floatingIcon.isNotEmpty()) {
354
- Icon(
355
- source = floatingIcon,
356
- modifier = Modifier.padding(start = Spacing.XS),
357
- size = 16.dp,
358
- color = floatingIconTintColor
359
- )
360
- }
361
- }
362
- }
363
- }
313
+ FloatingLabel(
314
+ floatingValue = floatingValue,
315
+ floatingIcon = floatingIcon,
316
+ titleColor = floatingTitleColor,
317
+ iconColor = floatingIconTintColor,
318
+ offsetY = -size.values.height / 2,
319
+ required = required,
320
+ )
364
321
 
365
322
  // Input container
366
323
  Box(
@@ -450,3 +407,71 @@ fun Input(
450
407
  ErrorView(error, errorSpacing, hintText)
451
408
  }
452
409
  }
410
+
411
+ internal data class InputColors(
412
+ val text: Color,
413
+ val placeholder: Color,
414
+ val iconTint: Color,
415
+ val floatingTitle: Color,
416
+ val floatingIcon: Color,
417
+ )
418
+
419
+ @Composable
420
+ internal fun getInputColors(
421
+ disabled: Boolean,
422
+ iconColor: Color,
423
+ floatingValueColor: Color,
424
+ floatingIconColor: Color,
425
+ ): InputColors {
426
+ val theme = AppTheme.current
427
+ val disabledColor = theme.colors.text.disable
428
+ return InputColors(
429
+ text = if (disabled) disabledColor else theme.colors.text.default,
430
+ placeholder = if (disabled) disabledColor else theme.colors.text.hint,
431
+ iconTint = if (disabled) disabledColor else iconColor,
432
+ floatingTitle = if (disabled) disabledColor else floatingValueColor,
433
+ floatingIcon = if (disabled) disabledColor else floatingIconColor,
434
+ )
435
+ }
436
+
437
+ @Composable
438
+ internal fun FloatingLabel(
439
+ floatingValue: String,
440
+ floatingIcon: String,
441
+ titleColor: Color,
442
+ iconColor: Color,
443
+ offsetY: Dp,
444
+ offsetX: Dp = Spacing.S,
445
+ required: Boolean = false,
446
+ ) {
447
+ if (floatingValue.isEmpty() && floatingIcon.isEmpty()) return
448
+ Box(
449
+ modifier = Modifier
450
+ .wrapContentSize()
451
+ .offset(y = offsetY, x = offsetX)
452
+ .background(AppTheme.current.colors.background.surface)
453
+ .zIndex(10f),
454
+ ) {
455
+ Row(
456
+ modifier = Modifier.padding(horizontal = Spacing.S),
457
+ verticalAlignment = Alignment.CenterVertically,
458
+ ) {
459
+ Text(floatingValue, style = Typography.labelSMedium, color = titleColor)
460
+ if (required) {
461
+ Text(
462
+ "*",
463
+ style = Typography.labelSMedium,
464
+ color = AppTheme.current.colors.error.primary,
465
+ )
466
+ }
467
+ if (floatingIcon.isNotEmpty()) {
468
+ Icon(
469
+ source = floatingIcon,
470
+ modifier = Modifier.padding(start = Spacing.XS),
471
+ size = 16.dp,
472
+ color = iconColor,
473
+ )
474
+ }
475
+ }
476
+ }
477
+ }
@@ -3,20 +3,9 @@ package vn.momo.kits.components
3
3
  import androidx.compose.foundation.background
4
4
  import androidx.compose.foundation.border
5
5
  import androidx.compose.foundation.clickable
6
- import androidx.compose.foundation.layout.Box
7
- import androidx.compose.foundation.layout.Column
8
- import androidx.compose.foundation.layout.Row
9
- import androidx.compose.foundation.layout.fillMaxWidth
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.wrapContentSize
6
+ import androidx.compose.foundation.layout.*
14
7
  import androidx.compose.foundation.shape.RoundedCornerShape
15
- import androidx.compose.runtime.Composable
16
- import androidx.compose.runtime.MutableState
17
- import androidx.compose.runtime.getValue
18
- import androidx.compose.runtime.mutableStateOf
19
- import androidx.compose.runtime.remember
8
+ import androidx.compose.runtime.*
20
9
  import androidx.compose.ui.Alignment
21
10
  import androidx.compose.ui.Modifier
22
11
  import androidx.compose.ui.graphics.Color
@@ -27,12 +16,8 @@ import androidx.compose.ui.text.TextStyle
27
16
  import androidx.compose.ui.unit.dp
28
17
  import androidx.compose.ui.unit.sp
29
18
  import androidx.compose.ui.zIndex
30
- import vn.momo.kits.const.AppTheme
31
- import vn.momo.kits.const.Spacing
32
19
  import vn.momo.kits.application.IsShowBaseLineDebug
33
- import vn.momo.kits.const.Colors
34
- import vn.momo.kits.const.Typography
35
- import vn.momo.kits.const.scaleSize
20
+ import vn.momo.kits.const.*
36
21
  import vn.momo.kits.modifier.conditional
37
22
 
38
23
  @Composable
@@ -59,24 +44,8 @@ fun InputDropDown(
59
44
  ) {
60
45
  val isFocused by remember { mutableStateOf(false) }
61
46
 
62
- val disabledColor = AppTheme.current.colors.text.disable
63
- var textColor = AppTheme.current.colors.text.default
64
- var placeholderColor = AppTheme.current.colors.text.hint
65
- var iconTintColor = iconColor
66
- val floatingTitleColor = when {
67
- disabled -> AppTheme.current.colors.text.disable
68
- else -> floatingValueColor
69
- }
70
- val floatingIconTintColor = when {
71
- disabled -> AppTheme.current.colors.text.disable
72
- else -> floatingIconColor
73
- }
74
-
75
- if (disabled) {
76
- textColor = disabledColor
77
- placeholderColor = disabledColor
78
- iconTintColor = disabledColor
79
- }
47
+ val (textColor, placeholderColor, iconTintColor, floatingTitleColor, floatingIconTintColor) =
48
+ getInputColors(disabled, iconColor, floatingValueColor, floatingIconColor)
80
49
 
81
50
  val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
82
51
 
@@ -92,41 +61,14 @@ fun InputDropDown(
92
61
  contentDescription = floatingValue; testTag = testId
93
62
  }) {
94
63
  Box {
95
- if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
96
- Box(
97
- modifier = Modifier.wrapContentSize()
98
- .offset(y = -Spacing.S, x = Spacing.S)
99
- .background(AppTheme.current.colors.background.surface)
100
- .zIndex(10f),
101
- ) {
102
- Row(
103
- modifier = Modifier
104
- .padding(horizontal = Spacing.S),
105
- verticalAlignment = Alignment.CenterVertically
106
- ) {
107
- Text(
108
- floatingValue,
109
- style = Typography.labelSMedium,
110
- color = floatingTitleColor
111
- )
112
- if (required) {
113
- Text(
114
- "*",
115
- style = Typography.labelSMedium,
116
- color = AppTheme.current.colors.error.primary,
117
- )
118
- }
119
- if (floatingIcon.isNotEmpty()) {
120
- Icon(
121
- source = floatingIcon,
122
- modifier = Modifier.padding(start = Spacing.XS),
123
- size = 16.dp,
124
- color = floatingIconTintColor
125
- )
126
- }
127
- }
128
- }
129
- }
64
+ FloatingLabel(
65
+ floatingValue = floatingValue,
66
+ floatingIcon = floatingIcon,
67
+ titleColor = floatingTitleColor,
68
+ iconColor = floatingIconTintColor,
69
+ offsetY = -Spacing.S,
70
+ required = required,
71
+ )
130
72
  Box(
131
73
  modifier = Modifier.fillMaxWidth()
132
74
  .height(if (size == InputSize.SMALL) 48.dp else 56.dp)
@@ -102,24 +102,8 @@ fun InputMoney(
102
102
  ) {
103
103
  var isFocused by remember { mutableStateOf(false) }
104
104
  var isBlurred = false
105
- val disabledColor = AppTheme.current.colors.text.disable
106
- var textColor = AppTheme.current.colors.text.default
107
- var placeholderColor = AppTheme.current.colors.text.hint
108
- var iconTintColor = iconColor
109
- val floatingTitleColor = when {
110
- disabled -> AppTheme.current.colors.text.disable
111
- else -> floatingValueColor
112
- }
113
- val floatingIconTintColor = when {
114
- disabled -> AppTheme.current.colors.text.disable
115
- else -> floatingIconColor
116
- }
117
-
118
- if (disabled) {
119
- textColor = disabledColor
120
- placeholderColor = disabledColor
121
- iconTintColor = disabledColor
122
- }
105
+ val (textColor, placeholderColor, iconTintColor, floatingTitleColor, floatingIconTintColor) =
106
+ getInputColors(disabled, iconColor, floatingValueColor, floatingIconColor)
123
107
 
124
108
  val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
125
109
 
@@ -156,39 +140,14 @@ fun InputMoney(
156
140
  },
157
141
  decorationBox = { innerTextField ->
158
142
  // Floating Icon
159
- if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
160
- Box(
161
- modifier = Modifier.wrapContentSize()
162
- .offset(y = (-size.values.height / 2), x = (Spacing.S))
163
- .background(AppTheme.current.colors.background.surface)
164
- .zIndex(10f),
165
- ) {
166
- Row(
167
- modifier = Modifier.padding(horizontal = Spacing.S),
168
- ) {
169
- Text(
170
- floatingValue,
171
- style = Typography.labelSMedium,
172
- color = floatingTitleColor
173
- )
174
- if (required) {
175
- Text(
176
- "*",
177
- style = Typography.labelSMedium,
178
- color = AppTheme.current.colors.error.primary,
179
- )
180
- }
181
- if (floatingIcon.isNotEmpty()) {
182
- Icon(
183
- source = floatingIcon,
184
- modifier = Modifier.padding(start = Spacing.XS),
185
- size = 16.dp,
186
- color = floatingIconTintColor
187
- )
188
- }
189
- }
190
- }
191
- }
143
+ FloatingLabel(
144
+ floatingValue = floatingValue,
145
+ floatingIcon = floatingIcon,
146
+ titleColor = floatingTitleColor,
147
+ iconColor = floatingIconTintColor,
148
+ offsetY = -size.values.height / 2,
149
+ required = required,
150
+ )
192
151
  //input box wrapper
193
152
  Box(
194
153
  modifier = Modifier.fillMaxWidth()
@@ -1,5 +1,7 @@
1
1
  package vn.momo.kits.components
2
2
 
3
+ import vn.momo.kits.modifier.InternalApi
4
+
3
5
  import androidx.compose.animation.core.LinearEasing
4
6
  import androidx.compose.animation.core.RepeatMode
5
7
  import androidx.compose.animation.core.animateFloat
@@ -48,6 +50,7 @@ import vn.momo.kits.const.scaleSize
48
50
  import vn.momo.kits.modifier.conditional
49
51
 
50
52
  @Composable
53
+ @InternalApi
51
54
  fun OTPCaret() {
52
55
  val duration = 500
53
56
  val backgroundColor = AppTheme.current.colors.primary
@@ -66,7 +69,9 @@ fun OTPCaret() {
66
69
  )
67
70
  )
68
71
 
69
- Row(verticalAlignment = Alignment.CenterVertically) {
72
+ Row(
73
+ verticalAlignment = Alignment.CenterVertically
74
+ ) {
70
75
  Box(
71
76
  modifier = Modifier
72
77
  .size(1.dp, scaleSize(12f).dp)
@@ -4,23 +4,11 @@ import androidx.compose.foundation.background
4
4
  import androidx.compose.foundation.border
5
5
  import androidx.compose.foundation.clickable
6
6
  import androidx.compose.foundation.interaction.MutableInteractionSource
7
- import androidx.compose.foundation.layout.Box
8
- import androidx.compose.foundation.layout.Column
9
- import androidx.compose.foundation.layout.Row
10
- import androidx.compose.foundation.layout.fillMaxWidth
11
- import androidx.compose.foundation.layout.height
12
- import androidx.compose.foundation.layout.padding
13
- import androidx.compose.foundation.layout.size
14
- import androidx.compose.foundation.layout.width
7
+ import androidx.compose.foundation.layout.*
15
8
  import androidx.compose.foundation.shape.RoundedCornerShape
16
9
  import androidx.compose.foundation.text.BasicTextField
17
10
  import androidx.compose.foundation.text.KeyboardOptions
18
- import androidx.compose.runtime.Composable
19
- import androidx.compose.runtime.MutableState
20
- import androidx.compose.runtime.getValue
21
- import androidx.compose.runtime.mutableStateOf
22
- import androidx.compose.runtime.remember
23
- import androidx.compose.runtime.setValue
11
+ import androidx.compose.runtime.*
24
12
  import androidx.compose.ui.Alignment
25
13
  import androidx.compose.ui.Modifier
26
14
  import androidx.compose.ui.focus.onFocusChanged
@@ -32,12 +20,7 @@ import androidx.compose.ui.text.input.KeyboardType
32
20
  import androidx.compose.ui.unit.Dp
33
21
  import androidx.compose.ui.unit.dp
34
22
  import vn.momo.kits.application.IsShowBaseLineDebug
35
- import vn.momo.kits.const.AppTheme
36
- import vn.momo.kits.const.Colors
37
- import vn.momo.kits.const.Radius
38
- import vn.momo.kits.const.Spacing
39
- import vn.momo.kits.const.Typography
40
- import vn.momo.kits.const.scaleSize
23
+ import vn.momo.kits.const.*
41
24
  import vn.momo.kits.modifier.conditional
42
25
  import vn.momo.kits.modifier.setAutomationId
43
26
 
@@ -71,7 +54,7 @@ enum class InputPhoneNumberSize(val values: InputPhoneNumberSizeDetail) {
71
54
  }
72
55
 
73
56
  @Composable
74
- fun getBorderColor(isFocused: Boolean, error: String): Color {
57
+ private fun getBorderColor(isFocused: Boolean, error: String): Color {
75
58
  val theme = AppTheme.current
76
59
  return remember(isFocused, error, theme) {
77
60
  when {
@@ -46,7 +46,7 @@ import vn.momo.kits.modifier.conditional
46
46
  import vn.momo.kits.utils.ifTrue
47
47
 
48
48
  @Composable
49
- fun RenderRightIconSearch(
49
+ internal fun RenderRightIconSearch(
50
50
  loading: Boolean,
51
51
  icon: String,
52
52
  color: Color,