@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
@@ -13,11 +13,16 @@ public struct ScreenUsage: Hashable, Identifiable {
13
13
  public let title: String
14
14
  public let destination: AnyView
15
15
  public let icon: String
16
-
17
- public init(title: String, destination: AnyView, icon: String) {
16
+ /// True when the destination hosts its own chrome (e.g. a `BottomTab` — the
17
+ /// Preview/Playground `DemoScreen` or `BottomTabDemo`); such screens are pushed
18
+ /// with `headerType: .none, scrollable: false`.
19
+ public let hostsOwnChrome: Bool
20
+
21
+ public init(title: String, destination: AnyView, icon: String, hostsOwnChrome: Bool = false) {
18
22
  self.title = title
19
23
  self.destination = destination
20
24
  self.icon = icon
25
+ self.hostsOwnChrome = hostsOwnChrome
21
26
  }
22
27
 
23
28
  public static func == (lhs: ScreenUsage, rhs: ScreenUsage) -> Bool {
@@ -34,59 +39,51 @@ public func getIcon(icon: String) -> String {
34
39
  }
35
40
 
36
41
  public let ScreenUsages: [ScreenUsage] = [
37
- // ScreenUsage(title: "ScreenUsage", destination: AnyView(ContentView()), icon: getIcon(icon: "Layout")),
38
- ScreenUsage(title: "Badge", destination: AnyView(BadgeDemo()), icon: getIcon(icon: "Badge")),
39
- ScreenUsage(title: "Button", destination: AnyView(ButtonDemo()), icon: getIcon(icon: "Button")),
40
- ScreenUsage(title: "CheckBox", destination: AnyView(CheckboxDemo()), icon: getIcon(icon: "Checkbox")),
41
- ScreenUsage(title: "Chip", destination: AnyView(ChipDemo()), icon: getIcon(icon: "Chip")),
42
- // ScreenUsage(title: "IconButton", destination: AnyView(ContentView()), icon: getIcon(icon: "Button")),
43
- // ScreenUsage(title: "Icon", destination: AnyView(ContentView()), icon: getIcon(icon: "Icon")),
44
- ScreenUsage(title: "Image", destination: AnyView(ImageDemo()), icon: getIcon(icon: "Layout")),
45
- ScreenUsage(title: "Baseline View", destination: AnyView(BaselineViewDemo()), icon: getIcon(icon: "Layout")),
46
- // ScreenUsage(title: "InputMoney", destination: AnyView(ContentView()), icon: getIcon(icon: "FormInput")),
47
- ScreenUsage(title: "Input", destination: AnyView(InputDemo()), icon: getIcon(icon: "FormInput")),
48
- ScreenUsage(title: "Input Phone Number", destination: AnyView(InputPhoneNumberDemo()), icon: getIcon(icon: "FormInput")),
49
- ScreenUsage(title: "InputTextArea", destination: AnyView(InputTextAreaDemo()), icon: getIcon(icon: "FormInput")),
50
- ScreenUsage(title: "InputSearch", destination: AnyView(InputSearchDemo()), icon: getIcon(icon: "FormInput")),
51
- // ScreenUsage(title: "Pagination", destination: AnyView(ContentView()), icon: getIcon(icon: "Badge")),
52
- // ScreenUsage(title: "InputDropdown", destination: AnyView(ContentView()), icon: getIcon(icon: "FormInput")),
53
- ScreenUsage(title: "PopupNotify", destination: AnyView(PopupNotifyDemo()), icon: getIcon(icon: "Popup")),
54
- ScreenUsage(title: "PopupPromotion", destination: AnyView(PopupPromotionDemo()), icon: getIcon(icon: "Popup")),
55
- ScreenUsage(title: "SnackBar", destination: AnyView(SnackBarDemo()), icon: getIcon(icon: "Popup")),
56
- // ScreenUsage(title: "Radio", destination: AnyView(ContentView()), icon: getIcon(icon: "Radio")),
57
- // ScreenUsage(title: "Skeleton", destination: AnyView(ContentView()), icon: getIcon(icon: "Skeleton")),
58
- ScreenUsage(title: "Switch", destination: AnyView(SwitchDemo()), icon: getIcon(icon: "Toggle")),
59
- // ScreenUsage(title: "Tag", destination: AnyView(ContentView()), icon: getIcon(icon: "Skeleton")),
60
- ScreenUsage(title: "Text", destination: AnyView(TypographyDemo()), icon: getIcon(icon: "Typography")),
42
+ ScreenUsage(title: "Badge", destination: AnyView(BadgeDemo()), icon: getIcon(icon: "Badge"), hostsOwnChrome: true),
43
+ ScreenUsage(title: "Button", destination: AnyView(ButtonDemo()), icon: getIcon(icon: "Button"), hostsOwnChrome: true),
44
+ ScreenUsage(title: "CheckBox", destination: AnyView(CheckboxDemo()), icon: getIcon(icon: "Checkbox"), hostsOwnChrome: true),
45
+ ScreenUsage(title: "Chip", destination: AnyView(ChipDemo()), icon: getIcon(icon: "Chip"), hostsOwnChrome: true),
46
+ ScreenUsage(title: "Icon", destination: AnyView(IconDemo()), icon: getIcon(icon: "Icon"), hostsOwnChrome: true),
47
+ ScreenUsage(title: "Image", destination: AnyView(ImageDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
48
+ ScreenUsage(title: "Section", destination: AnyView(SectionDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
49
+ ScreenUsage(title: "Input", destination: AnyView(InputDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
50
+ ScreenUsage(title: "Input Phone Number", destination: AnyView(InputPhoneNumberDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
51
+ ScreenUsage(title: "InputTextArea", destination: AnyView(InputTextAreaDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
52
+ ScreenUsage(title: "InputSearch", destination: AnyView(InputSearchDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
53
+ ScreenUsage(title: "PopupNotify", destination: AnyView(PopupNotifyDemo()), icon: getIcon(icon: "Popup"), hostsOwnChrome: true),
54
+ ScreenUsage(title: "PopupPromotion", destination: AnyView(PopupPromotionDemo()), icon: getIcon(icon: "Popup"), hostsOwnChrome: true),
55
+ ScreenUsage(title: "SnackBar", destination: AnyView(SnackBarDemo()), icon: getIcon(icon: "Popup"), hostsOwnChrome: true),
56
+ ScreenUsage(title: "Switch", destination: AnyView(SwitchDemo()), icon: getIcon(icon: "Toggle"), hostsOwnChrome: true),
57
+ ScreenUsage(title: "Text", destination: AnyView(TypographyDemo()), icon: getIcon(icon: "Typography"), hostsOwnChrome: true),
61
58
  // ScreenUsage(title: "TrustBanner", destination: AnyView(TrustBanner(onPress: {_ in })), icon: getIcon(icon: "Typography")),
62
- ScreenUsage(title: "Information", destination: AnyView(InformationDemo()), icon: getIcon(icon: "Typography")),
63
- ScreenUsage(title: "Avatar", destination: AnyView(AvatarDemo()), icon: getIcon(icon: "Avatar")),
64
- ScreenUsage(title: "Carousel", destination: AnyView(CarouselDemo()), icon: getIcon(icon: "Carousel")),
65
- ScreenUsage(title: "Divider", destination: AnyView(DividerDemo()), icon: getIcon(icon: "Divider")),
66
- ScreenUsage(title: "IconButton", destination: AnyView(IconButtonDemo()), icon: getIcon(icon: "Button")),
67
- ScreenUsage(title: "Loader", destination: AnyView(LoaderDemo()), icon: getIcon(icon: "Loader")),
68
- ScreenUsage(title: "Pagination", destination: AnyView(PaginationDemo()), icon: getIcon(icon: "Badge")),
69
- ScreenUsage(title: "Radio", destination: AnyView(RadioDemo()), icon: getIcon(icon: "Radio")),
70
- ScreenUsage(title: "Rating", destination: AnyView(RatingDemo()), icon: getIcon(icon: "Rating")),
71
- ScreenUsage(title: "Skeleton", destination: AnyView(SkeletonDemo()), icon: getIcon(icon: "Skeleton")),
72
- ScreenUsage(title: "SuggestAction", destination: AnyView(SuggestActionDemo()), icon: getIcon(icon: "Information")),
73
- ScreenUsage(title: "Tag", destination: AnyView(TagDemo()), icon: getIcon(icon: "Tag")),
74
- ScreenUsage(title: "Title", destination: AnyView(TitleDemo()), icon: getIcon(icon: "Typography")),
75
- ScreenUsage(title: "Collapse", destination: AnyView(CollapseDemo()), icon: getIcon(icon: "Layout")),
76
- ScreenUsage(title: "Stepper", destination: AnyView(StepperDemo()), icon: getIcon(icon: "Layout")),
77
- ScreenUsage(title: "Uploader", destination: AnyView(UploaderDemo()), icon: getIcon(icon: "FormInput")),
78
- ScreenUsage(title: "Swipe", destination: AnyView(SwipeDemo()), icon: getIcon(icon: "Layout")),
79
- ScreenUsage(title: "InputDropDown", destination: AnyView(InputDropDownDemo()), icon: getIcon(icon: "FormInput")),
80
- ScreenUsage(title: "InputMoney", destination: AnyView(InputMoneyDemo()), icon: getIcon(icon: "FormInput")),
81
- ScreenUsage(title: "InputOTP", destination: AnyView(InputOTPDemo()), icon: getIcon(icon: "FormInput")),
82
- ScreenUsage(title: "ProgressInfo", destination: AnyView(ProgressInfoDemo()), icon: getIcon(icon: "Layout")),
83
- ScreenUsage(title: "Steps", destination: AnyView(StepsDemo()), icon: getIcon(icon: "Layout")),
84
- ScreenUsage(title: "Slider", destination: AnyView(SliderDemo()), icon: getIcon(icon: "Layout")),
85
- ScreenUsage(title: "TabView", destination: AnyView(TabViewDemo()), icon: getIcon(icon: "Layout")),
86
- ScreenUsage(title: "Tooltip", destination: AnyView(TooltipDemo()), icon: getIcon(icon: "Layout")),
87
- ScreenUsage(title: "DateTimePicker", destination: AnyView(DateTimePickerDemo()), icon: getIcon(icon: "Layout")),
59
+ ScreenUsage(title: "Information", destination: AnyView(InformationDemo()), icon: getIcon(icon: "Typography"), hostsOwnChrome: true),
60
+ ScreenUsage(title: "Avatar", destination: AnyView(AvatarDemo()), icon: getIcon(icon: "Avatar"), hostsOwnChrome: true),
61
+ ScreenUsage(title: "Carousel", destination: AnyView(CarouselDemo()), icon: getIcon(icon: "Carousel"), hostsOwnChrome: true),
62
+ ScreenUsage(title: "Divider", destination: AnyView(DividerDemo()), icon: getIcon(icon: "Divider"), hostsOwnChrome: true),
63
+ ScreenUsage(title: "IconButton", destination: AnyView(IconButtonDemo()), icon: getIcon(icon: "Button"), hostsOwnChrome: true),
64
+ ScreenUsage(title: "Loader", destination: AnyView(LoaderDemo()), icon: getIcon(icon: "Loader"), hostsOwnChrome: true),
65
+ ScreenUsage(title: "Pagination", destination: AnyView(PaginationDemo()), icon: getIcon(icon: "Badge"), hostsOwnChrome: true),
66
+ ScreenUsage(title: "Radio", destination: AnyView(RadioDemo()), icon: getIcon(icon: "Radio"), hostsOwnChrome: true),
67
+ ScreenUsage(title: "Rating", destination: AnyView(RatingDemo()), icon: getIcon(icon: "Rating"), hostsOwnChrome: true),
68
+ ScreenUsage(title: "Skeleton", destination: AnyView(SkeletonDemo()), icon: getIcon(icon: "Skeleton"), hostsOwnChrome: true),
69
+ ScreenUsage(title: "SuggestAction", destination: AnyView(SuggestActionDemo()), icon: getIcon(icon: "Information"), hostsOwnChrome: true),
70
+ ScreenUsage(title: "Tag", destination: AnyView(TagDemo()), icon: getIcon(icon: "Tag"), hostsOwnChrome: true),
71
+ ScreenUsage(title: "Title", destination: AnyView(TitleDemo()), icon: getIcon(icon: "Typography"), hostsOwnChrome: true),
72
+ ScreenUsage(title: "Collapse", destination: AnyView(CollapseDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
73
+ ScreenUsage(title: "Stepper", destination: AnyView(StepperDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
74
+ ScreenUsage(title: "Uploader", destination: AnyView(UploaderDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
75
+ ScreenUsage(title: "Swipe", destination: AnyView(SwipeDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
76
+ ScreenUsage(title: "InputDropDown", destination: AnyView(InputDropDownDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
77
+ ScreenUsage(title: "InputMoney", destination: AnyView(InputMoneyDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
78
+ ScreenUsage(title: "InputOTP", destination: AnyView(InputOTPDemo()), icon: getIcon(icon: "FormInput"), hostsOwnChrome: true),
79
+ ScreenUsage(title: "ProgressInfo", destination: AnyView(ProgressInfoDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
80
+ ScreenUsage(title: "Steps", destination: AnyView(StepsDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
81
+ ScreenUsage(title: "Slider", destination: AnyView(SliderDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
82
+ ScreenUsage(title: "TabView", destination: AnyView(TabViewDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
83
+ ScreenUsage(title: "Tooltip", destination: AnyView(TooltipDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
84
+ ScreenUsage(title: "DateTimePicker", destination: AnyView(DateTimePickerDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
88
85
  ScreenUsage(title: "Navigation", destination: AnyView(NavigationDemo()), icon: getIcon(icon: "Layout")),
89
- ScreenUsage(title: "Bottom Tab", destination: AnyView(BottomTabDemo()), icon: getIcon(icon: "Layout")),
86
+ ScreenUsage(title: "Bottom Tab", destination: AnyView(BottomTabDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
90
87
  ScreenUsage(title: "Animated Header", destination: AnyView(AnimatedHeaderDemo()), icon: getIcon(icon: "Layout")),
91
88
  ScreenUsage(title: "Theme", destination: AnyView(ThemeDemo()), icon: getIcon(icon: "Typography")),
92
89
  ScreenUsage(title: "Localize", destination: AnyView(LocalizeDemo()), icon: getIcon(icon: "Typography")),
@@ -134,11 +131,11 @@ public struct HomeView: View {
134
131
  headerRight: {
135
132
  HeaderRight(headerRight: HeaderRightData(useShortcut: true))
136
133
  },
137
- // footerComponent = { Button("Footer Button") }
134
+ // footerComponent = { Button("Open SwiftUI (iOS only)") }
138
135
  footer: {
139
136
  AnyView(
140
137
  MoMoUIKits.Button(
141
- title: "Footer Button",
138
+ title: "Open Compose",
142
139
  action: onOpenCompose,
143
140
  type: .primary,
144
141
  size: .large
@@ -240,7 +237,7 @@ public struct HomeItemView: View {
240
237
  public var body: some View {
241
238
  ForEach(screenUsages) { screenUsage in
242
239
  SwiftUI.Button {
243
- let options = screenUsage.title == "Bottom Tab"
240
+ let options = screenUsage.hostsOwnChrome
244
241
  ? NavigationOptions(
245
242
  title: screenUsage.title,
246
243
  headerType: .none,
@@ -267,7 +264,7 @@ public struct HomeItemView: View {
267
264
  Divider()
268
265
  }
269
266
  .padding(.horizontal, 16)
270
- .padding(.vertical, 8)
267
+ .padding(.vertical, 16)
271
268
  }
272
269
  }
273
270
 
@@ -1,58 +1,93 @@
1
+ //
2
+ // IconButtonDemo.swift
3
+ // Example
4
+ //
5
+ // Preview + Playground demo (DemoScreen pattern).
6
+ //
7
+
1
8
  import MoMoUIKits
2
9
  import SwiftUI
3
10
 
4
- // MARK: - IconButtonDemo
11
+ private let iconButtonSizeList: [PlaygroundOption] = [
12
+ .init("large", IconSize.large),
13
+ .init("medium", IconSize.medium),
14
+ .init("small", IconSize.small),
15
+ ]
16
+
17
+ private let iconShapeList: [PlaygroundOption] = [
18
+ .init("circle", IconShape.circle),
19
+ .init("square", IconShape.square),
20
+ ]
5
21
 
6
22
  struct IconButtonDemo: View {
7
23
  var body: some View {
8
- ScrollView {
9
- VStack(alignment: .leading, spacing: 24) {
10
- Group {
11
- Text("Source")
12
- .font(.headline)
13
- HStack(spacing: 12) {
14
- IconButton(icon: url, onClick: onPress, type: .primary)
15
- IconButton(icon: url2, onClick: onPress, type: .primary)
16
- IconButton(icon: url3, onClick: onPress, type: .primary)
17
- IconButton(icon: url4, onClick: onPress, type: .primary)
18
- }
19
- }
20
-
21
- Group {
22
- Text("Type")
23
- .font(.headline)
24
- HStack(spacing: 12) {
25
- IconButton(icon: url, onClick: onPress, type: .primary)
26
- IconButton(icon: url, onClick: onPress, type: .secondary)
27
- IconButton(icon: url, onClick: onPress, type: .tonal)
28
- IconButton(icon: url, onClick: onPress, type: .outline)
29
- IconButton(icon: url, onClick: onPress, type: .disabled)
30
- IconButton(icon: url, onClick: onPress, type: .danger)
31
- }
32
- }
33
-
34
- Group {
35
- Text("Size")
36
- .font(.headline)
37
- HStack(spacing: 12) {
38
- IconButton(icon: url, onClick: onPress, type: .primary, size: .large)
39
- IconButton(icon: url, onClick: onPress, type: .primary, size: .small)
40
- }
41
- }
42
- }
43
- .padding(16)
24
+ if #available(iOS 16.0, *) {
25
+ DemoScreen(preview: { IconButtonPreview() }, playground: { IconButtonPlayground() })
26
+ } else {
27
+ Text("Requires iOS 16+").padding()
44
28
  }
45
- .padding(.top)
46
29
  }
30
+ }
31
+
32
+ // MARK: - Preview
47
33
 
48
- func onPress() {
49
- print("IconButton")
34
+ private struct IconButtonPreview: View {
35
+ private let icon = "travel_plane"
36
+
37
+ var body: some View {
38
+ BasicColumnBox("Source", alignment: .leading) {
39
+ HStack(spacing: Spacing.M) {
40
+ IconButton(icon: "travel_plane", onClick: {})
41
+ IconButton(icon: "shopping_coupon", onClick: {})
42
+ IconButton(icon: "shopping_store", onClick: {})
43
+ IconButton(icon: "time_alarm_check", onClick: {})
44
+ }
45
+ }
46
+ BasicColumnBox("Type", alignment: .leading) {
47
+ HStack(spacing: Spacing.M) {
48
+ IconButton(icon: icon, onClick: {}, type: .primary)
49
+ IconButton(icon: icon, onClick: {}, type: .secondary)
50
+ IconButton(icon: icon, onClick: {}, type: .tonal)
51
+ IconButton(icon: icon, onClick: {}, type: .outline)
52
+ IconButton(icon: icon, onClick: {}, type: .disabled)
53
+ IconButton(icon: icon, onClick: {}, type: .danger)
54
+ }
55
+ }
56
+ BasicColumnBox("Size", alignment: .leading) {
57
+ HStack(spacing: Spacing.M) {
58
+ IconButton(icon: icon, onClick: {}, type: .primary, size: .large)
59
+ IconButton(icon: icon, onClick: {}, type: .primary, size: .small)
60
+ }
61
+ }
50
62
  }
63
+ }
64
+
65
+ // MARK: - Playground
51
66
 
52
- // MARK: Private
67
+ @available(iOS 16.0, *)
68
+ private struct IconButtonPlayground: View {
69
+ @State private var icon: PlaygroundOption? = playgroundIcons.first { $0.key == "basic_home" }
70
+ @State private var type: PlaygroundOption? = buttonTypeList.first { $0.key == "primary" }
71
+ @State private var size: PlaygroundOption? = iconButtonSizeList.first { $0.key == "small" }
72
+ @State private var shape: PlaygroundOption? = iconShapeList.first { $0.key == "circle" }
53
73
 
54
- private let url = "travel_plane"
55
- private let url2 = "shopping_coupon"
56
- private let url3 = "shopping_store"
57
- private let url4 = "time_alarm_check"
74
+ var body: some View {
75
+ PlaygroundTab(
76
+ component: {
77
+ IconButton(
78
+ icon: (icon?.value as? String) ?? "basic_home",
79
+ onClick: {},
80
+ type: (type?.value as? ButtonType) ?? .primary,
81
+ size: (size?.value as? IconSize) ?? .small,
82
+ shape: (shape?.value as? IconShape) ?? .circle
83
+ )
84
+ },
85
+ params: [
86
+ .option("Icon", playgroundIcons, $icon),
87
+ .radio("Type", buttonTypeList, $type),
88
+ .radio("Size", iconButtonSizeList, $size),
89
+ .radio("Shape", iconShapeList, $shape),
90
+ ]
91
+ )
92
+ }
58
93
  }
@@ -0,0 +1,81 @@
1
+ //
2
+ // IconDemo.swift
3
+ // Example
4
+ //
5
+ // Preview + Playground demo, mirroring Compose's IconUsage.kt.
6
+ //
7
+
8
+ import MoMoUIKits
9
+ import SwiftUI
10
+
11
+ struct IconDemo: View {
12
+ var body: some View {
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { IconPreview() }, playground: { IconPlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
17
+ }
18
+ }
19
+ }
20
+
21
+ // MARK: - Preview
22
+
23
+ private struct IconPreview: View {
24
+ var body: some View {
25
+ BasicColumnBox("Source", alignment: .leading) {
26
+ HStack(spacing: Spacing.M) {
27
+ Icon(source: "basic_home", size: 24)
28
+ Icon(source: "basic_flag", size: 24)
29
+ Icon(source: "basic_filter", size: 24)
30
+ Icon(source: "basic_delete", size: 24)
31
+ }
32
+ }
33
+ BasicColumnBox("Size", alignment: .leading) {
34
+ HStack(alignment: .center, spacing: Spacing.M) {
35
+ Icon(source: "basic_home", size: 16)
36
+ Icon(source: "basic_flag", size: 20)
37
+ Icon(source: "basic_filter", size: 24)
38
+ Icon(source: "basic_delete", size: 28)
39
+ }
40
+ }
41
+ BasicColumnBox("Color", alignment: .leading) {
42
+ HStack(spacing: Spacing.M) {
43
+ Icon(source: "basic_home", size: 24, color: Colors.red03)
44
+ Icon(source: "basic_flag", size: 24, color: Colors.green04)
45
+ Icon(source: "basic_filter", size: 24, color: Colors.pink06)
46
+ Icon(source: "basic_delete", size: 24, color: Colors.yellow02)
47
+ }
48
+ }
49
+ BasicColumnBox("No theme icon", alignment: .leading) {
50
+ HStack(spacing: Spacing.M) {
51
+ Icon(source: "ic_round_momo_tiny", size: 24)
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ // MARK: - Playground
58
+
59
+ @available(iOS 16.0, *)
60
+ private struct IconPlayground: View {
61
+ @State private var source: PlaygroundOption? = playgroundIcons.first { $0.key == "basic_home" }
62
+ @State private var color: PlaygroundOption? = playgroundColors.first { $0.key == "black17" }
63
+ @State private var size = "24"
64
+
65
+ var body: some View {
66
+ PlaygroundTab(
67
+ component: {
68
+ Icon(
69
+ source: (source?.value as? String) ?? "basic_home",
70
+ size: CGFloat(Int(size) ?? 24),
71
+ color: color?.value as? Color
72
+ )
73
+ },
74
+ params: [
75
+ .option("Source", playgroundIcons, $source),
76
+ .color("Color", playgroundColors, $color),
77
+ .number("Size (dp)", $size),
78
+ ]
79
+ )
80
+ }
81
+ }
@@ -2,77 +2,64 @@
2
2
  // ImageDemo.swift
3
3
  // Example
4
4
  //
5
- // Created by dung.pham2 on 2/12/24.
5
+ // Preview + Playground demo for ImageView.
6
6
  //
7
7
 
8
- import SwiftUI
9
8
  import MoMoUIKits
9
+ import SwiftUI
10
10
 
11
11
  struct ImageDemo: View {
12
- // MARK: - Properties
13
- @State private var time = 1000
14
-
15
- // MARK: - Body
16
12
  var body: some View {
17
- NavigationView {
18
- ScrollView {
19
- VStack(spacing: 16) { // Equivalent to Spacing.M
20
- HStack {
21
- ImageView("https://source.unsplash.com/random/\(time)")
22
- .frame(width: 100, height: 100)
23
-
24
- Spacer()
25
-
26
- ImageView("https://abc.com")
27
- .frame(width: 100, height: 100)
28
- }
29
-
30
- ImageView("https://source.unsplash.com/random/\(time)")
31
- .frame(maxWidth: .infinity)
32
- .frame(height: 100)
33
- .aspectRatio(contentMode: .fill)
34
- .clipped()
35
-
36
- ImageView("https://images.unsplash.com/photo-1509395062183-67c5ad6faff9")
37
- .frame(maxWidth: .infinity)
38
- .frame(height: 100)
39
- .aspectRatio(contentMode: .fill)
40
- .clipped()
41
-
42
- ImageView("https://source.unsplash.com/random/\(time)")
43
- .frame(maxWidth: .infinity)
44
- .frame(height: 100)
45
- .aspectRatio(contentMode: .fill)
46
- .clipped()
47
-
48
- ImageView("https://source.unsplash.com/random/\(time)")
49
- .frame(maxWidth: .infinity)
50
- .frame(height: 100)
51
- .aspectRatio(contentMode: .fit)
52
-
53
- ImageView("https://source.unsplash.com/random/\(time)")
54
- .frame(maxWidth: .infinity)
55
- .frame(height: 100)
56
- .aspectRatio(contentMode: .fit)
57
-
58
- ImageView("https://source.unsplash.com/random/\(time)")
59
- .frame(maxWidth: .infinity)
60
- .frame(height: 100)
61
- .aspectRatio(contentMode: .fit)
62
- }
63
- .padding()
64
- }
65
- }
66
- .onAppear {
67
- startTimer()
13
+ if #available(iOS 16.0, *) {
14
+ DemoScreen(preview: { ImagePreview() }, playground: { ImagePlayground() })
15
+ } else {
16
+ Text("Requires iOS 16+").padding()
68
17
  }
69
18
  }
70
-
71
- // MARK: - Methods
72
- private func startTimer() {
73
- Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { _ in
74
- time = Int.random(in: 1...1000)
19
+ }
20
+
21
+ // MARK: - Preview
22
+
23
+ private struct ImagePreview: View {
24
+ private let sample = "https://images.unsplash.com/photo-1509395062183-67c5ad6faff9"
25
+
26
+ var body: some View {
27
+ BasicColumnBox("Fixed size", alignment: .leading) {
28
+ ImageView(sample).frame(width: 100, height: 100)
29
+ }
30
+ BasicColumnBox("Fill width", alignment: .leading) {
31
+ ImageView(sample)
32
+ .frame(maxWidth: .infinity)
33
+ .frame(height: 120)
34
+ .aspectRatio(contentMode: .fill)
35
+ .clipped()
36
+ }
37
+ BasicColumnBox("Invalid URL (fallback)", alignment: .leading) {
38
+ ImageView("https://abc.com").frame(width: 100, height: 100)
75
39
  }
76
40
  }
77
41
  }
78
42
 
43
+ // MARK: - Playground
44
+
45
+ @available(iOS 16.0, *)
46
+ private struct ImagePlayground: View {
47
+ @State private var url = "https://images.unsplash.com/photo-1509395062183-67c5ad6faff9"
48
+ @State private var height: Double = 120
49
+
50
+ var body: some View {
51
+ PlaygroundTab(
52
+ component: {
53
+ ImageView(url)
54
+ .frame(maxWidth: .infinity)
55
+ .frame(height: CGFloat(height))
56
+ .aspectRatio(contentMode: .fill)
57
+ .clipped()
58
+ },
59
+ params: [
60
+ .string("URL", $url),
61
+ .slider("Height", $height, min: 60, max: 240, step: 10),
62
+ ]
63
+ )
64
+ }
65
+ }