@momo-kits/native-kits 0.89.30-beta.7 → 0.89.30-nav.11

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.
@@ -1,6 +1,7 @@
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
@@ -24,6 +25,7 @@ import androidx.compose.runtime.setValue
24
25
  import androidx.compose.runtime.snapshotFlow
25
26
  import androidx.compose.ui.Alignment
26
27
  import androidx.compose.ui.Modifier
28
+ import androidx.compose.ui.draw.alpha
27
29
  import androidx.compose.ui.geometry.Offset
28
30
  import androidx.compose.ui.graphics.Brush
29
31
  import androidx.compose.ui.graphics.Color
@@ -40,6 +42,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged
40
42
  import kotlinx.coroutines.flow.map
41
43
  import vn.momo.kits.components.Icon
42
44
  import vn.momo.kits.components.Image
45
+ import vn.momo.kits.components.InputSearch
46
+ import vn.momo.kits.components.InputSearchProps
43
47
  import vn.momo.kits.components.Options
44
48
  import vn.momo.kits.components.Text
45
49
  import vn.momo.kits.const.AppStatusBar
@@ -47,6 +51,7 @@ import vn.momo.kits.const.AppTheme
47
51
  import vn.momo.kits.const.Colors
48
52
  import vn.momo.kits.const.Spacing
49
53
  import vn.momo.kits.const.Typography
54
+ import vn.momo.kits.modifier.shadow
50
55
  import vn.momo.kits.platform.getStatusBarHeight
51
56
  import vn.momo.kits.utils.bottomBorder
52
57
 
@@ -62,9 +67,15 @@ data class AnimatedHeader(
62
67
 
63
68
  @Composable
64
69
  fun HeaderBackground(
65
- headerType: HeaderType = HeaderType.DEFAULT
70
+ headerType: HeaderType = HeaderType.DEFAULT,
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
@@ -106,6 +117,7 @@ fun HeaderBackground(
106
117
  HeaderType.EXTENDED -> {
107
118
  Box(
108
119
  modifier = Modifier.fillMaxWidth().height(154.dp)
120
+ .alpha(opacityAni)
109
121
  .background(
110
122
  Brush.linearGradient(
111
123
  colors = listOf(
@@ -116,10 +128,6 @@ fun HeaderBackground(
116
128
  end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
117
129
  )
118
130
  )
119
- .bottomBorder(
120
- strokeWidth = 1.dp,
121
- color = AppTheme.current.colors.border.default
122
- )
123
131
  ) {
124
132
  if (AppTheme.current.assets.headerBackground != null) {
125
133
  Image(
@@ -131,6 +139,17 @@ fun HeaderBackground(
131
139
  )
132
140
  }
133
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
+ )
151
+ )
152
+ )
134
153
  }
135
154
 
136
155
  else -> {
@@ -144,14 +163,18 @@ fun Header(
144
163
  headerType: HeaderType = HeaderType.DEFAULT,
145
164
  titlePosition: TitlePosition,
146
165
  title: String,
166
+ isBack: Boolean,
147
167
  headerRight: @Composable (() -> Unit)? = null,
148
- goBack: (() -> Unit)? = null,
168
+ goBack: (() -> Unit) = { },
149
169
  opacity: Float? = null,
150
170
  animatedHeader: AnimatedHeader? = null,
151
- scrollState: Int = 0
171
+ useSearchInput: Boolean? = false,
172
+ scrollState: Int = 0,
173
+ inputSearchProps: InputSearchProps?
152
174
  ) {
153
175
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
154
176
  val tintIconColor = AppTheme.current.colors.text.default
177
+ val backgroundButton = Colors.black_01.copy(alpha = 0.2f)
155
178
 
156
179
  var colorFraction by remember { mutableStateOf(0f) }
157
180
 
@@ -170,7 +193,15 @@ fun Header(
170
193
  )
171
194
  )
172
195
 
173
- if (headerType != HeaderType.NONE || animatedHeader !== null) {
196
+ val backgroundSearch by animateColorAsState(
197
+ targetValue = animateColor(
198
+ Colors.black_01,
199
+ AppTheme.current.colors.background.default,
200
+ colorFraction
201
+ )
202
+ )
203
+
204
+ if (headerType != HeaderType.NONE) {
174
205
  BoxWithConstraints(
175
206
  Modifier.height(statusBarHeight + 52.dp)
176
207
  .fillMaxWidth()
@@ -185,19 +216,19 @@ fun Header(
185
216
  horizontalArrangement = Arrangement.SpaceBetween
186
217
  ) {
187
218
  Box {
188
- if (goBack !== null) {
219
+ if (isBack) {
189
220
  Box(
190
221
  modifier = Modifier
191
222
  .size(28.dp)
192
223
  .then(
193
224
  Modifier.border(
194
- 0.2.dp,
195
- Colors.black_20.copy(alpha = 0.2f),
196
- RoundedCornerShape(14.dp)
225
+ 0.5.dp,
226
+ Colors.black_20.copy(alpha = 0.4f),
227
+ RoundedCornerShape(100)
197
228
  )
198
229
  )
199
230
  .background(
200
- Colors.black_01.copy(alpha = 0.6f),
231
+ backgroundButton,
201
232
  RoundedCornerShape(100)
202
233
  )
203
234
  .clickable(
@@ -205,23 +236,24 @@ fun Header(
205
236
  )
206
237
  .padding(Spacing.XS)
207
238
  .semantics {
208
- contentDescription = "btn_navigation_back"; testTag =
209
- "btn_navigation_back"
239
+ testTag = "btn_navigation_back"
210
240
  },
211
241
  contentAlignment = Alignment.Center
212
242
  ) {
213
243
  Icon(
214
- source = "arrow_back",
244
+ source = "ic_back_ios",
215
245
  color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
216
246
  size = 20.dp,
217
247
  )
218
248
  }
219
249
  }
220
250
  }
221
- Box(Modifier.graphicsLayer {
222
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
223
- }) {
224
- headerRight?.invoke()
251
+ if (useSearchInput == false) {
252
+ Box(Modifier.graphicsLayer {
253
+ alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
254
+ }) {
255
+ headerRight?.invoke()
256
+ }
225
257
  }
226
258
  }
227
259
 
@@ -232,26 +264,28 @@ fun Header(
232
264
  .padding(horizontal = Spacing.M),
233
265
  verticalAlignment = Alignment.CenterVertically,
234
266
  ) {
235
- if (goBack !== null) {
267
+ if (isBack) {
236
268
  Spacer(Modifier.width(40.dp))
237
269
  }
238
- Box(
239
- Modifier.weight(1f).graphicsLayer {
240
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
241
- },
242
- contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
243
- ) {
244
- HeaderTitle(
245
- title = title,
246
- color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
247
- modifier = Modifier.semantics {
248
- contentDescription = "title_navigation_header"
249
- testTag = "title_navigation_header"
250
- }
251
- )
270
+ if (useSearchInput == true && inputSearchProps != null) {
271
+ InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
252
272
  }
253
- if (goBack !== null) {
254
- 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
+ }
255
289
  }
256
290
  }
257
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,15 +25,19 @@ 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
 
@@ -45,19 +50,25 @@ enum class HeaderType {
45
50
  @Composable
46
51
  fun Screen(
47
52
  backgroundColor: Color? = null,
48
- isBack: Boolean = true, headerType: HeaderType = HeaderType.DEFAULT,
53
+ isBack: Boolean = true,
54
+ headerType: HeaderType = HeaderType.DEFAULT,
49
55
  verticalArrangement: Arrangement.Vertical = Arrangement.Top,
50
56
  horizontalAlignment: Alignment.Horizontal = Alignment.Start,
51
57
  title: String = "Stack",
52
58
  titlePosition: TitlePosition = TitlePosition.LEFT,
53
- goBack: (() -> Unit)? = null,
59
+ goBack: (() -> Unit) = { },
54
60
  scrollable: Boolean = true,
61
+ scrollState: ScrollState = rememberScrollState(),
62
+ onContentLayout: ((LayoutCoordinates) -> Unit)? = null,
55
63
  useAvoidKeyboard: Boolean = true,
56
64
  footer: @Composable (() -> Unit)? = null,
57
65
  headerRight: @Composable (() -> Unit)? = null,
58
66
  fabProps: FabProps? = null,
59
67
  animatedHeader: AnimatedHeader? = null,
60
68
  layoutOffset: Dp = 56.dp,
69
+ useShadow: Boolean? = true,
70
+ useSearchInput: Boolean? = false,
71
+ inputSearchProps: InputSearchProps? = null,
61
72
  content: @Composable () -> Unit,
62
73
  ) {
63
74
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
@@ -72,7 +83,6 @@ fun Screen(
72
83
 
73
84
  val indicator = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
74
85
  val bottomPadding = min(indicator, 21.dp)
75
- val scrollState = rememberScrollState()
76
86
 
77
87
  val opacity by animateFloatAsState(
78
88
  targetValue = ((scrollState.value / 114f)).coerceIn(0f, 1f)
@@ -87,14 +97,18 @@ fun Screen(
87
97
  ) {
88
98
 
89
99
  if (animatedHeader === null) {
90
- HeaderBackground(headerType)
100
+ HeaderBackground(headerType = headerType, scrollState = scrollState.value)
91
101
  } else {
92
102
  Box(
93
103
  Modifier.zIndex(5f)
94
104
  .background(Color.White.copy(alpha = opacity))
95
105
  .graphicsLayer { alpha = opacity }
96
106
  ) {
97
- HeaderBackground(HeaderType.DEFAULT)
107
+ HeaderBackground(
108
+ headerType = headerType,
109
+ useShadow = useShadow,
110
+ scrollState = scrollState.value
111
+ )
98
112
  }
99
113
  }
100
114
 
@@ -103,9 +117,12 @@ fun Screen(
103
117
  title = title,
104
118
  titlePosition = titlePosition,
105
119
  headerRight = headerRight,
120
+ isBack = isBack,
106
121
  goBack = goBack,
107
122
  opacity = opacity,
108
123
  animatedHeader = animatedHeader,
124
+ useSearchInput = useSearchInput,
125
+ inputSearchProps = inputSearchProps,
109
126
  scrollState = scrollState.value
110
127
  )
111
128
 
@@ -121,7 +138,13 @@ fun Screen(
121
138
  ) {
122
139
 
123
140
  Column(
124
- modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize).verticalScroll(scrollState) else 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) },
125
148
  verticalArrangement = verticalArrangement,
126
149
  horizontalAlignment = horizontalAlignment
127
150
  ) {
@@ -146,7 +169,8 @@ fun Screen(
146
169
  scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
147
170
  onClick = fabProps.onClick,
148
171
  containerColor = AppTheme.current.colors.primary,
149
- bottom = fabProps.bottom ?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
172
+ bottom = fabProps.bottom
173
+ ?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
150
174
  icon = fabProps.icon,
151
175
  iconColor = fabProps.iconColor,
152
176
  text = fabProps.label,
@@ -260,7 +260,7 @@ fun Button(
260
260
  minWidth = size.value.width
261
261
  ).height(size.value.height)
262
262
  .semantics {
263
- contentDescription = testId; testTag = testId
263
+ contentDescription = title; testTag = testId
264
264
  },
265
265
  horizontalArrangement = Arrangement.Center,
266
266
  verticalAlignment = Alignment.CenterVertically,
@@ -204,7 +204,7 @@ fun Input(
204
204
  val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
205
205
 
206
206
  Column(modifier = Modifier.semantics {
207
- contentDescription = testId; testTag = testId
207
+ contentDescription = floatingValue; testTag = testId
208
208
  }) {
209
209
  BasicTextField(
210
210
  enabled = !disabled,
@@ -17,7 +17,6 @@ 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
@@ -78,7 +77,7 @@ fun InputDropDown(
78
77
  val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
79
78
 
80
79
  Column(modifier = Modifier.clickable(enabled = !disabled, onClick = onPress).semantics {
81
- contentDescription = testId; testTag = testId
80
+ contentDescription = floatingValue; testTag = testId
82
81
  }) {
83
82
  Box {
84
83
  if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
@@ -110,7 +110,7 @@ fun InputMoney(
110
110
  val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
111
111
 
112
112
  Column(modifier = Modifier.semantics {
113
- contentDescription = testId; testTag = testId
113
+ contentDescription = floatingValue; testTag = testId
114
114
  }) {
115
115
  BasicTextField(
116
116
  enabled = !disabled,
@@ -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
  }
@@ -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.layout.Arrangement
7
6
  import androidx.compose.foundation.layout.Column
@@ -9,9 +8,7 @@ import androidx.compose.foundation.layout.Row
9
8
  import androidx.compose.foundation.layout.fillMaxWidth
10
9
  import androidx.compose.foundation.layout.height
11
10
  import androidx.compose.foundation.layout.padding
12
- import androidx.compose.foundation.layout.size
13
11
  import androidx.compose.foundation.layout.width
14
- import androidx.compose.foundation.shape.CircleShape
15
12
  import androidx.compose.foundation.shape.RoundedCornerShape
16
13
  import androidx.compose.material.Text
17
14
  import androidx.compose.runtime.Composable
@@ -29,7 +26,11 @@ val defaultBanner = TrustBannerData(
29
26
  "vi" to "Bảo mật thông tin & An toàn tài sản của bạn là ưu tiên hàng đầu của MoMo.",
30
27
  "en" to "Your data security and money safety are MoMo's top priorities."
31
28
  ),
32
- pciImage = "https://static.momocdn.net/app/img/kits/trustBanner/pci.png",
29
+ subContent = mapOf(
30
+ "vi" to "Tìm hiểu thêm",
31
+ "en" to "Learn more"
32
+ ),
33
+ pciImage = "https://static.momocdn.net/app/img/kits/trustBanner/pci_dss.png",
33
34
  sslImage = "https://static.momocdn.net/app/img/kits/trustBanner/ssl.png",
34
35
  urlConfig = "login_and_security",
35
36
  icons = listOf(
@@ -38,40 +39,23 @@ val defaultBanner = TrustBannerData(
38
39
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_vietcombank.png",
39
40
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_bidv.png"
40
41
  ),
41
- momoImage = "https://static.momocdn.net/app/img/kits/trustBanner/ic_momo_secu.png"
42
+ momoImage = "https://static.momocdn.net/app/img/kits/trustBanner/ic_secu.png"
42
43
  )
43
44
 
44
- const val borderColor = 0xFFE8E8E8
45
- const val tonalColor = 0xFFFDEAF4
46
45
  const val backgroundBlue = 0xFFF2F8FF
47
46
  const val contentColor = 0xFF484848
48
- const val primaryColor = 0xFFEB2F96
49
-
50
- data class TrustBannerClass(
51
- val trustBanner: TrustBannerData
52
- )
47
+ const val subContentColor = 0xFFEB2F96
53
48
 
54
49
  data class TrustBannerData(
55
50
  val content: Map<String, String>,
51
+ val subContent: Map<String, String>,
56
52
  val pciImage: String,
53
+ val momoImage: String,
57
54
  val sslImage: String,
58
55
  val icons: List<String>,
59
- val momoImage: String,
60
56
  val urlConfig: String
61
57
  )
62
58
 
63
- @Composable
64
- fun Avatar(iconURL: String) {
65
- Image(
66
- source = iconURL,
67
- modifier = Modifier
68
- .size(24.dp)
69
- .background(Color.White, CircleShape)
70
- .border(width = 1.dp, color = Color(borderColor), CircleShape),
71
- options = Options(contentScale = ContentScale.Fit)
72
- )
73
- }
74
-
75
59
  @Composable
76
60
  fun TrustBanner(
77
61
  trustBanner: TrustBannerData = defaultBanner,
@@ -80,6 +64,7 @@ fun TrustBanner(
80
64
  onPress: ((Map<String, String>) -> Unit)? = null,
81
65
  trackEvent: ((String, Map<String, String>) -> Unit)? = null,
82
66
  language: String = "vi"
67
+
83
68
  ) {
84
69
  val trackParams = mapOf(
85
70
  "service_name" to serviceName,
@@ -123,12 +108,11 @@ fun TrustBanner(
123
108
  modifier = Modifier
124
109
  .width(64.dp)
125
110
  .height(64.dp)
126
- .padding(end = 8.dp),
127
- options = Options(
128
- contentScale = ContentScale.Fit,
129
- )
130
111
  )
131
- Column {
112
+ Column (
113
+ modifier = Modifier
114
+ .padding(start = 10.dp)
115
+ ) {
132
116
  Text(
133
117
  text = trustBanner.content[language] ?: "",
134
118
  modifier = Modifier.padding(bottom = 8.dp),
@@ -138,11 +122,26 @@ fun TrustBanner(
138
122
  maxLines = 2
139
123
  )
140
124
  Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
125
+ Row (
126
+ verticalAlignment = Alignment.CenterVertically,
127
+ ) {
128
+ Text(
129
+ text = trustBanner.subContent[language] ?: "",
130
+ lineHeight = 16.sp,
131
+ fontSize = 12.sp,
132
+ color = Color(subContentColor),
133
+ maxLines = 2
134
+ )
135
+ Icon(
136
+ source = "https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/16_arrow_chevron_right_small.png",
137
+ color = Color(subContentColor),
138
+ )
139
+ }
141
140
  Row {
142
141
  Image(
143
142
  source = trustBanner.pciImage, modifier = Modifier
144
143
  .padding(end = 4.dp)
145
- .width(52.dp)
144
+ .width(27.dp)
146
145
  .height(20.dp)
147
146
  ,options = Options(
148
147
  contentScale = ContentScale.Fit,
@@ -157,31 +156,6 @@ fun TrustBanner(
157
156
  )
158
157
  )
159
158
  }
160
- Row(
161
- modifier = Modifier
162
- .width(96.dp)
163
- .height(24.dp),
164
- horizontalArrangement = Arrangement.spacedBy((-6).dp)
165
- ) {
166
- trustBanner.icons.forEach { iconURL ->
167
- Avatar(iconURL = iconURL)
168
- }
169
- Row(
170
- modifier = Modifier
171
- .size(24.dp)
172
- .background(color = Color(tonalColor), CircleShape)
173
- .border(width = 1.dp, color = Color(borderColor), CircleShape),
174
- verticalAlignment = Alignment.CenterVertically,
175
- horizontalArrangement = Arrangement.Center
176
- ) {
177
- Text(
178
- text = "36+",
179
- color = Color(primaryColor),
180
- lineHeight = 14.sp,
181
- fontSize = 10.sp
182
- )
183
- }
184
- }
185
159
  }
186
160
  }
187
161
  }
@@ -58,6 +58,16 @@ fun getFontFamily(fontFamily: String, fontWeight: FontWeight? = FontWeight.Norma
58
58
  "MoMoSignature-700" to "momosignature.otf",
59
59
  "MoMoSignature-800" to "momosignature.otf",
60
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
72
  val font = fontMap[key] ?: "sfprotext_regular.ttf"
63
73
  return getFont(font)
@@ -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
+ }
@@ -1317,7 +1317,5 @@ val Icons = mapOf(
1317
1317
  "ic_checked" to "https://img.mservice.com.vn/app/img/kits/checked_ic.png",
1318
1318
  "ic_minus" to "https://img.mservice.com.vn/app/img/kits/minus.png",
1319
1319
  "ic_navigation" to "https://static.momocdn.net/app/img/kits/ic_navigation.png",
1320
- "ic_money_bag" to "https://static.momocdn.net/app/img/kits/ic_money_bag.png",
1321
- "help_center" to "https://static.momocdn.net/app/img/kits/ic_money_bag_2.png",
1322
- "arrow_back" to "https://static.momocdn.net/app/img/kits/arrow-back.png",
1320
+ "ic_money_bag" to "https://static.momocdn.net/app/img/kits/ic_money_bag.png"
1323
1321
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.89.30-beta.7",
3
+ "version": "0.89.30-nav.11",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},