@momo-kits/native-kits 0.300.3-debug → 0.300.4-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 (218) hide show
  1. package/CLAUDE.md +51 -7
  2. package/README.md +2 -2
  3. package/compose/build.gradle.kts +10 -2
  4. package/compose/build.gradle.kts.backup +8 -0
  5. package/compose/compose.podspec +1 -3
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +4 -3
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -0
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -14
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +351 -111
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +20 -21
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +2 -1
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +4 -2
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +1 -1
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +1 -1
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -1
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +9 -6
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +11 -12
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +4 -9
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +2 -2
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +10 -9
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +6 -6
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +55 -22
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +12 -1
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +7 -9
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +1 -1
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +13 -6
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +13 -5
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +3 -2
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +14 -6
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +19 -21
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +2 -2
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +5 -2
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +3 -1
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +7 -15
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +2 -1
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +20 -15
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -2
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +43 -4
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +8 -0
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +10 -0
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +6 -2
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +6 -0
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +197 -60
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +132 -83
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +54 -62
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +97 -0
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +377 -0
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +122 -24
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +34 -14
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +3 -3
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +1 -2
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +113 -26
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +2 -2
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -2
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +37 -0
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +2 -1
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +8 -0
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +3 -0
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +13 -0
  65. package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +44 -0
  66. package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +15 -0
  67. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +3 -1
  68. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +4 -0
  69. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
  70. package/gradle/libs.versions.toml +3 -14
  71. package/gradle/wrapper/gradle-wrapper.properties +0 -2
  72. package/gradle.properties +3 -5
  73. package/ios/Application/ApplicationEnvironment.swift +24 -6
  74. package/ios/Application/DesignSystemKits.swift +100 -0
  75. package/ios/Application/DesignSystemKitsPayload.swift +68 -0
  76. package/ios/Application/MaxApi.swift +30 -3
  77. package/ios/Avatar/Avatar.swift +4 -3
  78. package/ios/Badge/Badge.swift +6 -4
  79. package/ios/Badge/BadgeDot.swift +1 -1
  80. package/ios/Badge/BadgeRibbon.swift +8 -2
  81. package/ios/Button/Button.swift +15 -12
  82. package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +64 -18
  83. package/ios/Carousel/Carousel.swift +29 -12
  84. package/ios/Checkbox/Checkbox.swift +7 -3
  85. package/ios/Chip/Chip.swift +5 -4
  86. package/ios/Collapse/Collapse.swift +70 -19
  87. package/ios/Colors+Radius+Spacing/Colors.swift +10 -1
  88. package/ios/Colors+Radius+Spacing/Radius.swift +6 -0
  89. package/ios/DateTimePicker/DateTimePicker.swift +54 -20
  90. package/ios/DateTimePicker/WheelPicker.swift +103 -105
  91. package/ios/Divider/Divider.swift +37 -4
  92. package/ios/Extensions/Color++.swift +38 -9
  93. package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
  94. package/ios/Extensions/SkeletonUICompat.swift +11 -0
  95. package/ios/Icon/Icon.swift +21 -23
  96. package/ios/Icon/Icons.swift +1329 -0
  97. package/ios/IconButton/IconButton.swift +15 -7
  98. package/ios/Image/Image.swift +7 -23
  99. package/ios/Information/Information.swift +27 -9
  100. package/ios/Input/ErrorView.swift +2 -2
  101. package/ios/Input/Input.swift +171 -148
  102. package/ios/Input/InputPhoneNumber.swift +10 -9
  103. package/ios/Input/InputSearch.swift +107 -78
  104. package/ios/Input/InputTextArea.swift +133 -148
  105. package/ios/InputDropDown/InputDropDown.swift +10 -7
  106. package/ios/InputMoney/InputMoney.swift +32 -11
  107. package/ios/InputOTP/InputOTP.swift +22 -12
  108. package/ios/Layout/Card.swift +50 -0
  109. package/ios/Layout/GridContext.swift +187 -3
  110. package/ios/Layout/Item.swift +5 -4
  111. package/ios/Layout/ScreenLayout.swift +415 -0
  112. package/ios/Layout/Section.swift +4 -100
  113. package/ios/Loader/Loader.swift +5 -9
  114. package/ios/Lottie/LottieView.swift +14 -2
  115. package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +169 -29
  116. package/ios/Navigation/BottomTab/BottomTab.swift +332 -0
  117. package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +18 -7
  118. package/ios/Navigation/BottomTab/DuoBarCompression.swift +104 -0
  119. package/ios/Navigation/BottomTab/DuoTabBar.swift +329 -0
  120. package/ios/{Application → Navigation/Component}/FloatingButton.swift +43 -54
  121. package/ios/Navigation/Component/Header.swift +545 -0
  122. package/ios/Navigation/Component/HeaderBackground.swift +154 -0
  123. package/ios/Navigation/Component/HeaderJourney.swift +73 -0
  124. package/ios/Navigation/Component/HeaderLocation.swift +48 -0
  125. package/ios/Navigation/Component/HeaderRight.swift +425 -0
  126. package/ios/Navigation/Component/HeaderTitle.swift +36 -0
  127. package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +21 -24
  128. package/ios/Navigation/Component/SideBar.swift +183 -0
  129. package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +8 -8
  130. package/ios/Navigation/HostBackGestureBridge.swift +78 -0
  131. package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +9 -2
  132. package/ios/Navigation/Navigation.swift +204 -0
  133. package/ios/Navigation/NavigationContainer.swift +195 -0
  134. package/ios/{Application/Navigation → Navigation}/Navigator.swift +207 -107
  135. package/ios/Navigation/StackScreen.swift +930 -0
  136. package/ios/Navigation/StackTransition.swift +400 -0
  137. package/ios/Navigation/SwipeBackHaptic.swift +33 -0
  138. package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
  139. package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
  140. package/ios/Pagination/PaginationScroll.swift +2 -2
  141. package/ios/Popup/PopupDisplay.swift +72 -135
  142. package/ios/Popup/PopupInput.swift +10 -13
  143. package/ios/Popup/PopupLayout.swift +138 -0
  144. package/ios/Popup/PopupNotify.swift +59 -69
  145. package/ios/Popup/PopupPromotion.swift +31 -47
  146. package/ios/PopupView/FullscreenPopup.swift +13 -19
  147. package/ios/PopupView/PopupView.swift +1 -1
  148. package/ios/PopupView/Utils++.swift +0 -8
  149. package/ios/ProgressInfo/ProgressInfo.swift +4 -2
  150. package/ios/Radio/Radio.swift +2 -1
  151. package/ios/Rating/Rating.swift +9 -1
  152. package/ios/Resources/dot_loading.json +558 -0
  153. package/ios/Resources/lottie_circle_loader.json +1 -0
  154. package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
  155. package/ios/Skeleton/Skeleton.swift +22 -27
  156. package/ios/Slider/Slider.swift +16 -18
  157. package/ios/Stepper/Stepper.swift +7 -3
  158. package/ios/Steps/Steps.swift +8 -6
  159. package/ios/SuggestAction/SuggestAction.swift +5 -0
  160. package/ios/Swipeable/SwipeCell.swift +10 -6
  161. package/ios/Switch/Switch.swift +22 -20
  162. package/ios/TabView/TabView.swift +102 -21
  163. package/ios/Tag/Tag.swift +15 -4
  164. package/ios/Template/Logo/Logo.swift +2 -1
  165. package/ios/Template/TrustBanner/TrustBanner.swift +109 -55
  166. package/ios/Title/Title.swift +6 -17
  167. package/ios/Tooltip/Tooltip.swift +29 -14
  168. package/ios/Typography/FontScale.swift +17 -14
  169. package/ios/Typography/Text.swift +156 -20
  170. package/ios/Typography/Typography.swift +2 -2
  171. package/ios/Uploader/Uploader.swift +3 -1
  172. package/ios/native-kits.podspec +2 -3
  173. package/ios-demo/MoMoUIKitsDemo.podspec +1 -3
  174. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
  175. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
  176. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +2 -0
  177. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
  178. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
  179. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +1 -0
  180. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +2 -2
  181. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +2 -0
  182. package/package.json +1 -1
  183. package/publish.sh +19 -2
  184. package/scripts/gen-ios-icons.mjs +36 -0
  185. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  186. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  187. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  188. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  189. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  190. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  191. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  192. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  193. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  194. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  195. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  196. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  197. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
  198. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  199. package/ios/Application/Components.swift +0 -270
  200. package/ios/Application/ComposeApi.swift +0 -22
  201. package/ios/Application/HeaderRight.swift +0 -306
  202. package/ios/Application/Navigation/BottomTab/BottomTab.swift +0 -104
  203. package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
  204. package/ios/Application/Navigation/HeaderTitle.swift +0 -57
  205. package/ios/Application/Navigation/NavigationContainer.swift +0 -213
  206. package/ios/Application/Navigation/NavigationOptions.swift +0 -109
  207. package/ios/Application/Navigation/NavigatorManager.swift +0 -22
  208. package/ios/Application/Navigation/component/Header.swift +0 -178
  209. package/ios/Application/Navigation/component/HeaderBackground.swift +0 -83
  210. package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
  211. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
  212. package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
  213. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -196
  214. package/ios/Application/Screen.swift +0 -250
  215. package/ios/Application/StackScreen.swift +0 -492
  216. package/ios/Typography/FontScaleStore.swift +0 -58
  217. package/ios/Typography/KitDesignSystem.swift +0 -17
  218. /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
@@ -2,7 +2,7 @@
2
2
  // HeaderUser.swift
3
3
  // MoMoUIKits
4
4
  //
5
- // SwiftUI mirror of Compose's `HeaderUser` (navigation/component/HeaderUser.kt).
5
+ // SwiftUI mirror of Compose's `navigation/component/HeaderUser.kt`.
6
6
  // Renders a `HeaderTitle.User`: an avatar group (1..n avatars with overflow),
7
7
  // a title with optional inline icons, and an optional subtitle. Shows a
8
8
  // skeleton shimmer placeholder while `isLoading`.
@@ -10,7 +10,6 @@
10
10
 
11
11
  import SwiftUI
12
12
 
13
- @available(iOS 16.0, *)
14
13
  public struct HeaderUserView: View {
15
14
  private let data: HeaderUserData
16
15
 
@@ -20,9 +19,7 @@ public struct HeaderUserView: View {
20
19
 
21
20
  private let avatarSize: CGFloat = Spacing.XXL // 32
22
21
 
23
- private var maxWidth: CGFloat {
24
- UIScreen.main.bounds.width - 172
25
- }
22
+ @Environment(\.screenLayout) private var layout
26
23
 
27
24
  public var body: some View {
28
25
  if data.isLoading {
@@ -33,6 +30,14 @@ public struct HeaderUserView: View {
33
30
  }
34
31
 
35
32
  private var content: some View {
33
+ SwiftUI.Button(action: { data.onPress?() }) {
34
+ row
35
+ }
36
+ .buttonStyle(ActiveOpacityButtonStyle())
37
+ .disabled(data.onPress == nil)
38
+ }
39
+
40
+ private var row: some View {
36
41
  HStack(spacing: 0) {
37
42
  HStack(spacing: 0) {
38
43
  ZStack(alignment: .bottomTrailing) {
@@ -49,8 +54,7 @@ public struct HeaderUserView: View {
49
54
 
50
55
  VStack(alignment: .leading, spacing: 0) {
51
56
  HStack(spacing: 0) {
52
- MomoText(data.title, typography: .actionXsBold, color: data.tintColor ?? Colors.black17, maxLines: 1)
53
- .truncationMode(.tail)
57
+ MomoText(data.title, typography: .actionXsBold, color: data.tintColor, maxLines: 1, fontFamily: headerFontFamily)
54
58
 
55
59
  if !data.icons.isEmpty {
56
60
  Spacer().frame(width: 6)
@@ -66,34 +70,27 @@ public struct HeaderUserView: View {
66
70
 
67
71
  if let subTitle = data.subTitle, !subTitle.isEmpty {
68
72
  Spacer().frame(height: 2)
69
- MomoText(subTitle, typography: .descriptionXsRegular, color: data.tintColor ?? Colors.black17, maxLines: 1)
70
- .truncationMode(.tail)
73
+ MomoText(subTitle, typography: .descriptionXsRegular, color: data.tintColor, maxLines: 1)
71
74
  }
72
75
  }
73
76
  }
74
- .frame(maxWidth: maxWidth, alignment: .leading)
77
+ .frame(maxWidth: headerTitleMaxWidth(layout), alignment: .leading)
75
78
 
76
79
  Spacer(minLength: 0)
77
80
  }
78
81
  .frame(maxWidth: .infinity, alignment: .leading)
79
82
  .padding(.vertical, Spacing.XS)
80
83
  .contentShape(Rectangle())
81
- .onTapGesture { data.onPress?() }
82
- .allowsHitTesting(data.onPress != nil)
83
84
  }
84
85
 
85
86
  private var shimmer: some View {
86
87
  HStack(spacing: Spacing.M / 2) {
87
- Circle()
88
- .fill(Colors.black05)
88
+ Skeleton()
89
89
  .frame(width: avatarSize, height: avatarSize)
90
+ .clipShape(Circle())
90
91
  VStack(alignment: .leading, spacing: Spacing.XXS) {
91
- RoundedRectangle(cornerRadius: 8)
92
- .fill(Colors.black05)
93
- .frame(width: 120, height: 18)
94
- RoundedRectangle(cornerRadius: 8)
95
- .fill(Colors.black05)
96
- .frame(width: 120, height: 12)
92
+ titleSkeleton(height: 18)
93
+ titleSkeleton(height: 12)
97
94
  }
98
95
  }
99
96
  .frame(maxWidth: .infinity, alignment: .leading)
@@ -105,8 +102,8 @@ public struct HeaderUserView: View {
105
102
 
106
103
  /// Mirrors Compose's `AvatarGroup`: lays out 1..4 avatars in a fixed collage,
107
104
  /// falls back to initials when empty, and shows a "+n" overflow tile beyond 4.
108
- @available(iOS 16.0, *)
109
105
  private struct AvatarGroup: View {
106
+ @Environment(\.appTheme) private var theme
110
107
  let urls: [String]
111
108
  let title: String
112
109
  let size: CGFloat
@@ -176,7 +173,7 @@ private struct AvatarGroup: View {
176
173
  ImageView(url)
177
174
  .aspectRatio(contentMode: .fill)
178
175
  .clipShape(Circle())
179
- .overlay(Circle().stroke(Colors.black05, lineWidth: 0.5))
176
+ .overlay(Circle().stroke(theme.colors.border.default, lineWidth: 0.5))
180
177
  }
181
178
 
182
179
  private func overflowTile(more: Int) -> some View {
@@ -187,8 +184,8 @@ private struct AvatarGroup: View {
187
184
  }
188
185
  }
189
186
 
190
- @available(iOS 16.0, *)
191
187
  private struct InitialsAvatar: View {
188
+ @Environment(\.appTheme) private var theme
192
189
  let name: String
193
190
  let size: CGFloat
194
191
 
@@ -204,6 +201,6 @@ private struct InitialsAvatar: View {
204
201
  .frame(width: size, height: size)
205
202
  .background(Colors.pink09)
206
203
  .clipShape(Circle())
207
- .overlay(Circle().stroke(Colors.black05, lineWidth: 0.5))
204
+ .overlay(Circle().stroke(theme.colors.border.default, lineWidth: 0.5))
208
205
  }
209
206
  }
@@ -0,0 +1,183 @@
1
+ //
2
+ // SideBar.swift
3
+ // MoMoUIKits
4
+ //
5
+ // SwiftUI mirror of Compose's `navigation/component/SideBar.kt`. iPhone Duo: back and toolkit
6
+ // leave the header bar for a column in the side safe area, as the system bars do.
7
+ // Port of RN `SideBarButton.tsx` + `useSideBarItemStyle`.
8
+ //
9
+
10
+ import SwiftUI
11
+
12
+ private let sideBarIconSize: CGFloat = 24
13
+
14
+ /// The back button and toolkit column, placed in window coordinates over the side strip.
15
+ struct HeaderSideBar: View {
16
+ let sideBar: SideBarLayout
17
+ let goBack: (() -> Void)?
18
+ let toolkit: (data: HeaderRightData?, tintColor: Color?)?
19
+ let headerColor: HeaderColor
20
+ /// What footer / tab bar / home indicator take from the bottom, gap included; the column stays above it.
21
+ let bottomInset: CGFloat
22
+
23
+ @Environment(\.screenLayout) private var layout
24
+ @Environment(\.applicationEnvironment) private var environment
25
+ @Environment(\.duoBarCompression) private var compression
26
+ @State private var columnHeight: CGFloat = 0
27
+
28
+ private var isRight: Bool { sideBar.edge == .right }
29
+
30
+ private var top: CGFloat {
31
+ let maxY = layout.height - bottomInset - columnHeight
32
+ return max(min(sideBar.top, maxY), 0)
33
+ }
34
+
35
+ /// Full height, so the tab bar compression decision follows this screen's toolkit.
36
+ private var fullHeight: CGFloat {
37
+ let toolkitHeight = toolkit.map {
38
+ Spacing.M + toolkitColumnHeight($0.data ?? HeaderRightData(), context: environment.applicationContext)
39
+ }
40
+ return DuoMetrics.controlSize + (toolkitHeight ?? 0)
41
+ }
42
+
43
+ var body: some View {
44
+ VStack(alignment: isRight ? .leading : .trailing, spacing: Spacing.M) {
45
+ if let goBack {
46
+ SideBarButton(
47
+ icon: "arrow-back",
48
+ headerColor: headerColor,
49
+ accessibilityId: "btn_navigation_back",
50
+ action: goBack
51
+ )
52
+ } else {
53
+ // keep the slot so the toolkit does not jump between root and pushed screens
54
+ Color.clear.frame(width: DuoMetrics.controlSize, height: DuoMetrics.controlSize)
55
+ }
56
+ if let toolkit {
57
+ if compression.toolbarHidden {
58
+ // an open tab rail takes this slot for a moment
59
+ EmptyView()
60
+ } else if compression.toolbarCompressed {
61
+ // HIG "Toolbar compressed": tools fold into one button, distinct from the useMore icon
62
+ SideBarButton(
63
+ icon: "navigation_menu",
64
+ headerColor: headerColor,
65
+ showBadge: toolkit.data?.showBadge ?? false,
66
+ accessibilityId: "btn_navigation_toolbar",
67
+ action: compression.expandToolbar
68
+ )
69
+ } else {
70
+ Toolkit(
71
+ headerRight: toolkit.data ?? HeaderRightData(),
72
+ tintColor: toolkit.tintColor,
73
+ layout: .sideBarColumn
74
+ )
75
+ .environment(\.headerColor, headerColor)
76
+ }
77
+ }
78
+ }
79
+ .padding(isRight ? .leading : .trailing, Spacing.M)
80
+ .frame(width: sideBar.width, alignment: isRight ? .leading : .trailing)
81
+ .background(
82
+ GeometryReader { proxy in
83
+ Color.clear
84
+ .onAppear { columnHeight = proxy.size.height }
85
+ .onChange(of: proxy.size.height) { columnHeight = $0 }
86
+ }
87
+ )
88
+ .padding(.top, top)
89
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: isRight ? .topTrailing : .topLeading)
90
+ .ignoresSafeArea()
91
+ .onAppear { compression.setToolbarHeight(fullHeight) }
92
+ .onChange(of: fullHeight) { compression.setToolbarHeight($0) }
93
+ }
94
+ }
95
+
96
+ /// Dark glass under light icons (banner headers), light glass otherwise.
97
+ private struct SideBarGlass<S: Shape>: ViewModifier {
98
+ let headerColor: HeaderColor
99
+ let shape: S
100
+
101
+ private var isDark: Bool { headerColor.tintIconColor == Colors.black01 || headerColor.tintIconColor == .white }
102
+
103
+ func body(content: Content) -> some View {
104
+ if isDark {
105
+ content
106
+ .background(shape.fill(Colors.black20.opacity(0.5)))
107
+ .overlay(shape.stroke(Colors.black01.opacity(0.2), lineWidth: 0.5))
108
+ } else {
109
+ content
110
+ .background(
111
+ shape.fill(Colors.black01.opacity(0.85))
112
+ .shadow(color: Color.black.opacity(0.12), radius: 4, x: 0, y: 2)
113
+ )
114
+ .overlay(shape.stroke(Colors.black20.opacity(0.08), lineWidth: 0.5))
115
+ }
116
+ }
117
+ }
118
+
119
+ /// 48pt glass circle for a single side bar control.
120
+ struct SideBarButton: View {
121
+ let icon: String
122
+ let headerColor: HeaderColor
123
+ var showBadge: Bool = false
124
+ var disabled: Bool = false
125
+ var accessibilityId: String?
126
+ let action: () -> Void
127
+
128
+ var body: some View {
129
+ SwiftUI.Button(action: action) {
130
+ Icon(source: icon, size: sideBarIconSize, color: headerColor.tintIconColor)
131
+ .frame(width: DuoMetrics.controlSize, height: DuoMetrics.controlSize)
132
+ .modifier(SideBarGlass(headerColor: headerColor, shape: Circle()))
133
+ .overlay(alignment: .topTrailing) {
134
+ if showBadge {
135
+ BadgeDot(size: .small).offset(x: -Spacing.XXS, y: Spacing.XXS)
136
+ }
137
+ }
138
+ }
139
+ .buttonStyle(ActiveOpacityButtonStyle())
140
+ .disabled(disabled)
141
+ .accessibilityIdentifier(accessibilityId ?? "")
142
+ }
143
+ }
144
+
145
+ /// 48pt glass capsule grouping related controls, one item per 50pt: vertical in the side bar,
146
+ /// horizontal on a header row.
147
+ struct SideBarGroup<Content: View>: View {
148
+ let headerColor: HeaderColor
149
+ let itemCount: Int
150
+ var horizontal: Bool = false
151
+ @ViewBuilder let content: () -> Content
152
+
153
+ var body: some View {
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)))
165
+ }
166
+ }
167
+
168
+ struct SideBarGroupItem: View {
169
+ let icon: String
170
+ let headerColor: HeaderColor
171
+ let accessibilityId: String
172
+ let action: () -> Void
173
+
174
+ var body: some View {
175
+ SwiftUI.Button(action: action) {
176
+ Icon(source: icon, size: sideBarIconSize, color: headerColor.tintIconColor)
177
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
178
+ .contentShape(Rectangle())
179
+ }
180
+ .buttonStyle(ActiveOpacityButtonStyle())
181
+ .accessibilityIdentifier(accessibilityId)
182
+ }
183
+ }
@@ -2,9 +2,8 @@
2
2
  // SnackBar.swift
3
3
  // MoMoUIKits
4
4
  //
5
- // SwiftUI mirror of Compose's `SnackBar` (navigation/component/SnackBar.kt).
6
- // A snack bar slides up from the bottom (just above the footer / home
7
- // indicator), stays for `duration`, then slides back down and is removed.
5
+ // SwiftUI mirror of Compose's `navigation/component/SnackBar.kt`: slides up above the screen's
6
+ // footer (or the home indicator), stays for `duration`, then slides back down.
8
7
  // `Navigator.showSnackBar(_:)` drives it through the overplay host.
9
8
  //
10
9
 
@@ -50,11 +49,11 @@ public struct SnackBar {
50
49
 
51
50
  /// Self-animating container. Slides the content up on appear, schedules an
52
51
  /// auto-dismiss after `duration`, and animates out before removing the overplay.
53
- @available(iOS 16.0, *)
54
52
  struct SnackBarView: View {
53
+ let overplayId: UUID
55
54
  let snackBar: SnackBar
56
- /// Bottom inset so the bar sits above the footer / home indicator
57
- /// (mirrors Compose's `footerHeight` offset).
55
+ /// Distance from the window bottom to the top of the screen's footer, or the navigation bar
56
+ /// inset without one (Compose's `footerHeight` offset).
58
57
  let bottomInset: CGFloat
59
58
 
60
59
  @EnvironmentObject private var navigator: Navigator
@@ -78,6 +77,7 @@ struct SnackBarView: View {
78
77
  .padding(.bottom, bottomInset)
79
78
  }
80
79
  .frame(maxWidth: .infinity, maxHeight: .infinity)
80
+ .ignoresSafeArea()
81
81
  .onAppear {
82
82
  guard !didAppear else { return }
83
83
  didAppear = true
@@ -122,7 +122,7 @@ struct SnackBarView: View {
122
122
  offsetY = max(contentHeight, 200) + bottomInset
123
123
  }
124
124
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
125
- navigator.finishOverplayDismiss()
125
+ navigator.finishOverplayDismiss(id: overplayId)
126
126
  }
127
127
  }
128
128
 
@@ -134,7 +134,7 @@ struct SnackBarView: View {
134
134
  guard let duration = snackBar.duration else { return }
135
135
  let workItem = DispatchWorkItem {
136
136
  // Only auto-dismiss if this snack bar is still the active overplay.
137
- if navigator.overplay?.type == .snackBar {
137
+ if navigator.overplay?.id == overplayId {
138
138
  navigator.hideSnackBar()
139
139
  }
140
140
  }
@@ -0,0 +1,78 @@
1
+ //
2
+ // HostBackGestureBridge.swift
3
+ // MoMoUIKits
4
+ //
5
+ // SwiftUI mirror of Compose's `navigation/HostBackGestureBridge.kt`: the host owns the edge-pan
6
+ // recogniser and routes a back into the topmost kit stack. NavigationContainer attaches itself.
7
+ // `started` / `progressed` / `completed` / `cancelled` scrub the pop transition with the finger;
8
+ // a host that only calls `pop` gets the regular animated back.
9
+ //
10
+
11
+ import UIKit
12
+
13
+ public final class HostBackGestureBridge {
14
+ public static let shared = HostBackGestureBridge()
15
+ private init() {}
16
+
17
+ // Weak: a container torn down without disappearing must not keep receiving backs.
18
+ private var navigators: [WeakNavigator] = []
19
+ private weak var gestureTarget: Navigator?
20
+
21
+ /// Set while a bottom tab other than the first is selected; the host shows its floating arrow.
22
+ public var shouldUseFloatingArrowBack = false
23
+
24
+ public func attach(_ navigator: Navigator) {
25
+ navigators.removeAll { $0.value == nil }
26
+ guard !navigators.contains(where: { $0.value === navigator }) else { return }
27
+ navigators.append(WeakNavigator(value: navigator))
28
+ }
29
+
30
+ public func detach(_ navigator: Navigator) {
31
+ navigators.removeAll { $0.value == nil || $0.value === navigator }
32
+ if gestureTarget === navigator { gestureTarget = nil }
33
+ }
34
+
35
+ /// Whether a kit stack is on screen at all.
36
+ public func checkCanPop() -> Bool { top() != nil }
37
+
38
+ /// Whether the top stack pops a screen itself; false means a back dismisses the mini app.
39
+ public func canPopInner() -> Bool { top()?.canPop() == true }
40
+
41
+ public func pop() { top()?.onBackSafe() }
42
+
43
+ public func started() {
44
+ guard let target = top() else { return }
45
+ gestureTarget = target
46
+ target.backStarted()
47
+ }
48
+
49
+ /// `progress` is the touch travel over the window width, 0...1.
50
+ public func progressed(_ progress: CGFloat) {
51
+ gestureTarget?.backProgressed(min(max(progress, 0), 1))
52
+ }
53
+
54
+ public func completed() {
55
+ (gestureTarget ?? top())?.backCompleted()
56
+ gestureTarget = nil
57
+ }
58
+
59
+ public func cancelled() {
60
+ gestureTarget?.backCancelled()
61
+ gestureTarget = nil
62
+ }
63
+
64
+ @available(*, deprecated, renamed: "attach")
65
+ public func push(_ navigator: Navigator) { attach(navigator) }
66
+
67
+ @available(*, deprecated, renamed: "detach")
68
+ public func remove(_ navigator: Navigator) { detach(navigator) }
69
+
70
+ private func top() -> Navigator? { navigators.last { $0.value != nil }?.value }
71
+ }
72
+
73
+ @available(*, deprecated, renamed: "HostBackGestureBridge")
74
+ public typealias NavigatorManager = HostBackGestureBridge
75
+
76
+ private struct WeakNavigator {
77
+ weak var value: Navigator?
78
+ }
@@ -9,13 +9,14 @@
9
9
 
10
10
  import SwiftUI
11
11
 
12
- @available(iOS 16.0, *)
13
12
  struct ModalScreen<Content: View>: View {
13
+ let overplayId: UUID
14
14
  let barrierDismissible: Bool
15
15
  let content: () -> Content
16
16
 
17
17
  @EnvironmentObject private var navigator: Navigator
18
18
  @Environment(\.applicationEnvironment) private var appEnv
19
+ @Environment(\.screenLayout) private var layout
19
20
 
20
21
  @State private var scrimOpacity: CGFloat = 0
21
22
  @State private var contentScale: CGFloat = 0.8
@@ -35,7 +36,13 @@ struct ModalScreen<Content: View>: View {
35
36
  content()
36
37
  .scaleEffect(contentScale)
37
38
  .opacity(contentOpacity)
39
+ // iPhone Duo: center below the side status bar and above the home indicator
40
+ .padding(.top, layout.isDuoDevice ? layout.duoTopInset : 0)
41
+ .padding(.bottom, layout.isDuoDevice ? layout.insets.bottom : 0)
38
42
  }
43
+ // Full screen like RN's Modal, so asymmetric landscape insets don't shift the content sideways.
44
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
45
+ .ignoresSafeArea(.container)
39
46
  .onAppear {
40
47
  guard !didAppear else { return }
41
48
  didAppear = true
@@ -68,7 +75,7 @@ struct ModalScreen<Content: View>: View {
68
75
  contentOpacity = 0
69
76
  }
70
77
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
71
- navigator.finishOverplayDismiss()
78
+ navigator.finishOverplayDismiss(id: overplayId)
72
79
  }
73
80
  }
74
81
  }
@@ -0,0 +1,204 @@
1
+ //
2
+ // Navigation.swift
3
+ // MoMoUIKits
4
+ //
5
+ // SwiftUI mirror of Compose's `navigation/Navigation.kt`: a screen's `NavigationOptions` and the
6
+ // per-screen `Navigation` that updates them at runtime.
7
+ //
8
+
9
+ import SwiftUI
10
+
11
+ /// Per-screen handle (Compose `LocalNavigation`). Read it inside a screen with
12
+ /// `@EnvironmentObject var navigation: Navigation` and call `setOptions` to change the header,
13
+ /// footer or back handling after the screen is shown.
14
+ public final class Navigation: ObservableObject {
15
+ public let id: Int
16
+ public let bottomTabIndex: Int
17
+ @Published public private(set) var options: NavigationOptions
18
+
19
+ private weak var registry: DynamicScreenRegistry?
20
+ /// What the footer (or navigation bar) takes from the window bottom; lifts snack bars.
21
+ var bottomObstruction: CGFloat = 0
22
+
23
+ init(
24
+ id: Int = -1,
25
+ bottomTabIndex: Int = -1,
26
+ options: NavigationOptions?,
27
+ registry: DynamicScreenRegistry? = nil
28
+ ) {
29
+ self.id = id
30
+ self.bottomTabIndex = bottomTabIndex
31
+ self.options = options ?? NavigationOptions()
32
+ self.registry = registry
33
+ if id != -1 { registry?.bind(self) }
34
+ }
35
+
36
+ public func setOptions(_ options: NavigationOptions) {
37
+ update(options)
38
+ }
39
+
40
+ /// Changes only what the closure touches, like Compose's named-argument `setOptions`.
41
+ public func setOptions(_ transform: (inout NavigationOptions) -> Void) {
42
+ var updated = options
43
+ transform(&updated)
44
+ update(updated)
45
+ }
46
+
47
+ private func update(_ updated: NavigationOptions) {
48
+ options = updated
49
+ // back handling reads the registry copy
50
+ if id != -1 { registry?.setOptions(id: id, options: updated) }
51
+ }
52
+ }
53
+
54
+ public struct NavigationOptions {
55
+ public var screenName: String?
56
+ public var title: String
57
+ /// Rich header title (Compose `headerTitle`); `title` is used when nil.
58
+ public var headerTitle: HeaderTitle?
59
+ public var titlePosition: TitlePosition
60
+ public var headerType: HeaderType
61
+ /// Compose's `HeaderType.Default/Extended(useAnimated:)`: with `inputSearchProps`, the search
62
+ /// rises into the header on scroll.
63
+ public var useAnimated: Bool
64
+ /// Compose's `HeaderType.Transparent`; with `fullScreenContent` the content starts under it.
65
+ public var headerTransparent: Bool
66
+ public var fullScreenContent: Bool
67
+ public var hiddenBack: Bool
68
+ public var backgroundColor: Color?
69
+ // AI-GENERATED START: custom screen background view (Compose backgroundComponent)
70
+ /// Drawn instead of `backgroundColor` over the whole window: under the header and the status bar,
71
+ /// across the iPhone Duo side strips, and not shrunk by the keyboard. Pair with `headerTransparent`.
72
+ public var background: (() -> AnyView)?
73
+ // AI-GENERATED END: custom screen background view (Compose backgroundComponent)
74
+ public var tintColor: Color?
75
+ public var scrollable: Bool
76
+ /// Compose's `ScrollData.scrollToTopCallback`, fired on a status-bar tap.
77
+ public var scrollToTopCallback: (() -> Void)?
78
+ public var useAvoidKeyboard: Bool
79
+ /// Compose's `KeyboardOptions.keyboardShouldPersistTaps`: a tap anywhere hides the keyboard.
80
+ public var keyboardShouldPersistTaps: Bool
81
+ public var headerBackProps: HeaderBackProps?
82
+ /// Toolkit data for the default header right (Compose `HeaderRight.Toolkit`). Use `headerRight`
83
+ /// for a custom view and nil for none.
84
+ public var headerRightData: HeaderRightData?
85
+ public var headerRight: (() -> any View)?
86
+ public var footer: (() -> AnyView)?
87
+ public var footerTransparent: Bool
88
+ public var footerUseMargin: Bool
89
+ public var animatedHeader: AnimatedHeader?
90
+ public var layoutOffset: CGFloat
91
+ public var inputSearchProps: InputSearchProps?
92
+ public var fabProps: FabProps?
93
+ public var onBackHandler: (() -> Void)?
94
+
95
+ public init(
96
+ screenName: String? = nil,
97
+ title: String = "Stack",
98
+ headerTitle: HeaderTitle? = nil,
99
+ titlePosition: TitlePosition = .left,
100
+ headerType: HeaderType = .default,
101
+ useAnimated: Bool = false,
102
+ headerTransparent: Bool = false,
103
+ fullScreenContent: Bool = false,
104
+ hiddenBack: Bool = false,
105
+ backgroundColor: Color? = nil,
106
+ // AI-GENERATED START: custom screen background view (Compose backgroundComponent)
107
+ background: (() -> AnyView)? = nil,
108
+ // AI-GENERATED END: custom screen background view (Compose backgroundComponent)
109
+ tintColor: Color? = Colors.black17,
110
+ scrollable: Bool = true,
111
+ scrollToTopCallback: (() -> Void)? = nil,
112
+ useAvoidKeyboard: Bool = true,
113
+ keyboardShouldPersistTaps: Bool = false,
114
+ headerBackProps: HeaderBackProps? = nil,
115
+ headerRightData: HeaderRightData? = nil,
116
+ headerRight: (() -> any View)? = { HeaderRight() },
117
+ footer: (() -> AnyView)? = nil,
118
+ footerTransparent: Bool = false,
119
+ footerUseMargin: Bool = true,
120
+ animatedHeader: AnimatedHeader? = nil,
121
+ layoutOffset: CGFloat = 56,
122
+ inputSearchProps: InputSearchProps? = nil,
123
+ fabProps: FabProps? = nil,
124
+ onBackHandler: (() -> Void)? = nil
125
+ ) {
126
+ self.screenName = screenName
127
+ self.title = title
128
+ self.headerTitle = headerTitle
129
+ self.titlePosition = titlePosition
130
+ self.headerType = headerType
131
+ self.useAnimated = useAnimated
132
+ self.headerTransparent = headerTransparent
133
+ self.fullScreenContent = fullScreenContent
134
+ self.hiddenBack = hiddenBack
135
+ self.backgroundColor = backgroundColor
136
+ // AI-GENERATED START: custom screen background view (Compose backgroundComponent)
137
+ self.background = background
138
+ // AI-GENERATED END: custom screen background view (Compose backgroundComponent)
139
+ self.tintColor = tintColor
140
+ self.scrollable = scrollable
141
+ self.scrollToTopCallback = scrollToTopCallback
142
+ self.useAvoidKeyboard = useAvoidKeyboard
143
+ self.keyboardShouldPersistTaps = keyboardShouldPersistTaps
144
+ self.headerBackProps = headerBackProps
145
+ self.headerRightData = headerRightData
146
+ self.headerRight = headerRight
147
+ self.footer = footer
148
+ self.footerTransparent = footerTransparent
149
+ self.footerUseMargin = footerUseMargin
150
+ self.animatedHeader = animatedHeader
151
+ self.layoutOffset = layoutOffset
152
+ self.inputSearchProps = inputSearchProps
153
+ self.fabProps = fabProps
154
+ self.onBackHandler = onBackHandler
155
+ }
156
+ }
157
+
158
+ extension NavigationOptions {
159
+ var resolvedHeaderRight: (() -> any View)? {
160
+ guard let headerRightData else { return headerRight }
161
+ return { HeaderRight(headerRight: headerRightData, tintColor: tintColor) }
162
+ }
163
+ }
164
+
165
+ /// `StackScreen` built from options, shared by stack screens and bottom-tab screens.
166
+ struct OptionsStackScreen: View {
167
+ let options: NavigationOptions
168
+ let screenName: String
169
+ let goBack: (() -> Void)?
170
+ let content: () -> AnyView
171
+
172
+ var body: some View {
173
+ StackScreen(
174
+ backgroundColor: options.backgroundColor,
175
+ // AI-GENERATED START: custom screen background view (Compose backgroundComponent)
176
+ background: options.background,
177
+ // AI-GENERATED END: custom screen background view (Compose backgroundComponent)
178
+ headerTransparent: options.headerTransparent,
179
+ fullScreenContent: options.fullScreenContent,
180
+ tintColor: options.tintColor ?? Colors.black17,
181
+ isBack: !options.hiddenBack,
182
+ headerType: options.headerType,
183
+ useAnimated: options.useAnimated,
184
+ title: options.title,
185
+ headerTitle: options.headerTitle,
186
+ titlePosition: options.titlePosition,
187
+ goBack: options.hiddenBack ? nil : goBack,
188
+ scrollable: options.scrollable,
189
+ scrollToTopCallback: options.scrollToTopCallback,
190
+ useAvoidKeyboard: options.useAvoidKeyboard,
191
+ keyboardShouldPersistTaps: options.keyboardShouldPersistTaps,
192
+ footer: options.footer,
193
+ footerTransparent: options.footerTransparent,
194
+ footerUseMargin: options.footerUseMargin,
195
+ headerRight: options.resolvedHeaderRight,
196
+ animatedHeader: options.animatedHeader,
197
+ layoutOffset: options.layoutOffset,
198
+ inputSearchProps: options.inputSearchProps,
199
+ fabProps: options.fabProps,
200
+ screenName: screenName,
201
+ content: content
202
+ )
203
+ }
204
+ }