@momo-kits/native-kits 0.300.3 → 0.300.4-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 (272) hide show
  1. package/CLAUDE.md +51 -7
  2. package/README.md +2 -2
  3. package/build.gradle.kts +13 -0
  4. package/compose/build.gradle.kts +197 -0
  5. package/compose/build.gradle.kts.backup +197 -0
  6. package/compose/compose.podspec +47 -0
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +20 -0
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
  10. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  11. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +153 -0
  12. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +110 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +1071 -0
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +81 -0
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +115 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +478 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +265 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +265 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +361 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +108 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +308 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +330 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +207 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +92 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +560 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +86 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +501 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +236 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +180 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +17 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +287 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +50 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +338 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +137 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +116 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +215 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +404 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +732 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +40 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +233 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +217 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +97 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +377 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +455 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +103 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +74 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +413 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +363 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +37 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +133 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +41 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +135 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +74 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +118 -0
  124. package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +44 -0
  125. package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +62 -0
  126. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +42 -0
  127. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
  128. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +36 -0
  129. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -0
  130. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  131. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +217 -0
  132. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
  133. package/gradle/libs.versions.toml +68 -0
  134. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  135. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  136. package/gradle.properties +26 -0
  137. package/gradlew +252 -0
  138. package/gradlew.bat +94 -0
  139. package/ios/Application/ApplicationEnvironment.swift +24 -6
  140. package/ios/Application/DesignSystemKits.swift +100 -0
  141. package/ios/Application/DesignSystemKitsPayload.swift +68 -0
  142. package/ios/Application/MaxApi.swift +30 -3
  143. package/ios/Avatar/Avatar.swift +4 -3
  144. package/ios/Badge/Badge.swift +6 -4
  145. package/ios/Badge/BadgeDot.swift +1 -1
  146. package/ios/Badge/BadgeRibbon.swift +8 -2
  147. package/ios/Button/Button.swift +15 -12
  148. package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +64 -18
  149. package/ios/Carousel/Carousel.swift +29 -12
  150. package/ios/Checkbox/Checkbox.swift +7 -3
  151. package/ios/Chip/Chip.swift +5 -4
  152. package/ios/Collapse/Collapse.swift +70 -19
  153. package/ios/Colors+Radius+Spacing/Colors.swift +10 -1
  154. package/ios/Colors+Radius+Spacing/Radius.swift +6 -0
  155. package/ios/DateTimePicker/DateTimePicker.swift +54 -20
  156. package/ios/DateTimePicker/WheelPicker.swift +103 -105
  157. package/ios/Divider/Divider.swift +37 -4
  158. package/ios/Extensions/Color++.swift +38 -9
  159. package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
  160. package/ios/Extensions/SkeletonUICompat.swift +11 -0
  161. package/ios/Icon/Icon.swift +21 -23
  162. package/ios/Icon/Icons.swift +1329 -0
  163. package/ios/IconButton/IconButton.swift +15 -7
  164. package/ios/Image/Image.swift +7 -23
  165. package/ios/Information/Information.swift +27 -9
  166. package/ios/Input/ErrorView.swift +2 -2
  167. package/ios/Input/Input.swift +171 -148
  168. package/ios/Input/InputPhoneNumber.swift +10 -9
  169. package/ios/Input/InputSearch.swift +107 -78
  170. package/ios/Input/InputTextArea.swift +133 -148
  171. package/ios/InputDropDown/InputDropDown.swift +10 -7
  172. package/ios/InputMoney/InputMoney.swift +32 -11
  173. package/ios/InputOTP/InputOTP.swift +22 -12
  174. package/ios/Layout/Card.swift +50 -0
  175. package/ios/Layout/GridContext.swift +187 -3
  176. package/ios/Layout/Item.swift +5 -4
  177. package/ios/Layout/ScreenLayout.swift +415 -0
  178. package/ios/Layout/Section.swift +4 -100
  179. package/ios/Loader/Loader.swift +5 -9
  180. package/ios/Lottie/LottieView.swift +14 -2
  181. package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +169 -29
  182. package/ios/Navigation/BottomTab/BottomTab.swift +332 -0
  183. package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +18 -7
  184. package/ios/Navigation/BottomTab/DuoBarCompression.swift +104 -0
  185. package/ios/Navigation/BottomTab/DuoTabBar.swift +329 -0
  186. package/ios/{Application → Navigation/Component}/FloatingButton.swift +43 -54
  187. package/ios/Navigation/Component/Header.swift +545 -0
  188. package/ios/Navigation/Component/HeaderBackground.swift +154 -0
  189. package/ios/Navigation/Component/HeaderJourney.swift +73 -0
  190. package/ios/Navigation/Component/HeaderLocation.swift +48 -0
  191. package/ios/Navigation/Component/HeaderRight.swift +425 -0
  192. package/ios/Navigation/Component/HeaderTitle.swift +36 -0
  193. package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +21 -24
  194. package/ios/Navigation/Component/SideBar.swift +183 -0
  195. package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +8 -8
  196. package/ios/Navigation/HostBackGestureBridge.swift +78 -0
  197. package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +9 -2
  198. package/ios/Navigation/Navigation.swift +204 -0
  199. package/ios/Navigation/NavigationContainer.swift +195 -0
  200. package/ios/{Application/Navigation → Navigation}/Navigator.swift +207 -107
  201. package/ios/Navigation/StackScreen.swift +930 -0
  202. package/ios/Navigation/StackTransition.swift +400 -0
  203. package/ios/Navigation/SwipeBackHaptic.swift +33 -0
  204. package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
  205. package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
  206. package/ios/Pagination/PaginationScroll.swift +2 -2
  207. package/ios/Popup/PopupDisplay.swift +72 -135
  208. package/ios/Popup/PopupInput.swift +10 -13
  209. package/ios/Popup/PopupLayout.swift +138 -0
  210. package/ios/Popup/PopupNotify.swift +59 -69
  211. package/ios/Popup/PopupPromotion.swift +31 -47
  212. package/ios/PopupView/FullscreenPopup.swift +13 -19
  213. package/ios/PopupView/PopupView.swift +1 -1
  214. package/ios/PopupView/Utils++.swift +0 -8
  215. package/ios/ProgressInfo/ProgressInfo.swift +4 -2
  216. package/ios/Radio/Radio.swift +2 -1
  217. package/ios/Rating/Rating.swift +9 -1
  218. package/ios/Resources/dot_loading.json +558 -0
  219. package/ios/Resources/lottie_circle_loader.json +1 -0
  220. package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
  221. package/ios/Skeleton/Skeleton.swift +22 -27
  222. package/ios/Slider/Slider.swift +16 -18
  223. package/ios/Stepper/Stepper.swift +7 -3
  224. package/ios/Steps/Steps.swift +8 -6
  225. package/ios/SuggestAction/SuggestAction.swift +5 -0
  226. package/ios/Swipeable/SwipeCell.swift +10 -6
  227. package/ios/Switch/Switch.swift +22 -20
  228. package/ios/TabView/TabView.swift +102 -21
  229. package/ios/Tag/Tag.swift +15 -4
  230. package/ios/Template/Logo/Logo.swift +2 -1
  231. package/ios/Template/TrustBanner/TrustBanner.swift +109 -55
  232. package/ios/Title/Title.swift +6 -17
  233. package/ios/Tooltip/Tooltip.swift +29 -14
  234. package/ios/Typography/FontScale.swift +17 -14
  235. package/ios/Typography/Text.swift +156 -20
  236. package/ios/Typography/Typography.swift +2 -2
  237. package/ios/Uploader/Uploader.swift +3 -1
  238. package/ios/native-kits.podspec +2 -3
  239. package/ios-demo/MoMoUIKitsDemo.podspec +1 -3
  240. package/ios-demo/README.md +120 -0
  241. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
  242. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
  243. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +2 -0
  244. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
  245. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
  246. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +1 -0
  247. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +2 -2
  248. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +2 -0
  249. package/package.json +1 -1
  250. package/publish.sh +19 -2
  251. package/scripts/gen-ios-icons.mjs +36 -0
  252. package/settings.gradle.kts +64 -0
  253. package/ios/Application/Components.swift +0 -270
  254. package/ios/Application/ComposeApi.swift +0 -22
  255. package/ios/Application/HeaderRight.swift +0 -306
  256. package/ios/Application/Navigation/BottomTab/BottomTab.swift +0 -104
  257. package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
  258. package/ios/Application/Navigation/HeaderTitle.swift +0 -57
  259. package/ios/Application/Navigation/NavigationContainer.swift +0 -213
  260. package/ios/Application/Navigation/NavigationOptions.swift +0 -109
  261. package/ios/Application/Navigation/NavigatorManager.swift +0 -22
  262. package/ios/Application/Navigation/component/Header.swift +0 -178
  263. package/ios/Application/Navigation/component/HeaderBackground.swift +0 -83
  264. package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
  265. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
  266. package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
  267. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -196
  268. package/ios/Application/Screen.swift +0 -250
  269. package/ios/Application/StackScreen.swift +0 -492
  270. package/ios/Typography/FontScaleStore.swift +0 -58
  271. package/ios/Typography/KitDesignSystem.swift +0 -17
  272. /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
@@ -1,492 +0,0 @@
1
- //
2
- // StackScreen.swift
3
- // Pods
4
- //
5
- // SwiftUI mirror of Compose's `StackScreen`. This is a refactor of `Screen`:
6
- // the body is decomposed into the same focused pieces Compose uses — header
7
- // layer, scrollable content (`StackScreenContent`), floating button
8
- // (`FloatingContent`) and footer (`NavigationFooter`) — instead of one
9
- // monolithic, partially-duplicated view. The public init matches `Screen`
10
- // so call sites (e.g. NavigationContainer's ScreenHost) can swap over.
11
- //
12
-
13
- import SwiftUI
14
-
15
- public struct StackScreen<Content: View>: View {
16
- // MARK: - Properties
17
-
18
- var backgroundColor: Color?
19
- var headerTransparent: Bool = false
20
- var fullScreenContent: Bool = false
21
- var tintColor: Color? = Colors.black17
22
- var isBack: Bool
23
- var headerType: HeaderType
24
- var useAnimated: Bool = false
25
- var verticalAlignment: VerticalAlignment
26
- var horizontalAlignment: HorizontalAlignment
27
- var title: String
28
- var headerTitle: HeaderTitle?
29
- var titlePosition: TitlePosition
30
- var goBack: (() -> Void)?
31
- var scrollable: Bool
32
- var scrollToTopCallback: (() -> Void)?
33
- var onContentLayout: ((CGRect) -> Void)?
34
- var useAvoidKeyboard: Bool
35
- var keyboardShouldPersistTaps: Bool
36
- var footer: (() -> AnyView)?
37
- var headerRight: (()->any View)? = {HeaderRight()}
38
- var animatedHeader: AnimatedHeader? = nil
39
- var layoutOffset: CGFloat
40
- var inputSearchProps: InputSearchProps?
41
- var fabProps: FabProps?
42
- var screenName: String = ""
43
- var content: () -> Content
44
-
45
- public init(
46
- backgroundColor: Color? = nil,
47
- headerTransparent: Bool = false,
48
- fullScreenContent: Bool = false,
49
- tintColor: Color = Colors.black17,
50
- isBack: Bool = true,
51
- headerType: HeaderType = .default,
52
- useAnimated: Bool = false,
53
- verticalAlignment: VerticalAlignment = .top,
54
- horizontalAlignment: HorizontalAlignment = .leading,
55
- title: String = "Stack",
56
- headerTitle: HeaderTitle? = nil,
57
- titlePosition: TitlePosition = .left,
58
- goBack: (() -> Void)? = nil,
59
- scrollable: Bool = true,
60
- scrollToTopCallback: (() -> Void)? = nil,
61
- onContentLayout: ((CGRect) -> Void)? = nil,
62
- useAvoidKeyboard: Bool = true,
63
- keyboardShouldPersistTaps: Bool = false,
64
- footer: (() -> AnyView)? = nil,
65
- headerRight: (()->any View)? = {HeaderRight()},
66
- animatedHeader: AnimatedHeader? = nil,
67
- layoutOffset: CGFloat = 56,
68
- inputSearchProps: InputSearchProps? = nil,
69
- fabProps: FabProps? = nil,
70
- screenName: String = "",
71
- @ViewBuilder content: @escaping () -> Content
72
- ) {
73
- self.backgroundColor = backgroundColor
74
- self.headerTransparent = headerTransparent
75
- self.fullScreenContent = fullScreenContent
76
- self.tintColor = tintColor
77
- self.isBack = isBack
78
- self.headerType = headerType
79
- self.useAnimated = useAnimated
80
- self.verticalAlignment = verticalAlignment
81
- self.horizontalAlignment = horizontalAlignment
82
- self.title = title
83
- self.headerTitle = headerTitle
84
- self.titlePosition = titlePosition
85
- self.goBack = goBack
86
- self.scrollable = scrollable
87
- self.scrollToTopCallback = scrollToTopCallback
88
- self.onContentLayout = onContentLayout
89
- self.useAvoidKeyboard = useAvoidKeyboard
90
- self.keyboardShouldPersistTaps = keyboardShouldPersistTaps
91
- self.footer = footer
92
- self.headerRight = headerRight
93
- self.animatedHeader = animatedHeader
94
- self.layoutOffset = layoutOffset
95
- self.inputSearchProps = inputSearchProps
96
- self.fabProps = fabProps
97
- self.screenName = screenName
98
- self.content = content
99
- }
100
-
101
- @State private var scrollOffset: CGFloat = 0
102
- @State private var keyboardHeight: CGFloat = 0
103
- @State private var headerRightWidth: CGFloat = 0
104
- @State private var isBottomTabRoot: Bool = false
105
-
106
- @Environment(\.applicationEnvironment) private var appEnv
107
-
108
- // Auto-tracking state (mirrors Compose's `remember { ScreenTrackingState() }` +
109
- // the once-computed push/back `action`).
110
- @State private var trackingState = ScreenTrackingState()
111
- @State private var trackingAction: String = ScreenTracker.getLastScreenName() != nil ? "push" : "back"
112
-
113
- /// Header background fade tied to scroll: 0 → transparent (over a hero image
114
- /// or transparent header), 1 → opaque surface with the drop shadow.
115
- private var scrollOpacity: CGFloat { min(scrollOffset / 114, 1) }
116
-
117
- // MARK: - Search header (mirrors Compose's getInputSearchType / SearchAnimated)
118
-
119
- private enum InputSearchType { case none, header, animated }
120
-
121
- private var inputSearchType: InputSearchType {
122
- guard inputSearchProps != nil else { return .none }
123
- return useAnimated ? .animated : .header
124
- }
125
-
126
- private static var headerHeight: CGFloat { 52 }
127
-
128
- /// Extra top space reserved inside the content so the animated search bar has
129
- /// room below the header at scroll 0; it shrinks to 0 as the bar slides up.
130
- private var animatedSearchInset: CGFloat {
131
- guard inputSearchType == .animated else { return 0 }
132
- let scroll = max(scrollOffset, 0)
133
- return min(max(Self.headerHeight - scroll, 0), Self.headerHeight)
134
- }
135
-
136
- /// Title fades out as the animated search bar rises into the header.
137
- private var titleOpacity: CGFloat {
138
- guard inputSearchType == .animated else { return 1 }
139
- let scroll = max(scrollOffset, 0)
140
- return 1 - min(max(scroll / Self.headerHeight, 0), 1)
141
- }
142
-
143
- // MARK: - Body
144
-
145
- public var body: some View {
146
- GeometryReader { _ in
147
- let keyboardSize: CGFloat = useAvoidKeyboard ? max(keyboardHeight, 0) : 0
148
-
149
- ZStack(alignment: .top) {
150
- // Background color
151
- (backgroundColor ?? Color.white)
152
- .edgesIgnoringSafeArea(.all)
153
-
154
- VStack(spacing: 0) {
155
- ZStack(alignment: fabProps?.position == .center ? .bottom : .bottomTrailing) {
156
- VStack(alignment: horizontalAlignment, spacing: 0) {
157
- headerAndContent
158
- }
159
-
160
- FloatingContent(
161
- fabProps: fabProps,
162
- keyboardSize: keyboardSize,
163
- hasFooter: footer != nil,
164
- scrollOffset: scrollOffset
165
- )
166
- }
167
-
168
- NavigationFooter(footerComponent: footer, keyboardSize: keyboardSize)
169
- }
170
-
171
- // Animated search bar overlay (mirrors Compose's SearchAnimated layer).
172
- if inputSearchType == .animated, let props = inputSearchProps {
173
- SearchAnimatedHeader(
174
- props: props,
175
- scrollOffset: scrollOffset,
176
- hiddenBack: !isBack,
177
- hasHeaderRight: headerRight != nil,
178
- headerRightWidth: headerRightWidth,
179
- headerHeight: Self.headerHeight
180
- )
181
- }
182
- }
183
- .ignoresSafeArea(.keyboard, edges: .bottom)
184
- .onPreferenceChange(HeaderRightWidthKey.self) { width in
185
- if headerRightWidth != width { headerRightWidth = width }
186
- }
187
- .onPreferenceChange(IsBottomTabRootKey.self) { isRoot in
188
- if isBottomTabRoot != isRoot { isBottomTabRoot = isRoot }
189
- }
190
- .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)) { notification in
191
- guard useAvoidKeyboard,
192
- let endFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
193
- withAnimation(.easeOut(duration: 0.25)) {
194
- keyboardHeight = UIScreen.main.bounds.height - endFrame.origin.y
195
- }
196
- }
197
- // Mirrors Compose's `hideKeyboardOnTap()`: a simultaneous gesture so
198
- // taps still reach buttons/fields while also dismissing the keyboard.
199
- .modifier(HideKeyboardOnTap(enabled: keyboardShouldPersistTaps))
200
- }
201
- .task(id: screenName) {
202
- ScreenTracker.trackScreenNavigated(
203
- maxApi: appEnv.maxApi,
204
- context: appEnv.applicationContext,
205
- screenName: screenName,
206
- action: trackingAction,
207
- state: trackingState
208
- )
209
- do {
210
- try await Task.sleep(nanoseconds: 2_000_000_000)
211
- } catch {
212
- return
213
- }
214
- let loadTime = Date().timeIntervalSince1970 * 1000 - trackingState.time
215
- ScreenTracker.trackScreenDisplayed(
216
- maxApi: appEnv.maxApi,
217
- context: appEnv.applicationContext,
218
- screenName: screenName,
219
- duration: loadTime,
220
- state: trackingState
221
- )
222
- let interactionTime = Date().timeIntervalSince1970 * 1000 - trackingState.time
223
- ScreenTracker.trackScreenInteracted(
224
- maxApi: appEnv.maxApi,
225
- context: appEnv.applicationContext,
226
- screenName: screenName,
227
- duration: interactionTime - loadTime,
228
- totalDuration: interactionTime,
229
- state: trackingState
230
- )
231
- }
232
- }
233
-
234
- // MARK: - Header + content layer
235
-
236
- @ViewBuilder
237
- private var headerAndContent: some View {
238
- if let animatedHeader = animatedHeader {
239
- // Animated (hero) header: the image is the top of the scroll content
240
- // and the body overlaps its lower part; the header bar background
241
- // fades in over the image as the screen scrolls (mirrors Compose's
242
- // ScreenContent for HeaderType.Animated).
243
- ZStack(alignment: .top) {
244
- StackScreenContent(
245
- scrollable: scrollable,
246
- scrollOffset: $scrollOffset,
247
- scrollToTopCallback: scrollToTopCallback,
248
- animatedSearchInset: animatedSearchInset,
249
- content: { animatedHeroBody(animatedHeader) }
250
- )
251
- .edgesIgnoringSafeArea(.all)
252
-
253
- header
254
- .background(
255
- Colors.black01
256
- .opacity(scrollOpacity)
257
- .edgesIgnoringSafeArea(.top)
258
- )
259
- .zIndex(100)
260
- }
261
- } else if headerTransparent && fullScreenContent {
262
- ZStack(alignment: .top) {
263
- header
264
- .background(
265
- NavigationHeaderBackground(
266
- headerType: headerType,
267
- scrollState: scrollOffset,
268
- headerTransparent: headerTransparent,
269
- fullScreenContent: fullScreenContent
270
- )
271
- )
272
- .zIndex(100)
273
-
274
- StackScreenContent(scrollable: scrollable, scrollOffset: $scrollOffset, scrollToTopCallback: scrollToTopCallback, animatedSearchInset: animatedSearchInset, content: content)
275
- .edgesIgnoringSafeArea(.all)
276
- }
277
- } else {
278
- header
279
- .background(
280
- NavigationHeaderBackground(
281
- headerType: headerType,
282
- scrollState: scrollOffset,
283
- headerTransparent: headerTransparent,
284
- fullScreenContent: fullScreenContent
285
- )
286
- .edgesIgnoringSafeArea(.top)
287
- )
288
-
289
- StackScreenContent(scrollable: scrollable, scrollOffset: $scrollOffset, scrollToTopCallback: scrollToTopCallback, animatedSearchInset: animatedSearchInset, content: content)
290
- }
291
- }
292
-
293
- /// Hero image + body for an animated header. The image fills the width at its
294
- /// aspect-ratio height; the body is offset below the header band so it overlaps
295
- /// the lower part of the image (mirrors Compose's image box + padded content).
296
- @ViewBuilder
297
- private func animatedHeroBody(_ animatedHeader: AnimatedHeader) -> some View {
298
- let width = UIScreen.main.bounds.width
299
- let imageHeight = width / animatedHeader.aspectRatio.value
300
- let contentTopInset = safeAreaTopInset() + HEADER_HEIGHT + layoutOffset
301
-
302
- ZStack(alignment: .top) {
303
- animatedHeader.composable(scrollOffset)
304
- .frame(width: width, height: imageHeight)
305
- .clipped()
306
-
307
- content()
308
- .padding(.top, contentTopInset)
309
- }
310
- .frame(maxWidth: .infinity, alignment: .top)
311
- }
312
-
313
- private var header: NavigationHeader {
314
- NavigationHeader(
315
- headerType: headerType,
316
- titlePosition: titlePosition,
317
- title: title,
318
- headerTitle: headerTitle,
319
- headerRight: headerRight,
320
- goBack: goBack,
321
- opacity: scrollOpacity,
322
- animatedHeader: animatedHeader,
323
- scrollState: scrollOffset,
324
- // For the animated search the bar is rendered by the overlay, so the
325
- // header shows the (fading) title instead of an inline search field.
326
- inputSearchProps: inputSearchType == .header ? inputSearchProps : nil,
327
- tintColor: tintColor,
328
- titleOpacity: titleOpacity
329
- )
330
- }
331
- }
332
-
333
- // MARK: - Screen content (scrollable body)
334
-
335
- /// Mirrors Compose's `ScreenContent`/`MainContent`: renders the screen body and,
336
- /// when scrollable, tracks the scroll offset so the header/FAB can react to it.
337
- private struct StackScreenContent<Content: View>: View {
338
- let scrollable: Bool
339
- @Binding var scrollOffset: CGFloat
340
- /// Mirrors Compose's `ScrollData.scrollToTopCallback`; fired alongside the
341
- /// scroll-to-top triggered by a status-bar tap.
342
- let scrollToTopCallback: (() -> Void)?
343
- /// Extra top space reserved for the animated search bar (mirrors Compose's
344
- /// MainContent animated top spacer). Zero for non-animated screens.
345
- var animatedSearchInset: CGFloat = 0
346
- let content: () -> Content
347
-
348
- private let topAnchorID = "stack_screen_top_anchor"
349
- private let scrollSpace = "stack_screen_scroll_space"
350
-
351
- var body: some View {
352
- if scrollable {
353
- ScrollViewReader { proxy in
354
- ScrollView(.vertical, showsIndicators: false) {
355
- VStack(spacing: 0) {
356
- // Top probe + scroll-to-top anchor. Measured in the scroll's
357
- // own coordinate space so the offset is a clean 0-based
358
- // "pixels scrolled" value, independent of the inset below.
359
- Color.clear
360
- .frame(height: 0)
361
- .id(topAnchorID)
362
- .background(GeometryReader { geo in
363
- Color.clear
364
- .onAppear {
365
- scrollOffset = -geo.frame(in: .named(scrollSpace)).minY
366
- }
367
- .onChange(of: geo.frame(in: .named(scrollSpace)).minY) { minY in
368
- scrollOffset = -minY
369
- }
370
- })
371
-
372
- if animatedSearchInset > 0 {
373
- Spacer().frame(height: animatedSearchInset)
374
- }
375
-
376
- VStack {
377
- content()
378
- }
379
- }
380
- }
381
- .coordinateSpace(name: scrollSpace)
382
- // Status-bar tap (via MoMoStatusBarTap swizzle) scrolls to top and
383
- // notifies the consumer, mirroring Compose's scrollToTopCallback.
384
- .onReceive(NotificationCenter.default.publisher(for: MoMoStatusBarTap.notificationName)) { _ in
385
- withAnimation {
386
- proxy.scrollTo(topAnchorID, anchor: .top)
387
- }
388
- scrollToTopCallback?()
389
- }
390
- }
391
- } else {
392
- content()
393
- }
394
- }
395
- }
396
-
397
- // MARK: - Animated search header
398
-
399
- /// Mirrors Compose's `SearchAnimated`: the search bar slides from below the
400
- /// header (scroll 0) up into the header band as the user scrolls, while its
401
- /// horizontal insets grow to make room for the back button and header-right.
402
- /// Note: Compose's scroll-end snap and background-color lerp are not ported.
403
- private struct SearchAnimatedHeader: View {
404
- let props: InputSearchProps
405
- let scrollOffset: CGFloat
406
- let hiddenBack: Bool
407
- let hasHeaderRight: Bool
408
- let headerRightWidth: CGFloat
409
- let headerHeight: CGFloat
410
-
411
- var body: some View {
412
- let scroll = max(scrollOffset, 0)
413
-
414
- // Insets are measured from the safe-area top (status bar handled by layout).
415
- let minTop: CGFloat = 0
416
- let maxTop = headerHeight
417
- let minSide = Spacing.M
418
- let maxStart: CGFloat = hiddenBack ? Spacing.M : 48
419
- let maxEnd = headerRightWidth + (hasHeaderRight ? Spacing.M * 2 : Spacing.M)
420
-
421
- let top = min(max(maxTop - scroll, minTop), maxTop)
422
- let start = min(max(minSide + scroll, minSide), maxStart)
423
- let end = min(max(minSide + scroll, minSide), maxEnd)
424
-
425
- VStack(spacing: 0) {
426
- Spacer().frame(height: top)
427
- InputSearch(props: props)
428
- .frame(height: headerHeight)
429
- .padding(.leading, start)
430
- .padding(.trailing, end)
431
- Spacer(minLength: 0)
432
- }
433
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
434
- }
435
- }
436
-
437
- // MARK: - Floating content
438
-
439
- /// Mirrors Compose's `FloatingContent`: no FAB props means nothing renders.
440
- private struct FloatingContent: View {
441
- let fabProps: FabProps?
442
- let keyboardSize: CGFloat
443
- /// With a footer the FAB is anchored to the footer's *layout* top, which does not move
444
- /// when the band offsets itself over the keyboard — so it rides the same offset.
445
- let hasFooter: Bool
446
- let scrollOffset: CGFloat
447
-
448
- /// Compose keeps the FAB `Spacing.M + AppNavigationBar` above the bottom of the screen
449
- /// and lifts it with `imePadding()`; here it sits `Spacing.M` above the safe area and
450
- /// nothing lifts it, so the difference is applied as an offset (see NavigationFooter).
451
- private var verticalOffset: CGFloat {
452
- if hasFooter { return NavigationFooter.verticalOffset(keyboardSize: keyboardSize) }
453
- return NavigationFooter.safeAreaBottom - NavigationFooter.navigationBarInset - keyboardSize
454
- }
455
-
456
- var body: some View {
457
- if let fabProps = fabProps {
458
- FloatingButton(
459
- props: fabProps,
460
- keyboardOffset: 0,
461
- scrollOffset: scrollOffset
462
- )
463
- .padding(.horizontal, Spacing.M)
464
- .offset(y: verticalOffset)
465
- .ignoresSafeArea(.keyboard, edges: .bottom)
466
- }
467
- }
468
- }
469
-
470
- // MARK: - Hide keyboard on tap
471
-
472
- /// Mirrors Compose's `Modifier.hideKeyboardOnTap()`. When enabled, a tap
473
- /// anywhere resigns the first responder. Uses `simultaneousGesture` so the tap
474
- /// is not consumed — buttons and text fields keep working.
475
- private struct HideKeyboardOnTap: ViewModifier {
476
- let enabled: Bool
477
-
478
- func body(content: Content) -> some View {
479
- if enabled {
480
- content.simultaneousGesture(
481
- TapGesture().onEnded {
482
- UIApplication.shared.sendAction(
483
- #selector(UIResponder.resignFirstResponder),
484
- to: nil, from: nil, for: nil
485
- )
486
- }
487
- )
488
- } else {
489
- content
490
- }
491
- }
492
- }
@@ -1,58 +0,0 @@
1
- import SwiftUI
2
-
3
- /// App-wide font-scale inputs for the SwiftUI kit, and the single place they publish from.
4
- /// The host writes `update(...)` at startup (from the cache-backed `FontScaleProvider`) and again
5
- /// whenever the in-app font-size preference changes; the OS Dynamic Type factor is tracked here.
6
- /// Mirrors Compose's `KitFontScale` + `ProvideOsFontScale` pair, including its live behaviour —
7
- /// views re-render on change as long as the subtree got `.momoFontScale()` (`NavigationContainer`
8
- /// applies it). When `useOSScaleRate` is false the kit applies `userScaleRate` instead of the OS factor.
9
- public final class FontScaleStore: ObservableObject {
10
- public static let shared = FontScaleStore()
11
-
12
- @Published public private(set) var userScaleRate: CGFloat = 1
13
- @Published public private(set) var useOSScaleRate: Bool = true
14
- @Published public private(set) var osFontScale: CGFloat = FontScaleStore.currentOsFontScale()
15
-
16
- private init() {
17
- NotificationCenter.default.addObserver(
18
- self,
19
- selector: #selector(contentSizeCategoryDidChange),
20
- name: UIContentSizeCategory.didChangeNotification,
21
- object: nil
22
- )
23
- }
24
-
25
- public var snapshot: FontScale {
26
- FontScale(
27
- userScaleRate: userScaleRate,
28
- useOSScaleRate: useOSScaleRate,
29
- osFontScale: osFontScale
30
- )
31
- }
32
-
33
- public func update(userScaleRate: CGFloat, useOSScaleRate: Bool) {
34
- onMain {
35
- // Re-assigning an unchanged value would still publish and invalidate every kit subtree.
36
- if self.userScaleRate != userScaleRate { self.userScaleRate = userScaleRate }
37
- if self.useOSScaleRate != useOSScaleRate { self.useOSScaleRate = useOSScaleRate }
38
- }
39
- }
40
-
41
- @objc private func contentSizeCategoryDidChange() {
42
- let next = Self.currentOsFontScale()
43
- guard next != osFontScale else { return }
44
- osFontScale = next
45
- }
46
-
47
- /// Same factor Compose's iOS `ProvideOsFontScale` derives from
48
- /// `UIFont.preferredFont(forTextStyle: .body).pointSize / 17`, so both iOS surfaces scale alike.
49
- static func currentOsFontScale() -> CGFloat {
50
- let base = UIFont.systemFont(ofSize: UIFont.labelFontSize)
51
- return UIFontMetrics.default.scaledFont(for: base).pointSize / base.pointSize
52
- }
53
-
54
- /// Synchronous when already on main — an async hop would defer the change by a frame.
55
- private func onMain(_ work: @escaping () -> Void) {
56
- if Thread.isMainThread { work() } else { DispatchQueue.main.async(execute: work) }
57
- }
58
- }
@@ -1,17 +0,0 @@
1
- import Foundation
2
-
3
- /// Design-system rollout flag for the SwiftUI kit, mirroring Compose's `KitDesignSystem`.
4
- /// The kit is sandboxed and can't read the host config, so the host writes `update(_:)` once at
5
- /// startup from `DesignSystemConfig`. Startup-only and non-reactive, like `FontScaleStore` was
6
- /// before it gained live updates: there is no SwiftUI navigation container to re-render from.
7
- public final class KitDesignSystem {
8
- public static let shared = KitDesignSystem()
9
-
10
- public private(set) var isWhiteList: Bool = false
11
-
12
- private init() {}
13
-
14
- public func update(isWhiteList: Bool) {
15
- self.isWhiteList = isWhiteList
16
- }
17
- }