@momo-kits/native-kits 0.162.2-debug → 0.162.2-lottie.1

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 (154) hide show
  1. package/.claude/settings.local.json +14 -0
  2. package/CLAUDE.md +78 -0
  3. package/ios/Application/Components.swift +1 -0
  4. package/ios/Application/FloatingButton.swift +1 -0
  5. package/ios/Badge/Badge.swift +1 -0
  6. package/ios/Badge/BadgeRibbon.swift +2 -0
  7. package/ios/Button/Button.swift +1 -1
  8. package/ios/Checkbox/Checkbox.swift +1 -0
  9. package/ios/Information/Information.swift +151 -0
  10. package/ios/Input/Input.swift +1 -0
  11. package/ios/Input/InputPhoneNumber.swift +1 -0
  12. package/ios/Input/InputSearch.swift +3 -0
  13. package/ios/Input/InputTextArea.swift +1 -0
  14. package/ios/OTPKeyboard/KeyboardButton.swift +1 -1
  15. package/ios/Popup/PopupDisplay.swift +6 -0
  16. package/ios/Popup/PopupInput.swift +2 -0
  17. package/ios/Template/TrustBanner/TrustBanner.swift +2 -0
  18. package/ios/Typography/Text.swift +1 -0
  19. package/ios/Typography/Typography.swift +14 -5
  20. package/package.json +1 -1
  21. package/build.gradle.kts +0 -11
  22. package/compose/build.gradle.kts +0 -186
  23. package/compose/build.gradle.kts.backup +0 -186
  24. package/compose/compose.podspec +0 -47
  25. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  26. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -123
  27. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  28. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  29. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  30. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  31. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  32. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  33. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  34. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  35. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  36. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  37. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  38. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  39. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  40. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -109
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -305
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -921
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -121
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -403
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -85
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -340
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -198
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -123
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -94
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -136
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -224
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -148
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -188
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -116
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -452
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -172
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -255
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -235
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -233
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -259
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -241
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -92
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -352
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -103
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -338
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -70
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -96
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -348
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -256
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -494
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -131
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -215
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -96
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -531
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -92
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -135
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -214
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -590
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -177
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -192
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -205
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -239
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -285
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -57
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -14
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -50
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -253
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -133
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -104
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -145
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -345
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -556
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -161
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -243
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -187
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -315
  134. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
  135. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
  136. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -34
  137. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -370
  138. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -131
  139. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -167
  140. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -72
  141. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -66
  142. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  143. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -70
  144. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  145. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
  146. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -33
  147. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -186
  148. package/gradle/libs.versions.toml +0 -67
  149. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  150. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  151. package/gradle.properties +0 -26
  152. package/gradlew +0 -252
  153. package/gradlew.bat +0 -94
  154. package/settings.gradle.kts +0 -64
@@ -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
- }