@momo-kits/native-kits 0.162.2-sp.1-debug → 0.162.2-sp.10-debug

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 (198) hide show
  1. package/.claude/settings.local.json +15 -1
  2. package/CLAUDE.md +78 -0
  3. package/compose/build.gradle.kts +12 -8
  4. package/compose/build.gradle.kts.backup +11 -7
  5. package/compose/compose.podspec +1 -1
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +2 -7
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +8 -11
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +6 -24
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +4 -19
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +1 -10
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +2 -2
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +1 -1
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +1 -1
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +5 -16
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +1 -1
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +6 -101
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +8 -19
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +8 -33
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +1 -1
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +22 -25
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +27 -29
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +3 -26
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +30 -31
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +3 -13
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -5
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +3 -11
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +3 -18
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +11 -11
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +42 -65
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -5
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +84 -59
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +13 -71
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +10 -51
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +6 -1
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +4 -21
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +1 -1
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +16 -75
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +5 -26
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +1 -1
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +3 -11
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +16 -40
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +3 -9
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -28
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +2 -13
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +4 -10
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +3 -28
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +8 -47
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +4 -25
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +2 -11
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +1 -17
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +1 -6
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +50 -111
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +1 -5
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -5
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +1 -12
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +4 -96
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +5 -7
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +2 -12
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +9 -21
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +2 -2
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +9 -14
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +8 -11
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +1 -1
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +11 -20
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -1
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -5
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -2
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +94 -4
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -2
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +2 -2
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +3 -7
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +12 -16
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +120 -93
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +48 -33
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +88 -63
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +9 -14
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +13 -31
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +1 -1
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +6 -24
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +11 -6
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +2 -1
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +9 -6
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +1 -1
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +3 -13
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +3 -2
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +1 -40
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -2
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -8
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +2 -17
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +1 -1
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +3 -3
  99. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +2 -3
  100. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  101. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -2
  102. package/gradle/libs.versions.toml +2 -0
  103. package/gradle.properties +1 -1
  104. package/ios/Application/ApplicationEnvironment.swift +15 -2
  105. package/ios/Application/Components.swift +16 -0
  106. package/ios/Application/HeaderRight.swift +79 -45
  107. package/ios/Application/Localize.swift +277 -0
  108. package/ios/Application/MaxApi.swift +18 -0
  109. package/ios/Application/Navigation/BottomTab/BottomTab.swift +3 -1
  110. package/ios/Application/Navigation/NavigationContainer.swift +53 -4
  111. package/ios/Application/Navigation/Navigator.swift +54 -29
  112. package/ios/Application/Navigation/Overplay/BottomSheet.swift +98 -18
  113. package/ios/Application/Navigation/Overplay/ModalScreen.swift +6 -0
  114. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  115. package/ios/Application/Screen.swift +2 -1
  116. package/ios/Application/StackScreen.swift +55 -3
  117. package/ios/Badge/BadgeRibbon.swift +80 -0
  118. package/ios/Button/Button.swift +67 -11
  119. package/ios/Carousel/Carousel.swift +16 -1
  120. package/ios/Checkbox/Checkbox.swift +14 -20
  121. package/ios/Chip/Chip.swift +35 -26
  122. package/ios/Collapse/Collapse.swift +11 -1
  123. package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
  124. package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
  125. package/ios/Colors+Radius+Spacing/Theme.swift +15 -15
  126. package/ios/DateTimePicker/DateTimePicker.swift +4 -2
  127. package/ios/DateTimePicker/WheelPicker.swift +7 -3
  128. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  129. package/ios/Extensions/Color++.swift +32 -0
  130. package/ios/Icon/Icon.swift +5 -1
  131. package/ios/IconButton/IconButton.swift +35 -7
  132. package/ios/Image/Image.swift +16 -3
  133. package/ios/Information/Information.swift +3 -1
  134. package/ios/Input/ErrorView.swift +3 -1
  135. package/ios/Input/Input.swift +31 -8
  136. package/ios/Input/InputPhoneNumber.swift +14 -3
  137. package/ios/Input/InputSearch.swift +7 -1
  138. package/ios/Input/InputTextArea.swift +78 -34
  139. package/ios/InputDropDown/InputDropDown.swift +4 -1
  140. package/ios/InputMoney/InputMoney.swift +16 -4
  141. package/ios/Popup/PopupDisplay.swift +3 -4
  142. package/ios/Popup/PopupNotify.swift +3 -4
  143. package/ios/ProgressInfo/ProgressInfo.swift +4 -2
  144. package/ios/Radio/Radio.swift +12 -13
  145. package/ios/Rating/Rating.swift +1 -1
  146. package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
  147. package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
  148. package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
  149. package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
  150. package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
  151. package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
  152. package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
  153. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
  154. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
  155. package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
  156. package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
  157. package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
  158. package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
  159. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  160. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  161. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  162. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  163. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  164. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  165. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  166. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  167. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  168. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  169. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  170. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  171. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  172. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  173. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  174. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  175. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  176. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  177. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  178. package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
  179. package/ios/Stepper/Stepper.swift +2 -2
  180. package/ios/Steps/Steps.swift +22 -6
  181. package/ios/SuggestAction/SuggestAction.swift +5 -3
  182. package/ios/Swipeable/SwipeCell.swift +5 -3
  183. package/ios/Switch/Switch.swift +53 -28
  184. package/ios/TabView/TabView.swift +18 -14
  185. package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
  186. package/ios/Tooltip/Tooltip.swift +3 -0
  187. package/ios/Typography/FontScaleStore.swift +19 -0
  188. package/ios/Typography/Text.swift +3 -0
  189. package/ios/Typography/Typography.swift +8 -5
  190. package/ios/Uploader/Uploader.swift +0 -9
  191. package/ios/native-kits.podspec +6 -3
  192. package/ios-demo/MoMoUIKitsDemo.podspec +5 -3
  193. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +9 -57
  194. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +21 -3
  195. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
  196. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +2 -0
  197. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +5 -4
  198. package/package.json +1 -1
@@ -9,6 +9,7 @@ import androidx.compose.runtime.staticCompositionLocalOf
9
9
  import androidx.compose.ui.Alignment
10
10
  import androidx.compose.ui.Modifier
11
11
  import androidx.navigation.NavController
12
+ import androidx.navigation.toRoute
12
13
  import kotlinx.coroutines.CoroutineScope
13
14
  import kotlinx.coroutines.Dispatchers
14
15
  import kotlinx.coroutines.SupervisorJob
@@ -21,30 +22,38 @@ import vn.momo.kits.components.PopupNotify
21
22
  import vn.momo.kits.navigation.BottomHeader.*
22
23
  import vn.momo.kits.navigation.component.SnackBar
23
24
  import vn.momo.maxapi.IMaxApi
25
+ import kotlin.time.Duration.Companion.milliseconds
24
26
 
25
27
  class Navigator(
26
28
  private val navController: NavController,
27
- private val maxApi: IMaxApi?
29
+ private val maxApi: IMaxApi?,
30
+ private val registry: DynamicScreenRegistry
28
31
  ) {
29
32
  private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
30
33
 
34
+ private fun currentScreen(): DynamicScreen? {
35
+ val entry = navController.currentBackStackEntry ?: return null
36
+ val id = runCatching { entry.toRoute<DynamicScreenRoute>().id }.getOrNull()
37
+ ?: runCatching { entry.toRoute<DynamicDialogRoute>().id }.getOrNull()
38
+ ?: return null
39
+ return registry.getScreen(id)
40
+ }
41
+
31
42
  fun push(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
32
- val route = DynamicScreenRegistry.register(screenName, content, options)
43
+ val route = registry.register(screenName, content, options)
33
44
  navController.navigate(DynamicScreenRoute(route.id))
34
45
  }
35
46
 
36
47
  fun replace(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
37
- if (navController.previousBackStackEntry != null){
38
- val latestScreen = DynamicScreenRegistry.getLatestScreen()
39
- latestScreen?.let { DynamicScreenRegistry.unregisterScreen(it.id) }
40
- navController.popBackStack()
41
- push(screenName, content, options)
42
- }
48
+ val replacedScreen = currentScreen()
49
+ replacedScreen?.let { registry.unregisterScreen(it.id) }
50
+ navController.popBackStack()
51
+ push(screenName, content, options)
43
52
  }
44
53
 
45
54
  fun onBackSafe(callBack: (() -> Unit)? = null) {
46
- val latestScreen = DynamicScreenRegistry.getLatestScreen()
47
- val options = latestScreen?.options
55
+ val currentScreen = currentScreen()
56
+ val options = currentScreen?.options
48
57
  if (options?.onBackHandler != null) {
49
58
  options.onBackHandler.invoke()
50
59
  return
@@ -87,31 +96,30 @@ class Navigator(
87
96
  }
88
97
  private suspend fun dismissOverplay(isDelay: Boolean = true) {
89
98
  OverplayComponentRegistry.clear()
90
- if (isDelay) delay(300L)
99
+ if (isDelay) delay(300L.milliseconds)
91
100
  OverplayComponentRegistry.hardClearAfterDismiss()
92
101
  }
93
102
 
94
103
  private suspend fun dismissScreen() {
95
104
  if (navController.previousBackStackEntry != null){
105
+ val dismissing = currentScreen()
96
106
  navController.popBackStack()
97
- delay(300L)
98
- DynamicScreenRegistry.getLatestScreen()?.let { it1 ->
99
- DynamicScreenRegistry.unregisterScreen(it1.id)
100
- }
107
+ delay(300L.milliseconds)
108
+ dismissing?.let { registry.unregisterScreen(it.id) }
101
109
  } else {
102
110
  maxApi?.dismiss { }
103
111
  }
104
112
  }
105
113
 
106
114
  fun present(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
107
- val route = DynamicScreenRegistry.register(screenName, content, options)
115
+ val route = registry.register(screenName, content, options)
108
116
  navController.navigate(DynamicDialogRoute(route.id))
109
117
  }
110
118
 
111
119
  fun reset(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
112
- DynamicScreenRegistry.unregisterAll()
120
+ registry.unregisterAll()
113
121
 
114
- val route = DynamicScreenRegistry.register(screenName, content, options)
122
+ val route = registry.register(screenName, content, options)
115
123
  navController.navigate(DynamicScreenRoute(route.id)) {
116
124
  popUpTo(0) { inclusive = true }
117
125
  }
@@ -122,7 +130,7 @@ class Navigator(
122
130
  barrierDismissible: Boolean = true,
123
131
  onDismiss: (() -> Unit)? = null
124
132
  ){
125
- val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
133
+ val id = currentScreen()?.id ?: -1
126
134
  OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.MODAL, false, barrierDismissible, onDismiss)
127
135
  }
128
136
 
@@ -133,12 +141,12 @@ class Navigator(
133
141
  onDismiss: (() -> Unit)? = null,
134
142
  bottomSheetHeader: BottomHeader? = null
135
143
  ){
136
- val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
144
+ val id = currentScreen()?.id ?: -1
137
145
  OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
138
146
  }
139
147
 
140
148
  fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
141
- val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
149
+ val id = currentScreen()?.id ?: -1
142
150
  scope.launch {
143
151
  OverplayComponentRegistry.registerOverplay(
144
152
  id = id,
@@ -154,7 +162,7 @@ class Navigator(
154
162
  fun hideSnackBar() {
155
163
  scope.launch {
156
164
  OverplayComponentRegistry.clear()
157
- delay(250L)
165
+ delay(250L.milliseconds)
158
166
  OverplayComponentRegistry.hardClearAfterDismiss()
159
167
  }
160
168
  }
@@ -181,12 +189,11 @@ data class DynamicScreen(
181
189
  var options: NavigationOptions? = null
182
190
  )
183
191
 
184
- object DynamicScreenRegistry {
192
+ class DynamicScreenRegistry {
185
193
  private val screens = mutableMapOf<Int, DynamicScreen>()
186
- private var idCounter = 1
187
194
 
188
195
  fun register(screenName: String, content: @Composable () -> Unit, options: NavigationOptions?): DynamicScreenRoute {
189
- val id = idCounter++
196
+ val id = nextGlobalId()
190
197
  screens[id] = DynamicScreen(
191
198
  id = id,
192
199
  name = screenName,
@@ -196,7 +203,7 @@ object DynamicScreenRegistry {
196
203
  return DynamicScreenRoute(id)
197
204
  }
198
205
 
199
- fun nextId(): Int = idCounter++
206
+ fun nextId(): Int = nextGlobalId()
200
207
 
201
208
  fun bind(id: Int, screenName: String, content: @Composable () -> Unit, options: NavigationOptions?) {
202
209
  screens[id] = DynamicScreen(
@@ -205,17 +212,13 @@ object DynamicScreenRegistry {
205
212
  content = content,
206
213
  options = options
207
214
  )
208
- if (id >= idCounter) idCounter = id + 1 // keep counter ahead after process-death restore
215
+ advanceGlobalIdPast(id) // keep counter ahead after process-death restore
209
216
  }
210
217
 
211
218
  fun unregisterScreen(id: Int) {
212
219
  screens.remove(id)
213
220
  }
214
221
 
215
- fun getLatestScreen(): DynamicScreen?{
216
- return screens.entries.lastOrNull()?.value
217
- }
218
-
219
222
  fun unregisterAll(){
220
223
  val ids = screens.keys.toList()
221
224
  for (id in ids) {
@@ -228,8 +231,20 @@ object DynamicScreenRegistry {
228
231
  fun setOptions(id: Int, options: NavigationOptions){
229
232
  screens[id]?.options = options
230
233
  }
234
+
235
+ companion object {
236
+ private var globalIdCounter = 1
237
+
238
+ private fun nextGlobalId(): Int = globalIdCounter++
239
+
240
+ private fun advanceGlobalIdPast(id: Int) {
241
+ if (id >= globalIdCounter) globalIdCounter = id + 1
242
+ }
243
+ }
231
244
  }
232
245
 
246
+ val LocalDynamicScreenRegistry = staticCompositionLocalOf<DynamicScreenRegistry?> { null }
247
+
233
248
 
234
249
  sealed class OverplayComponentParams {
235
250
  class Modal(
@@ -244,7 +259,7 @@ sealed class OverplayComponentParams {
244
259
  val bottomSheetHeader: BottomHeader? = null,
245
260
  ) : OverplayComponentParams()
246
261
 
247
- class SnackBar() : OverplayComponentParams()
262
+ class SnackBar : OverplayComponentParams()
248
263
  }
249
264
 
250
265
  data class OverplayComponent(
@@ -308,7 +323,7 @@ object OverplayComponentRegistry {
308
323
  }
309
324
 
310
325
  @Composable
311
- fun OverlayComponent(){
326
+ internal fun OverlayComponent(){
312
327
  val overplay = currentOverlayComponent.value ?: return
313
328
 
314
329
  when (val params = overplay.params) {
@@ -45,8 +45,8 @@ import androidx.compose.ui.layout.onGloballyPositioned
45
45
  import androidx.compose.ui.platform.LocalDensity
46
46
  import androidx.compose.ui.unit.Dp
47
47
  import androidx.compose.ui.unit.dp
48
- import androidx.compose.ui.unit.min
49
48
  import androidx.compose.ui.zIndex
49
+ import kotlinx.coroutines.flow.Flow
50
50
  import vn.momo.kits.components.InputSearch
51
51
  import vn.momo.kits.const.AppNavigationBar
52
52
  import vn.momo.kits.const.AppStatusBar
@@ -56,6 +56,7 @@ import vn.momo.kits.const.Colors
56
56
  import vn.momo.kits.const.Spacing
57
57
  import vn.momo.kits.modifier.conditional
58
58
  import vn.momo.kits.modifier.hideKeyboardOnTap
59
+ import vn.momo.kits.navigation.bottomtab.BOTTOM_TAB_BAR_HEIGHT
59
60
  import vn.momo.kits.navigation.component.FABPosition
60
61
  import vn.momo.kits.navigation.component.FloatingButton
61
62
  import vn.momo.kits.navigation.component.HEADER_HEIGHT
@@ -69,13 +70,21 @@ import vn.momo.kits.platform.supportsImePadding
69
70
  import vn.momo.kits.navigation.tracking.ScreenTracker
70
71
  import vn.momo.kits.navigation.tracking.ScreenTrackingState
71
72
  import kotlinx.coroutines.delay
72
- import vn.momo.kits.application.ApplicationContext
73
+ import vn.momo.kits.application.LocalContext
73
74
  import kotlin.time.Clock
75
+ import kotlin.time.Duration.Companion.milliseconds
74
76
  import kotlin.time.ExperimentalTime
75
77
 
76
78
  internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
77
79
  internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
78
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
+
79
88
  @OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
80
89
  @Composable
81
90
  internal fun StackScreen(
@@ -88,17 +97,20 @@ internal fun StackScreen(
88
97
  ) {
89
98
  val navigator = LocalNavigator.current
90
99
  val maxApi = LocalMaxApi.current
91
- val context = ApplicationContext.current
100
+ val context = LocalContext.current
92
101
  val statusBar = AppStatusBar.current
93
102
  val density = LocalDensity.current
94
- val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions) }
103
+ val screenRegistry = LocalDynamicScreenRegistry.current
104
+ val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions, registry = screenRegistry) }
95
105
 
96
106
  val options by navigation.currentOptions
107
+ val isBottomTabChild = bottomTabIndex != -1
108
+ val isBottomTabRoot = navigation.isBottomTabRoot
97
109
 
98
110
  // Auto tracking state
99
111
  val trackingState = remember {
100
112
  ScreenTrackingState().apply {
101
- startTime = Clock.System.now().toEpochMilliseconds()
113
+ time = Clock.System.now().toEpochMilliseconds()
102
114
  }
103
115
  }
104
116
 
@@ -119,8 +131,8 @@ internal fun StackScreen(
119
131
  )
120
132
 
121
133
  // Track screen displayed after 2 seconds (debounce)
122
- delay(2000)
123
- val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
134
+ delay(2000.milliseconds)
135
+ val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.time
124
136
  ScreenTracker.trackScreenDisplayed(
125
137
  maxApi = maxApi,
126
138
  context = context,
@@ -130,7 +142,7 @@ internal fun StackScreen(
130
142
  )
131
143
 
132
144
  // Track screen interacted after displayed
133
- val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
145
+ val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.time
134
146
  ScreenTracker.trackScreenInteracted(
135
147
  maxApi = maxApi,
136
148
  context = context,
@@ -191,29 +203,35 @@ internal fun StackScreen(
191
203
  }
192
204
 
193
205
  Column(Modifier.zIndex(2f).fillMaxSize()) {
194
- MainContent(content = content)
206
+ MainContent(content = content, isBottomTabRoot = isBottomTabRoot, isBottomTabChild = isBottomTabChild)
195
207
  FooterContent()
196
208
  }
197
209
 
198
210
  Box(Modifier.zIndex(6f)) {
199
- FloatingContent()
211
+ FloatingContent(isBottomTabChild = isBottomTabChild)
200
212
  }
201
213
 
202
- OverplayView(bottomTabIndex = bottomTabIndex, id = id)
214
+ OverplayView(isBottomTabChild = isBottomTabChild, id = id)
203
215
  }
204
216
  }
205
217
  }
206
218
 
219
+ @Suppress("FrequentlyChangingValue")
207
220
  @Composable
208
- fun FloatingContent() {
221
+ internal fun FloatingContent(isBottomTabChild: Boolean) {
209
222
  val options = LocalOptions.current
210
223
  val density = LocalDensity.current
211
224
  val footerHeightPx = LocalFooterHeightPx.current
212
225
  val scrollState = LocalScrollState.current
226
+ val navigationBar = AppNavigationBar.current
213
227
 
214
228
  val fabProps = options.floatingButtonProps ?: return
215
229
  val bottomPadding = fabProps.bottom
216
- ?: (Spacing.M + if (options.footerComponent != null) with(density) { footerHeightPx.intValue.toDp() } else 0.dp)
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
+ })
217
235
 
218
236
  FloatingButton(
219
237
  scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
@@ -229,11 +247,12 @@ fun FloatingContent() {
229
247
  }
230
248
 
231
249
  @Composable
232
- fun ColumnScope.MainContent(content: @Composable () -> Unit) {
250
+ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTabRoot: Boolean, isBottomTabChild: Boolean) {
233
251
  val options = LocalOptions.current
234
252
  val inputSearchType = getInputSearchType(options)
235
253
  val density = LocalDensity.current
236
254
  val scrollState = LocalScrollState.current
255
+ val navigationBar = AppNavigationBar.current
237
256
 
238
257
  Spacer(
239
258
  Modifier.height(
@@ -257,6 +276,14 @@ fun ColumnScope.MainContent(content: @Composable () -> Unit) {
257
276
  .conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
258
277
  verticalScroll(scrollState)
259
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 -> 0.dp
284
+ else -> navigationBar
285
+ }
286
+ )
260
287
  ) {
261
288
  ScreenContent(content = content)
262
289
  }
@@ -264,7 +291,7 @@ fun ColumnScope.MainContent(content: @Composable () -> Unit) {
264
291
  }
265
292
 
266
293
  @Composable
267
- fun ScreenContent(content: @Composable () -> Unit) {
294
+ internal fun ScreenContent(content: @Composable () -> Unit) {
268
295
  val scrollState = LocalScrollState.current
269
296
  val options = LocalOptions.current
270
297
 
@@ -284,9 +311,9 @@ fun ScreenContent(content: @Composable () -> Unit) {
284
311
  }
285
312
 
286
313
  @Composable
287
- fun FooterContent() {
314
+ internal fun FooterContent() {
288
315
  val options = LocalOptions.current
289
- if (options.footerComponent != null) {
316
+ if (options.hasFooter()) {
290
317
  val keyboardSize = keyboardSizeState()
291
318
  val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
292
319
  Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
@@ -294,18 +321,18 @@ fun FooterContent() {
294
321
  }
295
322
 
296
323
  @Composable
297
- fun keyboardSizeState(): State<Dp> {
324
+ internal fun keyboardSizeState(): State<Dp> {
298
325
  val bottom = WindowInsets.ime.asPaddingValues()
299
326
  return rememberUpdatedState(bottom.calculateBottomPadding())
300
327
  }
301
328
 
302
329
  @Composable
303
- fun OverplayView(bottomTabIndex: Int, id: Int) {
330
+ internal fun OverplayView(isBottomTabChild: Boolean, id: Int) {
304
331
  val overplayType = OverplayComponentRegistry.getOverplayType()
305
332
 
306
333
  if (overplayType != null) {
307
334
  Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 7f).fillMaxSize()) {
308
- if (bottomTabIndex != -1) return@Box
335
+ if (isBottomTabChild) return@Box
309
336
  if (OverplayComponentRegistry.currentRootId() != id) return@Box
310
337
  OverplayComponentRegistry.OverlayComponent()
311
338
  }
@@ -355,8 +382,9 @@ data class InputSearchLayoutParams(
355
382
  val endPadding: Dp
356
383
  )
357
384
 
385
+ @Suppress("FrequentlyChangingValue")
358
386
  @Composable
359
- fun SearchAnimated(
387
+ internal fun SearchAnimated(
360
388
  isScrollInProgress: Boolean
361
389
  ) {
362
390
  val scrollState = LocalScrollState.current
@@ -469,64 +497,61 @@ private fun quantize(value: Int, stepPx: Int): Int {
469
497
  }
470
498
 
471
499
  @Composable
472
- fun LazyListState.proxyScrollState(
500
+ internal fun LazyListState.proxyScrollState(
473
501
  thresholdPx: Int = 200,
474
502
  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
- }
503
+ ): Pair<ScrollState, Boolean> = proxyScroll(
504
+ source = this,
505
+ thresholdPx = thresholdPx,
506
+ stepPx = stepPx,
507
+ isScrollInProgress = { isScrollInProgress },
508
+ rawTargetFlow = {
509
+ snapshotFlow {
510
+ if (firstVisibleItemIndex == 0) firstVisibleItemScrollOffset
511
+ else SCROLLED_PAST_FIRST_ITEM_THRESHOLD
512
+ }
513
+ },
514
+ )
504
515
 
505
516
  @Composable
506
- fun ScrollState.proxyLimitedScrollState(
517
+ internal fun ScrollState.proxyLimitedScrollState(
507
518
  thresholdPx: Int = 200,
508
519
  stepPx: Int = 4
520
+ ): Pair<ScrollState, Boolean> = proxyScroll(
521
+ source = this,
522
+ thresholdPx = thresholdPx,
523
+ stepPx = stepPx,
524
+ isScrollInProgress = { isScrollInProgress },
525
+ rawTargetFlow = { snapshotFlow { value } },
526
+ )
527
+
528
+ @Composable
529
+ private fun proxyScroll(
530
+ source: Any,
531
+ thresholdPx: Int,
532
+ stepPx: Int,
533
+ isScrollInProgress: () -> Boolean,
534
+ rawTargetFlow: () -> Flow<Int>,
509
535
  ): Pair<ScrollState, Boolean> {
510
536
  val proxy = rememberScrollState()
511
537
  val locked = remember { mutableStateOf(false) }
512
538
 
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
539
+ LaunchedEffect(source, proxy, thresholdPx, stepPx) {
540
+ rawTargetFlow().collect { rawTarget ->
541
+ val shouldLock = rawTarget > thresholdPx
542
+ if (locked.value != shouldLock) locked.value = shouldLock
518
543
 
519
- val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
544
+ val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
520
545
 
521
- if (proxy.value != desired) {
522
- proxy.scrollTo(desired.coerceAtLeast(0))
523
- }
546
+ if (proxy.value != desired) {
547
+ proxy.scrollTo(desired.coerceAtLeast(0))
524
548
  }
549
+ }
525
550
  }
526
551
 
527
552
  val inProgress = remember { mutableStateOf(false) }
528
- LaunchedEffect(this, thresholdPx) {
529
- snapshotFlow { isScrollInProgress }
553
+ LaunchedEffect(source, thresholdPx) {
554
+ snapshotFlow { isScrollInProgress() }
530
555
  .collect { progressing ->
531
556
  inProgress.value = if (locked.value) false else progressing
532
557
  }
@@ -6,13 +6,7 @@ import androidx.compose.animation.fadeOut
6
6
  import androidx.compose.animation.scaleIn
7
7
  import androidx.compose.animation.scaleOut
8
8
  import androidx.compose.foundation.background
9
- import androidx.compose.foundation.layout.Box
10
- import androidx.compose.foundation.layout.Column
11
- import androidx.compose.foundation.layout.Spacer
12
- import androidx.compose.foundation.layout.fillMaxSize
13
- import androidx.compose.foundation.layout.fillMaxWidth
14
- import androidx.compose.foundation.layout.height
15
- import androidx.compose.foundation.layout.padding
9
+ import androidx.compose.foundation.layout.*
16
10
  import androidx.compose.runtime.Composable
17
11
  import androidx.compose.runtime.LaunchedEffect
18
12
  import androidx.compose.ui.Alignment
@@ -24,20 +18,20 @@ import androidx.navigation.compose.rememberNavController
24
18
  import vn.momo.kits.const.AppNavigationBar
25
19
  import vn.momo.kits.const.AppTheme
26
20
  import vn.momo.kits.const.Spacing
21
+ import vn.momo.kits.navigation.KeyboardOptions
27
22
  import vn.momo.kits.navigation.LocalNavigation
28
23
  import vn.momo.kits.navigation.LocalNavigator
29
24
  import vn.momo.kits.navigation.NavigationOptions
30
25
  import vn.momo.kits.navigation.StackScreen
31
26
  import vn.momo.kits.navigation.component.HeaderType
32
- import vn.momo.kits.platform.getScreenHeight
33
27
 
34
28
  private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
35
- fun setBottomTabOption(index: Int, options: NavigationOptions){
29
+ internal fun setBottomTabOption(index: Int, options: NavigationOptions){
36
30
  if (index in bottomTabOptionItems.indices) {
37
31
  bottomTabOptionItems[index] = options
38
32
  }
39
33
  }
40
- fun getBottomTabOption(index: Int): NavigationOptions? {
34
+ internal fun getBottomTabOption(index: Int): NavigationOptions? {
41
35
  return if (index in bottomTabOptionItems.indices) {
42
36
  bottomTabOptionItems[index]
43
37
  } else null
@@ -58,15 +52,16 @@ fun BottomTab(
58
52
 
59
53
 
60
54
  LaunchedEffect(Unit){
55
+ navigation.markAsBottomTabRoot()
61
56
  navigation.setOptions(
62
- headerType = HeaderType.None
57
+ headerType = HeaderType.None,
58
+ keyboardOptions = KeyboardOptions(useAvoidKeyboard = false)
63
59
  )
64
60
  }
65
61
 
66
- Box(modifier = Modifier.fillMaxWidth().height(getScreenHeight()), contentAlignment = Alignment.BottomCenter) {
62
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
67
63
  Box(modifier = Modifier
68
64
  .fillMaxSize()
69
- .padding(bottom = BOTTOM_TAB_BAR_HEIGHT.dp + AppNavigationBar.current)
70
65
  ) {
71
66
  NavHost(
72
67
  navController = navController,
@@ -133,7 +128,7 @@ fun BottomTab(
133
128
  onTabSelected = {
134
129
  val currentRoute = navController.currentBackStackEntry?.destination?.route
135
130
  val targetRoute = "option$it"
136
- if (currentRoute != targetRoute){
131
+ if (currentRoute != targetRoute) {
137
132
  navController.navigate(targetRoute)
138
133
  }
139
134
  }
@@ -5,19 +5,7 @@ import androidx.compose.animation.core.animateDpAsState
5
5
  import androidx.compose.animation.core.tween
6
6
  import androidx.compose.foundation.background
7
7
  import androidx.compose.foundation.border
8
- import androidx.compose.foundation.layout.Arrangement
9
- import androidx.compose.foundation.layout.Box
10
- import androidx.compose.foundation.layout.Column
11
- import androidx.compose.foundation.layout.Row
12
- import androidx.compose.foundation.layout.RowScope
13
- import androidx.compose.foundation.layout.Spacer
14
- import androidx.compose.foundation.layout.fillMaxSize
15
- import androidx.compose.foundation.layout.fillMaxWidth
16
- import androidx.compose.foundation.layout.height
17
- import androidx.compose.foundation.layout.offset
18
- import androidx.compose.foundation.layout.padding
19
- import androidx.compose.foundation.layout.size
20
- import androidx.compose.foundation.layout.width
8
+ import androidx.compose.foundation.layout.*
21
9
  import androidx.compose.foundation.shape.CircleShape
22
10
  import androidx.compose.foundation.shape.RoundedCornerShape
23
11
  import androidx.compose.runtime.Composable
@@ -32,26 +20,20 @@ import androidx.compose.ui.text.style.TextOverflow
32
20
  import androidx.compose.ui.unit.dp
33
21
  import androidx.navigation.NavController
34
22
  import androidx.navigation.compose.currentBackStackEntryAsState
35
- import vn.momo.kits.components.Badge
36
- import vn.momo.kits.components.Icon
37
- import vn.momo.kits.components.Text
38
- import vn.momo.kits.const.AppTheme
39
- import vn.momo.kits.const.Colors
40
- import vn.momo.kits.const.Radius
41
- import vn.momo.kits.const.Spacing
42
23
  import vn.momo.kits.application.IsShowBaseLineDebug
43
- import vn.momo.kits.components.BadgeDot
44
- import vn.momo.kits.components.DotSize
45
- import vn.momo.kits.const.Typography
24
+ import vn.momo.kits.components.*
25
+ import vn.momo.kits.const.*
26
+ import vn.momo.kits.modifier.InternalApi
46
27
  import vn.momo.kits.modifier.conditional
47
28
  import vn.momo.kits.modifier.noFeedbackClickable
48
29
  import vn.momo.kits.platform.getScreenDimensions
49
30
 
50
- val floatingButtonWidth = 75.dp
31
+ internal val floatingButtonWidth = 75.dp
32
+ @InternalApi
51
33
  const val BOTTOM_TAB_BAR_HEIGHT = 64
52
34
 
53
35
  @Composable
54
- fun BottomTabBar(
36
+ internal fun BottomTabBar(
55
37
  items: List<BottomTabItem>,
56
38
  floatingButton: BottomTabFloatingButton? = null,
57
39
  navController: NavController,
@@ -91,11 +73,11 @@ fun BottomTabBar(
91
73
  horizontalArrangement = Arrangement.SpaceAround,
92
74
  ) {
93
75
  if (floatingButton == null) {
94
- renderTabBarItem(items, 0, items.size, selectedIndex, onTabSelected)
76
+ RenderTabBarItem(items, 0, items.size, selectedIndex, onTabSelected)
95
77
  } else {
96
- renderTabBarItem(items, 0, mid, selectedIndex, onTabSelected)
78
+ RenderTabBarItem(items, 0, mid, selectedIndex, onTabSelected)
97
79
  Spacer(modifier = Modifier.width(floatingButtonWidth).padding(horizontal = Spacing.XXS))
98
- renderTabBarItem(items, mid, items.size, selectedIndex, onTabSelected)
80
+ RenderTabBarItem(items, mid, items.size, selectedIndex, onTabSelected)
99
81
  }
100
82
  }
101
83
 
@@ -124,7 +106,7 @@ fun BottomTabBar(
124
106
  }
125
107
 
126
108
  @Composable
127
- fun RowScope.renderTabBarItem(
109
+ internal fun RowScope.RenderTabBarItem(
128
110
  items: List<BottomTabItem>,
129
111
  fromIndex: Int,
130
112
  toIndex: Int,
@@ -143,7 +125,7 @@ fun RowScope.renderTabBarItem(
143
125
  }
144
126
 
145
127
  @Composable
146
- fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
128
+ internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
147
129
  fun isNumber(label: String): Boolean {
148
130
  val numberRegex = "^\\d+$".toRegex()
149
131
  return numberRegex.matches(label)
@@ -203,7 +185,7 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
203
185
  }
204
186
 
205
187
  @Composable
206
- fun FloatingButton(data: BottomTabFloatingButton) {
188
+ internal fun FloatingButton(data: BottomTabFloatingButton) {
207
189
  Column(
208
190
  modifier = Modifier
209
191
  .width(floatingButtonWidth)