@momo-kits/native-kits 0.156.6-sp.1-debug → 0.156.6-sp.2-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/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +9 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +19 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +198 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +12 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +29 -12
- package/package.json +1 -1
package/compose/build.gradle.kts
CHANGED
|
@@ -370,9 +370,14 @@ private class LiteScreenHeaderPolicy(
|
|
|
370
370
|
maxWidth = (realConstraints.maxWidth * (1 - scrollPercent)).toInt()
|
|
371
371
|
.coerceAtLeast(minWidth)
|
|
372
372
|
)
|
|
373
|
-
} else
|
|
374
|
-
|
|
375
|
-
|
|
373
|
+
} else {
|
|
374
|
+
var spaceConsumed = 0
|
|
375
|
+
if (backIconPlaceable.safeWidth != 0) spaceConsumed += backIconPlaceable.safeWidth + spacing12
|
|
376
|
+
if (headerRightPlaceable.safeWidth != 0) spaceConsumed += headerRightPlaceable.safeWidth + spacing12
|
|
377
|
+
realConstraints.copy(
|
|
378
|
+
maxWidth = realConstraints.maxWidth - spaceConsumed
|
|
379
|
+
)
|
|
380
|
+
}
|
|
376
381
|
val inputSearchPlaceable = measurables.find { it.layoutId == HeaderId.INPUT_SEARCH_ID }
|
|
377
382
|
?.measure(inputSearchConstraints)
|
|
378
383
|
val titlePlaceable = measurables.find { it.layoutId == HeaderId.TITLE_ID }?.measure(
|
|
@@ -516,7 +521,7 @@ private fun LiteInputSearch(
|
|
|
516
521
|
|
|
517
522
|
val isShowBtnText by remember(inputSearchProps.isShowBtnText, inputSearchProps.btnText) {
|
|
518
523
|
derivedStateOf {
|
|
519
|
-
inputSearchProps.isShowBtnText && inputSearchProps.btnText.isNullOrEmpty()
|
|
524
|
+
inputSearchProps.isShowBtnText && !inputSearchProps.btnText.isNullOrEmpty()
|
|
520
525
|
}
|
|
521
526
|
}
|
|
522
527
|
val inputFieldStyle = remember(theme) {
|
|
@@ -23,7 +23,7 @@ import vn.momo.kits.modifier.conditional
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
@Composable
|
|
26
|
-
fun Badge(label: String = "Label", backgroundColor: Color? = null) {
|
|
26
|
+
fun Badge(label: String = "Label", backgroundColor: Color? = null, modifier: Modifier? = null) {
|
|
27
27
|
val primaryColors = listOf(
|
|
28
28
|
Color(0xFFF0F0F0),
|
|
29
29
|
Color(0xFFEB2F96),
|
|
@@ -63,21 +63,23 @@ fun Badge(label: String = "Label", backgroundColor: Color? = null) {
|
|
|
63
63
|
}
|
|
64
64
|
val scaleSize = scaleSize(16f)
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
if (modifier != null) {
|
|
67
|
+
Box(
|
|
68
|
+
modifier = modifier
|
|
69
|
+
.height(scaleSize.dp)
|
|
70
|
+
.widthIn(min = scaleSize.dp)
|
|
71
|
+
.background(color = badgeColor, shape = RoundedCornerShape(Radius.M))
|
|
72
|
+
.border(width = 1.dp, shape = RoundedCornerShape(Radius.M), color = Colors.black_01)
|
|
73
|
+
.conditional(IsShowBaseLineDebug) {
|
|
74
|
+
border(1.dp, Colors.blue_03)
|
|
75
|
+
}
|
|
76
|
+
.padding(horizontal = Spacing.XS), contentAlignment = Alignment.Center
|
|
77
|
+
) {
|
|
78
|
+
Text(
|
|
79
|
+
text = formatTitle(label),
|
|
80
|
+
color = Colors.black_01,
|
|
81
|
+
style = Typography.actionXxsBold
|
|
82
|
+
)
|
|
83
|
+
}
|
|
82
84
|
}
|
|
83
85
|
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
package vn.momo.kits.components
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.Canvas
|
|
4
|
+
import androidx.compose.foundation.background
|
|
5
|
+
import androidx.compose.foundation.border
|
|
6
|
+
import androidx.compose.foundation.layout.Box
|
|
7
|
+
import androidx.compose.foundation.layout.WindowInsets
|
|
8
|
+
import androidx.compose.foundation.layout.asPaddingValues
|
|
9
|
+
import androidx.compose.foundation.layout.fillMaxHeight
|
|
10
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
11
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
12
|
+
import androidx.compose.foundation.layout.height
|
|
13
|
+
import androidx.compose.foundation.layout.navigationBars
|
|
14
|
+
import androidx.compose.foundation.layout.padding
|
|
15
|
+
import androidx.compose.foundation.layout.width
|
|
16
|
+
import androidx.compose.runtime.Composable
|
|
17
|
+
import androidx.compose.ui.Alignment
|
|
18
|
+
import androidx.compose.ui.Modifier
|
|
19
|
+
import androidx.compose.ui.geometry.Offset
|
|
20
|
+
import androidx.compose.ui.graphics.Color
|
|
21
|
+
import androidx.compose.ui.graphics.PathEffect
|
|
22
|
+
import androidx.compose.ui.graphics.StrokeCap
|
|
23
|
+
import androidx.compose.ui.unit.dp
|
|
24
|
+
import io.ktor.util.Platform
|
|
25
|
+
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
26
|
+
import vn.momo.kits.const.Colors
|
|
27
|
+
import vn.momo.kits.modifier.conditional
|
|
28
|
+
import vn.momo.kits.platform.getPlatformName
|
|
29
|
+
import vn.momo.kits.platform.getStatusBarHeight
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A debug overlay that draws danger/warning baseline guides on top of the screen.
|
|
33
|
+
*
|
|
34
|
+
* Highlights safe-area boundaries, header regions, and bottom navigation zones
|
|
35
|
+
* using colored solid or dotted lines and semi-transparent red zones.
|
|
36
|
+
*
|
|
37
|
+
* @param enabled When `false` the composable renders nothing. Pass `false` when
|
|
38
|
+
* your QC automation flag is active to suppress the overlay.
|
|
39
|
+
*/
|
|
40
|
+
@Composable
|
|
41
|
+
fun BaselineView(enabled: Boolean = true) {
|
|
42
|
+
if (!enabled) return
|
|
43
|
+
|
|
44
|
+
val bottomInsetHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
|
|
45
|
+
val topInset = if (getPlatformName() == "Android") getStatusBarHeight() - 14.dp else getStatusBarHeight()
|
|
46
|
+
val bottomInset = if (getPlatformName() == "iOS") minOf(bottomInsetHeight, 21.dp) else bottomInsetHeight
|
|
47
|
+
|
|
48
|
+
Box(modifier = Modifier.fillMaxSize()) {
|
|
49
|
+
// Danger zones
|
|
50
|
+
Box(
|
|
51
|
+
modifier = Modifier
|
|
52
|
+
.fillMaxWidth()
|
|
53
|
+
.height(topInset)
|
|
54
|
+
.background(Color.Red.copy(alpha = 0.15f))
|
|
55
|
+
)
|
|
56
|
+
Box(
|
|
57
|
+
modifier = Modifier
|
|
58
|
+
.width(12.dp)
|
|
59
|
+
.fillMaxHeight()
|
|
60
|
+
.padding(top = topInset, bottom = bottomInset)
|
|
61
|
+
.background(Color.Red.copy(alpha = 0.15f))
|
|
62
|
+
)
|
|
63
|
+
Box(
|
|
64
|
+
modifier = Modifier
|
|
65
|
+
.width(12.dp)
|
|
66
|
+
.fillMaxHeight()
|
|
67
|
+
.padding(top = topInset, bottom = bottomInset)
|
|
68
|
+
.background(Color.Red.copy(alpha = 0.15f))
|
|
69
|
+
.align(Alignment.TopEnd)
|
|
70
|
+
)
|
|
71
|
+
Box(
|
|
72
|
+
modifier = Modifier
|
|
73
|
+
.fillMaxWidth()
|
|
74
|
+
.height(bottomInset)
|
|
75
|
+
.background(Color.Red.copy(alpha = 0.15f))
|
|
76
|
+
.align(Alignment.BottomCenter)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// Danger lines
|
|
80
|
+
BaselineDottedLine(
|
|
81
|
+
Modifier
|
|
82
|
+
.padding(top = topInset)
|
|
83
|
+
.fillMaxWidth(),
|
|
84
|
+
isDotted = false,
|
|
85
|
+
color = Color(0xFFE400FF)
|
|
86
|
+
)
|
|
87
|
+
BaselineDottedLine(
|
|
88
|
+
Modifier
|
|
89
|
+
.padding(top = topInset + 52.dp)
|
|
90
|
+
.fillMaxWidth(),
|
|
91
|
+
color = Color(0xFFE400FF)
|
|
92
|
+
)
|
|
93
|
+
BaselineDottedLine(
|
|
94
|
+
Modifier
|
|
95
|
+
.padding(top = topInset + 104.dp)
|
|
96
|
+
.fillMaxWidth(),
|
|
97
|
+
color = Color(0xFFE400FF)
|
|
98
|
+
)
|
|
99
|
+
BaselineDottedLine(
|
|
100
|
+
Modifier
|
|
101
|
+
.padding(bottom = bottomInset + 64.dp)
|
|
102
|
+
.fillMaxWidth()
|
|
103
|
+
.align(Alignment.BottomCenter),
|
|
104
|
+
color = Color(0xFFE400FF)
|
|
105
|
+
)
|
|
106
|
+
BaselineDottedLine(
|
|
107
|
+
Modifier
|
|
108
|
+
.padding(bottom = bottomInset)
|
|
109
|
+
.fillMaxWidth()
|
|
110
|
+
.align(Alignment.BottomCenter),
|
|
111
|
+
isDotted = false,
|
|
112
|
+
color = Color(0xFFE400FF)
|
|
113
|
+
)
|
|
114
|
+
BaselineDottedLine(
|
|
115
|
+
Modifier
|
|
116
|
+
.padding(start = 12.dp)
|
|
117
|
+
.fillMaxHeight(),
|
|
118
|
+
orientation = BaselineOrientation.Vertical,
|
|
119
|
+
isDotted = false,
|
|
120
|
+
color = Color(0xFFE400FF)
|
|
121
|
+
)
|
|
122
|
+
BaselineDottedLine(
|
|
123
|
+
Modifier
|
|
124
|
+
.padding(end = 12.dp)
|
|
125
|
+
.fillMaxHeight()
|
|
126
|
+
.align(Alignment.BottomEnd),
|
|
127
|
+
orientation = BaselineOrientation.Vertical,
|
|
128
|
+
isDotted = false,
|
|
129
|
+
color = Color(0xFFE400FF)
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
// Warning lines
|
|
133
|
+
BaselineDottedLine(
|
|
134
|
+
Modifier
|
|
135
|
+
.padding(top = topInset + 26.dp)
|
|
136
|
+
.fillMaxWidth(),
|
|
137
|
+
color = Color(0xFFFF7A00)
|
|
138
|
+
)
|
|
139
|
+
BaselineDottedLine(
|
|
140
|
+
Modifier
|
|
141
|
+
.padding(bottom = bottomInset + 56.dp)
|
|
142
|
+
.fillMaxWidth()
|
|
143
|
+
.align(Alignment.BottomCenter),
|
|
144
|
+
color = Color(0xFFFFCC00)
|
|
145
|
+
)
|
|
146
|
+
BaselineDottedLine(
|
|
147
|
+
Modifier
|
|
148
|
+
.padding(bottom = bottomInset + 8.dp)
|
|
149
|
+
.fillMaxWidth()
|
|
150
|
+
.align(Alignment.BottomCenter),
|
|
151
|
+
color = Color(0xFFFFCC00)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
// Header background warning lines
|
|
155
|
+
BaselineDottedLine(
|
|
156
|
+
Modifier
|
|
157
|
+
.padding(start = 40.dp, top = topInset)
|
|
158
|
+
.height(52.dp),
|
|
159
|
+
color = Color(0xFF00C520),
|
|
160
|
+
orientation = BaselineOrientation.Vertical
|
|
161
|
+
)
|
|
162
|
+
BaselineDottedLine(
|
|
163
|
+
Modifier
|
|
164
|
+
.padding(start = 48.dp, top = topInset)
|
|
165
|
+
.height(52.dp),
|
|
166
|
+
color = Color(0xFF00C520),
|
|
167
|
+
orientation = BaselineOrientation.Vertical
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
enum class BaselineOrientation { Horizontal, Vertical }
|
|
173
|
+
|
|
174
|
+
@Composable
|
|
175
|
+
fun BaselineDottedLine(
|
|
176
|
+
modifier: Modifier = Modifier,
|
|
177
|
+
color: Color = Color.Red,
|
|
178
|
+
orientation: BaselineOrientation = BaselineOrientation.Horizontal,
|
|
179
|
+
isDotted: Boolean = true
|
|
180
|
+
) {
|
|
181
|
+
Canvas(modifier = modifier) {
|
|
182
|
+
val pathEffect = if (isDotted) PathEffect.dashPathEffect(floatArrayOf(8f, 8f)) else null
|
|
183
|
+
drawLine(
|
|
184
|
+
color = color,
|
|
185
|
+
start = if (orientation == BaselineOrientation.Horizontal) Offset(
|
|
186
|
+
0f,
|
|
187
|
+
size.height / 2
|
|
188
|
+
) else Offset(size.width / 2, 0f),
|
|
189
|
+
end = if (orientation == BaselineOrientation.Horizontal) Offset(
|
|
190
|
+
size.width,
|
|
191
|
+
size.height / 2
|
|
192
|
+
) else Offset(size.width / 2, size.height),
|
|
193
|
+
strokeWidth = 1.dp.toPx(),
|
|
194
|
+
pathEffect = pathEffect,
|
|
195
|
+
cap = StrokeCap.Round,
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -49,9 +49,20 @@ import vn.momo.kits.utils.formatNumberToMoney
|
|
|
49
49
|
|
|
50
50
|
class CustomConverter : VisualTransformation {
|
|
51
51
|
override fun filter(text: AnnotatedString): TransformedText {
|
|
52
|
-
if (text.text.isEmpty()
|
|
52
|
+
if (text.text.isEmpty()) {
|
|
53
|
+
return TransformedText(
|
|
54
|
+
AnnotatedString("0"),
|
|
55
|
+
object : OffsetMapping {
|
|
56
|
+
override fun originalToTransformed(offset: Int): Int = 0
|
|
57
|
+
override fun transformedToOriginal(offset: Int): Int = 0
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (text.text == "0") {
|
|
53
63
|
return TransformedText(AnnotatedString("0"), OffsetMapping.Identity)
|
|
54
64
|
}
|
|
65
|
+
|
|
55
66
|
val formattedText = formatNumberToMoney(text.text.toLong())
|
|
56
67
|
|
|
57
68
|
return TransformedText(
|
|
@@ -40,13 +40,15 @@ import vn.momo.kits.const.Colors
|
|
|
40
40
|
import vn.momo.kits.const.Radius
|
|
41
41
|
import vn.momo.kits.const.Spacing
|
|
42
42
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
43
|
+
import vn.momo.kits.components.BadgeDot
|
|
44
|
+
import vn.momo.kits.components.DotSize
|
|
43
45
|
import vn.momo.kits.const.Typography
|
|
44
46
|
import vn.momo.kits.modifier.conditional
|
|
45
47
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
46
48
|
import vn.momo.kits.platform.getScreenDimensions
|
|
47
49
|
|
|
48
50
|
val floatingButtonWidth = 75.dp
|
|
49
|
-
const val BOTTOM_TAB_BAR_HEIGHT =
|
|
51
|
+
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
50
52
|
|
|
51
53
|
@Composable
|
|
52
54
|
fun BottomTabBar(
|
|
@@ -142,6 +144,18 @@ fun RowScope.renderTabBarItem(
|
|
|
142
144
|
|
|
143
145
|
@Composable
|
|
144
146
|
fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
147
|
+
fun isNumber(label: String): Boolean {
|
|
148
|
+
val numberRegex = "^\\d+$".toRegex()
|
|
149
|
+
return numberRegex.matches(label)
|
|
150
|
+
}
|
|
151
|
+
fun formatLabel(label: String): String? {
|
|
152
|
+
if (isNumber(label) && label.toInt() == 0) {
|
|
153
|
+
return null
|
|
154
|
+
}
|
|
155
|
+
return label
|
|
156
|
+
}
|
|
157
|
+
val badgeLabel = item.badgeLabel?.let { formatLabel(it) }
|
|
158
|
+
|
|
145
159
|
Box(modifier = Modifier
|
|
146
160
|
.fillMaxSize()
|
|
147
161
|
.padding(horizontal = Spacing.XXS)
|
|
@@ -156,31 +170,34 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
|
156
170
|
Column(
|
|
157
171
|
modifier = Modifier
|
|
158
172
|
.fillMaxSize()
|
|
159
|
-
.padding(horizontal = Spacing.
|
|
173
|
+
.padding(horizontal = Spacing.S, vertical = Spacing.S)
|
|
160
174
|
.noFeedbackClickable {
|
|
161
175
|
onClick()
|
|
162
176
|
},
|
|
163
177
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
164
|
-
verticalArrangement = Arrangement.
|
|
178
|
+
verticalArrangement = Arrangement.Center
|
|
165
179
|
) {
|
|
166
180
|
Icon(
|
|
167
181
|
source = item.icon,
|
|
168
|
-
|
|
182
|
+
size = 28.dp,
|
|
183
|
+
modifier = Modifier.padding(Spacing.XS),
|
|
169
184
|
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint)
|
|
170
185
|
Text(
|
|
171
186
|
text = item.label,
|
|
172
187
|
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint,
|
|
173
|
-
style = Typography.labelXsMedium,
|
|
188
|
+
style = if (selected) Typography.labelXsMedium else Typography.descriptionXsRegular,
|
|
174
189
|
maxLines = 1,
|
|
175
190
|
overflow = TextOverflow.Ellipsis
|
|
176
191
|
)
|
|
177
192
|
}
|
|
178
|
-
if(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
if (badgeLabel != null) {
|
|
194
|
+
if (badgeLabel.isEmpty())
|
|
195
|
+
BadgeDot(
|
|
196
|
+
size = DotSize.Small,
|
|
197
|
+
modifier = Modifier.offset(x = 50.dp, y = (-48).dp)
|
|
198
|
+
)
|
|
199
|
+
else
|
|
200
|
+
Badge(badgeLabel, modifier = Modifier.offset(x = 44.dp, y = (-42).dp))
|
|
184
201
|
}
|
|
185
202
|
}
|
|
186
203
|
}
|
|
@@ -190,7 +207,7 @@ fun FloatingButton(data: BottomTabFloatingButton) {
|
|
|
190
207
|
Column(
|
|
191
208
|
modifier = Modifier
|
|
192
209
|
.width(floatingButtonWidth)
|
|
193
|
-
.padding(horizontal = Spacing.XXS)
|
|
210
|
+
.padding(horizontal = Spacing.XXS, vertical = Spacing.S)
|
|
194
211
|
.conditional(IsShowBaseLineDebug) {
|
|
195
212
|
border(1.dp, Colors.blue_03)
|
|
196
213
|
}
|