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