@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.
Files changed (93) hide show
  1. package/CLAUDE.md +19 -0
  2. package/compose/build.gradle.kts +1 -1
  3. package/compose/compose.podspec +1 -1
  4. package/gradle.properties +1 -1
  5. package/ios/Application/ApplicationEnvironment.swift +14 -6
  6. package/ios/Application/LanguageSource.swift +93 -0
  7. package/ios/Application/Localize.swift +73 -4
  8. package/ios/Application/LocalizeModifier.swift +30 -0
  9. package/ios/Application/Navigation/NavigationContainer.swift +28 -18
  10. package/ios/Application/Navigation/Navigator.swift +121 -53
  11. package/ios/Application/Navigation/NavigatorManager.swift +49 -0
  12. package/ios/Application/Navigation/component/NavigationFooter.swift +90 -0
  13. package/ios/Application/StackScreen.swift +19 -28
  14. package/ios/Badge/Badge.swift +2 -1
  15. package/ios/Badge/BadgeRibbon.swift +6 -2
  16. package/ios/Button/Button.swift +41 -61
  17. package/ios/Chip/Chip.swift +6 -5
  18. package/ios/Icon/Icon.swift +13 -4
  19. package/ios/Input/ErrorView.swift +2 -1
  20. package/ios/Input/Input.swift +9 -2
  21. package/ios/Input/InputPhoneNumber.swift +2 -1
  22. package/ios/Input/InputSearch.swift +3 -2
  23. package/ios/Input/InputTextArea.swift +6 -1
  24. package/ios/InputMoney/InputMoney.swift +5 -2
  25. package/ios/InputOTP/InputOTP.swift +2 -1
  26. package/ios/Layout/GridContext.swift +30 -0
  27. package/ios/Layout/Item.swift +42 -0
  28. package/ios/Layout/Section.swift +134 -0
  29. package/ios/Popup/PopupNotify.swift +2 -1
  30. package/ios/ProgressInfo/ProgressInfo.swift +4 -3
  31. package/ios/Rating/Rating.swift +2 -1
  32. package/ios/Stepper/Stepper.swift +2 -1
  33. package/ios/SuggestAction/SuggestAction.swift +3 -2
  34. package/ios/Tag/Tag.swift +2 -1
  35. package/ios/Template/TrustBanner/TrustBanner.swift +4 -2
  36. package/ios/Title/Title.swift +3 -2
  37. package/ios/Tooltip/Tooltip.swift +2 -1
  38. package/ios/Typography/FontScale.swift +103 -0
  39. package/ios/Typography/FontScaleStore.swift +52 -13
  40. package/ios/Typography/Text.swift +12 -29
  41. package/ios/Typography/Typography.swift +66 -86
  42. package/ios/native-kits.podspec +2 -1
  43. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  44. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +87 -73
  45. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +55 -249
  46. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +90 -82
  47. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +74 -104
  48. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +47 -50
  49. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +63 -7
  50. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +90 -81
  51. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +73 -97
  52. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +420 -0
  53. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +46 -4
  54. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +54 -57
  55. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +80 -45
  56. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +81 -0
  57. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +49 -62
  58. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +66 -116
  59. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +104 -98
  60. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +76 -118
  61. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +73 -86
  62. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +69 -54
  63. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +74 -54
  64. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +73 -20
  65. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +68 -38
  66. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +55 -52
  67. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +51 -4
  68. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +14 -2
  69. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +47 -51
  70. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
  71. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +67 -93
  72. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +34 -43
  73. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +83 -71
  74. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +55 -23
  75. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +58 -46
  76. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +83 -0
  77. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +41 -12
  78. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +67 -127
  79. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +54 -110
  80. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +69 -79
  81. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +78 -58
  82. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +76 -65
  83. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +82 -127
  84. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +44 -19
  85. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +92 -168
  86. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +79 -27
  87. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +0 -1
  88. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +87 -92
  89. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +94 -163
  90. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +70 -70
  91. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +68 -114
  92. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +3 -1
  93. package/package.json +2 -2
@@ -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
- ScrollView {
12
- VStack(alignment: .leading, spacing: 24) {
13
- section("Size") {
14
- HStack(alignment: .center, spacing: 8) {
15
- Avatar(size: .size24)
16
- Avatar(size: .size32)
17
- Avatar(size: .size40)
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
- section("showIconMomo") {
48
- HStack(spacing: 8) {
49
- Avatar(size: .size40, showIconMomo: true)
50
- Avatar(size: .size48, name: "MN", showIconMomo: true)
51
- Avatar(size: .size56, image: "https://i.pravatar.cc/150?img=4", showIconMomo: true)
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
- section("showIconSupport") {
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
- section("showIconMomo + showIconSupport") {
64
- HStack(spacing: 8) {
65
- Avatar(size: .size56, showIconMomo: true, showIconSupport: true)
66
- Avatar(size: .size72, name: "NV", showIconMomo: true, showIconSupport: true)
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
- @ViewBuilder
75
- private func section<Content: View>(
76
- _ title: String,
77
- @ViewBuilder content: () -> Content
78
- ) -> some View {
79
- VStack(alignment: .leading, spacing: 8) {
80
- Text(title)
81
- .font(.headline)
82
- content()
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
- #if DEBUG
88
- struct AvatarDemo_Previews: PreviewProvider {
89
- static var previews: some View {
90
- AvatarDemo()
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
- // Created by sophia on 12/5/25.
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
- // MARK: Internal
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
- ScrollView {
19
- VStack(alignment: .leading, spacing: 24) {
20
- // MARK: - Basic Badges
21
-
22
- VStack(alignment: .leading, spacing: 12) {
23
- Text("Basic Badges")
24
- .font(.headline)
25
- .padding(.horizontal, 16)
26
-
27
- VStack(spacing: 16) {
28
- HStack(spacing: 16) {
29
- VStack(spacing: 8) {
30
- Badge()
31
- Text("Default")
32
- .font(.caption)
33
- .foregroundColor(.gray)
34
- }
35
-
36
- VStack(spacing: 8) {
37
- Badge(label: "9")
38
- Text("Single Digit")
39
- .font(.caption)
40
- .foregroundColor(.gray)
41
- }
42
-
43
- VStack(spacing: 8) {
44
- Badge(label: "99")
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: - Preview
57
+ // MARK: - Playground
262
58
 
263
- #if DEBUG
264
- struct BadgeDemo_Previews: PreviewProvider {
265
- static var previews: some View {
266
- BadgeDemo()
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