@momo-kits/native-kits 0.163.1-beta.2 → 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 (345) hide show
  1. package/.claude/settings.local.json +112 -0
  2. package/CLAUDE.md +1 -1
  3. package/build.gradle.kts +11 -0
  4. package/compose/build.gradle.kts +190 -0
  5. package/compose/build.gradle.kts.backup +190 -0
  6. package/compose/compose.podspec +47 -0
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +150 -0
  10. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  11. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  22. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  23. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +106 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +826 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +82 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +356 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +76 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +112 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +477 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +214 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +216 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +259 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +182 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +328 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +323 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +217 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +199 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +470 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +131 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +203 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +498 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +175 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +234 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +188 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +276 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +52 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +38 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +39 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +299 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +129 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +100 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +172 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +372 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +581 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +156 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +320 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +81 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +309 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +34 -0
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +360 -0
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +127 -0
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +69 -0
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +105 -0
  133. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +32 -0
  134. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  135. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +207 -0
  136. package/gradle/libs.versions.toml +69 -0
  137. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  138. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  139. package/gradle.properties +26 -0
  140. package/gradlew +252 -0
  141. package/gradlew.bat +94 -0
  142. package/ios/Application/ApplicationEnvironment.swift +15 -3
  143. package/ios/Application/Components.swift +36 -30
  144. package/ios/Application/FloatingButton.swift +10 -9
  145. package/ios/Application/Localize.swift +309 -0
  146. package/ios/Application/MaxApi.swift +18 -0
  147. package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
  148. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
  149. package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
  150. package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
  151. package/ios/Application/Navigation/HeaderTitle.swift +57 -0
  152. package/ios/Application/Navigation/HeaderUser.swift +209 -0
  153. package/ios/Application/Navigation/NavigationContainer.swift +203 -0
  154. package/ios/Application/Navigation/NavigationOptions.swift +109 -0
  155. package/ios/Application/Navigation/Navigator.swift +385 -0
  156. package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
  157. package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
  158. package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
  159. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  160. package/ios/Application/Navigation/component/Header.swift +178 -0
  161. package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
  162. package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
  163. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +11 -0
  164. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +196 -0
  165. package/ios/Application/Screen.swift +2 -1
  166. package/ios/Application/StackScreen.swift +501 -0
  167. package/ios/Avatar/Avatar.swift +193 -0
  168. package/ios/Badge/Badge.swift +11 -14
  169. package/ios/Badge/BadgeRibbon.swift +91 -17
  170. package/ios/BaselineView/BaselineView.swift +163 -0
  171. package/ios/Button/Button.swift +137 -28
  172. package/ios/Carousel/Carousel.swift +196 -0
  173. package/ios/Checkbox/Checkbox.swift +23 -28
  174. package/ios/Chip/Chip.swift +56 -33
  175. package/ios/Collapse/Collapse.swift +192 -0
  176. package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
  177. package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
  178. package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
  179. package/ios/DateTimePicker/DateTimePicker.swift +212 -0
  180. package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
  181. package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
  182. package/ios/DateTimePicker/WheelPicker.swift +165 -0
  183. package/ios/Divider/Divider.swift +16 -0
  184. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  185. package/ios/Extensions/Color++.swift +32 -0
  186. package/ios/Icon/Icon.swift +10 -1
  187. package/ios/IconButton/IconButton.swift +140 -0
  188. package/ios/Image/Image.swift +16 -3
  189. package/ios/Information/Information.swift +3 -1
  190. package/ios/Input/ErrorView.swift +3 -1
  191. package/ios/Input/Input.swift +72 -33
  192. package/ios/Input/InputPhoneNumber.swift +33 -21
  193. package/ios/Input/InputSearch.swift +107 -48
  194. package/ios/Input/InputTextArea.swift +134 -64
  195. package/ios/InputDropDown/InputDropDown.swift +201 -0
  196. package/ios/InputMoney/InputMoney.swift +347 -0
  197. package/ios/InputOTP/InputOTP.swift +210 -0
  198. package/ios/Loader/Loader.swift +113 -0
  199. package/ios/MoMoUIKits.podspec +5 -0
  200. package/ios/Pagination/PaginationDot.swift +61 -0
  201. package/ios/Pagination/PaginationNumber.swift +35 -0
  202. package/ios/Pagination/PaginationScroll.swift +101 -0
  203. package/ios/Pagination/PaginationWhiteDot.swift +37 -0
  204. package/ios/Popup/PopupDisplay.swift +11 -20
  205. package/ios/Popup/PopupInput.swift +2 -8
  206. package/ios/Popup/PopupNotify.swift +218 -0
  207. package/ios/Popup/PopupPromotion.swift +5 -3
  208. package/ios/ProgressInfo/ProgressInfo.swift +296 -0
  209. package/ios/Radio/Radio.swift +69 -0
  210. package/ios/Rating/Rating.swift +82 -0
  211. package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
  212. package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
  213. package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
  214. package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
  215. package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
  216. package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
  217. package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
  218. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
  219. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
  220. package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
  221. package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
  222. package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
  223. package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
  224. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  225. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  226. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  227. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  228. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  229. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  230. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  231. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  232. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  233. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  234. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  235. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  236. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  237. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  238. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  239. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  240. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  241. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  242. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  243. package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
  244. package/ios/Skeleton/Skeleton.swift +99 -0
  245. package/ios/Slider/Slider.swift +237 -0
  246. package/ios/Stepper/Stepper.swift +220 -0
  247. package/ios/Steps/Steps.swift +467 -0
  248. package/ios/SuggestAction/SuggestAction.swift +99 -0
  249. package/ios/Swipeable/SwipeCell.swift +187 -0
  250. package/ios/Swipeable/SwipeCellModel.swift +21 -0
  251. package/ios/Switch/Switch.swift +53 -28
  252. package/ios/TabView/TabView.swift +534 -0
  253. package/ios/Tag/Tag.swift +98 -0
  254. package/ios/Template/TrustBanner/TrustBanner.swift +7 -8
  255. package/ios/Title/Title.swift +269 -0
  256. package/ios/Tooltip/Tooltip.swift +485 -0
  257. package/ios/Typography/FontScaleStore.swift +19 -0
  258. package/ios/Typography/Text.swift +86 -17
  259. package/ios/Typography/Typography.swift +12 -14
  260. package/ios/Uploader/Uploader.swift +174 -0
  261. package/ios/native-kits.podspec +61 -8
  262. package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
  263. package/ios-demo/README.md +120 -0
  264. package/ios-demo/Resources/dot_loading.json +558 -0
  265. package/ios-demo/Resources/icon.json +4052 -0
  266. package/ios-demo/Resources/lottie_circle_loader.json +1 -0
  267. package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
  268. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
  269. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
  270. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
  271. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
  272. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
  273. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
  274. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
  275. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
  276. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
  277. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
  278. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
  279. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
  280. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
  281. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
  282. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
  283. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
  284. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
  285. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +64 -0
  286. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
  287. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
  288. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
  289. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
  290. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
  291. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
  292. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
  293. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
  294. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
  295. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
  296. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
  297. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
  298. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
  299. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
  300. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
  301. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
  302. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
  303. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
  304. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
  305. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
  306. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
  307. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
  308. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
  309. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
  310. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
  311. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
  312. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
  313. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
  314. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
  315. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
  316. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
  317. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
  318. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
  319. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
  320. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
  321. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
  322. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
  323. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
  324. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
  325. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
  326. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
  327. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
  328. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
  329. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
  330. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
  331. package/local.properties +8 -0
  332. package/package.json +1 -1
  333. package/publish.sh +53 -0
  334. package/scripts/gen-ios-color.mjs +136 -0
  335. package/settings.gradle.kts +64 -0
  336. package/example/ios/Example.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  337. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  338. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
  339. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
  340. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
  341. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
  342. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
  343. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
  344. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -46
  345. package/ios/Application/FontScaleStore.swift +0 -59
@@ -1,6 +1,7 @@
1
1
  import SwiftUI
2
2
 
3
3
  public struct Badge: View {
4
+ @Environment(\.appTheme) private var theme
4
5
  let label: String
5
6
  let backgroundColor: Color?
6
7
 
@@ -38,24 +39,21 @@ public struct Badge: View {
38
39
  }
39
40
 
40
41
  private var badgeColor: Color {
41
- // If a custom background color is provided, use it
42
- if let bgColor = backgroundColor {
42
+ // Default colors based on label type
43
+ let defaultColor: Color = isNumber(label)
44
+ ? theme.colors.error.primary
45
+ : theme.colors.warning.primary
46
+
47
+ // Mirror Compose: only apply backgroundColor when it is one of the
48
+ // allowed primaryColors; otherwise fall back to the label-based default.
49
+ if let bgColor = backgroundColor, primaryColors.contains(bgColor) {
43
50
  return bgColor
44
51
  }
45
-
46
- // Otherwise, use default colors based on label type
47
- if isNumber(label) {
48
- return Colors.red03 // error.primary
49
- } else {
50
- return Colors.orange03 // warning.primary
51
- }
52
+ return defaultColor
52
53
  }
53
54
 
54
55
  public var body: some View {
55
- Text(formatTitle(label))
56
- .font(.system(size: scaleSize(10), weight: .bold))
57
- .ignoreBoldTextSetting()
58
- .foregroundColor(Colors.black01)
56
+ MomoText(formatTitle(label), typography: .actionXxsBold, color: Colors.black01)
59
57
  .padding(.horizontal, Spacing.XS)
60
58
  .frame(minWidth: scaleSize(16), minHeight: scaleSize(16))
61
59
  .background(badgeColor)
@@ -83,4 +81,3 @@ struct Badge_Previews: PreviewProvider {
83
81
  }
84
82
  }
85
83
  #endif
86
-
@@ -77,10 +77,11 @@ public enum RibbonPosition {
77
77
  }
78
78
 
79
79
  public struct BadgeRibbon: View {
80
+ @Environment(\.appTheme) private var theme
80
81
  let position: RibbonPosition
81
82
  let label: String
82
83
  let isRound: Bool
83
- let backgroundColor: Color
84
+ let backgroundColor: Color?
84
85
 
85
86
  public init(
86
87
  position: RibbonPosition = .topRight,
@@ -91,7 +92,7 @@ public struct BadgeRibbon: View {
91
92
  self.position = position
92
93
  self.label = label
93
94
  self.isRound = isRound
94
- self.backgroundColor = backgroundColor ?? Colors.orange03
95
+ self.backgroundColor = backgroundColor
95
96
  }
96
97
 
97
98
  private var rotation: Angle {
@@ -117,6 +118,8 @@ public struct BadgeRibbon: View {
117
118
  }
118
119
 
119
120
  public var body: some View {
121
+ let bgColor = backgroundColor ?? theme.colors.warning.primary
122
+
120
123
  HStack(alignment: verticalAlignment, spacing: 0) {
121
124
  if useUpTail {
122
125
  upTail
@@ -125,22 +128,18 @@ public struct BadgeRibbon: View {
125
128
  }
126
129
 
127
130
  if isRound {
128
- roundContent
131
+ roundContent(backgroundColor: bgColor)
129
132
  } else {
130
- skewContent
133
+ skewContent(backgroundColor: bgColor)
131
134
  }
132
135
  }
133
136
  .frame(height: RibbonConstants.ribbonHeight)
134
137
  .rotationEffect(rotation)
135
138
  }
136
139
 
137
- private var roundContent: some View {
140
+ private func roundContent(backgroundColor: Color) -> some View {
138
141
  HStack(spacing: 0) {
139
- Text(label)
140
- .font(.system(size: scaleSize(12), weight: .medium))
141
- .ignoreBoldTextSetting()
142
- .foregroundColor(Colors.black01)
143
- .lineLimit(1)
142
+ MomoText(label, typography: .labelXsMedium, color: Colors.black01, maxLines: 1)
144
143
  .rotationEffect(rotation)
145
144
  }
146
145
  .frame(height: RibbonConstants.roundHeight)
@@ -156,13 +155,9 @@ public struct BadgeRibbon: View {
156
155
  )
157
156
  }
158
157
 
159
- private var skewContent: some View {
158
+ private func skewContent(backgroundColor: Color) -> some View {
160
159
  HStack(spacing: 0) {
161
- Text(label)
162
- .font(.system(size: scaleSize(12), weight: .medium))
163
- .ignoreBoldTextSetting()
164
- .foregroundColor(Colors.black01)
165
- .lineLimit(1)
160
+ MomoText(label, typography: .labelXsMedium, color: Colors.black01, maxLines: 1)
166
161
  .rotationEffect(rotation)
167
162
  .frame(height: RibbonConstants.skewBodyHeight)
168
163
  .padding(.horizontal, 8)
@@ -204,6 +199,86 @@ public struct BadgeRibbon: View {
204
199
  }
205
200
  }
206
201
 
202
+ /// Ported from Compose's `RoundedBadgeRibbon` (BadgeRibbon.kt:164-326): a canvas-drawn
203
+ /// ribbon shape sized to its text, mirrored per corner via scaleX/scaleY (never an actual
204
+ /// rotation) — the label gets the same scale applied a second time so it stays right-reading
205
+ /// while only the ribbon shape flips.
206
+ public struct RoundedBadgeRibbon: View {
207
+ let text: String
208
+ let position: RibbonPosition
209
+
210
+ public init(text: String = "Label", position: RibbonPosition = .topLeft) {
211
+ self.text = text
212
+ self.position = position
213
+ }
214
+
215
+ private var scale: (x: CGFloat, y: CGFloat) {
216
+ switch position {
217
+ case .topLeft: return (-1, 1)
218
+ case .topRight: return (1, 1)
219
+ case .bottomRight: return (1, -1)
220
+ case .bottomLeft: return (-1, -1)
221
+ }
222
+ }
223
+
224
+ private var measuredTextSize: CGSize {
225
+ let fontSize = scaleSize(TypographyStyle.labelXsMedium.fontSize)
226
+ let font = UIFont.systemFont(ofSize: fontSize, weight: .medium)
227
+ return text.size(withAttributes: [.font: font])
228
+ }
229
+
230
+ public var body: some View {
231
+ let textSize = measuredTextSize
232
+ let minRibbonHeight = max(textSize.height * 1.2, 16)
233
+ let padding = minRibbonHeight / 4
234
+ let badgeHeight = minRibbonHeight + padding
235
+ let badgeWidth = max(textSize.width + padding * 2, 28)
236
+
237
+ ZStack {
238
+ Canvas { context, size in
239
+ let ribbonHeight = size.height - padding
240
+ let cornerRadius = (badgeHeight - padding) / 2
241
+ let mainColor = Colors.orange03
242
+ let tailColor = Colors.red01
243
+
244
+ let headWidth: CGFloat = 4
245
+ // Kotlin computes `leftSectionWidth` + `middleSectionWidth` here, but those
246
+ // cancel algebraically to `width - headWidth` — kept as the direct result.
247
+ let rightX = size.width - headWidth
248
+
249
+ let leftMiddlePath = RoundedCorners(topLeft: cornerRadius, topRight: 0, bottomLeft: cornerRadius, bottomRight: 0)
250
+ .path(in: CGRect(x: 0, y: 0, width: rightX + 1, height: ribbonHeight))
251
+ context.fill(leftMiddlePath, with: .color(mainColor))
252
+
253
+ let headPath = RoundedCorners(topLeft: 0, topRight: cornerRadius, bottomLeft: 0, bottomRight: 0)
254
+ .path(in: CGRect(x: rightX, y: 0, width: headWidth, height: ribbonHeight))
255
+ context.fill(headPath, with: .color(mainColor))
256
+
257
+ let halfHeadWidth = headWidth / 2
258
+ let tailStartX = rightX + headWidth - halfHeadWidth
259
+ let tailY = ribbonHeight
260
+ let tailHeight = padding
261
+
262
+ context.fill(
263
+ Path(CGRect(x: tailStartX, y: tailY, width: halfHeadWidth, height: halfHeadWidth)),
264
+ with: .color(mainColor)
265
+ )
266
+
267
+ let tailRightPath = RoundedCorners(topLeft: 0, topRight: tailHeight, bottomLeft: 0, bottomRight: tailHeight)
268
+ .path(in: CGRect(x: tailStartX, y: tailY, width: halfHeadWidth, height: tailHeight))
269
+ context.fill(tailRightPath, with: .color(tailColor))
270
+ }
271
+
272
+ MomoText(text, typography: .labelXsMedium, color: Colors.black01, maxLines: 1)
273
+ .padding(.bottom, padding)
274
+ .padding(.horizontal, padding / 2)
275
+ .scaleEffect(x: scale.x, y: scale.y)
276
+ }
277
+ .frame(width: badgeWidth, height: badgeHeight)
278
+ .scaleEffect(x: scale.x, y: scale.y)
279
+ }
280
+ }
281
+
207
282
  // MARK: - Constants
208
283
  private struct RibbonConstants {
209
284
  static let ribbonHeight: CGFloat = 20
@@ -241,4 +316,3 @@ struct BadgeRibbon_Previews: PreviewProvider {
241
316
  }
242
317
  }
243
318
  #endif
244
-
@@ -0,0 +1,163 @@
1
+ import SwiftUI
2
+
3
+ public struct BaselineView: View {
4
+ private let enabled: Bool
5
+
6
+ public init(enabled: Bool = true) {
7
+ self.enabled = enabled
8
+ }
9
+
10
+ public var body: some View {
11
+ if enabled {
12
+ GeometryReader { geometry in
13
+ let topInset = geometry.safeAreaInsets.top
14
+ let bottomInset = min(geometry.safeAreaInsets.bottom, 21)
15
+
16
+ ZStack(alignment: .topLeading) {
17
+ dangerZones(topInset: topInset, bottomInset: bottomInset)
18
+ guideLines(
19
+ topInset: topInset,
20
+ bottomInset: bottomInset,
21
+ width: geometry.size.width
22
+ )
23
+ }
24
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
25
+ .ignoresSafeArea()
26
+ .allowsHitTesting(false)
27
+ .accessibilityHidden(true)
28
+ }
29
+ }
30
+ }
31
+
32
+ private func dangerZones(topInset: CGFloat, bottomInset: CGFloat) -> some View {
33
+ let safeBackground = Color.red.opacity(0.15)
34
+
35
+ return ZStack(alignment: .topLeading) {
36
+ safeBackground
37
+ .frame(maxWidth: .infinity)
38
+ .frame(height: topInset)
39
+
40
+ HStack(spacing: 0) {
41
+ safeBackground
42
+ .frame(width: 12)
43
+ Spacer(minLength: 0)
44
+ safeBackground
45
+ .frame(width: 12)
46
+ }
47
+ .padding(.top, topInset)
48
+ .padding(.bottom, bottomInset)
49
+
50
+ VStack(spacing: 0) {
51
+ Spacer(minLength: 0)
52
+ safeBackground
53
+ .frame(maxWidth: .infinity)
54
+ .frame(height: bottomInset)
55
+ }
56
+ }
57
+ }
58
+
59
+ private func guideLines(topInset: CGFloat, bottomInset: CGFloat, width: CGFloat) -> some View {
60
+ ZStack(alignment: .topLeading) {
61
+ baselineLine(isDotted: false, color: Color(hex: 0xE400FF))
62
+ .offset(y: topInset)
63
+
64
+ baselineLine(color: Color(hex: 0xE400FF))
65
+ .offset(y: topInset + 52)
66
+
67
+ baselineLine(color: Color(hex: 0xE400FF))
68
+ .offset(y: topInset + 104)
69
+
70
+ bottomLine(bottomInset: bottomInset + 64, color: Color(hex: 0xE400FF))
71
+
72
+ bottomLine(bottomInset: bottomInset, isDotted: false, color: Color(hex: 0xE400FF))
73
+
74
+ baselineLine(orientation: .vertical, isDotted: false, color: Color(hex: 0xE400FF))
75
+ .offset(x: 12)
76
+
77
+ baselineLine(orientation: .vertical, isDotted: false, color: Color(hex: 0xE400FF))
78
+ .offset(x: width - 12)
79
+
80
+ baselineLine(color: Color(hex: 0xFF7A00))
81
+ .offset(y: topInset + 26)
82
+
83
+ bottomLine(bottomInset: bottomInset + 56, color: Color(hex: 0xFFCC00))
84
+
85
+ bottomLine(bottomInset: bottomInset + 8, color: Color(hex: 0xFFCC00))
86
+
87
+ baselineLine(orientation: .vertical, color: Color(hex: 0x00C520))
88
+ .frame(height: 52)
89
+ .offset(x: 40, y: topInset)
90
+
91
+ baselineLine(orientation: .vertical, color: Color(hex: 0x00C520))
92
+ .frame(height: 52)
93
+ .offset(x: 48, y: topInset)
94
+ }
95
+ }
96
+
97
+ private func bottomLine(
98
+ bottomInset: CGFloat,
99
+ isDotted: Bool = true,
100
+ color: Color
101
+ ) -> some View {
102
+ VStack(spacing: 0) {
103
+ Spacer(minLength: 0)
104
+ baselineLine(isDotted: isDotted, color: color)
105
+ .padding(.bottom, bottomInset)
106
+ }
107
+ }
108
+
109
+ private func baselineLine(
110
+ orientation: BaselineOrientation = .horizontal,
111
+ isDotted: Bool = true,
112
+ color: Color
113
+ ) -> some View {
114
+ BaselineLineShape(orientation: orientation)
115
+ .stroke(
116
+ color,
117
+ style: StrokeStyle(
118
+ lineWidth: 1,
119
+ lineCap: .round,
120
+ dash: isDotted ? [8, 8] : []
121
+ )
122
+ )
123
+ .frame(
124
+ maxWidth: orientation == .horizontal ? .infinity : 1,
125
+ maxHeight: orientation == .vertical ? .infinity : 1
126
+ )
127
+ }
128
+ }
129
+
130
+ public enum BaselineOrientation: Sendable {
131
+ case horizontal
132
+ case vertical
133
+ }
134
+
135
+ private struct BaselineLineShape: Shape {
136
+ let orientation: BaselineOrientation
137
+
138
+ func path(in rect: CGRect) -> Path {
139
+ var path = Path()
140
+
141
+ switch orientation {
142
+ case .horizontal:
143
+ path.move(to: CGPoint(x: rect.minX, y: rect.midY))
144
+ path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
145
+ case .vertical:
146
+ path.move(to: CGPoint(x: rect.midX, y: rect.minY))
147
+ path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
148
+ }
149
+
150
+ return path
151
+ }
152
+ }
153
+
154
+ #if DEBUG
155
+ struct BaselineView_Previews: PreviewProvider {
156
+ static var previews: some View {
157
+ ZStack {
158
+ Colors.black01
159
+ BaselineView()
160
+ }
161
+ }
162
+ }
163
+ #endif
@@ -31,33 +31,45 @@ public struct ButtonStyleData {
31
31
 
32
32
  public extension ButtonType {
33
33
  func backgroundColor(loading: Bool) -> Color {
34
+ backgroundColor(loading: loading, theme: defaultTheme)
35
+ }
36
+
37
+ func backgroundColor(loading: Bool, theme: Theme) -> Color {
34
38
  switch self {
35
- case .disabled: return Colors.black05.opacity(loading ? 0.75 : 1)
36
- case .primary: return Colors.primary.opacity(loading ? 0.75 : 1)
37
- case .secondary: return Colors.card.opacity(loading ? 0.75 : 1)
38
- case .outline: return Colors.card.opacity(loading ? 0.75 : 1)
39
- case .tonal: return Colors.primaryLight.opacity(loading ? 0.75 : 1)
40
- case .danger: return Colors.error.opacity(loading ? 0.75 : 1)
39
+ case .disabled: return theme.colors.background.disable.opacity(loading ? 0.75 : 1)
40
+ case .primary: return theme.colors.primary.opacity(loading ? 0.75 : 1)
41
+ case .secondary: return theme.colors.background.surface.opacity(loading ? 0.75 : 1)
42
+ case .outline: return theme.colors.background.surface.opacity(loading ? 0.75 : 1)
43
+ case .tonal: return theme.colors.background.tonal.opacity(loading ? 0.75 : 1)
44
+ case .danger: return theme.colors.error.primary.opacity(loading ? 0.75 : 1)
41
45
  case .text: return .clear
42
46
  }
43
47
  }
44
48
 
45
49
  func contentColor(loading: Bool) -> Color {
50
+ contentColor(loading: loading, theme: defaultTheme)
51
+ }
52
+
53
+ func contentColor(loading: Bool, theme: Theme) -> Color {
46
54
  switch self {
47
- case .disabled: return Colors.black06.opacity(loading ? 0.75 : 1)
55
+ case .disabled: return theme.colors.text.disable.opacity(loading ? 0.75 : 1)
48
56
  case .primary: return Colors.black01
49
- case .secondary: return Colors.black17
50
- case .outline: return Colors.primary
51
- case .tonal: return Colors.primary
57
+ case .secondary: return theme.colors.text.default
58
+ case .outline: return theme.colors.primary
59
+ case .tonal: return theme.colors.primary
52
60
  case .danger: return Colors.black01
53
- case .text: return Colors.primary
61
+ case .text: return theme.colors.primary
54
62
  }
55
63
  }
56
64
 
57
65
  var borderColor: Color? {
66
+ borderColor(theme: defaultTheme)
67
+ }
68
+
69
+ func borderColor(theme: Theme) -> Color? {
58
70
  switch self {
59
- case .outline: return Colors.primary
60
- case .secondary: return Colors.black04
71
+ case .outline: return theme.colors.primary
72
+ case .secondary: return theme.colors.border.default
61
73
  default: return nil
62
74
  }
63
75
  }
@@ -111,12 +123,12 @@ extension ButtonSize {
111
123
  case .large: return .actionDefaultBold
112
124
  case .medium: return .actionSBold
113
125
  case .small: return .actionXsBold
114
- default : return .actionDefaultBold
115
126
  }
116
127
  }
117
128
  }
118
129
 
119
130
  public struct Button: View {
131
+ @Environment(\.appTheme) private var theme
120
132
  var title: String
121
133
  var action: () -> Void
122
134
  var type: ButtonType
@@ -125,6 +137,7 @@ public struct Button: View {
125
137
  var iconRight: AnyView?
126
138
  var isFull: Bool
127
139
  var loading: Bool
140
+ var useTintColor: Bool
128
141
 
129
142
  public init(
130
143
  title: String = "",
@@ -134,7 +147,8 @@ public struct Button: View {
134
147
  iconLeft: AnyView? = nil,
135
148
  iconRight: AnyView? = nil,
136
149
  isFull: Bool = true,
137
- loading: Bool = false
150
+ loading: Bool = false,
151
+ useTintColor: Bool = true
138
152
  ) {
139
153
  self.title = title
140
154
  self.action = action
@@ -144,6 +158,36 @@ public struct Button: View {
144
158
  self.iconRight = iconRight
145
159
  self.isFull = isFull
146
160
  self.loading = loading
161
+ self.useTintColor = useTintColor
162
+ }
163
+
164
+ /// Mirrors Kotlin's `Button(iconLeft: String, iconRight: String, ...)`, which resolves
165
+ /// icons by design-system source name through the shared `Icon` component rather than
166
+ /// a caller-supplied view. `iconLeft` is required here (unlike Kotlin's `= ""` default)
167
+ /// solely to keep this initializer unambiguous alongside the `AnyView`-based one above —
168
+ /// pass `""` explicitly for an icon-right-only button.
169
+ public init(
170
+ title: String = "Button",
171
+ action: @escaping () -> Void,
172
+ type: ButtonType = .primary,
173
+ size: ButtonSize = .large,
174
+ iconLeft: String,
175
+ iconRight: String = "",
176
+ isFull: Bool = true,
177
+ loading: Bool = false,
178
+ useTintColor: Bool = true
179
+ ) {
180
+ self.init(
181
+ title: title,
182
+ action: action,
183
+ type: type,
184
+ size: size,
185
+ iconLeft: iconLeft.isEmpty ? nil : AnyView(Icon(source: iconLeft)),
186
+ iconRight: iconRight.isEmpty ? nil : AnyView(Icon(source: iconRight)),
187
+ isFull: isFull,
188
+ loading: loading,
189
+ useTintColor: useTintColor
190
+ )
147
191
  }
148
192
 
149
193
  private func shouldLoadingOnLeft(_ left: AnyView?, _ right: AnyView?) -> Bool {
@@ -160,14 +204,15 @@ public struct Button: View {
160
204
 
161
205
  public var body: some View {
162
206
  let loadingOnLeft = shouldLoadingOnLeft(iconLeft, iconRight)
207
+ let isEnabled = type != .disabled && !loading
163
208
 
164
- let bg = type.backgroundColor(loading: loading)
165
- let fg = type.contentColor(loading: loading)
166
- let border = type.borderColor
209
+ let bg = type.backgroundColor(loading: loading, theme: theme)
210
+ let fg = type.contentColor(loading: loading, theme: theme)
211
+ let border = type.borderColor(theme: theme)
167
212
  let borderWidth = type.borderWidth
168
213
 
169
214
  SwiftUI.Button(action: {
170
- if !loading, type != .disabled {
215
+ if isEnabled {
171
216
  action()
172
217
  }
173
218
  }) {
@@ -178,7 +223,7 @@ public struct Button: View {
178
223
  .colorMultiply(fg)
179
224
 
180
225
  } else if let iconLeft = iconLeft {
181
- iconLeft.frame(width: size.iconSize, height: size.iconSize)
226
+ tintedIcon(iconLeft, color: fg)
182
227
  }
183
228
 
184
229
  MomoText(title, typography: size.typographyStyle, color: fg)
@@ -191,20 +236,84 @@ public struct Button: View {
191
236
  .colorMultiply(fg)
192
237
 
193
238
  } else if let iconRight = iconRight {
194
- iconRight.frame(width: size.iconSize, height: size.iconSize)
239
+ tintedIcon(iconRight, color: fg)
195
240
  }
196
241
  }
197
242
  .frame(maxWidth: isFull ? .infinity : nil)
198
243
  .padding(.horizontal, size.padding)
199
244
  .frame(height: size.height)
200
- .background(bg)
201
- .overlay(
202
- RoundedRectangle(cornerRadius: size.radius)
203
- .strokeBorder(border ?? .clear, lineWidth: border != nil ? borderWidth : 0)
245
+ }
246
+ .buttonStyle(ButtonPressFeedbackStyle(
247
+ isEnabled: isEnabled,
248
+ background: bg,
249
+ border: border,
250
+ borderWidth: borderWidth,
251
+ radius: size.radius,
252
+ height: size.height,
253
+ isFull: isFull
254
+ ))
255
+ .disabled(!isEnabled)
256
+ }
257
+
258
+ @ViewBuilder
259
+ private func tintedIcon(_ icon: AnyView, color: Color) -> some View {
260
+ if useTintColor {
261
+ icon
262
+ .frame(width: size.iconSize, height: size.iconSize)
263
+ .colorMultiply(color)
264
+ } else {
265
+ icon
266
+ .frame(width: size.iconSize, height: size.iconSize)
267
+ }
268
+ }
269
+ }
270
+
271
+ /// Mirrors Compose's press feedback: the background shrinks via an animated
272
+ /// horizontal inset while the content fades, rather than a plain opacity dim on
273
+ /// the whole button (matching `animatedPadding`/`alpha` in Button.kt).
274
+ private struct ButtonPressFeedbackStyle: ButtonStyle {
275
+ let isEnabled: Bool
276
+ let background: Color
277
+ let border: Color?
278
+ let borderWidth: CGFloat
279
+ let radius: CGFloat
280
+ let height: CGFloat
281
+ let isFull: Bool
282
+
283
+ func makeBody(configuration: Configuration) -> some View {
284
+ let pressed = configuration.isPressed && isEnabled
285
+
286
+ configuration.label
287
+ .modifier(HugContentOnLegacyOS(isFull: isFull))
288
+ .opacity(pressed ? 0.5 : 1)
289
+ .background(
290
+ RoundedRectangle(cornerRadius: radius)
291
+ .fill(background)
292
+ .overlay(
293
+ RoundedRectangle(cornerRadius: radius)
294
+ .strokeBorder(border ?? .clear, lineWidth: border != nil ? borderWidth : 0)
295
+ )
296
+ .padding(.horizontal, pressed ? 2 : 0)
204
297
  )
205
- .clipShape(RoundedRectangle(cornerRadius: size.radius))
206
- .opacity(loading ? 0.75 : 1)
298
+ .frame(height: height)
299
+ .clipShape(RoundedRectangle(cornerRadius: radius))
300
+ .animation(.easeInOut(duration: 0.1), value: pressed)
301
+ }
302
+ }
303
+
304
+ /// `ButtonStyleConfiguration.Label` is greedy on iOS 16 and earlier — it accepts
305
+ /// the full proposed width, so the background drawn in `makeBody` stretches past
306
+ /// the content even when `isFull == false`. iOS 17 fixed the label to hug its
307
+ /// content, so only legacy OSes need the `fixedSize` clamp (kept off on 17+ to
308
+ /// preserve tail truncation of long titles).
309
+ private struct HugContentOnLegacyOS: ViewModifier {
310
+ let isFull: Bool
311
+
312
+ func body(content: Content) -> some View {
313
+ if #available(iOS 17.0, *) {
314
+ content
315
+ } else {
316
+ content.fixedSize(horizontal: !isFull, vertical: false)
207
317
  }
208
- .disabled(type == .disabled || loading)
209
318
  }
210
319
  }