@momo-kits/native-kits 0.167.1-duo.2-debug → 0.167.1-duo.3

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 (171) hide show
  1. package/.claude/scheduled_tasks.lock +1 -0
  2. package/.claude/settings.local.json +185 -0
  3. package/CLAUDE.md +8 -3
  4. package/ios/Application/HeaderRight.swift +25 -12
  5. package/ios/Application/Layout/ScreenLayout.swift +196 -0
  6. package/ios/Application/Navigation/BottomTab/BottomTab.swift +30 -9
  7. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +5 -2
  8. package/ios/Application/Navigation/BottomTab/DuoTabBar.swift +275 -0
  9. package/ios/Application/Navigation/HeaderUser.swift +4 -1
  10. package/ios/Application/Navigation/NavigationContainer.swift +3 -0
  11. package/ios/Application/Navigation/Overplay/BottomSheet.swift +41 -4
  12. package/ios/Application/Navigation/Overplay/ModalScreen.swift +5 -1
  13. package/ios/Application/Navigation/component/DuoScrollGradient.swift +55 -0
  14. package/ios/Application/Navigation/component/Header.swift +9 -3
  15. package/ios/Application/Navigation/component/HeaderBackground.swift +3 -2
  16. package/ios/Application/Navigation/component/NavigationFooter.swift +1 -1
  17. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +61 -9
  18. package/ios/Application/Navigation/component/SideBar.swift +155 -0
  19. package/ios/Application/StackScreen.swift +135 -18
  20. package/ios/Popup/PopupDisplay.swift +84 -68
  21. package/ios/Popup/PopupLayout.swift +45 -0
  22. package/ios/Popup/PopupNotify.swift +43 -32
  23. package/ios/Popup/PopupPromotion.swift +17 -5
  24. package/ios/native-kits.podspec +1 -1
  25. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  26. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +76 -0
  27. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +1 -0
  28. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +170 -0
  29. package/package.json +1 -1
  30. package/build.gradle.kts +0 -11
  31. package/compose/build.gradle.kts +0 -190
  32. package/compose/build.gradle.kts.backup +0 -190
  33. package/compose/compose.podspec +0 -47
  34. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
  35. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  36. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
  37. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
  38. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -151
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -831
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -82
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -356
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -113
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -475
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -266
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -240
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -264
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -334
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -98
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -310
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -323
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -199
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -552
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -88
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -498
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -234
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -188
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -16
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -297
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -157
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -299
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -129
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -205
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -622
  134. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
  135. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
  136. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -175
  137. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -232
  138. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  139. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
  140. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -381
  141. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -83
  142. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -105
  143. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
  144. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -347
  145. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -37
  146. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
  147. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -169
  148. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
  149. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
  150. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
  151. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
  152. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
  153. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -71
  154. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  155. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
  156. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  157. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
  158. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -40
  159. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
  160. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
  161. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
  162. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
  163. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -213
  164. package/gradle/libs.versions.toml +0 -69
  165. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  166. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  167. package/gradle.properties +0 -26
  168. package/gradlew +0 -252
  169. package/gradlew.bat +0 -94
  170. package/ios-demo/README.md +0 -120
  171. package/settings.gradle.kts +0 -64
@@ -3,12 +3,6 @@ import SwiftUI
3
3
 
4
4
  public typealias PopupActionDirection = PopupButtonDirection
5
5
 
6
- // Portrait width in landscape too, so aspect-ratio images don't push popups past the screen height.
7
- var popupMaxWidth: CGFloat {
8
- let size = UIScreen.main.bounds.size
9
- return min(size.width, size.height)
10
- }
11
-
12
6
  public struct PopupNotifyProps {
13
7
  public var image: String
14
8
  public var title: String
@@ -46,10 +40,12 @@ public struct PopupNotifyProps {
46
40
  public struct PopupNotify: View {
47
41
  @Environment(\.localize) private var localize
48
42
  @Environment(\.momoFontScale) private var fontScale
43
+ @Environment(\.screenLayout) private var layout
49
44
 
50
45
  public let props: PopupNotifyProps
51
46
 
52
47
  @State private var descriptionHeight: CGFloat = 0
48
+ @State private var actionsHeight: CGFloat = 0
53
49
 
54
50
  private var errorCodePrefix: String {
55
51
  localize.translate("errorCode")
@@ -77,37 +73,26 @@ public struct PopupNotify: View {
77
73
  public var body: some View {
78
74
  ZStack(alignment: .topTrailing) {
79
75
  VStack(spacing: 0) {
80
- if !props.image.isEmpty {
81
- popupImage
82
- }
83
-
84
- VStack(alignment: .leading, spacing: 0) {
85
- MomoText(
86
- props.title,
87
- typography: .headerDefaultBold,
88
- maxLines: 2,
89
- accessibilityId: "title_popup_permission"
90
- )
91
- .padding(.bottom, Spacing.S)
92
-
93
- descriptionContent
94
-
95
- if !props.error.isEmpty {
96
- MomoText(
97
- errorCodePrefix + props.error,
98
- typography: .descriptionXsRegular,
99
- color: Colors.black12,
100
- maxLines: 1
101
- )
102
- .padding(.top, Spacing.S)
76
+ // scrolls when iPhone Duo landscape is too short; actions stay visible
77
+ PopupScrollBody(maxHeight: layout.popupMaxHeight.map { $0 - actionsHeight }) {
78
+ VStack(spacing: 0) {
79
+ if !props.image.isEmpty {
80
+ popupImage
81
+ }
82
+ textContent
103
83
  }
104
84
  }
105
- .frame(maxWidth: .infinity, alignment: .leading)
106
- .padding(Spacing.XL)
107
85
 
108
86
  actionButtons
109
87
  .padding(.horizontal, Spacing.XL)
110
88
  .padding(.bottom, Spacing.XL)
89
+ .background(
90
+ GeometryReader { proxy in
91
+ Color.clear
92
+ .onAppear { actionsHeight = proxy.size.height }
93
+ .onChange(of: proxy.size.height) { actionsHeight = $0 }
94
+ }
95
+ )
111
96
  }
112
97
  .background(Colors.black01)
113
98
  .clipShape(RoundedRectangle(cornerRadius: Radius.L))
@@ -117,12 +102,38 @@ public struct PopupNotify: View {
117
102
  .offset(x: 11, y: -11)
118
103
  }
119
104
  }
120
- .frame(maxWidth: popupMaxWidth - Spacing.M * 2)
105
+ .frame(maxWidth: layout.popupMaxWidth)
121
106
  .padding(.horizontal, Spacing.M)
122
107
  .accessibilityElement(children: .ignore)
123
108
  .accessibilityIdentifier("popup_notify")
124
109
  }
125
110
 
111
+ private var textContent: some View {
112
+ VStack(alignment: .leading, spacing: 0) {
113
+ MomoText(
114
+ props.title,
115
+ typography: .headerDefaultBold,
116
+ maxLines: 2,
117
+ accessibilityId: "title_popup_permission"
118
+ )
119
+ .padding(.bottom, Spacing.S)
120
+
121
+ descriptionContent
122
+
123
+ if !props.error.isEmpty {
124
+ MomoText(
125
+ errorCodePrefix + props.error,
126
+ typography: .descriptionXsRegular,
127
+ color: Colors.black12,
128
+ maxLines: 1
129
+ )
130
+ .padding(.top, Spacing.S)
131
+ }
132
+ }
133
+ .frame(maxWidth: .infinity, alignment: .leading)
134
+ .padding(Spacing.XL)
135
+ }
136
+
126
137
  private var popupImage: some View {
127
138
  WebImage(url: URL(string: props.image), isAnimating: .constant(true))
128
139
  .resizable()
@@ -3,6 +3,7 @@ import SDWebImageSwiftUI
3
3
 
4
4
  public struct PopupPromotion: View {
5
5
  @Environment(\.appTheme) private var theme
6
+ @Environment(\.screenLayout) private var layout
6
7
 
7
8
  var imageUrl: String
8
9
  var onIconClose: (() -> Void)?
@@ -19,22 +20,33 @@ public struct PopupPromotion: View {
19
20
  self.onAction = onAction
20
21
  }
21
22
 
23
+ private static let aspectRatio: CGFloat = 0.72
24
+ // close button row under the image: stack spacing + padded 40pt button
25
+ private static let closeRowHeight: CGFloat = 8 + 40 + Spacing.S * 2
26
+
27
+ // fit the portrait image by height when iPhone Duo leaves too little room
28
+ private var imageWidth: CGFloat {
29
+ let width = min(layout.width - Spacing.XL * 2, layout.popupMaxWidth)
30
+ guard let maxHeight = layout.popupMaxHeight else { return width }
31
+ return min(width, (maxHeight - Self.closeRowHeight) * Self.aspectRatio)
32
+ }
33
+
22
34
  public var body: some View {
23
35
  VStack(spacing: 8) {
24
36
  if(imageUrl.isEmpty) {
25
- Icon(source: "media_fail", size: popupMaxWidth - Spacing.XL * 2)
37
+ Icon(source: "media_fail", size: imageWidth)
26
38
  }
27
39
  else {
28
40
  WebImage(url: URL(string: imageUrl)!)
29
41
  .resizable()
30
42
  .placeholder {
31
43
  Color.gray
32
- .aspectRatio(0.72, contentMode: .fit)
33
- .frame(maxWidth: popupMaxWidth - Spacing.XL * 2)
44
+ .aspectRatio(Self.aspectRatio, contentMode: .fit)
45
+ .frame(maxWidth: imageWidth)
34
46
  .clipped()
35
47
  }
36
- .aspectRatio(0.72, contentMode: .fit)
37
- .frame(maxWidth: popupMaxWidth - Spacing.XL * 2, alignment: .center)
48
+ .aspectRatio(Self.aspectRatio, contentMode: .fit)
49
+ .frame(maxWidth: imageWidth, alignment: .center)
38
50
  .clipped()
39
51
  .onTapGesture {
40
52
  onAction?()
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKits'
3
- s.version = '0.167.1-beta.4'
3
+ s.version = '0.167.1-duo.3'
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.167.1-beta.4'
3
+ s.version = '0.167.1-duo.3'
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,76 @@
1
+ //
2
+ // DuoTabDemo.swift
3
+ // Example
4
+ //
5
+ // Mirrors RN `app/screens/IPhoneDuo/DuoTabUsage`: glass rail in the Duo side bar, floating
6
+ // glass bar when unfolded portrait. `useShortcut` gives the tallest side bar header, for the
7
+ // overlap review.
8
+ //
9
+
10
+ import MoMoUIKits
11
+ import SwiftUI
12
+
13
+ private let swatches = [Colors.pink03, Colors.orange03, Colors.green03]
14
+ private let history = (1...18).map { "Giao dịch #\($0)" }
15
+
16
+ struct DuoTabDemo: View {
17
+ let useShortcut: Bool
18
+
19
+ var body: some View {
20
+ if #available(iOS 16.0, *) {
21
+ DuoTabDemoContent(useShortcut: useShortcut)
22
+ } else {
23
+ Text("Requires iOS 16+").padding()
24
+ }
25
+ }
26
+ }
27
+
28
+ @available(iOS 16.0, *)
29
+ private struct DuoTabDemoContent: View {
30
+ let useShortcut: Bool
31
+
32
+ var body: some View {
33
+ BottomTab(
34
+ items: [
35
+ tab("DuoMoMo", label: "MoMo", icon: "basic_home", title: "MoMo"),
36
+ tab("DuoPromotion", label: "Ưu đãi", icon: "shopping_coupon", title: "Ưu đãi", badge: ""),
37
+ tab("DuoHistory", label: "Lịch sử GD", icon: "time_clock_reset", title: "Lịch sử giao dịch", badge: "3"),
38
+ tab("DuoMe", label: "Tôi", icon: "basic_person", title: "Tôi"),
39
+ ],
40
+ floatingButton: BottomTabFloatingButton(icon: "navigation_full_screen", label: "Quét mọi QR", onPress: {})
41
+ )
42
+ }
43
+
44
+ private func tab(_ name: String, label: String, icon: String, title: String, badge: String? = nil) -> BottomTabItem {
45
+ BottomTabItem(
46
+ name: name,
47
+ label: label,
48
+ icon: icon,
49
+ badgeLabel: badge,
50
+ options: NavigationOptions(title: title, headerRightData: HeaderRightData(useShortcut: useShortcut)),
51
+ screen: { DuoTabList() }
52
+ )
53
+ }
54
+ }
55
+
56
+ private struct DuoTabList: View {
57
+ var body: some View {
58
+ VStack(spacing: 0) {
59
+ ForEach(history.indices, id: \.self) { index in
60
+ if index > 0 { MomoDivider() }
61
+ HStack(spacing: Spacing.M) {
62
+ RoundedRectangle(cornerRadius: Radius.S)
63
+ .fill(swatches[index % swatches.count])
64
+ .frame(width: Spacing.XL, height: Spacing.XL)
65
+ MomoText(history[index], typography: .bodyDefaultRegular)
66
+ Spacer()
67
+ }
68
+ .padding(.vertical, Spacing.M)
69
+ }
70
+ }
71
+ .padding(.horizontal, Spacing.M)
72
+ .background(Colors.black01)
73
+ .clipShape(RoundedRectangle(cornerRadius: Radius.M))
74
+ .padding(Spacing.M)
75
+ }
76
+ }
@@ -85,6 +85,7 @@ public let ScreenUsages: [ScreenUsage] = [
85
85
  ScreenUsage(title: "DateTimePicker", destination: AnyView(DateTimePickerDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
86
86
  ScreenUsage(title: "Navigation", destination: AnyView(NavigationDemo()), icon: getIcon(icon: "Layout")),
87
87
  ScreenUsage(title: "Bottom Tab", destination: AnyView(BottomTabDemo()), icon: getIcon(icon: "Layout"), hostsOwnChrome: true),
88
+ ScreenUsage(title: "iPhone Duo", destination: AnyView(IPhoneDuoDemo()), icon: getIcon(icon: "Layout")),
88
89
  ScreenUsage(title: "Animated Header", destination: AnyView(AnimatedHeaderDemo()), icon: getIcon(icon: "Layout")),
89
90
  ScreenUsage(title: "Theme", destination: AnyView(ThemeDemo()), icon: getIcon(icon: "Typography")),
90
91
  ScreenUsage(title: "Localize", destination: AnyView(LocalizeDemo()), icon: getIcon(icon: "Typography")),
@@ -0,0 +1,170 @@
1
+ //
2
+ // IPhoneDuoDemo.swift
3
+ // Example
4
+ //
5
+ // Mirrors RN `app/screens/IPhoneDuo`: the live screen layout, an extended header + search
6
+ // + footer screen, the Duo tab bars, the popup / bottom sheet behaviour and a grid to scroll.
7
+ //
8
+
9
+ import MoMoUIKits
10
+ import SwiftUI
11
+
12
+ private let gridRows: [[Int]] = [[12], [6, 6], [4, 4, 4], [3, 3, 3, 3]]
13
+
14
+ // enough rows to scroll, so the header glass and side bar can be checked
15
+ private let scrollRows: [[Int]] = Array(repeating: gridRows, count: 4).flatMap { $0 }
16
+
17
+ struct IPhoneDuoDemo: View {
18
+ var body: some View {
19
+ if #available(iOS 16.0, *) {
20
+ IPhoneDuoDemoContent()
21
+ } else {
22
+ Text("Requires iOS 16+").padding()
23
+ }
24
+ }
25
+ }
26
+
27
+ @available(iOS 16.0, *)
28
+ private struct IPhoneDuoDemoContent: View {
29
+ @EnvironmentObject private var navigator: Navigator
30
+ @Environment(\.screenLayout) private var layout
31
+
32
+ var body: some View {
33
+ VStack(alignment: .leading, spacing: Spacing.M) {
34
+ VStack(spacing: 0) {
35
+ ForEach(info, id: \.0) { label, value in
36
+ HStack {
37
+ MomoText(label, typography: .bodyDefaultRegular)
38
+ Spacer()
39
+ MomoText(value, typography: .headerSSemibold)
40
+ }
41
+ .padding(.vertical, Spacing.XS)
42
+ }
43
+ }
44
+ .padding(.horizontal, Spacing.M)
45
+
46
+ VStack(spacing: Spacing.S) {
47
+ demoButton("Extended header + footer") {
48
+ navigator.push({ DuoGridScreen() }, options: extendedOptions)
49
+ }
50
+ demoButton("Glass tab bar") {
51
+ navigator.push({ DuoTabDemo(useShortcut: false) }, options: tabOptions)
52
+ }
53
+ demoButton("Glass tab bar + useShortcut") {
54
+ navigator.push({ DuoTabDemo(useShortcut: true) }, options: tabOptions)
55
+ }
56
+ demoButton("Bottom sheet: iPhone Duo safe area") {
57
+ navigator.showBottomSheet({ BottomSheetSafeArea() }, isSurface: true, header: .title("Safe area"))
58
+ }
59
+ demoButton("PopupNotify") {
60
+ navigator.showModal {
61
+ PopupNotify(props: PopupNotifyProps(
62
+ image: "https://static.momocdn.net/app/img/popup_permission/img_permission_popup_camera.png",
63
+ title: "Title",
64
+ description: String(repeating: "Check lại một nhịp auto chuyển sang dạng CTA. ", count: 8),
65
+ primary: PopupAction(title: "Đồng ý", onPress: { navigator.hideOverplay() }),
66
+ secondary: PopupAction(title: "Đóng", onPress: { navigator.hideOverplay() }),
67
+ onIconClose: { navigator.hideOverplay() }
68
+ ))
69
+ }
70
+ }
71
+ }
72
+ .padding(.horizontal, Spacing.M)
73
+
74
+ DuoGrid()
75
+ }
76
+ .padding(.vertical, Spacing.M)
77
+ }
78
+
79
+ private var info: [(String, String)] {
80
+ let insets = layout.insets
81
+ return [
82
+ ("iPhone Duo", layout.isIPhoneDuo ? "yes" : "no"),
83
+ ("Window", "\(Int(layout.width)) x \(Int(layout.height))"),
84
+ ("Safe area (T R B L)", "\(Int(insets.top)) \(Int(insets.trailing)) \(Int(insets.bottom)) \(Int(insets.leading))"),
85
+ ("Content inset (L R)", "\(Int(layout.insetLeft)) \(Int(layout.insetRight))"),
86
+ ("Content width", "\(Int(layout.contentWidth))"),
87
+ ("Header height", "\(Int(layout.headerHeight))"),
88
+ ("Side bar", layout.sideBar.map { "\($0.edge == .left ? "left" : "right"), \(Int($0.width))pt, top \(Int($0.top))" } ?? "none"),
89
+ ]
90
+ }
91
+
92
+ private var extendedOptions: NavigationOptions {
93
+ NavigationOptions(
94
+ title: "Extended",
95
+ headerType: .extended,
96
+ headerRightData: HeaderRightData(useShortcut: true),
97
+ footer: { AnyView(MoMoUIKits.Button(title: "Footer action", action: {}, size: .large)) }
98
+ )
99
+ }
100
+
101
+ private var tabOptions: NavigationOptions {
102
+ NavigationOptions(title: "Duo tabs", headerType: .none, scrollable: false)
103
+ }
104
+
105
+ private func demoButton(_ title: String, action: @escaping () -> Void) -> some View {
106
+ MoMoUIKits.Button(title: title, action: action, type: .secondary, size: .small)
107
+ }
108
+ }
109
+
110
+ private struct DuoGridScreen: View {
111
+ var body: some View {
112
+ DuoGrid().padding(.vertical, Spacing.M)
113
+ }
114
+ }
115
+
116
+ private struct DuoGrid: View {
117
+ var body: some View {
118
+ VStack(spacing: Spacing.M) {
119
+ ForEach(scrollRows.indices, id: \.self) { row in
120
+ SectionView {
121
+ ForEach(scrollRows[row].indices, id: \.self) { index in
122
+ let span = scrollRows[row][index]
123
+ ItemView(widthSpan: span) {
124
+ MomoText("span \(span)", typography: .descriptionDefaultRegular)
125
+ .frame(maxWidth: .infinity)
126
+ .frame(height: 48)
127
+ .background(Colors.black04)
128
+ .clipShape(RoundedRectangle(cornerRadius: Radius.S))
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ /// Markers on the content edges show the side safe area inside the sheet.
138
+ private struct BottomSheetSafeArea: View {
139
+ @Environment(\.screenLayout) private var layout
140
+
141
+ var body: some View {
142
+ VStack(alignment: .leading, spacing: Spacing.XS) {
143
+ HStack {
144
+ marker("← content edge")
145
+ Spacer()
146
+ marker("content edge →")
147
+ }
148
+ .padding(.bottom, Spacing.S)
149
+ MomoText("Window: \(Int(layout.width)) × \(Int(layout.height))", typography: .bodyDefaultRegular)
150
+ MomoText(
151
+ "Insets: top \(Int(layout.insets.top)) · right \(Int(layout.insets.trailing)) · bottom \(Int(layout.insets.bottom)) · left \(Int(layout.insets.leading))",
152
+ typography: .bodyDefaultRegular
153
+ )
154
+ MomoText(
155
+ "On iPhone Duo: the outer display keeps a full-width sheet with content inside the side safe area; the inner display centers the sheet, still attached to the bottom edge. Other devices are unchanged.",
156
+ typography: .descriptionDefaultRegular,
157
+ color: Colors.black12
158
+ )
159
+ }
160
+ .padding(.vertical, Spacing.M)
161
+ }
162
+
163
+ private func marker(_ text: String) -> some View {
164
+ MomoText(text, typography: .labelSMedium, color: Colors.pink03)
165
+ .padding(.vertical, Spacing.XS)
166
+ .padding(.horizontal, Spacing.S)
167
+ .background(Colors.black04)
168
+ .clipShape(RoundedRectangle(cornerRadius: Radius.XS))
169
+ }
170
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.167.1-duo.2-debug",
3
+ "version": "0.167.1-duo.3",
4
4
  "private": false,
5
5
  "dependeNavigationncies": {},
6
6
  "devDependencies": {},
package/build.gradle.kts DELETED
@@ -1,11 +0,0 @@
1
- plugins {
2
- // this is necessary to avoid the plugins to be loaded multiple times
3
- // in each subproject's classloader
4
- alias(libs.plugins.android.application) apply false
5
- alias(libs.plugins.android.library) apply false
6
- alias(libs.plugins.compose) apply false
7
- alias(libs.plugins.kotlin.compose.compiler) apply false
8
- alias(libs.plugins.jetbrains.kotlin.multiplatform) apply false
9
- alias(libs.plugins.jetbrains.kotlin.serialization) apply false
10
- alias(libs.plugins.vanniktech.mavenPublish) apply false
11
- }
@@ -1,190 +0,0 @@
1
- // import com.vanniktech.maven.publish.JavadocJar
2
- // import com.vanniktech.maven.publish.KotlinMultiplatform
3
- import org.jetbrains.kotlin.gradle.dsl.JvmTarget
4
-
5
- plugins {
6
- alias(libs.plugins.jetbrains.kotlin.multiplatform)
7
- alias(libs.plugins.android.library)
8
- alias(libs.plugins.compose)
9
- alias(libs.plugins.kotlin.compose.compiler)
10
- // alias(libs.plugins.vanniktech.mavenPublish)
11
- id(libs.plugins.jetbrains.kotlin.cocoapods.get().pluginId)
12
- kotlin("plugin.serialization")
13
- }
14
-
15
- val gitlabName: String = findProperty("name") as String? ?: ""
16
- val gitlabRepo: String = findProperty("repo") as String? ?: ""
17
- val gitlabUrl: String = findProperty("url") as String? ?: ""
18
- val gitlabGroup: String = findProperty("group") as String? ?: ""
19
- val gitlabArtifactId: String = findProperty("artifact.id") as String? ?: ""
20
- val gitlabVersion: String = findProperty("version") as String? ?: ""
21
- val gitlabUser: String = findProperty("gitlab.user") as String? ?: ""
22
- val gitlabKey: String = findProperty("gitlab.password") as String? ?: ""
23
-
24
- kotlin {
25
- androidTarget {
26
- compilerOptions {
27
- jvmTarget.set(JvmTarget.JVM_17)
28
- }
29
- publishLibraryVariants("release")
30
- }
31
-
32
- val fwName = gitlabArtifactId
33
- val iosTargets = listOf(iosArm64(), iosSimulatorArm64())
34
- iosTargets.forEach {
35
- it.binaries.framework {
36
- baseName = fwName
37
- binaryOption("bundleId", "$gitlabGroup.$fwName")
38
- isStatic = true
39
- }
40
- }
41
-
42
- cocoapods {
43
- version = "0.167.1-duo.2-debug"
44
- summary = "IOS Shared module"
45
- homepage = "https://momo.vn"
46
- ios.deploymentTarget = "15.0"
47
-
48
- framework {
49
- baseName = fwName
50
- isStatic = true
51
- }
52
-
53
- pod("lottie-ios") {
54
- moduleName = "Lottie"
55
- version = "4.4.3"
56
- extraOpts += listOf("-compiler-option", "-fmodules")
57
- }
58
- }
59
-
60
- sourceSets {
61
- all {
62
- languageSettings.optIn("vn.momo.kits.modifier.InternalApi")
63
- }
64
- commonMain.dependencies {
65
- implementation(compose.runtime)
66
- implementation(compose.material)
67
- implementation(compose.material3)
68
- implementation(compose.components.resources)
69
- implementation(libs.compose.ui.backhandler)
70
- implementation(libs.ktor.client.core)
71
- implementation(libs.jetbrains.coroutines.core)
72
- implementation(libs.navigation.multiplatform)
73
- implementation(libs.coil.multiplatform.compose)
74
- implementation(libs.coil.multiplatform.core)
75
- implementation(libs.coil.multiplatform.network.ktor)
76
- implementation(libs.jetbrains.serialization.json)
77
- implementation(libs.kotlinx.datetime)
78
- api(libs.native.max.api)
79
- implementation(libs.compottie)
80
- implementation(libs.gif.image)
81
- }
82
- androidMain.dependencies {
83
- implementation(libs.ktor.client.okhttp)
84
- implementation(libs.airbnb.lottie)
85
- }
86
- iosMain.dependencies {
87
- implementation(libs.ktor.client.darwin)
88
- }
89
- }
90
- }
91
-
92
- android {
93
- namespace = "vn.momo.kits.kits"
94
- compileSdk = 35
95
- compileOptions {
96
- sourceCompatibility = JavaVersion.VERSION_17
97
- targetCompatibility = JavaVersion.VERSION_17
98
- }
99
- defaultConfig {
100
- minSdk = 24
101
- }
102
- }
103
-
104
- dependencies {
105
- }
106
-
107
- repositories {
108
- google {
109
- mavenContent {
110
- includeGroupAndSubgroups("androidx")
111
- includeGroupAndSubgroups("com.android")
112
- includeGroupAndSubgroups("com.google")
113
- }
114
- }
115
- mavenCentral()
116
- maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") }
117
- maven {
118
- url = uri("https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven")
119
- credentials {username = "download_packages"; password = "gldt-bjDqLpU_sPcHDuXau2ws" }
120
- }
121
- maven {
122
- url = uri("https://artifacts.mservice.com.vn/repository/maven-momo-app/")
123
- credentials {
124
- username = "viewer"
125
- password = "viewer"
126
- }
127
- isAllowInsecureProtocol = true
128
- }
129
- }
130
-
131
- compose {
132
- resources {
133
- publicResClass = true
134
- packageOfResClass = "vn.momo.uikits.resources"
135
- generateResClass = always
136
- }
137
- }
138
-
139
- // publishing {
140
- // repositories {
141
- // maven {
142
- // name = "${gitlabRepo}Packages"
143
- // credentials {
144
- // username = gitlabUser
145
- // password = gitlabKey
146
- // }
147
- // url = uri("$gitlabUrl")
148
- // }
149
- // }
150
- // }
151
-
152
- // mavenPublishing {
153
- // configure(
154
- // KotlinMultiplatform(
155
- // javadocJar = JavadocJar.Empty(),
156
- // sourcesJar = true,
157
- // androidVariantsToPublish = listOf("release")
158
- // )
159
- // )
160
- //
161
- // repositories {
162
- // maven {
163
- // name = "${gitlabRepo}Packages"
164
- // credentials { username = gitlabUser; password = gitlabKey }
165
- // url = uri("$gitlabUrl")
166
- // }
167
- // }
168
- //
169
- // coordinates(gitlabGroup.toString(), gitlabArtifactId, gitlabVersion.toString())
170
- //
171
- // pom {
172
- // name = "$gitlabName Klib"
173
- // description = "$gitlabName"
174
- // url = "https://gitlab.mservice.com.vn"
175
- // licenses {
176
- // license {
177
- // name = "The Apache License, Version 2.0"
178
- // url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
179
- // distribution = "https://www.apache.org/licenses/LICENSE-2.0.txt"
180
- // }
181
- // }
182
- // developers {
183
- // developer {
184
- // id = "kotlin-hands-on"
185
- // name = "Kotlin Developer Advocate"
186
- // url = "https://github.com/kotlin-hands-on/"
187
- // }
188
- // }
189
- // }
190
- // }