@momo-kits/native-kits 0.162.30 → 0.162.31

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 (90) hide show
  1. package/CLAUDE.md +19 -0
  2. package/ios/Application/ApplicationEnvironment.swift +14 -6
  3. package/ios/Application/LanguageSource.swift +93 -0
  4. package/ios/Application/Localize.swift +73 -4
  5. package/ios/Application/LocalizeModifier.swift +30 -0
  6. package/ios/Application/Navigation/NavigationContainer.swift +28 -18
  7. package/ios/Application/Navigation/Navigator.swift +121 -53
  8. package/ios/Application/Navigation/NavigatorManager.swift +49 -0
  9. package/ios/Application/Navigation/component/NavigationFooter.swift +90 -0
  10. package/ios/Application/StackScreen.swift +19 -28
  11. package/ios/Badge/Badge.swift +2 -1
  12. package/ios/Badge/BadgeRibbon.swift +6 -2
  13. package/ios/Button/Button.swift +41 -61
  14. package/ios/Chip/Chip.swift +6 -5
  15. package/ios/Icon/Icon.swift +13 -4
  16. package/ios/Input/ErrorView.swift +2 -1
  17. package/ios/Input/Input.swift +9 -2
  18. package/ios/Input/InputPhoneNumber.swift +2 -1
  19. package/ios/Input/InputSearch.swift +3 -2
  20. package/ios/Input/InputTextArea.swift +6 -1
  21. package/ios/InputMoney/InputMoney.swift +5 -2
  22. package/ios/InputOTP/InputOTP.swift +2 -1
  23. package/ios/Layout/GridContext.swift +30 -0
  24. package/ios/Layout/Item.swift +42 -0
  25. package/ios/Layout/Section.swift +134 -0
  26. package/ios/Popup/PopupNotify.swift +2 -1
  27. package/ios/ProgressInfo/ProgressInfo.swift +4 -3
  28. package/ios/Rating/Rating.swift +2 -1
  29. package/ios/Stepper/Stepper.swift +2 -1
  30. package/ios/SuggestAction/SuggestAction.swift +3 -2
  31. package/ios/Tag/Tag.swift +2 -1
  32. package/ios/Template/TrustBanner/TrustBanner.swift +4 -2
  33. package/ios/Title/Title.swift +3 -2
  34. package/ios/Tooltip/Tooltip.swift +2 -1
  35. package/ios/Typography/FontScale.swift +103 -0
  36. package/ios/Typography/FontScaleStore.swift +52 -13
  37. package/ios/Typography/Text.swift +12 -29
  38. package/ios/Typography/Typography.swift +66 -86
  39. package/ios/native-kits.podspec +2 -1
  40. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  41. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +87 -73
  42. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +55 -249
  43. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +90 -82
  44. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +74 -104
  45. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +47 -50
  46. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +63 -7
  47. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +90 -81
  48. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +73 -97
  49. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +420 -0
  50. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +46 -4
  51. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +54 -57
  52. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +80 -45
  53. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +81 -0
  54. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +49 -62
  55. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +66 -116
  56. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +104 -98
  57. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +76 -118
  58. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +73 -86
  59. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +69 -54
  60. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +74 -54
  61. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +73 -20
  62. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +68 -38
  63. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +55 -52
  64. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +51 -4
  65. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +14 -2
  66. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +47 -51
  67. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
  68. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +67 -93
  69. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +34 -43
  70. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +83 -71
  71. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +55 -23
  72. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +58 -46
  73. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +83 -0
  74. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +41 -12
  75. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +67 -127
  76. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +54 -110
  77. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +69 -79
  78. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +78 -58
  79. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +76 -65
  80. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +82 -127
  81. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +44 -19
  82. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +92 -168
  83. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +79 -27
  84. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +0 -1
  85. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +87 -92
  86. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +94 -163
  87. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +70 -70
  88. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +68 -114
  89. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +3 -1
  90. package/package.json +2 -2
@@ -2,137 +2,87 @@
2
2
  // InformationDemo.swift
3
3
  // Example
4
4
  //
5
- // Created by product2 on 6/18/26.
5
+ // Preview + Playground demo (DemoScreen pattern).
6
6
  //
7
7
 
8
- import Foundation
9
8
  import MoMoUIKits
10
9
  import SwiftUI
11
10
 
12
- // MARK: - InformationDemo
11
+ private let informationStateList: [PlaygroundOption] = [
12
+ .init("default", InformationState.default),
13
+ .init("warning", InformationState.warning),
14
+ .init("error", InformationState.error),
15
+ ]
13
16
 
14
17
  struct InformationDemo: View {
15
- @State private var showDismissible = true
16
-
17
18
  var body: some View {
18
- ScrollView {
19
- VStack(alignment: .leading, spacing: 24) {
20
- // MARK: - States
21
-
22
- section("States") {
23
- Information(
24
- title: "Default",
25
- description: "This is a default information message.",
26
- showIconClose: true,
27
- onPressClose: {}
28
- )
29
- Information(
30
- title: "Warning",
31
- description: "This is a warning information message.",
32
- state: .warning
33
- )
34
- Information(
35
- title: "Error",
36
- description: "This is an error information message.",
37
- state: .error
38
- )
39
- }
40
-
41
- // MARK: - Without title
42
-
43
- section("Description only") {
44
- Information(
45
- description: "Information without a title, only a description."
46
- )
47
- Information(
48
- description: "Warning without a title.",
49
- state: .warning
50
- )
51
- }
52
-
53
- // MARK: - With action
54
-
55
- section("With action") {
56
- Information(
57
- title: "Update available",
58
- description: "A new version is ready to install.",
59
- onPressAction: { print("Action pressed") },
60
- action: "Update now"
61
- )
62
- Information(
63
- title: "Payment failed",
64
- description: "We couldn't process your payment.",
65
- state: .error,
66
- onPressAction: { print("Retry pressed") },
67
- action: "Retry"
68
- )
69
- }
70
-
71
- // MARK: - With close button
72
-
73
- section("Dismissible") {
74
- if showDismissible {
75
- Information(
76
- title: "Dismissible",
77
- description: "Tap the close icon to dismiss this banner.",
78
- onPressClose: { showDismissible = false }
79
- )
80
- } else {
81
- Information(
82
- description: "Banner dismissed. Toggle to show again.",
83
- state: .warning,
84
- onPressAction: { showDismissible = true }, showIcon: true,
85
- action: "Show again"
86
-
87
- )
88
- }
89
- }
90
-
91
- // MARK: - With image
92
-
93
- section("With image") {
94
- Information(
95
- title: "Custom image",
96
- description: "Uses a remote image instead of the state icon.",
97
- image: "https://images.unsplash.com/photo-1509395062183-67c5ad6faff9",
98
- onPressClose: { print("Close pressed") }
99
- )
100
- }
101
-
102
- // MARK: - Without icon
103
-
104
- section("Without icon") {
105
- Information(
106
- title: "No icon",
107
- description: "showIcon is set to false.",
108
- showIcon: false
109
- )
110
- }
111
- }
112
- .padding(.vertical, 16)
19
+ if #available(iOS 16.0, *) {
20
+ DemoScreen(preview: { InformationPreview() }, playground: { InformationPlayground() })
21
+ } else {
22
+ Text("Requires iOS 16+").padding()
113
23
  }
114
24
  }
25
+ }
115
26
 
116
- // MARK: - Helpers
27
+ // MARK: - Preview
117
28
 
118
- @ViewBuilder
119
- private func section<Content: View>(
120
- _ title: String,
121
- @ViewBuilder content: () -> Content
122
- ) -> some View {
123
- VStack(alignment: .leading, spacing: 12) {
124
- Text(title)
125
- .font(.headline)
126
- content()
29
+ private struct InformationPreview: View {
30
+ var body: some View {
31
+ BasicColumnBox("States", alignment: .leading) {
32
+ Information(title: "Default", description: "This is a default information message.",
33
+ showIconClose: true, onPressClose: {})
34
+ Information(title: "Warning", description: "This is a warning information message.", state: .warning)
35
+ Information(title: "Error", description: "This is an error information message.", state: .error)
36
+ }
37
+ BasicColumnBox("Description only", alignment: .leading) {
38
+ Information(description: "Information without a title, only a description.")
39
+ Information(description: "Warning without a title.", state: .warning)
40
+ }
41
+ BasicColumnBox("With action", alignment: .leading) {
42
+ Information(title: "Update available", description: "A new version is ready to install.",
43
+ onPressAction: {}, action: "Update now")
44
+ Information(title: "Payment failed", description: "We couldn't process your payment.",
45
+ state: .error, onPressAction: {}, action: "Retry")
46
+ }
47
+ BasicColumnBox("Without icon", alignment: .leading) {
48
+ Information(title: "No icon", description: "showIcon is set to false.", showIcon: false)
127
49
  }
128
- .padding(.horizontal, 16)
129
50
  }
130
51
  }
131
52
 
132
- #if DEBUG
133
- struct InformationDemo_Previews: PreviewProvider {
134
- static var previews: some View {
135
- InformationDemo()
53
+ // MARK: - Playground
54
+
55
+ @available(iOS 16.0, *)
56
+ private struct InformationPlayground: View {
57
+ @State private var title = "Title"
58
+ @State private var description = "Information description."
59
+ @State private var state: PlaygroundOption? = informationStateList.first { $0.key == "default" }
60
+ @State private var showIcon = true
61
+ @State private var showIconClose = false
62
+ @State private var action = ""
63
+
64
+ var body: some View {
65
+ PlaygroundTab(
66
+ component: {
67
+ Information(
68
+ title: title.isEmpty ? nil : title,
69
+ description: description,
70
+ state: (state?.value as? InformationState) ?? .default,
71
+ onPressAction: {},
72
+ showIcon: showIcon,
73
+ action: action.isEmpty ? nil : action,
74
+ showIconClose: showIconClose,
75
+ onPressClose: {}
76
+ )
77
+ },
78
+ params: [
79
+ .string("Title", $title),
80
+ .string("Description", $description),
81
+ .radio("State", informationStateList, $state),
82
+ .checkbox("ShowIcon", $showIcon),
83
+ .checkbox("ShowIconClose", $showIconClose),
84
+ .string("Action", $action),
85
+ ]
86
+ )
136
87
  }
137
88
  }
138
- #endif
@@ -2,110 +2,116 @@
2
2
  // InputDemo.swift
3
3
  // Example
4
4
  //
5
- // Created by dung.pham2 on 29/11/24.
5
+ // Preview + Playground demo, mirroring Compose's InputUsage.kt.
6
6
  //
7
7
 
8
- import SwiftUI
9
8
  import MoMoUIKits
9
+ import SwiftUI
10
10
 
11
11
  struct InputDemo: View {
12
- @State private var textValue1 = ""
13
- @State private var textValue2 = ""
14
- @State private var textValue3 = ""
15
- @State private var textValue4 = ""
16
- @State private var textValue5 = ""
17
- @State private var textValue6 = ""
18
- @State private var textValue7 = ""
19
- @State private var textValue8 = ""
20
- @State private var textValue9 = ""
21
-
22
12
  var body: some View {
23
- ScrollView {
24
- VStack(alignment: .leading, spacing: 20) {
25
- Text("Input Demo")
26
- .font(.title1)
27
-
28
- Group {
29
- Text("Size")
30
- .font(.headerText1)
31
-
32
- Input(text: $textValue1, placeholder: "Small", size: .small, autofocus: true)
33
- Input(text: $textValue1, placeholder: "Large", size: .large)
34
- }
35
-
36
- Group {
37
- Text("Secure Text Entry")
38
- .font(.headerText1)
39
-
40
- Input(text: $textValue2, placeholder: "Enter here", floatingValue: "Momo", floatingIcon: "01.MoMo", secureTextEntry: true, autofocus: true)
41
- Input(text: $textValue2, placeholder: "Enter here", floatingValue: "Momo", floatingIcon: "01.MoMo", size: .large, secureTextEntry: true)
42
- }
43
-
44
- Group {
45
- Text("Floating Value")
46
- .font(.headerText1)
47
-
48
- Input(text: $textValue3, placeholder: "Enter here", floatingValue: "Momo", floatingIcon: "01.MoMo")
49
-
50
- }
51
-
52
- Group {
53
- Text("Hint")
54
- .font(.headerText1)
55
-
56
- Input(text: $textValue4, placeholder: "Enter here", hintText: textValue4.isEmpty ? "Hint text" : textValue4 )
57
- }
58
-
59
- Group {
60
- Text("Error")
61
- .font(.headerText1)
62
-
63
- Input(text: $textValue4, placeholder: "Enter here", error: textValue4.isEmpty ? "Error" : textValue4 )
64
- }
65
-
66
- Group {
67
- Text("Disabled")
68
- .font(.headerText1)
69
-
70
- Input(text: $textValue5, placeholder: "Enter here", disabled: true, leadingIcon: "01.MoMo"
71
- )
72
- }
73
-
74
- Group {
75
- Text("Leading Icon")
76
- .font(.headerText1)
77
-
78
- Input(text: $textValue6, placeholder: "Leading Icon", floatingValue: "Small Input", leadingIcon: "01.MoMo"
79
- )
80
-
81
- Input(text: $textValue7, placeholder: "Leading Icon", floatingValue: "Large Input", size: .large, leadingIcon: "01.MoMo"
82
- )
83
- }
84
-
85
- Group {
86
- Text("Trailing Icon")
87
- .font(.headerText1)
88
-
89
- Input(text: $textValue8, placeholder: "Trailing Icon", floatingValue: "Trailing", rightIcon: "01.MoMo")
90
- }
91
-
92
- Group {
93
- Text("Loading")
94
- .font(.headerText1)
95
-
96
- Input(text: $textValue8, placeholder: "Loading", floatingValue: "Loading", loading: true, required: true)
97
- }
98
-
99
- Group {
100
- Text("Font Weight")
101
- .font(.headerText1)
102
-
103
- Input(text: $textValue9, placeholder: "Font Weight", floatingValue: "Regular Font Weight", required: true, fontWeight: .regular)
104
-
105
- Input(text: $textValue9, placeholder: "Font Weight", floatingValue: "Bold Font Weight", required: true, fontWeight: .bold)
106
- }
107
- }
108
- .padding()
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { InputPreview() }, playground: { InputPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
20
+
21
+ // MARK: - Preview
22
+
23
+ private struct InputPreview: View {
24
+ @State private var t1 = ""
25
+ @State private var t2 = ""
26
+ @State private var t3 = ""
27
+ @State private var t4 = ""
28
+ @State private var t5 = ""
29
+ @State private var t6 = ""
30
+ @State private var t7 = ""
31
+
32
+ var body: some View {
33
+ BasicColumnBox("Size", alignment: .leading) {
34
+ Input(text: $t1, placeholder: "Small", size: .small)
35
+ Input(text: $t1, placeholder: "Large", size: .large)
36
+ }
37
+ BasicColumnBox("Floating Value", alignment: .leading) {
38
+ Input(text: $t2, placeholder: "Enter here", floatingValue: "Momo", floatingIcon: "01.MoMo")
39
+ }
40
+ BasicColumnBox("Secure Text Entry", alignment: .leading) {
41
+ Input(text: $t3, placeholder: "Enter here", floatingValue: "Momo", secureTextEntry: true)
109
42
  }
43
+ BasicColumnBox("Hint", alignment: .leading) {
44
+ Input(text: $t4, placeholder: "Enter here", hintText: "Hint text")
45
+ }
46
+ BasicColumnBox("Error", alignment: .leading) {
47
+ Input(text: $t5, placeholder: "Enter here", error: "Error")
48
+ }
49
+ BasicColumnBox("Disabled", alignment: .leading) {
50
+ Input(text: $t6, placeholder: "Enter here", disabled: true, leadingIcon: "01.MoMo")
51
+ }
52
+ BasicColumnBox("Loading", alignment: .leading) {
53
+ Input(text: $t7, placeholder: "Loading", floatingValue: "Loading", loading: true, required: true)
54
+ }
55
+ }
56
+ }
57
+
58
+ // MARK: - Playground
59
+
60
+ @available(iOS 16.0, *)
61
+ private struct InputPlayground: View {
62
+ @State private var text = ""
63
+ @State private var placeholder = "Placeholder"
64
+ @State private var floatingValue = ""
65
+ @State private var hintText = ""
66
+ @State private var error = ""
67
+ @State private var size: PlaygroundOption? = inputSizeList.first { $0.key == "small" }
68
+ @State private var fontWeight: PlaygroundOption? = inputFontWeightList.first { $0.key == "regular" }
69
+ @State private var keyboardType: PlaygroundOption? = keyboardTypeList.first { $0.key == "default" }
70
+ @State private var leadingIcon: PlaygroundOption?
71
+ @State private var rightIcon: PlaygroundOption?
72
+ @State private var maxLength = ""
73
+ @State private var disabled = false
74
+ @State private var secure = false
75
+ @State private var loading = false
76
+ @State private var required = false
77
+
78
+ var body: some View {
79
+ PlaygroundTab(
80
+ component: {
81
+ Input(
82
+ text: $text,
83
+ placeholder: placeholder,
84
+ floatingValue: floatingValue,
85
+ size: (size?.value as? InputSize) ?? .small,
86
+ hintText: hintText,
87
+ error: error,
88
+ disabled: disabled,
89
+ secureTextEntry: secure,
90
+ rightIcon: (rightIcon?.value as? String) ?? "",
91
+ leadingIcon: (leadingIcon?.value as? String) ?? "",
92
+ loading: loading,
93
+ required: required,
94
+ maxLength: maxLength.isEmpty ? nil : Int(maxLength),
95
+ fontWeight: (fontWeight?.value as? InputFontWeight) ?? .regular,
96
+ keyboardType: (keyboardType?.value as? UIKeyboardType) ?? .default
97
+ )
98
+ },
99
+ params: [
100
+ .string("Placeholder", $placeholder),
101
+ .string("FloatingValue", $floatingValue),
102
+ .string("HintText", $hintText),
103
+ .string("Error", $error),
104
+ .radio("Size", inputSizeList, $size),
105
+ .radio("FontWeight", inputFontWeightList, $fontWeight),
106
+ .radio("KeyboardType", keyboardTypeList, $keyboardType),
107
+ .option("LeadingIcon", playgroundIcons, $leadingIcon),
108
+ .option("RightIcon", playgroundIcons, $rightIcon),
109
+ .number("MaxLength", $maxLength),
110
+ .checkbox("Disabled", $disabled),
111
+ .checkbox("SecureTextEntry", $secure),
112
+ .checkbox("Loading", $loading),
113
+ .checkbox("Required", $required),
114
+ ]
115
+ )
110
116
  }
111
117
  }
@@ -2,135 +2,93 @@
2
2
  // InputDropDownDemo.swift
3
3
  // Example
4
4
  //
5
- // Showcases InputDropDown mirroring InputDropDownUsage.kt.
5
+ // Preview + Playground demo for InputDropDown.
6
6
  //
7
7
 
8
- import SwiftUI
9
8
  import MoMoUIKits
9
+ import SwiftUI
10
10
 
11
11
  struct InputDropDownDemo: View {
12
- @State private var empty = ""
13
- @State private var errorValue = "Error input"
14
-
15
12
  var body: some View {
16
- ScrollView {
17
- VStack(alignment: .leading, spacing: 20) {
18
- Text("InputDropDown Demo")
19
- .font(.title1)
20
-
21
- Group {
22
- Text("Size").font(.headerText1)
23
- InputDropDown(value: $empty, placeholder: "Input small", size: .small)
24
- InputDropDown(value: $empty, placeholder: "Input large", size: .large)
25
- }
26
-
27
- Group {
28
- Text("Floating Value").font(.headerText1)
29
- InputDropDown(
30
- value: $empty,
31
- floatingValue: "Title",
32
- floatingIcon: "basic_home",
33
- placeholder: "Select options"
34
- )
35
- InputDropDown(
36
- value: $empty,
37
- floatingValue: "Title",
38
- floatingIcon: "basic_home",
39
- floatingIconColor: Colors.pink03,
40
- placeholder: "Select options"
41
- )
42
- }
43
-
44
- Group {
45
- Text("Error message").font(.headerText1)
46
- InputDropDown(
47
- value: $errorValue,
48
- placeholder: "Error input",
49
- error: "Error message"
50
- )
51
- }
52
-
53
- Group {
54
- Text("Hint message").font(.headerText1)
55
- InputDropDown(
56
- value: $empty,
57
- placeholder: "Error input",
58
- hintText: "Hint message"
59
- )
60
- }
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { InputDropDownPreview() }, playground: { InputDropDownPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
61
20
 
62
- Group {
63
- Text("Disabled").font(.headerText1)
64
- InputDropDown(
65
- value: $empty,
66
- floatingValue: "Title",
67
- floatingIcon: "basic_home",
68
- placeholder: "Disabled input",
69
- disabled: true
70
- )
71
- }
21
+ // MARK: - Preview
72
22
 
73
- Group {
74
- Text("Error spacing").font(.headerText1)
75
- InputDropDown(
76
- value: $empty,
77
- placeholder: "",
78
- errorSpacing: true
79
- )
80
- }
23
+ private struct InputDropDownPreview: View {
24
+ @State private var empty = ""
25
+ @State private var errorValue = "Error input"
81
26
 
82
- Group {
83
- Text("Leading Icon").font(.headerText1)
84
- InputDropDown(
85
- value: $empty,
86
- floatingValue: "Small input",
87
- placeholder: "Leading icon",
88
- leadingIcon: "basic_home"
89
- )
90
- InputDropDown(
91
- value: $empty,
92
- floatingValue: "Large input",
93
- placeholder: "Leading icon",
94
- size: .large,
95
- leadingIcon: "basic_home"
96
- )
97
- }
27
+ var body: some View {
28
+ BasicColumnBox("Size", alignment: .leading) {
29
+ InputDropDown(value: $empty, placeholder: "Input small", size: .small)
30
+ InputDropDown(value: $empty, placeholder: "Input large", size: .large)
31
+ }
32
+ BasicColumnBox("Floating Value", alignment: .leading) {
33
+ InputDropDown(value: $empty, floatingValue: "Title", floatingIcon: "basic_home", placeholder: "Select options")
34
+ }
35
+ BasicColumnBox("Error message", alignment: .leading) {
36
+ InputDropDown(value: $errorValue, placeholder: "Error input", error: "Error message")
37
+ }
38
+ BasicColumnBox("Disabled", alignment: .leading) {
39
+ InputDropDown(value: $empty, floatingValue: "Title", floatingIcon: "basic_home", placeholder: "Disabled input", disabled: true)
40
+ }
41
+ BasicColumnBox("Leading Icon", alignment: .leading) {
42
+ InputDropDown(value: $empty, floatingValue: "Small input", placeholder: "Leading icon", leadingIcon: "basic_home")
43
+ }
44
+ }
45
+ }
98
46
 
99
- Group {
100
- Text("Icon").font(.headerText1)
101
- InputDropDown(
102
- value: $empty,
103
- placeholder: "Right icon",
104
- icon: "arrow_chevron_down_small"
105
- )
106
- InputDropDown(
107
- value: $empty,
108
- placeholder: "Right icon",
109
- icon: "arrow_chevron_down_small",
110
- iconColor: Colors.pink03
111
- )
112
- }
47
+ // MARK: - Playground
113
48
 
114
- Group {
115
- Text("Required").font(.headerText1)
116
- InputDropDown(
117
- value: $empty,
118
- floatingValue: "Title",
119
- placeholder: "Required field",
120
- required: true
121
- )
122
- }
49
+ @available(iOS 16.0, *)
50
+ private struct InputDropDownPlayground: View {
51
+ @State private var value = ""
52
+ @State private var placeholder = "Select options"
53
+ @State private var floatingValue = ""
54
+ @State private var hintText = ""
55
+ @State private var error = ""
56
+ @State private var size: PlaygroundOption? = inputSizeList.first { $0.key == "small" }
57
+ @State private var leadingIcon: PlaygroundOption?
58
+ @State private var disabled = false
59
+ @State private var errorSpacing = false
60
+ @State private var loading = false
61
+ @State private var required = false
123
62
 
124
- Group {
125
- Text("Loading").font(.headerText1)
126
- InputDropDown(
127
- value: $empty,
128
- placeholder: "Loading",
129
- loading: true
130
- )
131
- }
132
- }
133
- .padding()
134
- }
63
+ var body: some View {
64
+ PlaygroundTab(
65
+ component: {
66
+ InputDropDown(
67
+ value: $value,
68
+ floatingValue: floatingValue,
69
+ placeholder: placeholder,
70
+ size: (size?.value as? InputSize) ?? .small,
71
+ hintText: hintText,
72
+ error: error,
73
+ errorSpacing: errorSpacing,
74
+ disabled: disabled,
75
+ leadingIcon: (leadingIcon?.value as? String) ?? "",
76
+ loading: loading,
77
+ required: required
78
+ )
79
+ },
80
+ params: [
81
+ .string("Placeholder", $placeholder),
82
+ .string("FloatingValue", $floatingValue),
83
+ .string("HintText", $hintText),
84
+ .string("Error", $error),
85
+ .radio("Size", inputSizeList, $size),
86
+ .option("LeadingIcon", playgroundIcons, $leadingIcon),
87
+ .checkbox("Disabled", $disabled),
88
+ .checkbox("ErrorSpacing", $errorSpacing),
89
+ .checkbox("Loading", $loading),
90
+ .checkbox("Required", $required),
91
+ ]
92
+ )
135
93
  }
136
94
  }