@momo-kits/native-kits 0.160.6 → 0.160.7-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/build.gradle.kts +11 -0
  2. package/compose/build.gradle.kts +180 -0
  3. package/compose/build.gradle.kts.backup +180 -0
  4. package/compose/compose.podspec +47 -0
  5. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +117 -0
  6. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  7. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  8. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  9. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  10. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  11. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +57 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +109 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +201 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +222 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +48 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +305 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +720 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +121 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +403 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +85 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +340 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +198 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +123 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +94 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +136 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +224 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +543 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +76 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +148 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +188 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +116 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +452 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +172 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +255 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +233 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +259 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +241 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +364 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +92 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +352 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +103 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +338 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +70 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +17 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +96 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +348 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +256 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +494 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +131 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +215 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +96 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +531 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +92 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +130 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +214 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +590 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +177 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +192 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +205 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +239 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +191 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +306 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +188 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +285 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +2 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +35 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +2 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +57 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +68 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +14 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +50 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +253 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +133 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +99 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +141 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +333 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +552 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +161 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +243 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +187 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +279 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +80 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +306 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +32 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +370 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +131 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +167 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +58 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +62 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +105 -0
  123. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +180 -0
  124. package/gradle/libs.versions.toml +58 -0
  125. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  126. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  127. package/gradle.properties +26 -0
  128. package/gradlew +252 -0
  129. package/gradlew.bat +94 -0
  130. package/package.json +1 -1
  131. package/settings.gradle.kts +52 -0
@@ -0,0 +1,255 @@
1
+ package vn.momo.kits.components
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.border
5
+ import androidx.compose.foundation.clickable
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.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.width
16
+ import androidx.compose.foundation.layout.wrapContentSize
17
+ import androidx.compose.foundation.shape.RoundedCornerShape
18
+ import androidx.compose.foundation.text.BasicTextField
19
+ import androidx.compose.foundation.text.KeyboardOptions
20
+ import androidx.compose.runtime.Composable
21
+ import androidx.compose.runtime.MutableState
22
+ import androidx.compose.runtime.getValue
23
+ import androidx.compose.runtime.mutableStateOf
24
+ import androidx.compose.runtime.remember
25
+ import androidx.compose.runtime.setValue
26
+ import androidx.compose.ui.Alignment
27
+ import androidx.compose.ui.Modifier
28
+ import androidx.compose.ui.focus.onFocusChanged
29
+ import androidx.compose.ui.graphics.Color
30
+ import androidx.compose.ui.semantics.contentDescription
31
+ import androidx.compose.ui.semantics.semantics
32
+ import androidx.compose.ui.semantics.testTag
33
+ import androidx.compose.ui.text.AnnotatedString
34
+ import androidx.compose.ui.text.TextStyle
35
+ import androidx.compose.ui.text.input.KeyboardType
36
+ import androidx.compose.ui.text.input.OffsetMapping
37
+ import androidx.compose.ui.text.input.TransformedText
38
+ import androidx.compose.ui.text.input.VisualTransformation
39
+ import androidx.compose.ui.unit.dp
40
+ import androidx.compose.ui.unit.sp
41
+ import androidx.compose.ui.zIndex
42
+ import vn.momo.kits.const.AppTheme
43
+ import vn.momo.kits.const.Spacing
44
+ import vn.momo.kits.application.IsShowBaseLineDebug
45
+ import vn.momo.kits.const.Colors
46
+ import vn.momo.kits.const.Typography
47
+ import vn.momo.kits.modifier.conditional
48
+ import vn.momo.kits.utils.formatNumberToMoney
49
+
50
+ class CustomConverter : VisualTransformation {
51
+ override fun filter(text: AnnotatedString): TransformedText {
52
+ if (text.text.isEmpty()) {
53
+ return TransformedText(
54
+ AnnotatedString("0"),
55
+ object : OffsetMapping {
56
+ override fun originalToTransformed(offset: Int): Int = 0
57
+ override fun transformedToOriginal(offset: Int): Int = 0
58
+ }
59
+ )
60
+ }
61
+
62
+ if (text.text == "0") {
63
+ return TransformedText(AnnotatedString("0"), OffsetMapping.Identity)
64
+ }
65
+
66
+ val formattedText = formatNumberToMoney(text.text.toLong())
67
+
68
+ return TransformedText(
69
+ AnnotatedString(formattedText),
70
+ object : OffsetMapping {
71
+ override fun originalToTransformed(offset: Int): Int = formattedText.length
72
+ override fun transformedToOriginal(offset: Int): Int = text.length
73
+ }
74
+ )
75
+ }
76
+ }
77
+
78
+ @Composable
79
+ fun InputMoney(
80
+ text: MutableState<String> = remember { mutableStateOf("0") },
81
+ floatingValue: String = "",
82
+ floatingValueColor: Color = AppTheme.current.colors.text.hint,
83
+ floatingIcon: String = "",
84
+ floatingIconColor: Color = AppTheme.current.colors.text.default,
85
+ placeholder: String = "0đ",
86
+ size: InputSize = InputSize.SMALL,
87
+ onChangeText: (String) -> Unit = {},
88
+ error: String = "",
89
+ errorSpacing: Boolean = false,
90
+ disabled: Boolean = false,
91
+ icon: String = "",
92
+ iconColor: Color = AppTheme.current.colors.text.default,
93
+ onPressIcon: () -> Unit = {},
94
+ leadingIcon: String = "",
95
+ leadingIconColor: Color = AppTheme.current.colors.text.hint,
96
+ onFocus: () -> Unit = {},
97
+ onBlur: () -> Unit = {},
98
+ loading: Boolean = false,
99
+ required: Boolean = false,
100
+ fontWeight: InputFontWeight = InputFontWeight.BOLD,
101
+ keyboardType: KeyboardType = KeyboardType.Number,
102
+ ) {
103
+ var isFocused by remember { mutableStateOf(false) }
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
+ }
123
+
124
+ val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
125
+
126
+ Column(modifier = Modifier
127
+ .conditional(IsShowBaseLineDebug) {
128
+ border(1.dp, Colors.blue_03)
129
+ }
130
+ .semantics {
131
+ contentDescription = floatingValue; testTag = testId
132
+ }) {
133
+ BasicTextField(
134
+ enabled = !disabled,
135
+ singleLine = true,
136
+ value = text.value,
137
+ textStyle = TextStyle(
138
+ color = textColor,
139
+ fontSize = 20.sp,
140
+ lineHeight = 24.sp,
141
+ fontWeight = fontWeight.value
142
+ ),
143
+ visualTransformation = CustomConverter(),
144
+ keyboardOptions = KeyboardOptions.Default.copy(keyboardType = keyboardType),
145
+ modifier = Modifier.height(size.values.height).onFocusChanged {
146
+ isFocused = it.isFocused
147
+ if (it.isFocused) {
148
+ onFocus()
149
+ }
150
+ if (!it.isFocused && isBlurred) onBlur()
151
+ if (it.isFocused && !isBlurred) isBlurred = true
152
+ },
153
+ onValueChange = {
154
+ val numericValue = it.filter { char -> char.isDigit() }
155
+ onChangeText(numericValue)
156
+ },
157
+ decorationBox = { innerTextField ->
158
+ // 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
+ }
192
+ //input box wrapper
193
+ Box(
194
+ modifier = Modifier.fillMaxWidth()
195
+ .border(
196
+ 1.dp,
197
+ getBorderColor(isFocused, error, disabled),
198
+ RoundedCornerShape(size.values.borderRadius)
199
+ ),
200
+ contentAlignment = Alignment.CenterStart
201
+ ) {
202
+ Row(
203
+ modifier = Modifier.padding(horizontal = Spacing.M),
204
+ verticalAlignment = Alignment.CenterVertically
205
+ ) {
206
+ //leading icon
207
+ if (leadingIcon.isNotEmpty()) {
208
+ Icon(
209
+ source = leadingIcon,
210
+ modifier = Modifier.padding(end = Spacing.XS),
211
+ size = if (size.name == InputSize.SMALL.name) 24.dp else 32.dp,
212
+ color = leadingIconColor
213
+ )
214
+ }
215
+ Box(Modifier.weight(9f).padding(start = 0.dp)) {
216
+ if (text.value.isEmpty()) {
217
+ Text(
218
+ text = placeholder,
219
+ style = TextStyle(
220
+ fontSize = 20.sp,
221
+ lineHeight = 24.sp,
222
+ fontWeight = fontWeight.value
223
+ ),
224
+ color = placeholderColor
225
+ )
226
+ } else {
227
+ innerTextField()
228
+ }
229
+ }
230
+ if (isFocused && text.value.isNotEmpty()) {
231
+ Row {
232
+ Spacer(Modifier.width(Spacing.XS))
233
+ Icon(
234
+ source = "24_navigation_close_circle_full",
235
+ size = 16.dp,
236
+ color = AppTheme.current.colors.text.hint,
237
+ modifier = Modifier.clickable(
238
+ onClick = {
239
+ text.value = ""
240
+ onChangeText.invoke("")
241
+ },
242
+ interactionSource = remember { MutableInteractionSource() },
243
+ indication = null
244
+ )
245
+ )
246
+ }
247
+ }
248
+ RenderRightIcon(loading, icon, iconTintColor, onPressIcon)
249
+ }
250
+ }
251
+ },
252
+ )
253
+ ErrorView(error, errorSpacing, "")
254
+ }
255
+ }
@@ -0,0 +1,235 @@
1
+ package vn.momo.kits.components
2
+
3
+ import androidx.compose.animation.core.LinearEasing
4
+ import androidx.compose.animation.core.RepeatMode
5
+ import androidx.compose.animation.core.animateFloat
6
+ import androidx.compose.animation.core.infiniteRepeatable
7
+ import androidx.compose.animation.core.rememberInfiniteTransition
8
+ import androidx.compose.animation.core.tween
9
+ import androidx.compose.foundation.background
10
+ import androidx.compose.foundation.border
11
+ import androidx.compose.ui.draw.alpha
12
+ import androidx.compose.foundation.clickable
13
+ import androidx.compose.foundation.layout.Arrangement
14
+ import androidx.compose.foundation.layout.Box
15
+ import androidx.compose.foundation.layout.Column
16
+ import androidx.compose.foundation.layout.Row
17
+ import androidx.compose.foundation.layout.Spacer
18
+ import androidx.compose.foundation.layout.fillMaxWidth
19
+ import androidx.compose.foundation.layout.height
20
+ import androidx.compose.foundation.layout.offset
21
+ import androidx.compose.foundation.layout.padding
22
+ import androidx.compose.foundation.layout.size
23
+ import androidx.compose.foundation.layout.width
24
+ import androidx.compose.foundation.layout.wrapContentSize
25
+ import androidx.compose.foundation.shape.RoundedCornerShape
26
+ import androidx.compose.foundation.text.BasicTextField
27
+ import androidx.compose.foundation.text.KeyboardOptions
28
+ import androidx.compose.runtime.Composable
29
+ import androidx.compose.runtime.getValue
30
+ import androidx.compose.runtime.mutableStateOf
31
+ import androidx.compose.runtime.remember
32
+ import androidx.compose.runtime.setValue
33
+ import androidx.compose.ui.Alignment
34
+ import androidx.compose.ui.Modifier
35
+ import androidx.compose.ui.focus.onFocusChanged
36
+ import androidx.compose.ui.text.TextStyle
37
+ import androidx.compose.ui.text.input.KeyboardType
38
+ import androidx.compose.ui.unit.dp
39
+ import androidx.compose.ui.unit.sp
40
+ import androidx.compose.ui.zIndex
41
+ import vn.momo.kits.const.AppTheme
42
+ import vn.momo.kits.const.Radius
43
+ import vn.momo.kits.const.Spacing
44
+ import vn.momo.kits.application.IsShowBaseLineDebug
45
+ import vn.momo.kits.const.Colors
46
+ import vn.momo.kits.const.Typography
47
+ import vn.momo.kits.const.scaleSize
48
+ import vn.momo.kits.modifier.conditional
49
+
50
+ @Composable
51
+ fun OTPCaret() {
52
+ val duration = 500
53
+ val backgroundColor = AppTheme.current.colors.primary
54
+
55
+ val infiniteTransition = rememberInfiniteTransition()
56
+ val alpha by infiniteTransition.animateFloat(
57
+ initialValue = 1f,
58
+ targetValue = 0f,
59
+ animationSpec = infiniteRepeatable(
60
+ animation = tween(
61
+ durationMillis = duration,
62
+ delayMillis = duration,
63
+ easing = LinearEasing
64
+ ),
65
+ repeatMode = RepeatMode.Reverse
66
+ )
67
+ )
68
+
69
+ Row(verticalAlignment = Alignment.CenterVertically) {
70
+ Box(
71
+ modifier = Modifier
72
+ .size(1.dp, scaleSize(12f).dp)
73
+ .background(backgroundColor.copy(alpha = alpha))
74
+ )
75
+ Text(
76
+ text = "-",
77
+ color = AppTheme.current.colors.text.hint,
78
+ style = Typography.descriptionDefaultRegular
79
+ )
80
+ }
81
+ }
82
+
83
+ @Composable
84
+ fun InputOTP(
85
+ value: String = "",
86
+ length: Int? = null,
87
+ errorMessage: String = "",
88
+ errorSpacing: Boolean = false,
89
+ floatingValue: String = "Label",
90
+ placeholder: String = "",
91
+ onChangeText: (String) -> Unit,
92
+ onFocus: () -> Unit = {},
93
+ onBlur: () -> Unit = {},
94
+ dataType: String = "number",
95
+ modifier: Modifier = Modifier
96
+ ) {
97
+ val maxLength = length ?: 10
98
+ var isFocused by remember { mutableStateOf(false) }
99
+ var isBlurred = false
100
+
101
+ val handleChangeText: (String) -> Unit = { text ->
102
+ if (text.length <= maxLength &&
103
+ (dataType != "number" || !text.any { !it.isDigit() }) &&
104
+ (text.length < value.length || value.length < text.length)
105
+ ) {
106
+ onChangeText(text)
107
+ }
108
+ }
109
+
110
+ fun onClearText(){
111
+ handleChangeText("")
112
+ }
113
+
114
+ val fontSize = scaleSize(20.sp)
115
+
116
+ Column(modifier = modifier.conditional(IsShowBaseLineDebug) {
117
+ border(1.dp, Colors.blue_03)
118
+ }) {
119
+ BasicTextField(
120
+ value = value,
121
+ textStyle = TextStyle(fontSize = fontSize),
122
+ onValueChange = handleChangeText,
123
+ singleLine = true,
124
+ keyboardOptions = KeyboardOptions.Default.copy(keyboardType = if (dataType == "number") KeyboardType.Number else KeyboardType.Ascii),
125
+ modifier = modifier.height(56.dp).onFocusChanged {
126
+ isFocused = it.isFocused
127
+ if (it.isFocused) {
128
+ onFocus()
129
+ }
130
+ if (!it.isFocused && isBlurred) onBlur()
131
+ if (it.isFocused && !isBlurred) isBlurred = true
132
+ },
133
+ decorationBox = { innerTextField ->
134
+ Box {
135
+ Box(
136
+ modifier = Modifier.fillMaxWidth().height(56.dp).alpha(0f)
137
+ ) { innerTextField() }
138
+ if (floatingValue.isNotEmpty()) {
139
+ Box(
140
+ modifier = Modifier.wrapContentSize()
141
+ .offset(y = ((-56).dp / 2))
142
+ .align(Alignment.Center)
143
+ .background(AppTheme.current.colors.background.surface)
144
+ .zIndex(10f),
145
+ ) {
146
+ Row(
147
+ modifier = Modifier
148
+ .padding(horizontal = Spacing.S),
149
+ verticalAlignment = Alignment.Bottom
150
+ ) {
151
+ Text(
152
+ floatingValue,
153
+ style = Typography.labelSMedium,
154
+ color = AppTheme.current.colors.text.hint
155
+ )
156
+ }
157
+ }
158
+ }
159
+ Box(
160
+ modifier = Modifier
161
+ .fillMaxWidth()
162
+ .height(56.dp)
163
+ .border(
164
+ 1.dp,
165
+ getBorderColor(isFocused, errorMessage, false),
166
+ RoundedCornerShape(
167
+ Radius.S
168
+ )
169
+ ), contentAlignment = Alignment.Center
170
+ ) {
171
+ Row(
172
+ modifier = Modifier.padding(vertical = 8.dp),
173
+ horizontalArrangement = Arrangement.SpaceBetween,
174
+ verticalAlignment = Alignment.CenterVertically
175
+ ) {
176
+ if (length != null) {
177
+ for (i in 0 until length) {
178
+ if (isFocused && value.length == i) {
179
+ OTPCaret()
180
+ } else {
181
+ val textColor =
182
+ if (value.getOrNull(i) != null) AppTheme.current.colors.text.default else AppTheme.current.colors.text.hint
183
+ val typo =
184
+ if (value.getOrNull(i) != null) Typography.headerDefaultBold else Typography.descriptionDefaultRegular
185
+ Text(
186
+ text = value.getOrNull(i)?.toString() ?: "-",
187
+ color = textColor,
188
+ style = typo
189
+ )
190
+ }
191
+ if (i != length - 1) Spacer(Modifier.width(Spacing.L))
192
+ }
193
+ } else {
194
+ if (value.isEmpty() && !isFocused && placeholder.isNotEmpty()) {
195
+ return@BasicTextField Text(
196
+ text = placeholder,
197
+ color = AppTheme.current.colors.text.hint
198
+ )
199
+ } else {
200
+ for (i in value.indices) {
201
+ Text(
202
+ style = Typography.headerDefaultBold,
203
+ text = value[i].toString()
204
+ )
205
+ if (i != value.length - 1 || (isFocused && value.length != MAX_LENGTH)) {
206
+ Spacer(Modifier.width(Spacing.L))
207
+ }
208
+ }
209
+ if (isFocused && value.length != MAX_LENGTH) OTPCaret()
210
+ }
211
+ }
212
+ }
213
+ }
214
+ Box(
215
+ modifier = Modifier.align(Alignment.Center).zIndex(10f)
216
+ ) {
217
+ Row(
218
+ horizontalArrangement = Arrangement.End,
219
+ modifier = Modifier.fillMaxWidth()
220
+ ) {
221
+ Icon(
222
+ "24_navigation_close_circle_full",
223
+ size = 12.dp,
224
+ modifier = Modifier.padding(end = 12.dp).clickable {
225
+ onClearText()
226
+ }
227
+ )
228
+ }
229
+ }
230
+ }
231
+ }
232
+ )
233
+ ErrorView(errorMessage, errorSpacing, "")
234
+ }
235
+ }