@momo-kits/native-kits 0.300.3-debug → 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/compose/build.gradle.kts +10 -2
- package/compose/build.gradle.kts.backup +8 -0
- package/compose/compose.podspec +1 -3
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +4 -3
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -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 +0 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +351 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +20 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +9 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +11 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +4 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +10 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +55 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +12 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +7 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +13 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +13 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +3 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +14 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +19 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +5 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +7 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +20 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +43 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +10 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +6 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +197 -60
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +132 -83
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +54 -62
- 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/Header.kt +122 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +34 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +113 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -2
- 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 +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +13 -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 +15 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +3 -1
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +4 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
- package/gradle/libs.versions.toml +3 -14
- package/gradle/wrapper/gradle-wrapper.properties +0 -2
- package/gradle.properties +3 -5
- 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/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/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
- 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/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/useHeaderSearchAnimation.kt +0 -69
- 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/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
|
@@ -11,15 +11,15 @@ import SDWebImageSwiftUI
|
|
|
11
11
|
|
|
12
12
|
let jsonUrl = "https://static.momocdn.net/app/json/component-kits/design_system.json"
|
|
13
13
|
|
|
14
|
-
public struct TrustBannerData: Decodable {
|
|
15
|
-
let content: [String: String]
|
|
16
|
-
let subContent: [String: String]
|
|
17
|
-
let pciImage: String
|
|
18
|
-
let
|
|
19
|
-
let
|
|
20
|
-
let icons: [String]
|
|
21
|
-
let
|
|
22
|
-
|
|
14
|
+
public struct TrustBannerData: Decodable, Equatable {
|
|
15
|
+
public let content: [String: String]
|
|
16
|
+
public let subContent: [String: String]
|
|
17
|
+
public let pciImage: String?
|
|
18
|
+
public let momoImage: String?
|
|
19
|
+
public let sslImage: String?
|
|
20
|
+
public let icons: [String]?
|
|
21
|
+
public let urlConfig: String
|
|
22
|
+
|
|
23
23
|
enum CodingKeys: String, CodingKey {
|
|
24
24
|
case content
|
|
25
25
|
case subContent
|
|
@@ -29,6 +29,38 @@ public struct TrustBannerData: Decodable {
|
|
|
29
29
|
case momoImage
|
|
30
30
|
case urlConfig = "url_config"
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
public init(
|
|
34
|
+
content: [String: String] = ["vi": "", "en": ""],
|
|
35
|
+
subContent: [String: String] = ["vi": "", "en": ""],
|
|
36
|
+
pciImage: String? = nil,
|
|
37
|
+
momoImage: String? = nil,
|
|
38
|
+
sslImage: String? = nil,
|
|
39
|
+
icons: [String]? = nil,
|
|
40
|
+
urlConfig: String = ""
|
|
41
|
+
) {
|
|
42
|
+
self.content = content
|
|
43
|
+
self.subContent = subContent
|
|
44
|
+
self.pciImage = pciImage
|
|
45
|
+
self.momoImage = momoImage
|
|
46
|
+
self.sslImage = sslImage
|
|
47
|
+
self.icons = icons
|
|
48
|
+
self.urlConfig = urlConfig
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Missing keys fall back to the init defaults, like the Compose data class.
|
|
52
|
+
public init(from decoder: Decoder) throws {
|
|
53
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
54
|
+
self.init(
|
|
55
|
+
content: try container.decodeIfPresent([String: String].self, forKey: .content) ?? ["vi": "", "en": ""],
|
|
56
|
+
subContent: try container.decodeIfPresent([String: String].self, forKey: .subContent) ?? ["vi": "", "en": ""],
|
|
57
|
+
pciImage: try container.decodeIfPresent(String.self, forKey: .pciImage),
|
|
58
|
+
momoImage: try container.decodeIfPresent(String.self, forKey: .momoImage),
|
|
59
|
+
sslImage: try container.decodeIfPresent(String.self, forKey: .sslImage),
|
|
60
|
+
icons: try container.decodeIfPresent([String].self, forKey: .icons),
|
|
61
|
+
urlConfig: try container.decodeIfPresent(String.self, forKey: .urlConfig) ?? ""
|
|
62
|
+
)
|
|
63
|
+
}
|
|
32
64
|
}
|
|
33
65
|
|
|
34
66
|
let defaultBanner = TrustBannerData(
|
|
@@ -38,83 +70,105 @@ let defaultBanner = TrustBannerData(
|
|
|
38
70
|
"vi": "Tìm hiểu thêm",
|
|
39
71
|
"en": "Learn more"
|
|
40
72
|
],
|
|
41
|
-
pciImage: "https://static.momocdn.net/app/img/kits/trustBanner/
|
|
73
|
+
pciImage: "https://static.momocdn.net/app/img/kits/trustBanner/pci_dss.png",
|
|
74
|
+
momoImage: "https://static.momocdn.net/app/img/kits/trustBanner/ic_secu.png",
|
|
42
75
|
sslImage: "https://static.momocdn.net/app/img/kits/trustBanner/ssl.png",
|
|
43
|
-
urlConfig: "login_and_security",
|
|
44
76
|
icons: [
|
|
45
77
|
"https://static.momocdn.net/app/img/kits/trustBanner/ic_viettinbank.png",
|
|
46
78
|
"https://static.momocdn.net/app/img/kits/trustBanner/ic_agribank.png",
|
|
47
79
|
"https://static.momocdn.net/app/img/kits/trustBanner/ic_vietcombank.png",
|
|
48
80
|
"https://static.momocdn.net/app/img/kits/trustBanner/ic_bidv.png"
|
|
49
81
|
],
|
|
50
|
-
|
|
82
|
+
urlConfig: "login_and_security"
|
|
51
83
|
)
|
|
52
84
|
|
|
53
85
|
public struct TrustBanner: View {
|
|
54
86
|
@Environment(\.applicationEnvironment) var applicationEnvironment
|
|
55
87
|
@Environment(\.localize) private var localize
|
|
88
|
+
@Environment(\.designSystemKitsConfigs) private var designSystemKitsConfigs
|
|
56
89
|
|
|
57
90
|
var onPress: ((String)->Void)?
|
|
91
|
+
private let serviceName: String
|
|
92
|
+
private let screenName: String
|
|
93
|
+
private let trackEvent: ((String, [String: String]) -> Void)?
|
|
58
94
|
|
|
59
|
-
public init(
|
|
95
|
+
public init(
|
|
96
|
+
onPress: ((String)->Void)?,
|
|
97
|
+
serviceName: String = "",
|
|
98
|
+
screenName: String = "",
|
|
99
|
+
trackEvent: ((String, [String: String]) -> Void)? = nil
|
|
100
|
+
) {
|
|
60
101
|
self.onPress = onPress
|
|
102
|
+
self.serviceName = serviceName
|
|
103
|
+
self.screenName = screenName
|
|
104
|
+
self.trackEvent = trackEvent
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private var banner: TrustBannerData {
|
|
108
|
+
// Container config wins, else the host-pushed DesignSystemKits config (Compose parity).
|
|
109
|
+
(applicationEnvironment.config ?? designSystemKitsConfigs.designSystemConfig)?.trustBanner ?? defaultBanner
|
|
61
110
|
}
|
|
62
111
|
|
|
63
112
|
func onPressSecurity() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
113
|
+
trackEvent?("service_component_clicked", [
|
|
114
|
+
"service_name": serviceName,
|
|
115
|
+
"screen_name": screenName,
|
|
116
|
+
"component_name": "logo_trust",
|
|
117
|
+
"url_config": banner.urlConfig
|
|
118
|
+
])
|
|
119
|
+
onPress?(banner.urlConfig)
|
|
67
120
|
}
|
|
68
|
-
|
|
69
|
-
|
|
121
|
+
|
|
70
122
|
public var body: some View {
|
|
71
|
-
HStack(alignment: .
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
123
|
+
HStack(alignment: .top, spacing: 10) {
|
|
124
|
+
if let momoImage = banner.momoImage {
|
|
125
|
+
WebImage(url: URL(string: momoImage))
|
|
126
|
+
.resizable()
|
|
127
|
+
.scaledToFit()
|
|
128
|
+
.frame(width: 64, height: 64)
|
|
129
|
+
}
|
|
130
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
131
|
+
MomoText(
|
|
132
|
+
localize.translateData(banner.content),
|
|
133
|
+
typography: .descriptionDefaultRegular,
|
|
134
|
+
color: Color(hex: "484848"),
|
|
135
|
+
maxLines: 2
|
|
136
|
+
)
|
|
137
|
+
.padding(.bottom, 8)
|
|
138
|
+
HStack(alignment: .top, spacing: 0) {
|
|
86
139
|
HStack(spacing: 0) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
140
|
+
MomoText(
|
|
141
|
+
localize.translateData(banner.subContent),
|
|
142
|
+
typography: .actionXsBold,
|
|
143
|
+
color: Colors.pink03,
|
|
144
|
+
maxLines: 2
|
|
145
|
+
)
|
|
94
146
|
Icon(source: "arrow_chevron_right_small", color: Colors.pink03)
|
|
95
|
-
}.onTapGesture {
|
|
96
|
-
onPressSecurity()
|
|
97
147
|
}
|
|
98
|
-
|
|
99
|
-
Spacer()
|
|
100
|
-
HStack{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
148
|
+
|
|
149
|
+
Spacer(minLength: 0)
|
|
150
|
+
HStack(spacing: 0) {
|
|
151
|
+
if let pciImage = banner.pciImage {
|
|
152
|
+
WebImage(url: URL(string: pciImage))
|
|
153
|
+
.resizable()
|
|
154
|
+
.scaledToFit()
|
|
155
|
+
.frame(width: 27, height: 20)
|
|
156
|
+
.padding(.trailing, 4)
|
|
157
|
+
}
|
|
158
|
+
if let sslImage = banner.sslImage {
|
|
159
|
+
WebImage(url: URL(string: sslImage))
|
|
160
|
+
.resizable()
|
|
161
|
+
.scaledToFit()
|
|
162
|
+
.frame(width: 52, height: 20)
|
|
163
|
+
}
|
|
109
164
|
}
|
|
110
165
|
}
|
|
111
|
-
|
|
112
166
|
}
|
|
113
|
-
|
|
114
167
|
}
|
|
115
168
|
.padding(.all, 12)
|
|
116
169
|
.background(Color(hex: "F2F8FF"))
|
|
117
170
|
.cornerRadius(12)
|
|
171
|
+
.contentShape(Rectangle())
|
|
118
172
|
.onTapGesture {
|
|
119
173
|
onPressSecurity()
|
|
120
174
|
}
|
package/ios/Title/Title.swift
CHANGED
|
@@ -28,7 +28,6 @@ public enum TitleButtonSize {
|
|
|
28
28
|
|
|
29
29
|
public struct Title: View {
|
|
30
30
|
@Environment(\.appTheme) private var theme
|
|
31
|
-
@Environment(\.momoFontScale) private var fontScale
|
|
32
31
|
|
|
33
32
|
private let title: String
|
|
34
33
|
private let type: TitleType
|
|
@@ -116,15 +115,9 @@ public struct Title: View {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
private var titleFontWeight: Font.Weight {
|
|
120
|
-
switch type {
|
|
121
|
-
case .card: return .regular
|
|
122
|
-
case .section: return .bold
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
118
|
private var titleMaxLines: Int {
|
|
127
|
-
|
|
119
|
+
if textOnly { return Int.max }
|
|
120
|
+
return (showTrailingAction || badgeLabel != nil) ? 1 : 2
|
|
128
121
|
}
|
|
129
122
|
|
|
130
123
|
private var iconVerticalAlignment: VerticalAlignment {
|
|
@@ -151,14 +144,10 @@ public struct Title: View {
|
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
|
|
147
|
+
// Every Title variant is bold in the theme font; `headerDefaultBold` only supplies the weight.
|
|
154
148
|
private var titleText: some View {
|
|
155
|
-
|
|
156
|
-
.
|
|
157
|
-
.ignoreBoldTextSetting()
|
|
158
|
-
.foregroundColor(theme.colors.text.default)
|
|
159
|
-
.lineSpacing(fontScale(titleLineHeight) - fontScale(titleFontSize))
|
|
160
|
-
.lineLimit(titleMaxLines)
|
|
161
|
-
.truncationMode(.tail)
|
|
149
|
+
MomoText(title, typography: .headerDefaultBold, maxLines: titleMaxLines)
|
|
150
|
+
.fontSize(titleFontSize, lineHeight: titleLineHeight)
|
|
162
151
|
}
|
|
163
152
|
|
|
164
153
|
private var fullLayout: some View {
|
|
@@ -237,7 +226,7 @@ public struct Title: View {
|
|
|
237
226
|
}
|
|
238
227
|
}
|
|
239
228
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
240
|
-
.padding(
|
|
229
|
+
.padding(.top, type == .section ? Spacing.S : 0)
|
|
241
230
|
}
|
|
242
231
|
}
|
|
243
232
|
|
|
@@ -3,7 +3,7 @@ import SwiftUI
|
|
|
3
3
|
// MARK: - Types
|
|
4
4
|
|
|
5
5
|
/// Tooltip placement relative to the anchor element.
|
|
6
|
-
public enum TooltipPlacement {
|
|
6
|
+
public enum TooltipPlacement: Sendable {
|
|
7
7
|
case top
|
|
8
8
|
case bottom
|
|
9
9
|
case left
|
|
@@ -78,24 +78,37 @@ struct TooltipArrowShape: Shape {
|
|
|
78
78
|
func path(in rect: CGRect) -> Path {
|
|
79
79
|
let w = rect.width
|
|
80
80
|
let h = rect.height
|
|
81
|
-
|
|
81
|
+
let points: [CGPoint]
|
|
82
82
|
switch placement {
|
|
83
83
|
case .top:
|
|
84
|
-
|
|
85
|
-
path.addLine(to: CGPoint(x: w, y: 0))
|
|
86
|
-
path.addLine(to: CGPoint(x: w / 2, y: h))
|
|
84
|
+
points = [CGPoint(x: 0, y: 0), CGPoint(x: w, y: 0), CGPoint(x: w / 2, y: h)]
|
|
87
85
|
case .bottom:
|
|
88
|
-
|
|
89
|
-
path.addLine(to: CGPoint(x: w, y: h))
|
|
90
|
-
path.addLine(to: CGPoint(x: w / 2, y: 0))
|
|
86
|
+
points = [CGPoint(x: 0, y: h), CGPoint(x: w, y: h), CGPoint(x: w / 2, y: 0)]
|
|
91
87
|
case .left:
|
|
92
|
-
|
|
93
|
-
path.addLine(to: CGPoint(x: 0, y: h))
|
|
94
|
-
path.addLine(to: CGPoint(x: w, y: h / 2))
|
|
88
|
+
points = [CGPoint(x: 0, y: 0), CGPoint(x: 0, y: h), CGPoint(x: w, y: h / 2)]
|
|
95
89
|
case .right:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
points = [CGPoint(x: w, y: 0), CGPoint(x: w, y: h), CGPoint(x: 0, y: h / 2)]
|
|
91
|
+
}
|
|
92
|
+
// rounded like Compose's cornerPathEffect: each corner is cut `radius` along both edges
|
|
93
|
+
let radius = TooltipConst.arrowCornerRadius
|
|
94
|
+
func toward(_ from: CGPoint, _ to: CGPoint) -> CGPoint {
|
|
95
|
+
let dx = to.x - from.x
|
|
96
|
+
let dy = to.y - from.y
|
|
97
|
+
let length = (dx * dx + dy * dy).squareRoot()
|
|
98
|
+
guard length > 0 else { return from }
|
|
99
|
+
let distance = min(radius, length / 2)
|
|
100
|
+
return CGPoint(x: from.x + dx / length * distance, y: from.y + dy / length * distance)
|
|
101
|
+
}
|
|
102
|
+
var path = Path()
|
|
103
|
+
for index in 0..<points.count {
|
|
104
|
+
let corner = points[index]
|
|
105
|
+
let start = toward(corner, points[(index + points.count - 1) % points.count])
|
|
106
|
+
if index == 0 {
|
|
107
|
+
path.move(to: start)
|
|
108
|
+
} else {
|
|
109
|
+
path.addLine(to: start)
|
|
110
|
+
}
|
|
111
|
+
path.addQuadCurve(to: toward(corner, points[(index + 1) % points.count]), control: corner)
|
|
99
112
|
}
|
|
100
113
|
path.closeSubpath()
|
|
101
114
|
return path
|
|
@@ -209,6 +222,8 @@ private struct TooltipPositionModifier: ViewModifier {
|
|
|
209
222
|
}
|
|
210
223
|
)
|
|
211
224
|
.offset(x: originX, y: originY)
|
|
225
|
+
// the first pass has no size yet and would flash at the wrong spot
|
|
226
|
+
.opacity(popupSize == .zero ? 0 : 1)
|
|
212
227
|
}
|
|
213
228
|
|
|
214
229
|
private var originX: CGFloat {
|
|
@@ -30,9 +30,9 @@ public struct FontScale: Equatable {
|
|
|
30
30
|
public func callAsFunction(_ size: CGFloat) -> CGFloat {
|
|
31
31
|
guard useOSScaleRate else { return size * userScaleRate }
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
let deviceScale =
|
|
33
|
+
// Short side, not width: landscape must not inflate every font (and so every popup's height).
|
|
34
|
+
let bounds = UIScreen.main.bounds.size
|
|
35
|
+
let deviceScale = min(bounds.width, bounds.height) / Self.defaultScreenSize
|
|
36
36
|
|
|
37
37
|
var deviceScaled = size
|
|
38
38
|
var osScaled = size
|
|
@@ -52,7 +52,7 @@ public struct FontScale: Equatable {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/// A host-pushed mini-app context wins per field, matching Compose's
|
|
55
|
-
/// `context?.useOSScaleRate ?:
|
|
55
|
+
/// `context?.useOSScaleRate ?: DesignSystemKits.getConfigs().useOSScaleRate`.
|
|
56
56
|
public func overriding(userScaleRate: CGFloat?, useOSScaleRate: Bool?) -> FontScale {
|
|
57
57
|
guard userScaleRate != nil || useOSScaleRate != nil else { return self }
|
|
58
58
|
return FontScale(
|
|
@@ -66,7 +66,7 @@ public struct FontScale: Equatable {
|
|
|
66
66
|
private struct FontScaleKey: EnvironmentKey {
|
|
67
67
|
/// Computed, never stored: a bare `UIHostingController` root that never got `.momoFontScale()`
|
|
68
68
|
/// still reads the live store instead of a value frozen at first access.
|
|
69
|
-
static var defaultValue: FontScale {
|
|
69
|
+
static var defaultValue: FontScale { DesignSystemKits.shared.fontScale }
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
public extension EnvironmentValues {
|
|
@@ -77,9 +77,10 @@ public extension EnvironmentValues {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
public extension View {
|
|
80
|
-
/// Injects a Dynamic-Type-observing font scale
|
|
80
|
+
/// Injects a Dynamic-Type-observing font scale plus `\.designSystemKitsConfigs` (whitelist, remote config)
|
|
81
|
+
/// and re-renders this subtree on change.
|
|
81
82
|
/// Use at every `UIHostingController` root that is not inside a `NavigationContainer`.
|
|
82
|
-
func momoFontScale(_ store:
|
|
83
|
+
func momoFontScale(_ store: DesignSystemKits = .shared, context: MiniAppContext? = nil) -> some View {
|
|
83
84
|
modifier(MomoFontScaleModifier(store: store, context: context))
|
|
84
85
|
}
|
|
85
86
|
}
|
|
@@ -87,17 +88,19 @@ public extension View {
|
|
|
87
88
|
/// `@ObservedObject` is load-bearing, same as `MomoLocalizeModifier`: `@Environment(\.momoFontScale)`
|
|
88
89
|
/// only invalidates when the boxed snapshot changes, which requires *this* body to re-run on publish.
|
|
89
90
|
private struct MomoFontScaleModifier: ViewModifier {
|
|
90
|
-
@ObservedObject var store:
|
|
91
|
+
@ObservedObject var store: DesignSystemKits
|
|
91
92
|
let context: MiniAppContext?
|
|
92
93
|
|
|
93
94
|
func body(content: Content) -> some View {
|
|
94
|
-
content
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
content
|
|
96
|
+
.environment(
|
|
97
|
+
\.momoFontScale,
|
|
98
|
+
store.fontScale.overriding(
|
|
99
|
+
userScaleRate: context?.userScaleRate,
|
|
100
|
+
useOSScaleRate: context?.useOSScaleRate
|
|
101
|
+
)
|
|
99
102
|
)
|
|
100
|
-
|
|
103
|
+
.environment(\.designSystemKitsConfigs, store.getConfigs())
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
// AI-GENERATED END: reactive font-scale snapshot injected through the environment
|
|
@@ -4,7 +4,7 @@ import SwiftUI
|
|
|
4
4
|
/// free functions). Inside a SwiftUI view prefer `@Environment(\.momoFontScale)` so the view
|
|
5
5
|
/// re-renders when Dynamic Type or the host preference changes.
|
|
6
6
|
public func scaleSize(_ size: CGFloat) -> CGFloat {
|
|
7
|
-
|
|
7
|
+
DesignSystemKits.shared.fontScale(size)
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
@available(*, deprecated, message: "Max font scale is fixed at 1.5; this override is no longer applied. Drop the second argument.")
|
|
@@ -99,33 +99,130 @@ public extension TypographyStyle {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
private enum MomoFontFace {
|
|
103
|
+
case system
|
|
104
|
+
case named(String)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Port of Compose `getFontFamily`; SF Pro Text is the iOS system font, so the legacy family is `.system`.
|
|
108
|
+
private func momoFontFace(family: String, weight: Font.Weight, isWhiteList: Bool) -> MomoFontFace? {
|
|
109
|
+
let isNewFamily = family == "MomoTrustSans" || family == headerFontFamily
|
|
110
|
+
// Outside the whitelist the new DS families drop to the legacy font, as before DS-791.
|
|
111
|
+
if family == "SFProText" || (isNewFamily && !isWhiteList) { return .system }
|
|
112
|
+
// single-file families (Compose maps every weight to the same .otf)
|
|
113
|
+
if family == headerFontFamily || family == "MoMoSignature" { return .named(family) }
|
|
105
114
|
guard family == "MomoTrustSans" else { return nil }
|
|
106
115
|
switch weight {
|
|
107
|
-
case .ultraLight, .thin: return "MomoTrustSans-ExtraLight"
|
|
108
|
-
case .light: return "MomoTrustSans-Light"
|
|
109
|
-
case .regular: return "MomoTrustSans-Regular"
|
|
110
|
-
case .medium: return "MomoTrustSans-Medium"
|
|
111
|
-
case .semibold: return "MomoTrustSans-SemiBold"
|
|
112
|
-
case .bold: return "MomoTrustSans-Bold"
|
|
113
|
-
case .heavy, .black: return "MomoTrustSans-ExtraBold"
|
|
114
|
-
default: return "MomoTrustSans-Regular"
|
|
116
|
+
case .ultraLight, .thin: return .named("MomoTrustSans-ExtraLight")
|
|
117
|
+
case .light: return .named("MomoTrustSans-Light")
|
|
118
|
+
case .regular: return .named("MomoTrustSans-Regular")
|
|
119
|
+
case .medium: return .named("MomoTrustSans-Medium")
|
|
120
|
+
case .semibold: return .named("MomoTrustSans-SemiBold")
|
|
121
|
+
case .bold: return .named("MomoTrustSans-Bold")
|
|
122
|
+
case .heavy, .black: return .named("MomoTrustSans-ExtraBold")
|
|
123
|
+
default: return .named("MomoTrustSans-Regular")
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
126
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
/// Header title family (Compose `HEADER_FONT_FAMILY`), whitelist only like the default font.
|
|
128
|
+
let headerFontFamily = "MoMoTrustDisplay"
|
|
129
|
+
|
|
130
|
+
private func momoFont(
|
|
131
|
+
size: CGFloat,
|
|
132
|
+
weight: Font.Weight,
|
|
133
|
+
family: String,
|
|
134
|
+
fallbackFamily: String? = nil,
|
|
135
|
+
isWhiteList: Bool
|
|
136
|
+
) -> Font {
|
|
137
|
+
switch momoFontFace(family: family, weight: weight, isWhiteList: isWhiteList) {
|
|
138
|
+
case .system:
|
|
139
|
+
return .system(size: size, weight: weight)
|
|
140
|
+
case .named(let name) where UIFont(name: name, size: size) != nil:
|
|
141
|
+
return .custom(name, fixedSize: size)
|
|
142
|
+
default:
|
|
143
|
+
// Compose falls back to the default font file when a family is missing
|
|
144
|
+
if let fallbackFamily, fallbackFamily != family {
|
|
145
|
+
return momoFont(size: size, weight: weight, family: fallbackFamily, isWhiteList: isWhiteList)
|
|
146
|
+
}
|
|
121
147
|
return .system(size: size, weight: weight)
|
|
122
148
|
}
|
|
123
|
-
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// lineHeight is identical across weights of a family, so the regular face is enough.
|
|
152
|
+
private func momoLineHeight(size: CGFloat, family: String, fallbackFamily: String? = nil, isWhiteList: Bool) -> CGFloat {
|
|
153
|
+
switch momoFontFace(family: family, weight: .regular, isWhiteList: isWhiteList) {
|
|
154
|
+
case .system:
|
|
155
|
+
break
|
|
156
|
+
case .named(let name):
|
|
157
|
+
if let font = UIFont(name: name, size: size) { return font.lineHeight }
|
|
158
|
+
fallthrough
|
|
159
|
+
case nil:
|
|
160
|
+
if let fallbackFamily, fallbackFamily != family {
|
|
161
|
+
return momoLineHeight(size: size, family: fallbackFamily, isWhiteList: isWhiteList)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return UIFont.systemFont(ofSize: size).lineHeight
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// UIKit counterpart of `momoFont`, for text that is not a `MomoText` (UITextField/UITextView, text measuring).
|
|
168
|
+
func momoUIFont(size: CGFloat, weight: UIFont.Weight, family: String, isWhiteList: Bool) -> UIFont {
|
|
169
|
+
guard case .named(let name) = momoFontFace(family: family, weight: Font.Weight(weight), isWhiteList: isWhiteList),
|
|
170
|
+
let font = UIFont(name: name, size: size) else {
|
|
171
|
+
return .systemFont(ofSize: size, weight: weight)
|
|
172
|
+
}
|
|
173
|
+
return font
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private extension Font.Weight {
|
|
177
|
+
init(_ weight: UIFont.Weight) {
|
|
178
|
+
switch weight {
|
|
179
|
+
case .ultraLight: self = .ultraLight
|
|
180
|
+
case .thin: self = .thin
|
|
181
|
+
case .light: self = .light
|
|
182
|
+
case .medium: self = .medium
|
|
183
|
+
case .semibold: self = .semibold
|
|
184
|
+
case .bold: self = .bold
|
|
185
|
+
case .heavy: self = .heavy
|
|
186
|
+
case .black: self = .black
|
|
187
|
+
default: self = .regular
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/// Gives input text the same family as `MomoText` (Compose's `getFontFamily`), e.g. a TextField
|
|
193
|
+
/// next to a `MomoText` placeholder. `size` is unscaled; the environment font scale is applied here.
|
|
194
|
+
private struct KitFontModifier: ViewModifier {
|
|
195
|
+
@Environment(\.appTheme) private var theme
|
|
196
|
+
@Environment(\.momoFontScale) private var fontScale
|
|
197
|
+
@Environment(\.designSystemKitsConfigs) private var designSystemKitsConfigs
|
|
198
|
+
let size: CGFloat
|
|
199
|
+
let weight: Font.Weight
|
|
200
|
+
|
|
201
|
+
func body(content: Content) -> some View {
|
|
202
|
+
content.font(momoFont(
|
|
203
|
+
size: fontScale(size),
|
|
204
|
+
weight: weight,
|
|
205
|
+
family: theme.font,
|
|
206
|
+
isWhiteList: designSystemKitsConfigs.isWhiteList
|
|
207
|
+
))
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
extension View {
|
|
212
|
+
func kitFont(_ typography: TypographyStyle) -> some View {
|
|
213
|
+
modifier(KitFontModifier(size: typography.fontSize, weight: typography.fontWeight))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
func kitFont(size: CGFloat, weight: Font.Weight = .regular) -> some View {
|
|
217
|
+
modifier(KitFontModifier(size: size, weight: weight))
|
|
218
|
+
}
|
|
124
219
|
}
|
|
125
220
|
|
|
126
221
|
public struct MomoText: View {
|
|
127
222
|
@Environment(\.appTheme) private var theme
|
|
128
223
|
@Environment(\.momoFontScale) private var fontScale
|
|
224
|
+
// From the environment, not DesignSystemKits.shared, so a whitelist flip re-renders the text.
|
|
225
|
+
@Environment(\.designSystemKitsConfigs) private var designSystemKitsConfigs
|
|
129
226
|
private let content: String
|
|
130
227
|
private let typography: TypographyStyle
|
|
131
228
|
private let color: Color?
|
|
@@ -139,7 +236,12 @@ public struct MomoText: View {
|
|
|
139
236
|
private let letterSpacing: CGFloat?
|
|
140
237
|
private let softWrap: Bool
|
|
141
238
|
private let accessibilityId: String?
|
|
239
|
+
private let fontFamily: String?
|
|
142
240
|
private var highlightText: [String] = []
|
|
241
|
+
private var sizeOverride: (fontSize: CGFloat, lineHeight: CGFloat)?
|
|
242
|
+
|
|
243
|
+
private var fontSize: CGFloat { sizeOverride?.fontSize ?? typography.fontSize }
|
|
244
|
+
private var lineHeight: CGFloat { sizeOverride?.lineHeight ?? typography.lineHeight }
|
|
143
245
|
|
|
144
246
|
public init(
|
|
145
247
|
_ content: String,
|
|
@@ -153,7 +255,8 @@ public struct MomoText: View {
|
|
|
153
255
|
underline: Bool = false,
|
|
154
256
|
letterSpacing: CGFloat? = nil,
|
|
155
257
|
softWrap: Bool = true,
|
|
156
|
-
accessibilityId: String? = nil
|
|
258
|
+
accessibilityId: String? = nil,
|
|
259
|
+
fontFamily: String? = nil
|
|
157
260
|
) {
|
|
158
261
|
self.content = content
|
|
159
262
|
self.typography = typography
|
|
@@ -175,6 +278,7 @@ public struct MomoText: View {
|
|
|
175
278
|
self.letterSpacing = letterSpacing
|
|
176
279
|
self.softWrap = softWrap
|
|
177
280
|
self.accessibilityId = accessibilityId
|
|
281
|
+
self.fontFamily = fontFamily
|
|
178
282
|
}
|
|
179
283
|
|
|
180
284
|
init(_ content: String, typography: TypographyStyle, highlightText: [String]) {
|
|
@@ -182,11 +286,34 @@ public struct MomoText: View {
|
|
|
182
286
|
self.highlightText = highlightText
|
|
183
287
|
}
|
|
184
288
|
|
|
289
|
+
/// Compose's `style.copy(fontSize, lineHeight)`; the weight still comes from `typography`.
|
|
290
|
+
func fontSize(_ fontSize: CGFloat, lineHeight: CGFloat) -> MomoText {
|
|
291
|
+
var text = self
|
|
292
|
+
text.sizeOverride = (fontSize, lineHeight)
|
|
293
|
+
return text
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private var font: Font {
|
|
297
|
+
momoFont(
|
|
298
|
+
size: fontScale(fontSize),
|
|
299
|
+
weight: typography.fontWeight,
|
|
300
|
+
family: fontFamily ?? theme.font,
|
|
301
|
+
fallbackFamily: theme.font,
|
|
302
|
+
isWhiteList: designSystemKitsConfigs.isWhiteList
|
|
303
|
+
)
|
|
304
|
+
}
|
|
305
|
+
|
|
185
306
|
// Whole-word matches of `highlightText` render semibold; the longest keyword wins (RN parity).
|
|
186
307
|
private var baseText: SwiftUI.Text {
|
|
187
308
|
let keywords = highlightText.filter { !$0.isEmpty }.sorted { $0.count > $1.count }
|
|
188
309
|
guard !keywords.isEmpty else { return SwiftUI.Text(content) }
|
|
189
|
-
let highlightFont = momoFont(
|
|
310
|
+
let highlightFont = momoFont(
|
|
311
|
+
size: fontScale(fontSize),
|
|
312
|
+
weight: TypographyStyle.headerXsSemibold.fontWeight,
|
|
313
|
+
family: fontFamily ?? theme.font,
|
|
314
|
+
fallbackFamily: theme.font,
|
|
315
|
+
isWhiteList: designSystemKitsConfigs.isWhiteList
|
|
316
|
+
)
|
|
190
317
|
func isWordChar(_ character: Character?) -> Bool {
|
|
191
318
|
guard let character else { return false }
|
|
192
319
|
return character.isLetter || character.isNumber || character == "_"
|
|
@@ -222,8 +349,17 @@ public struct MomoText: View {
|
|
|
222
349
|
// *Strikethrough styles) or the explicit `strikethrough` flag.
|
|
223
350
|
let isStrikethrough = strikethrough || typography.isStrikethrough
|
|
224
351
|
|
|
352
|
+
// lineSpacing is added on top of the font's natural line height, not on top of fontSize.
|
|
353
|
+
let lineSpacing = max(0, fontScale(lineHeight)
|
|
354
|
+
- momoLineHeight(
|
|
355
|
+
size: fontScale(fontSize),
|
|
356
|
+
family: fontFamily ?? theme.font,
|
|
357
|
+
fallbackFamily: theme.font,
|
|
358
|
+
isWhiteList: designSystemKitsConfigs.isWhiteList
|
|
359
|
+
))
|
|
360
|
+
|
|
225
361
|
var text = baseText
|
|
226
|
-
.font(
|
|
362
|
+
.font(font)
|
|
227
363
|
.foregroundColor(textColor)
|
|
228
364
|
.strikethrough(isStrikethrough, color: textColor)
|
|
229
365
|
.underline(underline, color: textColor)
|
|
@@ -234,7 +370,7 @@ public struct MomoText: View {
|
|
|
234
370
|
|
|
235
371
|
return text
|
|
236
372
|
.multilineTextAlignment(textAlign)
|
|
237
|
-
.lineSpacing(
|
|
373
|
+
.lineSpacing(lineSpacing)
|
|
238
374
|
.modifier(LineLimitModifier(range: lineLimitRange))
|
|
239
375
|
.truncationMode(truncationMode)
|
|
240
376
|
.fixedSize(horizontal: !softWrap, vertical: false)
|