@momo-kits/native-kits 0.162.30-debug → 0.162.31-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 +19 -0
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +14 -6
- package/ios/Application/LanguageSource.swift +93 -0
- package/ios/Application/Localize.swift +73 -4
- package/ios/Application/LocalizeModifier.swift +30 -0
- package/ios/Application/Navigation/NavigationContainer.swift +28 -18
- package/ios/Application/Navigation/Navigator.swift +121 -53
- package/ios/Application/Navigation/NavigatorManager.swift +49 -0
- package/ios/Application/Navigation/component/NavigationFooter.swift +90 -0
- package/ios/Application/StackScreen.swift +19 -28
- package/ios/Badge/Badge.swift +2 -1
- package/ios/Badge/BadgeRibbon.swift +6 -2
- package/ios/Button/Button.swift +41 -61
- package/ios/Chip/Chip.swift +6 -5
- package/ios/Icon/Icon.swift +13 -4
- package/ios/Input/ErrorView.swift +2 -1
- package/ios/Input/Input.swift +9 -2
- package/ios/Input/InputPhoneNumber.swift +2 -1
- package/ios/Input/InputSearch.swift +3 -2
- package/ios/Input/InputTextArea.swift +6 -1
- package/ios/InputMoney/InputMoney.swift +5 -2
- package/ios/InputOTP/InputOTP.swift +2 -1
- package/ios/Layout/GridContext.swift +30 -0
- package/ios/Layout/Item.swift +42 -0
- package/ios/Layout/Section.swift +134 -0
- package/ios/Popup/PopupNotify.swift +2 -1
- package/ios/ProgressInfo/ProgressInfo.swift +4 -3
- package/ios/Rating/Rating.swift +2 -1
- package/ios/Stepper/Stepper.swift +2 -1
- package/ios/SuggestAction/SuggestAction.swift +3 -2
- package/ios/Tag/Tag.swift +2 -1
- package/ios/Template/TrustBanner/TrustBanner.swift +4 -2
- package/ios/Title/Title.swift +3 -2
- package/ios/Tooltip/Tooltip.swift +2 -1
- package/ios/Typography/FontScale.swift +103 -0
- package/ios/Typography/FontScaleStore.swift +52 -13
- package/ios/Typography/Text.swift +12 -29
- package/ios/Typography/Typography.swift +66 -86
- package/ios/native-kits.podspec +2 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +87 -73
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +55 -249
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +90 -82
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +74 -104
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +47 -50
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +63 -7
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +90 -81
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +73 -97
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +420 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +46 -4
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +54 -57
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +80 -45
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +81 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +49 -62
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +66 -116
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +104 -98
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +76 -118
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +73 -86
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +69 -54
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +74 -54
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +73 -20
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +68 -38
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +55 -52
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +51 -4
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +14 -2
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +47 -51
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +67 -93
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +34 -43
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +83 -71
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +55 -23
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +58 -46
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +83 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +41 -12
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +67 -127
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +54 -110
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +69 -79
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +78 -58
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +76 -65
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +82 -127
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +44 -19
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +92 -168
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +79 -27
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +0 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +87 -92
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +94 -163
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +70 -70
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +68 -114
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +3 -1
- package/package.json +2 -2
|
@@ -24,27 +24,72 @@ private let AppTranslations = LocalizationObject(
|
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
struct LocalizeDemo: View {
|
|
27
|
-
|
|
27
|
+
// AI-GENERATED START: observe the app language and drive it through the real platform API
|
|
28
|
+
@Environment(\.localize) private var localize
|
|
29
|
+
@Environment(\.applicationEnvironment) private var applicationEnvironment
|
|
30
|
+
// AI-GENERATED END: observe the app language and drive it through the real platform API
|
|
28
31
|
|
|
29
32
|
private var isEnglish: Bool { localize.currentLanguage == Localize.EN }
|
|
30
33
|
|
|
34
|
+
// AI-GENERATED START: observe the app language and drive it through the real platform API
|
|
35
|
+
private var storedLanguage: String {
|
|
36
|
+
UserDefaults.standard.string(forKey: UserDefaultsLanguageSource.defaultKey) ?? "nil"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private func setLanguage(_ language: String) {
|
|
40
|
+
// Platform API -> KMP LanguageApi.SetLanguage -> LocalizationProvider.set, which also
|
|
41
|
+
// mirrors AppleLanguages. KVO then pushes the change back into Localize. The real wire.
|
|
42
|
+
if let composeApi = applicationEnvironment.composeApi {
|
|
43
|
+
_ = composeApi.request(funcName: "setLanguage", params: language)
|
|
44
|
+
} else {
|
|
45
|
+
localize.changeLanguage(language) // #Preview / sample app: no host bridge
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// AI-GENERATED END: observe the app language and drive it through the real platform API
|
|
49
|
+
|
|
31
50
|
var body: some View {
|
|
32
51
|
ScrollView {
|
|
33
52
|
VStack(alignment: .leading, spacing: 0) {
|
|
34
53
|
|
|
35
54
|
LocalizeSectionBox(title: "Đổi ngôn ngữ (toàn app)") {
|
|
36
55
|
MomoText(
|
|
37
|
-
"
|
|
56
|
+
"Switch gọi platform API setLanguage — đổi ngôn ngữ THẬT của app. Localize observe lại "
|
|
57
|
+
+ "qua UserDefaults nên mọi màn hình đang đọc translate() đều cập nhật.",
|
|
38
58
|
typography: .descriptionDefaultRegular
|
|
39
59
|
)
|
|
40
60
|
Switch(
|
|
41
61
|
.constant(isEnglish),
|
|
42
|
-
onChange: { _ in
|
|
62
|
+
onChange: { _ in setLanguage(isEnglish ? Localize.VI : Localize.EN) },
|
|
43
63
|
title: "English"
|
|
44
64
|
)
|
|
45
65
|
MomoText("currentLanguage = \(localize.currentLanguage)", typography: .labelDefaultMedium)
|
|
46
66
|
}
|
|
47
67
|
|
|
68
|
+
// AI-GENERATED START: prove the observation loop, not kit-local state, drives updates
|
|
69
|
+
LocalizeSectionBox(title: "Nguồn thật: UserDefaults") {
|
|
70
|
+
MomoText(
|
|
71
|
+
"Ghi thẳng vào UserDefaults, bỏ qua mọi API của kit — màn hình vẫn đổi, chứng minh "
|
|
72
|
+
+ "Localize đang observe ngôn ngữ app.",
|
|
73
|
+
typography: .descriptionDefaultRegular
|
|
74
|
+
)
|
|
75
|
+
TranslationRow(key: UserDefaultsLanguageSource.defaultKey, value: storedLanguage)
|
|
76
|
+
Button(
|
|
77
|
+
title: "Ghi thẳng UserDefaults = \"en\"",
|
|
78
|
+
action: {
|
|
79
|
+
// Quoted on purpose: proves normalize() strips the JSON quoting
|
|
80
|
+
// RN and KMP persist.
|
|
81
|
+
UserDefaults.standard.set(
|
|
82
|
+
"\"en\"",
|
|
83
|
+
forKey: UserDefaultsLanguageSource.defaultKey
|
|
84
|
+
)
|
|
85
|
+
},
|
|
86
|
+
type: .outline,
|
|
87
|
+
size: .medium,
|
|
88
|
+
isFull: false
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
// AI-GENERATED END: prove the observation loop, not kit-local state, drives updates
|
|
92
|
+
|
|
48
93
|
LocalizeSectionBox(title: "translate(key) — từ điển mặc định của kit") {
|
|
49
94
|
TranslationRow(key: "confirm", value: localize.translate("confirm"))
|
|
50
95
|
TranslationRow(key: "cancel", value: localize.translate("cancel"))
|
|
@@ -179,8 +224,10 @@ private struct TranslationRow: View {
|
|
|
179
224
|
#Preview {
|
|
180
225
|
if #available(iOS 16.0, *) {
|
|
181
226
|
NavigationStack {
|
|
227
|
+
// AI-GENERATED START: preview needs the observing provider or the toggle will not update
|
|
182
228
|
LocalizeDemo()
|
|
183
|
-
.
|
|
229
|
+
.momoLocalize(Localize())
|
|
230
|
+
// AI-GENERATED END: preview needs the observing provider or the toggle will not update
|
|
184
231
|
}
|
|
185
232
|
} else {
|
|
186
233
|
// Fallback on earlier versions
|
|
@@ -101,9 +101,21 @@ private struct NavigationDemoContent: View {
|
|
|
101
101
|
|
|
102
102
|
Divider().padding(.vertical, 4)
|
|
103
103
|
|
|
104
|
+
row("Custom Back Handler") {
|
|
105
|
+
// The screen owns back: the header button and the edge swipe both
|
|
106
|
+
// run this instead of popping (mirrors Compose's onBackHandler).
|
|
107
|
+
navigator.push(
|
|
108
|
+
{ DemoLeafScreen(title: "Back is intercepted — swipe from the edge", color: Colors.blue09) },
|
|
109
|
+
options: NavigationOptions(
|
|
110
|
+
title: "Custom Back",
|
|
111
|
+
onBackHandler: { print("back intercepted") }
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
104
116
|
row("Prevent Back") {
|
|
105
|
-
//
|
|
106
|
-
// leaving (mirrors Compose's headerBackProps.preventBack).
|
|
117
|
+
// The header back button and the edge swipe both show a confirm popup
|
|
118
|
+
// before leaving (mirrors Compose's headerBackProps.preventBack).
|
|
107
119
|
navigator.push(
|
|
108
120
|
{ DemoLeafScreen(title: "Tap the header back button", color: Colors.pink09) },
|
|
109
121
|
options: NavigationOptions(
|
|
@@ -2,71 +2,67 @@
|
|
|
2
2
|
// PaginationDemo.swift
|
|
3
3
|
// Example
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// Mirrors shared PaginationUsage.kt: a configurable Data Length plus
|
|
7
|
-
// Prev/Next controls drive PaginationScroll, PaginationNumber,
|
|
8
|
-
// PaginationDot and PaginationWhiteDot.
|
|
5
|
+
// Preview + Playground demo for the pagination variants.
|
|
9
6
|
//
|
|
10
7
|
|
|
11
8
|
import MoMoUIKits
|
|
12
9
|
import SwiftUI
|
|
13
10
|
|
|
14
11
|
struct PaginationDemo: View {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
var body: some View {
|
|
13
|
+
if #available(iOS 16.0, *) {
|
|
14
|
+
DemoScreen(preview: { PaginationPreview() }, playground: { PaginationPlayground() })
|
|
15
|
+
} else {
|
|
16
|
+
Text("Requires iOS 16+").padding()
|
|
17
|
+
}
|
|
21
18
|
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// MARK: - Preview
|
|
22
22
|
|
|
23
|
+
private struct PaginationPreview: View {
|
|
23
24
|
var body: some View {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.overlay(
|
|
32
|
-
Rectangle().stroke(Colors.black06, lineWidth: 1)
|
|
33
|
-
)
|
|
34
|
-
}
|
|
25
|
+
BasicColumnBox("PaginationScroll", alignment: .leading) {
|
|
26
|
+
PaginationScroll {
|
|
27
|
+
ForEach(0..<10, id: \.self) { i in
|
|
28
|
+
MomoText("\(i)", typography: .bodyDefaultRegular)
|
|
29
|
+
.frame(width: 120, height: 60)
|
|
30
|
+
.background(Colors.blue08)
|
|
31
|
+
.overlay(Rectangle().stroke(Colors.black06, lineWidth: 1))
|
|
35
32
|
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
BasicColumnBox("Number / Dot", alignment: .leading) {
|
|
36
|
+
PaginationNumber(activeIndex: 1, dataLength: 3)
|
|
37
|
+
PaginationDot(activeIndex: 1, dataLength: 3)
|
|
38
|
+
}
|
|
39
|
+
BasicColumnBox("WhiteDot", alignment: .leading, background: Colors.black17) {
|
|
40
|
+
PaginationWhiteDot(activeIndex: 1, dataLength: 3)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
PaginationDot(activeIndex: activeIndex, dataLength: dataLength)
|
|
40
|
-
|
|
41
|
-
PaginationWhiteDot(activeIndex: activeIndex, dataLength: dataLength)
|
|
42
|
-
.padding(Spacing.S)
|
|
43
|
-
.background(Colors.black17) // dark backdrop so white dots are visible
|
|
45
|
+
// MARK: - Playground
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.onChange(of: dataLengthText) { _ in activeIndex = 0 }
|
|
50
|
-
.frame(maxWidth: 200)
|
|
47
|
+
@available(iOS 16.0, *)
|
|
48
|
+
private struct PaginationPlayground: View {
|
|
49
|
+
@State private var dataLength = "5"
|
|
50
|
+
@State private var activeIndex: Double = 0
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
Button("Prev") {
|
|
54
|
-
if activeIndex != 0 { activeIndex -= 1 }
|
|
55
|
-
}
|
|
56
|
-
.frame(maxWidth: .infinity)
|
|
52
|
+
private var length: Int { max(Int(dataLength) ?? 1, 1) }
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
var body: some View {
|
|
55
|
+
PlaygroundTab(
|
|
56
|
+
component: {
|
|
57
|
+
VStack(alignment: .leading, spacing: Spacing.L) {
|
|
58
|
+
PaginationNumber(activeIndex: Int(activeIndex), dataLength: length)
|
|
59
|
+
PaginationDot(activeIndex: Int(activeIndex), dataLength: length)
|
|
62
60
|
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
},
|
|
62
|
+
params: [
|
|
63
|
+
.number("DataLength", $dataLength),
|
|
64
|
+
.slider("ActiveIndex", $activeIndex, min: 0, max: 9, step: 1),
|
|
65
|
+
]
|
|
66
|
+
)
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
#Preview {
|
|
71
|
-
PaginationDemo()
|
|
72
|
-
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PlaygroundData.swift
|
|
3
|
+
// Example
|
|
4
|
+
//
|
|
5
|
+
// Swift equivalents of the option maps in Compose's DemoScreen.kt (buttonTypeList,
|
|
6
|
+
// sizeList, Icons, Colors.colorList, ...). Each list feeds an OPTION / RADIO / COLOR
|
|
7
|
+
// PlaygroundParams. Extend as more demos are converted.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import MoMoUIKits
|
|
11
|
+
import SwiftUI
|
|
12
|
+
|
|
13
|
+
// MARK: - Enum option maps
|
|
14
|
+
|
|
15
|
+
let buttonTypeList: [PlaygroundOption] = [
|
|
16
|
+
.init("primary", ButtonType.primary),
|
|
17
|
+
.init("secondary", ButtonType.secondary),
|
|
18
|
+
.init("tonal", ButtonType.tonal),
|
|
19
|
+
.init("outline", ButtonType.outline),
|
|
20
|
+
.init("danger", ButtonType.danger),
|
|
21
|
+
.init("text", ButtonType.text),
|
|
22
|
+
.init("disabled", ButtonType.disabled),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
let buttonSizeList: [PlaygroundOption] = [
|
|
26
|
+
.init("large", ButtonSize.large),
|
|
27
|
+
.init("medium", ButtonSize.medium),
|
|
28
|
+
.init("small", ButtonSize.small),
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
let inputSizeList: [PlaygroundOption] = [
|
|
32
|
+
.init("large", InputSize.large),
|
|
33
|
+
.init("small", InputSize.small),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
let inputFontWeightList: [PlaygroundOption] = [
|
|
37
|
+
.init("regular", InputFontWeight.regular),
|
|
38
|
+
.init("bold", InputFontWeight.bold),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
let keyboardTypeList: [PlaygroundOption] = [
|
|
42
|
+
.init("default", UIKeyboardType.default),
|
|
43
|
+
.init("asciiCapable", UIKeyboardType.asciiCapable),
|
|
44
|
+
.init("numberPad", UIKeyboardType.numberPad),
|
|
45
|
+
.init("phonePad", UIKeyboardType.phonePad),
|
|
46
|
+
.init("URL", UIKeyboardType.URL),
|
|
47
|
+
.init("emailAddress", UIKeyboardType.emailAddress),
|
|
48
|
+
.init("decimalPad", UIKeyboardType.decimalPad),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
// MARK: - Icons (curated from icon.json; Compose `Icons`)
|
|
52
|
+
|
|
53
|
+
let playgroundIcons: [PlaygroundOption] = [
|
|
54
|
+
"basic_home", "basic_flag", "basic_filter", "basic_delete", "basic_copy",
|
|
55
|
+
"basic_account", "basic_chart", "basic_setting", "basic_sun", "basic_person",
|
|
56
|
+
"basic_person_add", "basic_person_group", "basic_options", "basic_sorting",
|
|
57
|
+
"arrow_chevron_down", "arrow_chevron_up", "arrow_chevron_left", "arrow_chevron_right",
|
|
58
|
+
"arrow_arrow_forward", "arrow_redo", "arrow_undo", "arrow_refresh_ccw",
|
|
59
|
+
"security_eye_open", "notifications_check_circle", "help_center", "pin_star",
|
|
60
|
+
"navigation_more_icon",
|
|
61
|
+
].map { PlaygroundOption($0, $0) }
|
|
62
|
+
|
|
63
|
+
// MARK: - Colors (Compose `Colors.colorList`)
|
|
64
|
+
|
|
65
|
+
let playgroundColors: [PlaygroundOption] = [
|
|
66
|
+
.init("primary", Colors.primary),
|
|
67
|
+
.init("black17", Colors.black17),
|
|
68
|
+
.init("black13", Colors.black13),
|
|
69
|
+
.init("black10", Colors.black10),
|
|
70
|
+
.init("black05", Colors.black05),
|
|
71
|
+
.init("black01", Colors.black01),
|
|
72
|
+
.init("pink06", Colors.pink06),
|
|
73
|
+
.init("pink03", Colors.pink03),
|
|
74
|
+
.init("blue09", Colors.blue09),
|
|
75
|
+
.init("blue05", Colors.blue05),
|
|
76
|
+
]
|
|
@@ -4,118 +4,92 @@ import SwiftUI
|
|
|
4
4
|
struct PopupNotifyDemo: View {
|
|
5
5
|
var body: some View {
|
|
6
6
|
if #available(iOS 16.0, *) {
|
|
7
|
-
|
|
7
|
+
DemoScreen(preview: { PopupNotifyPreview() }, playground: { PopupNotifyPlayground() })
|
|
8
8
|
} else {
|
|
9
|
-
|
|
10
|
-
.padding()
|
|
9
|
+
Text("Requires iOS 16+").padding()
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
13
|
|
|
14
|
+
// MARK: - Preview
|
|
15
|
+
|
|
15
16
|
@available(iOS 16.0, *)
|
|
16
|
-
private struct
|
|
17
|
+
private struct PopupNotifyPreview: View {
|
|
17
18
|
@EnvironmentObject private var navigator: Navigator
|
|
18
19
|
|
|
20
|
+
var body: some View {
|
|
21
|
+
BasicColumnBox("PopupNotify", alignment: .leading) {
|
|
22
|
+
MoMoUIKits.Button(title: "Show popup", action: { show() }, size: .large)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private func show() {
|
|
27
|
+
navigator.showModal {
|
|
28
|
+
PopupNotify(props: PopupNotifyProps(
|
|
29
|
+
image: "https://i.imgur.com/s70S9s9.png",
|
|
30
|
+
title: "Title",
|
|
31
|
+
description: "Check lại một nhịp auto chuyển sang dạng CTA.",
|
|
32
|
+
error: "9004",
|
|
33
|
+
primary: PopupAction(title: "Primary", onPress: { navigator.hideOverplay() }),
|
|
34
|
+
secondary: PopupAction(title: "Secondary", onPress: { navigator.hideOverplay() }),
|
|
35
|
+
onIconClose: { navigator.hideOverplay() },
|
|
36
|
+
isShowCloseIcon: true
|
|
37
|
+
))
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// MARK: - Playground
|
|
43
|
+
|
|
44
|
+
private let popupDirectionList: [PlaygroundOption] = [
|
|
45
|
+
.init("auto", PopupActionDirection.auto),
|
|
46
|
+
.init("row", PopupActionDirection.row),
|
|
47
|
+
.init("column", PopupActionDirection.column),
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
@available(iOS 16.0, *)
|
|
51
|
+
private struct PopupNotifyPlayground: View {
|
|
52
|
+
@EnvironmentObject private var navigator: Navigator
|
|
19
53
|
@State private var image = "https://i.imgur.com/s70S9s9.png"
|
|
20
54
|
@State private var title = "Title"
|
|
21
55
|
@State private var description = "Check lại một nhịp auto chuyển sang dạng CTA."
|
|
22
56
|
@State private var error = "9004"
|
|
23
|
-
@State private var buttonDirection: PopupActionDirection = .auto
|
|
24
57
|
@State private var primaryTitle = "Primary"
|
|
25
58
|
@State private var secondaryTitle = "Secondary"
|
|
26
|
-
@State private var
|
|
59
|
+
@State private var showClose = false
|
|
60
|
+
@State private var direction: PlaygroundOption? = popupDirectionList.first { $0.key == "auto" }
|
|
27
61
|
|
|
28
62
|
var body: some View {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
title: "undefined"
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
Input(text: $title, placeholder: "Title", floatingValue: "Title")
|
|
49
|
-
Input(text: $description, placeholder: "Description", floatingValue: "Description")
|
|
50
|
-
|
|
51
|
-
HStack(alignment: .center, spacing: Spacing.S) {
|
|
52
|
-
Input(text: $error, placeholder: "Error", floatingValue: "Error")
|
|
53
|
-
Checkbox(
|
|
54
|
-
Binding(
|
|
55
|
-
get: { error.isEmpty },
|
|
56
|
-
set: { checked in error = checked ? "" : "9004" }
|
|
57
|
-
),
|
|
58
|
-
title: "undefined"
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
VStack(alignment: .leading, spacing: Spacing.XS) {
|
|
63
|
-
MomoText("Button Direction", typography: .descriptionDefaultRegular, color: Colors.black12)
|
|
64
|
-
Picker("Button Direction", selection: $buttonDirection) {
|
|
65
|
-
Text("Auto").tag(PopupActionDirection.auto)
|
|
66
|
-
Text("Row").tag(PopupActionDirection.row)
|
|
67
|
-
Text("Column").tag(PopupActionDirection.column)
|
|
68
|
-
}
|
|
69
|
-
.pickerStyle(.segmented)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
Input(
|
|
73
|
-
text: $primaryTitle,
|
|
74
|
-
placeholder: "Primary Button Title",
|
|
75
|
-
floatingValue: "Primary Button Title"
|
|
76
|
-
)
|
|
77
|
-
Input(
|
|
78
|
-
text: $secondaryTitle,
|
|
79
|
-
placeholder: "Secondary Button Title",
|
|
80
|
-
floatingValue: "Secondary Button Title"
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
Checkbox($showCloseButton, title: "Show Close Button")
|
|
84
|
-
|
|
85
|
-
MoMoUIKits.Button(
|
|
86
|
-
title: "Show popup",
|
|
87
|
-
action: showPopup,
|
|
88
|
-
size: .large
|
|
89
|
-
)
|
|
90
|
-
.padding(.top, Spacing.XS)
|
|
91
|
-
}
|
|
92
|
-
.padding(Spacing.M * 2)
|
|
93
|
-
}
|
|
63
|
+
PlaygroundTab(
|
|
64
|
+
component: {
|
|
65
|
+
MoMoUIKits.Button(title: "Show popup", action: { show() }, size: .large)
|
|
66
|
+
},
|
|
67
|
+
params: [
|
|
68
|
+
.string("Image", $image),
|
|
69
|
+
.string("Title", $title),
|
|
70
|
+
.string("Description", $description),
|
|
71
|
+
.string("Error", $error),
|
|
72
|
+
.string("PrimaryTitle", $primaryTitle),
|
|
73
|
+
.string("SecondaryTitle", $secondaryTitle),
|
|
74
|
+
.radio("ButtonDirection", popupDirectionList, $direction),
|
|
75
|
+
.checkbox("ShowCloseButton", $showClose),
|
|
76
|
+
]
|
|
77
|
+
)
|
|
94
78
|
}
|
|
95
79
|
|
|
96
|
-
private func
|
|
80
|
+
private func show() {
|
|
97
81
|
navigator.showModal {
|
|
98
|
-
PopupNotify(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
110
|
-
)
|
|
82
|
+
PopupNotify(props: PopupNotifyProps(
|
|
83
|
+
image: image,
|
|
84
|
+
title: title,
|
|
85
|
+
description: description,
|
|
86
|
+
error: error,
|
|
87
|
+
primary: PopupAction(title: primaryTitle, onPress: { navigator.hideOverplay() }),
|
|
88
|
+
secondary: PopupAction(title: secondaryTitle, onPress: { navigator.hideOverplay() }),
|
|
89
|
+
buttonDirection: (direction?.value as? PopupActionDirection) ?? .auto,
|
|
90
|
+
onIconClose: { navigator.hideOverplay() },
|
|
91
|
+
isShowCloseIcon: showClose
|
|
92
|
+
))
|
|
111
93
|
}
|
|
112
94
|
}
|
|
113
95
|
}
|
|
114
|
-
|
|
115
|
-
#if DEBUG
|
|
116
|
-
struct PopupNotifyDemo_Previews: PreviewProvider {
|
|
117
|
-
static var previews: some View {
|
|
118
|
-
PopupNotifyDemo()
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
#endif
|
|
@@ -2,75 +2,66 @@
|
|
|
2
2
|
// PopupPromotionDemo.swift
|
|
3
3
|
// Example
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// Mirrors Compose's PromotionPopupUsage: an image-URL form whose action
|
|
7
|
-
// button presents the popup through `navigator.showModal`.
|
|
5
|
+
// Preview + Playground demo. PopupPromotion is presented via `navigator.showModal`.
|
|
8
6
|
//
|
|
9
7
|
|
|
10
8
|
import MoMoUIKits
|
|
11
9
|
import SwiftUI
|
|
12
10
|
|
|
13
|
-
// MARK: - PopupPromotionDemo
|
|
14
|
-
|
|
15
11
|
struct PopupPromotionDemo: View {
|
|
16
12
|
var body: some View {
|
|
17
13
|
if #available(iOS 16.0, *) {
|
|
18
|
-
|
|
14
|
+
DemoScreen(preview: { PopupPromotionPreview() }, playground: { PopupPromotionPlayground() })
|
|
19
15
|
} else {
|
|
20
|
-
Text("
|
|
21
|
-
.padding()
|
|
16
|
+
Text("Requires iOS 16+").padding()
|
|
22
17
|
}
|
|
23
18
|
}
|
|
24
19
|
}
|
|
25
20
|
|
|
26
|
-
// MARK: -
|
|
21
|
+
// MARK: - Preview
|
|
27
22
|
|
|
28
23
|
@available(iOS 16.0, *)
|
|
29
|
-
private struct
|
|
24
|
+
private struct PopupPromotionPreview: View {
|
|
30
25
|
@EnvironmentObject private var navigator: Navigator
|
|
31
26
|
|
|
32
|
-
@State private var imageUrl = "https://static.momocdn.net/app/app/appx/ABC.png?size=M"
|
|
33
|
-
|
|
34
27
|
var body: some View {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
Button(
|
|
44
|
-
title: "Show Popup",
|
|
45
|
-
action: showPopup,
|
|
46
|
-
type: .primary,
|
|
47
|
-
size: .large
|
|
48
|
-
)
|
|
49
|
-
.padding(.top, 8)
|
|
50
|
-
}
|
|
51
|
-
.padding(Spacing.M * 2)
|
|
28
|
+
BasicColumnBox("PopupPromotion", alignment: .leading) {
|
|
29
|
+
MoMoUIKits.Button(
|
|
30
|
+
title: "Show Popup",
|
|
31
|
+
action: { show("https://static.momocdn.net/app/app/appx/ABC.png?size=M") },
|
|
32
|
+
size: .large
|
|
33
|
+
)
|
|
52
34
|
}
|
|
53
35
|
}
|
|
54
36
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
private func showPopup() {
|
|
37
|
+
private func show(_ url: String) {
|
|
58
38
|
navigator.showModal {
|
|
59
|
-
PopupPromotion(
|
|
60
|
-
imageUrl: imageUrl,
|
|
61
|
-
onIconClose: { navigator.hideOverplay() },
|
|
62
|
-
onAction: { navigator.hideOverplay() }
|
|
63
|
-
)
|
|
39
|
+
PopupPromotion(imageUrl: url, onIconClose: { navigator.hideOverplay() }, onAction: { navigator.hideOverplay() })
|
|
64
40
|
}
|
|
65
41
|
}
|
|
66
42
|
}
|
|
67
43
|
|
|
68
|
-
// MARK: -
|
|
44
|
+
// MARK: - Playground
|
|
69
45
|
|
|
70
|
-
|
|
71
|
-
struct
|
|
72
|
-
|
|
73
|
-
|
|
46
|
+
@available(iOS 16.0, *)
|
|
47
|
+
private struct PopupPromotionPlayground: View {
|
|
48
|
+
@EnvironmentObject private var navigator: Navigator
|
|
49
|
+
@State private var imageUrl = "https://static.momocdn.net/app/app/appx/ABC.png?size=M"
|
|
50
|
+
|
|
51
|
+
var body: some View {
|
|
52
|
+
PlaygroundTab(
|
|
53
|
+
component: {
|
|
54
|
+
MoMoUIKits.Button(title: "Show Popup", action: { show() }, size: .large)
|
|
55
|
+
},
|
|
56
|
+
params: [
|
|
57
|
+
.string("ImageURL", $imageUrl),
|
|
58
|
+
]
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private func show() {
|
|
63
|
+
navigator.showModal {
|
|
64
|
+
PopupPromotion(imageUrl: imageUrl, onIconClose: { navigator.hideOverplay() }, onAction: { navigator.hideOverplay() })
|
|
65
|
+
}
|
|
74
66
|
}
|
|
75
67
|
}
|
|
76
|
-
#endif
|