@momo-kits/native-kits 0.162.2-test.21-debug → 0.162.2-test.21

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