@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.
- package/CLAUDE.md +99 -0
- package/PUBLISH_GUIDE.md +675 -0
- package/README.md +184 -5
- package/ios/Application/ApplicationEnvironment.swift +71 -0
- package/ios/Application/Components.swift +270 -0
- package/ios/Application/ComposeApi.swift +22 -0
- package/ios/Application/FloatingButton.swift +174 -0
- package/ios/Application/HeaderRight.swift +306 -0
- package/ios/Application/LanguageSource.swift +93 -0
- package/ios/Application/Localize.swift +378 -0
- package/ios/Application/LocalizeModifier.swift +30 -0
- package/ios/Application/MaxApi.swift +18 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
- package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
- package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
- package/ios/Application/Navigation/HeaderTitle.swift +57 -0
- package/ios/Application/Navigation/HeaderUser.swift +209 -0
- package/ios/Application/Navigation/NavigationContainer.swift +213 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +453 -0
- package/ios/Application/Navigation/NavigatorManager.swift +22 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
- package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
- package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
- package/ios/Application/Navigation/component/Header.swift +178 -0
- package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
- package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
- package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +11 -0
- package/ios/Application/Navigation/component/NavigationFooter.swift +90 -0
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +196 -0
- package/ios/Application/Screen.swift +250 -0
- package/ios/Application/StackScreen.swift +492 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +84 -0
- package/ios/Badge/BadgeDot.swift +31 -0
- package/ios/Badge/BadgeRibbon.swift +319 -0
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +232 -84
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +126 -0
- package/ios/Carousel/Carousel.swift +196 -0
- package/ios/Checkbox/Checkbox.swift +77 -0
- package/ios/Chip/Chip.swift +120 -0
- package/ios/Collapse/Collapse.swift +192 -0
- package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Colors.swift +42 -37
- package/ios/Colors+Radius+Spacing/Radius.swift +22 -0
- package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Spacing.swift +3 -1
- package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
- package/ios/DateTimePicker/DateTimePicker.swift +212 -0
- package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
- package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
- package/ios/DateTimePicker/WheelPicker.swift +165 -0
- package/ios/Divider/Divider.swift +16 -0
- package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +69 -0
- package/ios/IconButton/IconButton.swift +140 -0
- package/ios/Image/Image.swift +87 -0
- package/ios/Information/Information.swift +156 -0
- package/ios/Input/ErrorView.swift +58 -0
- package/ios/Input/Input.swift +461 -77
- package/ios/Input/InputPhoneNumber.swift +192 -0
- package/ios/Input/InputSearch.swift +301 -0
- package/ios/Input/InputTextArea.swift +318 -0
- package/ios/InputDropDown/InputDropDown.swift +201 -0
- package/ios/InputMoney/InputMoney.swift +405 -0
- package/ios/InputOTP/InputOTP.swift +211 -0
- package/ios/Layout/GridContext.swift +30 -0
- package/ios/Layout/Item.swift +42 -0
- package/ios/Layout/Section.swift +134 -0
- package/ios/Loader/Loader.swift +113 -0
- package/ios/Lottie/LottieView.swift +86 -0
- package/ios/MoMoUIKits.podspec +5 -0
- package/ios/OTPKeyboard/KeyboardButton.swift +13 -5
- package/ios/OTPKeyboard/OTPKeyboard.swift +1 -1
- package/ios/Pagination/PaginationDot.swift +61 -0
- package/ios/Pagination/PaginationNumber.swift +35 -0
- package/ios/Pagination/PaginationScroll.swift +101 -0
- package/ios/Pagination/PaginationWhiteDot.swift +37 -0
- package/ios/Popup/PopupDisplay.swift +279 -0
- package/ios/Popup/PopupInput.swift +92 -0
- package/ios/Popup/PopupNotify.swift +219 -0
- package/ios/Popup/PopupPromotion.swift +74 -0
- package/ios/PopupView/FullscreenPopup.swift +251 -0
- package/ios/{Popup → PopupView}/Modifiers.swift +6 -20
- package/ios/{Popup → PopupView}/PopupView.swift +38 -146
- package/ios/PopupView/Utils++.swift +281 -0
- package/ios/ProgressInfo/ProgressInfo.swift +297 -0
- package/ios/Radio/Radio.swift +69 -0
- package/ios/Rating/Rating.swift +83 -0
- package/{example/ios/Example/Preview Content/Preview Assets.xcassets/Contents.json → ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json} +5 -0
- package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Text.colorset/Contents.json +3 -3
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
- package/ios/ScrollIndicator/ScrollIndicator.swift +110 -0
- package/ios/Skeleton/Skeleton.swift +99 -0
- package/ios/Slider/Slider.swift +237 -0
- package/ios/StatusBarTap/StatusBarTap.h +13 -0
- package/ios/StatusBarTap/StatusBarTap.m +75 -0
- package/ios/Stepper/Stepper.swift +221 -0
- package/ios/Steps/Steps.swift +467 -0
- package/ios/SuggestAction/SuggestAction.swift +100 -0
- package/ios/Swipeable/SwipeCell.swift +226 -31
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/Switch/Switch.swift +69 -0
- package/ios/TabView/TabView.swift +534 -0
- package/ios/Tag/Tag.swift +99 -0
- package/ios/Template/Logo/Logo.swift +75 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +123 -0
- package/ios/Title/Title.swift +270 -0
- package/ios/Tooltip/Tooltip.swift +486 -0
- package/ios/Typography/FontScale.swift +103 -0
- package/ios/Typography/FontScaleStore.swift +58 -0
- package/ios/Typography/KitDesignSystem.swift +17 -0
- package/ios/Typography/Text.swift +262 -0
- package/ios/Typography/Typography.swift +80 -23
- package/ios/Uploader/Uploader.swift +174 -0
- package/ios/native-kits.podspec +73 -13
- package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
- package/ios-demo/Resources/dot_loading.json +558 -0
- package/ios-demo/Resources/icon.json +4052 -0
- package/ios-demo/Resources/lottie_circle_loader.json +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +75 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +108 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +96 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +60 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +102 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +420 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +56 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +276 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +81 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +65 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +96 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +117 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +88 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +120 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +85 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +73 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +235 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +241 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +68 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +95 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +67 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +101 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +64 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +68 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +83 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +61 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +90 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +82 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +114 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +90 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +58 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +114 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +86 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +181 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +104 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +118 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +85 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +53 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
- package/package.json +6 -6
- package/publish.sh +554 -20
- package/scripts/gen-ios-color.mjs +136 -0
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -114
- package/LICENSE +0 -20
- package/android/build.gradle +0 -82
- package/android/gradle.properties +0 -5
- package/android/src/main/AndroidManifest.xml +0 -4
- package/android/src/main/java/com/momoplatform/nativekits/NativeKitsPackage.kt +0 -17
- package/android/src/main/java/com/momoplatform/nativekits/NativeKitsViewManager.kt +0 -20
- package/example/ios/Example/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -63
- package/example/ios/Example/ComponentDetail.swift +0 -35
- package/example/ios/Example/ComponentItem.swift +0 -24
- package/example/ios/Example/ComponentModel.swift +0 -33
- package/example/ios/Example/ContentView.swift +0 -53
- package/example/ios/Example/Example.entitlements +0 -10
- package/example/ios/Example/Foundation/ButtonDemo.swift +0 -80
- package/example/ios/Example/Foundation/Popup/ActionSheets.swift +0 -136
- package/example/ios/Example/Foundation/Popup/Floats.swift +0 -127
- package/example/ios/Example/Foundation/Popup/Popups.swift +0 -101
- package/example/ios/Example/Foundation/PopupDemo.swift +0 -366
- package/example/ios/Example/Foundation/TextInputDemo.swift +0 -31
- package/example/ios/Example/Foundation/TypographyDemo.swift +0 -53
- package/example/ios/Example/Foundation.swift +0 -26
- package/example/ios/Example/Info.plist +0 -18
- package/example/ios/Example/Library/SwipeableDemo.swift +0 -105
- package/example/ios/Example/Library.swift +0 -26
- package/example/ios/Example/Main.swift +0 -11
- package/example/ios/Example/Overview.swift +0 -20
- package/example/ios/Example/Resource/SFProText-Black.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Bold.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Heavy.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Light.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Medium.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Regular.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Semibold.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Thin.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Ultralight.ttf +0 -0
- package/example/ios/Example/Resource/foundation.json +0 -33
- package/example/ios/Example/Resource/library.json +0 -8
- package/example/ios/Example/Utils.swift +0 -30
- package/example/ios/Example/ViewModifier/DarkViewModifier.swift +0 -22
- package/example/ios/Example.xcodeproj/project.pbxproj +0 -570
- package/example/ios/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/example/ios/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/example/ios/Example.xcodeproj/project.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/example/ios/Example.xcworkspace/contents.xcworkspacedata +0 -10
- package/example/ios/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
- package/example/ios/Podfile +0 -6
- package/example/ios/Podfile.lock +0 -16
- package/example/ios/Pods/Local Podspecs/MoMoUIKits.podspec.json +0 -29
- package/example/ios/Pods/Manifest.lock +0 -16
- package/example/ios/Pods/Pods.xcodeproj/project.pbxproj +0 -661
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -25
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-dummy.m +0 -5
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-prefix.pch +0 -12
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-umbrella.h +0 -16
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.debug.xcconfig +0 -12
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.modulemap +0 -6
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.release.xcconfig +0 -12
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.markdown +0 -3
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.plist +0 -29
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-dummy.m +0 -5
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-umbrella.h +0 -16
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig +0 -14
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.modulemap +0 -6
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig +0 -14
- package/ios/Colors+Spacing/Radius.swift +0 -11
- package/ios/Popup/Utils++.swift +0 -163
- package/ios/Theme.md +0 -18
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Background.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Border.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Card.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Error.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Primary.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/PrimaryDark.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/PrimaryLight.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Secondary.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/Success.colorset/Contents.json +0 -0
- /package/{example/ios/Example/Assets.xcassets → ios/Resources/MoMoUIKitsColors.xcassets}/TextSecondary.colorset/Contents.json +0 -0
- /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
|
+
}
|