@momo-kits/native-kits 0.300.3 → 0.300.4-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.md +51 -7
- package/README.md +2 -2
- package/build.gradle.kts +13 -0
- package/compose/build.gradle.kts +197 -0
- package/compose/build.gradle.kts.backup +197 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +20 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
- 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 +153 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +1071 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +81 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +115 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +478 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +361 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +308 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +330 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +92 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +560 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +501 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +236 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +180 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +17 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +287 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +137 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +116 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +215 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +404 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +732 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +233 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +217 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +377 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +455 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +103 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +413 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +363 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +133 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +135 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +118 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +44 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +62 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +42 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +36 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -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 +217 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
- package/gradle/libs.versions.toml +68 -0
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/gradle.properties +26 -0
- package/gradlew +252 -0
- package/gradlew.bat +94 -0
- package/ios/Application/ApplicationEnvironment.swift +24 -6
- package/ios/Application/DesignSystemKits.swift +100 -0
- package/ios/Application/DesignSystemKitsPayload.swift +68 -0
- package/ios/Application/MaxApi.swift +30 -3
- package/ios/Avatar/Avatar.swift +4 -3
- package/ios/Badge/Badge.swift +6 -4
- package/ios/Badge/BadgeDot.swift +1 -1
- package/ios/Badge/BadgeRibbon.swift +8 -2
- package/ios/Button/Button.swift +15 -12
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +64 -18
- package/ios/Carousel/Carousel.swift +29 -12
- package/ios/Checkbox/Checkbox.swift +7 -3
- package/ios/Chip/Chip.swift +5 -4
- package/ios/Collapse/Collapse.swift +70 -19
- package/ios/Colors+Radius+Spacing/Colors.swift +10 -1
- package/ios/Colors+Radius+Spacing/Radius.swift +6 -0
- package/ios/DateTimePicker/DateTimePicker.swift +54 -20
- package/ios/DateTimePicker/WheelPicker.swift +103 -105
- package/ios/Divider/Divider.swift +37 -4
- package/ios/Extensions/Color++.swift +38 -9
- package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
- package/ios/Extensions/SkeletonUICompat.swift +11 -0
- package/ios/Icon/Icon.swift +21 -23
- package/ios/Icon/Icons.swift +1329 -0
- package/ios/IconButton/IconButton.swift +15 -7
- package/ios/Image/Image.swift +7 -23
- package/ios/Information/Information.swift +27 -9
- package/ios/Input/ErrorView.swift +2 -2
- package/ios/Input/Input.swift +171 -148
- package/ios/Input/InputPhoneNumber.swift +10 -9
- package/ios/Input/InputSearch.swift +107 -78
- package/ios/Input/InputTextArea.swift +133 -148
- package/ios/InputDropDown/InputDropDown.swift +10 -7
- package/ios/InputMoney/InputMoney.swift +32 -11
- package/ios/InputOTP/InputOTP.swift +22 -12
- package/ios/Layout/Card.swift +50 -0
- package/ios/Layout/GridContext.swift +187 -3
- package/ios/Layout/Item.swift +5 -4
- package/ios/Layout/ScreenLayout.swift +415 -0
- package/ios/Layout/Section.swift +4 -100
- package/ios/Loader/Loader.swift +5 -9
- package/ios/Lottie/LottieView.swift +14 -2
- package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +169 -29
- package/ios/Navigation/BottomTab/BottomTab.swift +332 -0
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +18 -7
- package/ios/Navigation/BottomTab/DuoBarCompression.swift +104 -0
- package/ios/Navigation/BottomTab/DuoTabBar.swift +329 -0
- package/ios/{Application → Navigation/Component}/FloatingButton.swift +43 -54
- package/ios/Navigation/Component/Header.swift +545 -0
- package/ios/Navigation/Component/HeaderBackground.swift +154 -0
- package/ios/Navigation/Component/HeaderJourney.swift +73 -0
- package/ios/Navigation/Component/HeaderLocation.swift +48 -0
- package/ios/Navigation/Component/HeaderRight.swift +425 -0
- package/ios/Navigation/Component/HeaderTitle.swift +36 -0
- package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +21 -24
- package/ios/Navigation/Component/SideBar.swift +183 -0
- package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +8 -8
- package/ios/Navigation/HostBackGestureBridge.swift +78 -0
- package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +9 -2
- package/ios/Navigation/Navigation.swift +204 -0
- package/ios/Navigation/NavigationContainer.swift +195 -0
- package/ios/{Application/Navigation → Navigation}/Navigator.swift +207 -107
- package/ios/Navigation/StackScreen.swift +930 -0
- package/ios/Navigation/StackTransition.swift +400 -0
- package/ios/Navigation/SwipeBackHaptic.swift +33 -0
- package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
- package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
- package/ios/Pagination/PaginationScroll.swift +2 -2
- package/ios/Popup/PopupDisplay.swift +72 -135
- package/ios/Popup/PopupInput.swift +10 -13
- package/ios/Popup/PopupLayout.swift +138 -0
- package/ios/Popup/PopupNotify.swift +59 -69
- package/ios/Popup/PopupPromotion.swift +31 -47
- package/ios/PopupView/FullscreenPopup.swift +13 -19
- package/ios/PopupView/PopupView.swift +1 -1
- package/ios/PopupView/Utils++.swift +0 -8
- package/ios/ProgressInfo/ProgressInfo.swift +4 -2
- package/ios/Radio/Radio.swift +2 -1
- package/ios/Rating/Rating.swift +9 -1
- package/ios/Resources/dot_loading.json +558 -0
- package/ios/Resources/lottie_circle_loader.json +1 -0
- package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
- package/ios/Skeleton/Skeleton.swift +22 -27
- package/ios/Slider/Slider.swift +16 -18
- package/ios/Stepper/Stepper.swift +7 -3
- package/ios/Steps/Steps.swift +8 -6
- package/ios/SuggestAction/SuggestAction.swift +5 -0
- package/ios/Swipeable/SwipeCell.swift +10 -6
- package/ios/Switch/Switch.swift +22 -20
- package/ios/TabView/TabView.swift +102 -21
- package/ios/Tag/Tag.swift +15 -4
- package/ios/Template/Logo/Logo.swift +2 -1
- package/ios/Template/TrustBanner/TrustBanner.swift +109 -55
- package/ios/Title/Title.swift +6 -17
- package/ios/Tooltip/Tooltip.swift +29 -14
- package/ios/Typography/FontScale.swift +17 -14
- package/ios/Typography/Text.swift +156 -20
- package/ios/Typography/Typography.swift +2 -2
- package/ios/Uploader/Uploader.swift +3 -1
- package/ios/native-kits.podspec +2 -3
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -3
- package/ios-demo/README.md +120 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +2 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +2 -2
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +2 -0
- package/package.json +1 -1
- package/publish.sh +19 -2
- package/scripts/gen-ios-icons.mjs +36 -0
- package/settings.gradle.kts +64 -0
- package/ios/Application/Components.swift +0 -270
- package/ios/Application/ComposeApi.swift +0 -22
- package/ios/Application/HeaderRight.swift +0 -306
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +0 -104
- package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
- package/ios/Application/Navigation/HeaderTitle.swift +0 -57
- package/ios/Application/Navigation/NavigationContainer.swift +0 -213
- package/ios/Application/Navigation/NavigationOptions.swift +0 -109
- package/ios/Application/Navigation/NavigatorManager.swift +0 -22
- package/ios/Application/Navigation/component/Header.swift +0 -178
- package/ios/Application/Navigation/component/HeaderBackground.swift +0 -83
- package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
- package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
- package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -196
- package/ios/Application/Screen.swift +0 -250
- package/ios/Application/StackScreen.swift +0 -492
- package/ios/Typography/FontScaleStore.swift +0 -58
- package/ios/Typography/KitDesignSystem.swift +0 -17
- /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// NavigationContainer.swift
|
|
3
|
-
// MoMoUIKits
|
|
4
|
-
//
|
|
5
|
-
// SwiftUI mirror of Compose's NavigationContainer.
|
|
6
|
-
// Wraps NavigationStack, injects Navigator into the environment, and renders
|
|
7
|
-
// every registered screen inside `Screen(options)` chrome — same auto-wrap
|
|
8
|
-
// behavior as Compose's StackScreen.
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
import SwiftUI
|
|
12
|
-
|
|
13
|
-
@available(iOS 16.0, *)
|
|
14
|
-
public struct NavigationContainer<Initial: View>: View {
|
|
15
|
-
@StateObject private var navigator: Navigator
|
|
16
|
-
@StateObject private var applicationEnvironment: ApplicationEnvironment
|
|
17
|
-
@StateObject private var localize: Localize
|
|
18
|
-
|
|
19
|
-
private let setNavigator: ((Navigator) -> Void)?
|
|
20
|
-
private let composeApi: KitComposeApi?
|
|
21
|
-
private let maxApi: MaxApi?
|
|
22
|
-
|
|
23
|
-
public init(
|
|
24
|
-
initialScreenName: String = "",
|
|
25
|
-
@ViewBuilder initialScreen: @escaping () -> Initial,
|
|
26
|
-
options: NavigationOptions? = nil,
|
|
27
|
-
applicationContext: MiniAppContext? = nil,
|
|
28
|
-
composeApi: KitComposeApi? = nil,
|
|
29
|
-
config: KitConfig? = nil,
|
|
30
|
-
maxApi: MaxApi? = nil,
|
|
31
|
-
localize: Localize? = nil,
|
|
32
|
-
setNavigator: ((Navigator) -> Void)? = nil
|
|
33
|
-
) {
|
|
34
|
-
let nav = Navigator(
|
|
35
|
-
initialScreenName: initialScreenName.isEmpty ? (options?.screenName ?? "") : initialScreenName,
|
|
36
|
-
initialContent: { AnyView(initialScreen()) },
|
|
37
|
-
options: options,
|
|
38
|
-
composeApi: composeApi
|
|
39
|
-
)
|
|
40
|
-
_navigator = StateObject(wrappedValue: nav)
|
|
41
|
-
_applicationEnvironment = StateObject(
|
|
42
|
-
wrappedValue: ApplicationEnvironment(
|
|
43
|
-
applicationContext: applicationContext,
|
|
44
|
-
composeApi: composeApi,
|
|
45
|
-
config: config,
|
|
46
|
-
maxApi: maxApi
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
// AI-GENERATED START: default to the app-language-observing shared Localize
|
|
50
|
-
_localize = StateObject(wrappedValue: localize ?? Localize.shared)
|
|
51
|
-
// AI-GENERATED END: default to the app-language-observing shared Localize
|
|
52
|
-
self.composeApi = composeApi
|
|
53
|
-
self.maxApi = maxApi
|
|
54
|
-
self.setNavigator = setNavigator
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
public var body: some View {
|
|
58
|
-
NavigationStack(path: $navigator.path) {
|
|
59
|
-
screenView(for: navigator.rootRoute)
|
|
60
|
-
.navigationDestination(for: DynamicScreenRoute.self) { route in
|
|
61
|
-
screenView(for: route)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
.environmentObject(navigator)
|
|
65
|
-
.environmentObject(applicationEnvironment)
|
|
66
|
-
.environment(\.applicationEnvironment, applicationEnvironment)
|
|
67
|
-
// AI-GENERATED START: route Localize + font-scale injection through the observing modifiers
|
|
68
|
-
.momoLocalize(localize)
|
|
69
|
-
.momoFontScale(context: applicationEnvironment.applicationContext)
|
|
70
|
-
// AI-GENERATED END: route Localize + font-scale injection through the observing modifiers
|
|
71
|
-
.fullScreenCover(item: $navigator.presented) { route in
|
|
72
|
-
screenView(forDialog: route)
|
|
73
|
-
.environmentObject(navigator)
|
|
74
|
-
.environmentObject(applicationEnvironment)
|
|
75
|
-
.environment(\.applicationEnvironment, applicationEnvironment)
|
|
76
|
-
// AI-GENERATED START: route Localize + font-scale injection through the observing modifiers
|
|
77
|
-
.momoLocalize(localize)
|
|
78
|
-
.momoFontScale(context: applicationEnvironment.applicationContext)
|
|
79
|
-
// AI-GENERATED END: route Localize + font-scale injection through the observing modifiers
|
|
80
|
-
}
|
|
81
|
-
.overlay {
|
|
82
|
-
if let item = navigator.overplay {
|
|
83
|
-
OverplayHost(item: item)
|
|
84
|
-
.environmentObject(navigator)
|
|
85
|
-
.environmentObject(applicationEnvironment)
|
|
86
|
-
.environment(\.applicationEnvironment, applicationEnvironment)
|
|
87
|
-
// AI-GENERATED START: route Localize + font-scale injection through the observing modifiers
|
|
88
|
-
.momoLocalize(localize)
|
|
89
|
-
.momoFontScale(context: applicationEnvironment.applicationContext)
|
|
90
|
-
// AI-GENERATED END: route Localize + font-scale injection through the observing modifiers
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
.onAppear {
|
|
94
|
-
if navigator.composeApi == nil {
|
|
95
|
-
navigator.composeApi = composeApi
|
|
96
|
-
}
|
|
97
|
-
setNavigator?(navigator)
|
|
98
|
-
// Register with the host swipe-back bridge (mirrors ComposeAppContainer's
|
|
99
|
-
// ComposeNavigatorManager.push). Idempotent, so a re-appear won't double-count.
|
|
100
|
-
NavigatorManager.shared.push(navigator)
|
|
101
|
-
// AI-GENERATED START: demote the MaxApi language pull to a seed of last resort
|
|
102
|
-
// Only a seed: a Localize with a language source already tracks the host in both
|
|
103
|
-
// directions, so asking maxApi would just race it. `changeLanguage` normalizes the
|
|
104
|
-
// raw response and hops to main itself.
|
|
105
|
-
guard !localize.observesAppLanguage else { return }
|
|
106
|
-
maxApi?.getLanguage { data in
|
|
107
|
-
localize.changeLanguage(data?["response"] as? String)
|
|
108
|
-
}
|
|
109
|
-
// AI-GENERATED END: demote the MaxApi language pull to a seed of last resort
|
|
110
|
-
}
|
|
111
|
-
.onDisappear {
|
|
112
|
-
NavigatorManager.shared.remove(navigator)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
@ViewBuilder
|
|
117
|
-
private func screenView(for route: DynamicScreenRoute) -> some View {
|
|
118
|
-
if let screen = navigator.registry.getScreen(id: route.id) {
|
|
119
|
-
ScreenHost(screen: screen, navigator: navigator)
|
|
120
|
-
.navigationBarBackButtonHidden(true)
|
|
121
|
-
} else {
|
|
122
|
-
EmptyView()
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
@ViewBuilder
|
|
127
|
-
private func screenView(forDialog route: DynamicDialogRoute) -> some View {
|
|
128
|
-
if let screen = navigator.registry.getScreen(id: route.id) {
|
|
129
|
-
ScreenHost(screen: screen, navigator: navigator)
|
|
130
|
-
} else {
|
|
131
|
-
EmptyView()
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// MARK: - ScreenHost
|
|
137
|
-
|
|
138
|
-
@available(iOS 16.0, *)
|
|
139
|
-
private struct ScreenHost: View {
|
|
140
|
-
let screen: DynamicScreen
|
|
141
|
-
let navigator: Navigator
|
|
142
|
-
|
|
143
|
-
var body: some View {
|
|
144
|
-
let options = screen.options ?? NavigationOptions()
|
|
145
|
-
StackScreen(
|
|
146
|
-
backgroundColor: options.backgroundColor,
|
|
147
|
-
headerTransparent: options.headerTransparent,
|
|
148
|
-
fullScreenContent: options.fullScreenContent,
|
|
149
|
-
tintColor: options.tintColor ?? Colors.black17,
|
|
150
|
-
isBack: !options.hiddenBack,
|
|
151
|
-
headerType: options.headerType,
|
|
152
|
-
useAnimated: options.useAnimated,
|
|
153
|
-
title: options.title,
|
|
154
|
-
headerTitle: options.headerTitle,
|
|
155
|
-
titlePosition: options.titlePosition,
|
|
156
|
-
goBack: options.hiddenBack ? nil : { navigator.onBackSafe() },
|
|
157
|
-
scrollable: options.scrollable,
|
|
158
|
-
scrollToTopCallback: options.scrollToTopCallback,
|
|
159
|
-
useAvoidKeyboard: options.useAvoidKeyboard,
|
|
160
|
-
keyboardShouldPersistTaps: options.keyboardShouldPersistTaps,
|
|
161
|
-
footer: options.footer,
|
|
162
|
-
headerRight: options.resolvedHeaderRight,
|
|
163
|
-
animatedHeader: options.animatedHeader,
|
|
164
|
-
layoutOffset: options.layoutOffset,
|
|
165
|
-
inputSearchProps: options.inputSearchProps,
|
|
166
|
-
fabProps: options.fabProps,
|
|
167
|
-
screenName: screen.name,
|
|
168
|
-
content: { screen.content() }
|
|
169
|
-
)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// MARK: - Overplay host
|
|
174
|
-
|
|
175
|
-
@available(iOS 16.0, *)
|
|
176
|
-
private struct OverplayHost: View {
|
|
177
|
-
let item: OverplayItem
|
|
178
|
-
@EnvironmentObject var navigator: Navigator
|
|
179
|
-
|
|
180
|
-
var body: some View {
|
|
181
|
-
// Each component self-animates on appear and drives its own exit through
|
|
182
|
-
// the Navigator before the item is removed (mirrors Compose's overplay).
|
|
183
|
-
switch item.type {
|
|
184
|
-
case .modal:
|
|
185
|
-
ModalScreen(barrierDismissible: item.barrierDismissible) {
|
|
186
|
-
item.content()
|
|
187
|
-
}
|
|
188
|
-
.id(item.id)
|
|
189
|
-
case .bottomSheet:
|
|
190
|
-
BottomSheetView(
|
|
191
|
-
header: item.header ?? .title(),
|
|
192
|
-
isSurface: item.isSurface,
|
|
193
|
-
barrierDismissible: item.barrierDismissible
|
|
194
|
-
) {
|
|
195
|
-
item.content()
|
|
196
|
-
}
|
|
197
|
-
.id(item.id)
|
|
198
|
-
case .snackBar:
|
|
199
|
-
if let snackBar = item.snackBar {
|
|
200
|
-
SnackBarView(snackBar: snackBar, bottomInset: safeAreaBottomInset() + Spacing.S)
|
|
201
|
-
.id(item.id)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/// Bottom safe-area inset (home indicator), used to lift the snack bar.
|
|
208
|
-
@available(iOS 16.0, *)
|
|
209
|
-
private func safeAreaBottomInset() -> CGFloat {
|
|
210
|
-
UIApplication.shared.connectedScenes
|
|
211
|
-
.compactMap { ($0 as? UIWindowScene)?.keyWindow?.safeAreaInsets.bottom }
|
|
212
|
-
.first ?? 0
|
|
213
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
@available(iOS 16.0, *)
|
|
4
|
-
public final class NavigatorManager {
|
|
5
|
-
public static let shared = NavigatorManager()
|
|
6
|
-
private init() {}
|
|
7
|
-
|
|
8
|
-
private var navigators: [Navigator] = []
|
|
9
|
-
|
|
10
|
-
public func push(_ navigator: Navigator) {
|
|
11
|
-
guard !navigators.contains(where: { $0 === navigator }) else { return }
|
|
12
|
-
navigators.append(navigator)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public func remove(_ navigator: Navigator) {
|
|
16
|
-
navigators.removeAll { $0 === navigator }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public func checkCanPop() -> Bool { !navigators.isEmpty }
|
|
20
|
-
|
|
21
|
-
public func pop() { navigators.last?.onBackSafe() }
|
|
22
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Header.swift
|
|
3
|
-
// MoMoUIKits
|
|
4
|
-
//
|
|
5
|
-
// SwiftUI mirror of Compose's `Header` (navigation/component/Header.kt).
|
|
6
|
-
// Renders the 52pt header bar: a circular back button (colors resolved via
|
|
7
|
-
// `getHeaderColor`), the title area (`HeaderContent` → plain title, user title
|
|
8
|
-
// or inline search), the header-right toolkit, and a scroll-triggered bottom
|
|
9
|
-
// shadow. The header band background itself is painted by `HeaderBackground`.
|
|
10
|
-
//
|
|
11
|
-
// Named `NavigationHeader` to coexist with the legacy `Header` in
|
|
12
|
-
// `Components.swift` (kept as-is, used as a package elsewhere; to be marked
|
|
13
|
-
// deprecated later). Used by the new `StackScreen` navigation path.
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
import SwiftUI
|
|
17
|
-
|
|
18
|
-
public struct NavigationHeader: View {
|
|
19
|
-
var headerType: HeaderType = .default
|
|
20
|
-
var titlePosition: TitlePosition
|
|
21
|
-
var title: String
|
|
22
|
-
/// Optional rich title (mirrors Compose's `HeaderTitle`); `.user` renders an
|
|
23
|
-
/// avatar group, `.default`/nil renders plain `title`.
|
|
24
|
-
var headerTitle: HeaderTitle?
|
|
25
|
-
var headerRight: (() -> any View)? = { NavigationHeaderRight() }
|
|
26
|
-
var goBack: (() -> Void)?
|
|
27
|
-
var opacity: CGFloat = 1
|
|
28
|
-
var animatedHeader: AnimatedHeader?
|
|
29
|
-
var scrollState: CGFloat = 0
|
|
30
|
-
var inputSearchProps: InputSearchProps?
|
|
31
|
-
var tintColor: Color?
|
|
32
|
-
/// Title opacity; used by the animated search header to fade the title out on scroll.
|
|
33
|
-
var titleOpacity: CGFloat = 1
|
|
34
|
-
|
|
35
|
-
public init(
|
|
36
|
-
headerType: HeaderType = .default,
|
|
37
|
-
titlePosition: TitlePosition,
|
|
38
|
-
title: String,
|
|
39
|
-
headerTitle: HeaderTitle? = nil,
|
|
40
|
-
headerRight: (() -> any View)? = { HeaderRight() },
|
|
41
|
-
goBack: (() -> Void)? = nil,
|
|
42
|
-
opacity: CGFloat = 1,
|
|
43
|
-
animatedHeader: AnimatedHeader? = nil,
|
|
44
|
-
scrollState: CGFloat = 0,
|
|
45
|
-
inputSearchProps: InputSearchProps? = nil,
|
|
46
|
-
tintColor: Color? = nil,
|
|
47
|
-
titleOpacity: CGFloat = 1
|
|
48
|
-
) {
|
|
49
|
-
self.headerType = headerType
|
|
50
|
-
self.titlePosition = titlePosition
|
|
51
|
-
self.title = title
|
|
52
|
-
self.headerTitle = headerTitle
|
|
53
|
-
self.headerRight = headerRight
|
|
54
|
-
self.goBack = goBack
|
|
55
|
-
self.opacity = opacity
|
|
56
|
-
self.animatedHeader = animatedHeader
|
|
57
|
-
self.scrollState = scrollState
|
|
58
|
-
self.inputSearchProps = inputSearchProps
|
|
59
|
-
self.tintColor = tintColor
|
|
60
|
-
self.titleOpacity = titleOpacity
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private var isAnimated: Bool { animatedHeader != nil }
|
|
64
|
-
private var isSurface: Bool { animatedHeader?.isSurface ?? true }
|
|
65
|
-
|
|
66
|
-
private var headerColor: HeaderColor {
|
|
67
|
-
getHeaderColor(isAnimated: isAnimated, isSurface: isSurface, opacity: opacity, tintColor: tintColor)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/// Centered title needs a full-width overlay to stay screen-centered, not
|
|
71
|
-
/// boxed between the back button and the header-right (mirrors Compose).
|
|
72
|
-
private var centerTitle: Bool {
|
|
73
|
-
guard inputSearchProps == nil else { return false }
|
|
74
|
-
let isDefault = headerTitle == nil || headerTitle?.defaultTitle != nil
|
|
75
|
-
return titlePosition == .center && isDefault
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
public var body: some View {
|
|
79
|
-
if headerType != .none {
|
|
80
|
-
ZStack {
|
|
81
|
-
HStack(spacing: 0) {
|
|
82
|
-
if let goBack {
|
|
83
|
-
BackButton(color: headerColor, onBack: goBack)
|
|
84
|
-
Spacer().frame(width: Spacing.S)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if centerTitle {
|
|
88
|
-
Spacer()
|
|
89
|
-
} else {
|
|
90
|
-
titleArea(centered: false)
|
|
91
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if let headerRight {
|
|
95
|
-
AnyView(headerRight())
|
|
96
|
-
.background(
|
|
97
|
-
GeometryReader { geo in
|
|
98
|
-
Color.clear.preference(key: HeaderRightWidthKey.self, value: geo.size.width)
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
.padding(.horizontal, Spacing.M)
|
|
104
|
-
|
|
105
|
-
if centerTitle {
|
|
106
|
-
titleArea(centered: true)
|
|
107
|
-
.padding(.horizontal, Spacing.M)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
.frame(height: HEADER_HEIGHT)
|
|
111
|
-
.overlay(alignment: .bottom) { VerticalShadow(opacity: opacity) }
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/// Mirrors Compose's `HeaderContent`: plain title, user title, or — when a
|
|
116
|
-
/// header search is active — the inline search field.
|
|
117
|
-
@ViewBuilder
|
|
118
|
-
private func titleArea(centered: Bool) -> some View {
|
|
119
|
-
if let inputSearchProps {
|
|
120
|
-
InputSearch(props: inputSearchProps)
|
|
121
|
-
} else if case let .user(userData)? = headerTitle {
|
|
122
|
-
if #available(iOS 16.0, *) {
|
|
123
|
-
HeaderUserView(userData)
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
MomoText(
|
|
127
|
-
headerTitle?.defaultTitle ?? title,
|
|
128
|
-
typography: .actionSBold,
|
|
129
|
-
color: headerColor.tintIconColor,
|
|
130
|
-
textAlign: centered ? .center : .leading,
|
|
131
|
-
maxLines: 1
|
|
132
|
-
)
|
|
133
|
-
.opacity(titleOpacity)
|
|
134
|
-
.truncationMode(.tail)
|
|
135
|
-
.frame(maxWidth: centered ? .infinity : nil, alignment: centered ? .center : .leading)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// MARK: - Back button
|
|
141
|
-
|
|
142
|
-
/// Mirrors Compose's `BackButton`: a 28pt circular control with the back arrow.
|
|
143
|
-
private struct BackButton: View {
|
|
144
|
-
let color: HeaderColor
|
|
145
|
-
let onBack: () -> Void
|
|
146
|
-
|
|
147
|
-
var body: some View {
|
|
148
|
-
SwiftUI.Button(action: onBack) {
|
|
149
|
-
Circle()
|
|
150
|
-
.fill(color.backgroundButton)
|
|
151
|
-
.overlay(Circle().stroke(color.borderColor, lineWidth: 0.2))
|
|
152
|
-
.frame(width: 28, height: 28)
|
|
153
|
-
.overlay(Icon(source: "arrow-back", size: 20, color: color.tintIconColor))
|
|
154
|
-
}
|
|
155
|
-
.buttonStyle(.plain)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// MARK: - Vertical shadow
|
|
160
|
-
|
|
161
|
-
/// Mirrors Compose's `VerticalShadow`: a 6pt drop shadow under the header that
|
|
162
|
-
/// only appears once the header is fully opaque (scrolled).
|
|
163
|
-
private struct VerticalShadow: View {
|
|
164
|
-
let opacity: CGFloat
|
|
165
|
-
|
|
166
|
-
var body: some View {
|
|
167
|
-
if opacity >= 1 {
|
|
168
|
-
LinearGradient(
|
|
169
|
-
gradient: Gradient(colors: [Color.black.opacity(0.05), .clear]),
|
|
170
|
-
startPoint: .top,
|
|
171
|
-
endPoint: .bottom
|
|
172
|
-
)
|
|
173
|
-
.frame(height: 6)
|
|
174
|
-
.frame(maxWidth: .infinity)
|
|
175
|
-
.offset(y: 6)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// HeaderBackground.swift
|
|
3
|
-
// MoMoUIKits
|
|
4
|
-
//
|
|
5
|
-
// SwiftUI mirror of Compose's `HeaderBackground` (navigation/component/HeaderBackground.kt).
|
|
6
|
-
// Paints the header band behind the `Header`: a flat surface for `.default`,
|
|
7
|
-
// the taller pink gradient for `.extended`, fading out as the screen scrolls.
|
|
8
|
-
// Stays transparent when the header is transparent or the content is full-screen.
|
|
9
|
-
//
|
|
10
|
-
// Named `NavigationHeaderBackground` to coexist with the legacy
|
|
11
|
-
// `HeaderBackground` in `Components.swift` (kept as-is, used as a package
|
|
12
|
-
// elsewhere; to be marked deprecated later). Used by the new `StackScreen`.
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
import SwiftUI
|
|
16
|
-
|
|
17
|
-
public struct NavigationHeaderBackground: View {
|
|
18
|
-
var headerType: HeaderType = .default
|
|
19
|
-
var scrollState: CGFloat
|
|
20
|
-
var headerTransparent: Bool = false
|
|
21
|
-
var fullScreenContent: Bool = false
|
|
22
|
-
|
|
23
|
-
public init(
|
|
24
|
-
headerType: HeaderType = .default,
|
|
25
|
-
scrollState: CGFloat = 0,
|
|
26
|
-
headerTransparent: Bool = false,
|
|
27
|
-
fullScreenContent: Bool = false
|
|
28
|
-
) {
|
|
29
|
-
self.headerType = headerType
|
|
30
|
-
self.scrollState = scrollState
|
|
31
|
-
self.headerTransparent = headerTransparent
|
|
32
|
-
self.fullScreenContent = fullScreenContent
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private func pinkGradient(topColor: Color, bottomColor: Color) -> LinearGradient {
|
|
36
|
-
LinearGradient(
|
|
37
|
-
gradient: Gradient(colors: [
|
|
38
|
-
topColor,
|
|
39
|
-
bottomColor
|
|
40
|
-
]),
|
|
41
|
-
startPoint: .top,
|
|
42
|
-
endPoint: .bottom
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
public var body: some View {
|
|
47
|
-
let statusBarHeight = safeAreaTopInset()
|
|
48
|
-
let opacity = max(0, 1 - scrollState / CGFloat(HEADER_HEIGHT))
|
|
49
|
-
let minHeight = fullScreenContent ? 0 : statusBarHeight + HEADER_HEIGHT
|
|
50
|
-
let maxHeight: CGFloat = 154
|
|
51
|
-
let backgroundColor = headerTransparent ? Color.clear : Colors.black01
|
|
52
|
-
let topColor = opacity == 0 ? backgroundColor : Color(hex: 0xFDCADE)
|
|
53
|
-
|
|
54
|
-
Group {
|
|
55
|
-
switch headerType {
|
|
56
|
-
case .default:
|
|
57
|
-
ZStack(alignment: .bottom) {
|
|
58
|
-
backgroundColor
|
|
59
|
-
.frame(height: minHeight)
|
|
60
|
-
if !headerTransparent {
|
|
61
|
-
pinkGradient(topColor: topColor, bottomColor: backgroundColor)
|
|
62
|
-
.frame(height: maxHeight)
|
|
63
|
-
.frame(height: minHeight, alignment: .top)
|
|
64
|
-
.clipped()
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
case .extended:
|
|
69
|
-
ZStack {
|
|
70
|
-
if !headerTransparent {
|
|
71
|
-
backgroundColor
|
|
72
|
-
.frame(height: maxHeight)
|
|
73
|
-
pinkGradient(topColor: topColor, bottomColor: backgroundColor)
|
|
74
|
-
.frame(height: maxHeight)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
case .none:
|
|
79
|
-
EmptyView()
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// HeaderColor.swift
|
|
3
|
-
// MoMoUIKits
|
|
4
|
-
//
|
|
5
|
-
// SwiftUI mirror of Compose's `HeaderColor` + `getHeaderColor`
|
|
6
|
-
// (navigation/component/Header.kt). Resolves the back-button / control colors
|
|
7
|
-
// for the header based on whether it sits over an animated (image) header and
|
|
8
|
-
// how far the screen has scrolled.
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
import SwiftUI
|
|
12
|
-
|
|
13
|
-
/// Header band height, mirrors Compose's `HEADER_HEIGHT`.
|
|
14
|
-
public let HEADER_HEIGHT: CGFloat = 52
|
|
15
|
-
|
|
16
|
-
/// Mirrors Compose's `enum InputSearchType`.
|
|
17
|
-
enum NavInputSearchType {
|
|
18
|
-
case none, header, animated
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/// Mirrors Compose's `HeaderColor`.
|
|
22
|
-
public struct HeaderColor {
|
|
23
|
-
public let tintIconColor: Color
|
|
24
|
-
public let backgroundButton: Color
|
|
25
|
-
public let borderColor: Color
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/// Mirrors Compose's `getHeaderColor`. On iOS the "animated" header is expressed
|
|
29
|
-
/// via a non-nil `animatedHeader`, so we pass `isAnimated`/`isSurface` instead of
|
|
30
|
-
/// the Compose `HeaderType.Animated` case.
|
|
31
|
-
func getHeaderColor(
|
|
32
|
-
isAnimated: Bool,
|
|
33
|
-
isSurface: Bool,
|
|
34
|
-
opacity: CGFloat,
|
|
35
|
-
tintColor: Color?,
|
|
36
|
-
defaultColor: Color = Colors.black17
|
|
37
|
-
) -> HeaderColor {
|
|
38
|
-
if isAnimated {
|
|
39
|
-
if opacity >= 1 || !isSurface {
|
|
40
|
-
return HeaderColor(
|
|
41
|
-
tintIconColor: Colors.black17,
|
|
42
|
-
backgroundButton: Colors.black01.opacity(0.6),
|
|
43
|
-
borderColor: Colors.black20.opacity(0.2)
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
return HeaderColor(
|
|
47
|
-
tintIconColor: Colors.black01,
|
|
48
|
-
backgroundButton: Colors.black20.opacity(0.6),
|
|
49
|
-
borderColor: .clear
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if tintColor == Colors.black01 {
|
|
54
|
-
return HeaderColor(
|
|
55
|
-
tintIconColor: Colors.black01,
|
|
56
|
-
backgroundButton: Colors.black20.opacity(0.6),
|
|
57
|
-
borderColor: Colors.black01.opacity(0.2)
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
return HeaderColor(
|
|
61
|
-
tintIconColor: tintColor ?? defaultColor,
|
|
62
|
-
backgroundButton: Colors.black01.opacity(0.6),
|
|
63
|
-
borderColor: Colors.black20.opacity(0.2)
|
|
64
|
-
)
|
|
65
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
/// Reports the measured width of the header-right area so the animated search
|
|
4
|
-
/// header can compute its trailing inset (mirrors Compose's headerRightWidthPx).
|
|
5
|
-
/// Written by the header views (`NavigationHeader`) and read by `StackScreen`.
|
|
6
|
-
public struct HeaderRightWidthKey: PreferenceKey {
|
|
7
|
-
public static var defaultValue: CGFloat = 0
|
|
8
|
-
public static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
|
9
|
-
value = max(value, nextValue())
|
|
10
|
-
}
|
|
11
|
-
}
|