@momo-kits/native-kits 0.152.4-beta.3 → 0.152.5

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 (155) hide show
  1. package/package.json +7 -6
  2. package/shared/build.gradle.kts +74 -0
  3. package/CODE_OF_CONDUCT.md +0 -133
  4. package/CONTRIBUTING.md +0 -114
  5. package/LICENSE +0 -20
  6. package/README.md +0 -7
  7. package/build.gradle.kts +0 -32
  8. package/compose/MoMoComposeKits.podspec +0 -54
  9. package/compose/build.gradle.kts +0 -149
  10. package/compose/src/androidMain/AndroidManifest.xml +0 -2
  11. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -105
  12. package/compose/src/commonMain/composeResources/files/lottie_circle_loader.json +0 -1
  13. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  14. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  22. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  23. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  24. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  25. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  26. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -306
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -715
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -214
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -236
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -77
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -27
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -334
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -345
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -90
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -131
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -69
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -143
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -179
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -111
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -384
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -160
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -234
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -223
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -232
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -236
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -228
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -50
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -34
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -85
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -33
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -338
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -95
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -64
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -89
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -84
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -208
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -172
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -199
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -237
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -13
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -191
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -258
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -59
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -49
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -232
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -111
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -94
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -159
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -232
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScaleSizeScope.kt +0 -17
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -459
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -169
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -216
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -180
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -251
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -31
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -385
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -38
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -62
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -88
  110. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -144
  111. package/gradle.properties +0 -19
  112. package/gradlew +0 -240
  113. package/gradlew.bat +0 -91
  114. package/ios/Application/ApplicationEnvironment.swift +0 -50
  115. package/ios/Application/Components.swift +0 -263
  116. package/ios/Application/ComposeApi.swift +0 -22
  117. package/ios/Application/FloatingButton.swift +0 -172
  118. package/ios/Application/HeaderRight.swift +0 -271
  119. package/ios/Application/Screen.swift +0 -249
  120. package/ios/Badge/BadgeDot.swift +0 -31
  121. package/ios/Button/Button.swift +0 -211
  122. package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +0 -126
  123. package/ios/Checkbox/Checkbox.swift +0 -81
  124. package/ios/Chip/Chip.swift +0 -96
  125. package/ios/Colors+Radius+Spacing/Colors.swift +0 -172
  126. package/ios/Colors+Radius+Spacing/Radius.swift +0 -22
  127. package/ios/Colors+Radius+Spacing/Spacing.swift +0 -12
  128. package/ios/Extensions/Color++.swift +0 -25
  129. package/ios/Icon/Icon.swift +0 -51
  130. package/ios/Image/Image.swift +0 -70
  131. package/ios/Input/Input.swift +0 -207
  132. package/ios/Input/InputPhoneNumber.swift +0 -176
  133. package/ios/Input/InputSearch.swift +0 -238
  134. package/ios/Input/InputTextArea.swift +0 -242
  135. package/ios/Lottie/LottieView.swift +0 -86
  136. package/ios/OTPKeyboard/KeyboardButton.swift +0 -41
  137. package/ios/OTPKeyboard/OTPKeyboard.swift +0 -145
  138. package/ios/Popup/PopupDisplay.swift +0 -284
  139. package/ios/Popup/PopupInput.swift +0 -96
  140. package/ios/Popup/PopupPromotion.swift +0 -73
  141. package/ios/PopupView/FullscreenPopup.swift +0 -251
  142. package/ios/PopupView/Modifiers.swift +0 -158
  143. package/ios/PopupView/PopupView.swift +0 -289
  144. package/ios/PopupView/Utils++.swift +0 -281
  145. package/ios/ScrollIndicator/ScrollIndicator.swift +0 -110
  146. package/ios/Swipeable/SwipeCell.swift +0 -278
  147. package/ios/Swipeable/SwipeCellModel.swift +0 -86
  148. package/ios/Switch/Switch.swift +0 -44
  149. package/ios/Template/Logo/Logo.swift +0 -75
  150. package/ios/Template/TrustBanner/TrustBanner.swift +0 -120
  151. package/ios/Theme.md +0 -18
  152. package/ios/Typography/Text.swift +0 -140
  153. package/ios/Typography/Typography.swift +0 -95
  154. package/ios/native-kits.podspec +0 -18
  155. package/settings.gradle.kts +0 -25
@@ -1,364 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.animation.core.LinearEasing
4
- import androidx.compose.animation.core.RepeatMode
5
- import androidx.compose.animation.core.animateFloat
6
- import androidx.compose.animation.core.infiniteRepeatable
7
- import androidx.compose.animation.core.rememberInfiniteTransition
8
- import androidx.compose.animation.core.tween
9
- import androidx.compose.foundation.Canvas
10
- import androidx.compose.foundation.OverscrollEffect
11
- import androidx.compose.foundation.background
12
- import androidx.compose.foundation.gestures.FlingBehavior
13
- import androidx.compose.foundation.gestures.ScrollableDefaults
14
- import androidx.compose.foundation.layout.Arrangement
15
- import androidx.compose.foundation.layout.Box
16
- import androidx.compose.foundation.layout.PaddingValues
17
- import androidx.compose.foundation.layout.fillMaxWidth
18
- import androidx.compose.foundation.layout.padding
19
- import androidx.compose.foundation.layout.size
20
- import androidx.compose.foundation.lazy.LazyColumn
21
- import androidx.compose.foundation.lazy.LazyListLayoutInfo
22
- import androidx.compose.foundation.lazy.LazyListScope
23
- import androidx.compose.foundation.lazy.LazyListState
24
- import androidx.compose.foundation.lazy.rememberLazyListState
25
- import androidx.compose.material.ExperimentalMaterialApi
26
- import androidx.compose.material.pullrefresh.PullRefreshIndicator
27
- import androidx.compose.material.pullrefresh.pullRefresh
28
- import androidx.compose.material.pullrefresh.rememberPullRefreshState
29
- import androidx.compose.runtime.Composable
30
- import androidx.compose.runtime.LaunchedEffect
31
- import androidx.compose.runtime.MutableState
32
- import androidx.compose.runtime.State
33
- import androidx.compose.runtime.mutableIntStateOf
34
- import androidx.compose.runtime.mutableStateOf
35
- import androidx.compose.runtime.remember
36
- import androidx.compose.runtime.snapshotFlow
37
- import androidx.compose.ui.Alignment
38
- import androidx.compose.ui.Modifier
39
- import androidx.compose.ui.composed
40
- import androidx.compose.ui.geometry.CornerRadius
41
- import androidx.compose.ui.geometry.Offset
42
- import androidx.compose.ui.geometry.Size
43
- import androidx.compose.ui.graphics.Color
44
- import androidx.compose.ui.graphics.drawscope.rotate
45
- import androidx.compose.ui.hapticfeedback.HapticFeedbackType
46
- import androidx.compose.ui.layout.Measurable
47
- import androidx.compose.ui.layout.MeasureResult
48
- import androidx.compose.ui.layout.MeasureScope
49
- import androidx.compose.ui.layout.layout
50
- import androidx.compose.ui.platform.LocalDensity
51
- import androidx.compose.ui.platform.LocalHapticFeedback
52
- import androidx.compose.ui.unit.Constraints
53
- import androidx.compose.ui.unit.IntOffset
54
- import androidx.compose.ui.unit.dp
55
- import kotlinx.coroutines.flow.collect
56
- import kotlinx.coroutines.flow.combine
57
- import kotlinx.coroutines.flow.distinctUntilChanged
58
- import vn.momo.kits.const.Spacing
59
- import vn.momo.kits.modifier.conditional
60
- import vn.momo.kits.platform.getPlatformName
61
-
62
- private const val BOX_KEY = "LazyColumnWithBouncing_BOX_KEY"
63
-
64
-
65
- @OptIn(ExperimentalMaterialApi::class)
66
- @Composable
67
- fun overScrollWithPullToRefresh(
68
- pullRefreshState: PullToRefreshCustomState?,
69
- ): OverscrollEffect {
70
- val density = LocalDensity.current
71
- val hapticFeedback = LocalHapticFeedback.current
72
-
73
- return remember(density) {
74
- CupertinoOverscrollEffect(
75
- pullRefreshState = if (pullRefreshState != null && pullRefreshState.sendHaptic != null) pullRefreshState
76
- else pullRefreshState?.copy(
77
- sendHaptic = {
78
- hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
79
- }),
80
- density = density.density,
81
- applyClip = false,
82
- )
83
- }
84
- }
85
-
86
- @OptIn(ExperimentalMaterialApi::class)
87
- @Composable
88
- fun LazyColumnWithBouncing(
89
- modifier: Modifier = Modifier,
90
- modifierIndicator: Modifier = Modifier,
91
- state: LazyListState = rememberLazyListState(),
92
- contentPadding: PaddingValues = PaddingValues(0.dp),
93
- reverseLayout: Boolean = false,
94
- verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
95
- horizontalAlignment: Alignment.Horizontal = Alignment.Start,
96
- flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
97
- userScrollEnabled: Boolean = true,
98
- pullRefreshState: PullToRefreshCustomState? = null,
99
- content: LazyListScope.() -> Unit,
100
- ) {
101
- val height = remember { mutableIntStateOf(0) }
102
- val maxConstraint = remember { mutableIntStateOf(0) }
103
-
104
- LaunchedEffect(Unit) {
105
- val addOn = 1
106
- combine(
107
- snapshotFlow { maxConstraint.value }.distinctUntilChanged(),
108
- snapshotFlow { state.layoutInfo }
109
- ) { cHeight, layoutInfo ->
110
- height.value = when {
111
- height.value == 0 && (state.canScrollForward || state.canScrollBackward) -> 0
112
- layoutInfo.viewportSize.height >= cHeight && height.value == 0 -> 0
113
- layoutInfo.visibleItemsInfo.lastOrNull()?.key != BOX_KEY -> 0
114
- else -> {
115
- val vH = layoutInfo.totalHeight
116
- (cHeight - (vH - height.value) + addOn).coerceIn(0, cHeight)
117
- }
118
- }
119
- }.collect()
120
- }
121
-
122
- val measureLayout =
123
- remember<MeasureScope.(Measurable, Constraints) -> MeasureResult>(maxConstraint) {
124
- { m, c ->
125
- val p = m.measure(c.copy(minHeight = 0))
126
- maxConstraint.value = c.maxHeight
127
- layout(p.width, p.height) {
128
- p.place(IntOffset.Zero)
129
- }
130
- }
131
- }
132
-
133
- if (getPlatformName() == "iOS") {
134
-
135
- val overscroll = overScrollWithPullToRefresh(
136
- pullRefreshState = remember {
137
- pullRefreshState
138
- })
139
-
140
- Box {
141
- IosIndicator(
142
- effect = overscroll,
143
- modifier = modifierIndicator.align(Alignment.TopCenter).padding(top = Spacing.L).size(24.dp),
144
- )
145
- LazyColumn(
146
- modifier = modifier
147
- .layout(measure = measureLayout),
148
- state = state,
149
- contentPadding = contentPadding,
150
- flingBehavior = flingBehavior,
151
- horizontalAlignment = horizontalAlignment,
152
- verticalArrangement = verticalArrangement,
153
- reverseLayout = reverseLayout,
154
- userScrollEnabled = userScrollEnabled,
155
- overscrollEffect = overscroll,
156
- ) {
157
- content()
158
- item(key = BOX_KEY) {
159
- FakeBox(height)
160
- }
161
- }
162
- }
163
- } else {
164
- val pullState = rememberPullRefreshState(
165
- refreshing = pullRefreshState?.refreshingState?.value ?: false,
166
- onRefresh = {
167
- pullRefreshState?.onRefresh()
168
- },
169
- )
170
-
171
- Box(
172
- contentAlignment = Alignment.TopCenter,
173
- modifier = Modifier.conditional(pullRefreshState != null) {
174
- pullRefresh(pullState)
175
- }) {
176
- LazyColumn(
177
- modifier = modifier.calculateHeight(height),
178
- state = state,
179
- contentPadding = contentPadding,
180
- flingBehavior = flingBehavior,
181
- horizontalAlignment = horizontalAlignment,
182
- verticalArrangement = verticalArrangement,
183
- reverseLayout = reverseLayout,
184
- userScrollEnabled = userScrollEnabled,
185
- ) {
186
- content()
187
- }
188
- if (pullRefreshState != null) {
189
- PullRefreshIndicator(
190
- pullRefreshState.refreshingState.value,
191
- pullState,
192
- modifierIndicator.align(Alignment.TopCenter)
193
- )
194
- }
195
-
196
- }
197
- }
198
- }
199
-
200
- @Composable
201
- private fun IosIndicator(
202
- effect: OverscrollEffect?,
203
- modifier: Modifier = Modifier,
204
- ) {
205
- if (effect !is CupertinoOverscrollEffect) return
206
- if (effect.pullRefreshState == null) return
207
- val state = effect.pullRefreshState
208
-
209
-
210
- SpinningProgressBarLoading(
211
- progress = state.position, modifier = modifier
212
- )
213
- }
214
-
215
- @Composable
216
- private fun SpinningProgressBarLoading(
217
- progress: State<Float>, modifier: Modifier = Modifier
218
- ) {
219
- if (progress.value <= 0) {
220
- return
221
- }
222
-
223
- val hapticFeedback = LocalHapticFeedback.current
224
- val isSendHaptic = remember { mutableStateOf(false) }
225
-
226
- val totalStep = 8
227
- val stepAngle = 360f / totalStep
228
- val baseOpacity = 1.0f / (totalStep + 2)
229
- val minAlpha = 0.2f
230
-
231
- val infiniteTransition = rememberInfiniteTransition()
232
- val angle = infiniteTransition.animateFloat(
233
- initialValue = 0f, targetValue = totalStep.toFloat(), animationSpec = infiniteRepeatable(
234
- animation = tween(totalStep * 100, easing = LinearEasing),
235
- repeatMode = RepeatMode.Restart
236
- )
237
- )
238
-
239
- LaunchedEffect(Unit) {
240
- snapshotFlow { progress.value }.collect {
241
- if (it >= 1.0f && !isSendHaptic.value) {
242
- hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
243
- isSendHaptic.value = true
244
- } else if (progress.value < 1.0f && isSendHaptic.value) {
245
- isSendHaptic.value = false
246
- }
247
- }
248
-
249
- }
250
-
251
- Canvas(modifier = modifier) {
252
- val percentage = progress.value
253
- val clampedProgress = percentage.coerceIn(0f, 1f)
254
- val value = (totalStep * clampedProgress).coerceIn(0f, totalStep.toFloat())
255
- val integerPart = value.toInt()
256
- val decimalPart = value - integerPart
257
-
258
- if (integerPart <= 0) return@Canvas
259
-
260
- val canvasWidth = size.width
261
- val canvasHeight = size.height
262
- val width = size.width * 0.3f
263
- val height = size.height / 8
264
- val cornerRadius = (width.coerceAtMost(height) / 2)
265
-
266
- if (percentage >= 1f) {
267
- for (i in 0..360 step 360 / totalStep) {
268
- rotate(i.toFloat()) {
269
- drawRoundRect(
270
- color = Color.LightGray.copy(alpha = .7f),
271
- topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
272
- size = Size(width, height),
273
- cornerRadius = CornerRadius(cornerRadius, cornerRadius)
274
- )
275
- }
276
- }
277
-
278
- val coefficient = 360f / totalStep
279
-
280
- for (i in 1..4) {
281
- rotate((angle.value.toInt() + i) * coefficient) {
282
- drawRoundRect(
283
- color = Color.Gray.copy(alpha = (0.2f + 0.2f * i).coerceIn(0f, 1f)),
284
- topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
285
- size = Size(width, height),
286
- cornerRadius = CornerRadius(cornerRadius, cornerRadius)
287
- )
288
- }
289
- }
290
- return@Canvas
291
- }
292
-
293
- val topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2)
294
- val rectSize = Size(width, height)
295
- val cornerRadiusValue = CornerRadius(cornerRadius, cornerRadius)
296
- repeat(integerPart) { i ->
297
- val angle = i * stepAngle - 90f
298
- val stepOpacity = 1f - (baseOpacity * i)
299
-
300
- val alpha = if (i == integerPart - 1) {
301
- (decimalPart * stepOpacity).coerceIn(minAlpha, 1f)
302
- } else {
303
- stepOpacity.coerceIn(minAlpha, 1f)
304
- }
305
-
306
- rotate(angle) {
307
- drawRoundRect(
308
- color = Color.Gray.copy(alpha = alpha),
309
- topLeft = topLeft,
310
- size = rectSize,
311
- cornerRadius = cornerRadiusValue
312
- )
313
- }
314
- }
315
- }
316
- }
317
-
318
- @Composable
319
- private fun FakeBox(height: MutableState<Int>) {
320
- Box(
321
- modifier = Modifier
322
- .dynamicHeight(height).fillMaxWidth().background(Color.Red),
323
- )
324
- }
325
-
326
- private fun Modifier.calculateHeight(
327
- height: MutableState<Int>,
328
- ) = this.layout { m, c ->
329
- val p = m.measure(
330
- constraints = c.copy(
331
- minHeight = 0
332
- )
333
- )
334
- val vH = p.height
335
- val cMaxHeight = c.maxHeight
336
- val addOn = 0.5.dp.roundToPx()
337
- var extraSpace = addOn + height.value
338
- if (height.value == 0) {
339
- extraSpace = 0
340
- }
341
- if (vH - extraSpace >= cMaxHeight && height.value != 0) {
342
- height.value = 0
343
- } else if (vH - extraSpace < cMaxHeight) {
344
- height.value = cMaxHeight - (vH - extraSpace) + addOn
345
- }
346
-
347
- layout(c.maxWidth, cMaxHeight) {
348
- p.place(IntOffset.Zero)
349
- }
350
- }
351
-
352
-
353
- private fun Modifier.dynamicHeight(height: MutableState<Int>) = composed {
354
- val measure = remember<MeasureScope.(Measurable, Constraints) -> MeasureResult>(this, height) {
355
- { m, c ->
356
- val p = m.measure(c)
357
- layout(c.maxWidth, height.value) { p.place(IntOffset.Zero) }
358
- }
359
- }
360
- this.layout(measure = measure)
361
- }
362
-
363
- private val LazyListLayoutInfo.totalHeight: Int
364
- get() = visibleItemsInfo.sumOf { it.size }
@@ -1,50 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.layout.Box
5
- import androidx.compose.foundation.layout.Row
6
- import androidx.compose.foundation.layout.padding
7
- import androidx.compose.foundation.layout.size
8
- import androidx.compose.foundation.shape.RoundedCornerShape
9
- import androidx.compose.runtime.Composable
10
- import androidx.compose.ui.Modifier
11
- import androidx.compose.ui.graphics.Color
12
- import androidx.compose.ui.unit.dp
13
- import vn.momo.kits.const.AppTheme
14
- import vn.momo.kits.const.Spacing
15
-
16
- @Composable
17
- fun Dot(active: Boolean = false, activeColor: Color, modifier: Modifier = Modifier) {
18
- return if (active) {
19
- Box(
20
- modifier = modifier.size(width = 12.dp, height = 4.dp).background(
21
- color = activeColor,
22
- shape = RoundedCornerShape(4.dp)
23
- )
24
- )
25
- } else {
26
- Box(
27
- modifier = modifier.size(4.dp)
28
- .background(
29
- color = AppTheme.current.colors.background.pressed,
30
- shape = RoundedCornerShape(4.dp)
31
- )
32
- )
33
- }
34
- }
35
-
36
- @Composable
37
- fun PaginationDot(
38
- activeIndex: Int = 0,
39
- dataLength: Int = 3
40
- ) {
41
- Row {
42
- for (i in 0 until dataLength) {
43
- Dot(
44
- i == activeIndex,
45
- AppTheme.current.colors.primary,
46
- modifier = Modifier.padding(end = if (i != dataLength - 1) Spacing.XS else 0.dp)
47
- )
48
- }
49
- }
50
- }
@@ -1,34 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.layout.BoxWithConstraints
5
- import androidx.compose.foundation.layout.padding
6
- import androidx.compose.foundation.shape.RoundedCornerShape
7
- import androidx.compose.runtime.Composable
8
- import androidx.compose.ui.Alignment
9
- import androidx.compose.ui.Modifier
10
- import androidx.compose.ui.graphics.Color
11
- import vn.momo.kits.const.Colors
12
- import vn.momo.kits.const.Spacing
13
- import vn.momo.kits.const.Typography
14
-
15
- @Composable
16
- fun PaginationNumber(
17
- activeIndex: Int = 0,
18
- dataLength: Int = 2
19
- ) {
20
- BoxWithConstraints(
21
- modifier = Modifier.background(
22
- color = Color(0x33000000),
23
- shape = RoundedCornerShape(Spacing.L)
24
- ),
25
- contentAlignment = Alignment.Center
26
- ) {
27
- Text(
28
- modifier = Modifier.padding(horizontal = Spacing.S),
29
- text = "${1 + activeIndex}/$dataLength",
30
- color = Colors.black_01,
31
- style = Typography.labelDefaultMedium
32
- )
33
- }
34
- }
@@ -1,85 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.horizontalScroll
5
- import androidx.compose.foundation.layout.Box
6
- import androidx.compose.foundation.layout.Column
7
- import androidx.compose.foundation.layout.Row
8
- import androidx.compose.foundation.layout.fillMaxWidth
9
- import androidx.compose.foundation.layout.height
10
- import androidx.compose.foundation.layout.offset
11
- import androidx.compose.foundation.layout.padding
12
- import androidx.compose.foundation.layout.width
13
- import androidx.compose.foundation.rememberScrollState
14
- import androidx.compose.foundation.shape.RoundedCornerShape
15
- import androidx.compose.runtime.Composable
16
- import androidx.compose.runtime.derivedStateOf
17
- import androidx.compose.runtime.getValue
18
- import androidx.compose.runtime.remember
19
- import androidx.compose.ui.Alignment
20
- import androidx.compose.ui.Modifier
21
- import androidx.compose.ui.draw.clip
22
- import androidx.compose.ui.unit.Dp
23
- import androidx.compose.ui.unit.dp
24
- import vn.momo.kits.const.AppTheme
25
- import vn.momo.kits.const.Spacing
26
-
27
- val INDICATOR_WIDTH = 24.dp
28
- val PROGRESS_WIDTH = 72.dp
29
-
30
- // Memoized offset calculation to avoid repeated computations during scroll
31
- private fun calculateOffset(currentPosition: Int, maxBound: Int): Dp {
32
- return if (maxBound == 0) 0.dp else {
33
- (PROGRESS_WIDTH - INDICATOR_WIDTH) * (currentPosition / maxBound.toFloat())
34
- }
35
- }
36
-
37
- @Composable
38
- fun PaginationScroll(
39
- modifier: Modifier = Modifier,
40
- content: @Composable () -> Unit
41
- ) {
42
- val scrollState = rememberScrollState()
43
- val theme = AppTheme.current
44
-
45
- // Use derivedStateOf to optimize scroll position calculations
46
- val indicatorOffset by remember {
47
- derivedStateOf {
48
- calculateOffset(scrollState.value, scrollState.maxValue)
49
- }
50
- }
51
-
52
- // Cache theme colors to avoid repeated access
53
- val (progressBackground, indicatorColor) = remember(theme) {
54
- theme.colors.background.pressed to theme.colors.primary
55
- }
56
-
57
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
58
- Row(
59
- modifier = modifier
60
- .fillMaxWidth()
61
- .padding(bottom = Spacing.L)
62
- .horizontalScroll(scrollState)
63
- ) {
64
- content()
65
- }
66
-
67
- // Progress indicator
68
- Box(
69
- modifier = Modifier
70
- .clip(RoundedCornerShape(Spacing.XS))
71
- .width(PROGRESS_WIDTH)
72
- .height(4.dp)
73
- .background(color = progressBackground)
74
- ) {
75
- Box(
76
- modifier = Modifier
77
- .offset(x = indicatorOffset)
78
- .clip(RoundedCornerShape(Spacing.XS))
79
- .width(INDICATOR_WIDTH)
80
- .height(4.dp)
81
- .background(color = indicatorColor)
82
- )
83
- }
84
- }
85
- }
@@ -1,33 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.layout.Row
5
- import androidx.compose.foundation.layout.padding
6
- import androidx.compose.foundation.shape.RoundedCornerShape
7
- import androidx.compose.runtime.Composable
8
- import androidx.compose.ui.Modifier
9
- import androidx.compose.ui.graphics.Color
10
- import androidx.compose.ui.unit.dp
11
- import vn.momo.kits.const.Colors
12
- import vn.momo.kits.const.Spacing
13
-
14
- @Composable
15
- fun PaginationWhiteDot(
16
- activeIndex: Int = 0,
17
- dataLength: Int = 3
18
- ) {
19
- Row(
20
- modifier = Modifier.background(
21
- color = Color(0x33000000),
22
- shape = RoundedCornerShape(Spacing.S)
23
- ).padding(Spacing.XS)
24
- ) {
25
- for (i in 0 until dataLength) {
26
- Dot(
27
- i == activeIndex,
28
- Colors.black_01,
29
- modifier = Modifier.padding(end = if (i != dataLength - 1) Spacing.XS else 0.dp)
30
- )
31
- }
32
- }
33
- }