@momo-kits/native-kits 0.89.19 → 0.89.21
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 +11 -15
- 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 +71 -27
- 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 +0 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +6 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +37 -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 +0 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -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/gradle.properties +1 -1
- 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/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)
|
|
@@ -224,8 +224,6 @@ fun getTypeStyle(
|
|
|
224
224
|
* @param enabled controls the enabled state of this button. When `false`,
|
|
225
225
|
* this component will not respond to user input, and it will appear
|
|
226
226
|
* visually disabled and disabled to accessibility services.
|
|
227
|
-
* @param isRipple [Boolean] controls the ripple animation of button. When
|
|
228
|
-
* `false`, the button won't have ripple animation.
|
|
229
227
|
* @param useTintColor [Boolean] controls color of the icon.
|
|
230
228
|
*/
|
|
231
229
|
@Composable
|
|
@@ -238,7 +236,6 @@ fun Button(
|
|
|
238
236
|
title: String = "Button",
|
|
239
237
|
loading: Boolean = false,
|
|
240
238
|
enabled: Boolean = true,
|
|
241
|
-
isRipple: Boolean = true,
|
|
242
239
|
useTintColor: Boolean = true,
|
|
243
240
|
isFull: Boolean = true,
|
|
244
241
|
modifier: Modifier = Modifier,
|
|
@@ -247,8 +244,6 @@ fun Button(
|
|
|
247
244
|
modifier
|
|
248
245
|
.fillMaxWidth()
|
|
249
246
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
250
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
251
|
-
indication = if (isRipple) rememberRipple() else null,
|
|
252
247
|
enabled = enabled,
|
|
253
248
|
onClick = onClick
|
|
254
249
|
)
|
|
@@ -256,8 +251,6 @@ fun Button(
|
|
|
256
251
|
} else {
|
|
257
252
|
modifier
|
|
258
253
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
259
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
260
|
-
indication = if (isRipple) rememberRipple() else null,
|
|
261
254
|
enabled = enabled,
|
|
262
255
|
onClick = onClick
|
|
263
256
|
)
|
|
@@ -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
|
}
|
|
@@ -110,8 +110,6 @@ fun IconButton(
|
|
|
110
110
|
.then(getIconStyle(type))
|
|
111
111
|
.clip(RoundedCornerShape(size.value.radius))
|
|
112
112
|
.clickable(
|
|
113
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
114
|
-
indication = rememberRipple(),
|
|
115
113
|
enabled = type == ButtonType.DISABLED,
|
|
116
114
|
onClick = onClick
|
|
117
115
|
),
|
|
@@ -1,6 +1,11 @@
|
|
|
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
|
|
@@ -10,9 +15,8 @@ import androidx.compose.ui.layout.ContentScale
|
|
|
10
15
|
import androidx.compose.ui.semantics.contentDescription
|
|
11
16
|
import androidx.compose.ui.semantics.semantics
|
|
12
17
|
import androidx.compose.ui.semantics.testTag
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import org.jetbrains.compose.resources.ExperimentalResourceApi
|
|
18
|
+
import androidx.compose.ui.unit.dp
|
|
19
|
+
import coil3.compose.AsyncImage
|
|
16
20
|
import vn.momo.kits.const.AppTheme
|
|
17
21
|
|
|
18
22
|
data class Options(
|
|
@@ -22,38 +26,54 @@ data class Options(
|
|
|
22
26
|
val alpha: Float = DefaultAlpha,
|
|
23
27
|
)
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
enum class ImageState {
|
|
30
|
+
Loading, Success, Error
|
|
31
|
+
}
|
|
32
|
+
|
|
26
33
|
@Composable
|
|
27
34
|
fun Image(
|
|
28
|
-
source:
|
|
35
|
+
source: Any,
|
|
29
36
|
modifier: Modifier = Modifier,
|
|
30
37
|
options: Options? = null,
|
|
31
38
|
loading: Boolean = true,
|
|
32
39
|
) {
|
|
33
40
|
modifier.semantics {contentDescription = "img|$source"; testTag = "img|$source"}
|
|
34
|
-
var imageOptions =
|
|
41
|
+
var imageOptions = Options()
|
|
42
|
+
var imageState by remember { mutableStateOf(ImageState.Loading) }
|
|
43
|
+
|
|
35
44
|
options?.let {
|
|
36
|
-
imageOptions =
|
|
45
|
+
imageOptions = Options(
|
|
37
46
|
alignment = options.alignment,
|
|
38
47
|
contentScale = options.contentScale,
|
|
39
48
|
colorFilter = options.colorFilter,
|
|
40
49
|
alpha = DefaultAlpha,
|
|
41
50
|
)
|
|
42
51
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
|
|
53
|
+
Box(modifier = modifier) {
|
|
54
|
+
AsyncImage(
|
|
55
|
+
modifier = modifier,
|
|
56
|
+
model = source,
|
|
57
|
+
contentDescription = null,
|
|
58
|
+
contentScale = imageOptions.contentScale,
|
|
59
|
+
alignment = imageOptions.alignment,
|
|
60
|
+
colorFilter = imageOptions.colorFilter,
|
|
61
|
+
alpha = imageOptions.alpha,
|
|
62
|
+
onLoading = { imageState = ImageState.Loading },
|
|
63
|
+
onSuccess = { imageState = ImageState.Success },
|
|
64
|
+
onError = { imageState = ImageState.Error },
|
|
65
|
+
)
|
|
66
|
+
when (imageState) {
|
|
67
|
+
ImageState.Loading -> if (loading) Skeleton()
|
|
68
|
+
ImageState.Error -> Icon(
|
|
52
69
|
source = "media_fail",
|
|
53
70
|
color = AppTheme.current.colors.text.disable,
|
|
71
|
+
modifier = modifier
|
|
54
72
|
)
|
|
73
|
+
ImageState.Success -> {}
|
|
55
74
|
}
|
|
56
|
-
|
|
75
|
+
}
|
|
76
|
+
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
@Composable
|