@momo-kits/native-kits 0.113.2-beta.15 → 0.113.2-beta.16

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,5 +1,6 @@
1
1
  package vn.momo.kits.application
2
2
 
3
+ import androidx.compose.animation.animateColorAsState
3
4
  import androidx.compose.foundation.background
4
5
  import androidx.compose.foundation.border
5
6
  import androidx.compose.foundation.clickable
@@ -23,6 +24,7 @@ import androidx.compose.runtime.setValue
23
24
  import androidx.compose.runtime.snapshotFlow
24
25
  import androidx.compose.ui.Alignment
25
26
  import androidx.compose.ui.Modifier
27
+ import androidx.compose.ui.graphics.Color
26
28
  import androidx.compose.ui.graphics.graphicsLayer
27
29
  import androidx.compose.ui.semantics.semantics
28
30
  import androidx.compose.ui.semantics.testTag
@@ -40,6 +42,15 @@ import vn.momo.kits.const.Spacing
40
42
  import vn.momo.kits.modifier.setAutomationId
41
43
  import vn.momo.kits.platform.getStatusBarHeight
42
44
 
45
+ enum class TitlePosition {
46
+ LEFT, CENTER,
47
+ }
48
+
49
+ data class AnimatedHeader(
50
+ val type: HeaderType = HeaderType.DEFAULT,
51
+ val composable: @Composable (scrollState: Int) -> Unit = {}
52
+ )
53
+
43
54
  @Composable
44
55
  fun Header(
45
56
  headerType: HeaderType = HeaderType.DEFAULT,
@@ -66,15 +77,24 @@ fun Header(
66
77
  .collect { fraction -> colorFraction = fraction }
67
78
  }
68
79
 
69
- val backgroundSearch = animateColor(
70
- Colors.black_01,
71
- AppTheme.current.colors.background.default,
72
- colorFraction
80
+ val backgroundSearch by animateColorAsState(
81
+ targetValue = animateColor(
82
+ AppTheme.current.colors.background.surface,
83
+ AppTheme.current.colors.background.default,
84
+ colorFraction
85
+ )
73
86
  )
74
87
 
88
+ val backgroundColor = if (scrollState == 0) {
89
+ Color.Transparent
90
+ } else {
91
+ AppTheme.current.colors.background.surface
92
+ }
93
+
75
94
  if (headerType != HeaderType.NONE) {
76
95
  BoxWithConstraints(
77
96
  Modifier.height(statusBarHeight + 52.dp)
97
+ .background(backgroundColor)
78
98
  .fillMaxWidth()
79
99
  .zIndex(10f),
80
100
  contentAlignment = Alignment.BottomCenter
@@ -118,9 +138,9 @@ fun Header(
118
138
  }
119
139
  }
120
140
 
121
- if (useAnimationSearch || inputSearchProps == null) {
141
+ if ((useAnimationSearch && inputSearchProps != null) || inputSearchProps == null) {
122
142
  Box(Modifier.graphicsLayer {
123
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
143
+ alpha = if (useAnimationSearch) 1f - (opacity ?: 1f) else 1f
124
144
  }) {
125
145
  headerRight?.invoke()
126
146
  }
@@ -136,32 +156,40 @@ fun Header(
136
156
  ) {
137
157
  if (goBack != null && titlePosition == TitlePosition.LEFT) {
138
158
  Spacer(Modifier.width(40.dp))
159
+ }
160
+ if (inputSearchProps != null && !useAnimationSearch) {
161
+ InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
139
162
  } else {
140
- if (inputSearchProps != null && !useAnimationSearch) {
141
- InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
142
- } else {
143
- Box(
144
- Modifier.weight(1f).graphicsLayer {
145
- alpha = if (useAnimationSearch) {
146
- 1f - (opacity ?: 1f)
147
- } else {
148
- if (animatedHeader !== null) opacity ?: 1f else 1f
149
- }
150
- },
151
- contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
152
- ) {
153
-
154
- HeaderTitle(
155
- title = title,
156
- color = tintIconColor,
157
- modifier = Modifier.semantics {
158
- testTag = "title_navigation_header"
159
- }
160
- )
161
- }
163
+ Box(
164
+ Modifier.weight(1f).graphicsLayer {
165
+ alpha = if (useAnimationSearch && inputSearchProps != null) {
166
+ 1f - (opacity ?: 1f)
167
+ } else {
168
+ if (animatedHeader !== null) opacity ?: 1f else 1f
169
+ }
170
+ },
171
+ contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
172
+ ) {
173
+ HeaderTitle(
174
+ title = title,
175
+ color = tintIconColor,
176
+ modifier = Modifier.semantics {
177
+ testTag = "title_navigation_header"
178
+ }
179
+ )
162
180
  }
163
181
  }
164
182
  }
165
183
  }
166
184
  }
167
- }
185
+ }
186
+
187
+
188
+ fun animateColor(start: Color, stop: Color, fraction: Float): Color {
189
+ return Color(
190
+ red = start.red + fraction * (stop.red - start.red),
191
+ green = start.green + fraction * (stop.green - start.green),
192
+ blue = start.blue + fraction * (stop.blue - start.blue),
193
+ alpha = start.alpha + fraction * (stop.alpha - start.alpha)
194
+ )
195
+ }
@@ -1,11 +1,8 @@
1
1
  package vn.momo.kits.application
2
2
 
3
- import androidx.compose.animation.animateColorAsState
4
- import androidx.compose.animation.core.animateFloatAsState
5
3
  import androidx.compose.foundation.layout.Box
6
4
  import androidx.compose.foundation.layout.fillMaxWidth
7
5
  import androidx.compose.runtime.Composable
8
- import androidx.compose.runtime.getValue
9
6
  import androidx.compose.ui.Modifier
10
7
  import androidx.compose.ui.graphics.Color
11
8
  import androidx.compose.ui.unit.Dp
@@ -13,25 +10,11 @@ import androidx.compose.ui.unit.dp
13
10
  import vn.momo.kits.components.InputSearchProps
14
11
  import vn.momo.kits.const.AppStatusBar
15
12
  import vn.momo.kits.const.AppTheme
13
+ import vn.momo.kits.platform.getScreenDimensions
16
14
  import vn.momo.kits.platform.getStatusBarHeight
17
15
 
18
- enum class TitlePosition {
19
- LEFT, CENTER,
20
- }
21
-
22
- data class AnimatedHeader(
23
- val type: HeaderType = HeaderType.DEFAULT,
24
- val composable: @Composable (scrollState: Int) -> Unit = {}
25
- )
26
-
27
- fun animateColor(start: Color, stop: Color, fraction: Float): Color {
28
- return Color(
29
- red = start.red + fraction * (stop.red - start.red),
30
- green = start.green + fraction * (stop.green - start.green),
31
- blue = start.blue + fraction * (stop.blue - start.blue),
32
- alpha = start.alpha + fraction * (stop.alpha - start.alpha)
33
- )
34
- }
16
+ private const val SCREEN_PADDING = 12
17
+ private const val BACK_WIDTH = 28
35
18
 
36
19
  @Composable
37
20
  fun HeaderBackground(
@@ -43,39 +26,41 @@ fun HeaderBackground(
43
26
  useAnimationSearch: Boolean = false
44
27
  ) {
45
28
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
29
+ val screenWidth = getScreenDimensions().width
30
+ val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
31
+ val searchWidth = screenWidth - (SCREEN_PADDING * 2)
46
32
 
47
- val opacityAni by animateFloatAsState(
48
- targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f),
33
+ val animations = useHeaderSearchAnimation(
34
+ scrollState = scrollState,
35
+ statusBarHeight = statusBarHeight,
36
+ leftPosition = leftPosition,
37
+ searchWidth = searchWidth,
38
+ headerRightWidth = headerRightWidth
49
39
  )
50
40
 
51
- val backgroundColor by animateColorAsState(
52
- targetValue = animateColor(
53
- Color.Transparent,
54
- AppTheme.current.colors.background.surface,
55
- opacityAni
56
- ),
57
- )
41
+ val backgroundColor = if (scrollState == 0) {
42
+ Color.Transparent
43
+ } else {
44
+ AppTheme.current.colors.background.surface
45
+ }
58
46
 
59
47
  when (headerType) {
60
48
  HeaderType.DEFAULT -> {
49
+ val height = statusBarHeight + 52.dp
61
50
  HeaderDefault(
62
- opacityAni = opacityAni,
63
- statusBarHeight = statusBarHeight,
64
- backgroundColor = backgroundColor,
51
+ height = height,
52
+ animations = animations,
53
+ backgroundColor = backgroundColor
65
54
  )
66
55
  }
67
56
 
68
57
  HeaderType.EXTENDED -> {
69
- HeaderExtended(
70
- scrollState = scrollState,
58
+ HeaderExtended(
59
+ animations = animations,
71
60
  inputSearchProps = inputSearchProps,
72
- headerRightWidth = headerRightWidth,
73
61
  useAnimationSearch = useAnimationSearch,
74
- opacityAni = opacityAni,
75
- isBack = isBack,
76
- statusBarHeight = statusBarHeight,
77
- backgroundColor = backgroundColor,
78
- )
62
+ backgroundColor = backgroundColor
63
+ )
79
64
  }
80
65
 
81
66
  else -> {
@@ -21,11 +21,10 @@ import vn.momo.kits.utils.bottomBorder
21
21
 
22
22
  @Composable
23
23
  fun HeaderDefault(
24
- opacityAni: Float,
25
- statusBarHeight: Dp,
26
- backgroundColor: Color
24
+ height: Dp,
25
+ backgroundColor: Color,
26
+ animations: HeaderAnimations
27
27
  ) {
28
- val height = statusBarHeight + 52.dp
29
28
  Box(
30
29
  modifier = Modifier.fillMaxWidth().height(height)
31
30
  .background(backgroundColor)
@@ -38,7 +37,7 @@ fun HeaderDefault(
38
37
  modifier = Modifier
39
38
  .height(height)
40
39
  .fillMaxWidth()
41
- .alpha(opacityAni)
40
+ .alpha(animations.opacity)
42
41
  .background(
43
42
  Brush.linearGradient(
44
43
  colors = listOf(
@@ -1,7 +1,5 @@
1
1
  package vn.momo.kits.application
2
2
 
3
- import androidx.compose.animation.animateColorAsState
4
- import androidx.compose.animation.core.animateFloatAsState
5
3
  import androidx.compose.foundation.background
6
4
  import androidx.compose.foundation.layout.Box
7
5
  import androidx.compose.foundation.layout.fillMaxWidth
@@ -11,7 +9,6 @@ import androidx.compose.foundation.layout.padding
11
9
  import androidx.compose.foundation.layout.width
12
10
  import androidx.compose.foundation.shape.RoundedCornerShape
13
11
  import androidx.compose.runtime.Composable
14
- import androidx.compose.runtime.getValue
15
12
  import androidx.compose.ui.Alignment
16
13
  import androidx.compose.ui.Modifier
17
14
  import androidx.compose.ui.draw.alpha
@@ -20,47 +17,30 @@ import androidx.compose.ui.graphics.Brush
20
17
  import androidx.compose.ui.graphics.Color
21
18
  import androidx.compose.ui.layout.ContentScale
22
19
  import androidx.compose.ui.platform.LocalDensity
23
- import androidx.compose.ui.unit.Dp
24
20
  import androidx.compose.ui.unit.dp
25
21
  import vn.momo.kits.components.Image
26
22
  import vn.momo.kits.components.InputSearch
27
23
  import vn.momo.kits.components.InputSearchProps
28
24
  import vn.momo.kits.components.Options
29
25
  import vn.momo.kits.const.AppTheme
30
- import vn.momo.kits.const.Colors
31
26
  import vn.momo.kits.const.Radius
32
27
  import vn.momo.kits.const.Spacing
33
- import vn.momo.kits.platform.getScreenDimensions
34
- import vn.momo.kits.utils.bottomBorder
35
28
 
36
29
  @Composable
37
30
  fun HeaderExtended(
38
- opacityAni: Float,
39
- inputSearchProps: InputSearchProps?,
40
- useAnimationSearch: Boolean = true,
41
- scrollState: Int,
42
- headerRightWidth: Dp,
43
- isBack: Boolean,
44
- statusBarHeight: Dp,
45
- backgroundColor: Color
46
- ) {
47
- val animations = useHeaderSearchAnimation(
48
- opacityAni = opacityAni,
49
- scrollState = scrollState,
50
- headerRightWidth = headerRightWidth,
51
- statusBarHeight = statusBarHeight,
52
- isBack = isBack
53
- )
54
-
31
+ animations: HeaderAnimations,
32
+ inputSearchProps: InputSearchProps? = null,
33
+ useAnimationSearch: Boolean = false,
34
+ backgroundColor: Color = Color.Transparent
35
+ ){
55
36
  Box(
56
- modifier = Modifier.fillMaxWidth()
57
- .height(animations.height.dp)
37
+ modifier = Modifier.fillMaxWidth().height(animations.height.dp)
58
38
  ) {
59
39
  Box(
60
40
  modifier = Modifier
61
41
  .fillMaxWidth()
62
42
  .height(154.dp)
63
- .alpha(opacityAni)
43
+ .alpha(animations.opacity)
64
44
  .background(
65
45
  Brush.linearGradient(
66
46
  colors = listOf(
@@ -90,19 +70,6 @@ fun HeaderExtended(
90
70
  }
91
71
  }
92
72
 
93
- Box(
94
- modifier = Modifier
95
- .fillMaxWidth()
96
- .alpha(1f - opacityAni)
97
- .height(statusBarHeight + 52.dp)
98
- .background(
99
- AppTheme.current.colors.background.surface
100
- )
101
- .bottomBorder(
102
- strokeWidth = 1.dp,
103
- color = AppTheme.current.colors.border.default
104
- )
105
- )
106
73
  if (inputSearchProps != null && useAnimationSearch) {
107
74
  Box(
108
75
  modifier = Modifier
@@ -131,4 +98,5 @@ fun HeaderExtended(
131
98
  }
132
99
  }
133
100
  }
134
- }
101
+ }
102
+
@@ -79,12 +79,12 @@ object Spacing {
79
79
 
80
80
  @Composable
81
81
  fun HeaderRight(
82
- headerRight: HeaderRightData? = null,
82
+ data: HeaderRightData? = null,
83
83
  ) {
84
84
  Row(
85
85
  verticalAlignment = Alignment.CenterVertically,
86
86
  ) {
87
- ToolkitHeaderRight(headerRight = headerRight)
87
+ ToolkitHeaderRight(headerRight = data)
88
88
  }
89
89
  }
90
90
 
@@ -180,6 +180,8 @@ fun ToolkitHeaderRight(headerRight: HeaderRightData? = null) {
180
180
  group.items.any { it.showBadge }
181
181
  }
182
182
 
183
+ if (context === null) return
184
+
183
185
  Row(
184
186
  verticalAlignment = Alignment.CenterVertically
185
187
  ) {
@@ -8,6 +8,7 @@ import androidx.compose.ui.zIndex
8
8
  import vn.momo.kits.components.Text
9
9
  import vn.momo.kits.const.Typography
10
10
 
11
+
11
12
  @Composable
12
13
  fun HeaderTitle(
13
14
  title: String = "",
@@ -68,7 +68,6 @@ fun Screen(
68
68
  layoutOffset: Dp = 56.dp,
69
69
  inputSearchProps: InputSearchProps? = null,
70
70
  useAnimationSearch: Boolean = false,
71
- headerRightWidth: Dp = 0.dp,
72
71
  content: @Composable () -> Unit,
73
72
  ) {
74
73
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
@@ -85,7 +84,7 @@ fun Screen(
85
84
  val bottomPadding = min(indicator, 21.dp)
86
85
 
87
86
  val opacity by animateFloatAsState(
88
- targetValue = ((scrollState.value / 52f)).coerceIn(0f, 1f),
87
+ targetValue = ((scrollState.value / 114f)).coerceIn(0f, 1f)
89
88
  )
90
89
 
91
90
  val headerAnimated =
@@ -95,16 +94,15 @@ fun Screen(
95
94
 
96
95
  Box(
97
96
  Modifier.fillMaxSize()
98
- .background(backgroundColor ?: AppTheme.current.colors.background.default)
97
+ .background(AppTheme.current.colors.background.surface)
99
98
  ) {
100
99
 
101
100
  if (animatedHeader === null) {
102
101
  HeaderBackground(
103
102
  headerType = headerType,
104
103
  scrollState = scrollState.value,
105
- inputSearchProps= inputSearchProps,
106
- useAnimationSearch = useAnimationSearch,
107
- headerRightWidth = headerRightWidth
104
+ inputSearchProps = inputSearchProps,
105
+ useAnimationSearch = useAnimationSearch
108
106
  )
109
107
  } else {
110
108
  Box(
@@ -116,9 +114,8 @@ fun Screen(
116
114
  isBack = isBack,
117
115
  headerType = headerType,
118
116
  scrollState = scrollState.value,
119
- inputSearchProps= inputSearchProps,
120
- useAnimationSearch = useAnimationSearch,
121
- headerRightWidth = headerRightWidth
117
+ inputSearchProps = inputSearchProps,
118
+ useAnimationSearch = useAnimationSearch
122
119
  )
123
120
  }
124
121
  }
@@ -133,7 +130,7 @@ fun Screen(
133
130
  animatedHeader = animatedHeader,
134
131
  inputSearchProps = inputSearchProps,
135
132
  scrollState = scrollState.value,
136
- useAnimationSearch = useAnimationSearch,
133
+ useAnimationSearch = useAnimationSearch
137
134
  )
138
135
 
139
136
  Column(
@@ -158,7 +155,11 @@ fun Screen(
158
155
  verticalArrangement = verticalArrangement,
159
156
  horizontalAlignment = horizontalAlignment
160
157
  ) {
161
- Box {
158
+ Box(
159
+ modifier = Modifier.background(
160
+ backgroundColor ?: AppTheme.current.colors.background.default
161
+ )
162
+ ) {
162
163
  headerAnimated()
163
164
  Column {
164
165
  if (animatedHeader !== null) {
@@ -3,13 +3,11 @@ package vn.momo.kits.application
3
3
  import androidx.compose.animation.animateColorAsState
4
4
  import androidx.compose.animation.core.animateFloatAsState
5
5
  import androidx.compose.runtime.Composable
6
- import androidx.compose.runtime.getValue
7
6
  import androidx.compose.ui.graphics.Color
8
7
  import androidx.compose.ui.unit.Dp
9
- import androidx.compose.ui.unit.dp
10
8
  import vn.momo.kits.const.AppTheme
11
9
  import vn.momo.kits.const.Colors
12
- import vn.momo.kits.platform.getScreenDimensions
10
+ import androidx.compose.runtime.getValue
13
11
 
14
12
  data class HeaderAnimations(
15
13
  val opacity: Float,
@@ -19,46 +17,40 @@ data class HeaderAnimations(
19
17
  val height: Float
20
18
  )
21
19
 
22
- private const val SCREEN_PADDING = 12
23
- private const val BACK_WIDTH = 28
24
-
25
20
  @Composable
26
21
  fun useHeaderSearchAnimation(
27
- opacityAni: Float,
28
22
  scrollState: Int,
29
- headerRightWidth: Dp,
30
23
  statusBarHeight: Dp,
31
- isBack: Boolean
24
+ leftPosition: Dp,
25
+ searchWidth: Int,
26
+ headerRightWidth: Dp
32
27
  ): HeaderAnimations {
33
- val screenWidth = getScreenDimensions().width
34
- val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
35
- val searchWidth = screenWidth - (SCREEN_PADDING * 2)
28
+ val opacityAni by animateFloatAsState(
29
+ targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f)
30
+ )
36
31
 
37
32
  val backgroundSearch by animateColorAsState(
38
33
  targetValue = animateColor(
39
34
  AppTheme.current.colors.background.default,
40
35
  Colors.black_01,
41
36
  opacityAni
42
- ),
37
+ )
43
38
  )
44
39
 
45
40
  val animatedTranslateX by animateFloatAsState(
46
- targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12,
41
+ targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12
47
42
  )
48
43
 
49
44
  val animatedWidth by animateFloatAsState(
50
- targetValue = (scrollState / 52f).coerceIn(
51
- 0f,
52
- 1f
53
- ) * ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth,
45
+ targetValue = (scrollState / 52f).coerceIn(0f, 1f) *
46
+ ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth
54
47
  )
55
48
 
56
49
  val animatedHeight by animateFloatAsState(
57
- targetValue = (1 - (scrollState / 52f).coerceIn(
58
- 0f,
59
- 1f
60
- )) * (statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52),
50
+ targetValue = (1 - (scrollState / 52f).coerceIn(0f, 1f)) *
51
+ (statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52)
61
52
  )
53
+
62
54
  return HeaderAnimations(
63
55
  opacity = opacityAni,
64
56
  backgroundSearch = backgroundSearch,
@@ -203,7 +203,9 @@ public struct Header: View {
203
203
  Text(title)
204
204
  .font(.headline)
205
205
  .foregroundColor(tintIconColor)
206
+ .frame(maxWidth: UIScreen.main.bounds.width - 172)
206
207
  .frame(maxWidth: titlePosition == .center ? .infinity : nil, alignment: titlePosition == .center ? .center : .leading)
208
+ .lineLimit(1)
207
209
  }
208
210
  Spacer()
209
211
  }
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
- #Sun Mar 02 11:30:14 ICT 2025
8
- sdk.dir=/Users/nguyenhoangson/Library/Android/sdk
7
+ #Thu Jan 09 10:43:10 ICT 2025
8
+ sdk.dir=/Users/sophia/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.113.2-beta.15",
3
+ "version": "0.113.2-beta.16",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},