@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,100 @@
1
+ import SwiftUI
2
+ import Foundation
3
+
4
+ public struct SuggestAction: View {
5
+ @Environment(\.appTheme) private var theme
6
+ @Environment(\.momoFontScale) private var fontScale
7
+
8
+ private let message: String
9
+ private let buttonTitle: String
10
+ private let boldMessage: String
11
+ private let image: String
12
+ private let visible: Bool
13
+ private let onClose: () -> Void
14
+ private let onPressButton: () -> Void
15
+
16
+ public init(
17
+ message: String,
18
+ buttonTitle: String,
19
+ boldMessage: String = "",
20
+ image: String = "",
21
+ visible: Bool = false,
22
+ onClose: @escaping () -> Void = {},
23
+ onPressButton: @escaping () -> Void = {}
24
+ ) {
25
+ self.message = message
26
+ self.buttonTitle = buttonTitle
27
+ self.boldMessage = boldMessage
28
+ self.image = image
29
+ self.visible = visible
30
+ self.onClose = onClose
31
+ self.onPressButton = onPressButton
32
+ }
33
+
34
+ // Builds an attributed string with `boldMessage` (case-insensitive) emphasized.
35
+ private var annotatedMessage: AttributedString {
36
+ let baseFont = Font.system(size: fontScale(TypographyStyle.bodyDefaultRegular.fontSize), weight: .regular)
37
+ var attributed = AttributedString(message)
38
+ attributed.font = baseFont
39
+
40
+ guard !boldMessage.isEmpty,
41
+ let range = message.range(of: boldMessage, options: .caseInsensitive)
42
+ else {
43
+ return attributed
44
+ }
45
+
46
+ if let boldRange = Range(range, in: attributed) {
47
+ attributed[boldRange].font = Font.system(
48
+ size: fontScale(TypographyStyle.bodyDefaultRegular.fontSize),
49
+ weight: .bold
50
+ )
51
+ }
52
+ return attributed
53
+ }
54
+
55
+ public var body: some View {
56
+ Group {
57
+ if visible {
58
+ HStack(spacing: 0) {
59
+ if !image.isEmpty {
60
+ ImageView(image)
61
+ .frame(width: 32, height: 32)
62
+ .clipShape(RoundedRectangle(cornerRadius: Radius.XS, style: .continuous))
63
+ Spacer().frame(width: Spacing.S)
64
+ }
65
+
66
+ Text(annotatedMessage)
67
+ .foregroundColor(theme.colors.text.default)
68
+ .frame(maxWidth: .infinity, alignment: .leading)
69
+ .padding(.trailing, Spacing.M)
70
+
71
+ Button(
72
+ title: buttonTitle,
73
+ action: { onPressButton() },
74
+ type: .tonal,
75
+ size: .small,
76
+ isFull: false
77
+ )
78
+
79
+ Spacer().frame(width: Spacing.S)
80
+
81
+ SwiftUI.Button(action: onClose) {
82
+ Icon(source: "navigation_close", size: 24, color: theme.colors.text.default)
83
+ .contentShape(Rectangle())
84
+ }
85
+ .buttonStyle(ActiveOpacityButtonStyle())
86
+ }
87
+ .padding(Spacing.M)
88
+ .frame(maxWidth: .infinity)
89
+ .background(
90
+ RoundedRectangle(cornerRadius: Radius.S, style: .continuous)
91
+ .fill(theme.colors.background.surface)
92
+ )
93
+ .clipShape(RoundedRectangle(cornerRadius: Radius.S, style: .continuous))
94
+ .shadow(color: theme.colors.text.default.opacity(0.12), radius: 8, x: 0, y: 4)
95
+ .transition(.opacity)
96
+ }
97
+ }
98
+ .animation(.easeInOut, value: visible)
99
+ }
100
+ }
@@ -1,6 +1,193 @@
1
1
  import Foundation
2
2
  import SwiftUI
3
3
 
4
+ private let swipeActionWidth: CGFloat = 56
5
+
6
+ // MARK: - Swipe
7
+
8
+ public struct Swipe<Content: View>: View {
9
+ @Environment(\.appTheme) private var theme
10
+
11
+ private let leftActions: [SwipeAction]
12
+ private let rightActions: [SwipeAction]
13
+ private let height: CGFloat
14
+ private let itemRadius: CGFloat
15
+ private let onSwipeableOpen: () -> Void
16
+ private let onSwipeableClose: () -> Void
17
+ private let onSwipeableLeftOpen: () -> Void
18
+ private let onSwipeableRightOpen: () -> Void
19
+ private let content: () -> Content
20
+
21
+ @State private var offsetX: CGFloat = 0
22
+ @State private var dragStartOffsetX: CGFloat?
23
+
24
+ public init(
25
+ leftActions: [SwipeAction] = [],
26
+ rightActions: [SwipeAction] = [],
27
+ height: CGFloat = 56,
28
+ itemRadius: CGFloat = 0,
29
+ onSwipeableOpen: @escaping () -> Void = {},
30
+ onSwipeableClose: @escaping () -> Void = {},
31
+ onSwipeableLeftOpen: @escaping () -> Void = {},
32
+ onSwipeableRightOpen: @escaping () -> Void = {},
33
+ @ViewBuilder content: @escaping () -> Content
34
+ ) {
35
+ self.leftActions = Array(leftActions.prefix(3))
36
+ self.rightActions = Array(rightActions.prefix(3))
37
+ self.height = height
38
+ self.itemRadius = itemRadius
39
+ self.onSwipeableOpen = onSwipeableOpen
40
+ self.onSwipeableClose = onSwipeableClose
41
+ self.onSwipeableLeftOpen = onSwipeableLeftOpen
42
+ self.onSwipeableRightOpen = onSwipeableRightOpen
43
+ self.content = content
44
+ }
45
+
46
+ public var body: some View {
47
+ let leftWidth = swipeActionWidth * CGFloat(leftActions.count)
48
+ let rightWidth = swipeActionWidth * CGFloat(rightActions.count)
49
+ let shape = RoundedRectangle(cornerRadius: itemRadius)
50
+
51
+ ZStack {
52
+ if !leftActions.isEmpty {
53
+ HStack(spacing: 0) {
54
+ ForEach(Array(leftActions.enumerated()), id: \.offset) { _, action in
55
+ SwipeActionButton(
56
+ action: action,
57
+ height: height,
58
+ itemRadius: itemRadius,
59
+ defaultBackgroundColor: theme.colors.primary
60
+ )
61
+ }
62
+ Spacer(minLength: 0)
63
+ }
64
+ }
65
+
66
+ if !rightActions.isEmpty {
67
+ HStack(spacing: 0) {
68
+ Spacer(minLength: 0)
69
+ ForEach(Array(rightActions.enumerated()), id: \.offset) { _, action in
70
+ SwipeActionButton(
71
+ action: action,
72
+ height: height,
73
+ itemRadius: itemRadius,
74
+ defaultBackgroundColor: theme.colors.error.primary
75
+ )
76
+ }
77
+ }
78
+ }
79
+
80
+ ZStack {
81
+ theme.colors.background.surface
82
+ content()
83
+ }
84
+ .frame(maxWidth: .infinity)
85
+ .frame(height: height)
86
+ .clipShape(shape)
87
+ .offset(x: offsetX)
88
+ .gesture(
89
+ DragGesture(minimumDistance: 8, coordinateSpace: .local)
90
+ .onChanged { value in
91
+ dragOnChanged(value: value, leftWidth: leftWidth, rightWidth: rightWidth)
92
+ }
93
+ .onEnded { _ in
94
+ dragStartOffsetX = nil
95
+ snapToClosest(leftWidth: leftWidth, rightWidth: rightWidth)
96
+ }
97
+ )
98
+ }
99
+ .frame(maxWidth: .infinity)
100
+ .frame(height: height)
101
+ .clipped()
102
+ }
103
+
104
+ private func dragOnChanged(value: DragGesture.Value, leftWidth: CGFloat, rightWidth: CGFloat) {
105
+ if dragStartOffsetX == nil {
106
+ dragStartOffsetX = offsetX
107
+ }
108
+
109
+ let proposedOffset = (dragStartOffsetX ?? 0) + value.translation.width
110
+ offsetX = min(max(proposedOffset, -rightWidth), leftWidth)
111
+ }
112
+
113
+ private func snapToClosest(leftWidth: CGFloat, rightWidth: CGFloat) {
114
+ let target: CGFloat
115
+
116
+ if offsetX > leftWidth * 0.5, !leftActions.isEmpty {
117
+ onSwipeableLeftOpen()
118
+ onSwipeableOpen()
119
+ target = leftWidth
120
+ } else if offsetX < -rightWidth * 0.5, !rightActions.isEmpty {
121
+ onSwipeableRightOpen()
122
+ onSwipeableOpen()
123
+ target = -rightWidth
124
+ } else {
125
+ onSwipeableClose()
126
+ target = 0
127
+ }
128
+
129
+ withAnimation(.easeOut(duration: 0.2)) {
130
+ offsetX = target
131
+ }
132
+ }
133
+ }
134
+
135
+ public extension Swipe where Content == EmptyView {
136
+ init(
137
+ leftActions: [SwipeAction] = [],
138
+ rightActions: [SwipeAction] = [],
139
+ height: CGFloat = 56,
140
+ itemRadius: CGFloat = 0,
141
+ onSwipeableOpen: @escaping () -> Void = {},
142
+ onSwipeableClose: @escaping () -> Void = {},
143
+ onSwipeableLeftOpen: @escaping () -> Void = {},
144
+ onSwipeableRightOpen: @escaping () -> Void = {}
145
+ ) {
146
+ self.init(
147
+ leftActions: leftActions,
148
+ rightActions: rightActions,
149
+ height: height,
150
+ itemRadius: itemRadius,
151
+ onSwipeableOpen: onSwipeableOpen,
152
+ onSwipeableClose: onSwipeableClose,
153
+ onSwipeableLeftOpen: onSwipeableLeftOpen,
154
+ onSwipeableRightOpen: onSwipeableRightOpen
155
+ ) {
156
+ EmptyView()
157
+ }
158
+ }
159
+ }
160
+
161
+ private struct SwipeActionButton: View {
162
+ let action: SwipeAction
163
+ let height: CGFloat
164
+ let itemRadius: CGFloat
165
+ let defaultBackgroundColor: Color
166
+
167
+ var body: some View {
168
+ SwiftUI.Button(action: action.onPress) {
169
+ VStack(spacing: Spacing.XXS) {
170
+ if !action.icon.isEmpty {
171
+ Icon(source: action.icon, size: 20, color: Colors.black01)
172
+ }
173
+
174
+ if !action.label.isEmpty {
175
+ MomoText(
176
+ action.label,
177
+ typography: .labelSMedium,
178
+ color: Colors.black01,
179
+ maxLines: 1
180
+ )
181
+ }
182
+ }
183
+ .frame(width: swipeActionWidth, height: height)
184
+ .background(action.backgroundColor ?? defaultBackgroundColor)
185
+ .clipShape(RoundedRectangle(cornerRadius: itemRadius))
186
+ }
187
+ .buttonStyle(.plain)
188
+ }
189
+ }
190
+
4
191
  // MARK: - SwipeCellModifier
5
192
 
6
193
  public struct SwipeCellModifier: ViewModifier {
@@ -10,9 +197,9 @@ public struct SwipeCellModifier: ViewModifier {
10
197
  var trailingSideGroup: [SwipeCellActionItem] = []
11
198
  @Binding var currentUserInteractionCellID: String?
12
199
  var settings: SwipeCellSettings = .init()
13
-
200
+
14
201
  @State private var offsetX: CGFloat = 0
15
-
202
+
16
203
  let generator = UINotificationFeedbackGenerator()
17
204
  @State private var hapticFeedbackOccurred: Bool = false
18
205
  @State private var openSideLock: SwipeGroupSide?
@@ -22,15 +209,23 @@ public struct SwipeCellModifier: ViewModifier {
22
209
  if self.leadingSideGroup.isEmpty == false && self.offsetX != 0 {
23
210
  self.swipeToRevealArea(swipeItemGroup: self.leadingSideGroup, side: .leading)
24
211
  }
25
-
212
+
26
213
  if self.trailingSideGroup.isEmpty == false && self.offsetX != 0 {
27
214
  self.swipeToRevealArea(swipeItemGroup: self.trailingSideGroup, side: .trailing)
28
215
  }
29
-
216
+
30
217
  content
31
218
  .offset(x: self.offsetX)
32
- .gesture(DragGesture(minimumDistance: 30, coordinateSpace: .local).onChanged(self.dragOnChanged(value:)).onEnded(dragOnEnded(value:)))
33
-
219
+ .simultaneousGesture(
220
+ DragGesture(minimumDistance: 30, coordinateSpace: .local)
221
+ .onChanged { value in
222
+ self.dragOnChanged(value: value)
223
+ }
224
+ .onEnded { value in
225
+ self.dragOnEnded(value: value)
226
+ }
227
+ )
228
+
34
229
  }.frame(width: cellWidth)
35
230
  .edgesIgnoringSafeArea(.horizontal)
36
231
  .clipped()
@@ -43,7 +238,7 @@ public struct SwipeCellModifier: ViewModifier {
43
238
  }
44
239
  }
45
240
  }
46
-
241
+
47
242
  internal func swipeToRevealArea(swipeItemGroup: [SwipeCellActionItem], side: SwipeGroupSide)->some View {
48
243
  HStack {
49
244
  if side == .trailing {
@@ -63,17 +258,17 @@ public struct SwipeCellModifier: ViewModifier {
63
258
  }
64
259
  }
65
260
  }.opacity(self.swipeRevealAreaOpacity(side: side))
66
-
261
+
67
262
  if side == .leading {
68
263
  Spacer()
69
264
  }
70
265
  }
71
266
  }
72
-
267
+
73
268
  internal func buttonContentView(item: SwipeCellActionItem, group: [SwipeCellActionItem], side: SwipeGroupSide)->some View {
74
269
  ZStack {
75
270
  item.backgroundColor
76
-
271
+
77
272
  HStack {
78
273
  if self.warnSwipeOutCondition(side: side, hasSwipeOut: item.swipeOutAction) && item.swipeOutButtonView != nil {
79
274
  item.swipeOutButtonView!()
@@ -81,28 +276,28 @@ public struct SwipeCellModifier: ViewModifier {
81
276
  item.buttonView()
82
277
  }
83
278
  }
84
-
279
+
85
280
  }.frame(width: self.itemButtonWidth(item: item, itemGroup: group, side: side))
86
281
  }
87
-
282
+
88
283
  internal func menuWidth(side: SwipeGroupSide)->CGFloat {
89
284
  switch side {
90
285
  case .leading:
91
286
  return self.leadingSideGroup.map { $0.buttonWidth }.reduce(0, +)
92
-
287
+
93
288
  case .trailing:
94
289
  return self.trailingSideGroup.map { $0.buttonWidth }.reduce(0, +)
95
290
  }
96
291
  }
97
-
292
+
98
293
  // MARK: drag gesture
99
-
294
+
100
295
  internal func dragOnChanged(value: DragGesture.Value) {
101
296
  let horizontalTranslation = value.translation.width
102
297
  if self.nonDraggableCondition(horizontalTranslation: horizontalTranslation) {
103
298
  return
104
299
  }
105
-
300
+
106
301
  if self.openSideLock != nil {
107
302
  // if one side is open, we need to add the menu width!
108
303
  let menuWidth = self.openSideLock == .leading ? self.menuWidth(side: .leading) : self.menuWidth(side: .trailing)
@@ -110,9 +305,9 @@ public struct SwipeCellModifier: ViewModifier {
110
305
  self.triggerHapticFeedbackIfNeeded(horizontalTranslation: horizontalTranslation)
111
306
  return
112
307
  }
113
-
308
+
114
309
  self.triggerHapticFeedbackIfNeeded(horizontalTranslation: horizontalTranslation)
115
-
310
+
116
311
  if horizontalTranslation > 8 || horizontalTranslation < -8 { // makes sure the swipe cell doesn't open too easily
117
312
  self.currentUserInteractionCellID = self.id
118
313
  self.offsetX = horizontalTranslation
@@ -120,11 +315,11 @@ public struct SwipeCellModifier: ViewModifier {
120
315
  self.offsetX = 0
121
316
  }
122
317
  }
123
-
318
+
124
319
  internal func nonDraggableCondition(horizontalTranslation: CGFloat)->Bool {
125
320
  return self.offsetX == 0 && (self.leadingSideGroup.isEmpty && horizontalTranslation > 0 || self.trailingSideGroup.isEmpty && horizontalTranslation < 0)
126
321
  }
127
-
322
+
128
323
  internal func dragOnEnded(value: DragGesture.Value) {
129
324
  let swipeOutTriggerValue = self.cellWidth * self.settings.swipeOutTriggerRatio
130
325
 
@@ -139,7 +334,7 @@ public struct SwipeCellModifier: ViewModifier {
139
334
  } else {
140
335
  self.lockSideMenu(side: .leading)
141
336
  }
142
-
337
+
143
338
  } else {
144
339
  // leading group emtpy
145
340
  self.setOffsetX(value: 0)
@@ -160,7 +355,7 @@ public struct SwipeCellModifier: ViewModifier {
160
355
  }
161
356
  }
162
357
  }
163
-
358
+
164
359
  internal func triggerHapticFeedbackIfNeeded(horizontalTranslation: CGFloat) {
165
360
  let side: SwipeGroupSide = horizontalTranslation > 0 ? .leading : .trailing
166
361
  let group = side == .leading ? self.leadingSideGroup : self.trailingSideGroup
@@ -170,7 +365,7 @@ public struct SwipeCellModifier: ViewModifier {
170
365
  self.hapticFeedbackOccurred = true
171
366
  }
172
367
  }
173
-
368
+
174
369
  internal func swipeOutItemWithHapticFeedback(group: [SwipeCellActionItem])->SwipeCellActionItem? {
175
370
  if let item = group.filter({ $0.swipeOutAction == true }).first {
176
371
  if item.swipeOutHapticFeedbackType != nil {
@@ -179,7 +374,7 @@ public struct SwipeCellModifier: ViewModifier {
179
374
  }
180
375
  return nil
181
376
  }
182
-
377
+
183
378
  internal func swipeOutAction(item: SwipeCellActionItem, sideFactor: CGFloat) {
184
379
  if item.swipeOutIsDestructive {
185
380
  let swipeOutWidth = cellWidth + 10
@@ -188,12 +383,12 @@ public struct SwipeCellModifier: ViewModifier {
188
383
  } else {
189
384
  self.setOffsetX(value: 0) // open side lock set in function!
190
385
  }
191
-
386
+
192
387
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
193
388
  item.actionCallback()
194
389
  }
195
390
  }
196
-
391
+
197
392
  internal func lockSideMenu(side: SwipeGroupSide) {
198
393
  self.setOffsetX(value: side.sideFactor * self.menuWidth(side: side))
199
394
  self.openSideLock = side
@@ -214,7 +409,7 @@ public struct SwipeCellModifier: ViewModifier {
214
409
  let dynamicButtonWidth = self.dynamicButtonWidth(item: item, itemCount: itemGroup.count, side: side)
215
410
  let triggerValue = self.cellWidth * settings.swipeOutTriggerRatio
216
411
  let swipeOutActionCondition = side == .leading ? self.offsetX > triggerValue : self.offsetX < -triggerValue
217
-
412
+
218
413
  if item.swipeOutAction && swipeOutActionCondition {
219
414
  return self.offsetX.magnitude + settings.addWidthMargin
220
415
  } else if swipeOutActionCondition && item.swipeOutAction == false && itemGroup.contains(where: { $0.swipeOutAction == true }) {
@@ -223,12 +418,12 @@ public struct SwipeCellModifier: ViewModifier {
223
418
  return dynamicButtonWidth
224
419
  }
225
420
  }
226
-
421
+
227
422
  internal func dynamicButtonWidth(item: SwipeCellActionItem, itemCount: Int, side: SwipeGroupSide)->CGFloat {
228
423
  let menuWidth = self.menuWidth(side: side)
229
424
  return (self.offsetX.magnitude + settings.addWidthMargin) * (item.buttonWidth / menuWidth)
230
425
  }
231
-
426
+
232
427
  internal func warnSwipeOutCondition(side: SwipeGroupSide, hasSwipeOut: Bool)->Bool {
233
428
  if hasSwipeOut == false {
234
429
  return false
@@ -236,11 +431,11 @@ public struct SwipeCellModifier: ViewModifier {
236
431
  let triggerValue = self.cellWidth * settings.swipeOutTriggerRatio
237
432
  return (side == .trailing && self.offsetX < -triggerValue) || (side == .leading && self.offsetX > triggerValue)
238
433
  }
239
-
434
+
240
435
  internal func swipeRevealAreaOpacity(side: SwipeGroupSide)->Double {
241
436
  switch side {
242
437
  case .leading:
243
-
438
+
244
439
  return self.offsetX > 5 ? 1 : 0
245
440
  case .trailing:
246
441
  return self.offsetX < -5 ? 1 : 0
@@ -3,6 +3,27 @@
3
3
  import Foundation
4
4
  import SwiftUI
5
5
 
6
+ // MARK: - SwipeAction
7
+
8
+ public struct SwipeAction {
9
+ public init(
10
+ label: String = "",
11
+ icon: String = "",
12
+ backgroundColor: Color? = nil,
13
+ onPress: @escaping () -> Void = {}
14
+ ) {
15
+ self.label = label
16
+ self.icon = icon
17
+ self.backgroundColor = backgroundColor
18
+ self.onPress = onPress
19
+ }
20
+
21
+ public var label: String
22
+ public var icon: String
23
+ public var backgroundColor: Color?
24
+ public var onPress: () -> Void
25
+ }
26
+
6
27
  // MARK: - SwipeGroupSide
7
28
 
8
29
  public enum SwipeGroupSide {
@@ -0,0 +1,69 @@
1
+ import Foundation
2
+ import SwiftUI
3
+
4
+ public struct Switch: View {
5
+ @Binding var value: Bool
6
+ var disabled: Bool
7
+ var onChange: ((Bool) -> Void)?
8
+ var title: String?
9
+ var accessibilityId: String?
10
+
11
+ public init(
12
+ _ value: Binding<Bool>,
13
+ disabled: Bool = false,
14
+ onChange: ((Bool) -> Void)? = nil,
15
+ title: String? = "",
16
+ accessibilityId: String? = ""
17
+ ) {
18
+ self._value = value
19
+ self.disabled = disabled
20
+ self.onChange = onChange
21
+ self.title = title
22
+ self.accessibilityId = accessibilityId
23
+ }
24
+
25
+ // Mirrors Kotlin's `backgroundColor`: shared by the track AND the inner dot.
26
+ private var backgroundColor: Color {
27
+ switch (disabled, value) {
28
+ case (true, true): return Colors.green09
29
+ case (true, false): return Colors.black05
30
+ case (false, true): return Colors.green03
31
+ case (false, false): return Colors.black07
32
+ }
33
+ }
34
+
35
+ // Mirrors Kotlin's `circleBackgroundColor` (the outer 14pt thumb circle).
36
+ private var circleColor: Color {
37
+ value ? Colors.black01 : Colors.black03
38
+ }
39
+
40
+ private var automationId: String {
41
+ accessibilityId?.isEmpty == false ? accessibilityId! : "toggle_\(title?.isEmpty == false ? title! : "unknown")_\(value)"
42
+ }
43
+
44
+ public var body: some View {
45
+ SwiftUI.Button(action: {
46
+ withAnimation {
47
+ value.toggle()
48
+ onChange?(value)
49
+ }
50
+ }) {
51
+ HStack {
52
+ HStack {}
53
+ .frame(width: 6, height: 6)
54
+ .background(backgroundColor)
55
+ .clipShape(Circle())
56
+ }
57
+ .frame(width: 14, height: 14)
58
+ .background(circleColor)
59
+ .clipShape(Circle())
60
+ .padding(.leading, Spacing.XS)
61
+ .padding(.trailing, Spacing.XS)
62
+ }
63
+ .disabled(disabled)
64
+ .frame(width: 38, height: 20, alignment: value ? .trailing : .leading)
65
+ .background(backgroundColor)
66
+ .clipShape(Capsule())
67
+ .accessibilityIdentifier(automationId)
68
+ }
69
+ }