@momo-kits/native-kits 0.167.1-duo.18 → 0.167.1-duo.19-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 +5 -3
- package/build.gradle.kts +11 -0
- package/compose/build.gradle.kts +204 -0
- package/compose/build.gradle.kts.backup +204 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -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/AnimationSearchInput.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +916 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -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 +20 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -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 +283 -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 +309 -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 +205 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +393 -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 +727 -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 +35 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +218 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +231 -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 +98 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +312 -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 +447 -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 +379 -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/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/tracking/ScreenTracker.kt +127 -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 +13 -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/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +78 -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 +32 -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 +94 -0
- package/gradle/libs.versions.toml +69 -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/MaxApi.swift +12 -3
- package/ios/Colors+Radius+Spacing/Radius.swift +6 -0
- package/ios/Layout/GridContext.swift +67 -3
- package/ios/Navigation/BottomSheet.swift +30 -4
- package/ios/Navigation/BottomTab/BottomTab.swift +0 -2
- package/ios/Navigation/Component/SnackBar.swift +0 -1
- package/ios/Navigation/HostBackGestureBridge.swift +27 -6
- package/ios/Navigation/ModalScreen.swift +0 -1
- package/ios/Navigation/Navigation.swift +14 -0
- package/ios/Navigation/NavigationContainer.swift +26 -56
- package/ios/Navigation/Navigator.swift +102 -165
- package/ios/Navigation/StackScreen.swift +19 -2
- package/ios/Navigation/StackTransition.swift +400 -0
- package/ios/Navigation/SwipeBackHaptic.swift +33 -0
- package/ios-demo/README.md +120 -0
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
|
@@ -35,7 +35,6 @@ public struct BottomSheetHeader {
|
|
|
35
35
|
|
|
36
36
|
// MARK: - Bottom sheet view
|
|
37
37
|
|
|
38
|
-
@available(iOS 16.0, *)
|
|
39
38
|
struct BottomSheetView<Content: View>: View {
|
|
40
39
|
let header: BottomSheetHeader
|
|
41
40
|
let isSurface: Bool
|
|
@@ -294,12 +293,40 @@ struct BottomSheetView<Content: View>: View {
|
|
|
294
293
|
/// Compose's `heightIn(max:)`. `.frame(maxHeight:)` grows to the cap whenever the proposal is
|
|
295
294
|
/// larger, leaving a gap above the header; this sizes the sheet to its content and only caps it
|
|
296
295
|
/// when taller.
|
|
297
|
-
@available(iOS 16.0, *)
|
|
298
296
|
private struct CapHeight: ViewModifier {
|
|
299
297
|
let maxHeight: CGFloat
|
|
300
298
|
|
|
301
299
|
func body(content: Content) -> some View {
|
|
302
|
-
|
|
300
|
+
if #available(iOS 16.0, *) {
|
|
301
|
+
CapHeightLayout(maxHeight: maxHeight) { content }
|
|
302
|
+
} else {
|
|
303
|
+
content.modifier(CapHeightFallback(maxHeight: maxHeight))
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/// iOS 15 has no `Layout`: the sheet hugs its ideal height until that outgrows the cap, then is
|
|
309
|
+
/// held at the cap (the ideal height can't be read again without a second copy of the content).
|
|
310
|
+
private struct CapHeightFallback: ViewModifier {
|
|
311
|
+
let maxHeight: CGFloat
|
|
312
|
+
@State private var capped = false
|
|
313
|
+
|
|
314
|
+
func body(content: Content) -> some View {
|
|
315
|
+
content
|
|
316
|
+
// both modifiers stay in place whatever `capped` is, so the content keeps its identity
|
|
317
|
+
.fixedSize(horizontal: false, vertical: !capped)
|
|
318
|
+
.background(
|
|
319
|
+
GeometryReader { proxy in
|
|
320
|
+
Color.clear
|
|
321
|
+
.onAppear { cap(proxy.size.height) }
|
|
322
|
+
.onChange(of: proxy.size.height) { cap($0) }
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
.frame(height: capped ? maxHeight : nil, alignment: .top)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private func cap(_ height: CGFloat) {
|
|
329
|
+
if !capped, height > maxHeight { capped = true }
|
|
303
330
|
}
|
|
304
331
|
}
|
|
305
332
|
|
|
@@ -340,7 +367,6 @@ private struct BottomSheetFooter: View {
|
|
|
340
367
|
}
|
|
341
368
|
}
|
|
342
369
|
|
|
343
|
-
@available(iOS 16.0, *)
|
|
344
370
|
private func safeAreaBottomInset() -> CGFloat {
|
|
345
371
|
let bottomInset = UIApplication.shared.connectedScenes
|
|
346
372
|
.compactMap { ($0 as? UIWindowScene)?.keyWindow?.safeAreaInsets.bottom }
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
import SwiftUI
|
|
11
11
|
|
|
12
|
-
@available(iOS 16.0, *)
|
|
13
12
|
public struct BottomTab: View {
|
|
14
13
|
private let items: [BottomTabItem]
|
|
15
14
|
private let floatingButton: BottomTabFloatingButton?
|
|
@@ -178,7 +177,6 @@ private struct TabScreenHost: View {
|
|
|
178
177
|
}
|
|
179
178
|
|
|
180
179
|
/// Bottom safe-area inset (home indicator).
|
|
181
|
-
@available(iOS 16.0, *)
|
|
182
180
|
private func safeAreaBottomInset() -> CGFloat {
|
|
183
181
|
let bottomInset = UIApplication.shared.connectedScenes
|
|
184
182
|
.compactMap { ($0 as? UIWindowScene)?.keyWindow?.safeAreaInsets.bottom }
|
|
@@ -49,7 +49,6 @@ public struct SnackBar {
|
|
|
49
49
|
|
|
50
50
|
/// Self-animating container. Slides the content up on appear, schedules an
|
|
51
51
|
/// auto-dismiss after `duration`, and animates out before removing the overplay.
|
|
52
|
-
@available(iOS 16.0, *)
|
|
53
52
|
struct SnackBarView: View {
|
|
54
53
|
let snackBar: SnackBar
|
|
55
54
|
/// Distance from the window bottom to the top of the screen's footer, or the navigation bar
|
|
@@ -4,18 +4,19 @@
|
|
|
4
4
|
//
|
|
5
5
|
// SwiftUI mirror of Compose's `navigation/HostBackGestureBridge.kt`: the host owns the edge-pan
|
|
6
6
|
// recogniser and routes a back into the topmost kit stack. NavigationContainer attaches itself.
|
|
7
|
-
//
|
|
7
|
+
// `started` / `progressed` / `completed` / `cancelled` scrub the pop transition with the finger;
|
|
8
|
+
// a host that only calls `pop` gets the regular animated back.
|
|
8
9
|
//
|
|
9
10
|
|
|
10
|
-
import
|
|
11
|
+
import UIKit
|
|
11
12
|
|
|
12
|
-
@available(iOS 16.0, *)
|
|
13
13
|
public final class HostBackGestureBridge {
|
|
14
14
|
public static let shared = HostBackGestureBridge()
|
|
15
15
|
private init() {}
|
|
16
16
|
|
|
17
|
-
// Weak: a container torn down
|
|
17
|
+
// Weak: a container torn down without disappearing must not keep receiving backs.
|
|
18
18
|
private var navigators: [WeakNavigator] = []
|
|
19
|
+
private weak var gestureTarget: Navigator?
|
|
19
20
|
|
|
20
21
|
/// Set while a bottom tab other than the first is selected; the host shows its floating arrow.
|
|
21
22
|
public var shouldUseFloatingArrowBack = false
|
|
@@ -28,6 +29,7 @@ public final class HostBackGestureBridge {
|
|
|
28
29
|
|
|
29
30
|
public func detach(_ navigator: Navigator) {
|
|
30
31
|
navigators.removeAll { $0.value == nil || $0.value === navigator }
|
|
32
|
+
if gestureTarget === navigator { gestureTarget = nil }
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/// Whether a kit stack is on screen at all.
|
|
@@ -38,6 +40,27 @@ public final class HostBackGestureBridge {
|
|
|
38
40
|
|
|
39
41
|
public func pop() { top()?.onBackSafe() }
|
|
40
42
|
|
|
43
|
+
public func started() {
|
|
44
|
+
guard let target = top() else { return }
|
|
45
|
+
gestureTarget = target
|
|
46
|
+
target.backStarted()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// `progress` is the touch travel over the window width, 0...1.
|
|
50
|
+
public func progressed(_ progress: CGFloat) {
|
|
51
|
+
gestureTarget?.backProgressed(min(max(progress, 0), 1))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func completed() {
|
|
55
|
+
(gestureTarget ?? top())?.backCompleted()
|
|
56
|
+
gestureTarget = nil
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public func cancelled() {
|
|
60
|
+
gestureTarget?.backCancelled()
|
|
61
|
+
gestureTarget = nil
|
|
62
|
+
}
|
|
63
|
+
|
|
41
64
|
@available(*, deprecated, renamed: "attach")
|
|
42
65
|
public func push(_ navigator: Navigator) { attach(navigator) }
|
|
43
66
|
|
|
@@ -47,11 +70,9 @@ public final class HostBackGestureBridge {
|
|
|
47
70
|
private func top() -> Navigator? { navigators.last { $0.value != nil }?.value }
|
|
48
71
|
}
|
|
49
72
|
|
|
50
|
-
@available(iOS 16.0, *)
|
|
51
73
|
@available(*, deprecated, renamed: "HostBackGestureBridge")
|
|
52
74
|
public typealias NavigatorManager = HostBackGestureBridge
|
|
53
75
|
|
|
54
|
-
@available(iOS 16.0, *)
|
|
55
76
|
private struct WeakNavigator {
|
|
56
77
|
weak var value: Navigator?
|
|
57
78
|
}
|
|
@@ -66,6 +66,11 @@ public struct NavigationOptions {
|
|
|
66
66
|
public var fullScreenContent: Bool
|
|
67
67
|
public var hiddenBack: Bool
|
|
68
68
|
public var backgroundColor: Color?
|
|
69
|
+
// AI-GENERATED START: custom screen background view (Compose backgroundComponent)
|
|
70
|
+
/// Drawn instead of `backgroundColor` over the whole window: under the header and the status bar,
|
|
71
|
+
/// across the iPhone Duo side strips, and not shrunk by the keyboard. Pair with `headerTransparent`.
|
|
72
|
+
public var background: (() -> AnyView)?
|
|
73
|
+
// AI-GENERATED END: custom screen background view (Compose backgroundComponent)
|
|
69
74
|
public var tintColor: Color?
|
|
70
75
|
public var scrollable: Bool
|
|
71
76
|
/// Compose's `ScrollData.scrollToTopCallback`, fired on a status-bar tap.
|
|
@@ -98,6 +103,9 @@ public struct NavigationOptions {
|
|
|
98
103
|
fullScreenContent: Bool = false,
|
|
99
104
|
hiddenBack: Bool = false,
|
|
100
105
|
backgroundColor: Color? = nil,
|
|
106
|
+
// AI-GENERATED START: custom screen background view (Compose backgroundComponent)
|
|
107
|
+
background: (() -> AnyView)? = nil,
|
|
108
|
+
// AI-GENERATED END: custom screen background view (Compose backgroundComponent)
|
|
101
109
|
tintColor: Color? = Colors.black17,
|
|
102
110
|
scrollable: Bool = true,
|
|
103
111
|
scrollToTopCallback: (() -> Void)? = nil,
|
|
@@ -125,6 +133,9 @@ public struct NavigationOptions {
|
|
|
125
133
|
self.fullScreenContent = fullScreenContent
|
|
126
134
|
self.hiddenBack = hiddenBack
|
|
127
135
|
self.backgroundColor = backgroundColor
|
|
136
|
+
// AI-GENERATED START: custom screen background view (Compose backgroundComponent)
|
|
137
|
+
self.background = background
|
|
138
|
+
// AI-GENERATED END: custom screen background view (Compose backgroundComponent)
|
|
128
139
|
self.tintColor = tintColor
|
|
129
140
|
self.scrollable = scrollable
|
|
130
141
|
self.scrollToTopCallback = scrollToTopCallback
|
|
@@ -161,6 +172,9 @@ struct OptionsStackScreen: View {
|
|
|
161
172
|
var body: some View {
|
|
162
173
|
StackScreen(
|
|
163
174
|
backgroundColor: options.backgroundColor,
|
|
175
|
+
// AI-GENERATED START: custom screen background view (Compose backgroundComponent)
|
|
176
|
+
background: options.background,
|
|
177
|
+
// AI-GENERATED END: custom screen background view (Compose backgroundComponent)
|
|
164
178
|
headerTransparent: options.headerTransparent,
|
|
165
179
|
fullScreenContent: options.fullScreenContent,
|
|
166
180
|
tintColor: options.tintColor ?? Colors.black17,
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
// NavigationContainer.swift
|
|
3
3
|
// MoMoUIKits
|
|
4
4
|
//
|
|
5
|
-
// SwiftUI mirror of Compose's `navigation/NavigationContainer.kt`:
|
|
6
|
-
// (
|
|
7
|
-
// screen inside `StackScreen` chrome built from its options.
|
|
5
|
+
// SwiftUI mirror of Compose's `navigation/NavigationContainer.kt`: hosts the kit stack
|
|
6
|
+
// (`StackHost`, the NavHost counterpart), injects Navigator, theme, localize and font scale, and
|
|
7
|
+
// renders every registered screen inside `StackScreen` chrome built from its options.
|
|
8
8
|
//
|
|
9
9
|
|
|
10
10
|
import SwiftUI
|
|
11
11
|
|
|
12
|
-
@available(iOS 16.0, *)
|
|
13
12
|
public struct NavigationContainer<Initial: View>: View {
|
|
14
13
|
@StateObject private var navigator: Navigator
|
|
15
14
|
@StateObject private var applicationEnvironment: ApplicationEnvironment
|
|
@@ -71,24 +70,17 @@ public struct NavigationContainer<Initial: View>: View {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
public var body: some View {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
StackHost(
|
|
74
|
+
navigator: navigator,
|
|
75
|
+
entries: navigator.entries,
|
|
76
|
+
screen: { [navigator] entry in
|
|
77
|
+
guard let screen = navigator.registry.getScreen(id: entry.id) else { return AnyView(EmptyView()) }
|
|
78
|
+
return AnyView(ScreenHost(screen: screen, navigator: navigator))
|
|
79
|
+
},
|
|
80
|
+
decorate: { AnyView(withKitEnvironment($0)) }
|
|
77
81
|
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// A close that bypasses the navigator (e.g. `dismiss()`) still tears the flow down.
|
|
81
|
-
// SwiftUI also writes nil after a navigator-driven close; by then a new screen may
|
|
82
|
-
// already be queued, so only a cover that is still showing counts.
|
|
83
|
-
set: { if $0 == nil, navigator.coverRoute != nil { navigator.dismiss() } }
|
|
84
|
-
)) { route in
|
|
85
|
-
withKitEnvironment(
|
|
86
|
-
stack(path: $navigator.presentedPath, root: DynamicScreenRoute(id: route.id))
|
|
87
|
-
.overlay { overplayLayer(presentedId: route.id) }
|
|
88
|
-
)
|
|
89
|
-
.onAppear { navigator.coverDidAppear() }
|
|
90
|
-
.onDisappear { navigator.coverDidDisappear() }
|
|
91
|
-
}
|
|
82
|
+
// edge to edge: each screen's hosting controller takes the safe area and keyboard itself
|
|
83
|
+
.ignoresSafeArea()
|
|
92
84
|
.onAppear {
|
|
93
85
|
if navigator.composeApi == nil {
|
|
94
86
|
navigator.composeApi = composeApi
|
|
@@ -110,42 +102,10 @@ public struct NavigationContainer<Initial: View>: View {
|
|
|
110
102
|
// AI-GENERATED END: demote the MaxApi language pull to a seed of last resort
|
|
111
103
|
}
|
|
112
104
|
.onDisappear {
|
|
113
|
-
// Our own cover hides the stack without leaving it; host back must still reach it.
|
|
114
|
-
guard navigator.presented == nil else { return }
|
|
115
105
|
HostBackGestureBridge.shared.detach(navigator)
|
|
116
106
|
}
|
|
117
107
|
}
|
|
118
108
|
|
|
119
|
-
private func stack(path: Binding<[DynamicScreenRoute]>, root: DynamicScreenRoute) -> some View {
|
|
120
|
-
NavigationStack(path: path) {
|
|
121
|
-
screenView(for: root)
|
|
122
|
-
// A reset swaps the root in place; without the id it would inherit the old root's state.
|
|
123
|
-
.id(root.id)
|
|
124
|
-
.navigationDestination(for: DynamicScreenRoute.self) { route in
|
|
125
|
-
screenView(for: route)
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
@ViewBuilder
|
|
131
|
-
private func screenView(for route: DynamicScreenRoute) -> some View {
|
|
132
|
-
if let screen = navigator.registry.getScreen(id: route.id) {
|
|
133
|
-
ScreenHost(screen: screen, navigator: navigator)
|
|
134
|
-
.navigationBarBackButtonHidden(true)
|
|
135
|
-
} else {
|
|
136
|
-
EmptyView()
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/// Each context draws only the overplays shown over it, so one never re-mounts elsewhere.
|
|
141
|
-
@ViewBuilder
|
|
142
|
-
private func overplayLayer(presentedId: Int?) -> some View {
|
|
143
|
-
if let item = navigator.overplay, item.presentedId == presentedId {
|
|
144
|
-
OverplayHost(item: item)
|
|
145
|
-
.momoScreenLayout()
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
109
|
private func withKitEnvironment<Content: View>(_ content: Content) -> some View {
|
|
150
110
|
content
|
|
151
111
|
.environmentObject(navigator)
|
|
@@ -159,7 +119,6 @@ public struct NavigationContainer<Initial: View>: View {
|
|
|
159
119
|
|
|
160
120
|
// MARK: - ScreenHost
|
|
161
121
|
|
|
162
|
-
@available(iOS 16.0, *)
|
|
163
122
|
private struct ScreenHost: View {
|
|
164
123
|
let screen: DynamicScreen
|
|
165
124
|
let navigator: Navigator
|
|
@@ -180,15 +139,26 @@ private struct ScreenHost: View {
|
|
|
180
139
|
goBack: { navigator.onBackSafe() },
|
|
181
140
|
content: screen.content
|
|
182
141
|
)
|
|
142
|
+
// Compose draws the overplay inside the screen it was shown over, under its LocalNavigation.
|
|
143
|
+
.overlay { OverplayLayer(screenId: screen.id) }
|
|
183
144
|
.environmentObject(navigation)
|
|
184
|
-
// Per screen, not around the NavigationStack: a state-driven reader there stops path pushes rendering.
|
|
185
145
|
.momoScreenLayout()
|
|
186
146
|
}
|
|
187
147
|
}
|
|
188
148
|
|
|
149
|
+
private struct OverplayLayer: View {
|
|
150
|
+
let screenId: Int
|
|
151
|
+
@EnvironmentObject private var navigator: Navigator
|
|
152
|
+
|
|
153
|
+
var body: some View {
|
|
154
|
+
if let item = navigator.overplay, item.screenId == screenId {
|
|
155
|
+
OverplayHost(item: item)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
189
160
|
// MARK: - Overplay host
|
|
190
161
|
|
|
191
|
-
@available(iOS 16.0, *)
|
|
192
162
|
private struct OverplayHost: View {
|
|
193
163
|
let item: OverplayItem
|
|
194
164
|
@EnvironmentObject var navigator: Navigator
|