@momo-kits/native-kits 0.0.1-beta.4 → 0.0.2-alpha.1

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 (296) hide show
  1. package/CLAUDE.md +99 -0
  2. package/PUBLISH_GUIDE.md +675 -0
  3. package/README.md +184 -5
  4. package/ios/Application/ApplicationEnvironment.swift +71 -0
  5. package/ios/Application/Components.swift +270 -0
  6. package/ios/Application/ComposeApi.swift +22 -0
  7. package/ios/Application/FloatingButton.swift +174 -0
  8. package/ios/Application/HeaderRight.swift +306 -0
  9. package/ios/Application/LanguageSource.swift +93 -0
  10. package/ios/Application/Localize.swift +378 -0
  11. package/ios/Application/LocalizeModifier.swift +30 -0
  12. package/ios/Application/MaxApi.swift +18 -0
  13. package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
  14. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
  15. package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
  16. package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
  17. package/ios/Application/Navigation/HeaderTitle.swift +57 -0
  18. package/ios/Application/Navigation/HeaderUser.swift +209 -0
  19. package/ios/Application/Navigation/NavigationContainer.swift +213 -0
  20. package/ios/Application/Navigation/NavigationOptions.swift +109 -0
  21. package/ios/Application/Navigation/Navigator.swift +453 -0
  22. package/ios/Application/Navigation/NavigatorManager.swift +22 -0
  23. package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
  24. package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
  25. package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
  26. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  27. package/ios/Application/Navigation/component/Header.swift +178 -0
  28. package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
  29. package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
  30. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +11 -0
  31. package/ios/Application/Navigation/component/NavigationFooter.swift +90 -0
  32. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +196 -0
  33. package/ios/Application/Screen.swift +250 -0
  34. package/ios/Application/StackScreen.swift +492 -0
  35. package/ios/Avatar/Avatar.swift +193 -0
  36. package/ios/Badge/Badge.swift +84 -0
  37. package/ios/Badge/BadgeDot.swift +31 -0
  38. package/ios/Badge/BadgeRibbon.swift +319 -0
  39. package/ios/BaselineView/BaselineView.swift +163 -0
  40. package/ios/Button/Button.swift +232 -84
  41. package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +126 -0
  42. package/ios/Carousel/Carousel.swift +196 -0
  43. package/ios/Checkbox/Checkbox.swift +77 -0
  44. package/ios/Chip/Chip.swift +120 -0
  45. package/ios/Collapse/Collapse.swift +192 -0
  46. package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Colors.swift +42 -37
  47. package/ios/Colors+Radius+Spacing/Radius.swift +22 -0
  48. package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Spacing.swift +3 -1
  49. package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
  50. package/ios/DateTimePicker/DateTimePicker.swift +212 -0
  51. package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
  52. package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
  53. package/ios/DateTimePicker/WheelPicker.swift +165 -0
  54. package/ios/Divider/Divider.swift +16 -0
  55. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  56. package/ios/Extensions/Color++.swift +32 -0
  57. package/ios/Icon/Icon.swift +69 -0
  58. package/ios/IconButton/IconButton.swift +140 -0
  59. package/ios/Image/Image.swift +87 -0
  60. package/ios/Information/Information.swift +156 -0
  61. package/ios/Input/ErrorView.swift +58 -0
  62. package/ios/Input/Input.swift +461 -77
  63. package/ios/Input/InputPhoneNumber.swift +192 -0
  64. package/ios/Input/InputSearch.swift +301 -0
  65. package/ios/Input/InputTextArea.swift +318 -0
  66. package/ios/InputDropDown/InputDropDown.swift +201 -0
  67. package/ios/InputMoney/InputMoney.swift +405 -0
  68. package/ios/InputOTP/InputOTP.swift +211 -0
  69. package/ios/Layout/GridContext.swift +30 -0
  70. package/ios/Layout/Item.swift +42 -0
  71. package/ios/Layout/Section.swift +134 -0
  72. package/ios/Loader/Loader.swift +113 -0
  73. package/ios/Lottie/LottieView.swift +86 -0
  74. package/ios/MoMoUIKits.podspec +5 -0
  75. package/ios/OTPKeyboard/KeyboardButton.swift +13 -5
  76. package/ios/OTPKeyboard/OTPKeyboard.swift +1 -1
  77. package/ios/Pagination/PaginationDot.swift +61 -0
  78. package/ios/Pagination/PaginationNumber.swift +35 -0
  79. package/ios/Pagination/PaginationScroll.swift +101 -0
  80. package/ios/Pagination/PaginationWhiteDot.swift +37 -0
  81. package/ios/Popup/PopupDisplay.swift +279 -0
  82. package/ios/Popup/PopupInput.swift +92 -0
  83. package/ios/Popup/PopupNotify.swift +219 -0
  84. package/ios/Popup/PopupPromotion.swift +74 -0
  85. package/ios/PopupView/FullscreenPopup.swift +251 -0
  86. package/ios/{Popup → PopupView}/Modifiers.swift +6 -20
  87. package/ios/{Popup → PopupView}/PopupView.swift +38 -146
  88. package/ios/PopupView/Utils++.swift +281 -0
  89. package/ios/ProgressInfo/ProgressInfo.swift +297 -0
  90. package/ios/Radio/Radio.swift +69 -0
  91. package/ios/Rating/Rating.swift +83 -0
  92. package/{example/ios/Example/Preview Content/Preview Assets.xcassets/Contents.json → ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json} +5 -0
  93. package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Text.colorset/Contents.json +3 -3
  94. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  95. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  96. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  97. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  98. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  99. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  100. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  101. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  102. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  103. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  104. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  105. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  106. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  107. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  108. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  109. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  110. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  111. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  112. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  113. package/ios/ScrollIndicator/ScrollIndicator.swift +110 -0
  114. package/ios/Skeleton/Skeleton.swift +99 -0
  115. package/ios/Slider/Slider.swift +237 -0
  116. package/ios/StatusBarTap/StatusBarTap.h +13 -0
  117. package/ios/StatusBarTap/StatusBarTap.m +75 -0
  118. package/ios/Stepper/Stepper.swift +221 -0
  119. package/ios/Steps/Steps.swift +467 -0
  120. package/ios/SuggestAction/SuggestAction.swift +100 -0
  121. package/ios/Swipeable/SwipeCell.swift +226 -31
  122. package/ios/Swipeable/SwipeCellModel.swift +21 -0
  123. package/ios/Switch/Switch.swift +69 -0
  124. package/ios/TabView/TabView.swift +534 -0
  125. package/ios/Tag/Tag.swift +99 -0
  126. package/ios/Template/Logo/Logo.swift +75 -0
  127. package/ios/Template/TrustBanner/TrustBanner.swift +123 -0
  128. package/ios/Title/Title.swift +270 -0
  129. package/ios/Tooltip/Tooltip.swift +486 -0
  130. package/ios/Typography/FontScale.swift +103 -0
  131. package/ios/Typography/FontScaleStore.swift +58 -0
  132. package/ios/Typography/KitDesignSystem.swift +17 -0
  133. package/ios/Typography/Text.swift +262 -0
  134. package/ios/Typography/Typography.swift +80 -23
  135. package/ios/Uploader/Uploader.swift +174 -0
  136. package/ios/native-kits.podspec +73 -13
  137. package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
  138. package/ios-demo/Resources/dot_loading.json +558 -0
  139. package/ios-demo/Resources/icon.json +4052 -0
  140. package/ios-demo/Resources/lottie_circle_loader.json +1 -0
  141. package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
  142. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
  143. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
  144. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
  145. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
  146. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
  147. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
  148. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
  149. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
  150. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
  151. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
  152. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
  153. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +107 -0
  154. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +75 -0
  155. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
  156. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
  157. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +108 -0
  158. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +96 -0
  159. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +60 -0
  160. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +76 -0
  161. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +102 -0
  162. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
  163. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +100 -0
  164. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +420 -0
  165. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +56 -0
  166. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
  167. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +276 -0
  168. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +93 -0
  169. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +81 -0
  170. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +65 -0
  171. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +96 -0
  172. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +117 -0
  173. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +94 -0
  174. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +94 -0
  175. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +88 -0
  176. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +120 -0
  177. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +85 -0
  178. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +87 -0
  179. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +73 -0
  180. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +235 -0
  181. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +241 -0
  182. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +68 -0
  183. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
  184. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
  185. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +95 -0
  186. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +67 -0
  187. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +101 -0
  188. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +64 -0
  189. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +68 -0
  190. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +83 -0
  191. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +61 -0
  192. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +90 -0
  193. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +82 -0
  194. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +93 -0
  195. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +114 -0
  196. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +90 -0
  197. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +107 -0
  198. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +58 -0
  199. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +114 -0
  200. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +86 -0
  201. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +181 -0
  202. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +104 -0
  203. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +118 -0
  204. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
  205. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +85 -0
  206. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +53 -0
  207. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
  208. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
  209. package/package.json +6 -6
  210. package/publish.sh +554 -20
  211. package/scripts/gen-ios-color.mjs +136 -0
  212. package/CODE_OF_CONDUCT.md +0 -133
  213. package/CONTRIBUTING.md +0 -114
  214. package/LICENSE +0 -20
  215. package/android/build.gradle +0 -82
  216. package/android/gradle.properties +0 -5
  217. package/android/src/main/AndroidManifest.xml +0 -4
  218. package/android/src/main/java/com/momoplatform/nativekits/NativeKitsPackage.kt +0 -17
  219. package/android/src/main/java/com/momoplatform/nativekits/NativeKitsViewManager.kt +0 -20
  220. package/example/ios/Example/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -63
  221. package/example/ios/Example/ComponentDetail.swift +0 -35
  222. package/example/ios/Example/ComponentItem.swift +0 -24
  223. package/example/ios/Example/ComponentModel.swift +0 -33
  224. package/example/ios/Example/ContentView.swift +0 -53
  225. package/example/ios/Example/Example.entitlements +0 -10
  226. package/example/ios/Example/Foundation/ButtonDemo.swift +0 -80
  227. package/example/ios/Example/Foundation/Popup/ActionSheets.swift +0 -136
  228. package/example/ios/Example/Foundation/Popup/Floats.swift +0 -127
  229. package/example/ios/Example/Foundation/Popup/Popups.swift +0 -101
  230. package/example/ios/Example/Foundation/PopupDemo.swift +0 -366
  231. package/example/ios/Example/Foundation/TextInputDemo.swift +0 -31
  232. package/example/ios/Example/Foundation/TypographyDemo.swift +0 -53
  233. package/example/ios/Example/Foundation.swift +0 -26
  234. package/example/ios/Example/Info.plist +0 -18
  235. package/example/ios/Example/Library/SwipeableDemo.swift +0 -105
  236. package/example/ios/Example/Library.swift +0 -26
  237. package/example/ios/Example/Main.swift +0 -11
  238. package/example/ios/Example/Overview.swift +0 -20
  239. package/example/ios/Example/Resource/SFProText-Black.ttf +0 -0
  240. package/example/ios/Example/Resource/SFProText-Bold.ttf +0 -0
  241. package/example/ios/Example/Resource/SFProText-Heavy.ttf +0 -0
  242. package/example/ios/Example/Resource/SFProText-Light.ttf +0 -0
  243. package/example/ios/Example/Resource/SFProText-Medium.ttf +0 -0
  244. package/example/ios/Example/Resource/SFProText-Regular.ttf +0 -0
  245. package/example/ios/Example/Resource/SFProText-Semibold.ttf +0 -0
  246. package/example/ios/Example/Resource/SFProText-Thin.ttf +0 -0
  247. package/example/ios/Example/Resource/SFProText-Ultralight.ttf +0 -0
  248. package/example/ios/Example/Resource/foundation.json +0 -33
  249. package/example/ios/Example/Resource/library.json +0 -8
  250. package/example/ios/Example/Utils.swift +0 -30
  251. package/example/ios/Example/ViewModifier/DarkViewModifier.swift +0 -22
  252. package/example/ios/Example.xcodeproj/project.pbxproj +0 -570
  253. package/example/ios/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  254. package/example/ios/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  255. package/example/ios/Example.xcodeproj/project.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  256. package/example/ios/Example.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  257. package/example/ios/Example.xcworkspace/contents.xcworkspacedata +0 -10
  258. package/example/ios/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  259. package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  260. package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
  261. package/example/ios/Podfile +0 -6
  262. package/example/ios/Podfile.lock +0 -16
  263. package/example/ios/Pods/Local Podspecs/MoMoUIKits.podspec.json +0 -29
  264. package/example/ios/Pods/Manifest.lock +0 -16
  265. package/example/ios/Pods/Pods.xcodeproj/project.pbxproj +0 -661
  266. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
  267. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
  268. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -25
  269. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-dummy.m +0 -5
  270. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-prefix.pch +0 -12
  271. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-umbrella.h +0 -16
  272. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.debug.xcconfig +0 -12
  273. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.modulemap +0 -6
  274. package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.release.xcconfig +0 -12
  275. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.markdown +0 -3
  276. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.plist +0 -29
  277. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-dummy.m +0 -5
  278. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-umbrella.h +0 -16
  279. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig +0 -14
  280. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.modulemap +0 -6
  281. package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig +0 -14
  282. package/ios/Colors+Spacing/Radius.swift +0 -11
  283. package/ios/Popup/Utils++.swift +0 -163
  284. package/ios/Theme.md +0 -18
  285. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Background.colorset/Contents.json +0 -0
  286. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Border.colorset/Contents.json +0 -0
  287. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Card.colorset/Contents.json +0 -0
  288. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Contents.json +0 -0
  289. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Error.colorset/Contents.json +0 -0
  290. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Primary.colorset/Contents.json +0 -0
  291. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/PrimaryDark.colorset/Contents.json +0 -0
  292. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/PrimaryLight.colorset/Contents.json +0 -0
  293. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Secondary.colorset/Contents.json +0 -0
  294. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Success.colorset/Contents.json +0 -0
  295. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/TextSecondary.colorset/Contents.json +0 -0
  296. /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Warning.colorset/Contents.json +0 -0
@@ -0,0 +1,281 @@
1
+ import SwiftUI
2
+ import Combine
3
+
4
+ final class DispatchWorkHolder {
5
+ var work: DispatchWorkItem?
6
+ }
7
+
8
+ final class ClassReference<T> {
9
+ var value: T
10
+
11
+ init(_ value: T) {
12
+ self.value = value
13
+ }
14
+ }
15
+
16
+ public extension View {
17
+
18
+ @ViewBuilder
19
+ func valueChanged<T: Equatable>(value: T, onChange: @escaping (T) -> Void) -> some View {
20
+ if #available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) {
21
+ self.onChange(of: value, perform: onChange)
22
+ } else {
23
+ self.onReceive(Just(value)) { value in
24
+ onChange(value)
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ public extension View {
31
+ @ViewBuilder
32
+ func applyIf<T: View>(_ condition: Bool, apply: (Self) -> T) -> some View {
33
+ if condition {
34
+ apply(self)
35
+ } else {
36
+ self
37
+ }
38
+ }
39
+
40
+ @ViewBuilder
41
+ func addTapIf(if condition: Bool, onTap: @escaping ()->()) -> some View {
42
+ if condition {
43
+ self.simultaneousGesture(
44
+ TapGesture().onEnded {
45
+ onTap()
46
+ }
47
+ )
48
+ } else {
49
+ self
50
+ }
51
+ }
52
+ }
53
+
54
+ struct FrameGetter: ViewModifier {
55
+
56
+ @Binding var frame: CGRect
57
+
58
+ func body(content: Content) -> some View {
59
+ content
60
+ .background(
61
+ GeometryReader { proxy -> AnyView in
62
+ DispatchQueue.main.async {
63
+ let rect = proxy.frame(in: .global)
64
+ // This avoids an infinite layout loop
65
+ if rect.integral != self.frame.integral {
66
+ self.frame = rect
67
+ }
68
+ }
69
+ return AnyView(EmptyView())
70
+ }
71
+ )
72
+ }
73
+ }
74
+
75
+ extension View {
76
+ public func frameGetter(_ frame: Binding<CGRect>) -> some View {
77
+ modifier(FrameGetter(frame: frame))
78
+ }
79
+ }
80
+
81
+ struct AnimationCompletionObserverModifier<Value>: AnimatableModifier where Value: VectorArithmetic, Value: Comparable {
82
+
83
+ /// While animating, SwiftUI changes the old input value to the new target value using this property. This value is set to the old value until the animation completes.
84
+ var animatableData: Value {
85
+ didSet {
86
+ notifyCompletionIfFinished()
87
+ }
88
+ }
89
+
90
+ /// The target value for which we're observing. This value is directly set once the animation starts. During animation, `animatableData` will hold the oldValue and is only updated to the target value once the animation completes.
91
+ private var targetValue: Value
92
+
93
+ /// The completion callback which is called once the animation completes.
94
+ private var completion: () -> Void
95
+
96
+ init(observedValue: Value, completion: @escaping () -> Void) {
97
+ self.completion = completion
98
+ self.animatableData = observedValue
99
+ targetValue = observedValue
100
+ }
101
+
102
+ /// Verifies whether the current animation is finished and calls the completion callback if true.
103
+ private func notifyCompletionIfFinished() {
104
+ guard animatableData == targetValue else { return }
105
+
106
+ /// Dispatching is needed to take the next runloop for the completion callback.
107
+ /// This prevents errors like "Modifying state during view update, this will cause undefined behavior."
108
+ DispatchQueue.main.async {
109
+ self.completion()
110
+ }
111
+ }
112
+
113
+ func body(content: Content) -> some View {
114
+ /// We're not really modifying the view so we can directly return the original input value.
115
+ return content
116
+ }
117
+ }
118
+
119
+ struct AnimatableModifierDouble: AnimatableModifier {
120
+
121
+ var targetValue: Double
122
+ static var done = false
123
+
124
+ // SwiftUI gradually varies it from old value to the new value
125
+ var animatableData: Double {
126
+ didSet {
127
+ checkIfFinished()
128
+ }
129
+ }
130
+ var completion: () -> ()
131
+
132
+ // Re-created every time the control argument changes
133
+ init(bindedValue: Double, completion: @escaping () -> ()) {
134
+ self.completion = completion
135
+
136
+ // Set animatableData to the new value. But SwiftUI again directly
137
+ // and gradually varies the value while the body
138
+ // is being called to animate. Following line serves the purpose of
139
+ // associating the extenal argument with the animatableData.
140
+ self.animatableData = bindedValue
141
+ targetValue = bindedValue
142
+ AnimatableModifierDouble.done = false
143
+ }
144
+
145
+ func checkIfFinished() -> () {
146
+ if AnimatableModifierDouble.done { return }
147
+ let delta = 0.1
148
+ if animatableData > targetValue - delta &&
149
+ animatableData < targetValue + delta {
150
+ //print("check", animatableData, targetValue)
151
+ AnimatableModifierDouble.done = true
152
+ DispatchQueue.main.async {
153
+ self.completion()
154
+ }
155
+ }
156
+ }
157
+
158
+ func body(content: Content) -> some View {
159
+ content
160
+ }
161
+ }
162
+
163
+ extension View {
164
+
165
+ func onAnimationCompleted(for value: Double, completion: @escaping () -> Void) -> some View {
166
+ modifier(AnimatableModifierDouble(bindedValue: value, completion: completion))
167
+ }
168
+ }
169
+
170
+ extension UIApplication {
171
+ var keyWindow: UIWindow? {
172
+ connectedScenes
173
+ .compactMap {
174
+ $0 as? UIWindowScene
175
+ }
176
+ .flatMap {
177
+ $0.windows
178
+ }
179
+ .first {
180
+ $0.isKeyWindow
181
+ }
182
+ }
183
+ }
184
+
185
+ private struct SafeAreaInsetsKey: EnvironmentKey {
186
+ static var defaultValue: EdgeInsets {
187
+ UIApplication.shared.keyWindow?.safeAreaInsets.swiftUiInsets ?? EdgeInsets()
188
+ }
189
+ }
190
+
191
+ extension EnvironmentValues {
192
+ var safeAreaInsets: EdgeInsets {
193
+ self[SafeAreaInsetsKey.self]
194
+ }
195
+ }
196
+
197
+ private extension UIEdgeInsets {
198
+ var swiftUiInsets: EdgeInsets {
199
+ EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
200
+ }
201
+ }
202
+
203
+ extension View {
204
+
205
+ func transparentNonAnimatingFullScreenCover<Content: View>(isPresented: Binding<Bool>, content: @escaping () -> Content) -> some View {
206
+ modifier(TransparentNonAnimatableFullScreenModifier(isPresented: isPresented, fullScreenContent: content))
207
+ }
208
+ }
209
+
210
+ private struct TransparentNonAnimatableFullScreenModifier<FullScreenContent: View>: ViewModifier {
211
+
212
+ @Binding var isPresented: Bool
213
+ let fullScreenContent: () -> (FullScreenContent)
214
+
215
+ func body(content: Content) -> some View {
216
+ if #available(iOS 14.0, *) {
217
+ content
218
+ .valueChanged(value: isPresented, onChange: { isPresented in
219
+ UIView.setAnimationsEnabled(false)
220
+ })
221
+ .fullScreenCover(isPresented: $isPresented, content: {
222
+ ZStack {
223
+ fullScreenContent()
224
+ }
225
+ .background(FullScreenCoverBackgroundRemovalView())
226
+ .onAppear {
227
+ if !UIView.areAnimationsEnabled {
228
+ UIView.setAnimationsEnabled(true)
229
+ }
230
+ }
231
+ .onDisappear {
232
+ if !UIView.areAnimationsEnabled {
233
+ UIView.setAnimationsEnabled(true)
234
+ }
235
+ }
236
+ })
237
+ } else {
238
+ content
239
+ .valueChanged(value: isPresented, onChange: { isPresented in
240
+ UIView.setAnimationsEnabled(false)
241
+ })
242
+ .sheet(isPresented: $isPresented, content: {
243
+ ZStack {
244
+ fullScreenContent()
245
+ }
246
+ .background(FullScreenCoverBackgroundRemovalView())
247
+ .onAppear {
248
+ if !UIView.areAnimationsEnabled {
249
+ UIView.setAnimationsEnabled(true)
250
+ }
251
+ }
252
+ .onDisappear {
253
+ if !UIView.areAnimationsEnabled {
254
+ UIView.setAnimationsEnabled(true)
255
+ }
256
+ }
257
+ })
258
+ }
259
+ }
260
+
261
+ }
262
+
263
+ private struct FullScreenCoverBackgroundRemovalView: UIViewRepresentable {
264
+
265
+ private class BackgroundRemovalView: UIView {
266
+
267
+ override func didMoveToWindow() {
268
+ super.didMoveToWindow()
269
+
270
+ superview?.superview?.backgroundColor = .clear
271
+ }
272
+
273
+ }
274
+
275
+ func makeUIView(context: Context) -> UIView {
276
+ return BackgroundRemovalView()
277
+ }
278
+
279
+ func updateUIView(_ uiView: UIView, context: Context) {}
280
+
281
+ }
@@ -0,0 +1,297 @@
1
+ import SwiftUI
2
+
3
+ // MARK: - Data model
4
+
5
+ public struct ProgressInfoItem: Identifiable {
6
+ public let id = UUID()
7
+ public let title: String
8
+ public let description: String?
9
+
10
+ public init(title: String, description: String? = nil) {
11
+ self.title = title
12
+ self.description = description
13
+ }
14
+ }
15
+
16
+ public enum ProgressInfoSize {
17
+ case small
18
+ case large
19
+ }
20
+
21
+ public enum ProgressInfoAlign {
22
+ case left
23
+ case right
24
+ case center
25
+ case stretch
26
+ }
27
+
28
+ // MARK: - Public entry-point
29
+
30
+ /// Display-only step progress indicator.
31
+ ///
32
+ /// - Parameters:
33
+ /// - steps: Ordered list of steps; each has a title and an optional description.
34
+ /// - horizontal: When `true` renders steps in a horizontal row with connector lines;
35
+ /// when `false` (default) renders a vertical column.
36
+ /// - size: Icon diameter: `.small` = 16, `.large` = 24 (default).
37
+ /// - useNumber: Show the 1-based step index inside the icon instead of the default dot.
38
+ /// - align: Alignment of icon + text for the horizontal variant.
39
+ /// - showTitle: Whether step titles are rendered (default `true`).
40
+ /// - showDescription: Whether step descriptions are rendered (default `true`).
41
+ /// - customIcon: Icon source key rendered inside each step circle (overrides the dot;
42
+ /// itself overridden by `useNumber`).
43
+ public struct ProgressInfo: View {
44
+ private let steps: [ProgressInfoItem]
45
+ private let horizontal: Bool
46
+ private let size: ProgressInfoSize
47
+ private let useNumber: Bool
48
+ private let align: ProgressInfoAlign
49
+ private let showTitle: Bool
50
+ private let showDescription: Bool
51
+ private let customIcon: String?
52
+
53
+ public init(
54
+ steps: [ProgressInfoItem],
55
+ horizontal: Bool = false,
56
+ size: ProgressInfoSize = .large,
57
+ useNumber: Bool = false,
58
+ align: ProgressInfoAlign = .center,
59
+ showTitle: Bool = true,
60
+ showDescription: Bool = true,
61
+ customIcon: String? = nil
62
+ ) {
63
+ self.steps = steps
64
+ self.horizontal = horizontal
65
+ self.size = size
66
+ self.useNumber = useNumber
67
+ self.align = align
68
+ self.showTitle = showTitle
69
+ self.showDescription = showDescription
70
+ self.customIcon = customIcon
71
+ }
72
+
73
+ public var body: some View {
74
+ if horizontal {
75
+ ProgressInfoHorizontal(
76
+ steps: steps,
77
+ size: size,
78
+ useNumber: useNumber,
79
+ align: align,
80
+ showTitle: showTitle,
81
+ showDescription: showDescription,
82
+ customIcon: customIcon
83
+ )
84
+ } else {
85
+ ProgressInfoVertical(
86
+ steps: steps,
87
+ size: size,
88
+ useNumber: useNumber,
89
+ showTitle: showTitle,
90
+ showDescription: showDescription,
91
+ customIcon: customIcon
92
+ )
93
+ }
94
+ }
95
+ }
96
+
97
+ // MARK: - Tokens
98
+
99
+ private let progressInfoLineColor = Colors.pink08
100
+ private let progressInfoAccentColor = Colors.pinkMoMoBranding
101
+
102
+ // MARK: - Horizontal variant
103
+
104
+ private struct ProgressInfoHorizontal: View {
105
+ let steps: [ProgressInfoItem]
106
+ let size: ProgressInfoSize
107
+ let useNumber: Bool
108
+ let align: ProgressInfoAlign
109
+ let showTitle: Bool
110
+ let showDescription: Bool
111
+ let customIcon: String?
112
+
113
+ var body: some View {
114
+ HStack(alignment: .top, spacing: 0) {
115
+ ForEach(Array(steps.enumerated()), id: \.element.id) { index, item in
116
+ let isFirst = index == 0
117
+ let isLast = index == steps.count - 1
118
+
119
+ let alignment = columnAlignment(isFirst: isFirst, isLast: isLast)
120
+ let textAlign = textAlignment(isFirst: isFirst, isLast: isLast)
121
+ let endPadding: CGFloat = (!isLast && align != .center && align != .stretch) ? Spacing.XS : 0
122
+ let hideLineLeft = align == .left || (align == .stretch && isFirst)
123
+ let hideLineRight = align == .right || (align == .stretch && isLast)
124
+
125
+ VStack(alignment: alignment, spacing: 0) {
126
+ HStack(spacing: 0) {
127
+ if !hideLineLeft {
128
+ ProgressInfoHorizontalLine()
129
+ }
130
+ ProgressInfoStepIcon(
131
+ index: index,
132
+ size: size,
133
+ useNumber: useNumber,
134
+ customIcon: customIcon
135
+ )
136
+ .padding(.vertical, Spacing.XS)
137
+ if !hideLineRight {
138
+ ProgressInfoHorizontalLine()
139
+ }
140
+ }
141
+ .frame(maxWidth: .infinity)
142
+
143
+ if showTitle && !item.title.isEmpty {
144
+ MomoText(item.title, typography: .headerXsSemibold)
145
+ .multilineTextAlignment(textAlign)
146
+ .frame(maxWidth: .infinity, alignment: frameAlignment(alignment))
147
+ .padding(.bottom, Spacing.XS)
148
+ }
149
+
150
+ if showDescription, let desc = item.description, !desc.isEmpty {
151
+ MomoText(desc, typography: .descriptionDefaultRegular, color: Colors.black12)
152
+ .multilineTextAlignment(textAlign)
153
+ .frame(maxWidth: .infinity, alignment: frameAlignment(alignment))
154
+ }
155
+ }
156
+ .frame(maxWidth: .infinity)
157
+ .padding(.trailing, endPadding)
158
+ }
159
+ }
160
+ .frame(maxWidth: .infinity)
161
+ }
162
+
163
+ private func columnAlignment(isFirst: Bool, isLast: Bool) -> HorizontalAlignment {
164
+ switch align {
165
+ case .left: return .leading
166
+ case .right: return .trailing
167
+ case .center: return .center
168
+ case .stretch:
169
+ if isFirst { return .leading }
170
+ if isLast { return .trailing }
171
+ return .center
172
+ }
173
+ }
174
+
175
+ private func frameAlignment(_ h: HorizontalAlignment) -> Alignment {
176
+ switch h {
177
+ case .leading: return .leading
178
+ case .trailing: return .trailing
179
+ default: return .center
180
+ }
181
+ }
182
+
183
+ private func textAlignment(isFirst: Bool, isLast: Bool) -> TextAlignment {
184
+ switch align {
185
+ case .left: return .leading
186
+ case .right: return .trailing
187
+ case .center: return .center
188
+ case .stretch:
189
+ if isFirst { return .leading }
190
+ if isLast { return .trailing }
191
+ return .center
192
+ }
193
+ }
194
+ }
195
+
196
+ // MARK: - Vertical variant
197
+
198
+ private struct ProgressInfoVertical: View {
199
+ @Environment(\.appTheme) private var theme
200
+
201
+ let steps: [ProgressInfoItem]
202
+ let size: ProgressInfoSize
203
+ let useNumber: Bool
204
+ let showTitle: Bool
205
+ let showDescription: Bool
206
+ let customIcon: String?
207
+
208
+ var body: some View {
209
+ VStack(alignment: .leading, spacing: 0) {
210
+ ForEach(Array(steps.enumerated()), id: \.element.id) { index, item in
211
+ let isLast = index == steps.count - 1
212
+
213
+ HStack(alignment: .top, spacing: 0) {
214
+ VStack(spacing: 0) {
215
+ ProgressInfoStepIcon(
216
+ index: index,
217
+ size: size,
218
+ useNumber: useNumber,
219
+ customIcon: customIcon
220
+ )
221
+ if !isLast {
222
+ Rectangle()
223
+ .fill(theme.colors.primary.opacity(0.2))
224
+ .frame(width: 2)
225
+ .frame(maxHeight: .infinity)
226
+ }
227
+ }
228
+ .frame(minHeight: isLast ? 40 : 48)
229
+
230
+ VStack(alignment: .leading, spacing: 0) {
231
+ if showTitle && !item.title.isEmpty {
232
+ MomoText(item.title, typography: .headerXsSemibold)
233
+ .lineLimit(2)
234
+ .frame(maxWidth: .infinity, alignment: .leading)
235
+ .padding(.trailing, Spacing.S)
236
+ }
237
+ if showDescription, let desc = item.description, !desc.isEmpty {
238
+ MomoText(desc, typography: .descriptionDefaultRegular, color: Colors.black12)
239
+ .frame(maxWidth: .infinity, alignment: .leading)
240
+ }
241
+ }
242
+ .frame(maxWidth: .infinity, alignment: .leading)
243
+ .padding(.trailing, Spacing.S)
244
+ .padding(.bottom, isLast ? 0 : Spacing.S)
245
+ }
246
+ .frame(maxWidth: .infinity, alignment: .leading)
247
+ .fixedSize(horizontal: false, vertical: true)
248
+ }
249
+ }
250
+ .frame(maxWidth: .infinity, alignment: .leading)
251
+ }
252
+ }
253
+
254
+ // MARK: - Step icon
255
+
256
+ private struct ProgressInfoStepIcon: View {
257
+ @Environment(\.momoFontScale) private var fontScale
258
+ let index: Int
259
+ let size: ProgressInfoSize
260
+ let useNumber: Bool
261
+ let customIcon: String?
262
+
263
+ var body: some View {
264
+ let containerSize = fontScale(size == .small ? 16 : 24)
265
+ let dotSize = fontScale(size == .small ? 6 : 8)
266
+ let iconSize = fontScale(size == .small ? 12 : 16)
267
+
268
+ ZStack {
269
+ Circle()
270
+ .fill(progressInfoLineColor)
271
+ .overlay(Circle().strokeBorder(progressInfoLineColor, lineWidth: 2))
272
+
273
+ if useNumber {
274
+ MomoText("\(index + 1)", typography: .headerXsSemibold, color: progressInfoAccentColor)
275
+ .multilineTextAlignment(.center)
276
+ } else if let icon = customIcon, !icon.isEmpty {
277
+ Icon(source: icon, size: iconSize, color: progressInfoAccentColor)
278
+ } else {
279
+ Circle()
280
+ .fill(progressInfoAccentColor)
281
+ .frame(width: dotSize, height: dotSize)
282
+ }
283
+ }
284
+ .frame(width: containerSize, height: containerSize)
285
+ }
286
+ }
287
+
288
+ // MARK: - Horizontal connector line
289
+
290
+ private struct ProgressInfoHorizontalLine: View {
291
+ var body: some View {
292
+ Rectangle()
293
+ .fill(progressInfoLineColor)
294
+ .frame(height: 2)
295
+ .frame(maxWidth: .infinity)
296
+ }
297
+ }
@@ -0,0 +1,69 @@
1
+ import Foundation
2
+ import SwiftUI
3
+
4
+ public struct Radio: View {
5
+ @Environment(\.appTheme) private var theme
6
+
7
+ var value: AnyHashable
8
+ @Binding var groupValue: AnyHashable
9
+ var disabled: Bool
10
+ var onChange: (() -> Void)?
11
+ var label: String
12
+
13
+ public init(
14
+ value: AnyHashable,
15
+ groupValue: Binding<AnyHashable>,
16
+ disabled: Bool = false,
17
+ onChange: (() -> Void)? = nil,
18
+ label: String = ""
19
+ ) {
20
+ self.value = value
21
+ self._groupValue = groupValue
22
+ self.disabled = disabled
23
+ self.onChange = onChange
24
+ self.label = label
25
+ }
26
+
27
+ private var selected: Bool {
28
+ value == groupValue
29
+ }
30
+
31
+ private func onTap() {
32
+ groupValue = value
33
+ onChange?()
34
+ }
35
+
36
+ public var body: some View {
37
+ SwiftUI.Button(action: onTap) {
38
+ HStack(spacing: 0) {
39
+ RoundedRectangle(cornerRadius: Radius.M)
40
+ .stroke(borderColor, lineWidth: borderWidth)
41
+ .frame(width: 20, height: 20)
42
+ .padding(.trailing, label.isEmpty ? 0 : Spacing.XS)
43
+
44
+ if !label.isEmpty {
45
+ MomoText(label, typography: .descriptionDefaultRegular)
46
+ }
47
+ }
48
+ .contentShape(Rectangle())
49
+ }
50
+ .buttonStyle(ActiveOpacityButtonStyle())
51
+ .disabled(disabled)
52
+ }
53
+
54
+ private var borderWidth: CGFloat {
55
+ selected ? 6 : 2
56
+ }
57
+
58
+ private var borderColor: Color {
59
+ if disabled && selected {
60
+ return theme.colors.background.tonal
61
+ } else if disabled {
62
+ return theme.colors.text.disable
63
+ } else if selected {
64
+ return theme.colors.primary
65
+ } else {
66
+ return theme.colors.text.default
67
+ }
68
+ }
69
+ }