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