@momo-kits/native-kits 0.89.18 → 0.89.20
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/build.gradle.kts +18 -14
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Components.kt +79 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +200 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +47 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +7 -139
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +89 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +17 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +6 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +6 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +40 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +54 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +155 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +2 -20
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +2 -18
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +58 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +43 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +23 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PromotionPopup.kt +8 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +14 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +28 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +18 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -23
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +33 -0
- package/package.json +1 -1
- package/settings.gradle.kts +1 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/Platform.kt +0 -3
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +0 -8
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/Utils.android.kt +0 -14
- package/compose/src/commonMain/composeResources/drawable/test.jpg +0 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Platform.kt +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +0 -5
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/Platform.kt +0 -3
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +0 -9
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/Utils.ios.kt +0 -18
|
@@ -1,48 +1,23 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
-
import androidx.compose.foundation.background
|
|
4
|
-
import androidx.compose.foundation.clickable
|
|
5
|
-
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
6
|
-
import androidx.compose.foundation.layout.Box
|
|
7
3
|
import androidx.compose.foundation.layout.WindowInsets
|
|
8
4
|
import androidx.compose.foundation.layout.asPaddingValues
|
|
9
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
10
|
-
import androidx.compose.foundation.layout.padding
|
|
11
5
|
import androidx.compose.foundation.layout.systemBars
|
|
12
|
-
import androidx.compose.material.ExperimentalMaterialApi
|
|
13
6
|
import androidx.compose.runtime.Composable
|
|
14
7
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
15
|
-
import androidx.compose.runtime.remember
|
|
16
8
|
import androidx.compose.runtime.staticCompositionLocalOf
|
|
17
|
-
import androidx.compose.ui.Alignment
|
|
18
|
-
import androidx.compose.ui.Modifier
|
|
19
|
-
import androidx.compose.ui.graphics.Color
|
|
20
|
-
import androidx.compose.ui.unit.Dp
|
|
21
|
-
import androidx.compose.ui.unit.dp
|
|
22
|
-
import cafe.adriel.voyager.core.screen.Screen
|
|
23
|
-
import cafe.adriel.voyager.navigator.LocalNavigator
|
|
24
|
-
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
|
25
|
-
import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator
|
|
26
|
-
import cafe.adriel.voyager.navigator.currentOrThrow
|
|
27
|
-
import cafe.adriel.voyager.transitions.SlideTransition
|
|
28
9
|
import vn.momo.kits.const.AppStatusBar
|
|
29
10
|
import vn.momo.kits.const.AppTheme
|
|
30
|
-
import vn.momo.kits.const.Spacing
|
|
31
11
|
import vn.momo.kits.const.Theme
|
|
32
12
|
import vn.momo.kits.const.defaultTheme
|
|
13
|
+
import vn.momo.kits.platform.disableOverscroll
|
|
33
14
|
|
|
34
15
|
val AppNavigator = staticCompositionLocalOf<Navigator> {
|
|
35
16
|
error("no navigator provided!")
|
|
36
17
|
}
|
|
37
18
|
|
|
38
|
-
class Navigator
|
|
39
|
-
private val stack: cafe.adriel.voyager.navigator.Navigator,
|
|
40
|
-
private val sheet: BottomSheetNavigator,
|
|
41
|
-
) {
|
|
19
|
+
class Navigator {
|
|
42
20
|
fun push(content: @Composable () -> Unit) {
|
|
43
|
-
stack.push(StackScreen {
|
|
44
|
-
content()
|
|
45
|
-
})
|
|
46
21
|
}
|
|
47
22
|
|
|
48
23
|
fun present(content: @Composable () -> Unit) {
|
|
@@ -54,21 +29,12 @@ class Navigator(
|
|
|
54
29
|
}
|
|
55
30
|
|
|
56
31
|
fun pop() {
|
|
57
|
-
if (sheet.isVisible) {
|
|
58
|
-
sheet.hide()
|
|
59
|
-
} else {
|
|
60
|
-
stack.pop()
|
|
61
|
-
}
|
|
62
32
|
}
|
|
63
33
|
|
|
64
34
|
fun replace(content: @Composable () -> Unit) {
|
|
65
|
-
stack.replace(StackScreen {
|
|
66
|
-
content()
|
|
67
|
-
})
|
|
68
35
|
}
|
|
69
36
|
|
|
70
37
|
fun popToTop() {
|
|
71
|
-
stack.popUntilRoot()
|
|
72
38
|
}
|
|
73
39
|
|
|
74
40
|
fun showModal(
|
|
@@ -76,122 +42,24 @@ class Navigator(
|
|
|
76
42
|
canBackgroundClose: Boolean = true,
|
|
77
43
|
content: @Composable () -> Unit,
|
|
78
44
|
) {
|
|
79
|
-
sheet.show(ModalScreen(onClose = onClose, barrierDismissible = canBackgroundClose) {
|
|
80
|
-
content()
|
|
81
|
-
})
|
|
82
45
|
}
|
|
83
46
|
|
|
84
47
|
fun showBottomSheet(content: @Composable () -> Unit) {
|
|
85
|
-
sheet.show(SheetScreen {
|
|
86
|
-
content()
|
|
87
|
-
})
|
|
88
48
|
}
|
|
89
49
|
}
|
|
90
50
|
|
|
91
|
-
@OptIn(ExperimentalMaterialApi::class)
|
|
92
51
|
@Composable
|
|
93
52
|
fun ApplicationContainer(
|
|
94
53
|
theme: Theme = defaultTheme,
|
|
95
|
-
statusBarHeight: Dp = WindowInsets.systemBars.asPaddingValues().calculateTopPadding(),
|
|
96
54
|
content: @Composable () -> Unit,
|
|
97
55
|
) {
|
|
56
|
+
disableOverscroll()
|
|
98
57
|
CompositionLocalProvider(
|
|
99
58
|
AppTheme provides theme,
|
|
100
|
-
|
|
59
|
+
AppNavigator provides Navigator(),
|
|
60
|
+
AppStatusBar provides WindowInsets.systemBars.asPaddingValues().calculateTopPadding(),
|
|
101
61
|
) {
|
|
102
|
-
|
|
103
|
-
cafe.adriel.voyager.navigator.Navigator(MainScreen {
|
|
104
|
-
content()
|
|
105
|
-
}) {
|
|
106
|
-
SlideTransition(it)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
class MainScreen(private val content: @Composable () -> Unit) : Screen {
|
|
114
|
-
@Composable
|
|
115
|
-
override fun Content() {
|
|
116
|
-
CompositionLocalProvider(
|
|
117
|
-
AppNavigator provides Navigator(
|
|
118
|
-
LocalNavigator.currentOrThrow,
|
|
119
|
-
LocalBottomSheetNavigator.current
|
|
120
|
-
),
|
|
121
|
-
) {
|
|
122
|
-
content()
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
class StackScreen(private val content: @Composable () -> Unit) : Screen {
|
|
128
|
-
@Composable
|
|
129
|
-
override fun Content() {
|
|
130
|
-
CompositionLocalProvider(
|
|
131
|
-
AppNavigator provides Navigator(
|
|
132
|
-
LocalNavigator.currentOrThrow,
|
|
133
|
-
LocalBottomSheetNavigator.current
|
|
134
|
-
),
|
|
135
|
-
) {
|
|
136
|
-
content()
|
|
137
|
-
}
|
|
62
|
+
content()
|
|
138
63
|
}
|
|
139
|
-
}
|
|
140
64
|
|
|
141
|
-
|
|
142
|
-
@Composable
|
|
143
|
-
override fun Content() {
|
|
144
|
-
CompositionLocalProvider(
|
|
145
|
-
AppNavigator provides Navigator(
|
|
146
|
-
LocalNavigator.currentOrThrow,
|
|
147
|
-
LocalBottomSheetNavigator.current
|
|
148
|
-
),
|
|
149
|
-
) {
|
|
150
|
-
content()
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
class ModalScreen(
|
|
156
|
-
private val onClose: () -> Unit,
|
|
157
|
-
private val barrierDismissible: Boolean = true,
|
|
158
|
-
private val content: @Composable () -> Unit,
|
|
159
|
-
) :
|
|
160
|
-
Screen {
|
|
161
|
-
@Composable
|
|
162
|
-
override fun Content() {
|
|
163
|
-
val navigator = Navigator(
|
|
164
|
-
LocalNavigator.currentOrThrow,
|
|
165
|
-
LocalBottomSheetNavigator.current
|
|
166
|
-
)
|
|
167
|
-
CompositionLocalProvider(
|
|
168
|
-
AppNavigator provides navigator,
|
|
169
|
-
) {
|
|
170
|
-
Box(
|
|
171
|
-
modifier = Modifier.fillMaxSize().padding(horizontal = Spacing.XL)
|
|
172
|
-
.background(Color.Transparent)
|
|
173
|
-
.clickable(
|
|
174
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
175
|
-
indication = null,
|
|
176
|
-
onClick = {
|
|
177
|
-
if (barrierDismissible) {
|
|
178
|
-
navigator.pop()
|
|
179
|
-
onClose()
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
),
|
|
183
|
-
contentAlignment = Alignment.Center
|
|
184
|
-
) {
|
|
185
|
-
Box(
|
|
186
|
-
modifier = Modifier.clickable(
|
|
187
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
188
|
-
indication = null
|
|
189
|
-
) {},
|
|
190
|
-
contentAlignment = Alignment.Center
|
|
191
|
-
) {
|
|
192
|
-
content()
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
65
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
3
4
|
import androidx.compose.foundation.background
|
|
4
5
|
import androidx.compose.foundation.gestures.detectTapGestures
|
|
5
6
|
import androidx.compose.foundation.layout.Arrangement
|
|
6
7
|
import androidx.compose.foundation.layout.Box
|
|
7
8
|
import androidx.compose.foundation.layout.Column
|
|
9
|
+
import androidx.compose.foundation.layout.Spacer
|
|
8
10
|
import androidx.compose.foundation.layout.WindowInsets
|
|
9
11
|
import androidx.compose.foundation.layout.asPaddingValues
|
|
10
12
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
@@ -16,14 +18,18 @@ import androidx.compose.foundation.layout.systemBars
|
|
|
16
18
|
import androidx.compose.foundation.rememberScrollState
|
|
17
19
|
import androidx.compose.foundation.verticalScroll
|
|
18
20
|
import androidx.compose.runtime.Composable
|
|
21
|
+
import androidx.compose.runtime.getValue
|
|
19
22
|
import androidx.compose.ui.Alignment
|
|
20
23
|
import androidx.compose.ui.Modifier
|
|
21
24
|
import androidx.compose.ui.graphics.Color
|
|
25
|
+
import androidx.compose.ui.graphics.graphicsLayer
|
|
22
26
|
import androidx.compose.ui.input.pointer.pointerInput
|
|
23
27
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
24
28
|
import androidx.compose.ui.unit.Dp
|
|
25
29
|
import androidx.compose.ui.unit.dp
|
|
26
30
|
import androidx.compose.ui.unit.min
|
|
31
|
+
import androidx.compose.ui.zIndex
|
|
32
|
+
import vn.momo.kits.const.AppStatusBar
|
|
27
33
|
import vn.momo.kits.const.AppTheme
|
|
28
34
|
import vn.momo.kits.const.Colors
|
|
29
35
|
import vn.momo.kits.const.Spacing
|
|
@@ -51,6 +57,9 @@ fun Screen(
|
|
|
51
57
|
useAvoidKeyboard: Boolean = true,
|
|
52
58
|
footer: @Composable (() -> Unit)? = null,
|
|
53
59
|
headerRight: @Composable (() -> Unit)? = null,
|
|
60
|
+
fabProps: FabProps? = null,
|
|
61
|
+
animatedHeader: AnimatedHeader? = null,
|
|
62
|
+
layoutOffset: Dp = 56.dp,
|
|
54
63
|
content: @Composable () -> Unit,
|
|
55
64
|
) {
|
|
56
65
|
val keyboardController = LocalSoftwareKeyboardController.current
|
|
@@ -62,50 +71,108 @@ fun Screen(
|
|
|
62
71
|
else -> 0.dp
|
|
63
72
|
}
|
|
64
73
|
|
|
74
|
+
val indicator = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
|
|
75
|
+
val bottomPadding = min(indicator, 21.dp)
|
|
76
|
+
val scrollState = rememberScrollState()
|
|
77
|
+
|
|
78
|
+
val opacity by animateFloatAsState(
|
|
79
|
+
targetValue = ((scrollState.value / 114f)).coerceIn(0f, 1f)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
val headerAnimated =
|
|
83
|
+
@Composable { animatedHeader?.composable?.invoke(scrollState.value) }
|
|
84
|
+
|
|
65
85
|
Box(
|
|
66
|
-
Modifier.fillMaxSize()
|
|
86
|
+
Modifier.fillMaxSize()
|
|
87
|
+
.background(backgroundColor ?: AppTheme.current.colors.background.default)
|
|
67
88
|
) {
|
|
68
|
-
|
|
89
|
+
|
|
90
|
+
if (animatedHeader === null) {
|
|
91
|
+
HeaderImage(
|
|
92
|
+
headerType,
|
|
93
|
+
headerBackground ?: AppTheme.current.assets.headerBackground
|
|
94
|
+
)
|
|
95
|
+
} else {
|
|
96
|
+
Box(
|
|
97
|
+
Modifier.zIndex(5f).background(Color.White.copy(alpha = opacity))
|
|
98
|
+
.graphicsLayer { alpha = opacity }) {
|
|
99
|
+
HeaderImage(
|
|
100
|
+
headerType,
|
|
101
|
+
headerBackground ?: AppTheme.current.assets.headerBackground
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Header(
|
|
107
|
+
headerType = headerType,
|
|
108
|
+
title = title,
|
|
109
|
+
titlePosition = titlePosition,
|
|
110
|
+
headerRight = headerRight,
|
|
111
|
+
isBack = isBack,
|
|
112
|
+
goBack = goBack,
|
|
113
|
+
opacity = opacity,
|
|
114
|
+
animatedHeader = animatedHeader,
|
|
115
|
+
scrollState = scrollState.value
|
|
116
|
+
)
|
|
117
|
+
|
|
69
118
|
Column(
|
|
70
|
-
modifier = Modifier.fillMaxSize()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
119
|
+
modifier = Modifier.fillMaxSize()
|
|
120
|
+
.padding(top = if (animatedHeader === null && headerType !== HeaderType.NONE) AppStatusBar.current + 52.dp else 0.dp)
|
|
121
|
+
.pointerInput(Unit) {
|
|
122
|
+
detectTapGestures(onTap = {
|
|
123
|
+
keyboardController?.hide()
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
.zIndex(1f),
|
|
75
127
|
) {
|
|
76
|
-
Header(
|
|
77
|
-
headerType = headerType,
|
|
78
|
-
title = title,
|
|
79
|
-
titlePosition = titlePosition,
|
|
80
|
-
headerRight = headerRight,
|
|
81
|
-
isBack = isBack,
|
|
82
|
-
goBack = goBack,
|
|
83
|
-
)
|
|
84
128
|
|
|
85
129
|
Column(
|
|
86
130
|
modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize)
|
|
87
|
-
.verticalScroll(
|
|
131
|
+
.verticalScroll(scrollState) else
|
|
88
132
|
Modifier.padding(bottom = keyboardSize),
|
|
89
133
|
verticalArrangement = verticalArrangement,
|
|
90
134
|
horizontalAlignment = horizontalAlignment
|
|
91
135
|
) {
|
|
92
|
-
|
|
136
|
+
Box {
|
|
137
|
+
headerAnimated()
|
|
138
|
+
Column {
|
|
139
|
+
if (animatedHeader !== null) {
|
|
140
|
+
Spacer(modifier = Modifier.padding(top = AppStatusBar.current + 52.dp + layoutOffset))
|
|
141
|
+
}
|
|
142
|
+
content()
|
|
143
|
+
}
|
|
144
|
+
}
|
|
93
145
|
}
|
|
94
146
|
|
|
95
147
|
footer?.let {
|
|
96
|
-
Footer(footer, keyboardSize)
|
|
148
|
+
Footer(footer, keyboardSize, bottomPadding)
|
|
97
149
|
}
|
|
98
150
|
}
|
|
151
|
+
|
|
152
|
+
if (fabProps != null) {
|
|
153
|
+
FloatingButton(
|
|
154
|
+
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
155
|
+
onClick = fabProps.onClick,
|
|
156
|
+
containerColor = AppTheme.current.colors.primary,
|
|
157
|
+
bottom = fabProps.bottom
|
|
158
|
+
?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
|
|
159
|
+
icon = fabProps.icon,
|
|
160
|
+
iconColor = fabProps.iconColor,
|
|
161
|
+
text = fabProps.label,
|
|
162
|
+
size = fabProps.size,
|
|
163
|
+
position = fabProps.position ?: FABPosition.END,
|
|
164
|
+
keyboardSize = keyboardSize
|
|
165
|
+
)
|
|
166
|
+
}
|
|
99
167
|
}
|
|
100
168
|
}
|
|
101
169
|
|
|
102
170
|
@Composable
|
|
103
|
-
fun Footer(footer: @Composable (() -> Unit)? = null, keyboardSize: Dp = 0.dp) {
|
|
104
|
-
val indicator = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
|
|
171
|
+
fun Footer(footer: @Composable (() -> Unit)? = null, keyboardSize: Dp = 0.dp, bottom: Dp = 0.dp) {
|
|
105
172
|
Box(
|
|
106
173
|
Modifier
|
|
107
|
-
.offset(y = -
|
|
108
|
-
.padding(bottom =
|
|
174
|
+
.offset(y = -keyboardSize)
|
|
175
|
+
.padding(bottom = bottom)
|
|
109
176
|
.shadow(
|
|
110
177
|
Colors.black_20.copy(alpha = 0.1f),
|
|
111
178
|
borderRadius = 0.dp,
|
|
@@ -18,10 +18,26 @@ import vn.momo.kits.const.Radius
|
|
|
18
18
|
import vn.momo.kits.const.Spacing
|
|
19
19
|
import vn.momo.kits.const.Typography
|
|
20
20
|
import vn.momo.kits.const.scaleSize
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
|
|
22
23
|
|
|
23
24
|
@Composable
|
|
24
25
|
fun Badge(label: String = "Label", backgroundColor: Color? = null) {
|
|
26
|
+
val primaryColors = listOf(
|
|
27
|
+
Color(0xFFF0F0F0),
|
|
28
|
+
Color(0xFFEB2F96),
|
|
29
|
+
Color(0xFF962AF0),
|
|
30
|
+
Color(0xFF4E4BFF),
|
|
31
|
+
Color(0xFF007AFF),
|
|
32
|
+
Color(0xFF13C2C2),
|
|
33
|
+
Color(0xFF34C759),
|
|
34
|
+
Color(0xFFA0D911),
|
|
35
|
+
Color(0xFFFFCC00),
|
|
36
|
+
Color(0xFFFA8C16),
|
|
37
|
+
Color(0xFFFA541C),
|
|
38
|
+
Color(0xFFF5222D)
|
|
39
|
+
)
|
|
40
|
+
|
|
25
41
|
fun isNumber(label: String): Boolean {
|
|
26
42
|
val numberRegex = "^\\d+$".toRegex()
|
|
27
43
|
return numberRegex.matches(label)
|
|
@@ -22,6 +22,7 @@ import androidx.compose.ui.Modifier
|
|
|
22
22
|
import androidx.compose.ui.draw.clip
|
|
23
23
|
import androidx.compose.ui.graphics.Color
|
|
24
24
|
import androidx.compose.ui.text.TextStyle
|
|
25
|
+
import androidx.compose.ui.text.style.TextOverflow
|
|
25
26
|
import androidx.compose.ui.unit.Dp
|
|
26
27
|
import androidx.compose.ui.unit.dp
|
|
27
28
|
import vn.momo.kits.const.AppTheme
|
|
@@ -116,7 +117,7 @@ fun getTextColor(type: ButtonType): Color {
|
|
|
116
117
|
fun RenderTitle(size: Size, title: String = "", type: ButtonType) {
|
|
117
118
|
val style = getStyle(size)
|
|
118
119
|
val color = getTextColor(type)
|
|
119
|
-
Text(style = style, text = title, color = color)
|
|
120
|
+
Text(style = style, text = title, color = color, overflow = TextOverflow.Ellipsis, maxLines = 1)
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
@Composable
|
|
@@ -240,9 +241,10 @@ fun Button(
|
|
|
240
241
|
isRipple: Boolean = true,
|
|
241
242
|
useTintColor: Boolean = true,
|
|
242
243
|
isFull: Boolean = true,
|
|
244
|
+
modifier: Modifier = Modifier,
|
|
243
245
|
) {
|
|
244
246
|
val customModifier = if (isFull) {
|
|
245
|
-
|
|
247
|
+
modifier
|
|
246
248
|
.fillMaxWidth()
|
|
247
249
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
248
250
|
interactionSource = remember { MutableInteractionSource() },
|
|
@@ -252,7 +254,7 @@ fun Button(
|
|
|
252
254
|
)
|
|
253
255
|
|
|
254
256
|
} else {
|
|
255
|
-
|
|
257
|
+
modifier
|
|
256
258
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
257
259
|
interactionSource = remember { MutableInteractionSource() },
|
|
258
260
|
indication = if (isRipple) rememberRipple() else null,
|
|
@@ -285,4 +287,4 @@ fun Button(
|
|
|
285
287
|
iconRight = iconRight
|
|
286
288
|
)
|
|
287
289
|
}
|
|
288
|
-
}
|
|
290
|
+
}
|
|
@@ -11,8 +11,7 @@ import androidx.compose.ui.graphics.ColorFilter
|
|
|
11
11
|
import androidx.compose.ui.layout.ContentScale
|
|
12
12
|
import androidx.compose.ui.unit.Dp
|
|
13
13
|
import androidx.compose.ui.unit.dp
|
|
14
|
-
import
|
|
15
|
-
import com.skydoves.landscapist.coil3.CoilImage
|
|
14
|
+
import coil3.compose.AsyncImage
|
|
16
15
|
import vn.momo.kits.const.AppTheme
|
|
17
16
|
import vn.momo.kits.utils.Icons
|
|
18
17
|
|
|
@@ -29,13 +28,12 @@ fun Icon(
|
|
|
29
28
|
Icons[source]
|
|
30
29
|
}
|
|
31
30
|
Box(modifier.size(size), contentAlignment = Alignment.Center) {
|
|
32
|
-
|
|
31
|
+
AsyncImage(
|
|
33
32
|
modifier = Modifier.fillMaxSize(),
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
imageModel = { icon },
|
|
33
|
+
model = icon,
|
|
34
|
+
contentDescription = null,
|
|
35
|
+
contentScale = ContentScale.Fit,
|
|
36
|
+
colorFilter = color?.let { ColorFilter.tint(it) }
|
|
39
37
|
)
|
|
40
38
|
}
|
|
41
39
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
package vn.momo.kits.components
|
|
2
2
|
|
|
3
|
+
import androidx.compose.foundation.layout.Box
|
|
3
4
|
import androidx.compose.runtime.Composable
|
|
5
|
+
import androidx.compose.runtime.getValue
|
|
6
|
+
import androidx.compose.runtime.mutableStateOf
|
|
7
|
+
import androidx.compose.runtime.remember
|
|
8
|
+
import androidx.compose.runtime.setValue
|
|
4
9
|
import androidx.compose.ui.Alignment
|
|
5
10
|
import androidx.compose.ui.Modifier
|
|
6
11
|
import androidx.compose.ui.graphics.ColorFilter
|
|
7
12
|
import androidx.compose.ui.graphics.DefaultAlpha
|
|
8
13
|
import androidx.compose.ui.graphics.painter.Painter
|
|
9
14
|
import androidx.compose.ui.layout.ContentScale
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
15
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
16
|
+
import androidx.compose.ui.semantics.semantics
|
|
17
|
+
import androidx.compose.ui.semantics.testTag
|
|
18
|
+
import coil3.compose.AsyncImage
|
|
13
19
|
import vn.momo.kits.const.AppTheme
|
|
14
20
|
|
|
15
21
|
data class Options(
|
|
@@ -19,37 +25,54 @@ data class Options(
|
|
|
19
25
|
val alpha: Float = DefaultAlpha,
|
|
20
26
|
)
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
enum class ImageState {
|
|
29
|
+
Loading, Success, Error
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
@Composable
|
|
24
33
|
fun Image(
|
|
25
|
-
source:
|
|
34
|
+
source: Any,
|
|
26
35
|
modifier: Modifier = Modifier,
|
|
27
36
|
options: Options? = null,
|
|
28
37
|
loading: Boolean = true,
|
|
29
38
|
) {
|
|
30
|
-
|
|
39
|
+
modifier.semantics {contentDescription = "img|$source"; testTag = "img|$source"}
|
|
40
|
+
var imageOptions = Options()
|
|
41
|
+
var imageState by remember { mutableStateOf(ImageState.Loading) }
|
|
42
|
+
|
|
31
43
|
options?.let {
|
|
32
|
-
imageOptions =
|
|
44
|
+
imageOptions = Options(
|
|
33
45
|
alignment = options.alignment,
|
|
34
46
|
contentScale = options.contentScale,
|
|
35
47
|
colorFilter = options.colorFilter,
|
|
36
48
|
alpha = DefaultAlpha,
|
|
37
49
|
)
|
|
38
50
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
|
|
52
|
+
Box(modifier = modifier) {
|
|
53
|
+
AsyncImage(
|
|
54
|
+
modifier = modifier,
|
|
55
|
+
model = source,
|
|
56
|
+
contentDescription = null,
|
|
57
|
+
contentScale = imageOptions.contentScale,
|
|
58
|
+
alignment = imageOptions.alignment,
|
|
59
|
+
colorFilter = imageOptions.colorFilter,
|
|
60
|
+
alpha = imageOptions.alpha,
|
|
61
|
+
onLoading = { imageState = ImageState.Loading },
|
|
62
|
+
onSuccess = { imageState = ImageState.Success },
|
|
63
|
+
onError = { imageState = ImageState.Error },
|
|
64
|
+
)
|
|
65
|
+
when (imageState) {
|
|
66
|
+
ImageState.Loading -> Skeleton()
|
|
67
|
+
ImageState.Error -> Icon(
|
|
48
68
|
source = "media_fail",
|
|
49
69
|
color = AppTheme.current.colors.text.disable,
|
|
70
|
+
modifier = modifier
|
|
50
71
|
)
|
|
72
|
+
ImageState.Success -> {}
|
|
51
73
|
}
|
|
52
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
}
|
|
54
77
|
|
|
55
78
|
@Composable
|