@momo-kits/native-kits 0.167.1-duo.17 → 0.167.1-duo.18-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 (154) hide show
  1. package/CLAUDE.md +1 -0
  2. package/build.gradle.kts +11 -0
  3. package/compose/build.gradle.kts +204 -0
  4. package/compose/build.gradle.kts.backup +204 -0
  5. package/compose/compose.podspec +47 -0
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -0
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  10. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +153 -0
  11. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +916 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +81 -0
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +115 -0
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +478 -0
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +265 -0
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +265 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +361 -0
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +108 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +308 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +330 -0
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +207 -0
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +92 -0
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +560 -0
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +86 -0
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +501 -0
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +236 -0
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +180 -0
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +20 -0
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +283 -0
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +50 -0
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +309 -0
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +338 -0
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +137 -0
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +106 -0
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +205 -0
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +393 -0
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +713 -0
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +35 -0
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +218 -0
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +231 -0
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +98 -0
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +312 -0
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +447 -0
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +103 -0
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +74 -0
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +379 -0
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +363 -0
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +133 -0
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +127 -0
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +74 -0
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +13 -0
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +118 -0
  134. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +78 -0
  135. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
  136. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +32 -0
  137. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -0
  138. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  139. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +217 -0
  140. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +94 -0
  141. package/gradle/libs.versions.toml +69 -0
  142. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  143. package/gradle/wrapper/gradle-wrapper.properties +8 -0
  144. package/gradle.properties +26 -0
  145. package/gradlew +252 -0
  146. package/gradlew.bat +94 -0
  147. package/ios/Layout/ScreenLayout.swift +49 -3
  148. package/ios/Navigation/Component/Header.swift +48 -11
  149. package/ios/Navigation/Component/HeaderRight.swift +34 -28
  150. package/ios/Navigation/Component/SideBar.swift +15 -8
  151. package/ios/Navigation/StackScreen.swift +13 -12
  152. package/ios-demo/README.md +120 -0
  153. package/package.json +1 -1
  154. package/settings.gradle.kts +64 -0
@@ -13,6 +13,8 @@ public let HEADER_HEIGHT: CGFloat = 52
13
13
 
14
14
  /// Room the back button and toolkit take from the bar (Compose `HEADER_ACTIONS_WIDTH`).
15
15
  let headerActionsWidth: CGFloat = 172
16
+ // Extra width the 48pt back and toolkit take on the iPhone Duo status bar row.
17
+ private let statusBarRowActionsExtra: CGFloat = 55
16
18
 
17
19
  public enum TitlePosition {
18
20
  case left, center
@@ -282,7 +284,9 @@ func headerSearchProps(_ props: InputSearchProps, scroll: CGFloat, layout: Scree
282
284
 
283
285
  /// Max title width: back button and toolkit share the bar unless the iPhone Duo side bar holds them.
284
286
  func headerTitleMaxWidth(_ layout: ScreenLayout) -> CGFloat {
285
- layout.sideBar != nil ? layout.contentWidth - Spacing.M * 2 : layout.width - headerActionsWidth
287
+ let clearance = layout.statusBarClearance.map { $0.left + $0.right } ?? 0
288
+ if layout.sideBar != nil { return layout.contentWidth - Spacing.M * 2 - clearance }
289
+ return layout.width - headerActionsWidth - (layout.statusBarClearance != nil ? statusBarRowActionsExtra : 0) - clearance
286
290
  }
287
291
 
288
292
  // MARK: - Header
@@ -333,10 +337,22 @@ public struct NavigationHeader: View {
333
337
 
334
338
  @Environment(\.screenLayout) private var layout
335
339
  @Environment(\.appTheme) private var theme
340
+ @State private var headerRightWidth: CGFloat = 0
336
341
 
337
342
  /// iPhone Duo side bar holds back and the toolkit; a custom header right stays in the bar.
338
343
  private var useSideBar: Bool { layout.sideBar != nil }
339
344
 
345
+ /// iPhone Duo inner portrait: the row sits on the status bar, between its clusters, with 48pt controls.
346
+ private var statusBarRow: Bool { layout.statusBarClearance != nil && !useSideBar }
347
+
348
+ /// Max centered title width; on the status bar row the clusters are lopsided, so both sides keep the wider one's room.
349
+ private var centerTitleMaxWidth: CGFloat {
350
+ guard let clearance = layout.statusBarClearance else { return (layout.contentWidth - Spacing.M * 2) / 2 }
351
+ let back = goBack == nil || useSideBar ? 0 : DuoMetrics.controlSize + Spacing.S
352
+ let inset = max(clearance.left + back, clearance.right + headerRightWidth) + Spacing.S
353
+ return max(layout.contentWidth - (Spacing.M + inset) * 2, 0)
354
+ }
355
+
340
356
  private var headerColor: HeaderColor {
341
357
  getHeaderColor(
342
358
  isAnimated: animatedHeader != nil,
@@ -357,7 +373,16 @@ public struct NavigationHeader: View {
357
373
  ZStack {
358
374
  HStack(spacing: 0) {
359
375
  if let goBack, !useSideBar {
360
- BackButton(color: headerColor, onBack: goBack)
376
+ if statusBarRow {
377
+ SideBarButton(
378
+ icon: "arrow-back",
379
+ headerColor: headerColor,
380
+ accessibilityId: "btn_navigation_back",
381
+ action: goBack
382
+ )
383
+ } else {
384
+ BackButton(color: headerColor, onBack: goBack)
385
+ }
361
386
  Spacer().frame(width: Spacing.S)
362
387
  }
363
388
 
@@ -369,24 +394,36 @@ public struct NavigationHeader: View {
369
394
  }
370
395
 
371
396
  if let headerRight, !(useSideBar && toolkitHeaderRight(headerRight) != nil) {
372
- AnyView(headerRight())
373
- .environment(\.headerColor, headerColor)
374
- .background(
375
- GeometryReader { geo in
376
- Color.clear.preference(key: HeaderRightWidthKey.self, value: geo.size.width)
377
- }
378
- )
397
+ Group {
398
+ if statusBarRow, let toolkit = toolkitHeaderRight(headerRight) {
399
+ Toolkit(
400
+ headerRight: toolkit.data ?? HeaderRightData(),
401
+ tintColor: toolkit.tintColor,
402
+ layout: .sideBarRow
403
+ )
404
+ } else {
405
+ AnyView(headerRight())
406
+ }
407
+ }
408
+ .environment(\.headerColor, headerColor)
409
+ .background(
410
+ GeometryReader { geo in
411
+ Color.clear.preference(key: HeaderRightWidthKey.self, value: geo.size.width)
412
+ }
413
+ )
379
414
  }
380
415
  }
381
- .padding(.horizontal, Spacing.M)
416
+ .padding(.leading, Spacing.M + (layout.statusBarClearance?.left ?? 0))
417
+ .padding(.trailing, Spacing.M + (layout.statusBarClearance?.right ?? 0))
382
418
 
383
419
  if centerTitle {
384
420
  titleArea(centered: true)
385
421
  // Compose caps a centered title at half the bar
386
- .frame(maxWidth: (layout.contentWidth - Spacing.M * 2) / 2)
422
+ .frame(maxWidth: centerTitleMaxWidth)
387
423
  .padding(.horizontal, Spacing.M)
388
424
  }
389
425
  }
426
+ .onPreferenceChange(HeaderRightWidthKey.self) { headerRightWidth = $0 }
390
427
  .frame(height: layout.headerBarHeight)
391
428
  .overlay(alignment: .bottom) { VerticalShadow(opacity: opacity) }
392
429
  // the row starts headerStatusBarHeight below the window top: 0 with the status bar off
@@ -158,11 +158,15 @@ private struct NavigationButtonConfig {
158
158
  let onPress: () -> Void
159
159
  }
160
160
 
161
+ /// `sideBarColumn`: the iPhone Duo side bar; `sideBarRow`: the Duo header row on the status bar, same 48pt controls.
162
+ enum ToolkitLayout {
163
+ case bar, sideBarColumn, sideBarRow
164
+ }
165
+
161
166
  struct Toolkit: View {
162
167
  let headerRight: HeaderRightData
163
168
  var tintColor: Color?
164
- /// iPhone Duo side bar column instead of the bar row.
165
- var vertical: Bool = false
169
+ var layout: ToolkitLayout = .bar
166
170
 
167
171
  @State private var isFavorite = false
168
172
  @State private var isLoading = false
@@ -276,44 +280,46 @@ struct Toolkit: View {
276
280
 
277
281
  var body: some View {
278
282
  Group {
279
- if vertical {
280
- verticalBody
281
- } else {
283
+ switch layout {
284
+ case .bar:
282
285
  horizontalBody
286
+ case .sideBarColumn:
287
+ VStack(spacing: Spacing.M) { sideBarControls(horizontal: false) }
288
+ case .sideBarRow:
289
+ HStack(spacing: Spacing.M) { sideBarControls(horizontal: true) }
283
290
  }
284
291
  }
285
292
  .onAppear(perform: loadFavoriteState)
286
293
  }
287
294
 
288
- private var verticalBody: some View {
295
+ @ViewBuilder
296
+ private func sideBarControls(horizontal: Bool) -> some View {
289
297
  let config = navigationButtonConfig
290
298
  let useHelpCenter = usesHelpCenter(context)
291
- return VStack(spacing: Spacing.M) {
292
- if showsShortcut(headerRight, context) {
293
- SideBarButton(
294
- icon: config.icon,
295
- headerColor: headerColor,
296
- showBadge: headerRight.showBadge,
297
- disabled: isLoading,
298
- action: config.onPress
299
- )
300
- }
301
- SideBarGroup(headerColor: headerColor, itemCount: useHelpCenter ? 2 : 1) {
302
- if useHelpCenter {
303
- SideBarGroupItem(
304
- icon: "help_center",
305
- headerColor: headerColor,
306
- accessibilityId: "btn_navigation_help_center",
307
- action: onPressHelpCenter
308
- )
309
- }
299
+ if showsShortcut(headerRight, context) {
300
+ SideBarButton(
301
+ icon: config.icon,
302
+ headerColor: headerColor,
303
+ showBadge: headerRight.showBadge,
304
+ disabled: isLoading,
305
+ action: config.onPress
306
+ )
307
+ }
308
+ SideBarGroup(headerColor: headerColor, itemCount: useHelpCenter ? 2 : 1, horizontal: horizontal) {
309
+ if useHelpCenter {
310
310
  SideBarGroupItem(
311
- icon: headerRight.closeIcon,
311
+ icon: "help_center",
312
312
  headerColor: headerColor,
313
- accessibilityId: "btn_navigation_close",
314
- action: onPressClose
313
+ accessibilityId: "btn_navigation_help_center",
314
+ action: onPressHelpCenter
315
315
  )
316
316
  }
317
+ SideBarGroupItem(
318
+ icon: headerRight.closeIcon,
319
+ headerColor: headerColor,
320
+ accessibilityId: "btn_navigation_close",
321
+ action: onPressClose
322
+ )
317
323
  }
318
324
  }
319
325
 
@@ -70,7 +70,7 @@ struct HeaderSideBar: View {
70
70
  Toolkit(
71
71
  headerRight: toolkit.data ?? HeaderRightData(),
72
72
  tintColor: toolkit.tintColor,
73
- vertical: true
73
+ layout: .sideBarColumn
74
74
  )
75
75
  .environment(\.headerColor, headerColor)
76
76
  }
@@ -142,19 +142,26 @@ struct SideBarButton: View {
142
142
  }
143
143
  }
144
144
 
145
- /// 48pt wide glass capsule grouping related controls, one item per 50pt.
145
+ /// 48pt glass capsule grouping related controls, one item per 50pt: vertical in the side bar,
146
+ /// horizontal on a header row.
146
147
  struct SideBarGroup<Content: View>: View {
147
148
  let headerColor: HeaderColor
148
149
  let itemCount: Int
150
+ var horizontal: Bool = false
149
151
  @ViewBuilder let content: () -> Content
150
152
 
151
153
  var body: some View {
152
- VStack(spacing: 0) { content() }
153
- .frame(
154
- width: DuoMetrics.controlSize,
155
- height: itemCount > 1 ? DuoMetrics.itemPitch * CGFloat(itemCount) : DuoMetrics.controlSize
156
- )
157
- .modifier(SideBarGlass(headerColor: headerColor, shape: RoundedRectangle(cornerRadius: Radius.XL)))
154
+ let length = itemCount > 1 ? DuoMetrics.itemPitch * CGFloat(itemCount) : DuoMetrics.controlSize
155
+ Group {
156
+ if horizontal {
157
+ HStack(spacing: 0) { content() }
158
+ .frame(width: length, height: DuoMetrics.controlSize)
159
+ } else {
160
+ VStack(spacing: 0) { content() }
161
+ .frame(width: DuoMetrics.controlSize, height: length)
162
+ }
163
+ }
164
+ .modifier(SideBarGlass(headerColor: headerColor, shape: RoundedRectangle(cornerRadius: Radius.XL)))
158
165
  }
159
166
  }
160
167
 
@@ -618,24 +618,25 @@ private struct SearchAnimatedHeader: View {
618
618
  let minTop = rowTop + (layout.headerBarHeight - HEADER_HEIGHT) / 2
619
619
  let maxTop = layout.headerHeight - layout.insets.top
620
620
  let minSide = Spacing.M
621
- let maxStart: CGFloat = hiddenBack || useSideBar ? Spacing.M : 48
622
- let maxEnd: CGFloat = useSideBar && hasToolkit
621
+ // collapsed on the iPhone Duo status bar row, the search stays between its clusters (48pt back there)
622
+ let clearance = layout.statusBarClearance
623
+ let backWidth: CGFloat = clearance != nil && !useSideBar ? DuoMetrics.controlSize : 28
624
+ let maxStart = (clearance?.left ?? 0) + (hiddenBack || useSideBar ? Spacing.M : backWidth + Spacing.M + Spacing.S)
625
+ let maxEnd = (clearance?.right ?? 0) + (useSideBar && hasToolkit
623
626
  ? Spacing.M
624
- : headerRightWidth + (hasHeaderRight ? Spacing.M * 2 : Spacing.M)
627
+ : headerRightWidth + (hasHeaderRight ? Spacing.M * 2 : Spacing.M))
625
628
 
626
629
  let top = min(max(maxTop - scroll, minTop), maxTop)
627
630
  let start = min(max(minSide + scroll, minSide), maxStart)
628
631
  let end = min(max(minSide + scroll, minSide), maxEnd)
629
632
 
630
- VStack(spacing: 0) {
631
- Spacer().frame(height: top)
632
- InputSearch(props: headerSearchProps(props, scroll: scroll, layout: layout, theme: theme))
633
- .frame(height: HEADER_HEIGHT)
634
- .padding(.leading, start)
635
- .padding(.trailing, end)
636
- Spacer(minLength: 0)
637
- }
638
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
633
+ // padding, not a Spacer: on the iPhone Duo status bar row the collapsed top is above the safe area
634
+ InputSearch(props: headerSearchProps(props, scroll: scroll, layout: layout, theme: theme))
635
+ .frame(height: HEADER_HEIGHT)
636
+ .padding(.leading, start)
637
+ .padding(.trailing, end)
638
+ .padding(.top, top)
639
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
639
640
  }
640
641
  }
641
642
 
@@ -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.167.1-duo.17",
3
+ "version": "0.167.1-duo.18-debug",
4
4
  "private": false,
5
5
  "dependeNavigationncies": {},
6
6
  "devDependencies": {},
@@ -0,0 +1,64 @@
1
+ import org.gradle.kotlin.dsl.maven
2
+
3
+ rootProject.name = "momo-native-kits"
4
+ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
5
+
6
+ pluginManagement {
7
+ repositories {
8
+ google {
9
+ mavenContent {
10
+ includeGroupAndSubgroups("androidx")
11
+ includeGroupAndSubgroups("com.android")
12
+ includeGroupAndSubgroups("com.google")
13
+ }
14
+ }
15
+ mavenCentral()
16
+ gradlePluginPortal()
17
+ maven {
18
+ url = uri("https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven")
19
+ credentials {username = "download_packages"; password = "gldt-bjDqLpU_sPcHDuXau2ws" }
20
+ }
21
+ maven {
22
+ url = uri("https://artifacts.mservice.com.vn/repository/maven-momo-app/")
23
+ credentials {
24
+ username = "viewer"
25
+ password = "viewer"
26
+ }
27
+ isAllowInsecureProtocol = true
28
+ }
29
+ }
30
+ }
31
+
32
+ dependencyResolutionManagement {
33
+ repositories {
34
+ google {
35
+ mavenContent {
36
+ includeGroupAndSubgroups("androidx")
37
+ includeGroupAndSubgroups("com.android")
38
+ includeGroupAndSubgroups("com.google")
39
+ }
40
+ }
41
+ mavenCentral()
42
+ maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") }
43
+ maven {
44
+ url = uri("https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven")
45
+ credentials {
46
+ username = "download_packages";
47
+ password = "gldt-bjDqLpU_sPcHDuXau2ws"
48
+ }
49
+ }
50
+ maven {
51
+ url = uri("https://artifacts.mservice.com.vn/repository/maven-momo-app/")
52
+ credentials {
53
+ username = "viewer"
54
+ password = "viewer"
55
+ }
56
+ isAllowInsecureProtocol = true
57
+ }
58
+ }
59
+ }
60
+
61
+ include(":compose")
62
+
63
+ include(":sample:androidApp")
64
+ include(":sample:shared")