@momo-kits/native-kits 0.157.7-debug → 0.157.7

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 (130) hide show
  1. package/package.json +1 -1
  2. package/build.gradle.kts +0 -11
  3. package/compose/build.gradle.kts +0 -180
  4. package/compose/build.gradle.kts.backup +0 -180
  5. package/compose/compose.podspec +0 -54
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -117
  7. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  8. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  9. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  10. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  11. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -107
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -305
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -720
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -121
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -405
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -85
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -340
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -198
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -123
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -94
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -136
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -224
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -148
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -188
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -116
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -448
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -172
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -255
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -231
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -233
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -254
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -241
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -92
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -352
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -103
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -338
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -70
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -96
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -348
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -256
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -494
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -131
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -215
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -96
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -531
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -92
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -130
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -214
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -590
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -177
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -192
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -205
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -239
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -285
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -50
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -14
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -50
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -239
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -119
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -98
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -161
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -331
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -497
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -162
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -243
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -187
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -279
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -32
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -370
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -46
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -62
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -88
  123. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -161
  124. package/gradle/libs.versions.toml +0 -57
  125. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  126. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  127. package/gradle.properties +0 -26
  128. package/gradlew +0 -252
  129. package/gradlew.bat +0 -94
  130. package/settings.gradle.kts +0 -52
@@ -1,494 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.border
5
- import androidx.compose.foundation.layout.Arrangement
6
- import androidx.compose.foundation.layout.Box
7
- import androidx.compose.foundation.layout.Column
8
- import androidx.compose.foundation.layout.Row
9
- import androidx.compose.foundation.layout.Spacer
10
- import androidx.compose.foundation.layout.fillMaxWidth
11
- import androidx.compose.foundation.layout.height
12
- import androidx.compose.foundation.layout.padding
13
- import androidx.compose.foundation.layout.size
14
- import androidx.compose.foundation.layout.width
15
- import androidx.compose.foundation.shape.CircleShape
16
- import androidx.compose.foundation.shape.RoundedCornerShape
17
- import androidx.compose.runtime.Composable
18
- import androidx.compose.runtime.remember
19
- import androidx.compose.ui.Alignment
20
- import androidx.compose.ui.Modifier
21
- import androidx.compose.ui.graphics.Color
22
- import androidx.compose.ui.text.style.TextAlign
23
- import androidx.compose.ui.unit.Dp
24
- import androidx.compose.ui.unit.dp
25
- import vn.momo.kits.application.IsShowBaseLineDebug
26
- import vn.momo.kits.const.AppTheme
27
- import vn.momo.kits.const.Colors
28
- import vn.momo.kits.const.Radius
29
- import vn.momo.kits.const.Spacing
30
- import vn.momo.kits.const.Typography
31
- import vn.momo.kits.modifier.activeOpacityClickable
32
- import vn.momo.kits.modifier.conditional
33
-
34
- // ─── Data model ────────────────────────────────────────────────────────────────
35
-
36
- data class StepItem(
37
- val title: String,
38
- val description: String? = null,
39
- val error: Boolean = false,
40
- val time: String? = null,
41
- )
42
-
43
- // ─── Enumerations ──────────────────────────────────────────────────────────────
44
-
45
- enum class StepsSize { SMALL, LARGE }
46
-
47
- enum class StepsAlign { LEFT, RIGHT, CENTER, STRETCH }
48
-
49
- // ─── Internal status ───────────────────────────────────────────────────────────
50
-
51
- private enum class StepStatus { INCOMPLETE, CURRENT, COMPLETED, ERROR, DISABLED }
52
-
53
- private fun resolveStatus(
54
- activeIndex: Int,
55
- currentIndex: Int,
56
- error: Boolean,
57
- disabled: Boolean,
58
- ): StepStatus = when {
59
- disabled -> StepStatus.DISABLED
60
- error -> StepStatus.ERROR
61
- activeIndex == currentIndex -> StepStatus.CURRENT
62
- activeIndex > currentIndex -> StepStatus.COMPLETED
63
- else -> StepStatus.INCOMPLETE
64
- }
65
-
66
- // ─── Color helpers ─────────────────────────────────────────────────────────────
67
-
68
- @Composable
69
- private fun resolveIconBgAndBorder(status: StepStatus): Pair<Color, Color> {
70
- val theme = AppTheme.current
71
- return when (status) {
72
- StepStatus.CURRENT, StepStatus.COMPLETED ->
73
- theme.colors.primary to theme.colors.background.tonal
74
- StepStatus.ERROR ->
75
- theme.colors.error.primary to theme.colors.error.container
76
- StepStatus.DISABLED ->
77
- Colors.pink_08 to Colors.pink_10
78
- StepStatus.INCOMPLETE ->
79
- Colors.black_06 to theme.colors.border.default
80
- }
81
- }
82
-
83
- @Composable
84
- private fun resolveTitleColor(status: StepStatus): Color {
85
- val theme = AppTheme.current
86
- return when (status) {
87
- StepStatus.CURRENT -> theme.colors.primary
88
- StepStatus.ERROR -> theme.colors.error.primary
89
- StepStatus.DISABLED -> theme.colors.text.disable
90
- else -> theme.colors.text.default
91
- }
92
- }
93
-
94
- // ─── Step bubble ───────────────────────────────────────────────────────────────
95
-
96
- @Composable
97
- private fun StepBubble(
98
- index: Int,
99
- isActive: Boolean,
100
- error: Boolean,
101
- size: StepsSize,
102
- status: StepStatus,
103
- useNumber: Boolean,
104
- customIcon: String?,
105
- modifier: Modifier = Modifier,
106
- ) {
107
- val bubbleSize: Dp = if (size == StepsSize.SMALL) 16.dp else 24.dp
108
- val innerSize: Dp = if (size == StepsSize.SMALL) 12.dp else 16.dp
109
- val dotSize: Dp = if (size == StepsSize.SMALL) 6.dp else 8.dp
110
-
111
- val (bgColor, borderColor) = resolveIconBgAndBorder(status)
112
-
113
- Box(
114
- modifier = modifier
115
- .size(bubbleSize)
116
- .background(color = bgColor, shape = CircleShape)
117
- .border(width = 2.dp, color = borderColor, shape = CircleShape)
118
- .conditional(IsShowBaseLineDebug) { border(1.dp, Colors.blue_03) },
119
- contentAlignment = Alignment.Center,
120
- ) {
121
- when {
122
- useNumber -> {
123
- Text(
124
- text = (index + 1).toString(),
125
- style = Typography.headerXsSemibold,
126
- color = Colors.black_01,
127
- )
128
- }
129
- isActive -> {
130
- if (!customIcon.isNullOrEmpty()) {
131
- Icon(
132
- source = customIcon,
133
- size = innerSize,
134
- color = Colors.black_01,
135
- )
136
- } else {
137
- // current-step dot (white circle matching RN currIcon style)
138
- Box(
139
- modifier = Modifier
140
- .size(dotSize)
141
- .background(color = Colors.black_01, shape = CircleShape),
142
- )
143
- }
144
- }
145
- else -> {
146
- Icon(
147
- source = if (error) "navigation_close" else "notifications_check",
148
- size = innerSize,
149
- color = Colors.black_01,
150
- )
151
- }
152
- }
153
- }
154
- }
155
-
156
- // ─── Horizontal layout ─────────────────────────────────────────────────────────
157
-
158
- @Composable
159
- private fun StepsHorizontal(
160
- steps: List<StepItem>,
161
- activeIndex: Int,
162
- size: StepsSize,
163
- useNumber: Boolean,
164
- align: StepsAlign,
165
- customIcon: String?,
166
- disabled: Boolean,
167
- onPress: ((StepItem, Int) -> Unit)?,
168
- ) {
169
- val theme = AppTheme.current
170
- // completed-line colour is primary at 20 % opacity (mirrors RN primary + '33')
171
- val completedLine = remember(theme.colors.primary) { theme.colors.primary.copy(alpha = 0.2f) }
172
- val defaultLine = theme.colors.background.default
173
-
174
- Row(modifier = Modifier.fillMaxWidth()) {
175
- steps.forEachIndexed { index, item ->
176
- val status = resolveStatus(activeIndex, index, item.error, disabled)
177
- val isActiveOrError = status == StepStatus.CURRENT || status == StepStatus.ERROR
178
-
179
- // Horizontal always uses the xs/description typography scale (checkSizeAndStepType=true)
180
- val currentTitleStyle = if (isActiveOrError)
181
- Typography.headerXsSemibold else Typography.descriptionDefaultRegular
182
- val currentDescStyle = if (size == StepsSize.SMALL)
183
- Typography.descriptionXsRegular else Typography.descriptionDefaultRegular
184
-
185
- val titleColor = resolveTitleColor(status)
186
- val subColor = if (disabled) theme.colors.text.disable else theme.colors.text.hint
187
-
188
- val colAlign = when (align) {
189
- StepsAlign.LEFT -> Alignment.Start
190
- StepsAlign.RIGHT -> Alignment.End
191
- StepsAlign.STRETCH -> when (index) {
192
- 0 -> Alignment.Start
193
- steps.size - 1 -> Alignment.End
194
- else -> Alignment.CenterHorizontally
195
- }
196
- StepsAlign.CENTER -> Alignment.CenterHorizontally
197
- }
198
- val textAlign = when (align) {
199
- StepsAlign.LEFT -> TextAlign.Start
200
- StepsAlign.RIGHT -> TextAlign.End
201
- StepsAlign.STRETCH -> when (index) {
202
- 0 -> TextAlign.Start
203
- steps.size - 1 -> TextAlign.End
204
- else -> TextAlign.Center
205
- }
206
- StepsAlign.CENTER -> TextAlign.Center
207
- }
208
-
209
- val hideLineLeft = align == StepsAlign.LEFT ||
210
- (align == StepsAlign.STRETCH && index == 0)
211
- val hideLineRight = align == StepsAlign.RIGHT ||
212
- (align == StepsAlign.STRETCH && index == steps.size - 1)
213
-
214
- val lineLeft = when {
215
- index == 0 -> Color.Transparent
216
- activeIndex >= index -> completedLine
217
- else -> defaultLine
218
- }
219
- val lineRight = when {
220
- index == steps.size - 1 -> Color.Transparent
221
- activeIndex > index -> completedLine
222
- else -> defaultLine
223
- }
224
-
225
- val clickable = status == StepStatus.COMPLETED && onPress != null && !disabled
226
-
227
- Column(
228
- modifier = Modifier
229
- .weight(1f)
230
- .then(
231
- if (clickable) Modifier.activeOpacityClickable { onPress?.invoke(item, index) }
232
- else Modifier
233
- ),
234
- horizontalAlignment = colAlign,
235
- ) {
236
- // time label shown above the icon row
237
- if (!item.time.isNullOrEmpty()) {
238
- Text(
239
- text = item.time,
240
- style = Typography.descriptionXsRegular,
241
- color = subColor,
242
- textAlign = textAlign,
243
- )
244
- } else {
245
- Spacer(modifier = Modifier.height(0.dp))
246
- }
247
-
248
- // icon row with horizontal connector lines
249
- Row(
250
- verticalAlignment = Alignment.CenterVertically,
251
- modifier = Modifier.fillMaxWidth(),
252
- ) {
253
- if (!hideLineLeft) {
254
- Box(
255
- modifier = Modifier
256
- .weight(1f)
257
- .height(2.dp)
258
- .background(
259
- color = lineLeft,
260
- shape = RoundedCornerShape(
261
- topEnd = Radius.XS,
262
- bottomEnd = Radius.XS,
263
- ),
264
- ),
265
- )
266
- }
267
- StepBubble(
268
- index = index,
269
- isActive = activeIndex == index,
270
- error = item.error,
271
- size = size,
272
- status = status,
273
- useNumber = useNumber,
274
- customIcon = customIcon,
275
- modifier = Modifier.padding(
276
- start = if (!hideLineLeft) Spacing.XS else 0.dp,
277
- end = if (!hideLineRight) Spacing.XS else 0.dp,
278
- top = Spacing.XS,
279
- bottom = Spacing.XS,
280
- ),
281
- )
282
- if (!hideLineRight) {
283
- Box(
284
- modifier = Modifier
285
- .weight(1f)
286
- .height(2.dp)
287
- .background(
288
- color = lineRight,
289
- shape = RoundedCornerShape(
290
- topStart = Radius.XS,
291
- bottomStart = Radius.XS,
292
- ),
293
- ),
294
- )
295
- }
296
- }
297
-
298
- if (item.title.isNotEmpty()) {
299
- Text(
300
- text = item.title,
301
- style = currentTitleStyle,
302
- color = titleColor,
303
- textAlign = textAlign,
304
- modifier = Modifier.padding(bottom = Spacing.XXS),
305
- )
306
- }
307
-
308
- if (!item.description.isNullOrEmpty()) {
309
- Text(
310
- text = item.description,
311
- style = currentDescStyle,
312
- color = subColor,
313
- textAlign = textAlign,
314
- )
315
- }
316
- }
317
- }
318
- }
319
- }
320
-
321
- // ─── Vertical layout ───────────────────────────────────────────────────────────
322
-
323
- @Composable
324
- private fun StepsVertical(
325
- steps: List<StepItem>,
326
- activeIndex: Int,
327
- size: StepsSize,
328
- useNumber: Boolean,
329
- customIcon: String?,
330
- disabled: Boolean,
331
- onPress: ((StepItem, Int) -> Unit)?,
332
- ) {
333
- val theme = AppTheme.current
334
- val completedLine = remember(theme.colors.primary) { theme.colors.primary.copy(alpha = 0.2f) }
335
- val defaultLine = theme.colors.background.default
336
- val useSmall = size == StepsSize.SMALL
337
- // Fixed connector height; grows proportionally with content in practice
338
- val connectorHeight: Dp = if (useSmall) 24.dp else 32.dp
339
-
340
- Column(modifier = Modifier.fillMaxWidth()) {
341
- steps.forEachIndexed { index, item ->
342
- val status = resolveStatus(activeIndex, index, item.error, disabled)
343
- val isActiveOrError = status == StepStatus.CURRENT || status == StepStatus.ERROR
344
- val isLast = index == steps.size - 1
345
-
346
- // Vertical large: header_s / body; vertical small: header_xs / description
347
- val currentTitleStyle = if (isActiveOrError) {
348
- if (useSmall) Typography.headerXsSemibold else Typography.headerSSemibold
349
- } else {
350
- if (useSmall) Typography.descriptionDefaultRegular else Typography.bodyDefaultRegular
351
- }
352
- val currentDescStyle = if (useSmall)
353
- Typography.descriptionXsRegular else Typography.descriptionDefaultRegular
354
-
355
- val titleColor = resolveTitleColor(status)
356
- val subColor = if (disabled) theme.colors.text.disable else theme.colors.text.hint
357
- val lineColor = if (activeIndex > index) completedLine else defaultLine
358
-
359
- val clickable = status == StepStatus.COMPLETED && onPress != null && !disabled
360
-
361
- Row(
362
- modifier = Modifier
363
- .fillMaxWidth()
364
- .then(
365
- if (clickable) Modifier.activeOpacityClickable { onPress?.invoke(item, index) }
366
- else Modifier
367
- ),
368
- ) {
369
- // Left column: bubble + vertical connector line
370
- Column(
371
- horizontalAlignment = Alignment.CenterHorizontally,
372
- modifier = Modifier.padding(end = Spacing.M),
373
- ) {
374
- StepBubble(
375
- index = index,
376
- isActive = activeIndex == index,
377
- error = item.error,
378
- size = size,
379
- status = status,
380
- useNumber = useNumber,
381
- customIcon = customIcon,
382
- )
383
- if (!isLast) {
384
- Box(
385
- modifier = Modifier
386
- .width(2.dp)
387
- .height(connectorHeight)
388
- .padding(vertical = Spacing.XS)
389
- .background(color = lineColor),
390
- )
391
- }
392
- }
393
-
394
- // Right column: title + time on the same row, description below
395
- Column(
396
- modifier = Modifier
397
- .weight(1f)
398
- .padding(bottom = if (isLast) 0.dp else Spacing.S),
399
- ) {
400
- Row(
401
- modifier = Modifier.fillMaxWidth(),
402
- horizontalArrangement = Arrangement.SpaceBetween,
403
- verticalAlignment = Alignment.Top,
404
- ) {
405
- Text(
406
- text = item.title,
407
- style = currentTitleStyle,
408
- color = titleColor,
409
- maxLines = 2,
410
- modifier = Modifier
411
- .weight(1f)
412
- .padding(end = Spacing.S),
413
- )
414
- if (!item.time.isNullOrEmpty()) {
415
- Text(
416
- text = item.time,
417
- style = Typography.descriptionXsRegular,
418
- color = subColor,
419
- )
420
- }
421
- }
422
- if (!item.description.isNullOrEmpty()) {
423
- Spacer(modifier = Modifier.height(Spacing.XXS))
424
- Text(
425
- text = item.description,
426
- style = currentDescStyle,
427
- color = subColor,
428
- )
429
- }
430
- }
431
- }
432
- }
433
- }
434
- }
435
-
436
- // ─── Public API ────────────────────────────────────────────────────────────────
437
-
438
- /**
439
- * Steps — guided progress indicator through a sequence of procedural steps.
440
- *
441
- * Mirrors the React Native `Steps` component from `@momo-kits/step`.
442
- *
443
- * @param steps Ordered list of [StepItem] values to display.
444
- * @param activeIndex Zero-based index of the currently active step.
445
- * @param modifier Modifier applied to the outermost container.
446
- * @param horizontal `true` renders a horizontal layout; defaults to vertical.
447
- * @param size [StepsSize.SMALL] or [StepsSize.LARGE] — affects bubble and typography scale.
448
- * @param useNumber Shows the 1-based step number inside the bubble instead of a check/dot icon.
449
- * @param align Text and icon alignment in horizontal mode: LEFT, RIGHT, CENTER, or STRETCH.
450
- * @param customIcon Icon source name rendered inside the active-step bubble (replaces the dot).
451
- * @param disabled Dims all steps and suppresses all press callbacks.
452
- * @param onPress Invoked with the tapped [StepItem] and its index; only fires for completed steps.
453
- */
454
- @Composable
455
- fun Steps(
456
- steps: List<StepItem>,
457
- activeIndex: Int,
458
- modifier: Modifier = Modifier,
459
- horizontal: Boolean = false,
460
- size: StepsSize = StepsSize.LARGE,
461
- useNumber: Boolean = false,
462
- align: StepsAlign = StepsAlign.CENTER,
463
- customIcon: String? = null,
464
- disabled: Boolean = false,
465
- onPress: ((StepItem, Int) -> Unit)? = null,
466
- ) {
467
- Box(
468
- modifier = modifier
469
- .conditional(IsShowBaseLineDebug) { border(1.dp, Colors.blue_03) },
470
- ) {
471
- if (horizontal) {
472
- StepsHorizontal(
473
- steps = steps,
474
- activeIndex = activeIndex,
475
- size = size,
476
- useNumber = useNumber,
477
- align = align,
478
- customIcon = customIcon,
479
- disabled = disabled,
480
- onPress = onPress,
481
- )
482
- } else {
483
- StepsVertical(
484
- steps = steps,
485
- activeIndex = activeIndex,
486
- size = size,
487
- useNumber = useNumber,
488
- customIcon = customIcon,
489
- disabled = disabled,
490
- onPress = onPress,
491
- )
492
- }
493
- }
494
- }
@@ -1,131 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.animation.AnimatedVisibility
4
- import androidx.compose.animation.fadeIn
5
- import androidx.compose.animation.fadeOut
6
- import androidx.compose.foundation.background
7
- import androidx.compose.foundation.border
8
- import androidx.compose.foundation.layout.Row
9
- import androidx.compose.foundation.layout.Spacer
10
- import androidx.compose.foundation.layout.fillMaxWidth
11
- import androidx.compose.foundation.layout.padding
12
- import androidx.compose.foundation.layout.size
13
- import androidx.compose.foundation.layout.width
14
- import androidx.compose.foundation.shape.RoundedCornerShape
15
- import androidx.compose.runtime.Composable
16
- import androidx.compose.runtime.remember
17
- import androidx.compose.ui.Alignment
18
- import androidx.compose.ui.Modifier
19
- import androidx.compose.ui.draw.clip
20
- import androidx.compose.ui.text.SpanStyle
21
- import androidx.compose.ui.text.buildAnnotatedString
22
- import androidx.compose.ui.text.font.FontWeight
23
- import androidx.compose.ui.text.withStyle
24
- import androidx.compose.ui.unit.dp
25
- import vn.momo.kits.application.IsShowBaseLineDebug
26
- import vn.momo.kits.const.AppTheme
27
- import vn.momo.kits.const.Colors
28
- import vn.momo.kits.const.Radius
29
- import vn.momo.kits.const.Spacing
30
- import vn.momo.kits.const.Typography
31
- import vn.momo.kits.modifier.activeOpacityClickable
32
- import vn.momo.kits.modifier.conditional
33
- import vn.momo.kits.modifier.shadow
34
-
35
- @Composable
36
- fun SuggestAction(
37
- message: String,
38
- buttonTitle: String,
39
- boldMessage: String = "",
40
- image: String = "",
41
- visible: Boolean = false,
42
- onClose: () -> Unit = {},
43
- onPressButton: () -> Unit = {},
44
- modifier: Modifier = Modifier,
45
- ) {
46
- val theme = AppTheme.current
47
-
48
- AnimatedVisibility(
49
- visible = visible,
50
- enter = fadeIn(),
51
- exit = fadeOut(),
52
- modifier = modifier,
53
- ) {
54
- Row(
55
- modifier = Modifier
56
- .fillMaxWidth()
57
- .shadow(
58
- color = theme.colors.text.default.copy(alpha = 0.12f),
59
- borderRadius = Radius.S,
60
- blurRadius = 16f,
61
- offsetY = 4.dp,
62
- )
63
- .clip(RoundedCornerShape(Radius.S))
64
- .background(
65
- color = theme.colors.background.surface,
66
- shape = RoundedCornerShape(Radius.S),
67
- )
68
- .conditional(IsShowBaseLineDebug) {
69
- border(1.dp, Colors.blue_03)
70
- }
71
- .padding(Spacing.M),
72
- verticalAlignment = Alignment.CenterVertically,
73
- ) {
74
- if (image.isNotEmpty()) {
75
- Image(
76
- source = image,
77
- modifier = Modifier
78
- .size(32.dp)
79
- .clip(RoundedCornerShape(Radius.XS)),
80
- )
81
- Spacer(modifier = Modifier.width(Spacing.S))
82
- }
83
-
84
- val annotatedMessage = remember(message, boldMessage) {
85
- if (boldMessage.isNotEmpty()) {
86
- val index = message.lowercase().indexOf(boldMessage.lowercase())
87
- if (index != -1) {
88
- buildAnnotatedString {
89
- append(message.substring(0, index))
90
- withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
91
- append(message.substring(index, index + boldMessage.length))
92
- }
93
- append(message.substring(index + boldMessage.length))
94
- }
95
- } else {
96
- buildAnnotatedString { append(message) }
97
- }
98
- } else {
99
- buildAnnotatedString { append(message) }
100
- }
101
- }
102
-
103
- Text(
104
- text = annotatedMessage,
105
- style = Typography.bodyDefaultRegular,
106
- modifier = Modifier
107
- .weight(1f)
108
- .padding(end = Spacing.M),
109
- )
110
-
111
- Button(
112
- title = buttonTitle,
113
- type = ButtonType.TONAL,
114
- size = Size.SMALL,
115
- isFull = false,
116
- onClick = {
117
- onPressButton()
118
- },
119
- )
120
-
121
- Spacer(modifier = Modifier.width(Spacing.S))
122
-
123
- Icon(
124
- source = "navigation_close",
125
- size = 24.dp,
126
- color = theme.colors.text.default,
127
- modifier = Modifier.activeOpacityClickable { onClose() },
128
- )
129
- }
130
- }
131
- }