@momo-kits/native-kits 0.167.1-duo.8-debug → 0.167.1-duo.9
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 +4 -1
- package/ios/Application/ApplicationEnvironment.swift +11 -0
- package/ios/Application/ComposeApi.swift +2 -1
- package/ios/Application/{Components.swift → LegacyHeader.swift} +6 -62
- package/ios/Application/Screen.swift +3 -2
- 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 +0 -1
- package/ios/Button/Button.swift +15 -12
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +12 -20
- 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 +9 -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 +18 -0
- package/ios/Icon/Icon.swift +7 -1
- package/ios/IconButton/IconButton.swift +15 -7
- package/ios/Image/Image.swift +7 -34
- package/ios/Information/Information.swift +27 -9
- package/ios/Input/ErrorView.swift +2 -2
- package/ios/Input/Input.swift +160 -147
- package/ios/Input/InputPhoneNumber.swift +12 -9
- package/ios/Input/InputSearch.swift +102 -75
- package/ios/Input/InputTextArea.swift +128 -145
- package/ios/InputDropDown/InputDropDown.swift +10 -7
- package/ios/InputMoney/InputMoney.swift +33 -11
- package/ios/InputOTP/InputOTP.swift +22 -12
- package/ios/Layout/Card.swift +50 -0
- package/ios/Layout/GridContext.swift +123 -3
- package/ios/Layout/Item.swift +5 -4
- package/ios/Layout/Section.swift +4 -100
- package/ios/Loader/Loader.swift +5 -9
- package/ios/Lottie/LottieView.swift +10 -0
- package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +61 -9
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTab.swift +60 -34
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +11 -6
- package/ios/{Application → Navigation/Component}/FloatingButton.swift +14 -3
- package/ios/Navigation/Component/Header.swift +493 -0
- package/ios/Navigation/Component/HeaderBackground.swift +134 -0
- package/ios/Navigation/Component/HeaderJourney.swift +73 -0
- package/ios/Navigation/Component/HeaderLocation.swift +48 -0
- package/ios/Navigation/Component/HeaderRight.swift +386 -0
- package/ios/Navigation/Component/HeaderTitle.swift +36 -0
- package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +20 -23
- package/ios/{Application/Navigation/component → Navigation/Component}/SideBar.swift +49 -28
- package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +5 -5
- package/ios/Navigation/HostBackGestureBridge.swift +57 -0
- package/ios/Navigation/Navigation.swift +190 -0
- package/ios/{Application/Navigation → Navigation}/NavigationContainer.swift +46 -41
- package/ios/{Application/Navigation → Navigation}/Navigator.swift +65 -9
- package/ios/{Application → Navigation}/StackScreen.swift +236 -103
- 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 +79 -159
- package/ios/Popup/PopupInput.swift +10 -13
- package/ios/Popup/PopupLayout.swift +97 -2
- package/ios/Popup/PopupNotify.swift +27 -55
- package/ios/Popup/PopupPromotion.swift +22 -50
- 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/ScrollIndicator/ScrollIndicator.swift +11 -10
- package/ios/Skeleton/Skeleton.swift +22 -27
- package/ios/Slider/Slider.swift +16 -18
- package/ios/Stepper/Stepper.swift +6 -1
- 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 +41 -27
- package/ios/Title/Title.swift +6 -17
- package/ios/Tooltip/Tooltip.swift +29 -14
- package/ios/Typography/Text.swift +61 -19
- package/ios/Uploader/Uploader.swift +3 -1
- package/ios/native-kits.podspec +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
- package/package.json +1 -1
- package/build.gradle.kts +0 -11
- package/compose/build.gradle.kts +0 -204
- package/compose/build.gradle.kts.backup +0 -204
- package/compose/compose.podspec +0 -47
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -153
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +0 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -831
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -82
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -356
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -113
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -475
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -266
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -240
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -264
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -361
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -310
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -323
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -199
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -552
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -88
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -498
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -234
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -188
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -297
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -137
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -205
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -708
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -203
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +0 -98
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +0 -312
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -408
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -92
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -105
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -366
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -37
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -185
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -74
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +0 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -40
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -217
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +0 -86
- package/gradle/libs.versions.toml +0 -69
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/gradle.properties +0 -26
- package/gradlew +0 -252
- package/gradlew.bat +0 -94
- package/ios/Application/HeaderRight.swift +0 -324
- package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
- package/ios/Application/Navigation/HeaderTitle.swift +0 -57
- package/ios/Application/Navigation/NavigationOptions.swift +0 -109
- package/ios/Application/Navigation/NavigatorManager.swift +0 -29
- package/ios/Application/Navigation/component/DuoScrollGradient.swift +0 -54
- package/ios/Application/Navigation/component/Header.swift +0 -183
- package/ios/Application/Navigation/component/HeaderBackground.swift +0 -84
- 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 -280
- package/ios-demo/README.md +0 -120
- package/settings.gradle.kts +0 -64
- /package/ios/{Application/Layout → Layout}/ScreenLayout.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoBarCompression.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoTabBar.swift +0 -0
- /package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HeaderLocation.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// SwiftUI mirror of Compose's `navigation/component/HeaderLocation.kt`: a description above a
|
|
6
|
+
// tappable location with a chevron.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
public struct HeaderLocationView: View {
|
|
12
|
+
private let data: HeaderLocationData
|
|
13
|
+
private let tintColor: Color
|
|
14
|
+
|
|
15
|
+
public init(_ data: HeaderLocationData, tintColor: Color) {
|
|
16
|
+
self.data = data
|
|
17
|
+
self.tintColor = tintColor
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Environment(\.screenLayout) private var layout
|
|
21
|
+
|
|
22
|
+
public var body: some View {
|
|
23
|
+
if data.isLoading {
|
|
24
|
+
VStack(alignment: .leading, spacing: Spacing.XXS) {
|
|
25
|
+
titleSkeleton(height: 12)
|
|
26
|
+
titleSkeleton(height: 18)
|
|
27
|
+
}
|
|
28
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
29
|
+
} else {
|
|
30
|
+
let tint = parseHeaderTint(data.tintColor) ?? tintColor
|
|
31
|
+
SwiftUI.Button(action: { data.onPress?() }) {
|
|
32
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
33
|
+
if let description = data.description, !description.isEmpty {
|
|
34
|
+
MomoText(description, typography: .descriptionXsRegular, color: tint, maxLines: 1)
|
|
35
|
+
}
|
|
36
|
+
HStack(spacing: 0) {
|
|
37
|
+
MomoText(data.location, typography: .actionXsBold, color: tint, maxLines: 1)
|
|
38
|
+
Spacer().frame(width: Spacing.XS)
|
|
39
|
+
Icon(source: "16_arrow_chevron_down_small", size: 16, color: tint)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
.frame(maxWidth: headerTitleMaxWidth(layout), alignment: .leading)
|
|
43
|
+
}
|
|
44
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
45
|
+
.disabled(data.onPress == nil)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HeaderRight.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// SwiftUI mirror of Compose's `navigation/component/HeaderRight.kt`: the mini-app toolkit
|
|
6
|
+
// (shortcut / more / single tool, help center and close) in the bar or the iPhone Duo side bar.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
/// Mirrors Compose's `HeaderRight.Toolkit`.
|
|
12
|
+
public struct HeaderRightData {
|
|
13
|
+
var useShortcut: Bool
|
|
14
|
+
var useMore: Bool
|
|
15
|
+
var tools: [ToolGroup]
|
|
16
|
+
var toolCallback: ((String) -> Void)?
|
|
17
|
+
var useSystemTools: Bool
|
|
18
|
+
/// Close dismisses only this mini app instead of returning home.
|
|
19
|
+
var useCloseIcon: Bool
|
|
20
|
+
|
|
21
|
+
public init(
|
|
22
|
+
useShortcut: Bool = false,
|
|
23
|
+
useMore: Bool = false,
|
|
24
|
+
tools: [ToolGroup] = [],
|
|
25
|
+
toolCallback: ((String) -> Void)? = nil,
|
|
26
|
+
useSystemTools: Bool = true,
|
|
27
|
+
useCloseIcon: Bool = false
|
|
28
|
+
) {
|
|
29
|
+
self.useShortcut = useShortcut
|
|
30
|
+
self.useMore = useMore
|
|
31
|
+
self.tools = tools
|
|
32
|
+
self.toolCallback = toolCallback
|
|
33
|
+
self.useSystemTools = useSystemTools
|
|
34
|
+
self.useCloseIcon = useCloseIcon
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var closeIcon: String { useCloseIcon ? "16_navigation_close_circle" : "16_basic_home" }
|
|
38
|
+
|
|
39
|
+
var showBadge: Bool { tools.contains { group in group.items.contains { $0.showBadge } } }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public struct Tool {
|
|
43
|
+
var key: String
|
|
44
|
+
var icon: String
|
|
45
|
+
var showBadge: Bool
|
|
46
|
+
var name: [String: String]
|
|
47
|
+
var showRightIcon: Bool
|
|
48
|
+
|
|
49
|
+
public init(
|
|
50
|
+
key: String,
|
|
51
|
+
icon: String,
|
|
52
|
+
name: [String: String] = [:],
|
|
53
|
+
showBadge: Bool = false,
|
|
54
|
+
showRightIcon: Bool = true
|
|
55
|
+
) {
|
|
56
|
+
self.key = key
|
|
57
|
+
self.icon = icon
|
|
58
|
+
self.showBadge = showBadge
|
|
59
|
+
self.name = name
|
|
60
|
+
self.showRightIcon = showRightIcon
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func toMap() -> [String: Any] {
|
|
64
|
+
[
|
|
65
|
+
"key": key,
|
|
66
|
+
"icon": icon,
|
|
67
|
+
"showBadge": showBadge,
|
|
68
|
+
"name": name,
|
|
69
|
+
"showRightIcon": showRightIcon
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public struct ToolGroup {
|
|
75
|
+
var title: [String: String]
|
|
76
|
+
var items: [Tool]
|
|
77
|
+
|
|
78
|
+
public init(title: [String: String] = [:], items: [Tool]) {
|
|
79
|
+
self.title = title
|
|
80
|
+
self.items = items
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func toMap() -> [String: Any] {
|
|
84
|
+
[
|
|
85
|
+
"title": title,
|
|
86
|
+
"items": items.map { $0.toMap() }
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private let helpCenterAppId = "vn.momo.helpcenter"
|
|
92
|
+
|
|
93
|
+
/// The Help Center mini app hides its own help button; without a context there is nothing to open.
|
|
94
|
+
private func usesHelpCenter(_ context: MiniAppContext?) -> Bool {
|
|
95
|
+
guard let context else { return false }
|
|
96
|
+
return context.appId != helpCenterAppId
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func showsShortcut(_ data: HeaderRightData, _ context: MiniAppContext?) -> Bool {
|
|
100
|
+
data.useShortcut && !(data.useMore && context == nil)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// Height of the vertical toolkit: the optional shortcut, then the help/home capsule.
|
|
104
|
+
func toolkitColumnHeight(_ data: HeaderRightData, context: MiniAppContext?) -> CGFloat {
|
|
105
|
+
let shortcut = showsShortcut(data, context) ? DuoMetrics.controlSize + Spacing.M : 0
|
|
106
|
+
return shortcut + (usesHelpCenter(context) ? 2 * DuoMetrics.itemPitch : DuoMetrics.controlSize)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// A header right that renders the kit toolkit, so the Duo side bar can take it over.
|
|
110
|
+
protocol ToolkitHeaderRightView {
|
|
111
|
+
var headerRight: HeaderRightData? { get }
|
|
112
|
+
var tintColor: Color? { get }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Toolkit data when `headerRight` renders the kit toolkit; nil for a custom header right.
|
|
116
|
+
func toolkitHeaderRight(_ headerRight: (() -> any View)?) -> (data: HeaderRightData?, tintColor: Color?)? {
|
|
117
|
+
guard let toolkit = headerRight?() as? ToolkitHeaderRightView else { return nil }
|
|
118
|
+
return (toolkit.headerRight, toolkit.tintColor)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// MARK: - Public views
|
|
122
|
+
|
|
123
|
+
/// The kit toolkit. Works under `NavigationContainer` (keyed environment) and under hosts that
|
|
124
|
+
/// inject `ApplicationEnvironment` with `.environmentObject`.
|
|
125
|
+
public struct HeaderRight: View, ToolkitHeaderRightView {
|
|
126
|
+
var headerRight: HeaderRightData?
|
|
127
|
+
var tintColor: Color?
|
|
128
|
+
|
|
129
|
+
public init(headerRight: HeaderRightData? = nil, tintColor: Color? = nil) {
|
|
130
|
+
self.headerRight = headerRight
|
|
131
|
+
self.tintColor = tintColor
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public var body: some View {
|
|
135
|
+
Toolkit(headerRight: headerRight ?? HeaderRightData(), tintColor: tintColor)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@available(*, deprecated, renamed: "HeaderRight", message: "HeaderRight now reads both environment styles.")
|
|
140
|
+
public struct NavigationHeaderRight: View, ToolkitHeaderRightView {
|
|
141
|
+
var headerRight: HeaderRightData?
|
|
142
|
+
var tintColor: Color?
|
|
143
|
+
|
|
144
|
+
public init(headerRight: HeaderRightData? = nil, tintColor: Color? = nil) {
|
|
145
|
+
self.headerRight = headerRight
|
|
146
|
+
self.tintColor = tintColor
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public var body: some View {
|
|
150
|
+
Toolkit(headerRight: headerRight ?? HeaderRightData(), tintColor: tintColor)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// MARK: - Toolkit
|
|
155
|
+
|
|
156
|
+
private struct NavigationButtonConfig {
|
|
157
|
+
let icon: String
|
|
158
|
+
let onPress: () -> Void
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
struct Toolkit: View {
|
|
162
|
+
let headerRight: HeaderRightData
|
|
163
|
+
var tintColor: Color?
|
|
164
|
+
/// iPhone Duo side bar column instead of the bar row.
|
|
165
|
+
var vertical: Bool = false
|
|
166
|
+
|
|
167
|
+
@State private var isFavorite = false
|
|
168
|
+
@State private var isLoading = false
|
|
169
|
+
@OptionalEnvironmentObject private var injectedEnvironment: ApplicationEnvironment?
|
|
170
|
+
@Environment(\.applicationEnvironment) private var keyedEnvironment
|
|
171
|
+
@Environment(\.headerColor) private var barColor
|
|
172
|
+
|
|
173
|
+
private var environment: ApplicationEnvironment { injectedEnvironment ?? keyedEnvironment }
|
|
174
|
+
private var context: MiniAppContext? { environment.applicationContext }
|
|
175
|
+
|
|
176
|
+
/// The bar's colors when inside a header, otherwise derived from the tint like a plain header.
|
|
177
|
+
private var headerColor: HeaderColor {
|
|
178
|
+
barColor ?? getHeaderColor(isAnimated: false, isSurface: true, opacity: 1, tintColor: tintColor)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private func apiValue(_ value: Any?) -> Any { value ?? NSNull() }
|
|
182
|
+
|
|
183
|
+
private var contextMap: [String: Any] {
|
|
184
|
+
[
|
|
185
|
+
"appId": apiValue(context?.appId),
|
|
186
|
+
"code": apiValue(context?.appCode),
|
|
187
|
+
"name": apiValue(context?.appName),
|
|
188
|
+
"icon": apiValue(context?.appIcon),
|
|
189
|
+
"description": apiValue(context?.description),
|
|
190
|
+
"support": apiValue(context?.support),
|
|
191
|
+
"toolkitConfig": apiValue(context?.toolkitConfig),
|
|
192
|
+
"providerId": apiValue(context?.providerId),
|
|
193
|
+
"permissions": apiValue(context?.permissions)
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private func parseResponse(_ response: String) -> Any? {
|
|
198
|
+
guard let data = response.data(using: .utf8),
|
|
199
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
200
|
+
return nil
|
|
201
|
+
}
|
|
202
|
+
return json["response"]
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// MARK: Actions
|
|
206
|
+
|
|
207
|
+
private func loadFavoriteState() {
|
|
208
|
+
_ = environment.composeApi?.request(
|
|
209
|
+
funcName: "isFavoriteApp",
|
|
210
|
+
params: ["code": apiValue(context?.appCode)]
|
|
211
|
+
) { response in
|
|
212
|
+
isFavorite = parseResponse(response) as? Bool == true
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private func onPressShortcut() {
|
|
217
|
+
_ = environment.composeApi?.request(
|
|
218
|
+
funcName: "onToolAction",
|
|
219
|
+
params: ["item": ["key": "onFavorite"], "context": contextMap]
|
|
220
|
+
) { response in
|
|
221
|
+
if let result = parseResponse(response) as? [String: Any], result["success"] as? Bool == true {
|
|
222
|
+
isFavorite.toggle()
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private func onPressMore() {
|
|
228
|
+
_ = environment.composeApi?.request(
|
|
229
|
+
funcName: "showTools",
|
|
230
|
+
params: [
|
|
231
|
+
"useSystemTools": headerRight.useSystemTools,
|
|
232
|
+
"tools": headerRight.tools.map { $0.toMap() },
|
|
233
|
+
"context": contextMap
|
|
234
|
+
]
|
|
235
|
+
) { response in
|
|
236
|
+
if let tool = parseResponse(response) as? String {
|
|
237
|
+
headerRight.toolCallback?(tool)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private func onPressHelpCenter() {
|
|
243
|
+
guard context != nil else { return }
|
|
244
|
+
_ = environment.composeApi?.request(
|
|
245
|
+
funcName: "showHelpCenter",
|
|
246
|
+
params: [
|
|
247
|
+
"appId": apiValue(context?.appId),
|
|
248
|
+
"code": apiValue(context?.appCode),
|
|
249
|
+
"name": apiValue(context?.appName),
|
|
250
|
+
"icon": apiValue(context?.appIcon),
|
|
251
|
+
"description": apiValue(context?.description)
|
|
252
|
+
]
|
|
253
|
+
) { _ in }
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private func onPressClose() {
|
|
257
|
+
if headerRight.useCloseIcon {
|
|
258
|
+
environment.requestDismiss()
|
|
259
|
+
} else {
|
|
260
|
+
_ = environment.composeApi?.request(funcName: "dismissAll", params: nil) { _ in }
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private var navigationButtonConfig: NavigationButtonConfig {
|
|
265
|
+
let totalTools = headerRight.tools.reduce(0) { $0 + $1.items.count }
|
|
266
|
+
if totalTools > 1 || headerRight.useMore {
|
|
267
|
+
return NavigationButtonConfig(icon: "navigation_more_icon", onPress: onPressMore)
|
|
268
|
+
}
|
|
269
|
+
if totalTools == 1, let tool = headerRight.tools.first?.items.first {
|
|
270
|
+
return NavigationButtonConfig(icon: tool.icon) { headerRight.toolCallback?(tool.key) }
|
|
271
|
+
}
|
|
272
|
+
return NavigationButtonConfig(icon: isFavorite ? "pin_star_checked" : "pin_star", onPress: onPressShortcut)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// MARK: Body
|
|
276
|
+
|
|
277
|
+
var body: some View {
|
|
278
|
+
Group {
|
|
279
|
+
if vertical {
|
|
280
|
+
verticalBody
|
|
281
|
+
} else {
|
|
282
|
+
horizontalBody
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
.onAppear(perform: loadFavoriteState)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private var verticalBody: some View {
|
|
289
|
+
let config = navigationButtonConfig
|
|
290
|
+
let useHelpCenter = usesHelpCenter(context)
|
|
291
|
+
return VStack(spacing: Spacing.M) {
|
|
292
|
+
if showsShortcut(headerRight, context) {
|
|
293
|
+
SideBarButton(
|
|
294
|
+
icon: config.icon,
|
|
295
|
+
headerColor: headerColor,
|
|
296
|
+
showBadge: headerRight.showBadge,
|
|
297
|
+
disabled: isLoading,
|
|
298
|
+
action: config.onPress
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
SideBarGroup(headerColor: headerColor, itemCount: useHelpCenter ? 2 : 1) {
|
|
302
|
+
if useHelpCenter {
|
|
303
|
+
SideBarGroupItem(
|
|
304
|
+
icon: "help_center",
|
|
305
|
+
headerColor: headerColor,
|
|
306
|
+
accessibilityId: "btn_navigation_help_center",
|
|
307
|
+
action: onPressHelpCenter
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
SideBarGroupItem(
|
|
311
|
+
icon: headerRight.closeIcon,
|
|
312
|
+
headerColor: headerColor,
|
|
313
|
+
accessibilityId: "btn_navigation_close",
|
|
314
|
+
action: onPressClose
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private var horizontalBody: some View {
|
|
321
|
+
let config = navigationButtonConfig
|
|
322
|
+
return HStack(alignment: .center, spacing: 0) {
|
|
323
|
+
if showsShortcut(headerRight, context) {
|
|
324
|
+
NavigationButton(
|
|
325
|
+
disabled: isLoading,
|
|
326
|
+
icon: config.icon,
|
|
327
|
+
showBadge: headerRight.showBadge,
|
|
328
|
+
headerColor: headerColor,
|
|
329
|
+
onClick: config.onPress
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
HStack(alignment: .center, spacing: 0) {
|
|
334
|
+
if usesHelpCenter(context) {
|
|
335
|
+
toolButton(icon: "help_center", accessibilityId: "btn_navigation_help_center", action: onPressHelpCenter)
|
|
336
|
+
Rectangle()
|
|
337
|
+
.fill(tintColor ?? Colors.black20)
|
|
338
|
+
.frame(width: 0.5, height: 12)
|
|
339
|
+
}
|
|
340
|
+
toolButton(icon: headerRight.closeIcon, accessibilityId: "btn_navigation_close", action: onPressClose)
|
|
341
|
+
}
|
|
342
|
+
.frame(width: 65, height: 28)
|
|
343
|
+
.background(headerColor.backgroundButton)
|
|
344
|
+
.cornerRadius(14)
|
|
345
|
+
.overlay(RoundedRectangle(cornerRadius: 14).stroke(headerColor.borderColor, lineWidth: 0.2))
|
|
346
|
+
.padding(.leading, Spacing.S)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private func toolButton(icon: String, accessibilityId: String, action: @escaping () -> Void) -> some View {
|
|
351
|
+
SwiftUI.Button(action: action) {
|
|
352
|
+
Icon(source: icon, size: 20, color: headerColor.tintIconColor)
|
|
353
|
+
.padding(4)
|
|
354
|
+
}
|
|
355
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
356
|
+
.accessibilityIdentifier(accessibilityId)
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/// Mirrors Compose's `NavigationButton`: the 28pt circular shortcut / more button.
|
|
361
|
+
struct NavigationButton: View {
|
|
362
|
+
var disabled: Bool
|
|
363
|
+
var icon: String
|
|
364
|
+
var showBadge: Bool
|
|
365
|
+
var headerColor: HeaderColor
|
|
366
|
+
var onClick: () -> Void
|
|
367
|
+
|
|
368
|
+
var body: some View {
|
|
369
|
+
SwiftUI.Button(action: onClick) {
|
|
370
|
+
ZStack {
|
|
371
|
+
Circle()
|
|
372
|
+
.fill(headerColor.backgroundButton)
|
|
373
|
+
.overlay(Circle().stroke(headerColor.borderColor, lineWidth: 0.2))
|
|
374
|
+
Icon(source: icon, size: 20, color: headerColor.tintIconColor)
|
|
375
|
+
}
|
|
376
|
+
.frame(width: 28, height: 28)
|
|
377
|
+
.overlay(alignment: .topTrailing) {
|
|
378
|
+
if showBadge {
|
|
379
|
+
BadgeDot(size: .small).offset(x: -Spacing.XXS, y: -Spacing.XXS)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
384
|
+
.disabled(disabled)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HeaderTitle.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// SwiftUI mirror of Compose's `navigation/component/HeaderTitle.kt`: the plain header title.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import SwiftUI
|
|
9
|
+
|
|
10
|
+
/// `actionSBold` at 15/22 in the header family, single line.
|
|
11
|
+
struct HeaderTitleText: View {
|
|
12
|
+
let title: String
|
|
13
|
+
let color: Color
|
|
14
|
+
var centered: Bool = false
|
|
15
|
+
|
|
16
|
+
init(_ title: String, color: Color, centered: Bool = false) {
|
|
17
|
+
self.title = title
|
|
18
|
+
self.color = color
|
|
19
|
+
self.centered = centered
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
var body: some View {
|
|
23
|
+
MomoText(
|
|
24
|
+
title,
|
|
25
|
+
typography: .actionSBold,
|
|
26
|
+
color: color,
|
|
27
|
+
textAlign: centered ? .center : .leading,
|
|
28
|
+
maxLines: 1,
|
|
29
|
+
truncationMode: .tail,
|
|
30
|
+
accessibilityId: "title_navigation_header",
|
|
31
|
+
fontFamily: headerFontFamily
|
|
32
|
+
)
|
|
33
|
+
.fontSize(15, lineHeight: 22)
|
|
34
|
+
.frame(maxWidth: centered ? .infinity : nil, alignment: centered ? .center : .leading)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// HeaderUser.swift
|
|
3
3
|
// MoMoUIKits
|
|
4
4
|
//
|
|
5
|
-
// SwiftUI mirror of Compose's `
|
|
5
|
+
// SwiftUI mirror of Compose's `navigation/component/HeaderUser.kt`.
|
|
6
6
|
// Renders a `HeaderTitle.User`: an avatar group (1..n avatars with overflow),
|
|
7
7
|
// a title with optional inline icons, and an optional subtitle. Shows a
|
|
8
8
|
// skeleton shimmer placeholder while `isLoading`.
|
|
@@ -21,11 +21,6 @@ public struct HeaderUserView: View {
|
|
|
21
21
|
|
|
22
22
|
@Environment(\.screenLayout) private var layout
|
|
23
23
|
|
|
24
|
-
// back button and toolkit share the bar unless the iPhone Duo side bar holds them
|
|
25
|
-
private var maxWidth: CGFloat {
|
|
26
|
-
layout.sideBar != nil ? layout.contentWidth - Spacing.M * 2 : layout.width - 172
|
|
27
|
-
}
|
|
28
|
-
|
|
29
24
|
public var body: some View {
|
|
30
25
|
if data.isLoading {
|
|
31
26
|
shimmer
|
|
@@ -35,6 +30,14 @@ public struct HeaderUserView: View {
|
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
private var content: some View {
|
|
33
|
+
SwiftUI.Button(action: { data.onPress?() }) {
|
|
34
|
+
row
|
|
35
|
+
}
|
|
36
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
37
|
+
.disabled(data.onPress == nil)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private var row: some View {
|
|
38
41
|
HStack(spacing: 0) {
|
|
39
42
|
HStack(spacing: 0) {
|
|
40
43
|
ZStack(alignment: .bottomTrailing) {
|
|
@@ -51,8 +54,7 @@ public struct HeaderUserView: View {
|
|
|
51
54
|
|
|
52
55
|
VStack(alignment: .leading, spacing: 0) {
|
|
53
56
|
HStack(spacing: 0) {
|
|
54
|
-
MomoText(data.title, typography: .actionXsBold, color: data.tintColor
|
|
55
|
-
.truncationMode(.tail)
|
|
57
|
+
MomoText(data.title, typography: .actionXsBold, color: data.tintColor, maxLines: 1, fontFamily: headerFontFamily)
|
|
56
58
|
|
|
57
59
|
if !data.icons.isEmpty {
|
|
58
60
|
Spacer().frame(width: 6)
|
|
@@ -68,34 +70,27 @@ public struct HeaderUserView: View {
|
|
|
68
70
|
|
|
69
71
|
if let subTitle = data.subTitle, !subTitle.isEmpty {
|
|
70
72
|
Spacer().frame(height: 2)
|
|
71
|
-
MomoText(subTitle, typography: .descriptionXsRegular, color: data.tintColor
|
|
72
|
-
.truncationMode(.tail)
|
|
73
|
+
MomoText(subTitle, typography: .descriptionXsRegular, color: data.tintColor, maxLines: 1)
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
|
-
.frame(maxWidth:
|
|
77
|
+
.frame(maxWidth: headerTitleMaxWidth(layout), alignment: .leading)
|
|
77
78
|
|
|
78
79
|
Spacer(minLength: 0)
|
|
79
80
|
}
|
|
80
81
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
81
82
|
.padding(.vertical, Spacing.XS)
|
|
82
83
|
.contentShape(Rectangle())
|
|
83
|
-
.onTapGesture { data.onPress?() }
|
|
84
|
-
.allowsHitTesting(data.onPress != nil)
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
private var shimmer: some View {
|
|
88
87
|
HStack(spacing: Spacing.M / 2) {
|
|
89
|
-
|
|
90
|
-
.fill(Colors.black05)
|
|
88
|
+
Skeleton()
|
|
91
89
|
.frame(width: avatarSize, height: avatarSize)
|
|
90
|
+
.clipShape(Circle())
|
|
92
91
|
VStack(alignment: .leading, spacing: Spacing.XXS) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
.frame(width: 120, height: 18)
|
|
96
|
-
RoundedRectangle(cornerRadius: 8)
|
|
97
|
-
.fill(Colors.black05)
|
|
98
|
-
.frame(width: 120, height: 12)
|
|
92
|
+
titleSkeleton(height: 18)
|
|
93
|
+
titleSkeleton(height: 12)
|
|
99
94
|
}
|
|
100
95
|
}
|
|
101
96
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
@@ -108,6 +103,7 @@ public struct HeaderUserView: View {
|
|
|
108
103
|
/// Mirrors Compose's `AvatarGroup`: lays out 1..4 avatars in a fixed collage,
|
|
109
104
|
/// falls back to initials when empty, and shows a "+n" overflow tile beyond 4.
|
|
110
105
|
private struct AvatarGroup: View {
|
|
106
|
+
@Environment(\.appTheme) private var theme
|
|
111
107
|
let urls: [String]
|
|
112
108
|
let title: String
|
|
113
109
|
let size: CGFloat
|
|
@@ -177,7 +173,7 @@ private struct AvatarGroup: View {
|
|
|
177
173
|
ImageView(url)
|
|
178
174
|
.aspectRatio(contentMode: .fill)
|
|
179
175
|
.clipShape(Circle())
|
|
180
|
-
.overlay(Circle().stroke(
|
|
176
|
+
.overlay(Circle().stroke(theme.colors.border.default, lineWidth: 0.5))
|
|
181
177
|
}
|
|
182
178
|
|
|
183
179
|
private func overflowTile(more: Int) -> some View {
|
|
@@ -189,6 +185,7 @@ private struct AvatarGroup: View {
|
|
|
189
185
|
}
|
|
190
186
|
|
|
191
187
|
private struct InitialsAvatar: View {
|
|
188
|
+
@Environment(\.appTheme) private var theme
|
|
192
189
|
let name: String
|
|
193
190
|
let size: CGFloat
|
|
194
191
|
|
|
@@ -204,6 +201,6 @@ private struct InitialsAvatar: View {
|
|
|
204
201
|
.frame(width: size, height: size)
|
|
205
202
|
.background(Colors.pink09)
|
|
206
203
|
.clipShape(Circle())
|
|
207
|
-
.overlay(Circle().stroke(
|
|
204
|
+
.overlay(Circle().stroke(theme.colors.border.default, lineWidth: 0.5))
|
|
208
205
|
}
|
|
209
206
|
}
|