@momo-kits/native-kits 0.162.21 → 0.162.22-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 (186) hide show
  1. package/build.gradle.kts +11 -0
  2. package/compose/build.gradle.kts +190 -0
  3. package/compose/build.gradle.kts.backup +190 -0
  4. package/compose/compose.podspec +47 -0
  5. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +123 -0
  8. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  9. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  10. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  11. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +106 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +294 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +826 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +82 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +356 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +543 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +76 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +112 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +477 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +214 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +216 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +259 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +182 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +328 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +323 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +217 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +199 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +470 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +131 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +203 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +498 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +175 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +234 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +306 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +188 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +276 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +2 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +35 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +2 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +253 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +129 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +100 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +172 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +360 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +581 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +156 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +320 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +81 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +309 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +34 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +360 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +128 -0
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +70 -0
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +58 -0
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +105 -0
  131. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +32 -0
  132. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  133. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +184 -0
  134. package/gradle/libs.versions.toml +69 -0
  135. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  136. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  137. package/gradle.properties +26 -0
  138. package/gradlew +252 -0
  139. package/gradlew.bat +94 -0
  140. package/ios/Application/ApplicationEnvironment.swift +4 -2
  141. package/ios/Application/MaxApi.swift +18 -0
  142. package/ios/Application/Navigation/NavigationContainer.swift +21 -3
  143. package/ios/Application/Navigation/Navigator.swift +50 -29
  144. package/ios/Application/Navigation/Overplay/ModalScreen.swift +6 -0
  145. package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
  146. package/ios/Application/StackScreen.swift +41 -0
  147. package/ios/Badge/BadgeRibbon.swift +80 -0
  148. package/ios/Button/Button.swift +67 -11
  149. package/ios/Carousel/Carousel.swift +16 -1
  150. package/ios/Checkbox/Checkbox.swift +14 -20
  151. package/ios/Chip/Chip.swift +35 -26
  152. package/ios/Collapse/Collapse.swift +11 -1
  153. package/ios/DateTimePicker/DateTimePicker.swift +4 -2
  154. package/ios/DateTimePicker/WheelPicker.swift +7 -3
  155. package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
  156. package/ios/Icon/Icon.swift +5 -1
  157. package/ios/IconButton/IconButton.swift +35 -7
  158. package/ios/Image/Image.swift +16 -3
  159. package/ios/Information/Information.swift +3 -1
  160. package/ios/Input/ErrorView.swift +3 -1
  161. package/ios/Input/Input.swift +31 -8
  162. package/ios/Input/InputPhoneNumber.swift +14 -3
  163. package/ios/Input/InputSearch.swift +7 -1
  164. package/ios/Input/InputTextArea.swift +78 -34
  165. package/ios/InputDropDown/InputDropDown.swift +4 -1
  166. package/ios/InputMoney/InputMoney.swift +16 -4
  167. package/ios/Popup/PopupDisplay.swift +3 -4
  168. package/ios/Popup/PopupNotify.swift +3 -4
  169. package/ios/Popup/PopupPromotion.swift +16 -8
  170. package/ios/ProgressInfo/ProgressInfo.swift +4 -2
  171. package/ios/Radio/Radio.swift +12 -13
  172. package/ios/Rating/Rating.swift +1 -1
  173. package/ios/Stepper/Stepper.swift +2 -2
  174. package/ios/Steps/Steps.swift +22 -6
  175. package/ios/SuggestAction/SuggestAction.swift +5 -3
  176. package/ios/Swipeable/SwipeCell.swift +5 -3
  177. package/ios/Switch/Switch.swift +53 -28
  178. package/ios/TabView/TabView.swift +18 -14
  179. package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
  180. package/ios/Tooltip/Tooltip.swift +3 -0
  181. package/ios/Uploader/Uploader.swift +0 -9
  182. package/ios/native-kits.podspec +1 -1
  183. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  184. package/ios-demo/README.md +120 -0
  185. package/package.json +1 -1
  186. package/settings.gradle.kts +64 -0
@@ -2,6 +2,8 @@ import SwiftUI
2
2
  import SDWebImageSwiftUI
3
3
 
4
4
  public struct PopupPromotion: View {
5
+ @Environment(\.appTheme) private var theme
6
+
5
7
  var imageUrl: String
6
8
  var onIconClose: (() -> Void)?
7
9
  var onAction: (() -> Void)?
@@ -18,21 +20,26 @@ public struct PopupPromotion: View {
18
20
  }
19
21
 
20
22
  public var body: some View {
23
+ // Mirrors Kotlin's `Modifier.fillMaxWidth().aspectRatio(0.72f)` box with
24
+ // `ContentScale.FillBounds` inside it: a fixed-ratio frame the image stretches
25
+ // to exactly fill (no `.aspectRatio` modifier on the image itself, unlike the
26
+ // previous `.fit`, which letterboxed instead of stretching).
27
+ let boxWidth = UIScreen.main.bounds.width - Spacing.XL * 2
28
+ let boxHeight = boxWidth / 0.72
29
+
21
30
  VStack(spacing: 8) {
22
31
  if(imageUrl.isEmpty) {
23
- Icon(source: "media_fail", size: UIScreen.main.bounds.width - Spacing.XL * 2)
32
+ Icon(source: "media_fail", size: boxWidth)
24
33
  }
25
34
  else {
26
35
  WebImage(url: URL(string: imageUrl)!)
27
36
  .resizable()
28
37
  .placeholder {
29
38
  Color.gray
30
- .aspectRatio(0.72, contentMode: .fit)
31
- .frame(maxWidth: UIScreen.main.bounds.width - Spacing.XL * 2)
39
+ .frame(width: boxWidth, height: boxHeight)
32
40
  .clipped()
33
41
  }
34
- .aspectRatio(0.72, contentMode: .fit)
35
- .frame(maxWidth: UIScreen.main.bounds.width - Spacing.XL * 2, alignment: .center)
42
+ .frame(width: boxWidth, height: boxHeight, alignment: .center)
36
43
  .clipped()
37
44
  .onTapGesture {
38
45
  onAction?()
@@ -53,16 +60,17 @@ public struct PopupPromotion: View {
53
60
  }) {
54
61
  ZStack {
55
62
  Circle()
56
- .strokeBorder(Colors.black01, lineWidth: 2)
57
- .background(Circle().fill(Colors.black17))
63
+ .strokeBorder(theme.colors.background.surface, lineWidth: 2)
64
+ .background(Circle().fill(theme.colors.text.default))
58
65
  .frame(width: 22, height: 22)
59
66
 
60
- Icon(source: "navigation_close", size: 16, color: Colors.black01)
67
+ Icon(source: "navigation_close", size: 16, color: theme.colors.background.surface)
61
68
  }
62
69
  .frame(width: 40, height: 40)
63
70
  .padding(8)
64
71
  .zIndex(1)
65
72
  }
73
+ .buttonStyle(.plain)
66
74
  }
67
75
  }
68
76
 
@@ -97,7 +97,7 @@ public struct ProgressInfo: View {
97
97
  // MARK: - Tokens
98
98
 
99
99
  private let progressInfoLineColor = Colors.pink08
100
- private let progressInfoAccentColor = Color(hex: "a50064") // pink_MoMo_Branding
100
+ private let progressInfoAccentColor = Colors.pinkMoMoBranding
101
101
 
102
102
  // MARK: - Horizontal variant
103
103
 
@@ -196,6 +196,8 @@ private struct ProgressInfoHorizontal: View {
196
196
  // MARK: - Vertical variant
197
197
 
198
198
  private struct ProgressInfoVertical: View {
199
+ @Environment(\.appTheme) private var theme
200
+
199
201
  let steps: [ProgressInfoItem]
200
202
  let size: ProgressInfoSize
201
203
  let useNumber: Bool
@@ -218,7 +220,7 @@ private struct ProgressInfoVertical: View {
218
220
  )
219
221
  if !isLast {
220
222
  Rectangle()
221
- .fill(Colors.primary.opacity(0.2))
223
+ .fill(theme.colors.primary.opacity(0.2))
222
224
  .frame(width: 2)
223
225
  .frame(maxHeight: .infinity)
224
226
  }
@@ -34,22 +34,21 @@ public struct Radio: View {
34
34
  }
35
35
 
36
36
  public var body: some View {
37
- HStack(spacing: 0) {
38
- RoundedRectangle(cornerRadius: Radius.M)
39
- .stroke(borderColor, lineWidth: borderWidth)
40
- .frame(width: 20, height: 20)
41
- .padding(.trailing, label.isEmpty ? 0 : Spacing.XS)
37
+ SwiftUI.Button(action: onTap) {
38
+ HStack(spacing: 0) {
39
+ RoundedRectangle(cornerRadius: Radius.M)
40
+ .stroke(borderColor, lineWidth: borderWidth)
41
+ .frame(width: 20, height: 20)
42
+ .padding(.trailing, label.isEmpty ? 0 : Spacing.XS)
42
43
 
43
- if !label.isEmpty {
44
- MomoText(label, typography: .descriptionDefaultRegular)
45
- }
46
- }
47
- .contentShape(Rectangle())
48
- .onTapGesture {
49
- if !disabled {
50
- onTap()
44
+ if !label.isEmpty {
45
+ MomoText(label, typography: .descriptionDefaultRegular)
46
+ }
51
47
  }
48
+ .contentShape(Rectangle())
52
49
  }
50
+ .buttonStyle(ActiveOpacityButtonStyle())
51
+ .disabled(disabled)
53
52
  }
54
53
 
55
54
  private var borderWidth: CGFloat {
@@ -52,7 +52,7 @@ public struct Rating: View {
52
52
  SwiftUI.Button(action: { onRatingChange(index + 1) }) {
53
53
  icon
54
54
  }
55
- .buttonStyle(.plain)
55
+ .buttonStyle(ActiveOpacityButtonStyle())
56
56
  } else {
57
57
  icon
58
58
  }
@@ -70,14 +70,14 @@ private struct StepperButton: View {
70
70
  let iconColor: Color = disabled ? theme.colors.text.disable : theme.colors.primary
71
71
  let iconName = sign == "-" ? "24_navigation_minus_circle" : "24_navigation_plus_circle"
72
72
 
73
- SwiftUI.Button(action: { if !disabled { onPress() } }) {
73
+ SwiftUI.Button(action: onPress) {
74
74
  ZStack {
75
75
  Circle().fill(theme.colors.background.disable)
76
76
  Icon(source: iconName, size: specs.iconSize, color: iconColor)
77
77
  }
78
78
  .frame(width: specs.buttonSize, height: specs.buttonSize)
79
79
  }
80
- .buttonStyle(.plain)
80
+ .buttonStyle(ActiveOpacityButtonStyle())
81
81
  .disabled(disabled)
82
82
  }
83
83
  }
@@ -201,7 +201,7 @@ private struct StepsHorizontal: View {
201
201
 
202
202
  let clickable = status == .completed && onPress != nil && !disabled
203
203
 
204
- VStack(alignment: colAlignment, spacing: 0) {
204
+ let columnBody = VStack(alignment: colAlignment, spacing: 0) {
205
205
  if let time = item.time, !time.isEmpty {
206
206
  MomoText(time, typography: .descriptionXsRegular, color: subColor)
207
207
  .multilineTextAlignment(textAlignment)
@@ -250,8 +250,16 @@ private struct StepsHorizontal: View {
250
250
  }
251
251
  }
252
252
  .contentShape(Rectangle())
253
- .onTapGesture {
254
- if clickable { onPress?(item, index) }
253
+
254
+ if clickable {
255
+ // Mirrors Compose's `activeOpacityClickable` press feedback; non-clickable
256
+ // steps render with no press interaction at all.
257
+ SwiftUI.Button(action: { onPress?(item, index) }) {
258
+ columnBody
259
+ }
260
+ .buttonStyle(ActiveOpacityButtonStyle())
261
+ } else {
262
+ columnBody
255
263
  }
256
264
  }
257
265
 
@@ -338,7 +346,7 @@ private struct StepsVertical: View {
338
346
 
339
347
  let clickable = status == .completed && onPress != nil && !disabled
340
348
 
341
- HStack(alignment: .top, spacing: 0) {
349
+ let rowBody = HStack(alignment: .top, spacing: 0) {
342
350
  VStack(spacing: 0) {
343
351
  StepBubble(
344
352
  index: index,
@@ -380,8 +388,16 @@ private struct StepsVertical: View {
380
388
  }
381
389
  .frame(maxWidth: .infinity)
382
390
  .contentShape(Rectangle())
383
- .onTapGesture {
384
- if clickable { onPress?(item, index) }
391
+
392
+ if clickable {
393
+ // Mirrors Compose's `activeOpacityClickable` press feedback; non-clickable
394
+ // steps render with no press interaction at all.
395
+ SwiftUI.Button(action: { onPress?(item, index) }) {
396
+ rowBody
397
+ }
398
+ .buttonStyle(ActiveOpacityButtonStyle())
399
+ } else {
400
+ rowBody
385
401
  }
386
402
  }
387
403
  }
@@ -77,9 +77,11 @@ public struct SuggestAction: View {
77
77
 
78
78
  Spacer().frame(width: Spacing.S)
79
79
 
80
- Icon(source: "navigation_close", size: 24, color: theme.colors.text.default)
81
- .contentShape(Rectangle())
82
- .onTapGesture { onClose() }
80
+ SwiftUI.Button(action: onClose) {
81
+ Icon(source: "navigation_close", size: 24, color: theme.colors.text.default)
82
+ .contentShape(Rectangle())
83
+ }
84
+ .buttonStyle(ActiveOpacityButtonStyle())
83
85
  }
84
86
  .padding(Spacing.M)
85
87
  .frame(maxWidth: .infinity)
@@ -6,6 +6,8 @@ private let swipeActionWidth: CGFloat = 56
6
6
  // MARK: - Swipe
7
7
 
8
8
  public struct Swipe<Content: View>: View {
9
+ @Environment(\.appTheme) private var theme
10
+
9
11
  private let leftActions: [SwipeAction]
10
12
  private let rightActions: [SwipeAction]
11
13
  private let height: CGFloat
@@ -54,7 +56,7 @@ public struct Swipe<Content: View>: View {
54
56
  action: action,
55
57
  height: height,
56
58
  itemRadius: itemRadius,
57
- defaultBackgroundColor: Colors.primary
59
+ defaultBackgroundColor: theme.colors.primary
58
60
  )
59
61
  }
60
62
  Spacer(minLength: 0)
@@ -69,14 +71,14 @@ public struct Swipe<Content: View>: View {
69
71
  action: action,
70
72
  height: height,
71
73
  itemRadius: itemRadius,
72
- defaultBackgroundColor: Colors.error
74
+ defaultBackgroundColor: theme.colors.error.primary
73
75
  )
74
76
  }
75
77
  }
76
78
  }
77
79
 
78
80
  ZStack {
79
- Colors.card
81
+ theme.colors.background.surface
80
82
  content()
81
83
  }
82
84
  .frame(maxWidth: .infinity)
@@ -1,44 +1,69 @@
1
1
  import Foundation
2
2
  import SwiftUI
3
3
 
4
- public struct Switch: View{
4
+ public struct Switch: View {
5
5
  @Binding var value: Bool
6
6
  var disabled: Bool
7
- var onChange: ((Bool)->Void)?
8
-
9
- public init(_ value: Binding<Bool>,disabled: Bool = false, onChange: ((Bool)->Void)? = nil){
7
+ var onChange: ((Bool) -> Void)?
8
+ var title: String?
9
+ var accessibilityId: String?
10
+
11
+ public init(
12
+ _ value: Binding<Bool>,
13
+ disabled: Bool = false,
14
+ onChange: ((Bool) -> Void)? = nil,
15
+ title: String? = "",
16
+ accessibilityId: String? = ""
17
+ ) {
10
18
  self._value = value
11
19
  self.disabled = disabled
12
20
  self.onChange = onChange
21
+ self.title = title
22
+ self.accessibilityId = accessibilityId
23
+ }
24
+
25
+ // Mirrors Kotlin's `backgroundColor`: shared by the track AND the inner dot.
26
+ private var backgroundColor: Color {
27
+ switch (disabled, value) {
28
+ case (true, true): return Colors.green09
29
+ case (true, false): return Colors.black05
30
+ case (false, true): return Colors.green03
31
+ case (false, false): return Colors.black07
32
+ }
33
+ }
34
+
35
+ // Mirrors Kotlin's `circleBackgroundColor` (the outer 14pt thumb circle).
36
+ private var circleColor: Color {
37
+ value ? Colors.black01 : Colors.black03
13
38
  }
14
-
15
-
39
+
40
+ private var automationId: String {
41
+ accessibilityId?.isEmpty == false ? accessibilityId! : "toggle_\(title?.isEmpty == false ? title! : "unknown")_\(value)"
42
+ }
43
+
16
44
  public var body: some View {
17
45
  SwiftUI.Button(action: {
18
- withAnimation{
46
+ withAnimation {
19
47
  value.toggle()
20
48
  onChange?(value)
21
49
  }
22
- }){
23
- HStack{
24
- HStack {
25
- }
26
- .frame(width: 6, height: 6)
27
- .background(value ? Colors.pink03 : Colors.black07)
28
- .clipShape(Circle())
29
- .opacity(disabled ? 0.4 : 1)
30
- }
31
- .frame(width: 14, height: 14)
32
- .background(Colors.black01)
33
- .clipShape(Circle())
34
- .padding(.leading,5)
35
- .padding(.trailing,5)
36
-
37
- }
38
- .disabled(disabled)
39
- .frame(width: 40, height: 24, alignment: value == true ? .trailing : .leading)
40
- .background(value ? Colors.pink03 : Colors.black07)
41
- .clipShape(Capsule())
42
- .opacity(disabled ? 0.4 : 1)
50
+ }) {
51
+ HStack {
52
+ HStack {}
53
+ .frame(width: 6, height: 6)
54
+ .background(backgroundColor)
55
+ .clipShape(Circle())
56
+ }
57
+ .frame(width: 14, height: 14)
58
+ .background(circleColor)
59
+ .clipShape(Circle())
60
+ .padding(.leading, Spacing.XS)
61
+ .padding(.trailing, Spacing.XS)
62
+ }
63
+ .disabled(disabled)
64
+ .frame(width: 38, height: 20, alignment: value ? .trailing : .leading)
65
+ .background(backgroundColor)
66
+ .clipShape(Capsule())
67
+ .accessibilityIdentifier(automationId)
43
68
  }
44
69
  }
@@ -363,13 +363,15 @@ private struct CardTabBar: View {
363
363
  let isActive = selectedIndex == index
364
364
  let iconColor = isActive ? selectedColor : unselectedColor
365
365
 
366
- cardItem(tab: tab, isActive: isActive, iconColor: iconColor)
367
- .frame(maxWidth: .infinity)
368
- .frame(height: isActive ? 44 : 40)
369
- .background(isActive ? theme.colors.background.surface : theme.colors.background.tonal)
370
- .clipShape(UnstyledRoundedRectangle(topLeft: Radius.M, topRight: Radius.M))
371
- .contentShape(Rectangle())
372
- .onTapGesture { onPress(index) }
366
+ SwiftUI.Button(action: { onPress(index) }) {
367
+ cardItem(tab: tab, isActive: isActive, iconColor: iconColor)
368
+ .frame(maxWidth: .infinity)
369
+ .frame(height: isActive ? 44 : 40)
370
+ .background(isActive ? theme.colors.background.surface : theme.colors.background.tonal)
371
+ .clipShape(UnstyledRoundedRectangle(topLeft: Radius.M, topRight: Radius.M))
372
+ .contentShape(Rectangle())
373
+ }
374
+ .buttonStyle(ActiveOpacityButtonStyle())
373
375
  }
374
376
  }
375
377
  .frame(maxWidth: .infinity)
@@ -416,15 +418,17 @@ private struct TabItemView: View {
416
418
  private var textStyle: TypographyStyle { active ? .headerSSemibold : .bodyDefaultRegular }
417
419
 
418
420
  var body: some View {
419
- Group {
420
- if direction == .column {
421
- columnBody
422
- } else {
423
- rowBody
421
+ SwiftUI.Button(action: onPress) {
422
+ Group {
423
+ if direction == .column {
424
+ columnBody
425
+ } else {
426
+ rowBody
427
+ }
424
428
  }
429
+ .contentShape(Rectangle())
425
430
  }
426
- .contentShape(Rectangle())
427
- .onTapGesture { onPress() }
431
+ .buttonStyle(ActiveOpacityButtonStyle())
428
432
  }
429
433
 
430
434
  @ViewBuilder
@@ -52,15 +52,14 @@ let defaultBanner = TrustBannerData(
52
52
 
53
53
  public struct TrustBanner: View {
54
54
  @EnvironmentObject var applicationEnvironment: ApplicationEnvironment
55
-
55
+ @EnvironmentObject private var localize: Localize
56
+
56
57
  var onPress: ((String)->Void)?
57
-
58
+
58
59
  public init(onPress: ((String)->Void)?) {
59
60
  self.onPress = onPress
60
61
  }
61
-
62
- var language: String? = "vi"
63
-
62
+
64
63
  func onPressSecurity() {
65
64
  if (onPress != nil) {
66
65
  onPress!(applicationEnvironment.config?.trustBanner?.urlConfig ?? defaultBanner.urlConfig)
@@ -75,7 +74,7 @@ public struct TrustBanner: View {
75
74
  .scaledToFit()
76
75
  .frame(width: 64, height: 64)
77
76
  VStack(alignment: .leading){
78
- Text(applicationEnvironment.config?.trustBanner?.content[language ?? "vi"] as? String ?? defaultBanner.content[language ?? "vi"])
77
+ Text(applicationEnvironment.config?.trustBanner?.content[localize.currentLanguage] ?? defaultBanner.content[localize.currentLanguage])
79
78
  .foregroundColor(Color(hex: "484848"))
80
79
  .lineLimit(2)
81
80
  .font(.system(size: 13, weight: Font.Weight.regular))
@@ -84,7 +83,7 @@ public struct TrustBanner: View {
84
83
  .padding(.bottom, 8)
85
84
  HStack {
86
85
  HStack(spacing: 0) {
87
- Text(applicationEnvironment.config?.trustBanner?.subContent[language ?? "vi"] as? String ?? defaultBanner.subContent[language ?? "vi"])
86
+ Text(applicationEnvironment.config?.trustBanner?.subContent[localize.currentLanguage] ?? defaultBanner.subContent[localize.currentLanguage])
88
87
  .foregroundColor(Colors.pink03)
89
88
  .font(.system(size: 13, weight: .bold))
90
89
  .ignoreBoldTextSetting()
@@ -462,6 +462,9 @@ private struct TooltipSecondaryButton: View {
462
462
  .padding(.vertical, Spacing.S)
463
463
  }
464
464
  .buttonStyle(.plain)
465
+ // Mirrors Compose's `Modifier.weight(1f, fill = false)` on the secondary button:
466
+ // it yields space to the primary button first under width pressure.
467
+ .layoutPriority(-1)
465
468
  }
466
469
  }
467
470
 
@@ -172,12 +172,3 @@ private struct UploaderImageItem: View {
172
172
  .buttonStyle(ActiveOpacityButtonStyle())
173
173
  }
174
174
  }
175
-
176
- // MARK: - Active opacity button style
177
-
178
- private struct ActiveOpacityButtonStyle: ButtonStyle {
179
- func makeBody(configuration: Configuration) -> some View {
180
- configuration.label
181
- .opacity(configuration.isPressed ? 0.5 : 1)
182
- }
183
- }
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKits'
3
- s.version = '0.163.1-beta.6'
3
+ s.version = '0.162.2-sp.9'
4
4
  s.summary = 'MoMoUIKits for iOS'
5
5
  s.homepage = 'https://momo.vn'
6
6
  s.license = { :type => 'MIT' }
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKitsDemo'
3
- s.version = '0.163.1-beta.6'
3
+ s.version = '0.162.2-sp.9'
4
4
  s.summary = 'Demo browser for MoMoUIKits SwiftUI components'
5
5
  s.homepage = 'https://momo.vn'
6
6
  s.license = { :type => 'MIT' }
@@ -0,0 +1,120 @@
1
+ # MoMoUIKitsDemo
2
+
3
+ SwiftUI demo browser for `MoMoUIKits`.
4
+
5
+ The package can optionally host a Compose UIKits screen by receiving a
6
+ `UIViewController` factory from the host app. It does not import the KMP
7
+ `shared` module directly.
8
+
9
+ SwiftUI mode reuses the full demo screen set from
10
+ `sample/iosApp/iosApp/Demo`, including the sample `HomeView` registry and demo
11
+ screens for all currently available components.
12
+
13
+ ## CocoaPods
14
+
15
+ In the host app `Podfile`, include both local pods:
16
+
17
+ ```ruby
18
+ pod 'MoMoUIKits', :path => '../momo-native-kits/ios/native-kits.podspec'
19
+ pod 'MoMoUIKitsDemo', :path => '../momo-native-kits/ios-demo'
20
+ ```
21
+
22
+ Adjust the relative paths to match the host app checkout.
23
+
24
+ ## Host App Usage
25
+
26
+ ```swift
27
+ import MoMoUIKitsDemo
28
+ import shared
29
+
30
+ class UIKitsViewController: BaseComposeAppViewController {
31
+ override func getViewController() -> UIViewController? {
32
+ let params = self.application.data as? [String: Any]
33
+
34
+ return MoMoUIKitsDemoViewControllerFactory.make(
35
+ context: MoMoUIKitsDemoContext(
36
+ appId: params?["appId"] as? String ?? "",
37
+ appCode: params?["code"] as? String ?? "",
38
+ appName: params?["name"] as? String,
39
+ appIcon: params?["icon"] as? String ?? ""
40
+ ),
41
+ composeViewController: {
42
+ UIKitsScreenComposeViewControllerKt.UIKitsScreenComposeViewController(
43
+ params: params
44
+ )
45
+ }
46
+ )
47
+ }
48
+
49
+ override func viewDidDisappear(_ animated: Bool) {
50
+ super.viewDidDisappear(animated)
51
+ composeViewController = nil
52
+ }
53
+ }
54
+ ```
55
+
56
+ If the host does not pass `composeViewController`, the demo opens directly in
57
+ SwiftUI mode.
58
+
59
+ ## Included SwiftUI Demos
60
+
61
+ The pod includes the sample demo screens for:
62
+
63
+ - Animated Header
64
+ - Avatar
65
+ - Badge
66
+ - Baseline View
67
+ - Bottom Tab
68
+ - Button
69
+ - Carousel
70
+ - Checkbox
71
+ - Chip
72
+ - Collapse
73
+ - DateTimePicker
74
+ - Divider
75
+ - Header User
76
+ - Icon Button
77
+ - Image
78
+ - Information
79
+ - Input
80
+ - Input DropDown
81
+ - Input Money
82
+ - Input OTP
83
+ - Input Phone Number
84
+ - Input Search
85
+ - Input TextArea
86
+ - Loader
87
+ - Navigation
88
+ - Pagination
89
+ - Popup Display
90
+ - Popup Notify
91
+ - Popup Promotion
92
+ - Progress Info
93
+ - Radio
94
+ - Rating
95
+ - Skeleton
96
+ - Slider
97
+ - SnackBar
98
+ - Stepper
99
+ - Steps
100
+ - Suggest Action
101
+ - Swipe
102
+ - Switch
103
+ - TabView
104
+ - Tag
105
+ - Theme
106
+ - Title
107
+ - Tooltip
108
+ - Typography
109
+ - Uploader
110
+
111
+ ## Validation Notes
112
+
113
+ Validated locally with:
114
+
115
+ ```sh
116
+ pod ipc spec ios/MoMoUIKits.podspec
117
+ pod ipc spec ios-demo/MoMoUIKitsDemo.podspec
118
+ pod lib lint ios/MoMoUIKits.podspec --allow-warnings --skip-import-validation
119
+ pod lib lint ios-demo/MoMoUIKitsDemo.podspec --allow-warnings --skip-import-validation --include-podspecs=ios/MoMoUIKits.podspec
120
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.162.21",
3
+ "version": "0.162.22-debug",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},