@momo-kits/native-kits 0.163.1-sp.8-debug → 0.163.1-sp.9-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/settings.local.json +3 -1
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/gradle.properties +1 -1
- package/ios/Application/Navigation/Navigator.swift +30 -24
- package/ios/Application/StackScreen.swift +1 -7
- package/ios/native-kits.podspec +1 -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 +89 -82
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +74 -104
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +47 -51
- 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 +418 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +46 -4
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +51 -47
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +80 -45
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +67 -90
- 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/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 +57 -74
- 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/package.json +2 -2
|
@@ -152,7 +152,9 @@
|
|
|
152
152
|
"Bash(cp /Users/sophia/Workspace/momo/momo-native-kits/ios/Application/Navigation/Navigator.swift /Users/sophia/Workspace/momo/momo-app/node_modules/@momo-kits/native-kits/ios/Application/Navigation/Navigator.swift)",
|
|
153
153
|
"Bash(cp /Users/sophia/Workspace/momo/momo-native-kits/ios/Application/Navigation/NavigatorManager.swift /Users/sophia/Workspace/momo/momo-app/node_modules/@momo-kits/native-kits/ios/Application/Navigation/NavigatorManager.swift)",
|
|
154
154
|
"Bash(cp /Users/sophia/Workspace/momo/momo-native-kits/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift /Users/sophia/Workspace/momo/momo-app/node_modules/@momo-kits/native-kits/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift)",
|
|
155
|
-
"Bash(xcodebuild -workspace MoMoPlatform.xcworkspace -scheme MoMoPlatform-UAT -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' -derivedDataPath build/DerivedData build)"
|
|
155
|
+
"Bash(xcodebuild -workspace MoMoPlatform.xcworkspace -scheme MoMoPlatform-UAT -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' -derivedDataPath build/DerivedData build)",
|
|
156
|
+
"Bash(cp android/gradle/libs.versions.toml /private/tmp/claude-503/-Users-sophia-Workspace-momo-momo-native-kits/bfb380ee-54cb-4a02-bc5f-d152cce4b727/scratchpad/libs.versions.toml.bak)",
|
|
157
|
+
"Bash(sed -i '' 's/kits = \"0.163.1-sp.8\"/kits = \"0.163.1-sp.7\"/' android/gradle/libs.versions.toml)"
|
|
156
158
|
]
|
|
157
159
|
}
|
|
158
160
|
}
|
package/compose/build.gradle.kts
CHANGED
package/compose/compose.podspec
CHANGED
package/gradle.properties
CHANGED
|
@@ -273,30 +273,36 @@ public final class Navigator: ObservableObject {
|
|
|
273
273
|
}
|
|
274
274
|
if let preventBack = latest?.options?.headerBackProps?.preventBack {
|
|
275
275
|
showModal {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
276
|
+
PopupNotify(
|
|
277
|
+
props: PopupNotifyProps(
|
|
278
|
+
image: preventBack.image,
|
|
279
|
+
title: preventBack.title,
|
|
280
|
+
description: preventBack.description,
|
|
281
|
+
error: preventBack.error,
|
|
282
|
+
primary: PopupAction(
|
|
283
|
+
title: preventBack.primary?.title ?? "",
|
|
284
|
+
onPress: { [weak self] in
|
|
285
|
+
preventBack.primary?.onPress?()
|
|
286
|
+
// Close the popup, then leave the screen (matches Compose's pop(2)).
|
|
287
|
+
self?.pop(2, callback: callback)
|
|
288
|
+
}
|
|
289
|
+
),
|
|
290
|
+
secondary: preventBack.secondary.map { secondary in
|
|
291
|
+
PopupAction(
|
|
292
|
+
title: secondary.title,
|
|
293
|
+
onPress: { [weak self] in
|
|
294
|
+
secondary.onPress?()
|
|
295
|
+
self?.hideOverplay()
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
},
|
|
299
|
+
buttonDirection: preventBack.buttonDirection,
|
|
300
|
+
onIconClose: { [weak self] in
|
|
301
|
+
preventBack.onIconClose?()
|
|
302
|
+
self?.hideOverplay()
|
|
303
|
+
},
|
|
304
|
+
isShowCloseIcon: preventBack.isShowCloseIcon
|
|
305
|
+
)
|
|
300
306
|
)
|
|
301
307
|
}
|
|
302
308
|
return
|
|
@@ -143,13 +143,8 @@ public struct StackScreen<Content: View>: View {
|
|
|
143
143
|
// MARK: - Body
|
|
144
144
|
|
|
145
145
|
public var body: some View {
|
|
146
|
-
GeometryReader {
|
|
146
|
+
GeometryReader { _ in
|
|
147
147
|
let keyboardSize: CGFloat = useAvoidKeyboard ? max(keyboardHeight, 0) : 0
|
|
148
|
-
let bottomInset = min(geometry.safeAreaInsets.bottom, 21)
|
|
149
|
-
// Skip this screen's own bottom-inset reservation when hosting a footer
|
|
150
|
-
// OR a self-contained BottomTab surface (mirrors Compose's
|
|
151
|
-
// `if (options.footerComponent != null || isBottomTab) 0.dp else navigationBar`).
|
|
152
|
-
let contentBottomInset = (footer == nil && !isBottomTabRoot) ? bottomInset : 0
|
|
153
148
|
|
|
154
149
|
ZStack(alignment: .top) {
|
|
155
150
|
// Background color
|
|
@@ -161,7 +156,6 @@ public struct StackScreen<Content: View>: View {
|
|
|
161
156
|
VStack(alignment: horizontalAlignment, spacing: 0) {
|
|
162
157
|
headerAndContent
|
|
163
158
|
}
|
|
164
|
-
.padding(.bottom, contentBottomInset)
|
|
165
159
|
|
|
166
160
|
FloatingContent(
|
|
167
161
|
fabProps: fabProps,
|
package/ios/native-kits.podspec
CHANGED
|
@@ -2,92 +2,106 @@
|
|
|
2
2
|
// AvatarDemo.swift
|
|
3
3
|
// Example
|
|
4
4
|
//
|
|
5
|
+
// Preview + Playground demo (DemoScreen pattern).
|
|
6
|
+
//
|
|
5
7
|
|
|
6
|
-
import SwiftUI
|
|
7
8
|
import MoMoUIKits
|
|
9
|
+
import SwiftUI
|
|
8
10
|
|
|
9
11
|
struct AvatarDemo: View {
|
|
10
12
|
var body: some View {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Avatar(size: .size48)
|
|
19
|
-
Avatar(size: .size56)
|
|
20
|
-
Avatar(size: .size72)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
section("Rounded vs Square") {
|
|
25
|
-
HStack(spacing: 8) {
|
|
26
|
-
Avatar(size: .size40, rounded: true)
|
|
27
|
-
Avatar(size: .size40, rounded: false)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
section("Name (initials)") {
|
|
32
|
-
HStack(spacing: 8) {
|
|
33
|
-
Avatar(size: .size40, name: "Nguyen Van A")
|
|
34
|
-
Avatar(size: .size40, name: "John Doe")
|
|
35
|
-
Avatar(size: .size40, name: "MoMo")
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
section("Image") {
|
|
40
|
-
HStack(spacing: 8) {
|
|
41
|
-
Avatar(size: .size40, image: "https://i.pravatar.cc/150?img=1")
|
|
42
|
-
Avatar(size: .size56, image: "https://i.pravatar.cc/150?img=2")
|
|
43
|
-
Avatar(size: .size72, image: "https://i.pravatar.cc/150?img=3")
|
|
44
|
-
}
|
|
45
|
-
}
|
|
13
|
+
if #available(iOS 16.0, *) {
|
|
14
|
+
DemoScreen(preview: { AvatarPreview() }, playground: { AvatarPlayground() })
|
|
15
|
+
} else {
|
|
16
|
+
Text("Requires iOS 16+").padding()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
46
20
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
21
|
+
private let avatarSizeList: [PlaygroundOption] = [
|
|
22
|
+
.init("size24", AvatarSize.size24),
|
|
23
|
+
.init("size32", AvatarSize.size32),
|
|
24
|
+
.init("size40", AvatarSize.size40),
|
|
25
|
+
.init("size48", AvatarSize.size48),
|
|
26
|
+
.init("size56", AvatarSize.size56),
|
|
27
|
+
.init("size72", AvatarSize.size72),
|
|
28
|
+
]
|
|
54
29
|
|
|
55
|
-
|
|
56
|
-
HStack(spacing: 8) {
|
|
57
|
-
Avatar(size: .size40, showIconSupport: true)
|
|
58
|
-
Avatar(size: .size48, name: "CS", showIconSupport: true)
|
|
59
|
-
Avatar(size: .size56, image: "https://i.pravatar.cc/150?img=5", showIconSupport: true)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
30
|
+
// MARK: - Preview
|
|
62
31
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
32
|
+
private struct AvatarPreview: View {
|
|
33
|
+
var body: some View {
|
|
34
|
+
BasicColumnBox("Size", alignment: .leading) {
|
|
35
|
+
HStack(alignment: .center, spacing: Spacing.S) {
|
|
36
|
+
Avatar(size: .size24)
|
|
37
|
+
Avatar(size: .size32)
|
|
38
|
+
Avatar(size: .size40)
|
|
39
|
+
Avatar(size: .size48)
|
|
40
|
+
Avatar(size: .size56)
|
|
41
|
+
Avatar(size: .size72)
|
|
69
42
|
}
|
|
70
|
-
.padding()
|
|
71
43
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
44
|
+
BasicColumnBox("Rounded vs Square", alignment: .leading) {
|
|
45
|
+
HStack(spacing: Spacing.S) {
|
|
46
|
+
Avatar(size: .size40, rounded: true)
|
|
47
|
+
Avatar(size: .size40, rounded: false)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
BasicColumnBox("Name (initials)", alignment: .leading) {
|
|
51
|
+
HStack(spacing: Spacing.S) {
|
|
52
|
+
Avatar(size: .size40, name: "Nguyen Van A")
|
|
53
|
+
Avatar(size: .size40, name: "John Doe")
|
|
54
|
+
Avatar(size: .size40, name: "MoMo")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
BasicColumnBox("Image", alignment: .leading) {
|
|
58
|
+
HStack(spacing: Spacing.S) {
|
|
59
|
+
Avatar(size: .size40, image: "https://i.pravatar.cc/150?img=1")
|
|
60
|
+
Avatar(size: .size56, image: "https://i.pravatar.cc/150?img=2")
|
|
61
|
+
Avatar(size: .size72, image: "https://i.pravatar.cc/150?img=3")
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
BasicColumnBox("Icon badges", alignment: .leading) {
|
|
65
|
+
HStack(spacing: Spacing.S) {
|
|
66
|
+
Avatar(size: .size48, showIconMomo: true)
|
|
67
|
+
Avatar(size: .size48, showIconSupport: true)
|
|
68
|
+
Avatar(size: .size56, showIconMomo: true, showIconSupport: true)
|
|
69
|
+
}
|
|
83
70
|
}
|
|
84
71
|
}
|
|
85
72
|
}
|
|
86
73
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
74
|
+
// MARK: - Playground
|
|
75
|
+
|
|
76
|
+
@available(iOS 16.0, *)
|
|
77
|
+
private struct AvatarPlayground: View {
|
|
78
|
+
@State private var size: PlaygroundOption? = avatarSizeList.first { $0.key == "size48" }
|
|
79
|
+
@State private var rounded = true
|
|
80
|
+
@State private var name = ""
|
|
81
|
+
@State private var image = ""
|
|
82
|
+
@State private var showIconMomo = false
|
|
83
|
+
@State private var showIconSupport = false
|
|
84
|
+
|
|
85
|
+
var body: some View {
|
|
86
|
+
PlaygroundTab(
|
|
87
|
+
component: {
|
|
88
|
+
Avatar(
|
|
89
|
+
size: (size?.value as? AvatarSize) ?? .size48,
|
|
90
|
+
rounded: rounded,
|
|
91
|
+
name: name.isEmpty ? nil : name,
|
|
92
|
+
image: image.isEmpty ? nil : image,
|
|
93
|
+
showIconMomo: showIconMomo,
|
|
94
|
+
showIconSupport: showIconSupport
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
params: [
|
|
98
|
+
.radio("Size", avatarSizeList, $size),
|
|
99
|
+
.checkbox("Rounded", $rounded),
|
|
100
|
+
.string("Name", $name),
|
|
101
|
+
.string("Image", $image),
|
|
102
|
+
.checkbox("ShowIconMomo", $showIconMomo),
|
|
103
|
+
.checkbox("ShowIconSupport", $showIconSupport),
|
|
104
|
+
]
|
|
105
|
+
)
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
|
-
#endif
|
|
@@ -2,268 +2,74 @@
|
|
|
2
2
|
// BadgeDemo.swift
|
|
3
3
|
// Example
|
|
4
4
|
//
|
|
5
|
-
//
|
|
5
|
+
// Preview + Playground demo for Badge / BadgeDot / BadgeRibbon.
|
|
6
6
|
//
|
|
7
7
|
|
|
8
|
-
import Foundation
|
|
9
8
|
import MoMoUIKits
|
|
10
9
|
import SwiftUI
|
|
11
10
|
|
|
12
|
-
// MARK: - BadgeDemo
|
|
13
|
-
|
|
14
11
|
struct BadgeDemo: View {
|
|
15
|
-
|
|
12
|
+
var body: some View {
|
|
13
|
+
if #available(iOS 16.0, *) {
|
|
14
|
+
DemoScreen(preview: { BadgePreview() }, playground: { BadgePlayground() })
|
|
15
|
+
} else {
|
|
16
|
+
Text("Requires iOS 16+").padding()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
16
20
|
|
|
21
|
+
// MARK: - Preview
|
|
22
|
+
|
|
23
|
+
private struct BadgePreview: View {
|
|
17
24
|
var body: some View {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Text("Two Digits")
|
|
46
|
-
.font(.caption)
|
|
47
|
-
.foregroundColor(.gray)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
VStack(spacing: 8) {
|
|
51
|
-
Badge(label: "999")
|
|
52
|
-
Text("99+ Format")
|
|
53
|
-
.font(.caption)
|
|
54
|
-
.foregroundColor(.gray)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
HStack(spacing: 16) {
|
|
59
|
-
VStack(spacing: 8) {
|
|
60
|
-
Badge(label: "New")
|
|
61
|
-
Text("Text Label")
|
|
62
|
-
.font(.caption)
|
|
63
|
-
.foregroundColor(.gray)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
VStack(spacing: 8) {
|
|
67
|
-
Badge(label: "Hot", backgroundColor: Colors.pink03)
|
|
68
|
-
Text("Custom Color")
|
|
69
|
-
.font(.caption)
|
|
70
|
-
.foregroundColor(.gray)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
VStack(spacing: 8) {
|
|
74
|
-
Badge(label: "5", backgroundColor: Colors.green03)
|
|
75
|
-
Text("Green Badge")
|
|
76
|
-
.font(.caption)
|
|
77
|
-
.foregroundColor(.gray)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
.padding(.horizontal, 16)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
Divider()
|
|
85
|
-
|
|
86
|
-
// MARK: - Badge Dots
|
|
87
|
-
|
|
88
|
-
VStack(alignment: .leading, spacing: 12) {
|
|
89
|
-
Text("Badge Dots")
|
|
90
|
-
.font(.headline)
|
|
91
|
-
.padding(.horizontal, 16)
|
|
92
|
-
|
|
93
|
-
HStack(spacing: 32) {
|
|
94
|
-
VStack(spacing: 8) {
|
|
95
|
-
BadgeDot(size: .small)
|
|
96
|
-
Text("Small")
|
|
97
|
-
.font(.caption)
|
|
98
|
-
.foregroundColor(.gray)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
VStack(spacing: 8) {
|
|
102
|
-
BadgeDot(size: .large)
|
|
103
|
-
Text("Large")
|
|
104
|
-
.font(.caption)
|
|
105
|
-
.foregroundColor(.gray)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
.padding(.horizontal, 16)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
Divider()
|
|
112
|
-
|
|
113
|
-
// MARK: - Badge Ribbons
|
|
114
|
-
|
|
115
|
-
VStack(alignment: .leading, spacing: 12) {
|
|
116
|
-
Text("Badge Ribbons")
|
|
117
|
-
.font(.headline)
|
|
118
|
-
.padding(.horizontal, 16)
|
|
119
|
-
|
|
120
|
-
VStack(spacing: 20) {
|
|
121
|
-
HStack(spacing: 20) {
|
|
122
|
-
VStack(spacing: 8) {
|
|
123
|
-
BadgeRibbon(position: .topLeft, label: "Top Left", isRound: true)
|
|
124
|
-
.frame(width: 150, height: 30)
|
|
125
|
-
Text("Top Left")
|
|
126
|
-
.font(.caption)
|
|
127
|
-
.foregroundColor(.gray)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
VStack(spacing: 8) {
|
|
131
|
-
BadgeRibbon(position: .topRight, label: "Top Right", isRound: true)
|
|
132
|
-
.frame(width: 150, height: 30)
|
|
133
|
-
Text("Top Right")
|
|
134
|
-
.font(.caption)
|
|
135
|
-
.foregroundColor(.gray)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
HStack(spacing: 20) {
|
|
140
|
-
VStack(spacing: 8) {
|
|
141
|
-
BadgeRibbon(position: .bottomLeft, label: "Bottom Left", isRound: true)
|
|
142
|
-
.frame(width: 150, height: 30)
|
|
143
|
-
Text("Bottom Left")
|
|
144
|
-
.font(.caption)
|
|
145
|
-
.foregroundColor(.gray)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
VStack(spacing: 8) {
|
|
149
|
-
BadgeRibbon(position: .bottomRight, label: "Bottom Right", isRound: true)
|
|
150
|
-
.frame(width: 150, height: 30)
|
|
151
|
-
Text("Bottom Right")
|
|
152
|
-
.font(.caption)
|
|
153
|
-
.foregroundColor(.gray)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
.padding(.horizontal, 16)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
Divider()
|
|
161
|
-
|
|
162
|
-
// MARK: - Badge in Context (Real Usage Examples)
|
|
163
|
-
|
|
164
|
-
VStack(alignment: .leading, spacing: 12) {
|
|
165
|
-
Text("Real Usage Examples")
|
|
166
|
-
.font(.headline)
|
|
167
|
-
.padding(.horizontal, 16)
|
|
168
|
-
|
|
169
|
-
VStack(spacing: 16) {
|
|
170
|
-
// Notification with badge
|
|
171
|
-
HStack {
|
|
172
|
-
Image(systemName: "bell.fill")
|
|
173
|
-
.font(.system(size: 24))
|
|
174
|
-
.foregroundColor(Colors.primary)
|
|
175
|
-
|
|
176
|
-
Text("Notifications")
|
|
177
|
-
.font(.body)
|
|
178
|
-
|
|
179
|
-
Spacer()
|
|
180
|
-
|
|
181
|
-
Badge(label: "23")
|
|
182
|
-
}
|
|
183
|
-
.padding()
|
|
184
|
-
.background(Color(.systemGray6))
|
|
185
|
-
.cornerRadius(12)
|
|
186
|
-
|
|
187
|
-
// Message with badge
|
|
188
|
-
HStack {
|
|
189
|
-
Image(systemName: "message.fill")
|
|
190
|
-
.font(.system(size: 24))
|
|
191
|
-
.foregroundColor(Colors.primary)
|
|
192
|
-
|
|
193
|
-
Text("Messages")
|
|
194
|
-
.font(.body)
|
|
195
|
-
|
|
196
|
-
Spacer()
|
|
197
|
-
|
|
198
|
-
Badge(label: "5")
|
|
199
|
-
}
|
|
200
|
-
.padding()
|
|
201
|
-
.background(Color(.systemGray6))
|
|
202
|
-
.cornerRadius(12)
|
|
203
|
-
|
|
204
|
-
// Product card with ribbon
|
|
205
|
-
ZStack(alignment: .topTrailing) {
|
|
206
|
-
VStack(alignment: .leading, spacing: 8) {
|
|
207
|
-
Rectangle()
|
|
208
|
-
.fill(Color(.systemGray5))
|
|
209
|
-
.frame(height: 120)
|
|
210
|
-
.cornerRadius(8)
|
|
211
|
-
|
|
212
|
-
Text("Product Name")
|
|
213
|
-
.font(.headline)
|
|
214
|
-
|
|
215
|
-
Text("$99.99")
|
|
216
|
-
.font(.subheadline)
|
|
217
|
-
.foregroundColor(.gray)
|
|
218
|
-
}
|
|
219
|
-
.padding()
|
|
220
|
-
.background(Color(.systemGray6))
|
|
221
|
-
.cornerRadius(12)
|
|
222
|
-
|
|
223
|
-
BadgeRibbon(position: .topRight, label: "NEW")
|
|
224
|
-
.frame(width: 60, height: 40)
|
|
225
|
-
.offset(x: 5, y: 0)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Profile with dot indicator
|
|
229
|
-
HStack {
|
|
230
|
-
ZStack(alignment: .topTrailing) {
|
|
231
|
-
Circle()
|
|
232
|
-
.fill(Color(.systemGray5))
|
|
233
|
-
.frame(width: 50, height: 50)
|
|
234
|
-
|
|
235
|
-
BadgeDot(size: .small)
|
|
236
|
-
.offset(x: 2, y: 2)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
VStack(alignment: .leading) {
|
|
240
|
-
Text("User Name")
|
|
241
|
-
.font(.headline)
|
|
242
|
-
Text("Online")
|
|
243
|
-
.font(.caption)
|
|
244
|
-
.foregroundColor(Colors.green03)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
Spacer()
|
|
248
|
-
}
|
|
249
|
-
.padding()
|
|
250
|
-
.background(Color(.systemGray6))
|
|
251
|
-
.cornerRadius(12)
|
|
252
|
-
}
|
|
253
|
-
.padding(.horizontal, 16)
|
|
254
|
-
}
|
|
25
|
+
BasicColumnBox("Basic Badges", alignment: .leading) {
|
|
26
|
+
HStack(spacing: Spacing.L) {
|
|
27
|
+
Badge()
|
|
28
|
+
Badge(label: "9")
|
|
29
|
+
Badge(label: "99")
|
|
30
|
+
Badge(label: "999")
|
|
31
|
+
}
|
|
32
|
+
HStack(spacing: Spacing.L) {
|
|
33
|
+
Badge(label: "New")
|
|
34
|
+
Badge(label: "Hot", backgroundColor: Colors.pink03)
|
|
35
|
+
Badge(label: "5", backgroundColor: Colors.green03)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
BasicColumnBox("Badge Dots", alignment: .leading) {
|
|
40
|
+
HStack(spacing: Spacing.XL) {
|
|
41
|
+
BadgeDot(size: .small)
|
|
42
|
+
BadgeDot(size: .large)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
BasicColumnBox("Badge Ribbons", alignment: .leading) {
|
|
47
|
+
HStack(spacing: Spacing.L) {
|
|
48
|
+
BadgeRibbon(position: .topLeft, label: "Top Left", isRound: true)
|
|
49
|
+
.frame(width: 150, height: 30)
|
|
50
|
+
BadgeRibbon(position: .topRight, label: "Top Right", isRound: true)
|
|
51
|
+
.frame(width: 150, height: 30)
|
|
255
52
|
}
|
|
256
|
-
.padding(.vertical, 16)
|
|
257
53
|
}
|
|
258
54
|
}
|
|
259
55
|
}
|
|
260
56
|
|
|
261
|
-
// MARK: -
|
|
57
|
+
// MARK: - Playground
|
|
262
58
|
|
|
263
|
-
|
|
264
|
-
struct
|
|
265
|
-
|
|
266
|
-
|
|
59
|
+
@available(iOS 16.0, *)
|
|
60
|
+
private struct BadgePlayground: View {
|
|
61
|
+
@State private var label = "New"
|
|
62
|
+
@State private var color: PlaygroundOption? = playgroundColors.first { $0.key == "pink03" }
|
|
63
|
+
|
|
64
|
+
var body: some View {
|
|
65
|
+
PlaygroundTab(
|
|
66
|
+
component: {
|
|
67
|
+
Badge(label: label, backgroundColor: color?.value as? Color)
|
|
68
|
+
},
|
|
69
|
+
params: [
|
|
70
|
+
.string("Label", $label),
|
|
71
|
+
.color("BackgroundColor", playgroundColors, $color),
|
|
72
|
+
]
|
|
73
|
+
)
|
|
267
74
|
}
|
|
268
75
|
}
|
|
269
|
-
#endif
|