@momo-kits/native-kits 0.113.1-beta.2 → 0.113.1-beta.20

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 (29) hide show
  1. package/compose/src/commonMain/kotlin/vn/momo/kits/application/{Components.kt → Header.kt} +19 -162
  2. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +85 -0
  3. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +64 -0
  4. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +134 -0
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +261 -0
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +26 -0
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +57 -60
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +17 -3
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +2 -2
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +2 -2
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +3 -3
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +3 -1
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +4 -4
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -1
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +47 -37
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +6 -1
  18. package/ios/Application/ApplicationEnvironment.swift +34 -0
  19. package/ios/Application/Components.swift +6 -7
  20. package/ios/Application/ComposeApi.swift +22 -0
  21. package/ios/Application/HeaderRight.swift +249 -0
  22. package/ios/Application/Screen.swift +18 -19
  23. package/ios/Badge/BadgeDot.swift +31 -0
  24. package/ios/Icon/Icon.swift +1 -3
  25. package/ios/Image/Image.swift +17 -1
  26. package/ios/Popup/PopupDisplay.swift +25 -12
  27. package/ios/Typography/Typography.swift +2 -1
  28. package/local.properties +2 -2
  29. package/package.json +1 -1
@@ -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.border
7
5
  import androidx.compose.foundation.clickable
@@ -25,143 +23,22 @@ import androidx.compose.runtime.setValue
25
23
  import androidx.compose.runtime.snapshotFlow
26
24
  import androidx.compose.ui.Alignment
27
25
  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
31
- import androidx.compose.ui.graphics.Color
32
26
  import androidx.compose.ui.graphics.graphicsLayer
33
- import androidx.compose.ui.layout.ContentScale
34
- import androidx.compose.ui.platform.LocalDensity
35
27
  import androidx.compose.ui.semantics.semantics
36
28
  import androidx.compose.ui.semantics.testTag
37
- import androidx.compose.ui.text.style.TextAlign
38
29
  import androidx.compose.ui.unit.dp
39
30
  import androidx.compose.ui.zIndex
40
31
  import kotlinx.coroutines.flow.distinctUntilChanged
41
32
  import kotlinx.coroutines.flow.map
42
33
  import vn.momo.kits.components.Icon
43
- import vn.momo.kits.components.Image
44
34
  import vn.momo.kits.components.InputSearch
45
35
  import vn.momo.kits.components.InputSearchProps
46
- import vn.momo.kits.components.Options
47
- import vn.momo.kits.components.Text
48
36
  import vn.momo.kits.const.AppStatusBar
49
37
  import vn.momo.kits.const.AppTheme
50
38
  import vn.momo.kits.const.Colors
51
39
  import vn.momo.kits.const.Spacing
52
- import vn.momo.kits.const.Typography
53
40
  import vn.momo.kits.modifier.setAutomationId
54
41
  import vn.momo.kits.platform.getStatusBarHeight
55
- import vn.momo.kits.utils.bottomBorder
56
-
57
- enum class TitlePosition {
58
- LEFT, CENTER,
59
- }
60
-
61
-
62
- data class AnimatedHeader(
63
- val type: HeaderType = HeaderType.DEFAULT,
64
- val composable: @Composable (scrollState: Int) -> Unit = {}
65
- )
66
-
67
- @Composable
68
- fun HeaderBackground(
69
- headerType: HeaderType = HeaderType.DEFAULT,
70
- scrollState: Int
71
- ) {
72
- val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
73
- val opacityAni by animateFloatAsState(
74
- targetValue = (1 - (scrollState / 200f)).coerceIn(0f, 1f),
75
- )
76
-
77
- val backgroundColor = if (scrollState == 0) {
78
- Color.Transparent
79
- } else {
80
- AppTheme.current.colors.background.surface
81
- }
82
-
83
-
84
- when (headerType) {
85
- HeaderType.DEFAULT -> {
86
- val height = statusBarHeight + 52.dp
87
- Box(
88
- modifier = Modifier.fillMaxWidth().height(height)
89
- .background(backgroundColor)
90
- .bottomBorder(
91
- strokeWidth = 1.dp,
92
- color = AppTheme.current.colors.border.default
93
- )
94
- ) {
95
- Box(
96
- modifier = Modifier
97
- .height(height)
98
- .fillMaxWidth()
99
- .alpha(opacityAni)
100
- .background(
101
- Brush.linearGradient(
102
- colors = listOf(
103
- Color(0xFFFDCADE),
104
- Color(0x00FDCADE)
105
- ),
106
- start = Offset(0f, 0f),
107
- end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
108
- )
109
- )
110
- )
111
- if (AppTheme.current.assets.headerBackground != null) {
112
- Image(
113
- loading = false,
114
- source = AppTheme.current.assets.headerBackground!!,
115
- modifier = Modifier.fillMaxWidth().height(height),
116
- options = Options(
117
- contentScale = ContentScale.FillWidth
118
- )
119
- )
120
- }
121
- }
122
-
123
- }
124
-
125
- HeaderType.EXTENDED -> {
126
-
127
- Box(
128
- modifier = Modifier.fillMaxWidth().height(154.dp)
129
- .alpha(opacityAni)
130
- .background(
131
- Brush.linearGradient(
132
- colors = listOf(
133
- Color(0xFFFDCADE),
134
- Color(0x00FDCADE)
135
- ),
136
- start = Offset(0f, 0f),
137
- end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
138
- )
139
- )
140
- ) {
141
- if (AppTheme.current.assets.headerBackground != null) {
142
- Box(
143
- modifier = Modifier.fillMaxWidth()
144
- .background(backgroundColor)
145
- ) {
146
- Image(
147
- loading = false,
148
- source = AppTheme.current.assets.headerBackground!!,
149
- modifier = Modifier.fillMaxWidth().height(154.dp),
150
- options = Options(
151
- contentScale = ContentScale.FillWidth
152
- )
153
- )
154
- }
155
- }
156
- }
157
- }
158
-
159
- else -> {
160
- Box(modifier = Modifier.fillMaxWidth())
161
- }
162
- }
163
-
164
- }
165
42
 
166
43
  @Composable
167
44
  fun Header(
@@ -173,7 +50,8 @@ fun Header(
173
50
  opacity: Float? = null,
174
51
  animatedHeader: AnimatedHeader? = null,
175
52
  scrollState: Int = 0,
176
- inputSearchProps: InputSearchProps?
53
+ inputSearchProps: InputSearchProps? = null,
54
+ useAnimationSearch: Boolean = false
177
55
  ) {
178
56
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
179
57
  val tintIconColor = AppTheme.current.colors.text.default
@@ -188,12 +66,10 @@ fun Header(
188
66
  .collect { fraction -> colorFraction = fraction }
189
67
  }
190
68
 
191
- val backgroundSearch by animateColorAsState(
192
- targetValue = animateColor(
193
- Colors.black_01,
194
- AppTheme.current.colors.background.default,
195
- colorFraction
196
- )
69
+ val backgroundSearch = animateColor(
70
+ Colors.black_01,
71
+ AppTheme.current.colors.background.default,
72
+ colorFraction
197
73
  )
198
74
 
199
75
  if (headerType != HeaderType.NONE) {
@@ -242,10 +118,12 @@ fun Header(
242
118
  }
243
119
  }
244
120
 
245
- Box(Modifier.graphicsLayer {
246
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
247
- }) {
248
- headerRight?.invoke()
121
+ if (useAnimationSearch || inputSearchProps == null) {
122
+ Box(Modifier.graphicsLayer {
123
+ alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
124
+ }) {
125
+ headerRight?.invoke()
126
+ }
249
127
  }
250
128
  }
251
129
 
@@ -259,15 +137,20 @@ fun Header(
259
137
  if (goBack != null && titlePosition == TitlePosition.LEFT) {
260
138
  Spacer(Modifier.width(40.dp))
261
139
  }
262
- if (inputSearchProps != null) {
140
+ if (inputSearchProps != null && !useAnimationSearch) {
263
141
  InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
264
142
  } else {
265
143
  Box(
266
144
  Modifier.weight(1f).graphicsLayer {
267
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
145
+ alpha = if (useAnimationSearch) {
146
+ 1f - (opacity ?: 1f)
147
+ } else {
148
+ if (animatedHeader !== null) opacity ?: 1f else 1f
149
+ }
268
150
  },
269
151
  contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
270
152
  ) {
153
+
271
154
  HeaderTitle(
272
155
  title = title,
273
156
  color = tintIconColor,
@@ -280,30 +163,4 @@ fun Header(
280
163
  }
281
164
  }
282
165
  }
283
- }
284
-
285
- @Composable
286
- fun HeaderTitle(
287
- title: String = "",
288
- modifier: Modifier = Modifier,
289
- textAlign: TextAlign = TextAlign.Start,
290
- color: Color? = null,
291
- ) {
292
- Text(
293
- modifier = Modifier.then(modifier).zIndex(1f),
294
- text = title,
295
- textAlign = textAlign,
296
- style = Typography.actionS,
297
- color = color,
298
- maxLines = 1
299
- )
300
- }
301
-
302
- fun animateColor(start: Color, stop: Color, fraction: Float): Color {
303
- return Color(
304
- red = start.red + fraction * (stop.red - start.red),
305
- green = start.green + fraction * (stop.green - start.green),
306
- blue = start.blue + fraction * (stop.blue - start.blue),
307
- alpha = start.alpha + fraction * (stop.alpha - start.alpha)
308
- )
309
166
  }
@@ -0,0 +1,85 @@
1
+ package vn.momo.kits.application
2
+
3
+ import androidx.compose.animation.animateColorAsState
4
+ import androidx.compose.animation.core.animateFloatAsState
5
+ import androidx.compose.foundation.layout.Box
6
+ import androidx.compose.foundation.layout.fillMaxWidth
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.runtime.getValue
9
+ import androidx.compose.ui.Modifier
10
+ import androidx.compose.ui.graphics.Color
11
+ import androidx.compose.ui.unit.Dp
12
+ import androidx.compose.ui.unit.dp
13
+ import vn.momo.kits.components.InputSearchProps
14
+ import vn.momo.kits.const.AppStatusBar
15
+ import vn.momo.kits.const.AppTheme
16
+ import vn.momo.kits.platform.getStatusBarHeight
17
+
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
+ }
35
+
36
+ @Composable
37
+ fun HeaderBackground(
38
+ isBack: Boolean = true,
39
+ headerType: HeaderType = HeaderType.DEFAULT,
40
+ scrollState: Int,
41
+ inputSearchProps: InputSearchProps? = null,
42
+ headerRightWidth: Dp = 0.dp,
43
+ useAnimationSearch: Boolean = false
44
+ ) {
45
+ val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
46
+
47
+ val opacityAni by animateFloatAsState(
48
+ targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f),
49
+ )
50
+
51
+ val backgroundColor by animateColorAsState(
52
+ targetValue = animateColor(
53
+ Color.Transparent,
54
+ AppTheme.current.colors.background.surface,
55
+ opacityAni
56
+ ),
57
+ )
58
+
59
+ when (headerType) {
60
+ HeaderType.DEFAULT -> {
61
+ HeaderDefault(
62
+ opacityAni = opacityAni,
63
+ statusBarHeight = statusBarHeight,
64
+ backgroundColor = backgroundColor,
65
+ )
66
+ }
67
+
68
+ HeaderType.EXTENDED -> {
69
+ HeaderExtended(
70
+ scrollState = scrollState,
71
+ inputSearchProps = inputSearchProps,
72
+ headerRightWidth = headerRightWidth,
73
+ useAnimationSearch = useAnimationSearch,
74
+ opacityAni = opacityAni,
75
+ isBack = isBack,
76
+ statusBarHeight = statusBarHeight,
77
+ backgroundColor = backgroundColor,
78
+ )
79
+ }
80
+
81
+ else -> {
82
+ Box(modifier = Modifier.fillMaxWidth())
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,64 @@
1
+ package vn.momo.kits.application
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.layout.Box
5
+ import androidx.compose.foundation.layout.fillMaxWidth
6
+ import androidx.compose.foundation.layout.height
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.ui.Modifier
9
+ import androidx.compose.ui.draw.alpha
10
+ import androidx.compose.ui.geometry.Offset
11
+ import androidx.compose.ui.graphics.Brush
12
+ import androidx.compose.ui.graphics.Color
13
+ import androidx.compose.ui.layout.ContentScale
14
+ import androidx.compose.ui.platform.LocalDensity
15
+ import androidx.compose.ui.unit.Dp
16
+ import androidx.compose.ui.unit.dp
17
+ import vn.momo.kits.components.Image
18
+ import vn.momo.kits.components.Options
19
+ import vn.momo.kits.const.AppTheme
20
+ import vn.momo.kits.utils.bottomBorder
21
+
22
+ @Composable
23
+ fun HeaderDefault(
24
+ opacityAni: Float,
25
+ statusBarHeight: Dp,
26
+ backgroundColor: Color
27
+ ) {
28
+ val height = statusBarHeight + 52.dp
29
+ Box(
30
+ modifier = Modifier.fillMaxWidth().height(height)
31
+ .background(backgroundColor)
32
+ .bottomBorder(
33
+ strokeWidth = 1.dp,
34
+ color = AppTheme.current.colors.border.default
35
+ )
36
+ ) {
37
+ Box(
38
+ modifier = Modifier
39
+ .height(height)
40
+ .fillMaxWidth()
41
+ .alpha(opacityAni)
42
+ .background(
43
+ Brush.linearGradient(
44
+ colors = listOf(
45
+ Color(0xFFFDCADE),
46
+ Color(0x00FDCADE)
47
+ ),
48
+ start = Offset(0f, 0f),
49
+ end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
50
+ )
51
+ )
52
+ )
53
+ if (AppTheme.current.assets.headerBackground != null) {
54
+ Image(
55
+ loading = false,
56
+ source = AppTheme.current.assets.headerBackground!!,
57
+ modifier = Modifier.fillMaxWidth().height(height),
58
+ options = Options(
59
+ contentScale = ContentScale.FillWidth
60
+ )
61
+ )
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,134 @@
1
+ package vn.momo.kits.application
2
+
3
+ import androidx.compose.animation.animateColorAsState
4
+ import androidx.compose.animation.core.animateFloatAsState
5
+ import androidx.compose.foundation.background
6
+ import androidx.compose.foundation.layout.Box
7
+ import androidx.compose.foundation.layout.fillMaxWidth
8
+ import androidx.compose.foundation.layout.height
9
+ import androidx.compose.foundation.layout.offset
10
+ import androidx.compose.foundation.layout.padding
11
+ import androidx.compose.foundation.layout.width
12
+ import androidx.compose.foundation.shape.RoundedCornerShape
13
+ import androidx.compose.runtime.Composable
14
+ import androidx.compose.runtime.getValue
15
+ import androidx.compose.ui.Alignment
16
+ import androidx.compose.ui.Modifier
17
+ import androidx.compose.ui.draw.alpha
18
+ import androidx.compose.ui.geometry.Offset
19
+ import androidx.compose.ui.graphics.Brush
20
+ import androidx.compose.ui.graphics.Color
21
+ import androidx.compose.ui.layout.ContentScale
22
+ import androidx.compose.ui.platform.LocalDensity
23
+ import androidx.compose.ui.unit.Dp
24
+ import androidx.compose.ui.unit.dp
25
+ import vn.momo.kits.components.Image
26
+ import vn.momo.kits.components.InputSearch
27
+ import vn.momo.kits.components.InputSearchProps
28
+ import vn.momo.kits.components.Options
29
+ import vn.momo.kits.const.AppTheme
30
+ import vn.momo.kits.const.Colors
31
+ import vn.momo.kits.const.Radius
32
+ import vn.momo.kits.const.Spacing
33
+ import vn.momo.kits.platform.getScreenDimensions
34
+ import vn.momo.kits.utils.bottomBorder
35
+
36
+ @Composable
37
+ 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
+
55
+ Box(
56
+ modifier = Modifier.fillMaxWidth()
57
+ .height(animations.height.dp)
58
+ ) {
59
+ Box(
60
+ modifier = Modifier
61
+ .fillMaxWidth()
62
+ .height(154.dp)
63
+ .alpha(opacityAni)
64
+ .background(
65
+ Brush.linearGradient(
66
+ colors = listOf(
67
+ Color(0xFFFDCADE),
68
+ Color(0x00FDCADE)
69
+ ),
70
+ start = Offset(0f, 0f),
71
+ end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
72
+ )
73
+ )
74
+ ) {
75
+ if (AppTheme.current.assets.headerBackground != null) {
76
+ Box(
77
+ modifier = Modifier
78
+ .fillMaxWidth()
79
+ .background(backgroundColor)
80
+ ) {
81
+ Image(
82
+ loading = false,
83
+ source = AppTheme.current.assets.headerBackground!!,
84
+ modifier = Modifier.fillMaxWidth().height(154.dp),
85
+ options = Options(
86
+ contentScale = ContentScale.FillWidth
87
+ )
88
+ )
89
+ }
90
+ }
91
+ }
92
+
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
+ if (inputSearchProps != null && useAnimationSearch) {
107
+ Box(
108
+ modifier = Modifier
109
+ .height(52.dp)
110
+ .offset(
111
+ x = animations.translateX.dp
112
+ )
113
+ .padding(vertical = Spacing.S)
114
+ .align(Alignment.BottomStart)
115
+ ) {
116
+ Box(
117
+ modifier = Modifier
118
+ .width(animations.width.dp)
119
+ .background(
120
+ color = animations.backgroundSearch,
121
+ shape = RoundedCornerShape(Radius.XL)
122
+ )
123
+ ) {
124
+ InputSearch(
125
+ inputSearchProps = inputSearchProps.copy(
126
+ showButtonText = false,
127
+ backgroundColor = Color.Transparent
128
+ )
129
+ )
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }