@momo-kits/native-kits 0.163.1-beta.2-debug → 0.163.1-beta.20-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 (245) hide show
  1. package/.claude/settings.local.json +112 -0
  2. package/CLAUDE.md +1 -1
  3. package/compose/build.gradle.kts +2 -1
  4. package/compose/build.gradle.kts.backup +1 -0
  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/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +30 -3
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +8 -10
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +2 -3
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +11 -9
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -1
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +40 -55
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +5 -5
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +3 -1
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +3 -6
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +19 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +28 -21
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +50 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +25 -22
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +37 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +68 -22
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -1
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +7 -1
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +112 -115
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +15 -3
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +33 -9
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +6 -5
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +3 -1
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +2 -1
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -1
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +23 -2
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +11 -0
  39. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  40. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +26 -3
  41. package/gradle/libs.versions.toml +2 -0
  42. package/gradle.properties +1 -1
  43. package/ios/Application/ApplicationEnvironment.swift +15 -3
  44. package/ios/Application/Components.swift +36 -30
  45. package/ios/Application/FloatingButton.swift +10 -9
  46. package/ios/Application/Localize.swift +309 -0
  47. package/ios/Application/MaxApi.swift +18 -0
  48. package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
  49. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
  50. package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
  51. package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
  52. package/ios/Application/Navigation/HeaderTitle.swift +57 -0
  53. package/ios/Application/Navigation/HeaderUser.swift +209 -0
  54. package/ios/Application/Navigation/NavigationContainer.swift +203 -0
  55. package/ios/Application/Navigation/NavigationOptions.swift +109 -0
  56. package/ios/Application/Navigation/Navigator.swift +385 -0
  57. package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
  58. package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
  59. package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
  60. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  61. package/ios/Application/Navigation/component/Header.swift +178 -0
  62. package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
  63. package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
  64. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +11 -0
  65. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +196 -0
  66. package/ios/Application/Screen.swift +2 -1
  67. package/ios/Application/StackScreen.swift +501 -0
  68. package/ios/Avatar/Avatar.swift +193 -0
  69. package/ios/Badge/Badge.swift +11 -14
  70. package/ios/Badge/BadgeRibbon.swift +91 -17
  71. package/ios/BaselineView/BaselineView.swift +163 -0
  72. package/ios/Button/Button.swift +137 -28
  73. package/ios/Carousel/Carousel.swift +196 -0
  74. package/ios/Checkbox/Checkbox.swift +23 -28
  75. package/ios/Chip/Chip.swift +56 -33
  76. package/ios/Collapse/Collapse.swift +192 -0
  77. package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
  78. package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
  79. package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
  80. package/ios/DateTimePicker/DateTimePicker.swift +212 -0
  81. package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
  82. package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
  83. package/ios/DateTimePicker/WheelPicker.swift +165 -0
  84. package/ios/Divider/Divider.swift +16 -0
  85. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  86. package/ios/Extensions/Color++.swift +32 -0
  87. package/ios/Icon/Icon.swift +10 -1
  88. package/ios/IconButton/IconButton.swift +140 -0
  89. package/ios/Image/Image.swift +16 -3
  90. package/ios/Information/Information.swift +3 -1
  91. package/ios/Input/ErrorView.swift +3 -1
  92. package/ios/Input/Input.swift +72 -33
  93. package/ios/Input/InputPhoneNumber.swift +33 -21
  94. package/ios/Input/InputSearch.swift +107 -48
  95. package/ios/Input/InputTextArea.swift +134 -64
  96. package/ios/InputDropDown/InputDropDown.swift +201 -0
  97. package/ios/InputMoney/InputMoney.swift +347 -0
  98. package/ios/InputOTP/InputOTP.swift +210 -0
  99. package/ios/Loader/Loader.swift +113 -0
  100. package/ios/MoMoUIKits.podspec +5 -0
  101. package/ios/Pagination/PaginationDot.swift +61 -0
  102. package/ios/Pagination/PaginationNumber.swift +35 -0
  103. package/ios/Pagination/PaginationScroll.swift +101 -0
  104. package/ios/Pagination/PaginationWhiteDot.swift +37 -0
  105. package/ios/Popup/PopupDisplay.swift +11 -20
  106. package/ios/Popup/PopupInput.swift +2 -8
  107. package/ios/Popup/PopupNotify.swift +218 -0
  108. package/ios/Popup/PopupPromotion.swift +5 -3
  109. package/ios/ProgressInfo/ProgressInfo.swift +296 -0
  110. package/ios/Radio/Radio.swift +69 -0
  111. package/ios/Rating/Rating.swift +82 -0
  112. package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
  113. package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
  114. package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
  115. package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
  116. package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
  117. package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
  118. package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
  119. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
  120. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
  121. package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
  122. package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
  123. package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
  124. package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
  125. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  126. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  127. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  128. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  129. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  130. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  131. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  132. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  133. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  134. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  135. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  136. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  137. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  138. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  139. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  140. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  141. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  142. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  143. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  144. package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
  145. package/ios/Skeleton/Skeleton.swift +99 -0
  146. package/ios/Slider/Slider.swift +237 -0
  147. package/ios/Stepper/Stepper.swift +220 -0
  148. package/ios/Steps/Steps.swift +467 -0
  149. package/ios/SuggestAction/SuggestAction.swift +99 -0
  150. package/ios/Swipeable/SwipeCell.swift +187 -0
  151. package/ios/Swipeable/SwipeCellModel.swift +21 -0
  152. package/ios/Switch/Switch.swift +53 -28
  153. package/ios/TabView/TabView.swift +534 -0
  154. package/ios/Tag/Tag.swift +98 -0
  155. package/ios/Template/TrustBanner/TrustBanner.swift +7 -8
  156. package/ios/Title/Title.swift +269 -0
  157. package/ios/Tooltip/Tooltip.swift +485 -0
  158. package/ios/Typography/FontScaleStore.swift +19 -0
  159. package/ios/Typography/Text.swift +86 -17
  160. package/ios/Typography/Typography.swift +12 -14
  161. package/ios/Uploader/Uploader.swift +174 -0
  162. package/ios/native-kits.podspec +61 -8
  163. package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
  164. package/ios-demo/README.md +120 -0
  165. package/ios-demo/Resources/dot_loading.json +558 -0
  166. package/ios-demo/Resources/icon.json +4052 -0
  167. package/ios-demo/Resources/lottie_circle_loader.json +1 -0
  168. package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
  169. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
  170. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
  171. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
  172. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
  173. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
  174. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
  175. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
  176. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
  177. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
  178. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
  179. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
  180. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
  181. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
  182. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
  183. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
  184. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
  185. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
  186. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +64 -0
  187. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
  188. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
  189. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
  190. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
  191. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
  192. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
  193. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
  194. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
  195. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
  196. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
  197. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
  198. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
  199. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
  200. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
  201. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
  202. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
  203. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
  204. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
  205. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
  206. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
  207. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
  208. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
  209. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
  210. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
  211. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
  212. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
  213. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
  214. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
  215. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
  216. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
  217. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
  218. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
  219. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
  220. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
  221. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
  222. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
  223. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
  224. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
  225. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
  226. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
  227. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
  228. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
  229. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
  230. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
  231. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
  232. package/local.properties +2 -2
  233. package/package.json +1 -1
  234. package/publish.sh +53 -0
  235. package/scripts/gen-ios-color.mjs +136 -0
  236. package/example/ios/Example.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  237. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  238. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
  239. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
  240. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
  241. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
  242. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
  243. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
  244. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -46
  245. package/ios/Application/FontScaleStore.swift +0 -59
@@ -28,6 +28,7 @@ import androidx.compose.runtime.remember
28
28
  import androidx.compose.runtime.rememberCoroutineScope
29
29
  import androidx.compose.ui.Alignment
30
30
  import androidx.compose.ui.Modifier
31
+ import androidx.compose.ui.graphics.Brush
31
32
  import androidx.compose.ui.graphics.Color
32
33
  import androidx.compose.ui.input.pointer.pointerInput
33
34
  import androidx.compose.ui.platform.LocalDensity
@@ -43,6 +44,7 @@ import vn.momo.kits.const.Radius
43
44
  import vn.momo.kits.const.Spacing
44
45
  import vn.momo.kits.application.LocalContext
45
46
  import vn.momo.kits.application.IsShowBaseLineDebug
47
+ import vn.momo.kits.const.AppNavigationBar
46
48
  import vn.momo.kits.const.Typography
47
49
  import vn.momo.kits.navigation.tracking.ScreenTracker
48
50
  import vn.momo.kits.modifier.conditional
@@ -56,10 +58,11 @@ internal fun BottomSheet(
56
58
  header: BottomHeader,
57
59
  isSurface: Boolean = false,
58
60
  barrierDismissible: Boolean = true,
61
+ draggable: Boolean = true,
62
+ useBottomInset: Boolean = true,
63
+ footerComponent: (@Composable () -> Unit)? = null,
59
64
  onDismiss: (() -> Unit)?
60
65
  ) {
61
- val navigator = LocalNavigator.current
62
-
63
66
  val screenHeightDp = getScreenHeight()
64
67
  val screenHeightPx = with(LocalDensity.current) { screenHeightDp.toPx() }
65
68
  val sheetOffset = remember { Animatable(screenHeightPx) }
@@ -117,7 +120,7 @@ internal fun BottomSheet(
117
120
  easing = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
118
121
  )
119
122
  )
120
- navigator.pop()
123
+ OverplayComponentRegistry.hardClearAfterDismiss()
121
124
  }
122
125
  }
123
126
 
@@ -162,30 +165,35 @@ internal fun BottomSheet(
162
165
  .noFeedbackClickable { },
163
166
  contentAlignment = Alignment.BottomCenter
164
167
  ) {
165
- Column {
168
+ val bottomInset = if (useBottomInset) {
169
+ (AppNavigationBar.current - keyboardSizeState().value).coerceAtLeast(0.dp)
170
+ } else 0.dp
171
+ Column(Modifier.padding(bottom = bottomInset)) {
166
172
  Box(
167
173
  modifier = Modifier
168
174
  .height(72.dp)
169
175
  .fillMaxWidth()
170
- .pointerInput(Unit) {
171
- detectDragGestures(
172
- onDrag = { change, dragAmount ->
173
- change.consume()
174
- coroutineScope.launch {
175
- val newOffset = (sheetOffset.value + dragAmount.y).coerceAtLeast(0f)
176
- sheetOffset.snapTo(newOffset)
177
- }
178
- },
179
- onDragEnd = {
180
- coroutineScope.launch {
181
- if (sheetOffset.value > sheetCloseOffset) {
182
- closeEvent()
183
- } else {
184
- sheetOffset.animateTo(0f)
176
+ .conditional(draggable) {
177
+ pointerInput(Unit) {
178
+ detectDragGestures(
179
+ onDrag = { change, dragAmount ->
180
+ change.consume()
181
+ coroutineScope.launch {
182
+ val newOffset = (sheetOffset.value + dragAmount.y).coerceAtLeast(0f)
183
+ sheetOffset.snapTo(newOffset)
184
+ }
185
+ },
186
+ onDragEnd = {
187
+ coroutineScope.launch {
188
+ if (sheetOffset.value > sheetCloseOffset) {
189
+ closeEvent()
190
+ } else {
191
+ sheetOffset.animateTo(0f)
192
+ }
185
193
  }
186
194
  }
187
- }
188
- )
195
+ )
196
+ }
189
197
  }
190
198
  ) {
191
199
  Column(
@@ -236,12 +244,50 @@ internal fun BottomSheet(
236
244
  }
237
245
  }
238
246
  Divider()
239
- content()
247
+ if (footerComponent != null) {
248
+ Box(Modifier.weight(1f, fill = false)) {
249
+ content()
250
+ }
251
+ BottomSheetFooter(footerComponent)
252
+ } else {
253
+ content()
254
+ }
240
255
  }
241
256
  }
242
257
  }
243
258
  }
244
259
 
260
+ @Composable
261
+ private fun BottomSheetFooter(footerComponent: @Composable () -> Unit) {
262
+ val shadowBrush = remember {
263
+ Brush.verticalGradient(
264
+ colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.05f))
265
+ )
266
+ }
267
+
268
+ Box {
269
+ Box(
270
+ Modifier
271
+ .fillMaxWidth()
272
+ .background(AppTheme.current.colors.background.surface)
273
+ .conditional(IsShowBaseLineDebug) {
274
+ border(1.dp, Colors.blue_03)
275
+ }
276
+ .padding(vertical = Spacing.S)
277
+ ) {
278
+ footerComponent()
279
+ }
280
+
281
+ Box(
282
+ modifier = Modifier
283
+ .fillMaxWidth()
284
+ .height(6.dp)
285
+ .offset(x = 0.dp, y = (-6).dp)
286
+ .background(shadowBrush)
287
+ )
288
+ }
289
+ }
290
+
245
291
  sealed class BottomHeader {
246
292
  data class Title(
247
293
  val data: String = "Bottom Sheet Title",
@@ -81,7 +81,7 @@ internal fun ModalScreen(
81
81
  targetValue = 0.8f,
82
82
  animationSpec = tween(durationMillis = 200)
83
83
  )
84
- navigator.pop()
84
+ OverplayComponentRegistry.hardClearAfterDismiss()
85
85
  }
86
86
  }
87
87
 
@@ -16,6 +16,10 @@ class Navigation(
16
16
  val currentOptions: State<NavigationOptions> get() = _options
17
17
  val options: NavigationOptions get() = _options.value
18
18
 
19
+ private val _isBottomTabRoot = mutableStateOf(false)
20
+ internal val isBottomTabRoot: Boolean get() = _isBottomTabRoot.value
21
+ internal fun markAsBottomTabRoot() { _isBottomTabRoot.value = true }
22
+
19
23
  fun setOptions(
20
24
  onBackHandler: (() -> Unit)? = null,
21
25
  hiddenBack: Boolean? = null,
@@ -81,7 +85,9 @@ data class NavigationOptions(
81
85
  val footerComponent: @Composable (() -> Unit)? = null,
82
86
  val floatingButtonProps: FloatingButtonProps? = null,
83
87
  val keyboardOptions: KeyboardOptions = KeyboardOptions()
84
- )
88
+ ) {
89
+ internal fun hasFooter() : Boolean = footerComponent != null
90
+ }
85
91
 
86
92
  data class KeyboardOptions(
87
93
  val keyboardShouldPersistTaps: Boolean = false,
@@ -1,17 +1,35 @@
1
1
  package vn.momo.kits.navigation
2
2
 
3
- import androidx.compose.animation.*
4
3
  import androidx.compose.animation.core.tween
5
- import androidx.compose.runtime.*
4
+ import androidx.compose.animation.fadeIn
5
+ import androidx.compose.animation.slideInHorizontally
6
+ import androidx.compose.animation.slideInVertically
7
+ import androidx.compose.animation.slideOutHorizontally
8
+ import androidx.compose.animation.slideOutVertically
9
+ import androidx.compose.runtime.Composable
10
+ import androidx.compose.runtime.CompositionLocalProvider
11
+ import androidx.compose.runtime.DisposableEffect
12
+ import androidx.compose.runtime.LaunchedEffect
13
+ import androidx.compose.runtime.mutableStateOf
14
+ import androidx.compose.runtime.remember
6
15
  import androidx.compose.runtime.saveable.rememberSaveable
16
+ import androidx.compose.runtime.staticCompositionLocalOf
7
17
  import androidx.compose.ui.unit.Dp
8
18
  import androidx.navigation.compose.NavHost
9
19
  import androidx.navigation.compose.composable
10
20
  import androidx.navigation.compose.rememberNavController
11
21
  import androidx.navigation.toRoute
12
- import vn.momo.kits.application.*
13
- import vn.momo.kits.const.*
22
+ import vn.momo.kits.application.LocalContext
23
+ import vn.momo.kits.application.LocalLocalize
24
+ import vn.momo.kits.application.Localize
25
+ import vn.momo.kits.application.MiniAppContext
26
+ import vn.momo.kits.const.AppNavigationBar
27
+ import vn.momo.kits.const.AppStatusBar
28
+ import vn.momo.kits.const.AppTheme
29
+ import vn.momo.kits.const.Theme
30
+ import vn.momo.kits.const.defaultTheme
14
31
  import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
32
+ import vn.momo.kits.platform.ProvideOsFontScale
15
33
  import vn.momo.kits.utils.getAppStatusBarHeight
16
34
  import vn.momo.kits.utils.getNavigationBarHeight
17
35
  import vn.momo.maxapi.IMaxApi
@@ -22,12 +40,12 @@ fun NavigationContainer(
22
40
  initialScreen: @Composable () -> Unit,
23
41
  options: NavigationOptions? = null,
24
42
  initialTheme: Theme = defaultTheme,
25
- miniappContext: MiniAppContext? = null,
26
- maxApi: IMaxApi?,
43
+ miniAppContext: MiniAppContext? = null,
44
+ maxApi: IMaxApi? = null,
27
45
  setNavigator: ((Navigator) -> Unit)? = null,
28
46
  statusBarHeight: Dp? = null,
29
47
  localize: Localize? = null,
30
- ){
48
+ ) {
31
49
  val navController = rememberNavController()
32
50
  val registry = remember { DynamicScreenRegistry() }
33
51
  val navigator = remember { Navigator(navController = navController, maxApi = maxApi, registry = registry) }
@@ -35,99 +53,101 @@ fun NavigationContainer(
35
53
  val navigationBarHeight = getNavigationBarHeight()
36
54
 
37
55
  val parentContext = LocalContext.current
38
- val mergedContext = MiniAppContext.merge(parentContext, miniappContext)
56
+ val mergedContext = MiniAppContext.merge(parentContext, miniAppContext)
39
57
 
40
- var observerFontScaleConfig by remember { mutableStateOf(mergedContext?.fontScaleConfig) }
41
- LaunchedEffect(maxApi) {
58
+ val theme = remember { mutableStateOf(initialTheme) }
59
+ val fallbackLocalize = remember { Localize() }
60
+
61
+ val resolvedLocalize = localize ?: fallbackLocalize
62
+
63
+ LaunchedEffect(maxApi, resolvedLocalize) {
42
64
  val api = maxApi ?: return@LaunchedEffect
43
65
  runCatching {
44
- api.observer(FONT_SCALE_OBSERVER_KEY).collect { data ->
45
- observerFontScaleConfig = parseFontScaleConfig(data)
46
- }
66
+ api.getLanguage(callback = { data ->
67
+ if (parseLanguage(data) == Localize.EN) {
68
+ resolvedLocalize.changeLanguage(Localize.EN)
69
+ }
70
+ })
47
71
  }
48
72
  }
49
73
 
50
- val theme = remember { mutableStateOf(initialTheme) }
51
-
52
- val fallbackLocalize = remember { Localize() }
53
- val resolvedLocalize = localize ?: fallbackLocalize
54
-
55
74
  val screenId = rememberSaveable { registry.nextId() }
56
75
  registry.bind(screenId, initialScreenName, initialScreen, options)
57
76
  val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
58
77
 
59
- ProvideNavigationEventDispatcherOwner {
60
- CompositionLocalProvider(
61
- LocalNavigator provides navigator,
62
- LocalDynamicScreenRegistry provides registry,
63
- LocalMaxApi provides maxApi,
64
- AppTheme provides theme.value,
65
- AppStatusBar provides statusBarHeight,
66
- AppNavigationBar provides navigationBarHeight,
67
- LocalContext provides mergedContext,
68
- LocalLocalize provides resolvedLocalize,
69
- LocalFontScaleConfig provides (observerFontScaleConfig ?: LocalFontScaleConfig.current),
78
+ ProvideOsFontScale {
79
+ ProvideNavigationEventDispatcherOwner {
80
+ CompositionLocalProvider(
81
+ LocalNavigator provides navigator,
82
+ LocalDynamicScreenRegistry provides registry,
83
+ LocalMaxApi provides maxApi,
84
+ AppTheme provides theme.value,
85
+ AppStatusBar provides statusBarHeight,
86
+ AppNavigationBar provides navigationBarHeight,
87
+ LocalContext provides mergedContext,
88
+ LocalLocalize provides resolvedLocalize,
70
89
  ) {
71
- LaunchedEffect(Unit) {
72
- setNavigator?.invoke(navigator)
73
- }
74
-
75
- NavHost(navController, startDestination = startDestination) {
76
- composable<DynamicScreenRoute>(
77
- enterTransition = {
78
- slideInHorizontally(
79
- animationSpec = tween(300),
80
- initialOffsetX = { it }
81
- )
82
- },
83
- exitTransition = null,
84
- popEnterTransition = { fadeIn(animationSpec = tween(0)) },
85
- popExitTransition = {
86
- slideOutHorizontally(
87
- animationSpec = tween(300),
88
- targetOffsetX = { it }
89
- )
90
- }
91
- ) { backStackEntry ->
92
- val route = backStackEntry.toRoute<DynamicScreenRoute>()
93
- val screen = registry.getScreen(route.id)
94
-
95
- if (screen != null) {
96
- StackScreen(
97
- id = route.id,
98
- name = screen.name,
99
- content = screen.content,
100
- navigationOptions = screen.options
101
- )
102
- }
90
+ LaunchedEffect(Unit) {
91
+ setNavigator?.invoke(navigator)
103
92
  }
104
93
 
105
- composable<DynamicDialogRoute>(
106
- enterTransition = {
107
- slideInVertically(
108
- animationSpec = tween(300),
109
- initialOffsetY = { it }
110
- )
111
- },
112
- exitTransition = null,
113
- popEnterTransition = { fadeIn(animationSpec = tween(0)) },
114
- popExitTransition = {
115
- slideOutVertically(
116
- animationSpec = tween(300),
117
- targetOffsetY = { it }
118
- )
94
+ NavHost(navController, startDestination = startDestination) {
95
+ composable<DynamicScreenRoute>(
96
+ enterTransition = {
97
+ slideInHorizontally(
98
+ animationSpec = tween(300),
99
+ initialOffsetX = { it }
100
+ )
101
+ },
102
+ exitTransition = null,
103
+ popEnterTransition = { fadeIn(animationSpec = tween(0)) },
104
+ popExitTransition = {
105
+ slideOutHorizontally(
106
+ animationSpec = tween(300),
107
+ targetOffsetX = { it }
108
+ )
109
+ }
110
+ ) { backStackEntry ->
111
+ val route = backStackEntry.toRoute<DynamicScreenRoute>()
112
+ val screen = registry.getScreen(route.id)
113
+
114
+ if (screen != null) {
115
+ StackScreen(
116
+ id = route.id,
117
+ name = screen.name,
118
+ content = screen.content,
119
+ navigationOptions = screen.options
120
+ )
121
+ }
119
122
  }
120
- ) { backStackEntry ->
121
- val route = backStackEntry.toRoute<DynamicDialogRoute>()
122
- val screen = registry.getScreen(route.id)
123
-
124
- if (screen != null) {
125
- StackScreen(
126
- id = route.id,
127
- name = screen.name,
128
- content = screen.content,
129
- navigationOptions = screen.options
130
- )
123
+
124
+ composable<DynamicDialogRoute>(
125
+ enterTransition = {
126
+ slideInVertically(
127
+ animationSpec = tween(300),
128
+ initialOffsetY = { it }
129
+ )
130
+ },
131
+ exitTransition = null,
132
+ popEnterTransition = { fadeIn(animationSpec = tween(0)) },
133
+ popExitTransition = {
134
+ slideOutVertically(
135
+ animationSpec = tween(300),
136
+ targetOffsetY = { it }
137
+ )
138
+ }
139
+ ) { backStackEntry ->
140
+ val route = backStackEntry.toRoute<DynamicDialogRoute>()
141
+ val screen = registry.getScreen(route.id)
142
+
143
+ if (screen != null) {
144
+ StackScreen(
145
+ id = route.id,
146
+ name = screen.name,
147
+ content = screen.content,
148
+ navigationOptions = screen.options
149
+ )
150
+ }
131
151
  }
132
152
  }
133
153
  }
@@ -142,34 +162,11 @@ fun NavigationContainer(
142
162
  }
143
163
  }
144
164
 
145
- val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
146
- error("No MaxApi provided")
147
- }
165
+ val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> { null }
148
166
 
149
- private const val FONT_SCALE_OBSERVER_KEY = "font_scale_config"
150
-
151
- private fun parseFontScaleConfig(raw: Map<String, Any?>?): FontScaleConfig? {
152
- if (raw.isNullOrEmpty()) return null
153
- @Suppress("UNCHECKED_CAST")
154
- val data = (raw["response"] as? Map<String, Any?>)
155
- ?: (raw["data"] as? Map<String, Any?>)
156
- ?: raw
157
- if (!data.containsKey("useOSFontScale") && !data.containsKey("userScaleRate")) return null
158
- val useOS = when (val v = data["useOSFontScale"]) {
159
- is Boolean -> v
160
- is String -> v.equals("true", ignoreCase = true)
161
- is Number -> v.toInt() != 0
162
- else -> true
163
- }
164
- val rate = when (val v = data["userScaleRate"]) {
165
- is Number -> v.toFloat()
166
- is String -> v.toFloatOrNull()
167
- else -> null
168
- }
169
- val osScale = when (val v = data["osFontScale"]) {
170
- is Number -> v.toFloat()
171
- is String -> v.toFloatOrNull()
172
- else -> null
173
- }
174
- return FontScaleConfig(useOSFontScale = useOS, userScaleRate = rate, osFontScale = osScale)
167
+ private fun parseLanguage(raw: Map<String, Any?>?): String? {
168
+ val code = (raw?.get("response") as? String)?.trim()?.lowercase()
169
+ if (code.isNullOrEmpty()) return null
170
+ return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
175
171
  }
172
+
@@ -139,10 +139,13 @@ class Navigator(
139
139
  isSurface: Boolean = false,
140
140
  barrierDismissible: Boolean = true,
141
141
  onDismiss: (() -> Unit)? = null,
142
- bottomSheetHeader: BottomHeader? = null
142
+ bottomSheetHeader: BottomHeader? = null,
143
+ draggable: Boolean = true,
144
+ useBottomInset: Boolean = true,
145
+ footerComponent: (@Composable () -> Unit)? = null
143
146
  ){
144
147
  val id = currentScreen()?.id ?: -1
145
- OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
148
+ OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader, draggable, useBottomInset, footerComponent)
146
149
  }
147
150
 
148
151
  fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
@@ -257,6 +260,9 @@ sealed class OverplayComponentParams {
257
260
  val onDismiss: (() -> Unit)? = null,
258
261
  val barrierDismissible: Boolean = true,
259
262
  val bottomSheetHeader: BottomHeader? = null,
263
+ val draggable: Boolean = true,
264
+ val useBottomInset: Boolean = true,
265
+ val footerComponent: (@Composable () -> Unit)? = null,
260
266
  ) : OverplayComponentParams()
261
267
 
262
268
  class SnackBar : OverplayComponentParams()
@@ -288,10 +294,13 @@ object OverplayComponentRegistry {
288
294
  barrierDismissible: Boolean = true,
289
295
  onDismiss: (() -> Unit)?,
290
296
  bottomSheetHeader: BottomHeader? = null,
297
+ draggable: Boolean = true,
298
+ useBottomInset: Boolean = true,
299
+ footerComponent: (@Composable () -> Unit)? = null,
291
300
  ){
292
301
  val params = when(type){
293
302
  OverplayComponentType.MODAL -> OverplayComponentParams.Modal(onDismiss, barrierDismissible)
294
- OverplayComponentType.BOTTOM_SHEET -> OverplayComponentParams.BottomSheet(isSurface, onDismiss, barrierDismissible, bottomSheetHeader)
303
+ OverplayComponentType.BOTTOM_SHEET -> OverplayComponentParams.BottomSheet(isSurface, onDismiss, barrierDismissible, bottomSheetHeader, draggable, useBottomInset, footerComponent)
295
304
  OverplayComponentType.SNACK_BAR -> OverplayComponentParams.SnackBar()
296
305
  }
297
306
 
@@ -333,6 +342,9 @@ object OverplayComponentRegistry {
333
342
  header = params.bottomSheetHeader ?: Title(),
334
343
  isSurface = params.isSurface,
335
344
  barrierDismissible = params.barrierDismissible,
345
+ draggable = params.draggable,
346
+ useBottomInset = params.useBottomInset,
347
+ footerComponent = params.footerComponent,
336
348
  onDismiss = params.onDismiss
337
349
  )
338
350
  }
@@ -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
@@ -77,6 +78,13 @@ import kotlin.time.ExperimentalTime
77
78
  internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
78
79
  internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
79
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
+
80
88
  @OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
81
89
  @Composable
82
90
  internal fun StackScreen(
@@ -96,6 +104,8 @@ internal fun StackScreen(
96
104
  val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions, registry = screenRegistry) }
97
105
 
98
106
  val options by navigation.currentOptions
107
+ val isBottomTabChild = bottomTabIndex != -1
108
+ val isBottomTabRoot = navigation.isBottomTabRoot
99
109
 
100
110
  // Auto tracking state
101
111
  val trackingState = remember {
@@ -193,30 +203,35 @@ internal fun StackScreen(
193
203
  }
194
204
 
195
205
  Column(Modifier.zIndex(2f).fillMaxSize()) {
196
- MainContent(content = content)
206
+ MainContent(content = content, isBottomTabRoot = isBottomTabRoot, isBottomTabChild = isBottomTabChild)
197
207
  FooterContent()
198
208
  }
199
209
 
200
210
  Box(Modifier.zIndex(6f)) {
201
- FloatingContent()
211
+ FloatingContent(isBottomTabChild = isBottomTabChild)
202
212
  }
203
213
 
204
- OverplayView(bottomTabIndex = bottomTabIndex, id = id)
214
+ OverplayView(isBottomTabChild = isBottomTabChild, id = id)
205
215
  }
206
216
  }
207
217
  }
208
218
 
209
219
  @Suppress("FrequentlyChangingValue")
210
220
  @Composable
211
- internal fun FloatingContent() {
221
+ internal fun FloatingContent(isBottomTabChild: Boolean) {
212
222
  val options = LocalOptions.current
213
223
  val density = LocalDensity.current
214
224
  val footerHeightPx = LocalFooterHeightPx.current
215
225
  val scrollState = LocalScrollState.current
226
+ val navigationBar = AppNavigationBar.current
216
227
 
217
228
  val fabProps = options.floatingButtonProps ?: return
218
229
  val bottomPadding = fabProps.bottom
219
- ?: (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
+ })
220
235
 
221
236
  FloatingButton(
222
237
  scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
@@ -232,11 +247,12 @@ internal fun FloatingContent() {
232
247
  }
233
248
 
234
249
  @Composable
235
- internal fun ColumnScope.MainContent(content: @Composable () -> Unit) {
250
+ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTabRoot: Boolean, isBottomTabChild: Boolean) {
236
251
  val options = LocalOptions.current
237
252
  val inputSearchType = getInputSearchType(options)
238
253
  val density = LocalDensity.current
239
254
  val scrollState = LocalScrollState.current
255
+ val navigationBar = AppNavigationBar.current
240
256
 
241
257
  Spacer(
242
258
  Modifier.height(
@@ -260,6 +276,14 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit) {
260
276
  .conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
261
277
  verticalScroll(scrollState)
262
278
  }
279
+ .padding(
280
+ bottom = when {
281
+ options.hasFooter() || isBottomTabRoot -> 0.dp
282
+ isBottomTabChild -> bottomTabBarInset() + (navigationBar - keyboardSizeState().value).coerceAtLeast(0.dp)
283
+ !options.scrollData.scrollable && options.scrollData.scrollState == null -> 0.dp
284
+ else -> navigationBar
285
+ }
286
+ )
263
287
  ) {
264
288
  ScreenContent(content = content)
265
289
  }
@@ -289,7 +313,7 @@ internal fun ScreenContent(content: @Composable () -> Unit) {
289
313
  @Composable
290
314
  internal fun FooterContent() {
291
315
  val options = LocalOptions.current
292
- if (options.footerComponent != null) {
316
+ if (options.hasFooter()) {
293
317
  val keyboardSize = keyboardSizeState()
294
318
  val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
295
319
  Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
@@ -303,12 +327,12 @@ internal fun keyboardSizeState(): State<Dp> {
303
327
  }
304
328
 
305
329
  @Composable
306
- internal fun OverplayView(bottomTabIndex: Int, id: Int) {
330
+ internal fun OverplayView(isBottomTabChild: Boolean, id: Int) {
307
331
  val overplayType = OverplayComponentRegistry.getOverplayType()
308
332
 
309
333
  if (overplayType != null) {
310
334
  Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 7f).fillMaxSize()) {
311
- if (bottomTabIndex != -1) return@Box
335
+ if (isBottomTabChild) return@Box
312
336
  if (OverplayComponentRegistry.currentRootId() != id) return@Box
313
337
  OverplayComponentRegistry.OverlayComponent()
314
338
  }
@@ -18,12 +18,12 @@ import androidx.navigation.compose.rememberNavController
18
18
  import vn.momo.kits.const.AppNavigationBar
19
19
  import vn.momo.kits.const.AppTheme
20
20
  import vn.momo.kits.const.Spacing
21
+ import vn.momo.kits.navigation.KeyboardOptions
21
22
  import vn.momo.kits.navigation.LocalNavigation
22
23
  import vn.momo.kits.navigation.LocalNavigator
23
24
  import vn.momo.kits.navigation.NavigationOptions
24
25
  import vn.momo.kits.navigation.StackScreen
25
26
  import vn.momo.kits.navigation.component.HeaderType
26
- import vn.momo.kits.platform.getScreenHeight
27
27
 
28
28
  private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
29
29
  internal fun setBottomTabOption(index: Int, options: NavigationOptions){
@@ -52,15 +52,16 @@ fun BottomTab(
52
52
 
53
53
 
54
54
  LaunchedEffect(Unit){
55
+ navigation.markAsBottomTabRoot()
55
56
  navigation.setOptions(
56
- headerType = HeaderType.None
57
+ headerType = HeaderType.None,
58
+ keyboardOptions = KeyboardOptions(useAvoidKeyboard = false)
57
59
  )
58
60
  }
59
61
 
60
- Box(modifier = Modifier.fillMaxWidth().height(getScreenHeight()), contentAlignment = Alignment.BottomCenter) {
62
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
61
63
  Box(modifier = Modifier
62
64
  .fillMaxSize()
63
- .padding(bottom = BOTTOM_TAB_BAR_HEIGHT.dp + AppNavigationBar.current)
64
65
  ) {
65
66
  NavHost(
66
67
  navController = navController,
@@ -127,7 +128,7 @@ fun BottomTab(
127
128
  onTabSelected = {
128
129
  val currentRoute = navController.currentBackStackEntry?.destination?.route
129
130
  val targetRoute = "option$it"
130
- if (currentRoute != targetRoute){
131
+ if (currentRoute != targetRoute) {
131
132
  navController.navigate(targetRoute)
132
133
  }
133
134
  }