@momo-kits/native-kits 0.163.1-beta.2-debug → 0.163.1-beta.20-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +112 -0
- package/CLAUDE.md +1 -1
- package/compose/build.gradle.kts +2 -1
- package/compose/build.gradle.kts.backup +1 -0
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +30 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +8 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +2 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +11 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +40 -55
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +5 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +3 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +19 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +28 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +25 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +68 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +7 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +112 -115
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +15 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +33 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +6 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +23 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +11 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +26 -3
- package/gradle/libs.versions.toml +2 -0
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +15 -3
- package/ios/Application/Components.swift +36 -30
- package/ios/Application/FloatingButton.swift +10 -9
- package/ios/Application/Localize.swift +309 -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 +203 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +385 -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/NavigationHeaderRight.swift +196 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +501 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +11 -14
- package/ios/Badge/BadgeRibbon.swift +91 -17
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +137 -28
- package/ios/Carousel/Carousel.swift +196 -0
- package/ios/Checkbox/Checkbox.swift +23 -28
- package/ios/Chip/Chip.swift +56 -33
- package/ios/Collapse/Collapse.swift +192 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
- package/ios/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 +10 -1
- package/ios/IconButton/IconButton.swift +140 -0
- package/ios/Image/Image.swift +16 -3
- package/ios/Information/Information.swift +3 -1
- package/ios/Input/ErrorView.swift +3 -1
- package/ios/Input/Input.swift +72 -33
- package/ios/Input/InputPhoneNumber.swift +33 -21
- package/ios/Input/InputSearch.swift +107 -48
- package/ios/Input/InputTextArea.swift +134 -64
- package/ios/InputDropDown/InputDropDown.swift +201 -0
- package/ios/InputMoney/InputMoney.swift +347 -0
- package/ios/InputOTP/InputOTP.swift +210 -0
- package/ios/Loader/Loader.swift +113 -0
- package/ios/MoMoUIKits.podspec +5 -0
- 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 +11 -20
- package/ios/Popup/PopupInput.swift +2 -8
- package/ios/Popup/PopupNotify.swift +218 -0
- package/ios/Popup/PopupPromotion.swift +5 -3
- package/ios/ProgressInfo/ProgressInfo.swift +296 -0
- package/ios/Radio/Radio.swift +69 -0
- package/ios/Rating/Rating.swift +82 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
- 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/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
- package/ios/Skeleton/Skeleton.swift +99 -0
- package/ios/Slider/Slider.swift +237 -0
- package/ios/Stepper/Stepper.swift +220 -0
- package/ios/Steps/Steps.swift +467 -0
- package/ios/SuggestAction/SuggestAction.swift +99 -0
- package/ios/Swipeable/SwipeCell.swift +187 -0
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/Switch/Switch.swift +53 -28
- package/ios/TabView/TabView.swift +534 -0
- package/ios/Tag/Tag.swift +98 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +7 -8
- package/ios/Title/Title.swift +269 -0
- package/ios/Tooltip/Tooltip.swift +485 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +86 -17
- package/ios/Typography/Typography.swift +12 -14
- package/ios/Uploader/Uploader.swift +174 -0
- package/ios/native-kits.podspec +61 -8
- package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
- package/ios-demo/README.md +120 -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 +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -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 +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +64 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
- package/local.properties +2 -2
- package/package.json +1 -1
- package/publish.sh +53 -0
- package/scripts/gen-ios-color.mjs +136 -0
- package/example/ios/Example.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -46
- package/ios/Application/FontScaleStore.swift +0 -59
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NavigationOptions.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// SwiftUI mirror of Compose's NavigationOptions.
|
|
6
|
+
// Each option lines up with a parameter on the existing `Screen` view,
|
|
7
|
+
// so NavigationContainer can auto-wrap a registered screen body in `Screen(options)`.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import SwiftUI
|
|
11
|
+
|
|
12
|
+
public struct NavigationOptions {
|
|
13
|
+
public var screenName: String?
|
|
14
|
+
public var title: String
|
|
15
|
+
/// Rich header title (mirrors Compose's `headerTitle`). When set to `.user`
|
|
16
|
+
/// the header renders an avatar group instead of `title`; `.default` keeps
|
|
17
|
+
/// the plain `title` text.
|
|
18
|
+
public var headerTitle: HeaderTitle?
|
|
19
|
+
public var titlePosition: TitlePosition
|
|
20
|
+
public var headerType: HeaderType
|
|
21
|
+
/// Mirrors Compose's `HeaderType.Extended/Default(useAnimated = ...)`: when true
|
|
22
|
+
/// and `inputSearchProps` is set, the search bar animates into the header on scroll.
|
|
23
|
+
public var useAnimated: Bool
|
|
24
|
+
public var headerTransparent: Bool
|
|
25
|
+
public var fullScreenContent: Bool
|
|
26
|
+
public var hiddenBack: Bool
|
|
27
|
+
public var backgroundColor: Color?
|
|
28
|
+
public var tintColor: Color?
|
|
29
|
+
public var scrollable: Bool
|
|
30
|
+
/// Mirrors Compose's `ScrollData.scrollToTopCallback`: invoked when the
|
|
31
|
+
/// screen is asked to scroll to top (e.g. on a status-bar tap).
|
|
32
|
+
public var scrollToTopCallback: (() -> Void)?
|
|
33
|
+
public var useAvoidKeyboard: Bool
|
|
34
|
+
/// Mirrors Compose's `KeyboardOptions.keyboardShouldPersistTaps`: when true,
|
|
35
|
+
/// tapping anywhere on the screen dismisses the keyboard.
|
|
36
|
+
public var keyboardShouldPersistTaps: Bool
|
|
37
|
+
/// Mirrors Compose's `HeaderBackProps`: drives the prevent-back confirm popup.
|
|
38
|
+
public var headerBackProps: HeaderBackProps?
|
|
39
|
+
/// Typed toolkit data for the default header right control (mirrors
|
|
40
|
+
/// Compose's `HeaderRight.Toolkit`). Use `headerRight` for `.custom` and nil
|
|
41
|
+
/// for `.none`.
|
|
42
|
+
public var headerRightData: HeaderRightData?
|
|
43
|
+
public var headerRight: (() -> any View)?
|
|
44
|
+
public var footer: (() -> AnyView)?
|
|
45
|
+
public var animatedHeader: AnimatedHeader?
|
|
46
|
+
public var layoutOffset: CGFloat
|
|
47
|
+
public var inputSearchProps: InputSearchProps?
|
|
48
|
+
public var fabProps: FabProps?
|
|
49
|
+
public var onBackHandler: (() -> Void)?
|
|
50
|
+
|
|
51
|
+
public init(
|
|
52
|
+
screenName: String? = nil,
|
|
53
|
+
title: String = "Stack",
|
|
54
|
+
headerTitle: HeaderTitle? = nil,
|
|
55
|
+
titlePosition: TitlePosition = .left,
|
|
56
|
+
headerType: HeaderType = .default,
|
|
57
|
+
useAnimated: Bool = false,
|
|
58
|
+
headerTransparent: Bool = false,
|
|
59
|
+
fullScreenContent: Bool = false,
|
|
60
|
+
hiddenBack: Bool = false,
|
|
61
|
+
backgroundColor: Color? = nil,
|
|
62
|
+
tintColor: Color? = Colors.black17,
|
|
63
|
+
scrollable: Bool = true,
|
|
64
|
+
scrollToTopCallback: (() -> Void)? = nil,
|
|
65
|
+
useAvoidKeyboard: Bool = true,
|
|
66
|
+
keyboardShouldPersistTaps: Bool = false,
|
|
67
|
+
headerBackProps: HeaderBackProps? = nil,
|
|
68
|
+
headerRightData: HeaderRightData? = nil,
|
|
69
|
+
headerRight: (() -> any View)? = { HeaderRight() },
|
|
70
|
+
footer: (() -> AnyView)? = nil,
|
|
71
|
+
animatedHeader: AnimatedHeader? = nil,
|
|
72
|
+
layoutOffset: CGFloat = 56,
|
|
73
|
+
inputSearchProps: InputSearchProps? = nil,
|
|
74
|
+
fabProps: FabProps? = nil,
|
|
75
|
+
onBackHandler: (() -> Void)? = nil
|
|
76
|
+
) {
|
|
77
|
+
self.screenName = screenName
|
|
78
|
+
self.title = title
|
|
79
|
+
self.headerTitle = headerTitle
|
|
80
|
+
self.titlePosition = titlePosition
|
|
81
|
+
self.headerType = headerType
|
|
82
|
+
self.useAnimated = useAnimated
|
|
83
|
+
self.headerTransparent = headerTransparent
|
|
84
|
+
self.fullScreenContent = fullScreenContent
|
|
85
|
+
self.hiddenBack = hiddenBack
|
|
86
|
+
self.backgroundColor = backgroundColor
|
|
87
|
+
self.tintColor = tintColor
|
|
88
|
+
self.scrollable = scrollable
|
|
89
|
+
self.scrollToTopCallback = scrollToTopCallback
|
|
90
|
+
self.useAvoidKeyboard = useAvoidKeyboard
|
|
91
|
+
self.keyboardShouldPersistTaps = keyboardShouldPersistTaps
|
|
92
|
+
self.headerBackProps = headerBackProps
|
|
93
|
+
self.headerRightData = headerRightData
|
|
94
|
+
self.headerRight = headerRight
|
|
95
|
+
self.footer = footer
|
|
96
|
+
self.animatedHeader = animatedHeader
|
|
97
|
+
self.layoutOffset = layoutOffset
|
|
98
|
+
self.inputSearchProps = inputSearchProps
|
|
99
|
+
self.fabProps = fabProps
|
|
100
|
+
self.onBackHandler = onBackHandler
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
extension NavigationOptions {
|
|
105
|
+
var resolvedHeaderRight: (() -> any View)? {
|
|
106
|
+
guard let headerRightData else { return headerRight }
|
|
107
|
+
return { HeaderRight(headerRight: headerRightData, tintColor: tintColor) }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Navigator.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// SwiftUI mirror of Compose's Navigator + DynamicScreenRegistry.
|
|
6
|
+
// Screens are registered by Int id; the NavigationStack path stores routes
|
|
7
|
+
// by id and looks up content from the registry on render.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import SwiftUI
|
|
11
|
+
import Combine
|
|
12
|
+
|
|
13
|
+
// MARK: - Routes
|
|
14
|
+
|
|
15
|
+
public struct DynamicScreenRoute: Hashable, Identifiable {
|
|
16
|
+
public let id: Int
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public struct DynamicDialogRoute: Hashable, Identifiable {
|
|
20
|
+
public let id: Int
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: - Registry
|
|
24
|
+
|
|
25
|
+
public struct DynamicScreen {
|
|
26
|
+
public let id: Int
|
|
27
|
+
public let name: String
|
|
28
|
+
public let content: () -> AnyView
|
|
29
|
+
public var options: NavigationOptions?
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public final class DynamicScreenRegistry {
|
|
33
|
+
private var screens: [Int: DynamicScreen] = [:]
|
|
34
|
+
private var idCounter: Int = 1
|
|
35
|
+
|
|
36
|
+
public init() {}
|
|
37
|
+
|
|
38
|
+
@discardableResult
|
|
39
|
+
public func register(
|
|
40
|
+
screenName: String = "",
|
|
41
|
+
content: @escaping () -> AnyView,
|
|
42
|
+
options: NavigationOptions? = nil
|
|
43
|
+
) -> DynamicScreenRoute {
|
|
44
|
+
let id = idCounter
|
|
45
|
+
idCounter += 1
|
|
46
|
+
screens[id] = DynamicScreen(id: id, name: screenName, content: content, options: options)
|
|
47
|
+
return DynamicScreenRoute(id: id)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public func unregister(id: Int) {
|
|
51
|
+
screens.removeValue(forKey: id)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func unregisterAll() {
|
|
55
|
+
screens.removeAll()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public func getScreen(id: Int) -> DynamicScreen? { screens[id] }
|
|
59
|
+
|
|
60
|
+
public func latest() -> DynamicScreen? {
|
|
61
|
+
screens.max(by: { $0.key < $1.key })?.value
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public func setOptions(id: Int, options: NavigationOptions) {
|
|
65
|
+
screens[id]?.options = options
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// MARK: - Overplay
|
|
70
|
+
|
|
71
|
+
public enum OverplayType {
|
|
72
|
+
case modal, bottomSheet, snackBar
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public struct OverplayItem: Identifiable {
|
|
76
|
+
public let id = UUID()
|
|
77
|
+
public let type: OverplayType
|
|
78
|
+
public let content: () -> AnyView
|
|
79
|
+
public let barrierDismissible: Bool
|
|
80
|
+
public let onDismiss: (() -> Void)?
|
|
81
|
+
// Bottom-sheet params (mirrors Compose's OverplayComponentParams.BottomSheet).
|
|
82
|
+
public var isSurface: Bool = false
|
|
83
|
+
public var header: BottomSheetHeader? = nil
|
|
84
|
+
// Snack-bar payload (mirrors Compose's SnackBar value).
|
|
85
|
+
public var snackBar: SnackBar? = nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// MARK: - Navigator
|
|
89
|
+
|
|
90
|
+
@available(iOS 16.0, *)
|
|
91
|
+
public final class Navigator: ObservableObject {
|
|
92
|
+
@Published public var path: [DynamicScreenRoute] = []
|
|
93
|
+
@Published public var presented: DynamicDialogRoute?
|
|
94
|
+
@Published public var overplay: OverplayItem?
|
|
95
|
+
|
|
96
|
+
/// Owned per-Navigator (mirrors Compose's `remember { DynamicScreenRegistry() }` +
|
|
97
|
+
/// disposal): screens registered by this navigator are released via ARC when the
|
|
98
|
+
/// navigator itself deallocates, instead of accumulating in a process-wide singleton.
|
|
99
|
+
public let registry = DynamicScreenRegistry()
|
|
100
|
+
|
|
101
|
+
/// Animated-close handler registered by the active overplay component
|
|
102
|
+
/// (mirrors Compose's `OverplayComponentRegistry.bindClose`). When set, a
|
|
103
|
+
/// dismiss request runs the component's exit animation before the item is
|
|
104
|
+
/// actually removed via `finishOverplayDismiss`.
|
|
105
|
+
private var overplayDismissHandler: (() -> Void)?
|
|
106
|
+
|
|
107
|
+
public private(set) var rootRoute: DynamicScreenRoute
|
|
108
|
+
public var composeApi: KitComposeApi?
|
|
109
|
+
|
|
110
|
+
public init(
|
|
111
|
+
initialScreenName: String = "",
|
|
112
|
+
initialContent: @escaping () -> AnyView,
|
|
113
|
+
options: NavigationOptions? = nil,
|
|
114
|
+
composeApi: KitComposeApi? = nil
|
|
115
|
+
) {
|
|
116
|
+
self.composeApi = composeApi
|
|
117
|
+
self.rootRoute = registry.register(
|
|
118
|
+
screenName: initialScreenName,
|
|
119
|
+
content: initialContent,
|
|
120
|
+
options: options
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// MARK: Stack
|
|
125
|
+
|
|
126
|
+
public func push<V: View>(@ViewBuilder _ content: @escaping () -> V, options: NavigationOptions? = nil) {
|
|
127
|
+
let route = registry.register(
|
|
128
|
+
screenName: options?.screenName ?? "",
|
|
129
|
+
content: { AnyView(content()) },
|
|
130
|
+
options: options
|
|
131
|
+
)
|
|
132
|
+
path.append(route)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public func push<V: View>(
|
|
136
|
+
screenName: String,
|
|
137
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
138
|
+
options: NavigationOptions? = nil
|
|
139
|
+
) {
|
|
140
|
+
let route = registry.register(
|
|
141
|
+
screenName: screenName,
|
|
142
|
+
content: { AnyView(content()) },
|
|
143
|
+
options: options
|
|
144
|
+
)
|
|
145
|
+
path.append(route)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public func replace<V: View>(@ViewBuilder _ content: @escaping () -> V, options: NavigationOptions? = nil) {
|
|
149
|
+
guard !path.isEmpty else { return }
|
|
150
|
+
let removed = path.removeLast()
|
|
151
|
+
registry.unregister(id: removed.id)
|
|
152
|
+
push(content, options: options)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public func replace<V: View>(
|
|
156
|
+
screenName: String,
|
|
157
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
158
|
+
options: NavigationOptions? = nil
|
|
159
|
+
) {
|
|
160
|
+
guard !path.isEmpty else { return }
|
|
161
|
+
let removed = path.removeLast()
|
|
162
|
+
registry.unregister(id: removed.id)
|
|
163
|
+
push(screenName: screenName, content, options: options)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public func reset<V: View>(@ViewBuilder _ content: @escaping () -> V, options: NavigationOptions? = nil) {
|
|
167
|
+
for route in path { registry.unregister(id: route.id) }
|
|
168
|
+
registry.unregister(id: rootRoute.id)
|
|
169
|
+
path.removeAll()
|
|
170
|
+
let route = registry.register(
|
|
171
|
+
screenName: options?.screenName ?? "",
|
|
172
|
+
content: { AnyView(content()) },
|
|
173
|
+
options: options
|
|
174
|
+
)
|
|
175
|
+
rootRoute = route
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public func reset<V: View>(
|
|
179
|
+
screenName: String,
|
|
180
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
181
|
+
options: NavigationOptions? = nil
|
|
182
|
+
) {
|
|
183
|
+
for route in path { registry.unregister(id: route.id) }
|
|
184
|
+
registry.unregister(id: rootRoute.id)
|
|
185
|
+
path.removeAll()
|
|
186
|
+
let route = registry.register(
|
|
187
|
+
screenName: screenName,
|
|
188
|
+
content: { AnyView(content()) },
|
|
189
|
+
options: options
|
|
190
|
+
)
|
|
191
|
+
rootRoute = route
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public func pop(_ count: Int = 1, callback: (() -> Void)? = nil) {
|
|
195
|
+
var remaining = count
|
|
196
|
+
while remaining > 0 {
|
|
197
|
+
if overplay?.type == .snackBar {
|
|
198
|
+
// Mirrors Kotlin: a snackbar doesn't block back-navigation, so popping
|
|
199
|
+
// while one is showing pops the screen underneath and clears the
|
|
200
|
+
// snackbar immediately, without playing its dismiss animation.
|
|
201
|
+
overplayDismissHandler = nil
|
|
202
|
+
overplay = nil
|
|
203
|
+
if !popScreen() { break }
|
|
204
|
+
} else if overplay != nil {
|
|
205
|
+
hideOverplay()
|
|
206
|
+
} else if !popScreen() {
|
|
207
|
+
break
|
|
208
|
+
}
|
|
209
|
+
remaining -= 1
|
|
210
|
+
}
|
|
211
|
+
callback?()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/// Pops the topmost presented screen or stack entry. Returns `false` (and requests
|
|
215
|
+
/// a host dismiss) when there is nothing left to pop.
|
|
216
|
+
@discardableResult
|
|
217
|
+
private func popScreen() -> Bool {
|
|
218
|
+
if presented != nil {
|
|
219
|
+
let dismissedId = presented?.id
|
|
220
|
+
presented = nil
|
|
221
|
+
if let id = dismissedId { registry.unregister(id: id) }
|
|
222
|
+
return true
|
|
223
|
+
} else if !path.isEmpty {
|
|
224
|
+
let removed = path.removeLast()
|
|
225
|
+
registry.unregister(id: removed.id)
|
|
226
|
+
return true
|
|
227
|
+
} else {
|
|
228
|
+
composeApi?.requestCallback(funcName: "dismiss", params: nil, onResponse: nil)
|
|
229
|
+
return false
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public func popToRoot() {
|
|
234
|
+
for route in path { registry.unregister(id: route.id) }
|
|
235
|
+
path.removeAll()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public func onBackSafe(callback: (() -> Void)? = nil) {
|
|
239
|
+
let latest = registry.latest()
|
|
240
|
+
if let onBack = latest?.options?.onBackHandler {
|
|
241
|
+
onBack()
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
if let preventBack = latest?.options?.headerBackProps?.preventBack {
|
|
245
|
+
showModal {
|
|
246
|
+
PopupDisplay(
|
|
247
|
+
isPresented: .constant(true),
|
|
248
|
+
title: preventBack.title,
|
|
249
|
+
description: preventBack.description,
|
|
250
|
+
url: preventBack.image,
|
|
251
|
+
buttonDirection: preventBack.buttonDirection,
|
|
252
|
+
buttonType: .button,
|
|
253
|
+
actionButtonTitle: preventBack.primary?.title ?? "",
|
|
254
|
+
closeButtonTitle: preventBack.secondary?.title ?? "",
|
|
255
|
+
onPressAction: { [weak self] in
|
|
256
|
+
preventBack.primary?.onPress?()
|
|
257
|
+
// Close the popup, then leave the screen (matches Compose's pop(2)).
|
|
258
|
+
self?.pop(2, callback: callback)
|
|
259
|
+
},
|
|
260
|
+
onPressCloseButton: { [weak self] in
|
|
261
|
+
preventBack.secondary?.onPress?()
|
|
262
|
+
self?.hideOverplay()
|
|
263
|
+
},
|
|
264
|
+
onClose: { [weak self] in
|
|
265
|
+
preventBack.onIconClose?()
|
|
266
|
+
self?.hideOverplay()
|
|
267
|
+
},
|
|
268
|
+
errorCode: preventBack.error,
|
|
269
|
+
isShowCloseIcon: preventBack.isShowCloseIcon
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
pop(1, callback: callback)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// MARK: Modal-style screen (vertical slide)
|
|
278
|
+
|
|
279
|
+
public func present<V: View>(@ViewBuilder _ content: @escaping () -> V, options: NavigationOptions? = nil) {
|
|
280
|
+
let route = registry.register(
|
|
281
|
+
screenName: options?.screenName ?? "",
|
|
282
|
+
content: { AnyView(content()) },
|
|
283
|
+
options: options
|
|
284
|
+
)
|
|
285
|
+
presented = DynamicDialogRoute(id: route.id)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public func present<V: View>(
|
|
289
|
+
screenName: String,
|
|
290
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
291
|
+
options: NavigationOptions? = nil
|
|
292
|
+
) {
|
|
293
|
+
let route = registry.register(
|
|
294
|
+
screenName: screenName,
|
|
295
|
+
content: { AnyView(content()) },
|
|
296
|
+
options: options
|
|
297
|
+
)
|
|
298
|
+
presented = DynamicDialogRoute(id: route.id)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public func dismiss() {
|
|
302
|
+
if let id = presented?.id {
|
|
303
|
+
registry.unregister(id: id)
|
|
304
|
+
}
|
|
305
|
+
presented = nil
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// MARK: Overplay
|
|
309
|
+
|
|
310
|
+
public func showModal<V: View>(
|
|
311
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
312
|
+
barrierDismissible: Bool = true,
|
|
313
|
+
onDismiss: (() -> Void)? = nil
|
|
314
|
+
) {
|
|
315
|
+
overplayDismissHandler = nil
|
|
316
|
+
overplay = OverplayItem(
|
|
317
|
+
type: .modal,
|
|
318
|
+
content: { AnyView(content()) },
|
|
319
|
+
barrierDismissible: barrierDismissible,
|
|
320
|
+
onDismiss: onDismiss
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
public func showBottomSheet<V: View>(
|
|
325
|
+
@ViewBuilder _ content: @escaping () -> V,
|
|
326
|
+
isSurface: Bool = false,
|
|
327
|
+
barrierDismissible: Bool = true,
|
|
328
|
+
header: BottomSheetHeader? = nil,
|
|
329
|
+
onDismiss: (() -> Void)? = nil
|
|
330
|
+
) {
|
|
331
|
+
overplayDismissHandler = nil
|
|
332
|
+
overplay = OverplayItem(
|
|
333
|
+
type: .bottomSheet,
|
|
334
|
+
content: { AnyView(content()) },
|
|
335
|
+
barrierDismissible: barrierDismissible,
|
|
336
|
+
onDismiss: onDismiss,
|
|
337
|
+
isSurface: isSurface,
|
|
338
|
+
header: header
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/// Mirrors Compose's `showSnackBar(snackBar:)`.
|
|
343
|
+
public func showSnackBar(_ snackBar: SnackBar, onDismiss: (() -> Void)? = nil) {
|
|
344
|
+
overplayDismissHandler = nil
|
|
345
|
+
overplay = OverplayItem(
|
|
346
|
+
type: .snackBar,
|
|
347
|
+
content: { AnyView(EmptyView()) },
|
|
348
|
+
barrierDismissible: false,
|
|
349
|
+
onDismiss: onDismiss,
|
|
350
|
+
snackBar: snackBar
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// MARK: Overplay dismissal
|
|
355
|
+
|
|
356
|
+
/// Registered by the active overplay component so external dismiss requests
|
|
357
|
+
/// run its exit animation (mirrors Compose's `bindClose`).
|
|
358
|
+
public func registerOverplayDismiss(_ handler: @escaping () -> Void) {
|
|
359
|
+
overplayDismissHandler = handler
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// Removes the overplay and fires its `onDismiss` (mirrors Compose's
|
|
363
|
+
/// `hardClearAfterDismiss`). Called by a component once its exit animation
|
|
364
|
+
/// has completed.
|
|
365
|
+
public func finishOverplayDismiss() {
|
|
366
|
+
let dismissCallback = overplay?.onDismiss
|
|
367
|
+
overplayDismissHandler = nil
|
|
368
|
+
overplay = nil
|
|
369
|
+
dismissCallback?()
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
public func hideOverplay() {
|
|
373
|
+
if let close = overplayDismissHandler {
|
|
374
|
+
// Component runs its exit animation, then calls finishOverplayDismiss.
|
|
375
|
+
overplayDismissHandler = nil
|
|
376
|
+
close()
|
|
377
|
+
} else {
|
|
378
|
+
finishOverplayDismiss()
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
public func hideSnackBar() {
|
|
383
|
+
if overplay?.type == .snackBar { hideOverplay() }
|
|
384
|
+
}
|
|
385
|
+
}
|