@momo-kits/native-kits 0.163.1-beta.8-debug → 0.163.1-beta.9-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 (220) hide show
  1. package/CLAUDE.md +1 -1
  2. package/compose/build.gradle.kts +1 -1
  3. package/compose/compose.podspec +1 -1
  4. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  5. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +30 -3
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +5 -0
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +1 -1
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +8 -2
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +63 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +32 -19
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +49 -0
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +1 -1
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -1
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +3 -1
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +93 -75
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +26 -7
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -1
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +23 -2
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +11 -0
  25. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  26. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +26 -3
  27. package/gradle.properties +1 -1
  28. package/ios/Application/ApplicationEnvironment.swift +15 -2
  29. package/ios/Application/Components.swift +50 -44
  30. package/ios/Application/FloatingButton.swift +10 -9
  31. package/ios/Application/HeaderRight.swift +79 -45
  32. package/ios/Application/Localize.swift +277 -0
  33. package/ios/Application/MaxApi.swift +18 -0
  34. package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
  35. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
  36. package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
  37. package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
  38. package/ios/Application/Navigation/HeaderTitle.swift +57 -0
  39. package/ios/Application/Navigation/HeaderUser.swift +209 -0
  40. package/ios/Application/Navigation/NavigationContainer.swift +200 -0
  41. package/ios/Application/Navigation/NavigationOptions.swift +109 -0
  42. package/ios/Application/Navigation/Navigator.swift +385 -0
  43. package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
  44. package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
  45. package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
  46. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  47. package/ios/Application/Navigation/component/Header.swift +178 -0
  48. package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
  49. package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
  50. package/ios/Application/Screen.swift +2 -1
  51. package/ios/Application/StackScreen.swift +501 -0
  52. package/ios/Avatar/Avatar.swift +193 -0
  53. package/ios/Badge/Badge.swift +11 -14
  54. package/ios/Badge/BadgeRibbon.swift +92 -21
  55. package/ios/BaselineView/BaselineView.swift +163 -0
  56. package/ios/Button/Button.swift +124 -29
  57. package/ios/Carousel/Carousel.swift +196 -0
  58. package/ios/Checkbox/Checkbox.swift +23 -28
  59. package/ios/Chip/Chip.swift +56 -33
  60. package/ios/Collapse/Collapse.swift +192 -0
  61. package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
  62. package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
  63. package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
  64. package/ios/DateTimePicker/DateTimePicker.swift +212 -0
  65. package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
  66. package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
  67. package/ios/DateTimePicker/WheelPicker.swift +165 -0
  68. package/ios/Divider/Divider.swift +16 -0
  69. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  70. package/ios/Extensions/Color++.swift +32 -0
  71. package/ios/Icon/Icon.swift +10 -1
  72. package/ios/IconButton/IconButton.swift +140 -0
  73. package/ios/Image/Image.swift +16 -3
  74. package/ios/Information/Information.swift +3 -1
  75. package/ios/Input/ErrorView.swift +3 -1
  76. package/ios/Input/Input.swift +72 -33
  77. package/ios/Input/InputPhoneNumber.swift +33 -21
  78. package/ios/Input/InputSearch.swift +107 -48
  79. package/ios/Input/InputTextArea.swift +134 -64
  80. package/ios/InputDropDown/InputDropDown.swift +201 -0
  81. package/ios/InputMoney/InputMoney.swift +347 -0
  82. package/ios/InputOTP/InputOTP.swift +210 -0
  83. package/ios/Loader/Loader.swift +113 -0
  84. package/ios/MoMoUIKits.podspec +5 -0
  85. package/ios/Pagination/PaginationDot.swift +61 -0
  86. package/ios/Pagination/PaginationNumber.swift +35 -0
  87. package/ios/Pagination/PaginationScroll.swift +101 -0
  88. package/ios/Pagination/PaginationWhiteDot.swift +37 -0
  89. package/ios/Popup/PopupDisplay.swift +11 -20
  90. package/ios/Popup/PopupInput.swift +2 -8
  91. package/ios/Popup/PopupNotify.swift +218 -0
  92. package/ios/Popup/PopupPromotion.swift +16 -8
  93. package/ios/ProgressInfo/ProgressInfo.swift +296 -0
  94. package/ios/Radio/Radio.swift +69 -0
  95. package/ios/Rating/Rating.swift +82 -0
  96. package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
  97. package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
  98. package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
  99. package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
  100. package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
  101. package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
  102. package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
  103. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
  104. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
  105. package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
  106. package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
  107. package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
  108. package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
  109. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  110. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  111. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  112. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  113. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  114. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  115. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  116. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  117. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  118. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  119. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  120. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  121. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  122. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  123. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  124. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  125. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  126. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  127. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  128. package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
  129. package/ios/Skeleton/Skeleton.swift +99 -0
  130. package/ios/Slider/Slider.swift +237 -0
  131. package/ios/Stepper/Stepper.swift +220 -0
  132. package/ios/Steps/Steps.swift +467 -0
  133. package/ios/SuggestAction/SuggestAction.swift +99 -0
  134. package/ios/Swipeable/SwipeCell.swift +187 -0
  135. package/ios/Swipeable/SwipeCellModel.swift +21 -0
  136. package/ios/Switch/Switch.swift +53 -28
  137. package/ios/TabView/TabView.swift +534 -0
  138. package/ios/Tag/Tag.swift +98 -0
  139. package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
  140. package/ios/Title/Title.swift +269 -0
  141. package/ios/Tooltip/Tooltip.swift +485 -0
  142. package/ios/Typography/FontScaleStore.swift +19 -0
  143. package/ios/Typography/Text.swift +79 -5
  144. package/ios/Typography/Typography.swift +3 -0
  145. package/ios/Uploader/Uploader.swift +174 -0
  146. package/ios/native-kits.podspec +61 -8
  147. package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
  148. package/ios-demo/README.md +120 -0
  149. package/ios-demo/Resources/dot_loading.json +558 -0
  150. package/ios-demo/Resources/icon.json +4052 -0
  151. package/ios-demo/Resources/lottie_circle_loader.json +1 -0
  152. package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
  153. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
  154. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
  155. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
  156. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
  157. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
  158. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
  159. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
  160. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
  161. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
  162. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
  163. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
  164. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
  165. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
  166. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
  167. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
  168. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
  169. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
  170. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +63 -0
  171. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
  172. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
  173. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
  174. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
  175. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
  176. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
  177. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
  178. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
  179. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
  180. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
  181. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
  182. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
  183. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
  184. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
  185. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
  186. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
  187. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
  188. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
  189. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
  190. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
  191. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
  192. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
  193. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
  194. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
  195. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
  196. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
  197. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
  198. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
  199. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
  200. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
  201. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
  202. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
  203. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
  204. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
  205. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
  206. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
  207. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
  208. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
  209. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
  210. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
  211. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
  212. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
  213. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
  214. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
  215. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
  216. package/local.properties +2 -2
  217. package/package.json +1 -1
  218. package/publish.sh +53 -0
  219. package/scripts/gen-ios-color.mjs +136 -0
  220. package/.claude/settings.local.json +0 -62
@@ -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
@@ -27,7 +45,7 @@ fun NavigationContainer(
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) }
@@ -57,77 +75,79 @@ fun NavigationContainer(
57
75
  registry.bind(screenId, initialScreenName, initialScreen, options)
58
76
  val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
59
77
 
60
- ProvideNavigationEventDispatcherOwner {
61
- CompositionLocalProvider(
62
- LocalNavigator provides navigator,
63
- LocalDynamicScreenRegistry provides registry,
64
- LocalMaxApi provides maxApi,
65
- AppTheme provides theme.value,
66
- AppStatusBar provides statusBarHeight,
67
- AppNavigationBar provides navigationBarHeight,
68
- LocalContext provides mergedContext,
69
- LocalLocalize provides resolvedLocalize,
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,9 +162,7 @@ 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
167
  private fun parseLanguage(raw: Map<String, Any?>?): String? {
150
168
  val code = (raw?.get("response") as? String)?.trim()?.lowercase()
@@ -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(
@@ -195,12 +203,12 @@ internal fun StackScreen(
195
203
  }
196
204
 
197
205
  Column(Modifier.zIndex(2f).fillMaxSize()) {
198
- MainContent(content = content, isBottomTab = isBottomTabRoot)
206
+ MainContent(content = content, isBottomTabRoot = isBottomTabRoot, isBottomTabChild = isBottomTabChild)
199
207
  FooterContent()
200
208
  }
201
209
 
202
210
  Box(Modifier.zIndex(6f)) {
203
- FloatingContent()
211
+ FloatingContent(isBottomTabChild = isBottomTabChild)
204
212
  }
205
213
 
206
214
  OverplayView(isBottomTabChild = isBottomTabChild, id = id)
@@ -210,7 +218,7 @@ internal fun StackScreen(
210
218
 
211
219
  @Suppress("FrequentlyChangingValue")
212
220
  @Composable
213
- internal fun FloatingContent() {
221
+ internal fun FloatingContent(isBottomTabChild: Boolean) {
214
222
  val options = LocalOptions.current
215
223
  val density = LocalDensity.current
216
224
  val footerHeightPx = LocalFooterHeightPx.current
@@ -219,7 +227,11 @@ internal fun FloatingContent() {
219
227
 
220
228
  val fabProps = options.floatingButtonProps ?: return
221
229
  val bottomPadding = fabProps.bottom
222
- ?: (Spacing.M + if (options.footerComponent != null) with(density) { footerHeightPx.intValue.toDp() } else navigationBar)
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
+ })
223
235
 
224
236
  FloatingButton(
225
237
  scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
@@ -235,7 +247,7 @@ internal fun FloatingContent() {
235
247
  }
236
248
 
237
249
  @Composable
238
- internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTab: Boolean) {
250
+ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTabRoot: Boolean, isBottomTabChild: Boolean) {
239
251
  val options = LocalOptions.current
240
252
  val inputSearchType = getInputSearchType(options)
241
253
  val density = LocalDensity.current
@@ -264,7 +276,14 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTa
264
276
  .conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
265
277
  verticalScroll(scrollState)
266
278
  }
267
- .padding(bottom = if (options.footerComponent != null || isBottomTab) 0.dp else navigationBar)
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
+ )
268
287
  ) {
269
288
  ScreenContent(content = content)
270
289
  }
@@ -294,7 +313,7 @@ internal fun ScreenContent(content: @Composable () -> Unit) {
294
313
  @Composable
295
314
  internal fun FooterContent() {
296
315
  val options = LocalOptions.current
297
- if (options.footerComponent != null) {
316
+ if (options.hasFooter()) {
298
317
  val keyboardSize = keyboardSizeState()
299
318
  val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
300
319
  Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
@@ -18,6 +18,7 @@ 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
@@ -53,7 +54,8 @@ fun BottomTab(
53
54
  LaunchedEffect(Unit){
54
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
 
@@ -5,10 +5,12 @@ import androidx.compose.foundation.background
5
5
  import androidx.compose.foundation.layout.Box
6
6
  import androidx.compose.foundation.layout.fillMaxSize
7
7
  import androidx.compose.runtime.Composable
8
+ import androidx.compose.runtime.LaunchedEffect
8
9
  import androidx.compose.runtime.getValue
10
+ import androidx.compose.runtime.rememberUpdatedState
11
+ import androidx.compose.runtime.snapshotFlow
9
12
  import androidx.compose.ui.Modifier
10
13
  import androidx.compose.ui.graphics.Color
11
- import io.github.alexzhirkevich.compottie.Compottie
12
14
  import io.github.alexzhirkevich.compottie.ExperimentalCompottieApi
13
15
  import io.github.alexzhirkevich.compottie.LottieCompositionSpec
14
16
  import io.github.alexzhirkevich.compottie.animateLottieCompositionAsState
@@ -23,6 +25,9 @@ internal fun ComposeLottieAnimation(
23
25
  path: String,
24
26
  tintColor: Color?,
25
27
  bgColor: Color?,
28
+ iterations: Int,
29
+ isPlaying: Boolean,
30
+ onEvent: ((String) -> Unit)?,
26
31
  modifier: Modifier,
27
32
  ) {
28
33
  val json = readJson(path)
@@ -49,9 +54,25 @@ internal fun ComposeLottieAnimation(
49
54
 
50
55
  val lottieState = animateLottieCompositionAsState(
51
56
  composition = composition,
52
- iterations = Compottie.IterateForever,
57
+ iterations = iterations,
58
+ isPlaying = isPlaying,
59
+ restartOnPlay = false,
53
60
  )
54
61
 
62
+ val currentOnEvent by rememberUpdatedState(onEvent)
63
+
64
+ LaunchedEffect(isPlaying) {
65
+ currentOnEvent?.invoke(if (isPlaying) LottieEvent.Start else LottieEvent.Pause)
66
+ }
67
+
68
+ LaunchedEffect(lottieState) {
69
+ var armed = false
70
+ snapshotFlow { lottieState.isAtEnd }.collect { atEnd ->
71
+ if (!atEnd) armed = true
72
+ else if (armed) { armed = false; currentOnEvent?.invoke(LottieEvent.Finish) }
73
+ }
74
+ }
75
+
55
76
  Box(modifier.background(bgColor ?: Color.Transparent)) {
56
77
  Image(
57
78
  painter = rememberLottiePainter(
@@ -0,0 +1,9 @@
1
+ package vn.momo.kits.platform
2
+
3
+ import androidx.compose.runtime.Composable
4
+
5
+ // Overrides LocalDensity.fontScale with the live OS Dynamic Type scale so text re-scales while a
6
+ // screen is visible. Wrapped inside the containers so every screen is covered, not just callers of
7
+ // the app-level wrappers.
8
+ @Composable
9
+ expect fun ProvideOsFontScale(content: @Composable () -> Unit)
@@ -43,12 +43,23 @@ fun supportsImePadding(): Boolean = when (val v = getOSVersion()) {
43
43
  is OSVersion.Android -> v.sdk > 29
44
44
  is OSVersion.IOS -> true
45
45
  }
46
+ const val LottieIterateForever: Int = Int.MAX_VALUE
47
+
48
+ object LottieEvent {
49
+ const val Start = "start"
50
+ const val Pause = "pause"
51
+ const val Finish = "finish"
52
+ }
53
+
46
54
  @Composable
47
55
  expect fun LottieAnimation(
48
56
  path: String,
49
57
  tintColor: Color? = null,
50
58
  bgColor: Color? = null,
51
59
  placedAsOverlay: Boolean = false,
60
+ iterations: Int = LottieIterateForever,
61
+ isPlaying: Boolean = true,
62
+ onEvent: ((String) -> Unit)? = null,
52
63
  modifier: Modifier = Modifier,
53
64
  useCompose: Boolean = false
54
65
  )
@@ -0,0 +1,66 @@
1
+ package vn.momo.kits.platform
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import androidx.compose.runtime.CompositionLocalProvider
5
+ import androidx.compose.runtime.DisposableEffect
6
+ import androidx.compose.runtime.mutableStateOf
7
+ import androidx.compose.runtime.remember
8
+ import androidx.compose.ui.platform.LocalDensity
9
+ import androidx.compose.ui.unit.Density
10
+ import kotlinx.cinterop.ExperimentalForeignApi
11
+ import kotlinx.cinterop.ObjCAction
12
+ import platform.Foundation.NSNotification
13
+ import platform.Foundation.NSNotificationCenter
14
+ import platform.Foundation.NSSelectorFromString
15
+ import platform.UIKit.UIContentSizeCategoryDidChangeNotification
16
+ import platform.UIKit.UIFont
17
+ import platform.UIKit.UIFontTextStyleBody
18
+ import platform.darwin.NSObject
19
+
20
+ // Compose MP iOS reads LocalDensity.fontScale once at ComposeUIViewController creation and does not
21
+ // recompose it when UIContentSizeCategory changes (Android tracks Configuration.fontScale live). We
22
+ // observe the notification and override LocalDensity.fontScale so scaleSize() recomposes live. The
23
+ // formula matches the SwiftUI kit (UIFont body point size / 17) so both iOS surfaces scale alike.
24
+ private const val DEFAULT_BODY_POINT_SIZE = 17.0
25
+
26
+ private fun currentOsFontScale(): Float =
27
+ (UIFont.preferredFontForTextStyle(UIFontTextStyleBody).pointSize / DEFAULT_BODY_POINT_SIZE).toFloat()
28
+
29
+ @OptIn(ExperimentalForeignApi::class)
30
+ @Composable
31
+ actual fun ProvideOsFontScale(content: @Composable () -> Unit) {
32
+ val osFontScale = remember { mutableStateOf(currentOsFontScale()) }
33
+
34
+ val listener = remember {
35
+ object : NSObject() {
36
+ @Suppress("unused")
37
+ @ObjCAction
38
+ fun contentSizeChanged(arg: NSNotification) {
39
+ osFontScale.value = currentOsFontScale()
40
+ }
41
+ }
42
+ }
43
+
44
+ DisposableEffect(Unit) {
45
+ NSNotificationCenter.defaultCenter.addObserver(
46
+ observer = listener,
47
+ selector = NSSelectorFromString(listener::contentSizeChanged.name + ":"),
48
+ name = UIContentSizeCategoryDidChangeNotification,
49
+ `object` = null,
50
+ )
51
+ onDispose {
52
+ NSNotificationCenter.defaultCenter.removeObserver(
53
+ observer = listener,
54
+ name = UIContentSizeCategoryDidChangeNotification,
55
+ `object` = null,
56
+ )
57
+ }
58
+ }
59
+
60
+ val density = LocalDensity.current
61
+ CompositionLocalProvider(
62
+ LocalDensity provides Density(density.density, osFontScale.value),
63
+ ) {
64
+ content()
65
+ }
66
+ }
@@ -11,6 +11,7 @@ import androidx.compose.runtime.LaunchedEffect
11
11
  import androidx.compose.runtime.getValue
12
12
  import androidx.compose.runtime.mutableStateOf
13
13
  import androidx.compose.runtime.remember
14
+ import androidx.compose.runtime.rememberUpdatedState
14
15
  import androidx.compose.runtime.setValue
15
16
  import androidx.compose.ui.ExperimentalComposeUiApi
16
17
  import androidx.compose.ui.InternalComposeUiApi
@@ -96,20 +97,41 @@ actual fun LottieAnimation(
96
97
  tintColor: Color?,
97
98
  bgColor: Color?,
98
99
  placedAsOverlay: Boolean,
100
+ iterations: Int,
101
+ isPlaying: Boolean,
102
+ onEvent: ((String) -> Unit)?,
99
103
  modifier: Modifier,
100
104
  useCompose: Boolean
101
105
  ) {
102
106
  if (useCompose) {
103
- ComposeLottieAnimation(path, tintColor, bgColor, modifier)
107
+ ComposeLottieAnimation(path, tintColor, bgColor, iterations, isPlaying, onEvent, modifier)
104
108
  return
105
109
  }
106
110
 
111
+ val loopCount = if (iterations == LottieIterateForever) -1.0 else iterations.toDouble()
112
+
107
113
  var animation by remember { mutableStateOf<CompatibleAnimation?>(null) }
114
+ val animationView = remember { mutableStateOf<CompatibleAnimationView?>(null) }
108
115
 
109
116
  LaunchedEffect(Unit) {
110
117
  animation = CompatibleAnimation(name = "compose-resources/composeResources/vn.momo.compose.resources/".plus(path), subdirectory = null, NSBundle.mainBundle)
111
118
  }
112
119
 
120
+ val currentOnEvent by rememberUpdatedState(onEvent)
121
+
122
+ LaunchedEffect(isPlaying) {
123
+ currentOnEvent?.invoke(if (isPlaying) LottieEvent.Start else LottieEvent.Pause)
124
+ }
125
+
126
+ LaunchedEffect(animationView.value, isPlaying) {
127
+ val view = animationView.value ?: return@LaunchedEffect
128
+ if (isPlaying) {
129
+ view.playWithCompletion(completion = { finished -> if (finished) currentOnEvent?.invoke(LottieEvent.Finish) })
130
+ } else {
131
+ view.pause()
132
+ }
133
+ }
134
+
113
135
  when (val value = animation) {
114
136
  null -> {
115
137
  Box(modifier)
@@ -126,7 +148,7 @@ actual fun LottieAnimation(
126
148
 
127
149
  setBackgroundColor(bgColor?.toUIColor() ?: UIColor.clearColor)
128
150
 
129
- setLoopAnimationCount(-1.0)
151
+ setLoopAnimationCount(loopCount)
130
152
  setAnimationSpeed(1.0)
131
153
 
132
154
  if (tintColor != null) {
@@ -140,12 +162,13 @@ actual fun LottieAnimation(
140
162
  setColorValue(uiColor, CompatibleAnimationKeypath("**.Stroke.Color"))
141
163
  }
142
164
 
143
- play()
165
+ animationView.value = this
144
166
  }
145
167
  },
146
168
 
147
169
  update = { view ->
148
170
  view.setBackgroundColor(bgColor?.toUIColor() ?: UIColor.clearColor)
171
+ view.setLoopAnimationCount(loopCount)
149
172
 
150
173
  if (tintColor != null) {
151
174
  val uiColor = tintColor.toUIColor()
package/gradle.properties CHANGED
@@ -18,7 +18,7 @@ kotlin.apple.xcodeCompatibility.nowarn=true
18
18
  name="ComposeKits"
19
19
  group=vn.momo.kits
20
20
  artifact.id=kits
21
- version=0.163.1-beta.8
21
+ version=0.163.1-beta.9
22
22
 
23
23
  repo=GitLab
24
24
  url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
@@ -41,10 +41,23 @@ public class ApplicationEnvironment: ObservableObject {
41
41
  let applicationContext: MiniAppContext?
42
42
  let composeApi: KitComposeApi?
43
43
  let config: KitConfig?
44
-
45
- public init(applicationContext: MiniAppContext? = nil, composeApi: KitComposeApi? = nil, config: KitConfig? = nil) {
44
+ let maxApi: MaxApi?
45
+
46
+ public init(applicationContext: MiniAppContext? = nil, composeApi: KitComposeApi? = nil, config: KitConfig? = nil, maxApi: MaxApi? = nil) {
46
47
  self.applicationContext = applicationContext
47
48
  self.composeApi = composeApi
48
49
  self.config = config
50
+ self.maxApi = maxApi
51
+ }
52
+ }
53
+
54
+ private struct ApplicationEnvironmentKey: EnvironmentKey {
55
+ static let defaultValue = ApplicationEnvironment()
56
+ }
57
+
58
+ public extension EnvironmentValues {
59
+ var applicationEnvironment: ApplicationEnvironment {
60
+ get { self[ApplicationEnvironmentKey.self] }
61
+ set { self[ApplicationEnvironmentKey.self] = newValue }
49
62
  }
50
63
  }