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

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