@momo-kits/native-kits 0.157.5-debug → 0.157.6-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compose/build.gradle.kts +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +7 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +123 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +224 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +348 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +256 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +494 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +131 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +215 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +531 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +192 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +5 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +2 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +5 -1
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +12 -0
- package/gradle.properties +1 -1
- package/ios/Popup/PopupPromotion.swift +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
package vn.momo.kits.components
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.tween
|
|
5
|
+
import androidx.compose.foundation.background
|
|
6
|
+
import androidx.compose.foundation.border
|
|
7
|
+
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
|
8
|
+
import androidx.compose.foundation.layout.Box
|
|
9
|
+
import androidx.compose.foundation.layout.Column
|
|
10
|
+
import androidx.compose.foundation.layout.Row
|
|
11
|
+
import androidx.compose.foundation.layout.fillMaxHeight
|
|
12
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
13
|
+
import androidx.compose.foundation.layout.height
|
|
14
|
+
import androidx.compose.foundation.layout.offset
|
|
15
|
+
import androidx.compose.foundation.layout.width
|
|
16
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
17
|
+
import androidx.compose.runtime.Composable
|
|
18
|
+
import androidx.compose.runtime.remember
|
|
19
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
20
|
+
import androidx.compose.ui.Alignment
|
|
21
|
+
import androidx.compose.ui.Modifier
|
|
22
|
+
import androidx.compose.ui.draw.clip
|
|
23
|
+
import androidx.compose.ui.graphics.Color
|
|
24
|
+
import androidx.compose.ui.input.pointer.pointerInput
|
|
25
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
26
|
+
import androidx.compose.ui.unit.Dp
|
|
27
|
+
import androidx.compose.ui.unit.IntOffset
|
|
28
|
+
import androidx.compose.ui.unit.dp
|
|
29
|
+
import kotlinx.coroutines.launch
|
|
30
|
+
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
31
|
+
import vn.momo.kits.const.AppTheme
|
|
32
|
+
import vn.momo.kits.const.Colors
|
|
33
|
+
import vn.momo.kits.const.Radius
|
|
34
|
+
import vn.momo.kits.const.Spacing
|
|
35
|
+
import vn.momo.kits.const.Typography
|
|
36
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
37
|
+
import vn.momo.kits.modifier.conditional
|
|
38
|
+
import kotlin.math.roundToInt
|
|
39
|
+
|
|
40
|
+
data class SwipeAction(
|
|
41
|
+
val label: String = "",
|
|
42
|
+
val icon: String = "",
|
|
43
|
+
val onPress: () -> Unit = {},
|
|
44
|
+
val backgroundColor: Color? = null,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
private val ACTION_WIDTH = 56.dp
|
|
48
|
+
|
|
49
|
+
@Composable
|
|
50
|
+
fun Swipe(
|
|
51
|
+
modifier: Modifier = Modifier,
|
|
52
|
+
leftActions: List<SwipeAction> = emptyList(),
|
|
53
|
+
rightActions: List<SwipeAction> = emptyList(),
|
|
54
|
+
height: Dp = 56.dp,
|
|
55
|
+
itemRadius: Dp = 0.dp,
|
|
56
|
+
onSwipeableOpen: () -> Unit = {},
|
|
57
|
+
onSwipeableClose: () -> Unit = {},
|
|
58
|
+
onSwipeableLeftOpen: () -> Unit = {},
|
|
59
|
+
onSwipeableRightOpen: () -> Unit = {},
|
|
60
|
+
content: @Composable () -> Unit = {},
|
|
61
|
+
) {
|
|
62
|
+
val theme = AppTheme.current
|
|
63
|
+
val density = LocalDensity.current
|
|
64
|
+
val scope = rememberCoroutineScope()
|
|
65
|
+
|
|
66
|
+
val left = leftActions.take(3)
|
|
67
|
+
val right = rightActions.take(3)
|
|
68
|
+
|
|
69
|
+
val leftWidthPx = with(density) { (ACTION_WIDTH * left.size).toPx() }
|
|
70
|
+
val rightWidthPx = with(density) { (ACTION_WIDTH * right.size).toPx() }
|
|
71
|
+
|
|
72
|
+
val offsetX = remember { Animatable(0f) }
|
|
73
|
+
|
|
74
|
+
val shape = remember(itemRadius) {
|
|
75
|
+
if (itemRadius > 0.dp) RoundedCornerShape(itemRadius) else RoundedCornerShape(0.dp)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fun snapToClosest() {
|
|
79
|
+
scope.launch {
|
|
80
|
+
val current = offsetX.value
|
|
81
|
+
val target = when {
|
|
82
|
+
current > leftWidthPx * 0.5f && left.isNotEmpty() -> {
|
|
83
|
+
onSwipeableLeftOpen()
|
|
84
|
+
onSwipeableOpen()
|
|
85
|
+
leftWidthPx
|
|
86
|
+
}
|
|
87
|
+
current < -rightWidthPx * 0.5f && right.isNotEmpty() -> {
|
|
88
|
+
onSwipeableRightOpen()
|
|
89
|
+
onSwipeableOpen()
|
|
90
|
+
-rightWidthPx
|
|
91
|
+
}
|
|
92
|
+
else -> {
|
|
93
|
+
onSwipeableClose()
|
|
94
|
+
0f
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
offsetX.animateTo(target, tween(200))
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fun close() {
|
|
102
|
+
scope.launch {
|
|
103
|
+
offsetX.animateTo(0f, tween(200))
|
|
104
|
+
onSwipeableClose()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Box(
|
|
109
|
+
modifier = modifier
|
|
110
|
+
.fillMaxWidth()
|
|
111
|
+
.height(height)
|
|
112
|
+
.conditional(IsShowBaseLineDebug) { border(1.dp, Colors.blue_03) }
|
|
113
|
+
) {
|
|
114
|
+
// Left actions
|
|
115
|
+
if (left.isNotEmpty()) {
|
|
116
|
+
Row(
|
|
117
|
+
modifier = Modifier
|
|
118
|
+
.align(Alignment.CenterStart)
|
|
119
|
+
.fillMaxHeight()
|
|
120
|
+
) {
|
|
121
|
+
left.forEach { action ->
|
|
122
|
+
SwipeActionButton(
|
|
123
|
+
action = action,
|
|
124
|
+
width = ACTION_WIDTH,
|
|
125
|
+
height = height,
|
|
126
|
+
shape = shape,
|
|
127
|
+
defaultColor = theme.colors.primary,
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Right actions
|
|
134
|
+
if (right.isNotEmpty()) {
|
|
135
|
+
Row(
|
|
136
|
+
modifier = Modifier
|
|
137
|
+
.align(Alignment.CenterEnd)
|
|
138
|
+
.fillMaxHeight()
|
|
139
|
+
) {
|
|
140
|
+
right.forEach { action ->
|
|
141
|
+
SwipeActionButton(
|
|
142
|
+
action = action,
|
|
143
|
+
width = ACTION_WIDTH,
|
|
144
|
+
height = height,
|
|
145
|
+
shape = shape,
|
|
146
|
+
defaultColor = theme.colors.error.primary,
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Main content
|
|
153
|
+
Box(
|
|
154
|
+
modifier = Modifier
|
|
155
|
+
.fillMaxWidth()
|
|
156
|
+
.height(height)
|
|
157
|
+
.offset { IntOffset(offsetX.value.roundToInt(), 0) }
|
|
158
|
+
.clip(shape)
|
|
159
|
+
.background(theme.colors.background.surface)
|
|
160
|
+
.pointerInput(left.size, right.size) {
|
|
161
|
+
detectHorizontalDragGestures(
|
|
162
|
+
onDragEnd = { snapToClosest() },
|
|
163
|
+
onDragCancel = { snapToClosest() },
|
|
164
|
+
) { _, dragAmount ->
|
|
165
|
+
scope.launch {
|
|
166
|
+
val newOffset = offsetX.value + dragAmount
|
|
167
|
+
val clamped = newOffset.coerceIn(-rightWidthPx, leftWidthPx)
|
|
168
|
+
offsetX.snapTo(clamped)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
) {
|
|
173
|
+
content()
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Composable
|
|
179
|
+
private fun SwipeActionButton(
|
|
180
|
+
action: SwipeAction,
|
|
181
|
+
width: Dp,
|
|
182
|
+
height: Dp,
|
|
183
|
+
shape: RoundedCornerShape,
|
|
184
|
+
defaultColor: Color,
|
|
185
|
+
) {
|
|
186
|
+
val bgColor = action.backgroundColor ?: defaultColor
|
|
187
|
+
|
|
188
|
+
Box(
|
|
189
|
+
modifier = Modifier
|
|
190
|
+
.width(width)
|
|
191
|
+
.height(height)
|
|
192
|
+
.clip(shape)
|
|
193
|
+
.background(bgColor)
|
|
194
|
+
.activeOpacityClickable(onClick = action.onPress),
|
|
195
|
+
contentAlignment = Alignment.Center,
|
|
196
|
+
) {
|
|
197
|
+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
|
198
|
+
if (action.icon.isNotEmpty()) {
|
|
199
|
+
Icon(
|
|
200
|
+
source = action.icon,
|
|
201
|
+
size = 20.dp,
|
|
202
|
+
color = Colors.black_01,
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
if (action.label.isNotEmpty()) {
|
|
206
|
+
Text(
|
|
207
|
+
text = action.label,
|
|
208
|
+
style = Typography.labelSMedium,
|
|
209
|
+
color = Colors.black_01,
|
|
210
|
+
maxLines = 1,
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|