@momo-kits/native-kits 0.160.1-test.1-debug → 0.160.1-test.1

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