@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.
@@ -40,7 +40,7 @@ kotlin {
40
40
  }
41
41
 
42
42
  cocoapods {
43
- version = "0.156.6-sp.1-debug"
43
+ version = "0.156.6-sp.2-debug"
44
44
  summary = "IOS Shared module"
45
45
  homepage = "https://momo.vn"
46
46
  ios.deploymentTarget = "15.0"
@@ -370,9 +370,14 @@ private class LiteScreenHeaderPolicy(
370
370
  maxWidth = (realConstraints.maxWidth * (1 - scrollPercent)).toInt()
371
371
  .coerceAtLeast(minWidth)
372
372
  )
373
- } else realConstraints.copy(
374
- maxWidth = realConstraints.maxWidth - backIconPlaceable.safeWidth - headerRightPlaceable.safeWidth - spacing12 * 2
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
- Box(
67
- modifier = Modifier
68
- .height(scaleSize.dp)
69
- .widthIn(min = scaleSize.dp)
70
- .background(color = badgeColor, shape = RoundedCornerShape(Radius.M))
71
- .border(width = 1.dp, shape = RoundedCornerShape(Radius.M), color = Colors.black_01)
72
- .conditional(IsShowBaseLineDebug) {
73
- border(1.dp, Colors.blue_03)
74
- }
75
- .padding(horizontal = Spacing.XS), contentAlignment = Alignment.Center
76
- ) {
77
- Text(
78
- text = formatTitle(label),
79
- color = Colors.black_01,
80
- style = Typography.actionXxsBold
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() || text.text == "0") {
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 = 56
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.XXS)
173
+ .padding(horizontal = Spacing.S, vertical = Spacing.S)
160
174
  .noFeedbackClickable {
161
175
  onClick()
162
176
  },
163
177
  horizontalAlignment = Alignment.CenterHorizontally,
164
- verticalArrangement = Arrangement.Bottom
178
+ verticalArrangement = Arrangement.Center
165
179
  ) {
166
180
  Icon(
167
181
  source = item.icon,
168
- modifier = Modifier.weight(1f),
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(item.badgeLabel != null){
179
- Box(modifier = Modifier
180
- .offset(x = 44.dp, y = (-32).dp)
181
- ){
182
- Badge(item.badgeLabel)
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.156.6-sp.1-debug",
3
+ "version": "0.156.6-sp.2-debug",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},