@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.
Files changed (55) hide show
  1. package/.claude/settings.local.json +3 -1
  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/Navigation/Navigator.swift +30 -24
  6. package/ios/Application/StackScreen.swift +1 -7
  7. package/ios/native-kits.podspec +1 -1
  8. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  9. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +87 -73
  10. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +55 -249
  11. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +89 -82
  12. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +74 -104
  13. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +47 -51
  14. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +63 -7
  15. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +90 -81
  16. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +73 -97
  17. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DemoScreen.swift +418 -0
  18. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +46 -4
  19. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +51 -47
  20. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +80 -45
  21. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconDemo.swift +67 -90
  22. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +49 -62
  23. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +66 -116
  24. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +104 -98
  25. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +76 -118
  26. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +73 -86
  27. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +69 -54
  28. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +74 -54
  29. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +73 -20
  30. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +68 -38
  31. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +55 -52
  32. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +47 -51
  33. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PlaygroundData.swift +76 -0
  34. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +67 -93
  35. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +34 -43
  36. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +83 -71
  37. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +55 -23
  38. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +58 -46
  39. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SectionDemo.swift +57 -74
  40. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +41 -12
  41. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +67 -127
  42. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +54 -110
  43. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +69 -79
  44. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +78 -58
  45. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +76 -65
  46. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +82 -127
  47. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +44 -19
  48. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +92 -168
  49. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +79 -27
  50. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +0 -1
  51. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +87 -92
  52. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +94 -163
  53. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +70 -70
  54. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +68 -114
  55. package/package.json +2 -2
@@ -1,32 +1,64 @@
1
- import SwiftUI
1
+ //
2
+ // RadioDemo.swift
3
+ // Example
4
+ //
5
+ // Preview + Playground demo for Radio.
6
+ //
7
+
2
8
  import MoMoUIKits
9
+ import SwiftUI
3
10
 
4
11
  struct RadioDemo: View {
12
+ var body: some View {
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { RadioPreview() }, playground: { RadioPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
20
+
21
+ // MARK: - Preview
22
+
23
+ private struct RadioPreview: View {
5
24
  @State private var group: AnyHashable = 1
6
25
 
7
26
  var body: some View {
8
- VStack(alignment: .leading, spacing: 24) {
9
- // Value
10
- VStack(alignment: .leading, spacing: 12) {
11
- Text("Value").font(.description1)
12
- Radio(value: 1, groupValue: $group)
13
- Radio(value: 2, groupValue: $group)
14
- }
15
-
16
- // Disabled
17
- VStack(alignment: .leading, spacing: 12) {
18
- Text("Disabled").font(.description1)
19
- Radio(value: 1, groupValue: .constant(1), disabled: true)
20
- Radio(value: 2, groupValue: .constant(1), disabled: false)
21
- }
22
-
23
- // Label
24
- VStack(alignment: .leading, spacing: 12) {
25
- Text("Label").font(.description1)
26
- Radio(value: 1, groupValue: .constant(1), label: "Label")
27
- Radio(value: 2, groupValue: .constant(1), label: "Label")
28
- }
27
+ BasicColumnBox("Value", alignment: .leading) {
28
+ Radio(value: 1, groupValue: $group)
29
+ Radio(value: 2, groupValue: $group)
29
30
  }
30
- .padding()
31
+ BasicColumnBox("Disabled", alignment: .leading) {
32
+ Radio(value: 1, groupValue: .constant(1), disabled: true)
33
+ Radio(value: 2, groupValue: .constant(1), disabled: false)
34
+ }
35
+ BasicColumnBox("Label", alignment: .leading) {
36
+ Radio(value: 1, groupValue: .constant(1), label: "Label")
37
+ Radio(value: 2, groupValue: .constant(1), label: "Label")
38
+ }
39
+ }
40
+ }
41
+
42
+ // MARK: - Playground
43
+
44
+ @available(iOS 16.0, *)
45
+ private struct RadioPlayground: View {
46
+ @State private var group: AnyHashable = 1
47
+ @State private var label = "Label"
48
+ @State private var disabled = false
49
+
50
+ var body: some View {
51
+ PlaygroundTab(
52
+ component: {
53
+ VStack(alignment: .leading, spacing: Spacing.S) {
54
+ Radio(value: 1, groupValue: $group, disabled: disabled, label: label)
55
+ Radio(value: 2, groupValue: $group, disabled: disabled, label: label)
56
+ }
57
+ },
58
+ params: [
59
+ .string("Label", $label),
60
+ .checkbox("Disabled", $disabled),
61
+ ]
62
+ )
31
63
  }
32
64
  }
@@ -1,56 +1,68 @@
1
- import SwiftUI
1
+ //
2
+ // RatingDemo.swift
3
+ // Example
4
+ //
5
+ // Preview + Playground demo for Rating.
6
+ //
7
+
2
8
  import MoMoUIKits
9
+ import SwiftUI
3
10
 
4
- struct RatingDemo: View {
5
- @State private var interactiveRating: Float = 3
11
+ private let ratingSizeList: [PlaygroundOption] = [
12
+ .init("small", RatingSize.small),
13
+ .init("medium", RatingSize.medium),
14
+ .init("large", RatingSize.large),
15
+ ]
6
16
 
17
+ struct RatingDemo: View {
7
18
  var body: some View {
8
- ScrollView {
9
- VStack(alignment: .leading, spacing: 24) {
10
- section("Size") {
11
- Rating(numOfStars: 5, rating: 3, size: .small)
12
- Rating(numOfStars: 5, rating: 3, size: .medium)
13
- Rating(numOfStars: 5, rating: 3, size: .large)
14
- }
15
-
16
- section("Half star") {
17
- Rating(numOfStars: 5, rating: 3.5)
18
- }
19
-
20
- section("Full") {
21
- Rating(numOfStars: 5, rating: 5)
22
- }
23
-
24
- section("Empty") {
25
- Rating(numOfStars: 5, rating: 0)
26
- }
27
-
28
- section("Read-only (no callback)") {
29
- Rating(numOfStars: 5, rating: 4)
30
- }
31
-
32
- section("Interactive") {
33
- Rating(
34
- numOfStars: 5,
35
- rating: interactiveRating,
36
- onRatingChange: { newRating in
37
- interactiveRating = Float(newRating)
38
- }
39
- )
40
- }
41
- }
42
- .padding()
19
+ if #available(iOS 16.0, *) {
20
+ DemoScreen(preview: { RatingPreview() }, playground: { RatingPlayground() })
21
+ } else {
22
+ Text("Requires iOS 16+").padding()
43
23
  }
44
24
  }
25
+ }
45
26
 
46
- @ViewBuilder
47
- private func section<Content: View>(
48
- _ title: String,
49
- @ViewBuilder content: () -> Content
50
- ) -> some View {
51
- VStack(alignment: .leading, spacing: 8) {
52
- Text(title)
53
- content()
27
+ // MARK: - Preview
28
+
29
+ private struct RatingPreview: View {
30
+ var body: some View {
31
+ BasicColumnBox("Size", alignment: .leading) {
32
+ Rating(numOfStars: 5, rating: 3, size: .small)
33
+ Rating(numOfStars: 5, rating: 3, size: .medium)
34
+ Rating(numOfStars: 5, rating: 3, size: .large)
54
35
  }
36
+ BasicColumnBox("Values", alignment: .leading) {
37
+ Rating(numOfStars: 5, rating: 3.5)
38
+ Rating(numOfStars: 5, rating: 5)
39
+ Rating(numOfStars: 5, rating: 0)
40
+ }
41
+ }
42
+ }
43
+
44
+ // MARK: - Playground
45
+
46
+ @available(iOS 16.0, *)
47
+ private struct RatingPlayground: View {
48
+ @State private var stars: Double = 5
49
+ @State private var rating: Double = 3
50
+ @State private var size: PlaygroundOption? = ratingSizeList.first { $0.key == "large" }
51
+
52
+ var body: some View {
53
+ PlaygroundTab(
54
+ component: {
55
+ Rating(
56
+ numOfStars: Int(stars),
57
+ rating: Float(rating),
58
+ size: (size?.value as? RatingSize) ?? .large
59
+ )
60
+ },
61
+ params: [
62
+ .slider("NumOfStars", $stars, min: 1, max: 10, step: 1),
63
+ .slider("Rating", $rating, min: 0, max: 10, step: 0.5),
64
+ .radio("Size", ratingSizeList, $size),
65
+ ]
66
+ )
55
67
  }
56
68
  }
@@ -1,93 +1,76 @@
1
- import SwiftUI
1
+ //
2
+ // SectionDemo.swift
3
+ // Example
4
+ //
5
+ // Preview + Playground demo for SectionView / ItemView (12-column grid).
6
+ //
7
+
2
8
  import MoMoUIKits
9
+ import SwiftUI
3
10
 
4
11
  struct SectionDemo: View {
5
12
  var body: some View {
6
- ScrollView {
7
- // No horizontal padding here — SectionView brings its own 12pt margin.
8
- VStack(alignment: .leading, spacing: 24) {
9
- block("Full width — span 12") {
10
- SectionView {
11
- SectionTile("12")
12
- }
13
- }
14
-
15
- block("Even splits") {
16
- SectionView {
17
- ItemView(widthSpan: 6) { SectionTile("6") }
18
- ItemView(widthSpan: 6) { SectionTile("6") }
19
- ItemView(widthSpan: 4) { SectionTile("4") }
20
- ItemView(widthSpan: 4) { SectionTile("4") }
21
- ItemView(widthSpan: 4) { SectionTile("4") }
22
- ItemView(widthSpan: 3) { SectionTile("3") }
23
- ItemView(widthSpan: 3) { SectionTile("3") }
24
- ItemView(widthSpan: 3) { SectionTile("3") }
25
- ItemView(widthSpan: 3) { SectionTile("3") }
26
- }
27
- }
28
-
29
- block("Wrapping — a row that overflows breaks to the next line") {
30
- SectionView {
31
- ItemView(widthSpan: 8) { SectionTile("8") }
32
- ItemView(widthSpan: 5) { SectionTile("5") }
33
- ItemView(widthSpan: 7) { SectionTile("7") }
34
- }
35
- }
36
-
37
- block("heightSpan — square tiles") {
38
- SectionView {
39
- ItemView(widthSpan: 3, heightSpan: 3) { SectionTile("3×3") }
40
- ItemView(widthSpan: 3, heightSpan: 3) { SectionTile("3×3") }
41
- ItemView(widthSpan: 6, heightSpan: 3) { SectionTile("6×3") }
42
- }
43
- }
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { SectionPreview() }, playground: { SectionPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
44
20
 
45
- block("useMargin: false — edge to edge") {
46
- SectionView(useMargin: false) {
47
- ItemView(widthSpan: 6) { SectionTile("6") }
48
- ItemView(widthSpan: 6) { SectionTile("6") }
49
- }
50
- }
21
+ // MARK: - Preview
51
22
 
52
- block("backgroundImage") {
53
- SectionView(backgroundImage: "https://images.unsplash.com/photo-1509395062183-67c5ad6faff9") {
54
- ItemView(widthSpan: 6, heightSpan: 4) { SectionTile("6×4") }
55
- ItemView(widthSpan: 6, heightSpan: 4) { SectionTile("6×4") }
56
- }
57
- }
58
-
59
- block("Multiple children stack vertically inside one Item") {
60
- SectionView {
61
- ItemView(widthSpan: 6) {
62
- SectionTile("top")
63
- SectionTile("bottom")
64
- }
65
- ItemView(widthSpan: 6) { SectionTile("6") }
66
- }
67
- }
23
+ private struct SectionPreview: View {
24
+ var body: some View {
25
+ BasicColumnBox("Full width — span 12", alignment: .leading) {
26
+ SectionView { SectionTile("12") }
27
+ }
28
+ BasicColumnBox("Even splits", alignment: .leading) {
29
+ SectionView {
30
+ ItemView(widthSpan: 6) { SectionTile("6") }
31
+ ItemView(widthSpan: 6) { SectionTile("6") }
32
+ ItemView(widthSpan: 4) { SectionTile("4") }
33
+ ItemView(widthSpan: 4) { SectionTile("4") }
34
+ ItemView(widthSpan: 4) { SectionTile("4") }
35
+ }
36
+ }
37
+ BasicColumnBox("heightSpan — square tiles", alignment: .leading) {
38
+ SectionView {
39
+ ItemView(widthSpan: 3, heightSpan: 3) { SectionTile("3×3") }
40
+ ItemView(widthSpan: 3, heightSpan: 3) { SectionTile("3×3") }
41
+ ItemView(widthSpan: 6, heightSpan: 3) { SectionTile("6×3") }
68
42
  }
69
- .padding(.vertical)
70
43
  }
71
44
  }
45
+ }
72
46
 
73
- @ViewBuilder
74
- private func block<Content: View>(_ title: String, @ViewBuilder content: () -> Content) -> some View {
75
- VStack(alignment: .leading, spacing: 8) {
76
- Text(title)
77
- .font(.headline)
78
- .padding(.horizontal, Spacing.M)
79
- content()
80
- }
47
+ // MARK: - Playground
48
+
49
+ @available(iOS 16.0, *)
50
+ private struct SectionPlayground: View {
51
+ @State private var span: Double = 6
52
+ @State private var useMargin = true
53
+
54
+ var body: some View {
55
+ PlaygroundTab(
56
+ component: {
57
+ SectionView(useMargin: useMargin) {
58
+ ItemView(widthSpan: Int(span)) { SectionTile("\(Int(span))") }
59
+ ItemView(widthSpan: 12 - Int(span)) { SectionTile("\(12 - Int(span))") }
60
+ }
61
+ },
62
+ params: [
63
+ .slider("Left widthSpan", $span, min: 1, max: 11, step: 1),
64
+ .checkbox("useMargin", $useMargin),
65
+ ]
66
+ )
81
67
  }
82
68
  }
83
69
 
84
70
  /// Filled placeholder so span widths are visible.
85
71
  private struct SectionTile: View {
86
72
  let label: String
87
-
88
- init(_ label: String) {
89
- self.label = label
90
- }
73
+ init(_ label: String) { self.label = label }
91
74
 
92
75
  var body: some View {
93
76
  Text(label)
@@ -2,31 +2,60 @@
2
2
  // SkeletonDemo.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
- public struct SkeletonDemo: View {
10
- public init() {}
11
+ struct SkeletonDemo: View {
12
+ var body: some View {
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { SkeletonPreview() }, playground: { SkeletonPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
11
20
 
12
- public var body: some View {
13
- VStack(alignment: .leading, spacing: 12) {
14
- Spacer().frame(height: 12)
21
+ // MARK: - Preview
15
22
 
16
- // Square skeleton (Compose: fillMaxWidth().aspectRatio(1f)).
23
+ private struct SkeletonPreview: View {
24
+ var body: some View {
25
+ BasicColumnBox("Square (aspect 1:1)", alignment: .leading) {
17
26
  Skeleton()
18
27
  .aspectRatio(1, contentMode: .fit)
19
28
  .frame(maxWidth: .infinity)
20
-
21
- // Fixed-height skeleton (Compose: fillMaxWidth().height(32.dp)).
29
+ }
30
+ BasicColumnBox("Fixed height (32)", alignment: .leading) {
22
31
  Skeleton()
23
32
  .frame(maxWidth: .infinity)
24
33
  .frame(height: 32)
25
34
  }
26
- .padding()
35
+ BasicColumnBox("Lines", alignment: .leading) {
36
+ Skeleton().frame(maxWidth: .infinity).frame(height: 16)
37
+ Skeleton().frame(maxWidth: .infinity).frame(height: 16)
38
+ Skeleton().frame(width: 160).frame(height: 16)
39
+ }
27
40
  }
28
41
  }
29
42
 
30
- #Preview {
31
- SkeletonDemo()
43
+ // MARK: - Playground
44
+
45
+ @available(iOS 16.0, *)
46
+ private struct SkeletonPlayground: View {
47
+ @State private var height: Double = 32
48
+
49
+ var body: some View {
50
+ PlaygroundTab(
51
+ component: {
52
+ Skeleton()
53
+ .frame(maxWidth: .infinity)
54
+ .frame(height: CGFloat(height))
55
+ },
56
+ params: [
57
+ .slider("Height", $height, min: 16, max: 200, step: 4),
58
+ ]
59
+ )
60
+ }
32
61
  }
@@ -2,149 +2,89 @@
2
2
  // SliderDemo.swift
3
3
  // Example
4
4
  //
5
+ // Preview + Playground demo for MomoSlider.
6
+ //
5
7
 
6
- import Foundation
7
8
  import MoMoUIKits
8
9
  import SwiftUI
9
10
 
10
- // MARK: - SliderDemo
11
-
12
11
  struct SliderDemo: View {
13
- // Playground state
14
- @State private var pgLow: CGFloat = 20
15
- @State private var pgHigh: CGFloat = 80
16
- @State private var pgDisableRange = false
17
- @State private var pgFloatingLabel = false
18
- @State private var pgDisabled = false
19
- @State private var pgMinRange = false
20
- @State private var pgStepBig = false
21
-
22
12
  var body: some View {
23
- ScrollView {
24
- VStack(alignment: .leading, spacing: 24) {
25
- preview
26
- Divider()
27
- playground
28
- }
29
- .padding(.vertical, 16)
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { SliderPreview() }, playground: { SliderPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
30
17
  }
31
18
  }
19
+ }
32
20
 
33
- // MARK: - Preview
34
-
35
- private var preview: some View {
36
- VStack(alignment: .leading, spacing: 24) {
37
- section("Range Slider (default)") {
38
- MomoSlider(min: 0, max: 100, step: 1)
39
- .padding(.horizontal, 8)
40
- }
41
-
42
- section("Range Slider with initial values") {
43
- MomoSlider(min: 0, max: 100, step: 1, low: 20, high: 80)
44
- .padding(.horizontal, 8)
45
- }
46
-
47
- section("Single-thumb Slider (disableRange)") {
48
- MomoSlider(min: 0, max: 100, step: 1, low: 40, disableRange: true)
49
- .padding(.horizontal, 8)
50
- }
51
-
52
- section("Slider with step = 10") {
53
- MomoSlider(min: 0, max: 100, step: 10, low: 20, high: 70)
54
- .padding(.horizontal, 8)
55
- }
56
-
57
- section("Slider with minRange = 20") {
58
- MomoSlider(min: 0, max: 100, step: 1, low: 10, high: 90, minRange: 20)
59
- .padding(.horizontal, 8)
60
- }
61
-
62
- section("Floating Label") {
63
- MomoSlider(min: 0, max: 100, step: 1, low: 30, high: 70, floatingLabel: true)
64
- .padding(.horizontal, 8)
65
- }
66
-
67
- section("Disabled") {
68
- MomoSlider(min: 0, max: 100, step: 1, low: 30, high: 70, disabled: true)
69
- .padding(.horizontal, 8)
70
- }
21
+ // MARK: - Preview
71
22
 
72
- section("Disabled single-thumb") {
73
- MomoSlider(min: 0, max: 100, step: 1, low: 50, disableRange: true, disabled: true)
74
- .padding(.horizontal, 8)
75
- }
23
+ private struct SliderPreview: View {
24
+ var body: some View {
25
+ BasicColumnBox("Range Slider (default)", alignment: .leading) {
26
+ MomoSlider(min: 0, max: 100, step: 1)
76
27
  }
77
- }
78
-
79
- // MARK: - Playground
80
-
81
- private var playground: some View {
82
- section("Playground") {
83
- toggle("Disable Range (single thumb)", $pgDisableRange)
84
- toggle("Floating Label", $pgFloatingLabel)
85
- toggle("Disabled", $pgDisabled)
86
- toggle("Min Range = 20", $pgMinRange)
87
- toggle("Step = 10 (instead of 1)", $pgStepBig)
88
-
89
- MomoSlider(
90
- min: 0,
91
- max: 100,
92
- step: pgStepBig ? 10 : 1,
93
- low: pgLow,
94
- high: pgHigh,
95
- minRange: pgMinRange ? 20 : 0,
96
- disableRange: pgDisableRange,
97
- floatingLabel: pgFloatingLabel,
98
- disabled: pgDisabled,
99
- onValueChanged: { low, high, _ in
100
- pgLow = low
101
- pgHigh = high
102
- }
103
- )
104
- .padding(.horizontal, 8)
105
- // Re-create slider when structural params change so initial values apply.
106
- .id("\(pgDisableRange)-\(pgMinRange)-\(pgStepBig)")
107
-
108
- if pgDisableRange {
109
- Text("Value: \(Int(pgLow))")
110
- .font(.subheadline)
111
- .padding(.top, 8)
112
- } else {
113
- Text("Low: \(Int(pgLow)) · High: \(Int(pgHigh))")
114
- .font(.subheadline)
115
- .padding(.top, 8)
116
- }
28
+ BasicColumnBox("With initial values", alignment: .leading) {
29
+ MomoSlider(min: 0, max: 100, step: 1, low: 20, high: 80)
117
30
  }
118
- }
119
-
120
- // MARK: - Helpers
121
-
122
- @ViewBuilder
123
- private func section<Content: View>(
124
- _ title: String,
125
- @ViewBuilder content: () -> Content
126
- ) -> some View {
127
- VStack(alignment: .leading, spacing: 12) {
128
- Text(title)
129
- .font(.headline)
130
- content()
31
+ BasicColumnBox("Single-thumb (disableRange)", alignment: .leading) {
32
+ MomoSlider(min: 0, max: 100, step: 1, low: 40, disableRange: true)
131
33
  }
132
- .padding(.horizontal, 16)
133
- }
134
-
135
- @ViewBuilder
136
- private func toggle(_ title: String, _ binding: Binding<Bool>) -> some View {
137
- Toggle(isOn: binding) {
138
- Text(title)
139
- .font(.subheadline)
34
+ BasicColumnBox("Step = 10", alignment: .leading) {
35
+ MomoSlider(min: 0, max: 100, step: 10, low: 20, high: 70)
36
+ }
37
+ BasicColumnBox("Min range = 20", alignment: .leading) {
38
+ MomoSlider(min: 0, max: 100, step: 1, low: 10, high: 90, minRange: 20)
39
+ }
40
+ BasicColumnBox("Floating Label", alignment: .leading) {
41
+ MomoSlider(min: 0, max: 100, step: 1, low: 30, high: 70, floatingLabel: true)
42
+ }
43
+ BasicColumnBox("Disabled", alignment: .leading) {
44
+ MomoSlider(min: 0, max: 100, step: 1, low: 30, high: 70, disabled: true)
140
45
  }
141
46
  }
142
47
  }
143
48
 
144
- #if DEBUG
145
- struct SliderDemo_Previews: PreviewProvider {
146
- static var previews: some View {
147
- SliderDemo()
49
+ // MARK: - Playground
50
+
51
+ @available(iOS 16.0, *)
52
+ private struct SliderPlayground: View {
53
+ @State private var low: Double = 20
54
+ @State private var high: Double = 80
55
+ @State private var minRange: Double = 0
56
+ @State private var step: Double = 1
57
+ @State private var disableRange = false
58
+ @State private var floatingLabel = false
59
+ @State private var disabled = false
60
+
61
+ var body: some View {
62
+ PlaygroundTab(
63
+ component: {
64
+ MomoSlider(
65
+ min: 0,
66
+ max: 100,
67
+ step: CGFloat(step),
68
+ low: CGFloat(low),
69
+ high: CGFloat(high),
70
+ minRange: CGFloat(minRange),
71
+ disableRange: disableRange,
72
+ floatingLabel: floatingLabel,
73
+ disabled: disabled,
74
+ onValueChanged: { l, h, _ in low = Double(l); high = Double(h) }
75
+ )
76
+ // Re-seed when structural params change so initial values apply.
77
+ .id("\(disableRange)-\(minRange)-\(step)")
78
+ },
79
+ params: [
80
+ .checkbox("DisableRange", $disableRange),
81
+ .checkbox("FloatingLabel", $floatingLabel),
82
+ .checkbox("Disabled", $disabled),
83
+ .slider("Low", $low, min: 0, max: 100, step: 1),
84
+ .slider("High", $high, min: 0, max: 100, step: 1),
85
+ .slider("MinRange", $minRange, min: 0, max: 40, step: 5),
86
+ .slider("Step", $step, min: 1, max: 10, step: 1),
87
+ ]
88
+ )
148
89
  }
149
90
  }
150
- #endif