@momo-kits/native-kits 0.114.2-beta.4 → 0.114.2-beta.6
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.
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +6 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +39 -20
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +22 -34
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +7 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +9 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/{dateTimePicker → datetimepicker}/DateTimePicker.kt +12 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/{dateTimePicker → datetimepicker}/DateTimePickerTypes.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/{dateTimePicker → datetimepicker}/DateTimePickerUtils.kt +34 -23
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/{dateTimePicker → datetimepicker}/WheelPicker.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +8 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +12 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +1 -1
- package/local.properties +2 -2
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/dateTimePicker/DateTimePickerExample.kt +0 -90
|
@@ -38,7 +38,7 @@ fun HeaderBackground(
|
|
|
38
38
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
39
39
|
|
|
40
40
|
val opacityAni by animateFloatAsState(
|
|
41
|
-
targetValue = (1 - (scrollState / HEADER_HEIGHT*1f)).coerceIn(0f, 1f),
|
|
41
|
+
targetValue = (1 - (scrollState / HEADER_HEIGHT * 1f)).coerceIn(0f, 1f),
|
|
42
42
|
)
|
|
43
43
|
|
|
44
44
|
val backgroundColor by animateColorAsState(
|
|
@@ -29,21 +29,27 @@ class Navigator {
|
|
|
29
29
|
fun push(content: @Composable () -> Unit) {
|
|
30
30
|
//implement
|
|
31
31
|
}
|
|
32
|
+
|
|
32
33
|
fun present(content: @Composable () -> Unit) {
|
|
33
34
|
//implement
|
|
34
35
|
}
|
|
36
|
+
|
|
35
37
|
fun reset(content: @Composable () -> Unit) {
|
|
36
38
|
//implement
|
|
37
39
|
}
|
|
40
|
+
|
|
38
41
|
fun pop() {
|
|
39
42
|
//implement
|
|
40
43
|
}
|
|
44
|
+
|
|
41
45
|
fun replace(content: @Composable () -> Unit) {
|
|
42
46
|
//implement
|
|
43
47
|
}
|
|
48
|
+
|
|
44
49
|
fun popToTop() {
|
|
45
50
|
//implement
|
|
46
51
|
}
|
|
52
|
+
|
|
47
53
|
fun showModal(
|
|
48
54
|
onClose: () -> Unit = {},
|
|
49
55
|
canBackgroundClose: Boolean = true,
|
|
@@ -87,7 +87,7 @@ fun Screen(
|
|
|
87
87
|
val bottomPadding = min(indicator, 21.dp)
|
|
88
88
|
|
|
89
89
|
val opacity by animateFloatAsState(
|
|
90
|
-
targetValue = ((scrollState.value / HEADER_HEIGHT*1f)).coerceIn(0f, 1f),
|
|
90
|
+
targetValue = ((scrollState.value / HEADER_HEIGHT * 1f)).coerceIn(0f, 1f),
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
val headerAnimated =
|
|
@@ -42,18 +42,21 @@ fun useHeaderSearchAnimation(
|
|
|
42
42
|
)
|
|
43
43
|
|
|
44
44
|
val animatedTranslateX by animateFloatAsState(
|
|
45
|
-
targetValue = (scrollState / HEADER_HEIGHT*1f).coerceIn(
|
|
45
|
+
targetValue = (scrollState / HEADER_HEIGHT * 1f).coerceIn(
|
|
46
|
+
0f,
|
|
47
|
+
1f
|
|
48
|
+
) * (leftPosition.value - 12) + 12,
|
|
46
49
|
)
|
|
47
50
|
|
|
48
51
|
val animatedWidth by animateFloatAsState(
|
|
49
|
-
targetValue = (scrollState / HEADER_HEIGHT*1f).coerceIn(
|
|
52
|
+
targetValue = (scrollState / HEADER_HEIGHT * 1f).coerceIn(
|
|
50
53
|
0f,
|
|
51
54
|
1f
|
|
52
55
|
) * ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth,
|
|
53
56
|
)
|
|
54
57
|
|
|
55
58
|
val animatedTranslateY by animateFloatAsState(
|
|
56
|
-
targetValue = (1 - (scrollState / HEADER_HEIGHT* 1f).coerceIn(0f, 1f)) * HEADER_HEIGHT
|
|
59
|
+
targetValue = (1 - (scrollState / HEADER_HEIGHT * 1f).coerceIn(0f, 1f)) * HEADER_HEIGHT
|
|
57
60
|
)
|
|
58
61
|
return HeaderAnimations(
|
|
59
62
|
opacity = opacityAni,
|
|
@@ -3,15 +3,12 @@ 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.interaction.MutableInteractionSource
|
|
7
6
|
import androidx.compose.foundation.layout.Box
|
|
8
7
|
import androidx.compose.foundation.layout.Row
|
|
9
8
|
import androidx.compose.foundation.layout.Spacer
|
|
10
9
|
import androidx.compose.foundation.layout.size
|
|
11
10
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
12
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
13
11
|
import androidx.compose.runtime.Composable
|
|
14
|
-
import androidx.compose.runtime.remember
|
|
15
12
|
import androidx.compose.ui.Alignment
|
|
16
13
|
import androidx.compose.ui.Modifier
|
|
17
14
|
import androidx.compose.ui.unit.dp
|
|
@@ -27,7 +27,7 @@ fun Icon(
|
|
|
27
27
|
} else {
|
|
28
28
|
Icons[source] ?: ""
|
|
29
29
|
}
|
|
30
|
-
Box(modifier = modifier.size(size).semantics {contentDescription = "img|$icon"}) {
|
|
30
|
+
Box(modifier = modifier.size(size).semantics { contentDescription = "img|$icon" }) {
|
|
31
31
|
AsyncImage(
|
|
32
32
|
modifier = Modifier.matchParentSize(),
|
|
33
33
|
model = icon,
|
|
@@ -3,13 +3,10 @@ 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.interaction.MutableInteractionSource
|
|
7
6
|
import androidx.compose.foundation.layout.Box
|
|
8
7
|
import androidx.compose.foundation.layout.size
|
|
9
8
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
10
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
11
9
|
import androidx.compose.runtime.Composable
|
|
12
|
-
import androidx.compose.runtime.remember
|
|
13
10
|
import androidx.compose.ui.Alignment
|
|
14
11
|
import androidx.compose.ui.Modifier
|
|
15
12
|
import androidx.compose.ui.draw.clip
|
|
@@ -47,7 +47,7 @@ fun Image(
|
|
|
47
47
|
)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
Box(modifier = modifier.semantics {contentDescription = "img|$source"}) {
|
|
50
|
+
Box(modifier = modifier.semantics { contentDescription = "img|$source" }) {
|
|
51
51
|
AsyncImage(
|
|
52
52
|
modifier = Modifier.matchParentSize(),
|
|
53
53
|
model = source,
|
|
@@ -67,6 +67,7 @@ fun Image(
|
|
|
67
67
|
color = AppTheme.current.colors.text.disable,
|
|
68
68
|
modifier = modifier
|
|
69
69
|
)
|
|
70
|
+
|
|
70
71
|
ImageState.Success -> {}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
@@ -20,7 +20,7 @@ import vn.momo.kits.const.Spacing
|
|
|
20
20
|
import vn.momo.kits.const.Typography
|
|
21
21
|
|
|
22
22
|
enum class InformationState {
|
|
23
|
-
DEFAULT
|
|
23
|
+
DEFAULT,
|
|
24
24
|
WARNING,
|
|
25
25
|
ERROR
|
|
26
26
|
}
|
|
@@ -31,12 +31,12 @@ fun Information(
|
|
|
31
31
|
description: String = "Description",
|
|
32
32
|
state: InformationState = InformationState.DEFAULT,
|
|
33
33
|
image: String? = null,
|
|
34
|
-
|
|
34
|
+
onPressAction: (() -> Unit)? = null,
|
|
35
35
|
showIcon: Boolean = true,
|
|
36
|
-
|
|
36
|
+
action: String? = null,
|
|
37
37
|
showIconClose: Boolean = true,
|
|
38
|
-
onPressClose: (()->Unit)? = null,
|
|
39
|
-
){
|
|
38
|
+
onPressClose: (() -> Unit)? = null,
|
|
39
|
+
) {
|
|
40
40
|
var borderColor = Colors.blue_07
|
|
41
41
|
var backgroundColor = Colors.blue_10
|
|
42
42
|
var color = Colors.blue_03
|
|
@@ -46,31 +46,40 @@ fun Information(
|
|
|
46
46
|
borderColor = Colors.yellow_06
|
|
47
47
|
backgroundColor = Colors.yellow_09
|
|
48
48
|
color = Colors.orange_03
|
|
49
|
-
iconSource = "24_notifications_alert_triangle"
|
|
49
|
+
iconSource = "24_notifications_alert_triangle"
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (state === InformationState.ERROR) {
|
|
53
53
|
borderColor = Colors.red_07
|
|
54
54
|
backgroundColor = Colors.red_10
|
|
55
55
|
color = Colors.red_03
|
|
56
|
-
iconSource = "24_notifications_alert_octagon"
|
|
56
|
+
iconSource = "24_notifications_alert_octagon"
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
Column(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.
|
|
59
|
+
Column(
|
|
60
|
+
modifier = Modifier.border(
|
|
61
|
+
width = 0.5.dp,
|
|
62
|
+
shape = RoundedCornerShape(Radius.S),
|
|
63
|
+
color = borderColor
|
|
64
|
+
).background(color = backgroundColor)
|
|
65
|
+
.padding(Spacing.M)
|
|
65
66
|
) {
|
|
66
67
|
Row {
|
|
67
68
|
if (image != null) {
|
|
68
|
-
Image(
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
Image(
|
|
70
|
+
source = image,
|
|
71
|
+
modifier = Modifier.padding(end = Spacing.S).width(40.dp).height(40.dp).clip(
|
|
72
|
+
RoundedCornerShape(Radius.S)
|
|
73
|
+
)
|
|
74
|
+
)
|
|
71
75
|
}
|
|
72
76
|
if (image == null && showIcon) {
|
|
73
|
-
Icon(
|
|
77
|
+
Icon(
|
|
78
|
+
source = iconSource,
|
|
79
|
+
size = 16.dp,
|
|
80
|
+
color = color,
|
|
81
|
+
modifier = Modifier.padding(end = Spacing.S)
|
|
82
|
+
)
|
|
74
83
|
}
|
|
75
84
|
Column(modifier = Modifier.weight(1f)) {
|
|
76
85
|
if (title != null) {
|
|
@@ -79,12 +88,22 @@ fun Information(
|
|
|
79
88
|
Text(description, style = Typography.descriptionDefaultRegular)
|
|
80
89
|
}
|
|
81
90
|
if (onPressClose != null && showIconClose) {
|
|
82
|
-
Icon(
|
|
91
|
+
Icon(
|
|
92
|
+
source = "navigation_close",
|
|
93
|
+
size = 16.dp,
|
|
94
|
+
modifier = Modifier.clickable(onClick = onPressClose)
|
|
95
|
+
)
|
|
83
96
|
}
|
|
84
97
|
}
|
|
85
|
-
if (
|
|
98
|
+
if (action != null && onPressAction != null) {
|
|
86
99
|
Row(modifier = Modifier.padding(top = Spacing.S)) {
|
|
87
|
-
Text(
|
|
100
|
+
Text(
|
|
101
|
+
action,
|
|
102
|
+
modifier = Modifier.weight(1f).clickable(onClick = onPressAction),
|
|
103
|
+
textAlign = TextAlign.End,
|
|
104
|
+
style = Typography.actionXsBold,
|
|
105
|
+
color = color
|
|
106
|
+
)
|
|
88
107
|
}
|
|
89
108
|
}
|
|
90
109
|
}
|
|
@@ -21,7 +21,6 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|
|
21
21
|
import androidx.compose.material3.CircularProgressIndicator
|
|
22
22
|
import androidx.compose.runtime.Composable
|
|
23
23
|
import androidx.compose.runtime.MutableState
|
|
24
|
-
import androidx.compose.runtime.SideEffect
|
|
25
24
|
import androidx.compose.runtime.getValue
|
|
26
25
|
import androidx.compose.runtime.mutableStateOf
|
|
27
26
|
import androidx.compose.runtime.remember
|
|
@@ -37,7 +36,6 @@ import androidx.compose.ui.text.TextStyle
|
|
|
37
36
|
import androidx.compose.ui.text.font.FontWeight
|
|
38
37
|
import androidx.compose.ui.text.input.KeyboardType
|
|
39
38
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
|
40
|
-
import androidx.compose.ui.text.input.TextFieldValue
|
|
41
39
|
import androidx.compose.ui.text.input.VisualTransformation
|
|
42
40
|
import androidx.compose.ui.unit.Dp
|
|
43
41
|
import androidx.compose.ui.unit.dp
|
|
@@ -156,7 +154,7 @@ fun ErrorView(errorMessage: String, errorSpacing: Boolean, hintText: String) {
|
|
|
156
154
|
|
|
157
155
|
@Composable
|
|
158
156
|
fun Input(
|
|
159
|
-
text: String = "",
|
|
157
|
+
text: MutableState<String> = remember { mutableStateOf("") },
|
|
160
158
|
floatingValue: String = "",
|
|
161
159
|
floatingValueColor: Color = AppTheme.current.colors.text.hint,
|
|
162
160
|
floatingIcon: String = "",
|
|
@@ -183,11 +181,6 @@ fun Input(
|
|
|
183
181
|
keyboardType: KeyboardType = KeyboardType.Text,
|
|
184
182
|
modifier: Modifier = Modifier,
|
|
185
183
|
) {
|
|
186
|
-
// Handling state based on the `BasicTextField` concept
|
|
187
|
-
var textFieldValueState by remember { mutableStateOf(TextFieldValue(text = text)) }
|
|
188
|
-
val textFieldValue = textFieldValueState.copy(text = text)
|
|
189
|
-
var lastTextValue by remember(text) { mutableStateOf(text) }
|
|
190
|
-
|
|
191
184
|
var isFocused by remember { mutableStateOf(false) }
|
|
192
185
|
var passHidden by remember { mutableStateOf(false) }
|
|
193
186
|
var isBlurred = false
|
|
@@ -212,14 +205,14 @@ fun Input(
|
|
|
212
205
|
|
|
213
206
|
val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
|
|
214
207
|
|
|
215
|
-
Column(
|
|
216
|
-
|
|
208
|
+
Column(
|
|
209
|
+
modifier = modifier.setAutomationId(testId)
|
|
217
210
|
) {
|
|
218
211
|
BasicTextField(
|
|
219
|
-
value = text,
|
|
220
212
|
enabled = !disabled,
|
|
221
213
|
readOnly = readOnly,
|
|
222
214
|
singleLine = true,
|
|
215
|
+
value = text.value,
|
|
223
216
|
textStyle = TextStyle(
|
|
224
217
|
color = textColor,
|
|
225
218
|
fontSize = 16.sp,
|
|
@@ -236,15 +229,7 @@ fun Input(
|
|
|
236
229
|
if (!it.isFocused && isBlurred) onBlur()
|
|
237
230
|
if (it.isFocused && !isBlurred) isBlurred = true
|
|
238
231
|
},
|
|
239
|
-
onValueChange =
|
|
240
|
-
textFieldValueState.copy(text = newValue)
|
|
241
|
-
val stringChangedSinceLastInvocation = lastTextValue != newValue
|
|
242
|
-
lastTextValue = newValue
|
|
243
|
-
|
|
244
|
-
if (stringChangedSinceLastInvocation) {
|
|
245
|
-
onChangeText(newValue)
|
|
246
|
-
}
|
|
247
|
-
},
|
|
232
|
+
onValueChange = onChangeText,
|
|
248
233
|
decorationBox = { innerTextField ->
|
|
249
234
|
// Floating Icon
|
|
250
235
|
if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
|
|
@@ -306,7 +291,7 @@ fun Input(
|
|
|
306
291
|
)
|
|
307
292
|
}
|
|
308
293
|
Box(Modifier.weight(1f)) {
|
|
309
|
-
if (
|
|
294
|
+
if (text.value.isEmpty()) {
|
|
310
295
|
Text(
|
|
311
296
|
text = placeholder,
|
|
312
297
|
style = TextStyle(
|
|
@@ -319,7 +304,7 @@ fun Input(
|
|
|
319
304
|
}
|
|
320
305
|
innerTextField()
|
|
321
306
|
}
|
|
322
|
-
if (isFocused &&
|
|
307
|
+
if (isFocused && text.value.isNotEmpty()) {
|
|
323
308
|
Row {
|
|
324
309
|
Spacer(Modifier.width(Spacing.XS))
|
|
325
310
|
Icon(
|
|
@@ -327,10 +312,7 @@ fun Input(
|
|
|
327
312
|
size = 16.dp,
|
|
328
313
|
color = AppTheme.current.colors.text.hint,
|
|
329
314
|
modifier = Modifier.clickable(
|
|
330
|
-
onClick = {
|
|
331
|
-
onChangeText("")
|
|
332
|
-
textFieldValueState = TextFieldValue(text = "")
|
|
333
|
-
},
|
|
315
|
+
onClick = { text.value = "" },
|
|
334
316
|
interactionSource = remember { MutableInteractionSource() },
|
|
335
317
|
indication = null
|
|
336
318
|
)
|
|
@@ -338,16 +320,22 @@ fun Input(
|
|
|
338
320
|
}
|
|
339
321
|
}
|
|
340
322
|
if (secureTextEntry && passHidden) {
|
|
341
|
-
val hidePassword = { onRightIconPressed(); passHidden = !passHidden}
|
|
342
|
-
RenderRightIcon(
|
|
343
|
-
|
|
323
|
+
val hidePassword = { onRightIconPressed(); passHidden = !passHidden }
|
|
324
|
+
RenderRightIcon(
|
|
325
|
+
loading, "24_security_eye_open", iconTintColor,
|
|
326
|
+
hidePassword
|
|
327
|
+
)
|
|
344
328
|
} else if (secureTextEntry && !passHidden) {
|
|
345
|
-
val showPassword = { onRightIconPressed(); passHidden = !passHidden}
|
|
346
|
-
RenderRightIcon(
|
|
347
|
-
|
|
329
|
+
val showPassword = { onRightIconPressed(); passHidden = !passHidden }
|
|
330
|
+
RenderRightIcon(
|
|
331
|
+
loading, "24_security_eye_off", iconTintColor,
|
|
332
|
+
showPassword
|
|
333
|
+
)
|
|
348
334
|
} else {
|
|
349
|
-
RenderRightIcon(
|
|
350
|
-
|
|
335
|
+
RenderRightIcon(
|
|
336
|
+
loading, icon, iconTintColor,
|
|
337
|
+
onRightIconPressed
|
|
338
|
+
)
|
|
351
339
|
}
|
|
352
340
|
}
|
|
353
341
|
}
|
|
@@ -33,7 +33,7 @@ import vn.momo.kits.const.Typography
|
|
|
33
33
|
|
|
34
34
|
@Composable
|
|
35
35
|
fun InputDropDown(
|
|
36
|
-
|
|
36
|
+
value: MutableState<String> = remember { mutableStateOf("") },
|
|
37
37
|
floatingValue: String = "",
|
|
38
38
|
floatingValueColor: Color = AppTheme.current.colors.text.hint,
|
|
39
39
|
floatingIcon: String = "",
|
|
@@ -140,12 +140,12 @@ fun InputDropDown(
|
|
|
140
140
|
}
|
|
141
141
|
Box(Modifier.weight(1f)) {
|
|
142
142
|
Text(
|
|
143
|
-
text =
|
|
143
|
+
text = value.value.ifEmpty { placeholder },
|
|
144
144
|
style = TextStyle(
|
|
145
145
|
fontSize = 16.sp,
|
|
146
146
|
lineHeight = 24.sp
|
|
147
147
|
),
|
|
148
|
-
color = if (
|
|
148
|
+
color = if (value.value.isEmpty()) placeholderColor else textColor
|
|
149
149
|
)
|
|
150
150
|
}
|
|
151
151
|
RenderRightIcon(
|
|
@@ -63,7 +63,7 @@ class CustomConverter : VisualTransformation {
|
|
|
63
63
|
|
|
64
64
|
@Composable
|
|
65
65
|
fun InputMoney(
|
|
66
|
-
text: String = "0",
|
|
66
|
+
text: MutableState<String> = remember { mutableStateOf("0") },
|
|
67
67
|
floatingValue: String = "",
|
|
68
68
|
floatingValueColor: Color = AppTheme.current.colors.text.hint,
|
|
69
69
|
floatingIcon: String = "",
|
|
@@ -109,13 +109,13 @@ fun InputMoney(
|
|
|
109
109
|
|
|
110
110
|
val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
|
|
111
111
|
|
|
112
|
-
Column(modifier =
|
|
112
|
+
Column(modifier = Modifier.semantics {
|
|
113
113
|
contentDescription = floatingValue; testTag = testId
|
|
114
114
|
}) {
|
|
115
115
|
BasicTextField(
|
|
116
116
|
enabled = !disabled,
|
|
117
117
|
singleLine = true,
|
|
118
|
-
value = text,
|
|
118
|
+
value = text.value,
|
|
119
119
|
textStyle = TextStyle(
|
|
120
120
|
color = textColor,
|
|
121
121
|
fontSize = 20.sp,
|
|
@@ -195,7 +195,7 @@ fun InputMoney(
|
|
|
195
195
|
)
|
|
196
196
|
}
|
|
197
197
|
Box(Modifier.weight(9f).padding(start = 0.dp)) {
|
|
198
|
-
if (text.isEmpty()) {
|
|
198
|
+
if (text.value.isEmpty()) {
|
|
199
199
|
Text(
|
|
200
200
|
text = placeholder,
|
|
201
201
|
style = TextStyle(
|
|
@@ -209,7 +209,7 @@ fun InputMoney(
|
|
|
209
209
|
innerTextField()
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
if (isFocused && text.isNotEmpty()) {
|
|
212
|
+
if (isFocused && text.value.isNotEmpty()) {
|
|
213
213
|
Row {
|
|
214
214
|
Spacer(Modifier.width(Spacing.XS))
|
|
215
215
|
Icon(
|
|
@@ -217,7 +217,7 @@ fun InputMoney(
|
|
|
217
217
|
size = 16.dp,
|
|
218
218
|
color = AppTheme.current.colors.text.hint,
|
|
219
219
|
modifier = Modifier.clickable(
|
|
220
|
-
onClick = {
|
|
220
|
+
onClick = { text.value = "" },
|
|
221
221
|
interactionSource = remember { MutableInteractionSource() },
|
|
222
222
|
indication = null
|
|
223
223
|
)
|
|
@@ -42,8 +42,8 @@ import vn.momo.kits.const.scaleSize
|
|
|
42
42
|
|
|
43
43
|
@Composable
|
|
44
44
|
fun OTPCaret() {
|
|
45
|
-
val
|
|
46
|
-
|
|
45
|
+
val duration = 500
|
|
46
|
+
val backgroundColor = AppTheme.current.colors.primary
|
|
47
47
|
|
|
48
48
|
val infiniteTransition = rememberInfiniteTransition()
|
|
49
49
|
val alpha by infiniteTransition.animateFloat(
|
|
@@ -51,8 +51,8 @@ fun OTPCaret() {
|
|
|
51
51
|
targetValue = 0f,
|
|
52
52
|
animationSpec = infiniteRepeatable(
|
|
53
53
|
animation = tween(
|
|
54
|
-
durationMillis =
|
|
55
|
-
delayMillis =
|
|
54
|
+
durationMillis = duration,
|
|
55
|
+
delayMillis = duration,
|
|
56
56
|
easing = LinearEasing
|
|
57
57
|
),
|
|
58
58
|
repeatMode = RepeatMode.Reverse
|
|
@@ -85,15 +85,14 @@ fun InputOTP(
|
|
|
85
85
|
onFocus: () -> Unit = {},
|
|
86
86
|
onBlur: () -> Unit = {},
|
|
87
87
|
dataType: String = "number",
|
|
88
|
-
accessibilityLabel: String? = null,
|
|
89
88
|
modifier: Modifier = Modifier
|
|
90
89
|
) {
|
|
91
|
-
val
|
|
90
|
+
val maxLength = 10
|
|
92
91
|
var isFocused by remember { mutableStateOf(false) }
|
|
93
92
|
var isBlurred = false
|
|
94
93
|
|
|
95
94
|
val handleChangeText: (String) -> Unit = { text ->
|
|
96
|
-
if (text.length <=
|
|
95
|
+
if (text.length <= maxLength &&
|
|
97
96
|
(dataType != "number" || !text.any { !it.isDigit() }) &&
|
|
98
97
|
(text.length < value.length || value.length < text.length)
|
|
99
98
|
) {
|
|
@@ -116,7 +115,7 @@ fun InputOTP(
|
|
|
116
115
|
if (!it.isFocused && isBlurred) onBlur()
|
|
117
116
|
if (it.isFocused && !isBlurred) isBlurred = true
|
|
118
117
|
},
|
|
119
|
-
decorationBox = {
|
|
118
|
+
decorationBox = { _ ->
|
|
120
119
|
Box {
|
|
121
120
|
if (floatingValue.isNotEmpty()) {
|
|
122
121
|
Box(
|
|
@@ -78,7 +78,7 @@ fun RenderRightIconSearch(
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
data class InputSearchProps(
|
|
81
|
-
val text: String
|
|
81
|
+
val text: MutableState<String>,
|
|
82
82
|
val buttonText: String = "",
|
|
83
83
|
val showButtonText: Boolean = false,
|
|
84
84
|
val placeholder: String = "",
|
|
@@ -106,7 +106,7 @@ data class InputSearchProps(
|
|
|
106
106
|
@Composable
|
|
107
107
|
fun InputSearch(
|
|
108
108
|
inputSearchProps: InputSearchProps = InputSearchProps(
|
|
109
|
-
text = "",
|
|
109
|
+
text = remember { mutableStateOf("") },
|
|
110
110
|
iconColor = AppTheme.current.colors.text.default
|
|
111
111
|
),
|
|
112
112
|
) {
|
|
@@ -127,7 +127,7 @@ fun InputSearch(
|
|
|
127
127
|
BasicTextField(
|
|
128
128
|
enabled = !inputSearchProps.disabled,
|
|
129
129
|
singleLine = true,
|
|
130
|
-
value = inputSearchProps.text,
|
|
130
|
+
value = inputSearchProps.text.value,
|
|
131
131
|
textStyle = TextStyle(
|
|
132
132
|
color = textColor,
|
|
133
133
|
fontSize = 14.sp,
|
|
@@ -175,7 +175,7 @@ fun InputSearch(
|
|
|
175
175
|
color = AppTheme.current.colors.text.hint
|
|
176
176
|
)
|
|
177
177
|
Box(Modifier.weight(1f)) {
|
|
178
|
-
if (inputSearchProps.text.isEmpty()) {
|
|
178
|
+
if (inputSearchProps.text.value.isEmpty()) {
|
|
179
179
|
Text(
|
|
180
180
|
text = inputSearchProps.placeholder,
|
|
181
181
|
style = TextStyle(
|
|
@@ -190,7 +190,7 @@ fun InputSearch(
|
|
|
190
190
|
}
|
|
191
191
|
innerTextField()
|
|
192
192
|
}
|
|
193
|
-
if (inputSearchProps.clearCondition?.invoke() == true || (isFocused && inputSearchProps.text.isNotEmpty())) {
|
|
193
|
+
if (inputSearchProps.clearCondition?.invoke() == true || (isFocused && inputSearchProps.text.value.isNotEmpty())) {
|
|
194
194
|
Row {
|
|
195
195
|
Spacer(Modifier.width(Spacing.XS))
|
|
196
196
|
Icon(
|
|
@@ -199,7 +199,7 @@ fun InputSearch(
|
|
|
199
199
|
color = AppTheme.current.colors.text.hint,
|
|
200
200
|
modifier = Modifier.clickable(
|
|
201
201
|
onClick = {
|
|
202
|
-
inputSearchProps.
|
|
202
|
+
inputSearchProps.text.value = ""
|
|
203
203
|
inputSearchProps.onClearPress.invoke()
|
|
204
204
|
},
|
|
205
205
|
interactionSource = remember { MutableInteractionSource() },
|
|
@@ -42,7 +42,7 @@ val DEFAULT_HEIGHT = 104.dp
|
|
|
42
42
|
|
|
43
43
|
@Composable
|
|
44
44
|
fun InputTextArea(
|
|
45
|
-
text: String = "",
|
|
45
|
+
text: MutableState<String> = remember { mutableStateOf("") },
|
|
46
46
|
maxLength: Int = MAX_LENGTH,
|
|
47
47
|
height: Dp = DEFAULT_HEIGHT,
|
|
48
48
|
floatingValue: String = "",
|
|
@@ -92,7 +92,7 @@ fun InputTextArea(
|
|
|
92
92
|
BasicTextField(
|
|
93
93
|
enabled = !disabled,
|
|
94
94
|
singleLine = false,
|
|
95
|
-
value = text,
|
|
95
|
+
value = text.value,
|
|
96
96
|
textStyle = TextStyle(
|
|
97
97
|
color = textColor,
|
|
98
98
|
fontSize = 16.sp,
|
|
@@ -173,7 +173,7 @@ fun InputTextArea(
|
|
|
173
173
|
verticalAlignment = Alignment.Top
|
|
174
174
|
) {
|
|
175
175
|
Box(Modifier.weight(1f)) {
|
|
176
|
-
if (text.isEmpty()) {
|
|
176
|
+
if (text.value.isEmpty()) {
|
|
177
177
|
Text(
|
|
178
178
|
text = placeholder,
|
|
179
179
|
style = TextStyle(
|
|
@@ -186,7 +186,7 @@ fun InputTextArea(
|
|
|
186
186
|
}
|
|
187
187
|
innerTextField()
|
|
188
188
|
}
|
|
189
|
-
if (isFocused && text.isNotEmpty()) {
|
|
189
|
+
if (isFocused && text.value.isNotEmpty()) {
|
|
190
190
|
Row {
|
|
191
191
|
Spacer(Modifier.width(Spacing.XS))
|
|
192
192
|
Icon(
|
|
@@ -194,7 +194,7 @@ fun InputTextArea(
|
|
|
194
194
|
size = 16.dp,
|
|
195
195
|
color = AppTheme.current.colors.text.hint,
|
|
196
196
|
modifier = Modifier.clickable(
|
|
197
|
-
onClick = {
|
|
197
|
+
onClick = { text.value = "" },
|
|
198
198
|
interactionSource = remember { MutableInteractionSource() },
|
|
199
199
|
indication = null
|
|
200
200
|
)
|
|
@@ -212,7 +212,7 @@ fun InputTextArea(
|
|
|
212
212
|
contentAlignment = Alignment.CenterEnd
|
|
213
213
|
) {
|
|
214
214
|
Text(
|
|
215
|
-
"${text.length}/$maxLength",
|
|
215
|
+
"${text.value.length}/$maxLength",
|
|
216
216
|
style = Typography.descriptionXsRegular,
|
|
217
217
|
color = AppTheme.current.colors.text.hint
|
|
218
218
|
)
|
|
@@ -2,24 +2,16 @@ package vn.momo.kits.components
|
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.background
|
|
4
4
|
import androidx.compose.foundation.layout.Box
|
|
5
|
-
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
6
5
|
import androidx.compose.foundation.layout.Row
|
|
7
|
-
import androidx.compose.foundation.layout.height
|
|
8
6
|
import androidx.compose.foundation.layout.padding
|
|
9
7
|
import androidx.compose.foundation.layout.size
|
|
10
8
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
11
9
|
import androidx.compose.runtime.Composable
|
|
12
|
-
import androidx.compose.ui.Alignment
|
|
13
10
|
import androidx.compose.ui.Modifier
|
|
14
|
-
import androidx.compose.ui.draw.alpha
|
|
15
|
-
import androidx.compose.ui.draw.clip
|
|
16
|
-
import androidx.compose.ui.draw.clipToBounds
|
|
17
11
|
import androidx.compose.ui.graphics.Color
|
|
18
12
|
import androidx.compose.ui.unit.dp
|
|
19
13
|
import vn.momo.kits.const.AppTheme
|
|
20
|
-
import vn.momo.kits.const.Colors
|
|
21
14
|
import vn.momo.kits.const.Spacing
|
|
22
|
-
import vn.momo.kits.const.Typography
|
|
23
15
|
|
|
24
16
|
@Composable
|
|
25
17
|
fun Dot(active: Boolean = false, activeColor: Color, modifier: Modifier = Modifier) {
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
package vn.momo.kits.components
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.background
|
|
4
|
-
import androidx.compose.foundation.layout.Box
|
|
5
4
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
6
|
-
import androidx.compose.foundation.layout.Row
|
|
7
5
|
import androidx.compose.foundation.layout.padding
|
|
8
6
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
9
7
|
import androidx.compose.runtime.Composable
|
|
10
8
|
import androidx.compose.ui.Alignment
|
|
11
9
|
import androidx.compose.ui.Modifier
|
|
12
|
-
import androidx.compose.ui.draw.alpha
|
|
13
10
|
import androidx.compose.ui.graphics.Color
|
|
14
11
|
import vn.momo.kits.const.Colors
|
|
15
12
|
import vn.momo.kits.const.Spacing
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
package vn.momo.kits.components
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.background
|
|
4
|
-
import androidx.compose.foundation.layout.Box
|
|
5
|
-
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
6
4
|
import androidx.compose.foundation.layout.Row
|
|
7
|
-
import androidx.compose.foundation.layout.height
|
|
8
5
|
import androidx.compose.foundation.layout.padding
|
|
9
|
-
import androidx.compose.foundation.layout.size
|
|
10
6
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
11
7
|
import androidx.compose.runtime.Composable
|
|
12
|
-
import androidx.compose.ui.Alignment
|
|
13
8
|
import androidx.compose.ui.Modifier
|
|
14
|
-
import androidx.compose.ui.draw.alpha
|
|
15
|
-
import androidx.compose.ui.draw.clip
|
|
16
|
-
import androidx.compose.ui.draw.clipToBounds
|
|
17
9
|
import androidx.compose.ui.graphics.Color
|
|
18
10
|
import androidx.compose.ui.unit.dp
|
|
19
|
-
import vn.momo.kits.const.AppTheme
|
|
20
11
|
import vn.momo.kits.const.Colors
|
|
21
12
|
import vn.momo.kits.const.Spacing
|
|
22
|
-
import vn.momo.kits.const.Typography
|
|
23
13
|
|
|
24
14
|
@Composable
|
|
25
15
|
fun PaginationWhiteDot(
|
|
@@ -27,8 +27,6 @@ import androidx.compose.runtime.setValue
|
|
|
27
27
|
import androidx.compose.ui.Alignment
|
|
28
28
|
import androidx.compose.ui.Modifier
|
|
29
29
|
import androidx.compose.ui.draw.clip
|
|
30
|
-
import androidx.compose.ui.semantics.semantics
|
|
31
|
-
import androidx.compose.ui.semantics.testTag
|
|
32
30
|
import androidx.compose.ui.text.TextLayoutResult
|
|
33
31
|
import androidx.compose.ui.unit.dp
|
|
34
32
|
import vn.momo.kits.const.AppTheme
|
|
@@ -96,8 +94,9 @@ fun PopupNotify(
|
|
|
96
94
|
callback?.invoke()
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
Box(
|
|
100
|
-
, contentAlignment = Alignment.TopEnd
|
|
97
|
+
Box(
|
|
98
|
+
Modifier.setAutomationId("popup_notify"), contentAlignment = Alignment.TopEnd
|
|
99
|
+
) {
|
|
101
100
|
Column(
|
|
102
101
|
modifier = Modifier
|
|
103
102
|
.fillMaxWidth()
|
|
@@ -116,7 +115,12 @@ fun PopupNotify(
|
|
|
116
115
|
)
|
|
117
116
|
|
|
118
117
|
Column(modifier = Modifier.padding(Spacing.XL)) {
|
|
119
|
-
Text(
|
|
118
|
+
Text(
|
|
119
|
+
style = Typography.headerDefaultBold,
|
|
120
|
+
maxLines = 2,
|
|
121
|
+
text = title,
|
|
122
|
+
modifier = Modifier.setAutomationId("title_popup_permission")
|
|
123
|
+
)
|
|
120
124
|
content(Modifier.padding(top = Spacing.S))
|
|
121
125
|
if (error.isNotEmpty()) {
|
|
122
126
|
Text(
|
|
@@ -3,16 +3,13 @@ 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.interaction.MutableInteractionSource
|
|
7
6
|
import androidx.compose.foundation.layout.Box
|
|
8
7
|
import androidx.compose.foundation.layout.height
|
|
9
8
|
import androidx.compose.foundation.layout.padding
|
|
10
9
|
import androidx.compose.foundation.layout.size
|
|
11
10
|
import androidx.compose.foundation.layout.width
|
|
12
11
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
13
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
14
12
|
import androidx.compose.runtime.Composable
|
|
15
|
-
import androidx.compose.runtime.remember
|
|
16
13
|
import androidx.compose.ui.Alignment
|
|
17
14
|
import androidx.compose.ui.Modifier
|
|
18
15
|
import androidx.compose.ui.draw.clip
|
|
@@ -9,7 +9,6 @@ import androidx.compose.ui.text.style.TextAlign
|
|
|
9
9
|
import androidx.compose.ui.text.style.TextDecoration
|
|
10
10
|
import androidx.compose.ui.text.style.TextOverflow
|
|
11
11
|
import androidx.compose.ui.unit.sp
|
|
12
|
-
import vn.momo.kits.application.PlatformApi
|
|
13
12
|
import vn.momo.kits.const.AppTheme
|
|
14
13
|
import vn.momo.kits.const.Typography
|
|
15
14
|
import vn.momo.kits.const.getFontFamily
|
|
@@ -34,7 +33,7 @@ fun Text(
|
|
|
34
33
|
val font = getFontFamily(fontFamily, style.fontWeight)
|
|
35
34
|
|
|
36
35
|
androidx.compose.material3.Text(
|
|
37
|
-
modifier = modifier.setAutomationId(accessibilityId?:text, text),
|
|
36
|
+
modifier = modifier.setAutomationId(accessibilityId ?: text, text),
|
|
38
37
|
text = text,
|
|
39
38
|
color = color ?: AppTheme.current.colors.text.default,
|
|
40
39
|
style = style.copy(fontWeight = null),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
package vn.momo.kits.components.
|
|
1
|
+
package vn.momo.kits.components.datetimepicker
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.background
|
|
4
4
|
import androidx.compose.foundation.layout.Column
|
|
@@ -32,7 +32,7 @@ private fun onPickerChange(
|
|
|
32
32
|
effectiveMinDate: LocalDateTime,
|
|
33
33
|
effectiveMaxDate: LocalDateTime,
|
|
34
34
|
onChange: (LocalDateTime) -> Unit
|
|
35
|
-
){
|
|
35
|
+
) {
|
|
36
36
|
when (name) {
|
|
37
37
|
"day" -> currentDate.day = value.toInt()
|
|
38
38
|
"month" -> currentDate.month = value.toInt()
|
|
@@ -82,15 +82,15 @@ fun DateTimePicker(
|
|
|
82
82
|
arrayLabelTime: List<String> = emptyList()
|
|
83
83
|
) {
|
|
84
84
|
val now = remember { getCurrentDateTime() }
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
val minDateDefault = remember { createRelativeDate(-10) }
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
val maxDateDefault = remember { createRelativeDate(10) }
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
val effectiveSelectedValue = selectedValue ?: now
|
|
91
91
|
val effectiveMinDate = minDate ?: minDateDefault
|
|
92
92
|
val effectiveMaxDate = maxDate ?: maxDateDefault
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
val initialValue = remember {
|
|
95
95
|
when {
|
|
96
96
|
effectiveSelectedValue < effectiveMinDate -> effectiveMinDate
|
|
@@ -110,11 +110,11 @@ fun DateTimePicker(
|
|
|
110
110
|
)
|
|
111
111
|
)
|
|
112
112
|
}
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
val pickerHeight = if (arrayLabelTime.isNotEmpty())
|
|
115
|
-
datePickerWithLabelsHeight else
|
|
115
|
+
datePickerWithLabelsHeight else
|
|
116
116
|
datePickerHeight
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
Row(
|
|
119
119
|
modifier = modifier
|
|
120
120
|
.fillMaxWidth()
|
|
@@ -132,7 +132,7 @@ fun DateTimePicker(
|
|
|
132
132
|
)
|
|
133
133
|
dateComponents.forEachIndexed { index, component ->
|
|
134
134
|
val hasLabel = index < arrayLabelTime.size && arrayLabelTime[index].isNotEmpty()
|
|
135
|
-
|
|
135
|
+
|
|
136
136
|
Column(
|
|
137
137
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
138
138
|
modifier = Modifier.weight(1f)
|
|
@@ -144,7 +144,7 @@ fun DateTimePicker(
|
|
|
144
144
|
modifier = Modifier.padding(bottom = Spacing.S)
|
|
145
145
|
)
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
WheelPicker(
|
|
149
149
|
name = component.name,
|
|
150
150
|
data = component.data,
|
|
@@ -169,7 +169,7 @@ fun DateTimePicker(
|
|
|
169
169
|
}
|
|
170
170
|
)
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
if (index < dateComponents.size - 1) {
|
|
174
174
|
Spacer(modifier = Modifier.width(Spacing.M))
|
|
175
175
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
package vn.momo.kits.components.
|
|
1
|
+
package vn.momo.kits.components.datetimepicker
|
|
2
2
|
|
|
3
3
|
import androidx.compose.runtime.Composable
|
|
4
4
|
import androidx.compose.runtime.remember
|
|
@@ -16,10 +16,19 @@ import kotlinx.datetime.toLocalDateTime
|
|
|
16
16
|
*/
|
|
17
17
|
fun formatLocalDateTime(dateTime: LocalDateTime, format: String = "yyyy-MM-dd HH:mm"): String {
|
|
18
18
|
return when (format) {
|
|
19
|
-
"yyyy-MM-dd HH:mm" -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${
|
|
19
|
+
"yyyy-MM-dd HH:mm" -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${
|
|
20
|
+
paddingNum(
|
|
21
|
+
dateTime.dayOfMonth
|
|
22
|
+
)
|
|
23
|
+
} ${paddingNum(dateTime.hour)}:${paddingNum(dateTime.minute)}"
|
|
24
|
+
|
|
20
25
|
"dd-MM-yyyy" -> "${paddingNum(dateTime.dayOfMonth)}-${paddingNum(dateTime.month.number)}-${dateTime.year}"
|
|
21
26
|
"HH:mm" -> "${paddingNum(dateTime.hour)}:${paddingNum(dateTime.minute)}"
|
|
22
|
-
else -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${paddingNum(dateTime.dayOfMonth)} ${
|
|
27
|
+
else -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${paddingNum(dateTime.dayOfMonth)} ${
|
|
28
|
+
paddingNum(
|
|
29
|
+
dateTime.hour
|
|
30
|
+
)
|
|
31
|
+
}:${paddingNum(dateTime.minute)}"
|
|
23
32
|
}
|
|
24
33
|
}
|
|
25
34
|
|
|
@@ -150,13 +159,13 @@ fun getCurrentDateTime(): LocalDateTime {
|
|
|
150
159
|
fun createRelativeDate(years: Int): LocalDateTime {
|
|
151
160
|
val currentDateTime = getCurrentDateTime()
|
|
152
161
|
val period = DatePeriod(years = if (years < 0) -years else years)
|
|
153
|
-
|
|
162
|
+
|
|
154
163
|
val adjustedDate = if (years < 0) {
|
|
155
164
|
currentDateTime.date.minus(period)
|
|
156
165
|
} else {
|
|
157
166
|
currentDateTime.date.plus(period)
|
|
158
167
|
}
|
|
159
|
-
|
|
168
|
+
|
|
160
169
|
return LocalDateTime(
|
|
161
170
|
adjustedDate.year,
|
|
162
171
|
adjustedDate.monthNumber,
|
|
@@ -182,9 +191,10 @@ internal fun getDateComponents(
|
|
|
182
191
|
formatParts.size == 1 && formatParts[0] == "HH"
|
|
183
192
|
}
|
|
184
193
|
|
|
185
|
-
val dayData =
|
|
186
|
-
|
|
187
|
-
|
|
194
|
+
val dayData =
|
|
195
|
+
remember(currentDate.year, currentDate.month, effectiveMinDate, effectiveMaxDate) {
|
|
196
|
+
getDaysInMonth(currentDate.year, currentDate.month, effectiveMinDate, effectiveMaxDate)
|
|
197
|
+
}
|
|
188
198
|
|
|
189
199
|
val monthData = remember(currentDate.year, effectiveMinDate, effectiveMaxDate) {
|
|
190
200
|
getMonths(effectiveMinDate, effectiveMaxDate, currentDate.year)
|
|
@@ -202,25 +212,26 @@ internal fun getDateComponents(
|
|
|
202
212
|
getMinutes(minuteInterval)
|
|
203
213
|
}
|
|
204
214
|
|
|
205
|
-
val dateComponents =
|
|
206
|
-
|
|
215
|
+
val dateComponents =
|
|
216
|
+
remember(formatParts, dayData, monthData, yearData, hourData, minData, isOnlyHour) {
|
|
217
|
+
val components = mutableListOf<DateComponent>()
|
|
207
218
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
219
|
+
formatParts.forEach { part ->
|
|
220
|
+
when (part) {
|
|
221
|
+
"DD" -> components.add(DateComponent("day", dayData))
|
|
222
|
+
"MM" -> components.add(DateComponent("month", monthData))
|
|
223
|
+
"YYYY" -> components.add(DateComponent("year", yearData))
|
|
224
|
+
"HH" -> components.add(DateComponent("hour", hourData))
|
|
225
|
+
"mm" -> components.add(DateComponent("minute", minData))
|
|
226
|
+
}
|
|
215
227
|
}
|
|
216
|
-
}
|
|
217
228
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
if (isOnlyHour) {
|
|
230
|
+
components.add(DateComponent("timeMode", timeMode))
|
|
231
|
+
}
|
|
221
232
|
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
components
|
|
234
|
+
}
|
|
224
235
|
|
|
225
236
|
return dateComponents
|
|
226
237
|
}
|
|
@@ -30,7 +30,14 @@ fun scaleSize(size: Float): Float {
|
|
|
30
30
|
fun getFont(font: String): FontFamily {
|
|
31
31
|
val fontResource = FontResource(
|
|
32
32
|
"font:${font.substringBeforeLast(".")}",
|
|
33
|
-
setOf(
|
|
33
|
+
setOf(
|
|
34
|
+
ResourceItem(
|
|
35
|
+
setOf(),
|
|
36
|
+
"font/${font.substringBeforeLast(".")}.${font.substringAfterLast(".")}",
|
|
37
|
+
-1,
|
|
38
|
+
-1
|
|
39
|
+
)
|
|
40
|
+
)
|
|
34
41
|
)
|
|
35
42
|
return FontFamily(Font(fontResource))
|
|
36
43
|
}
|
|
@@ -7,7 +7,7 @@ import androidx.compose.runtime.Composable
|
|
|
7
7
|
import androidx.compose.ui.Modifier
|
|
8
8
|
import androidx.compose.ui.unit.Dp
|
|
9
9
|
|
|
10
|
-
data class GridContext
|
|
10
|
+
data class GridContext(
|
|
11
11
|
val numberOfColumns: Number,
|
|
12
12
|
val gutterSize: Number,
|
|
13
13
|
val sizePerSpan: Number,
|
|
@@ -15,16 +15,21 @@ data class GridContext (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
@Composable
|
|
18
|
-
fun Item(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
fun Item(
|
|
19
|
+
heightSpan: Number = 1,
|
|
20
|
+
widthSpan: Number = 1,
|
|
21
|
+
content: @Composable() () -> Unit,
|
|
22
|
+
modifier: Modifier = Modifier,
|
|
23
|
+
grid: GridContext
|
|
24
|
+
) {
|
|
23
25
|
|
|
24
26
|
val widthItem = grid.getSizeSpan(widthSpan)
|
|
25
27
|
val heightItem = grid.getSizeSpan(heightSpan)
|
|
26
28
|
|
|
27
|
-
Box(
|
|
29
|
+
Box(
|
|
30
|
+
modifier = modifier.width(width = Dp(widthItem.toFloat()))
|
|
31
|
+
.height(height = Dp(heightItem.toFloat()))
|
|
32
|
+
) {
|
|
28
33
|
content()
|
|
29
34
|
}
|
|
30
35
|
}
|
|
@@ -11,7 +11,7 @@ import androidx.compose.ui.semantics.semantics
|
|
|
11
11
|
import androidx.compose.ui.semantics.testTag
|
|
12
12
|
import vn.momo.kits.platform.getPlatformName
|
|
13
13
|
|
|
14
|
-
fun Modifier.setAutomationId(accessibilityId
|
|
14
|
+
fun Modifier.setAutomationId(accessibilityId: String, label: String? = null): Modifier {
|
|
15
15
|
return if (getPlatformName() == "Android") {
|
|
16
16
|
semantics {
|
|
17
17
|
contentDescription = accessibilityId
|
|
@@ -2,7 +2,7 @@ package vn.momo.kits.modifier
|
|
|
2
2
|
|
|
3
3
|
import androidx.compose.ui.Modifier
|
|
4
4
|
|
|
5
|
-
fun Modifier.conditional(condition
|
|
5
|
+
fun Modifier.conditional(condition: Boolean, modifier: Modifier.() -> Modifier): Modifier {
|
|
6
6
|
return if (condition) {
|
|
7
7
|
then(modifier(Modifier))
|
|
8
8
|
} else {
|
package/local.properties
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
# Location of the SDK. This is only used by Gradle.
|
|
5
5
|
# For customization when using a Version Control System, please read the
|
|
6
6
|
# header note.
|
|
7
|
-
#
|
|
8
|
-
sdk.dir=/Users/
|
|
7
|
+
#Wed Aug 21 14:20:12 ICT 2024
|
|
8
|
+
sdk.dir=/Users/huynhdung/Library/Android/sdk
|
package/package.json
CHANGED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.components.dateTimePicker
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.Column
|
|
4
|
-
import androidx.compose.foundation.layout.Spacer
|
|
5
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
6
|
-
import androidx.compose.foundation.layout.height
|
|
7
|
-
import androidx.compose.foundation.layout.padding
|
|
8
|
-
import androidx.compose.runtime.Composable
|
|
9
|
-
import androidx.compose.runtime.getValue
|
|
10
|
-
import androidx.compose.runtime.mutableStateOf
|
|
11
|
-
import androidx.compose.runtime.remember
|
|
12
|
-
import androidx.compose.runtime.setValue
|
|
13
|
-
import androidx.compose.ui.Modifier
|
|
14
|
-
import vn.momo.kits.components.Text
|
|
15
|
-
import vn.momo.kits.const.Spacing
|
|
16
|
-
import vn.momo.kits.const.Typography
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Example usage of DateTimePicker component
|
|
20
|
-
*/
|
|
21
|
-
@Composable
|
|
22
|
-
fun DateTimePickerExample() {
|
|
23
|
-
// The current date and time
|
|
24
|
-
val now = remember { getCurrentDateTime() }
|
|
25
|
-
|
|
26
|
-
// State to hold the selected date
|
|
27
|
-
var selectedDate by remember { mutableStateOf(now) }
|
|
28
|
-
|
|
29
|
-
Column(
|
|
30
|
-
modifier = Modifier
|
|
31
|
-
.fillMaxWidth()
|
|
32
|
-
.padding(Spacing.M)
|
|
33
|
-
) {
|
|
34
|
-
// Display the current selected date
|
|
35
|
-
Text(
|
|
36
|
-
text = "Selected Date: ${formatLocalDateTime(selectedDate)}",
|
|
37
|
-
style = Typography.bodyDefaultRegular
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
Spacer(modifier = Modifier.height(Spacing.L))
|
|
41
|
-
|
|
42
|
-
// Date Picker (DD-MM-YYYY)
|
|
43
|
-
Text(
|
|
44
|
-
text = "Date Picker",
|
|
45
|
-
style = Typography.descriptionDefaultRegular
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
Spacer(modifier = Modifier.height(Spacing.S))
|
|
49
|
-
|
|
50
|
-
DateTimePicker(
|
|
51
|
-
selectedValue = selectedDate,
|
|
52
|
-
onChange = { selectedDate = it },
|
|
53
|
-
format = "DD-MM-YYYY"
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
Spacer(modifier = Modifier.height(Spacing.L))
|
|
57
|
-
|
|
58
|
-
// Date and Time Picker (DD-MM-YYYY HH:mm)
|
|
59
|
-
Text(
|
|
60
|
-
text = "Date and Time Picker",
|
|
61
|
-
style = Typography.descriptionDefaultRegular
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
Spacer(modifier = Modifier.height(Spacing.S))
|
|
65
|
-
|
|
66
|
-
DateTimePicker(
|
|
67
|
-
selectedValue = selectedDate,
|
|
68
|
-
onChange = { selectedDate = it },
|
|
69
|
-
format = "DD-MM-YYYY-HH-mm",
|
|
70
|
-
arrayLabelTime = listOf("Day", "Month", "Year", "Hour", "Minute")
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
Spacer(modifier = Modifier.height(Spacing.L))
|
|
74
|
-
|
|
75
|
-
// Time Picker (HH:mm)
|
|
76
|
-
Text(
|
|
77
|
-
text = "Time Picker",
|
|
78
|
-
style = Typography.descriptionDefaultRegular
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
Spacer(modifier = Modifier.height(Spacing.S))
|
|
82
|
-
|
|
83
|
-
DateTimePicker(
|
|
84
|
-
selectedValue = selectedDate,
|
|
85
|
-
onChange = { selectedDate = it },
|
|
86
|
-
format = "HH-mm",
|
|
87
|
-
arrayLabelTime = listOf("Hour", "Minute")
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
}
|