@momo-kits/native-kits 0.161.2-beta.5-debug → 0.161.2-beta.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 (136) hide show
  1. package/package.json +1 -1
  2. package/build.gradle.kts +0 -11
  3. package/compose/build.gradle.kts +0 -186
  4. package/compose/build.gradle.kts.backup +0 -186
  5. package/compose/compose.podspec +0 -47
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -123
  8. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  9. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  10. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  11. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -109
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -305
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -927
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -121
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -403
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -85
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -340
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -198
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -123
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -94
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -136
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -224
  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 -76
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -148
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -188
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -116
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -452
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -172
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -255
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -235
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -233
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -259
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -241
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -92
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -352
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -103
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -338
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -70
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -96
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -348
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -256
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -494
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -131
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -215
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -96
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -531
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -92
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -130
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -214
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -590
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -177
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -192
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -205
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -239
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -285
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -57
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -14
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -50
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -253
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -133
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -100
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -145
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -345
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -556
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -161
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -243
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -187
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -279
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -32
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -370
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -131
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -167
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -62
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -66
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -70
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
  127. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -33
  128. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -186
  129. package/gradle/libs.versions.toml +0 -60
  130. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  131. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  132. package/gradle.properties +0 -26
  133. package/gradlew +0 -252
  134. package/gradlew.bat +0 -94
  135. package/local.properties +0 -8
  136. package/settings.gradle.kts +0 -64
@@ -1,556 +0,0 @@
1
- package vn.momo.kits.navigation
2
-
3
- import androidx.compose.animation.animateColorAsState
4
- import androidx.compose.animation.core.animateDpAsState
5
- import androidx.compose.foundation.ScrollState
6
- import androidx.compose.foundation.background
7
- import androidx.compose.foundation.border
8
- import androidx.compose.foundation.gestures.ScrollableState
9
- import androidx.compose.foundation.layout.Box
10
- import androidx.compose.foundation.layout.Column
11
- import androidx.compose.foundation.layout.ColumnScope
12
- import androidx.compose.foundation.layout.Spacer
13
- import androidx.compose.foundation.layout.WindowInsets
14
- import androidx.compose.foundation.layout.asPaddingValues
15
- import androidx.compose.foundation.layout.aspectRatio
16
- import androidx.compose.foundation.layout.fillMaxSize
17
- import androidx.compose.foundation.layout.fillMaxWidth
18
- import androidx.compose.foundation.layout.height
19
- import androidx.compose.foundation.layout.ime
20
- import androidx.compose.foundation.layout.imePadding
21
- import androidx.compose.foundation.layout.offset
22
- import androidx.compose.foundation.layout.padding
23
- import androidx.compose.foundation.lazy.LazyListState
24
- import androidx.compose.foundation.lazy.rememberLazyListState
25
- import androidx.compose.foundation.rememberScrollState
26
- import androidx.compose.foundation.verticalScroll
27
- import androidx.compose.material.ExperimentalMaterialApi
28
- import androidx.compose.runtime.Composable
29
- import androidx.compose.runtime.CompositionLocalProvider
30
- import androidx.compose.runtime.LaunchedEffect
31
- import androidx.compose.runtime.State
32
- import androidx.compose.runtime.getValue
33
- import androidx.compose.runtime.mutableIntStateOf
34
- import androidx.compose.runtime.mutableStateOf
35
- import androidx.compose.runtime.remember
36
- import androidx.compose.runtime.rememberUpdatedState
37
- import androidx.compose.runtime.snapshotFlow
38
- import androidx.compose.runtime.staticCompositionLocalOf
39
- import androidx.compose.ui.Alignment
40
- import androidx.compose.ui.Modifier
41
- import androidx.compose.ui.graphics.Brush
42
- import androidx.compose.ui.graphics.Color
43
- import androidx.compose.ui.graphics.lerp
44
- import androidx.compose.ui.layout.onGloballyPositioned
45
- import androidx.compose.ui.platform.LocalDensity
46
- import androidx.compose.ui.unit.Dp
47
- import androidx.compose.ui.unit.dp
48
- import androidx.compose.ui.unit.min
49
- import androidx.compose.ui.zIndex
50
- import vn.momo.kits.components.InputSearch
51
- import vn.momo.kits.const.AppNavigationBar
52
- import vn.momo.kits.const.AppStatusBar
53
- import vn.momo.kits.const.AppTheme
54
- import vn.momo.kits.application.IsShowBaseLineDebug
55
- import vn.momo.kits.const.Colors
56
- import vn.momo.kits.const.Spacing
57
- import vn.momo.kits.modifier.conditional
58
- import vn.momo.kits.modifier.hideKeyboardOnTap
59
- import vn.momo.kits.navigation.component.FABPosition
60
- import vn.momo.kits.navigation.component.FloatingButton
61
- import vn.momo.kits.navigation.component.HEADER_HEIGHT
62
- import vn.momo.kits.navigation.component.Header
63
- import vn.momo.kits.navigation.component.HeaderBackground
64
- import vn.momo.kits.navigation.component.HeaderRight
65
- import vn.momo.kits.navigation.component.HeaderType
66
- import vn.momo.kits.navigation.component.InputSearchType
67
- import vn.momo.kits.platform.BackHandler
68
- import vn.momo.kits.platform.supportsImePadding
69
- import vn.momo.kits.navigation.tracking.ScreenTracker
70
- import vn.momo.kits.navigation.tracking.ScreenTrackingState
71
- import kotlinx.coroutines.delay
72
- import vn.momo.kits.application.ApplicationContext
73
- import kotlin.time.Clock
74
- import kotlin.time.ExperimentalTime
75
-
76
- internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
77
- internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
78
-
79
- @OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
80
- @Composable
81
- internal fun StackScreen(
82
- content: @Composable () -> Unit,
83
- navigationOptions: NavigationOptions? = null,
84
- id: Int = -1,
85
- name: String = "",
86
- bottomTabIndex: Int = -1,
87
- onBackHandler: (() -> Unit)? = null,
88
- ) {
89
- val navigator = LocalNavigator.current
90
- val maxApi = LocalMaxApi.current
91
- val context = ApplicationContext.current
92
- val statusBar = AppStatusBar.current
93
- val density = LocalDensity.current
94
- val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions) }
95
-
96
- val options by navigation.currentOptions
97
-
98
- // Auto tracking state
99
- val trackingState = remember {
100
- ScreenTrackingState().apply {
101
- startTime = Clock.System.now().toEpochMilliseconds()
102
- }
103
- }
104
-
105
- // Determine action: push or back
106
- val action = remember {
107
- if (ScreenTracker.getLastScreenName() != null) "push" else "back"
108
- }
109
-
110
- // Auto tracking effects
111
- LaunchedEffect(name) {
112
- // Track screen navigated immediately
113
- ScreenTracker.trackScreenNavigated(
114
- maxApi = maxApi,
115
- context = context,
116
- screenName = name,
117
- action = action,
118
- state = trackingState
119
- )
120
-
121
- // Track screen displayed after 2 seconds (debounce)
122
- delay(2000)
123
- val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
124
- ScreenTracker.trackScreenDisplayed(
125
- maxApi = maxApi,
126
- context = context,
127
- screenName = name,
128
- duration = loadTime,
129
- state = trackingState
130
- )
131
-
132
- // Track screen interacted after displayed
133
- val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
134
- ScreenTracker.trackScreenInteracted(
135
- maxApi = maxApi,
136
- context = context,
137
- screenName = name,
138
- duration = interactionTime - loadTime,
139
- totalDuration = interactionTime,
140
- state = trackingState
141
- )
142
- }
143
-
144
- val limit = with(density) {
145
- (statusBar).toPx() + HEADER_HEIGHT
146
- }.toInt()
147
-
148
- val (scrollState, scrollInProcess) = if (options.scrollData.scrollState is LazyListState)
149
- (options.scrollData.scrollState as? LazyListState ?: rememberLazyListState()).proxyScrollState(limit, 15)
150
- else
151
- (options.scrollData.scrollState as? ScrollState ?: rememberScrollState()).proxyLimitedScrollState(limit, 15)
152
-
153
- val footerHeightPx = remember { mutableIntStateOf(0) }
154
- val headerRightWidthPx = remember { mutableIntStateOf(0) }
155
-
156
- if (navigation.options.scrollData.scrollToTopCallback != null) {
157
- RegisterScrollToTop(navigation.options.scrollData.scrollToTopCallback)
158
- }
159
-
160
- BackHandler(true) { navigator.onBackSafe() }
161
-
162
- CompositionLocalProvider(
163
- StackScreenScrollableState provides options.scrollData.scrollState,
164
- LocalNavigation provides navigation,
165
- LocalScrollState provides scrollState,
166
- LocalOptions provides options,
167
- LocalFooterHeightPx provides footerHeightPx,
168
- LocalHeaderRightWidthPx provides headerRightWidthPx
169
- ) {
170
- Box(
171
- Modifier
172
- .fillMaxSize()
173
- .background(options.backgroundColor ?: AppTheme.current.colors.background.default)
174
- .conditional(options.keyboardOptions.keyboardShouldPersistTaps) {
175
- hideKeyboardOnTap()
176
- }
177
- .conditional(options.keyboardOptions.useAvoidKeyboard && supportsImePadding()) {
178
- imePadding()
179
- }
180
- ) {
181
- Box(Modifier.zIndex(1f)) {
182
- HeaderBackground()
183
- }
184
-
185
- Box(Modifier.zIndex(4f)) {
186
- Header(onBackHandler)
187
- }
188
-
189
- Column(Modifier.zIndex(5f)) {
190
- SearchAnimated(isScrollInProgress = scrollInProcess)
191
- }
192
-
193
- Column(Modifier.zIndex(2f).fillMaxSize()) {
194
- MainContent(content = content)
195
- FooterContent()
196
- }
197
-
198
- Box(Modifier.zIndex(6f)) {
199
- FloatingContent()
200
- }
201
-
202
- OverplayView(bottomTabIndex = bottomTabIndex, id = id)
203
- }
204
- }
205
- }
206
-
207
- @Composable
208
- fun FloatingContent() {
209
- val options = LocalOptions.current
210
- val density = LocalDensity.current
211
- val footerHeightPx = LocalFooterHeightPx.current
212
- val scrollState = LocalScrollState.current
213
-
214
- val fabProps = options.floatingButtonProps ?: return
215
- val bottomPadding = fabProps.bottom
216
- ?: (Spacing.M + if (options.footerComponent != null) with(density) { footerHeightPx.intValue.toDp() } else 0.dp)
217
-
218
- FloatingButton(
219
- scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
220
- onClick = fabProps.onClick,
221
- containerColor = AppTheme.current.colors.primary,
222
- bottom = bottomPadding,
223
- icon = fabProps.icon,
224
- iconColor = fabProps.iconColor,
225
- text = fabProps.label,
226
- size = fabProps.size,
227
- position = fabProps.position ?: FABPosition.END,
228
- )
229
- }
230
-
231
- @Composable
232
- fun ColumnScope.MainContent(content: @Composable () -> Unit) {
233
- val options = LocalOptions.current
234
- val inputSearchType = getInputSearchType(options)
235
- val density = LocalDensity.current
236
- val scrollState = LocalScrollState.current
237
-
238
- Spacer(
239
- Modifier.height(
240
- if (options.headerType is HeaderType.DefaultOrExtended || (options.headerType is HeaderType.Transparent && !options.headerType.isFullScreenContent))
241
- AppStatusBar.current + HEADER_HEIGHT.dp else 0.dp
242
- )
243
- )
244
- if (inputSearchType == InputSearchType.Animated) {
245
- val scrollDp = with(density) { scrollState.value.toDp() }
246
-
247
- val animatedTopPadding by animateDpAsState(
248
- targetValue = (HEADER_HEIGHT.dp - scrollDp).coerceIn(0.dp, HEADER_HEIGHT.dp),
249
- label = "AnimatedTopPadding"
250
- )
251
- Spacer(Modifier.height(animatedTopPadding))
252
- }
253
- Column(
254
- Modifier
255
- .fillMaxWidth()
256
- .weight(1f)
257
- .conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
258
- verticalScroll(scrollState)
259
- }
260
- ) {
261
- ScreenContent(content = content)
262
- }
263
-
264
- }
265
-
266
- @Composable
267
- fun ScreenContent(content: @Composable () -> Unit) {
268
- val scrollState = LocalScrollState.current
269
- val options = LocalOptions.current
270
-
271
- if (options.headerType is HeaderType.Animated) {
272
- val animatedHeader = options.headerType
273
- Box {
274
- Box(Modifier.fillMaxWidth().aspectRatio(animatedHeader.aspectRatio.value)) {
275
- animatedHeader.composable.invoke(scrollState.value)
276
- }
277
- Box(Modifier.padding(top = AppStatusBar.current + HEADER_HEIGHT.dp + animatedHeader.layoutOffSet)) {
278
- content()
279
- }
280
- }
281
- } else {
282
- content()
283
- }
284
- }
285
-
286
- @Composable
287
- fun FooterContent() {
288
- val options = LocalOptions.current
289
- if (options.footerComponent != null) {
290
- val keyboardSize = keyboardSizeState()
291
- val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
292
- Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
293
- }
294
- }
295
-
296
- @Composable
297
- fun keyboardSizeState(): State<Dp> {
298
- val bottom = WindowInsets.ime.asPaddingValues()
299
- return rememberUpdatedState(bottom.calculateBottomPadding())
300
- }
301
-
302
- @Composable
303
- fun OverplayView(bottomTabIndex: Int, id: Int) {
304
- val overplayType = OverplayComponentRegistry.getOverplayType()
305
-
306
- if (overplayType != null) {
307
- Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 7f).fillMaxSize()) {
308
- if (bottomTabIndex != -1) return@Box
309
- if (OverplayComponentRegistry.currentRootId() != id) return@Box
310
- OverplayComponentRegistry.OverlayComponent()
311
- }
312
- }
313
- }
314
-
315
- @Composable
316
- fun Footer(footerComponent: @Composable (() -> Unit)?, bottomPadding: Dp) {
317
- if (footerComponent == null) return
318
-
319
- val footerHeightPx = LocalFooterHeightPx.current
320
-
321
- val shadowBrush = remember {
322
- Brush.verticalGradient(
323
- colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.05f))
324
- )
325
- }
326
-
327
- Box(Modifier.onGloballyPositioned {
328
- if (footerHeightPx.intValue != it.size.height) footerHeightPx.intValue = it.size.height
329
- }) {
330
- Box(
331
- Modifier
332
- .fillMaxWidth()
333
- .background(AppTheme.current.colors.background.surface)
334
- .conditional(IsShowBaseLineDebug) {
335
- border(1.dp, Colors.blue_03)
336
- }
337
- .padding(top = Spacing.S, start = Spacing.M, end = Spacing.M, bottom = bottomPadding + Spacing.S)
338
- ) {
339
- footerComponent.invoke()
340
- }
341
-
342
- Box(
343
- modifier = Modifier
344
- .fillMaxWidth()
345
- .height(6.dp)
346
- .offset(x = 0.dp, y = (-6).dp)
347
- .background(shadowBrush)
348
- )
349
- }
350
- }
351
-
352
- data class InputSearchLayoutParams(
353
- val topPadding: Dp,
354
- val startPadding: Dp,
355
- val endPadding: Dp
356
- )
357
-
358
- @Composable
359
- fun SearchAnimated(
360
- isScrollInProgress: Boolean
361
- ) {
362
- val scrollState = LocalScrollState.current
363
- val options = LocalOptions.current
364
- val navigator = LocalNavigator.current
365
- val density = LocalDensity.current
366
-
367
- val scrollDp = with(density) { scrollState.value.toDp() }
368
-
369
- val inputSearchType = getInputSearchType(options)
370
- val headerRightWidthPx = LocalHeaderRightWidthPx.current
371
- val headerRightWidthDp = with(density) { headerRightWidthPx.intValue.toDp() }
372
-
373
- if (inputSearchType == InputSearchType.None) return
374
- val inputSearchProps = (options.headerType as? HeaderType.DefaultOrExtended)?.inputSearchProps ?: return
375
-
376
- val minTopPadding = AppStatusBar.current
377
- val maxTopPadding = AppStatusBar.current + HEADER_HEIGHT.dp
378
- val minStartPadding = Spacing.M
379
- val maxStartPadding = if (options.hiddenBack) Spacing.M else 52.dp
380
- val minEndPadding = Spacing.M
381
- val maxEndPadding = headerRightWidthDp + if (options.headerRight is HeaderRight.None) Spacing.M else Spacing.M * 2
382
-
383
- val targetColor = lerp(
384
- AppTheme.current.colors.background.surface,
385
- AppTheme.current.colors.background.default,
386
- (scrollDp / minTopPadding).coerceIn(0f, 1f)
387
- )
388
- val animatedColor by animateColorAsState(targetValue = targetColor, label = "BackgroundColor")
389
-
390
- val layoutParams = when (inputSearchType) {
391
- InputSearchType.Header -> {
392
- InputSearchLayoutParams(
393
- topPadding = minTopPadding,
394
- startPadding = maxStartPadding,
395
- endPadding = maxEndPadding
396
- )
397
- }
398
-
399
- InputSearchType.Animated -> {
400
- val animatedTopPadding by animateDpAsState(
401
- targetValue = (maxTopPadding - scrollDp).coerceIn(minTopPadding, maxTopPadding),
402
- label = "AnimatedTopPadding"
403
- )
404
-
405
- val animatedStartPadding by animateDpAsState(
406
- targetValue = (minStartPadding + scrollDp).coerceIn(minStartPadding, maxStartPadding),
407
- label = "AnimatedStartPadding"
408
- )
409
-
410
- val animatedEndPadding by animateDpAsState(
411
- targetValue = (minEndPadding + scrollDp).coerceIn(minEndPadding, maxEndPadding),
412
- label = "AnimatedEndPadding"
413
- )
414
-
415
- val maxPadding = remember(maxTopPadding, maxStartPadding, maxEndPadding) {
416
- maxOf(maxEndPadding, maxStartPadding, maxTopPadding)
417
- }
418
- val snapScrollValue = with(density) { maxPadding.toPx().toInt() }
419
-
420
- LaunchedEffect(isScrollInProgress && scrollState.value != 0 && scrollState.value != snapScrollValue) {
421
- if (scrollDp < maxPadding) {
422
- if (!isScrollInProgress) {
423
- val midpoint = (maxTopPadding - minTopPadding) / 2
424
-
425
- if (scrollDp < midpoint) {
426
- scrollState.animateScrollTo(0)
427
- } else {
428
- scrollState.animateScrollTo(snapScrollValue)
429
- }
430
- }
431
- }
432
- }
433
-
434
- InputSearchLayoutParams(
435
- topPadding = animatedTopPadding,
436
- startPadding = animatedStartPadding,
437
- endPadding = animatedEndPadding
438
- )
439
- }
440
-
441
- InputSearchType.None -> return
442
- }
443
-
444
- Spacer(Modifier.height(layoutParams.topPadding))
445
- Box(
446
- modifier = Modifier
447
- .height(HEADER_HEIGHT.dp)
448
- .fillMaxWidth()
449
- .padding(
450
- start = layoutParams.startPadding,
451
- end = layoutParams.endPadding
452
- ),
453
- contentAlignment = Alignment.Center
454
- ) {
455
- InputSearch(
456
- inputSearchProps = inputSearchProps.copy(
457
- backgroundColor = animatedColor,
458
- onPressButtonText = {
459
- navigator.pop()
460
- }
461
- )
462
- )
463
- }
464
- }
465
-
466
- private fun quantize(value: Int, stepPx: Int): Int {
467
- if (stepPx <= 1) return value
468
- return (value / stepPx) * stepPx
469
- }
470
-
471
- @Composable
472
- fun LazyListState.proxyScrollState(
473
- thresholdPx: Int = 200,
474
- stepPx: Int = 4
475
- ): Pair<ScrollState, Boolean> {
476
- val scrollState = rememberScrollState()
477
- val locked = remember { mutableStateOf(false) }
478
-
479
- LaunchedEffect(this, scrollState, thresholdPx, stepPx) {
480
- snapshotFlow { firstVisibleItemIndex to firstVisibleItemScrollOffset }
481
- .collect { (index, offset) ->
482
- val rawTarget = if (index == 0) offset else SCROLLED_PAST_FIRST_ITEM_THRESHOLD
483
- val shouldLock = rawTarget > thresholdPx
484
- if (locked.value != shouldLock) locked.value = shouldLock
485
-
486
- val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
487
-
488
- if (scrollState.value != desired) {
489
- scrollState.scrollTo(desired.coerceAtLeast(0))
490
- }
491
- }
492
- }
493
-
494
- val inProgress = remember { mutableStateOf(false) }
495
- LaunchedEffect(this, thresholdPx) {
496
- snapshotFlow { isScrollInProgress }
497
- .collect { progressing ->
498
- inProgress.value = if (locked.value) false else progressing
499
- }
500
- }
501
-
502
- return scrollState to inProgress.value
503
- }
504
-
505
- @Composable
506
- fun ScrollState.proxyLimitedScrollState(
507
- thresholdPx: Int = 200,
508
- stepPx: Int = 4
509
- ): Pair<ScrollState, Boolean> {
510
- val proxy = rememberScrollState()
511
- val locked = remember { mutableStateOf(false) }
512
-
513
- LaunchedEffect(this, proxy, thresholdPx, stepPx) {
514
- snapshotFlow { value }
515
- .collect { rawTarget ->
516
- val shouldLock = rawTarget > thresholdPx
517
- if (locked.value != shouldLock) locked.value = shouldLock
518
-
519
- val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
520
-
521
- if (proxy.value != desired) {
522
- proxy.scrollTo(desired.coerceAtLeast(0))
523
- }
524
- }
525
- }
526
-
527
- val inProgress = remember { mutableStateOf(false) }
528
- LaunchedEffect(this, thresholdPx) {
529
- snapshotFlow { isScrollInProgress }
530
- .collect { progressing ->
531
- inProgress.value = if (locked.value) false else progressing
532
- }
533
- }
534
-
535
- return proxy to inProgress.value
536
- }
537
-
538
- private const val SCROLLED_PAST_FIRST_ITEM_THRESHOLD = 10_000
539
-
540
- internal val LocalScrollState = staticCompositionLocalOf<ScrollState> { error("No Scroll State provided") }
541
- internal val LocalOptions = staticCompositionLocalOf<NavigationOptions> { error("No NavigationOptions provided") }
542
-
543
- val StackScreenScrollableState = staticCompositionLocalOf<ScrollableState?> { null }
544
-
545
- internal fun getInputSearchType(options: NavigationOptions): InputSearchType {
546
- return when (val headerType = options.headerType) {
547
- is HeaderType.DefaultOrExtended -> when {
548
- headerType.inputSearchProps == null -> InputSearchType.None
549
- headerType.useAnimated -> InputSearchType.Animated
550
- else -> InputSearchType.Header
551
- }
552
-
553
- else -> InputSearchType.None
554
- }
555
- }
556
-