@momo-kits/native-kits 0.89.30 → 0.89.31-beta.22

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.
Files changed (22) hide show
  1. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +10 -0
  2. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Components.kt +127 -71
  3. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +30 -20
  4. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +10 -10
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -1
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +8 -12
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +1 -1
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +1 -3
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +8 -1
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +8 -3
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +7 -1
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +58 -47
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +6 -6
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PromotionPopup.kt +2 -3
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +11 -2
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +3 -4
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +33 -22
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +4 -1
  20. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +6 -0
  21. package/local.properties +2 -2
  22. package/package.json +1 -1
@@ -3,9 +3,12 @@ package vn.momo.kits.platform
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.res.Resources
5
5
  import android.graphics.BlurMaskFilter
6
+ import androidx.compose.foundation.layout.WindowInsets
7
+ import androidx.compose.foundation.layout.navigationBars
6
8
  import androidx.compose.runtime.Composable
7
9
  import androidx.compose.ui.graphics.NativePaint
8
10
  import androidx.compose.ui.platform.LocalConfiguration
11
+ import androidx.compose.ui.platform.LocalDensity
9
12
  import androidx.compose.ui.unit.Dp
10
13
  import androidx.compose.ui.unit.dp
11
14
 
@@ -34,4 +37,11 @@ actual fun getStatusBarHeight(): Dp {
34
37
  "android"
35
38
  )
36
39
  return if(resourceId > 0) Resources.getSystem().getDimensionPixelSize(resourceId).dp else 0.dp
40
+ }
41
+
42
+ @Composable
43
+ actual fun getNavigationBarHeight(): Dp {
44
+ val density = LocalDensity.current
45
+ val navigationBarHeight = WindowInsets.navigationBars.getBottom(density)
46
+ return navigationBarHeight.dp
37
47
  }
@@ -1,10 +1,10 @@
1
1
  package vn.momo.kits.application
2
2
 
3
3
  import androidx.compose.animation.animateColorAsState
4
+ import androidx.compose.animation.core.animateFloatAsState
4
5
  import androidx.compose.foundation.background
5
6
  import androidx.compose.foundation.border
6
7
  import androidx.compose.foundation.clickable
7
- import androidx.compose.foundation.interaction.MutableInteractionSource
8
8
  import androidx.compose.foundation.layout.Arrangement
9
9
  import androidx.compose.foundation.layout.Box
10
10
  import androidx.compose.foundation.layout.BoxWithConstraints
@@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.padding
16
16
  import androidx.compose.foundation.layout.size
17
17
  import androidx.compose.foundation.layout.width
18
18
  import androidx.compose.foundation.shape.RoundedCornerShape
19
- import androidx.compose.material.ripple.rememberRipple
20
19
  import androidx.compose.runtime.Composable
21
20
  import androidx.compose.runtime.LaunchedEffect
22
21
  import androidx.compose.runtime.getValue
@@ -26,9 +25,13 @@ import androidx.compose.runtime.setValue
26
25
  import androidx.compose.runtime.snapshotFlow
27
26
  import androidx.compose.ui.Alignment
28
27
  import androidx.compose.ui.Modifier
28
+ import androidx.compose.ui.draw.alpha
29
+ import androidx.compose.ui.geometry.Offset
30
+ import androidx.compose.ui.graphics.Brush
29
31
  import androidx.compose.ui.graphics.Color
30
32
  import androidx.compose.ui.graphics.graphicsLayer
31
33
  import androidx.compose.ui.layout.ContentScale
34
+ import androidx.compose.ui.platform.LocalDensity
32
35
  import androidx.compose.ui.semantics.contentDescription
33
36
  import androidx.compose.ui.semantics.semantics
34
37
  import androidx.compose.ui.semantics.testTag
@@ -39,6 +42,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged
39
42
  import kotlinx.coroutines.flow.map
40
43
  import vn.momo.kits.components.Icon
41
44
  import vn.momo.kits.components.Image
45
+ import vn.momo.kits.components.InputSearch
46
+ import vn.momo.kits.components.InputSearchProps
42
47
  import vn.momo.kits.components.Options
43
48
  import vn.momo.kits.components.Text
44
49
  import vn.momo.kits.const.AppStatusBar
@@ -46,6 +51,7 @@ import vn.momo.kits.const.AppTheme
46
51
  import vn.momo.kits.const.Colors
47
52
  import vn.momo.kits.const.Spacing
48
53
  import vn.momo.kits.const.Typography
54
+ import vn.momo.kits.modifier.shadow
49
55
  import vn.momo.kits.platform.getStatusBarHeight
50
56
  import vn.momo.kits.utils.bottomBorder
51
57
 
@@ -60,41 +66,88 @@ data class AnimatedHeader(
60
66
  )
61
67
 
62
68
  @Composable
63
- fun HeaderImage(
69
+ fun HeaderBackground(
64
70
  headerType: HeaderType = HeaderType.DEFAULT,
65
- headerBackground: String?,
71
+ useShadow: Boolean? = true,
72
+ scrollState: Int
66
73
  ) {
67
74
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
75
+ val opacityAni by animateFloatAsState(
76
+ targetValue = (1 - (scrollState / 200f)).coerceIn(0f, 1f),
77
+ )
78
+
68
79
  when (headerType) {
69
80
  HeaderType.DEFAULT -> {
70
81
  val height = statusBarHeight + 52.dp
71
- Image(
72
- source = headerBackground ?: "",
73
- modifier = Modifier.fillMaxWidth().height(height),
74
- options = Options(
75
- contentScale = ContentScale.FillWidth
82
+ Box(
83
+ modifier = Modifier.fillMaxWidth().height(height)
84
+ .bottomBorder(
85
+ strokeWidth = 1.dp,
86
+ color = AppTheme.current.colors.border.default
87
+ )
88
+ ) {
89
+ Box(
90
+ modifier = Modifier
91
+ .height(height)
92
+ .fillMaxWidth()
93
+ .background(
94
+ Brush.linearGradient(
95
+ colors = listOf(
96
+ Color(0xFFFDCACE),
97
+ Color(0x00FDCACE)
98
+ ),
99
+ start = Offset(0f, 0f),
100
+ end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
101
+ )
102
+ )
76
103
  )
77
- )
78
- }
104
+ if (AppTheme.current.assets.headerBackground != null) {
105
+ Image(
106
+ source = AppTheme.current.assets.headerBackground!!,
107
+ modifier = Modifier.fillMaxWidth().height(height),
108
+ options = Options(
109
+ contentScale = ContentScale.FillWidth
110
+ )
111
+ )
112
+ }
113
+ }
79
114
 
80
- HeaderType.EXTENDED -> {
81
- Image(
82
- source = headerBackground ?: "",
83
- modifier = Modifier.fillMaxWidth(),
84
- options = Options(
85
- contentScale = ContentScale.FillWidth
86
- )
87
- )
88
115
  }
89
116
 
90
- HeaderType.SURFACE -> {
91
- val height = statusBarHeight + 52.dp
117
+ HeaderType.EXTENDED -> {
92
118
  Box(
93
- modifier = Modifier.fillMaxWidth().height(height)
94
- .background(AppTheme.current.colors.background.surface)
95
- .bottomBorder(
96
- strokeWidth = 2.dp,
97
- color = AppTheme.current.colors.border.default
119
+ modifier = Modifier.fillMaxWidth().height(154.dp)
120
+ .alpha(opacityAni)
121
+ .background(
122
+ Brush.linearGradient(
123
+ colors = listOf(
124
+ Color(0xFFFDCACE),
125
+ Color(0x00FDCACE)
126
+ ),
127
+ start = Offset(0f, 0f),
128
+ end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
129
+ )
130
+ )
131
+ ) {
132
+ if (AppTheme.current.assets.headerBackground != null) {
133
+ Image(
134
+ source = AppTheme.current.assets.headerBackground!!,
135
+ modifier = Modifier.fillMaxWidth().height(154.dp),
136
+ options = Options(
137
+ contentScale = ContentScale.FillWidth
138
+ )
139
+ )
140
+ }
141
+ }
142
+ Box(
143
+ modifier = Modifier.fillMaxWidth().height(statusBarHeight + 52.dp)
144
+ .alpha(1 - opacityAni)
145
+ .background(Colors.black_01)
146
+ .then(
147
+ if (useShadow == true) Modifier.shadow() else Modifier.bottomBorder(
148
+ 1.dp,
149
+ Colors.black_04
150
+ )
98
151
  )
99
152
  )
100
153
  }
@@ -115,25 +168,21 @@ fun Header(
115
168
  goBack: (() -> Unit) = { },
116
169
  opacity: Float? = null,
117
170
  animatedHeader: AnimatedHeader? = null,
118
- scrollState: Int = 0
171
+ useSearchInput: Boolean? = false,
172
+ scrollState: Int = 0,
173
+ inputSearchProps: InputSearchProps?
119
174
  ) {
120
175
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
121
- var tintIconColor = Colors.black_01
122
- var backgroundButton = Colors.black_20.copy(alpha = 0.4f)
123
- if (headerType == HeaderType.SURFACE) {
124
- tintIconColor = AppTheme.current.colors.text.default
125
- backgroundButton = Color.Transparent
126
- }
176
+ val tintIconColor = AppTheme.current.colors.text.default
177
+ val backgroundButton = Colors.black_01.copy(alpha = 0.2f)
127
178
 
128
179
  var colorFraction by remember { mutableStateOf(0f) }
129
180
 
130
181
  LaunchedEffect(scrollState) {
131
- if (headerType == HeaderType.SURFACE) {
132
- snapshotFlow { scrollState }
133
- .map { (it / 50f).coerceIn(0f, 1f) }
134
- .distinctUntilChanged()
135
- .collect { fraction -> colorFraction = fraction }
136
- }
182
+ snapshotFlow { scrollState }
183
+ .map { (it / 50f).coerceIn(0f, 1f) }
184
+ .distinctUntilChanged()
185
+ .collect { fraction -> colorFraction = fraction }
137
186
  }
138
187
 
139
188
  val tintIconColorAnim by animateColorAsState(
@@ -144,6 +193,14 @@ fun Header(
144
193
  )
145
194
  )
146
195
 
196
+ val backgroundSearch by animateColorAsState(
197
+ targetValue = animateColor(
198
+ Colors.black_01,
199
+ AppTheme.current.colors.background.default,
200
+ colorFraction
201
+ )
202
+ )
203
+
147
204
  if (headerType != HeaderType.NONE) {
148
205
  BoxWithConstraints(
149
206
  Modifier.height(statusBarHeight + 52.dp)
@@ -164,15 +221,11 @@ fun Header(
164
221
  modifier = Modifier
165
222
  .size(28.dp)
166
223
  .then(
167
- if (headerType == HeaderType.SURFACE) {
168
- Modifier.border(
169
- 0.5.dp,
170
- Colors.black_20.copy(alpha = 0.4f),
171
- RoundedCornerShape(100)
172
- )
173
- } else {
174
- Modifier
175
- }
224
+ Modifier.border(
225
+ 0.5.dp,
226
+ Colors.black_20.copy(alpha = 0.4f),
227
+ RoundedCornerShape(100)
228
+ )
176
229
  )
177
230
  .background(
178
231
  backgroundButton,
@@ -183,23 +236,24 @@ fun Header(
183
236
  )
184
237
  .padding(Spacing.XS)
185
238
  .semantics {
186
- contentDescription = "btn_navigation_back"; testTag =
187
- "btn_navigation_back"
239
+ testTag = "btn_navigation_back"
188
240
  },
189
241
  contentAlignment = Alignment.Center
190
242
  ) {
191
243
  Icon(
192
244
  source = "ic_back_ios",
193
- color = if (headerType == HeaderType.SURFACE && animatedHeader !== null) tintIconColorAnim else tintIconColor,
245
+ color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
194
246
  size = 20.dp,
195
247
  )
196
248
  }
197
249
  }
198
250
  }
199
- Box(Modifier.graphicsLayer {
200
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
201
- }) {
202
- headerRight?.invoke()
251
+ if (useSearchInput == false) {
252
+ Box(Modifier.graphicsLayer {
253
+ alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
254
+ }) {
255
+ headerRight?.invoke()
256
+ }
203
257
  }
204
258
  }
205
259
 
@@ -213,23 +267,25 @@ fun Header(
213
267
  if (isBack) {
214
268
  Spacer(Modifier.width(40.dp))
215
269
  }
216
- Box(
217
- Modifier.weight(1f).graphicsLayer {
218
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
219
- },
220
- contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
221
- ) {
222
- HeaderTitle(
223
- title = title,
224
- color = if (headerType == HeaderType.SURFACE && animatedHeader !== null) tintIconColorAnim else tintIconColor,
225
- modifier = Modifier.semantics {
226
- contentDescription = "title_navigation_header"
227
- testTag = "title_navigation_header"
228
- }
229
- )
270
+ if (useSearchInput == true && inputSearchProps != null) {
271
+ InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
230
272
  }
231
- if (isBack) {
232
- Spacer(Modifier.width(40.dp))
273
+ else{
274
+ Box(
275
+ Modifier.weight(1f).graphicsLayer {
276
+ alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
277
+ },
278
+ contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
279
+ ) {
280
+ HeaderTitle(
281
+ title = title,
282
+ color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
283
+ modifier = Modifier.semantics {
284
+ contentDescription = title
285
+ testTag = "title_navigation_header"
286
+ }
287
+ )
288
+ }
233
289
  }
234
290
  }
235
291
  }
@@ -1,6 +1,7 @@
1
1
  package vn.momo.kits.application
2
2
 
3
3
  import androidx.compose.animation.core.animateFloatAsState
4
+ import androidx.compose.foundation.ScrollState
4
5
  import androidx.compose.foundation.background
5
6
  import androidx.compose.foundation.gestures.detectTapGestures
6
7
  import androidx.compose.foundation.layout.Arrangement
@@ -24,21 +25,24 @@ import androidx.compose.ui.Modifier
24
25
  import androidx.compose.ui.graphics.Color
25
26
  import androidx.compose.ui.graphics.graphicsLayer
26
27
  import androidx.compose.ui.input.pointer.pointerInput
28
+ import androidx.compose.ui.layout.LayoutCoordinates
29
+ import androidx.compose.ui.layout.onGloballyPositioned
27
30
  import androidx.compose.ui.platform.LocalSoftwareKeyboardController
28
31
  import androidx.compose.ui.unit.Dp
29
32
  import androidx.compose.ui.unit.dp
30
33
  import androidx.compose.ui.unit.min
31
34
  import androidx.compose.ui.zIndex
35
+ import vn.momo.kits.components.InputSearchProps
32
36
  import vn.momo.kits.const.AppStatusBar
33
37
  import vn.momo.kits.const.AppTheme
34
38
  import vn.momo.kits.const.Colors
35
39
  import vn.momo.kits.const.Spacing
40
+ import vn.momo.kits.modifier.conditional
36
41
  import vn.momo.kits.modifier.shadow
37
42
  import vn.momo.kits.platform.getStatusBarHeight
38
43
 
39
44
  enum class HeaderType {
40
45
  DEFAULT,
41
- SURFACE,
42
46
  EXTENDED,
43
47
  NONE
44
48
  }
@@ -46,7 +50,6 @@ enum class HeaderType {
46
50
  @Composable
47
51
  fun Screen(
48
52
  backgroundColor: Color? = null,
49
- headerBackground: String? = null,
50
53
  isBack: Boolean = true,
51
54
  headerType: HeaderType = HeaderType.DEFAULT,
52
55
  verticalArrangement: Arrangement.Vertical = Arrangement.Top,
@@ -55,12 +58,17 @@ fun Screen(
55
58
  titlePosition: TitlePosition = TitlePosition.LEFT,
56
59
  goBack: (() -> Unit) = { },
57
60
  scrollable: Boolean = true,
61
+ scrollState: ScrollState = rememberScrollState(),
62
+ onContentLayout: ((LayoutCoordinates) -> Unit)? = null,
58
63
  useAvoidKeyboard: Boolean = true,
59
64
  footer: @Composable (() -> Unit)? = null,
60
65
  headerRight: @Composable (() -> Unit)? = null,
61
66
  fabProps: FabProps? = null,
62
67
  animatedHeader: AnimatedHeader? = null,
63
68
  layoutOffset: Dp = 56.dp,
69
+ useShadow: Boolean? = true,
70
+ useSearchInput: Boolean? = false,
71
+ inputSearchProps: InputSearchProps? = null,
64
72
  content: @Composable () -> Unit,
65
73
  ) {
66
74
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
@@ -75,7 +83,6 @@ fun Screen(
75
83
 
76
84
  val indicator = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
77
85
  val bottomPadding = min(indicator, 21.dp)
78
- val scrollState = rememberScrollState()
79
86
 
80
87
  val opacity by animateFloatAsState(
81
88
  targetValue = ((scrollState.value / 114f)).coerceIn(0f, 1f)
@@ -90,17 +97,17 @@ fun Screen(
90
97
  ) {
91
98
 
92
99
  if (animatedHeader === null) {
93
- HeaderImage(
94
- headerType,
95
- headerBackground ?: AppTheme.current.assets.headerBackground
96
- )
100
+ HeaderBackground(headerType = headerType, scrollState = scrollState.value)
97
101
  } else {
98
102
  Box(
99
- Modifier.zIndex(5f).background(Color.White.copy(alpha = opacity))
100
- .graphicsLayer { alpha = opacity }) {
101
- HeaderImage(
102
- headerType,
103
- headerBackground ?: AppTheme.current.assets.headerBackground
103
+ Modifier.zIndex(5f)
104
+ .background(Color.White.copy(alpha = opacity))
105
+ .graphicsLayer { alpha = opacity }
106
+ ) {
107
+ HeaderBackground(
108
+ headerType = headerType,
109
+ useShadow = useShadow,
110
+ scrollState = scrollState.value
104
111
  )
105
112
  }
106
113
  }
@@ -114,6 +121,8 @@ fun Screen(
114
121
  goBack = goBack,
115
122
  opacity = opacity,
116
123
  animatedHeader = animatedHeader,
124
+ useSearchInput = useSearchInput,
125
+ inputSearchProps = inputSearchProps,
117
126
  scrollState = scrollState.value
118
127
  )
119
128
 
@@ -129,9 +138,13 @@ fun Screen(
129
138
  ) {
130
139
 
131
140
  Column(
132
- modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize)
133
- .verticalScroll(scrollState) else
134
- Modifier.padding(bottom = keyboardSize),
141
+ modifier = Modifier
142
+ .conditional(scrollable) { weight(1f) }
143
+ .padding(bottom = keyboardSize)
144
+ .conditional(onContentLayout != null) {
145
+ onGloballyPositioned(onContentLayout ?: {})
146
+ }
147
+ .conditional(scrollable) { verticalScroll(scrollState) },
135
148
  verticalArrangement = verticalArrangement,
136
149
  horizontalAlignment = horizontalAlignment
137
150
  ) {
@@ -186,11 +199,8 @@ fun Footer(footer: @Composable (() -> Unit)? = null, keyboardSize: Dp = 0.dp, bo
186
199
  .background(AppTheme.current.colors.background.surface)
187
200
  ) {
188
201
  Box(
189
- Modifier
190
- .fillMaxWidth()
191
- .padding(vertical = Spacing.S, horizontal = Spacing.M)
192
- )
193
- {
202
+ Modifier.fillMaxWidth().padding(vertical = Spacing.S, horizontal = Spacing.M)
203
+ ) {
194
204
  footer?.invoke()
195
205
  }
196
206
  }
@@ -3,7 +3,6 @@ package vn.momo.kits.components
3
3
  import androidx.compose.foundation.background
4
4
  import androidx.compose.foundation.border
5
5
  import androidx.compose.foundation.clickable
6
- import androidx.compose.foundation.interaction.MutableInteractionSource
7
6
  import androidx.compose.foundation.layout.Arrangement
8
7
  import androidx.compose.foundation.layout.Box
9
8
  import androidx.compose.foundation.layout.Row
@@ -13,14 +12,15 @@ import androidx.compose.foundation.layout.height
13
12
  import androidx.compose.foundation.layout.padding
14
13
  import androidx.compose.foundation.layout.size
15
14
  import androidx.compose.foundation.shape.RoundedCornerShape
16
- import androidx.compose.material.ripple.rememberRipple
17
15
  import androidx.compose.material3.CircularProgressIndicator
18
16
  import androidx.compose.runtime.Composable
19
- import androidx.compose.runtime.remember
20
17
  import androidx.compose.ui.Alignment
21
18
  import androidx.compose.ui.Modifier
22
19
  import androidx.compose.ui.draw.clip
23
20
  import androidx.compose.ui.graphics.Color
21
+ import androidx.compose.ui.semantics.contentDescription
22
+ import androidx.compose.ui.semantics.semantics
23
+ import androidx.compose.ui.semantics.testTag
24
24
  import androidx.compose.ui.text.TextStyle
25
25
  import androidx.compose.ui.text.style.TextOverflow
26
26
  import androidx.compose.ui.unit.Dp
@@ -221,9 +221,6 @@ fun getTypeStyle(
221
221
  * @param iconLeft [String] the icon at the left of title
222
222
  * @param title [String] title of button
223
223
  * @param loading [Boolean] used when you want to use loading animation
224
- * @param enabled controls the enabled state of this button. When `false`,
225
- * this component will not respond to user input, and it will appear
226
- * visually disabled and disabled to accessibility services.
227
224
  * @param useTintColor [Boolean] controls color of the icon.
228
225
  */
229
226
  @Composable
@@ -235,23 +232,23 @@ fun Button(
235
232
  iconLeft: String = "",
236
233
  title: String = "Button",
237
234
  loading: Boolean = false,
238
- enabled: Boolean = true,
239
235
  useTintColor: Boolean = true,
240
236
  isFull: Boolean = true,
241
237
  modifier: Modifier = Modifier,
242
238
  ) {
239
+ val testId = "btn_${type.toString().lowercase()}_$title"
243
240
  val customModifier = if (isFull) {
244
241
  modifier
245
242
  .fillMaxWidth()
246
243
  .clip(RoundedCornerShape(size.value.radius)).clickable(
247
- enabled = enabled,
244
+ enabled = type != ButtonType.DISABLED,
248
245
  onClick = onClick
249
246
  )
250
247
 
251
248
  } else {
252
249
  modifier
253
250
  .clip(RoundedCornerShape(size.value.radius)).clickable(
254
- enabled = enabled,
251
+ enabled = type != ButtonType.DISABLED,
255
252
  onClick = onClick
256
253
  )
257
254
  }
@@ -261,7 +258,10 @@ fun Button(
261
258
  .padding(horizontal = size.value.padding)
262
259
  .defaultMinSize(
263
260
  minWidth = size.value.width
264
- ).height(size.value.height),
261
+ ).height(size.value.height)
262
+ .semantics {
263
+ contentDescription = title; testTag = testId
264
+ },
265
265
  horizontalArrangement = Arrangement.Center,
266
266
  verticalAlignment = Alignment.CenterVertically,
267
267
  ) {
@@ -33,7 +33,6 @@ fun CheckBox(
33
33
  var backgroundColor = AppTheme.current.colors.background.surface
34
34
  val iconSource = if (indeterminate) "minus" else "ic_checked"
35
35
 
36
-
37
36
  if (checked) {
38
37
  borderColor = AppTheme.current.colors.primary
39
38
  backgroundColor = AppTheme.current.colors.primary
@@ -1,17 +1,13 @@
1
1
  package vn.momo.kits.components
2
2
 
3
- import androidx.compose.foundation.layout.Box
4
- import androidx.compose.foundation.layout.fillMaxSize
5
3
  import androidx.compose.foundation.layout.size
6
4
  import androidx.compose.runtime.Composable
7
- import androidx.compose.ui.Alignment
8
5
  import androidx.compose.ui.Modifier
9
6
  import androidx.compose.ui.graphics.Color
10
7
  import androidx.compose.ui.graphics.ColorFilter
11
8
  import androidx.compose.ui.layout.ContentScale
12
9
  import androidx.compose.ui.unit.Dp
13
10
  import androidx.compose.ui.unit.dp
14
- import coil3.compose.AsyncImage
15
11
  import vn.momo.kits.const.AppTheme
16
12
  import vn.momo.kits.utils.Icons
17
13
 
@@ -25,16 +21,16 @@ fun Icon(
25
21
  val icon = if (source.contains("https")) {
26
22
  source
27
23
  } else {
28
- Icons[source]
24
+ Icons[source] ?: ""
29
25
  }
30
- Box(modifier.size(size), contentAlignment = Alignment.Center) {
31
- AsyncImage(
32
- modifier = Modifier.fillMaxSize(),
33
- model = icon,
34
- contentDescription = null,
26
+ Image(
27
+ modifier = modifier.size(size),
28
+ source = icon,
29
+ loading = false,
30
+ options = Options(
35
31
  contentScale = ContentScale.Fit,
36
32
  colorFilter = color?.let { ColorFilter.tint(it) }
37
- )
38
- }
33
+ ),
34
+ )
39
35
  }
40
36
 
@@ -110,7 +110,7 @@ fun IconButton(
110
110
  .then(getIconStyle(type))
111
111
  .clip(RoundedCornerShape(size.value.radius))
112
112
  .clickable(
113
- enabled = type == ButtonType.DISABLED,
113
+ enabled = type != ButtonType.DISABLED,
114
114
  onClick = onClick
115
115
  ),
116
116
  contentAlignment = Alignment.Center
@@ -15,7 +15,6 @@ import androidx.compose.ui.layout.ContentScale
15
15
  import androidx.compose.ui.semantics.contentDescription
16
16
  import androidx.compose.ui.semantics.semantics
17
17
  import androidx.compose.ui.semantics.testTag
18
- import androidx.compose.ui.unit.dp
19
18
  import coil3.compose.AsyncImage
20
19
  import vn.momo.kits.const.AppTheme
21
20
 
@@ -37,7 +36,6 @@ fun Image(
37
36
  options: Options? = null,
38
37
  loading: Boolean = true,
39
38
  ) {
40
- modifier.semantics {contentDescription = "img|$source"; testTag = "img|$source"}
41
39
  var imageOptions = Options()
42
40
  var imageState by remember { mutableStateOf(ImageState.Loading) }
43
41
 
@@ -52,7 +50,7 @@ fun Image(
52
50
 
53
51
  Box(modifier = modifier) {
54
52
  AsyncImage(
55
- modifier = modifier,
53
+ modifier = Modifier.matchParentSize().semantics {contentDescription = "img|$source"; testTag = "img|$source"},
56
54
  model = source,
57
55
  contentDescription = null,
58
56
  contentScale = imageOptions.contentScale,
@@ -29,6 +29,9 @@ import androidx.compose.ui.Alignment
29
29
  import androidx.compose.ui.Modifier
30
30
  import androidx.compose.ui.focus.onFocusChanged
31
31
  import androidx.compose.ui.graphics.Color
32
+ import androidx.compose.ui.semantics.contentDescription
33
+ import androidx.compose.ui.semantics.semantics
34
+ import androidx.compose.ui.semantics.testTag
32
35
  import androidx.compose.ui.text.TextStyle
33
36
  import androidx.compose.ui.text.font.FontWeight
34
37
  import androidx.compose.ui.text.input.KeyboardType
@@ -198,7 +201,11 @@ fun Input(
198
201
  iconTintColor = disabledColor
199
202
  }
200
203
 
201
- Column {
204
+ val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
205
+
206
+ Column(modifier = Modifier.semantics {
207
+ contentDescription = floatingValue; testTag = testId
208
+ }) {
202
209
  BasicTextField(
203
210
  enabled = !disabled,
204
211
  readOnly = readOnly,
@@ -17,10 +17,12 @@ import androidx.compose.runtime.MutableState
17
17
  import androidx.compose.runtime.getValue
18
18
  import androidx.compose.runtime.mutableStateOf
19
19
  import androidx.compose.runtime.remember
20
- import androidx.compose.runtime.setValue
21
20
  import androidx.compose.ui.Alignment
22
21
  import androidx.compose.ui.Modifier
23
22
  import androidx.compose.ui.graphics.Color
23
+ import androidx.compose.ui.semantics.contentDescription
24
+ import androidx.compose.ui.semantics.semantics
25
+ import androidx.compose.ui.semantics.testTag
24
26
  import androidx.compose.ui.text.TextStyle
25
27
  import androidx.compose.ui.unit.dp
26
28
  import androidx.compose.ui.unit.sp
@@ -51,7 +53,7 @@ fun InputDropDown(
51
53
  loading: Boolean = false,
52
54
  required: Boolean = false,
53
55
  ) {
54
- var isFocused by remember { mutableStateOf(false) }
56
+ val isFocused by remember { mutableStateOf(false) }
55
57
 
56
58
  val disabledColor = AppTheme.current.colors.text.disable
57
59
  var textColor = AppTheme.current.colors.text.default
@@ -72,8 +74,11 @@ fun InputDropDown(
72
74
  iconTintColor = disabledColor
73
75
  }
74
76
 
77
+ val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
75
78
 
76
- Column(modifier = Modifier.clickable(enabled = !disabled, onClick = onPress)) {
79
+ Column(modifier = Modifier.clickable(enabled = !disabled, onClick = onPress).semantics {
80
+ contentDescription = floatingValue; testTag = testId
81
+ }) {
77
82
  Box {
78
83
  if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
79
84
  Box(
@@ -27,6 +27,9 @@ import androidx.compose.ui.Alignment
27
27
  import androidx.compose.ui.Modifier
28
28
  import androidx.compose.ui.focus.onFocusChanged
29
29
  import androidx.compose.ui.graphics.Color
30
+ import androidx.compose.ui.semantics.contentDescription
31
+ import androidx.compose.ui.semantics.semantics
32
+ import androidx.compose.ui.semantics.testTag
30
33
  import androidx.compose.ui.text.AnnotatedString
31
34
  import androidx.compose.ui.text.TextStyle
32
35
  import androidx.compose.ui.text.input.KeyboardType
@@ -104,8 +107,11 @@ fun InputMoney(
104
107
  iconTintColor = disabledColor
105
108
  }
106
109
 
110
+ val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
107
111
 
108
- Column {
112
+ Column(modifier = Modifier.semantics {
113
+ contentDescription = floatingValue; testTag = testId
114
+ }) {
109
115
  BasicTextField(
110
116
  enabled = !disabled,
111
117
  singleLine = true,
@@ -1,7 +1,6 @@
1
1
  package vn.momo.kits.components
2
2
 
3
3
  import androidx.compose.foundation.background
4
- import androidx.compose.foundation.border
5
4
  import androidx.compose.foundation.clickable
6
5
  import androidx.compose.foundation.interaction.MutableInteractionSource
7
6
  import androidx.compose.foundation.layout.Arrangement
@@ -33,13 +32,19 @@ import androidx.compose.ui.text.input.KeyboardType
33
32
  import androidx.compose.ui.unit.dp
34
33
  import androidx.compose.ui.unit.sp
35
34
  import vn.momo.kits.const.AppTheme
35
+ import vn.momo.kits.const.Colors
36
36
  import vn.momo.kits.const.Radius
37
37
  import vn.momo.kits.const.Spacing
38
38
  import vn.momo.kits.const.Typography
39
39
  import vn.momo.kits.utils.ifTrue
40
40
 
41
41
  @Composable
42
- fun RenderRightIconSearch(loading: Boolean, icon: String, color: Color, onClick: () -> Unit) {
42
+ fun RenderRightIconSearch(
43
+ loading: Boolean,
44
+ icon: String,
45
+ color: Color,
46
+ onClick: () -> Unit,
47
+ ) {
43
48
  if (loading) {
44
49
  Box(Modifier.padding(horizontal = Spacing.S)) {
45
50
  CircularProgressIndicator(
@@ -68,34 +73,41 @@ fun RenderRightIconSearch(loading: Boolean, icon: String, color: Color, onClick:
68
73
  }
69
74
  }
70
75
 
76
+ data class InputSearchProps(
77
+ val text: MutableState<String>,
78
+ val buttonText: String = "",
79
+ val showButtonText: Boolean = false,
80
+ val placeholder: String = "",
81
+ val onChangeText: (String) -> Unit = {},
82
+ val onPressButtonText: () -> Unit = {},
83
+ val disabled: Boolean = false,
84
+ val icon: String = "",
85
+ val iconColor: Color = Color(0xff),
86
+ val onRightIconPressed: () -> Unit = {},
87
+ val onFocus: () -> Unit = {},
88
+ val onBlur: () -> Unit = {},
89
+ val loading: Boolean = false,
90
+ val fontWeight: InputFontWeight = InputFontWeight.REGULAR,
91
+ val keyboardType: KeyboardType = KeyboardType.Text,
92
+ val backgroundColor: Color = Colors.black_01,
93
+ )
94
+
71
95
  @Composable
72
96
  fun InputSearch(
73
- text: MutableState<String> = remember { mutableStateOf("") },
74
- buttonText: String = "",
75
- showButtonText: Boolean = false,
76
- showBorder: Boolean = true,
77
- placeholder: String = "",
78
- onChangeText: (String) -> Unit = {},
79
- onPressButtonText: () -> Unit = {},
80
- error: String = "",
81
- disabled: Boolean = false,
82
- icon: String = "",
83
- iconColor: Color = AppTheme.current.colors.text.default,
84
- onRightIconPressed: () -> Unit = {},
85
- onFocus: () -> Unit = {},
86
- onBlur: () -> Unit = {},
87
- loading: Boolean = false,
88
- fontWeight: InputFontWeight = InputFontWeight.REGULAR,
89
- keyboardType: KeyboardType = KeyboardType.Text,
97
+ inputSearchProps: InputSearchProps = InputSearchProps(
98
+ text = remember { mutableStateOf("") },
99
+ iconColor = AppTheme.current.colors.text.default
100
+ ),
101
+
90
102
  ) {
91
103
  var isFocused by remember { mutableStateOf(false) }
92
104
  var isBlurred = false
93
105
  val disabledColor = AppTheme.current.colors.text.disable
94
106
  var textColor = AppTheme.current.colors.text.default
95
107
  var placeholderColor = AppTheme.current.colors.text.hint
96
- var iconTintColor = iconColor
108
+ var iconTintColor = inputSearchProps.iconColor
97
109
 
98
- if (disabled) {
110
+ if (inputSearchProps.disabled) {
99
111
  textColor = disabledColor
100
112
  placeholderColor = disabledColor
101
113
  iconTintColor = disabledColor
@@ -103,37 +115,31 @@ fun InputSearch(
103
115
 
104
116
  Column {
105
117
  BasicTextField(
106
- enabled = !disabled,
118
+ enabled = !inputSearchProps.disabled,
107
119
  singleLine = true,
108
- value = text.value,
120
+ value = inputSearchProps.text.value,
109
121
  textStyle = TextStyle(
110
122
  color = textColor,
111
- fontSize = 15.sp,
112
- lineHeight = 24.sp,
113
- fontWeight = fontWeight.value
123
+ fontSize = 14.sp,
124
+ lineHeight = 20.sp,
125
+ fontWeight = inputSearchProps.fontWeight.value
114
126
  ),
115
- keyboardOptions = KeyboardOptions.Default.copy(keyboardType = keyboardType),
127
+ keyboardOptions = KeyboardOptions.Default.copy(keyboardType = inputSearchProps.keyboardType),
116
128
  modifier = Modifier.height(36.dp).onFocusChanged {
117
129
  isFocused = it.isFocused
118
130
  if (it.isFocused) {
119
- onFocus()
131
+ inputSearchProps.onFocus()
120
132
  }
121
- if (!it.isFocused && isBlurred) onBlur()
133
+ if (!it.isFocused && isBlurred) inputSearchProps.onBlur()
122
134
  if (it.isFocused && !isBlurred) isBlurred = true
123
135
  },
124
- onValueChange = onChangeText,
136
+ onValueChange = inputSearchProps.onChangeText,
125
137
  decorationBox = { innerTextField ->
126
- //input box wrapper
127
138
  Row(verticalAlignment = Alignment.CenterVertically) {
128
139
  Row(
129
- modifier = Modifier.weight(showButtonText.ifTrue(8f, 1f))
140
+ modifier = Modifier.weight(inputSearchProps.showButtonText.ifTrue(8f, 1f))
130
141
  .background(
131
- AppTheme.current.colors.background.surface,
132
- RoundedCornerShape(Radius.XL)
133
- )
134
- .border(
135
- showBorder.ifTrue(1.dp, 0.dp),
136
- getBorderColor(isFocused, error, disabled),
142
+ inputSearchProps.backgroundColor,
137
143
  RoundedCornerShape(Radius.XL)
138
144
  ),
139
145
  horizontalArrangement = Arrangement.Start,
@@ -154,20 +160,20 @@ fun InputSearch(
154
160
  color = AppTheme.current.colors.text.hint
155
161
  )
156
162
  Box(Modifier.weight(1f)) {
157
- if (text.value.isEmpty()) {
163
+ if (inputSearchProps.text.value.isEmpty()) {
158
164
  Text(
159
- text = placeholder,
165
+ text = inputSearchProps.placeholder,
160
166
  style = TextStyle(
161
167
  fontSize = 16.sp,
162
168
  lineHeight = 24.sp,
163
- fontWeight = fontWeight.value
169
+ fontWeight = inputSearchProps.fontWeight.value
164
170
  ),
165
171
  color = placeholderColor
166
172
  )
167
173
  }
168
174
  innerTextField()
169
175
  }
170
- if (isFocused && text.value.isNotEmpty()) {
176
+ if (isFocused && inputSearchProps.text.value.isNotEmpty()) {
171
177
  Row {
172
178
  Spacer(Modifier.width(Spacing.XS))
173
179
  Icon(
@@ -175,25 +181,30 @@ fun InputSearch(
175
181
  size = 16.dp,
176
182
  color = AppTheme.current.colors.text.hint,
177
183
  modifier = Modifier.clickable(
178
- onClick = { text.value = "" },
184
+ onClick = { inputSearchProps.text.value = "" },
179
185
  interactionSource = remember { MutableInteractionSource() },
180
186
  indication = null
181
187
  )
182
188
  )
183
189
  }
184
190
  }
185
- RenderRightIconSearch(loading, icon, iconTintColor, onRightIconPressed)
191
+ RenderRightIconSearch(
192
+ inputSearchProps.loading,
193
+ inputSearchProps.icon,
194
+ iconTintColor,
195
+ inputSearchProps.onRightIconPressed
196
+ )
186
197
  }
187
198
  }
188
- if (showButtonText) {
199
+ if (inputSearchProps.showButtonText) {
189
200
  Text(
190
- text = buttonText,
201
+ text = inputSearchProps.buttonText,
191
202
  style = Typography.actionDefault,
192
203
  color = AppTheme.current.colors.text.default,
193
204
  modifier = Modifier.padding(start = Spacing.L).clickable(
194
205
  interactionSource = remember { MutableInteractionSource() },
195
206
  indication = null,
196
- onClick = onPressButtonText
207
+ onClick = inputSearchProps.onPressButtonText
197
208
  )
198
209
  )
199
210
  }
@@ -97,7 +97,7 @@ fun PopupNotify(
97
97
  }
98
98
 
99
99
  Box(Modifier.semantics {
100
- contentDescription = "popup_notify"; testTag = "popup_notify"
100
+ contentDescription = title; testTag = "popup_notify"
101
101
  }, contentAlignment = Alignment.TopEnd) {
102
102
  Column(
103
103
  modifier = Modifier
@@ -166,7 +166,7 @@ fun PopupNotify(
166
166
  color = AppTheme.current.colors.background.surface,
167
167
  size = 14.dp,
168
168
  modifier = Modifier.semantics {
169
- contentDescription = "ic_popup_close"; testTag = "ic_popup_close"
169
+ testTag = "ic_popup_close"
170
170
  }
171
171
  )
172
172
  }
@@ -235,7 +235,7 @@ fun renderRow(
235
235
  title = it.title,
236
236
  type = ButtonType.TEXT,
237
237
  modifier = Modifier.semantics {
238
- contentDescription = "btn_popup_cancel"; testTag = "btn_popup_cancel"
238
+ contentDescription = it.title; testTag = "btn_popup_cancel"
239
239
  }
240
240
  )
241
241
  }
@@ -250,7 +250,7 @@ fun renderRow(
250
250
  },
251
251
  title = primary?.title ?: "",
252
252
  modifier = Modifier.semantics {
253
- contentDescription = "btn_popup_allow"; testTag = "btn_popup_allow"
253
+ contentDescription = primary?.title ?: ""; testTag = "btn_popup_allow"
254
254
  }
255
255
  )
256
256
  }
@@ -273,7 +273,7 @@ fun renderColumn(
273
273
  },
274
274
  title = primary?.title ?: "",
275
275
  modifier = Modifier.semantics {
276
- contentDescription = "btn_popup_allow"; testTag = "btn_popup_allow"
276
+ contentDescription = primary?.title ?: ""; testTag = "btn_popup_allow"
277
277
  }
278
278
  )
279
279
  secondary?.let {
@@ -288,7 +288,7 @@ fun renderColumn(
288
288
  title = it.title,
289
289
  type = ButtonType.TEXT,
290
290
  modifier = Modifier.semantics {
291
- contentDescription = "btn_popup_cancel"; testTag = "btn_popup_cancel"
291
+ contentDescription = it.title; testTag = "btn_popup_cancel"
292
292
  }
293
293
  )
294
294
  }
@@ -17,7 +17,6 @@ import androidx.compose.runtime.remember
17
17
  import androidx.compose.ui.Alignment
18
18
  import androidx.compose.ui.Modifier
19
19
  import androidx.compose.ui.draw.clip
20
- import androidx.compose.ui.semantics.contentDescription
21
20
  import androidx.compose.ui.semantics.semantics
22
21
  import androidx.compose.ui.semantics.testTag
23
22
  import androidx.compose.ui.unit.dp
@@ -30,7 +29,7 @@ fun PromotionPopup(
30
29
  source: String = "",
31
30
  onClose: (() -> Unit) = {},
32
31
  ) {
33
- Column(Modifier.semantics { contentDescription = "popup_notify"; testTag = "popup_notify" }) {
32
+ Column(Modifier.semantics { testTag = "popup_notify" }) {
34
33
  if (source.isNotEmpty()) {
35
34
  Image(
36
35
  source = source,
@@ -69,7 +68,7 @@ fun PromotionPopup(
69
68
  color = AppTheme.current.colors.background.surface,
70
69
  size = 14.dp,
71
70
  modifier = Modifier.semantics {
72
- contentDescription = "ic_popup_close"; testTag = "ic_popup_close"
71
+ testTag = "ic_popup_close"
73
72
  }
74
73
  )
75
74
  }
@@ -123,7 +123,10 @@ fun TrustBanner(
123
123
  modifier = Modifier
124
124
  .width(64.dp)
125
125
  .height(64.dp)
126
- .padding(end = 8.dp)
126
+ .padding(end = 8.dp),
127
+ options = Options(
128
+ contentScale = ContentScale.Fit,
129
+ )
127
130
  )
128
131
  Column {
129
132
  Text(
@@ -141,11 +144,17 @@ fun TrustBanner(
141
144
  .padding(end = 4.dp)
142
145
  .width(52.dp)
143
146
  .height(20.dp)
147
+ ,options = Options(
148
+ contentScale = ContentScale.Fit,
149
+ )
144
150
  )
145
151
  Image(
146
152
  source = trustBanner.sslImage, modifier = Modifier
147
153
  .width(52.dp)
148
- .height(20.dp)
154
+ .height(20.dp),
155
+ options = Options(
156
+ contentScale = ContentScale.Fit,
157
+ )
149
158
  )
150
159
  }
151
160
  Row(
@@ -106,7 +106,7 @@ val defaultTheme = Theme(
106
106
  ),
107
107
  font = "SFProText",
108
108
  assets = ThemeAssets(
109
- headerBackground = "https://static.momocdn.net/app/img/app/img/header-background.png"
109
+ headerBackground = null
110
110
  )
111
111
  )
112
112
 
@@ -168,6 +168,5 @@ val darkTheme = Theme(
168
168
 
169
169
 
170
170
  val AppTheme = staticCompositionLocalOf { defaultTheme }
171
- val AppStatusBar = staticCompositionLocalOf<Dp?> {
172
- null
173
- }
171
+
172
+ val AppStatusBar = staticCompositionLocalOf<Dp?> { null }
@@ -27,10 +27,10 @@ fun scaleSize(size: Float): Float {
27
27
 
28
28
  @OptIn(InternalResourceApi::class)
29
29
  @Composable
30
- fun getFont(font: String, ext: String = "ttf"): FontFamily {
30
+ fun getFont(font: String): FontFamily {
31
31
  val fontResource = FontResource(
32
- "font:${font}",
33
- setOf(ResourceItem(setOf(), "font/${font}.${ext}", -1, -1))
32
+ "font:${font.substringBeforeLast(".")}",
33
+ setOf(ResourceItem(setOf(), "font/${font.substringBeforeLast(".")}.${font.substringAfterLast(".")}", -1, -1))
34
34
  )
35
35
  return FontFamily(Font(fontResource))
36
36
  }
@@ -39,27 +39,38 @@ fun getFont(font: String, ext: String = "ttf"): FontFamily {
39
39
  fun getFontFamily(fontFamily: String, fontWeight: FontWeight? = FontWeight.Normal): FontFamily {
40
40
  val key = "$fontFamily-${fontWeight?.weight}"
41
41
  val fontMap = mapOf(
42
- "SFProText-100" to getFont("sfprotext_thin"),
43
- "SFProText-200" to getFont("sfprotext_ultralight"),
44
- "SFProText-300" to getFont("sfprotext_light"),
45
- "SFProText-400" to getFont("sfprotext_regular"),
46
- "SFProText-500" to getFont("sfprotext_medium"),
47
- "SFProText-600" to getFont("sfprotext_medium"),
48
- "SFProText-700" to getFont("sfprotext_semibold"),
49
- "SFProText-800" to getFont("sfprotext_bold"),
50
- "SFProText-900" to getFont("sfprotext_heavy"),
42
+ "SFProText-100" to "sfprotext_thin.ttf",
43
+ "SFProText-200" to "sfprotext_ultralight.ttf",
44
+ "SFProText-300" to "sfprotext_light.ttf",
45
+ "SFProText-400" to "sfprotext_regular.ttf",
46
+ "SFProText-500" to "sfprotext_medium.ttf",
47
+ "SFProText-600" to "sfprotext_medium.ttf",
48
+ "SFProText-700" to "sfprotext_semibold.ttf",
49
+ "SFProText-800" to "sfprotext_bold.ttf",
50
+ "SFProText-900" to "sfprotext_heavy.ttf",
51
51
 
52
- "MoMoSignature-100" to getFont("momosignature", "otf"),
53
- "MoMoSignature-200" to getFont("momosignature", "otf"),
54
- "MoMoSignature-300" to getFont("momosignature", "otf"),
55
- "MoMoSignature-400" to getFont("momosignature", "otf"),
56
- "MoMoSignature-500" to getFont("momosignature", "otf"),
57
- "MoMoSignature-600" to getFont("momosignature", "otf"),
58
- "MoMoSignature-700" to getFont("momosignature", "otf"),
59
- "MoMoSignature-800" to getFont("momosignature", "otf"),
60
- "MoMoSignature-900" to getFont("momosignature", "otf"),
52
+ "MoMoSignature-100" to "momosignature.otf",
53
+ "MoMoSignature-200" to "momosignature.otf",
54
+ "MoMoSignature-300" to "momosignature.otf",
55
+ "MoMoSignature-400" to "momosignature.otf",
56
+ "MoMoSignature-500" to "momosignature.otf",
57
+ "MoMoSignature-600" to "momosignature.otf",
58
+ "MoMoSignature-700" to "momosignature.otf",
59
+ "MoMoSignature-800" to "momosignature.otf",
60
+ "MoMoSignature-900" to "momosignature.otf",
61
+
62
+ "MoMoTrustDisplay-100" to "momotrustdisplay.otf",
63
+ "MoMoTrustDisplay-200" to "momotrustdisplay.otf",
64
+ "MoMoTrustDisplay-300" to "momotrustdisplay.otf",
65
+ "MoMoTrustDisplay-400" to "momotrustdisplay.otf",
66
+ "MoMoTrustDisplay-500" to "momotrustdisplay.otf",
67
+ "MoMoTrustDisplay-600" to "momotrustdisplay.otf",
68
+ "MoMoTrustDisplay-700" to "momotrustdisplay.otf",
69
+ "MoMoTrustDisplay-800" to "momotrustdisplay.otf",
70
+ "MoMoTrustDisplay-900" to "momotrustdisplay.otf",
61
71
  )
62
- return fontMap[key] ?: getFont("sfprotext_regular")
72
+ val font = fontMap[key] ?: "sfprotext_regular.ttf"
73
+ return getFont(font)
63
74
  }
64
75
 
65
76
  @Immutable
@@ -0,0 +1,11 @@
1
+ package vn.momo.kits.modifier
2
+
3
+ import androidx.compose.ui.Modifier
4
+
5
+ fun Modifier.conditional(condition : Boolean, modifier : Modifier.() -> Modifier) : Modifier {
6
+ return if (condition) {
7
+ then(modifier(Modifier))
8
+ } else {
9
+ this
10
+ }
11
+ }
@@ -19,4 +19,7 @@ expect fun getScreenDimensions(): ScreenDimension
19
19
  expect fun NativePaint.setMaskFilter(blurRadius: Float)
20
20
 
21
21
  @Composable
22
- expect fun getStatusBarHeight(): Dp
22
+ expect fun getStatusBarHeight(): Dp
23
+
24
+ @Composable
25
+ expect fun getNavigationBarHeight(): Dp
@@ -4,6 +4,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
4
4
  import androidx.compose.foundation.gestures.optOutOfCupertinoOverscroll
5
5
  import androidx.compose.foundation.layout.WindowInsets
6
6
  import androidx.compose.foundation.layout.asPaddingValues
7
+ import androidx.compose.foundation.layout.navigationBars
7
8
  import androidx.compose.foundation.layout.systemBars
8
9
  import androidx.compose.runtime.Composable
9
10
  import androidx.compose.ui.graphics.NativePaint
@@ -42,4 +43,9 @@ actual fun NativePaint.setMaskFilter(blurRadius: Float) {
42
43
  @Composable
43
44
  actual fun getStatusBarHeight(): Dp {
44
45
  return WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
46
+ }
47
+
48
+ @Composable
49
+ actual fun getNavigationBarHeight(): Dp {
50
+ return WindowInsets.navigationBars.asPaddingValues().calculateTopPadding()
45
51
  }
package/local.properties CHANGED
@@ -4,5 +4,5 @@
4
4
  # Location of the SDK. This is only used by Gradle.
5
5
  # For customization when using a Version Control System, please read the
6
6
  # header note.
7
- #Wed Aug 21 14:20:12 ICT 2024
8
- sdk.dir=/Users/huynhdung/Library/Android/sdk
7
+ #Tue Apr 23 16:40:15 ICT 2024
8
+ sdk.dir=/Users/hung.dao1/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.89.30",
3
+ "version": "0.89.31-beta.22",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},