@momo-kits/native-kits 0.167.1-duo.1-debug → 0.167.1-duo.2-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 (25) hide show
  1. package/CLAUDE.md +7 -0
  2. package/compose/build.gradle.kts +1 -1
  3. package/compose/compose.podspec +1 -1
  4. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +1 -1
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +13 -11
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +21 -9
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +157 -0
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +11 -9
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +4 -0
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +47 -21
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +14 -7
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +37 -16
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +2 -2
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +1 -2
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +1 -2
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +53 -15
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -2
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +169 -0
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +4 -1
  20. package/gradle.properties +1 -1
  21. package/ios/native-kits.podspec +1 -1
  22. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  23. package/package.json +1 -1
  24. package/.claude/settings.local.json +0 -185
  25. package/local.properties +0 -8
@@ -33,12 +33,12 @@ import androidx.compose.ui.unit.dp
33
33
  import vn.momo.kits.components.Icon
34
34
  import vn.momo.kits.components.Image
35
35
  import vn.momo.kits.components.InputSearchProps
36
- import vn.momo.kits.const.AppStatusBar
37
36
  import vn.momo.kits.const.AppTheme
38
37
  import vn.momo.kits.const.Colors
39
38
  import vn.momo.kits.components.PopupNotifyProps
40
39
  import vn.momo.kits.application.IsShowBaseLineDebug
41
40
  import vn.momo.kits.const.Spacing
41
+ import vn.momo.kits.layout.getScreenLayout
42
42
  import vn.momo.kits.modifier.activeOpacityClickable
43
43
  import vn.momo.kits.modifier.conditional
44
44
  import vn.momo.kits.modifier.setAutomationId
@@ -47,6 +47,7 @@ import vn.momo.kits.navigation.LocalNavigator
47
47
  import vn.momo.kits.navigation.LocalOptions
48
48
  import vn.momo.kits.navigation.LocalScrollState
49
49
  import vn.momo.kits.navigation.getInputSearchType
50
+ import vn.momo.kits.platform.getScreenDimensions
50
51
  import vn.momo.kits.utils.horizontalSafeAreaPadding
51
52
 
52
53
  @InternalApi
@@ -54,27 +55,44 @@ const val HEADER_HEIGHT = 52
54
55
  internal enum class InputSearchType { None, Header, Animated }
55
56
  enum class TitlePosition { LEFT, CENTER }
56
57
 
58
+ private val HEADER_ACTIONS_WIDTH = 172.dp
59
+
57
60
  @Suppress("FrequentlyChangingValue")
58
61
  @Composable
59
- internal fun Header(onBackHandler: (() -> Unit)? = null) {
62
+ internal fun headerOpacity(): Float {
60
63
  val options = LocalOptions.current
61
- val navigator = LocalNavigator.current
62
64
  val scrollState = LocalScrollState.current
63
- val headerRightWidthPx = LocalHeaderRightWidthPx.current
64
- val inputSearchType = getInputSearchType(options)
65
-
66
65
  val opacityHeight = when (val header = options.headerType) {
67
66
  is HeaderType.Animated -> with(LocalDensity.current) { header.layoutOffSet.roundToPx() }
68
67
  else -> HEADER_HEIGHT
69
68
  }
70
69
  val opacity by animateFloatAsState(
71
- targetValue = if (options.headerType is HeaderType.Transparent) {
72
- 0f
73
- } else {
74
- (scrollState.value / opacityHeight.toFloat())
75
- .coerceIn(0f, 1f)
70
+ targetValue = when {
71
+ options.headerType is HeaderType.Transparent -> 0f
72
+ opacityHeight <= 0 -> if (scrollState.value > 0) 1f else 0f
73
+ else -> (scrollState.value / opacityHeight.toFloat()).coerceIn(0f, 1f)
76
74
  }
77
75
  )
76
+ return opacity
77
+ }
78
+
79
+ // Back button and toolkit share the bar with the title unless the iPhone Duo side bar holds them.
80
+ @Composable
81
+ internal fun headerTitleMaxWidth(): Dp {
82
+ val layout = getScreenLayout()
83
+ if (layout.sideBar != null) return layout.contentWidth - Spacing.M * 2
84
+ return getScreenDimensions().width.dp - HEADER_ACTIONS_WIDTH
85
+ }
86
+
87
+ @Composable
88
+ internal fun Header(onBackHandler: (() -> Unit)? = null) {
89
+ val options = LocalOptions.current
90
+ val navigator = LocalNavigator.current
91
+ val headerRightWidthPx = LocalHeaderRightWidthPx.current
92
+ val inputSearchType = getInputSearchType(options)
93
+ val layout = getScreenLayout()
94
+ val useSideBar = layout.sideBar != null
95
+ val opacity = headerOpacity()
78
96
 
79
97
  val headerColor = getHeaderColor(options.headerType, opacity, options.tintColor, Colors.black_17)
80
98
 
@@ -97,7 +115,7 @@ internal fun Header(onBackHandler: (() -> Unit)? = null) {
97
115
  .takeUnless { options.headerType is HeaderType.Transparent }
98
116
 
99
117
  Box(
100
- Modifier.height(AppStatusBar.current + HEADER_HEIGHT.dp)
118
+ Modifier.height(layout.headerHeight)
101
119
  .fillMaxWidth()
102
120
  .conditional(headerImage.isNullOrEmpty()) {
103
121
  background(background.copy(alpha = animatedAlpha))
@@ -126,14 +144,14 @@ internal fun Header(onBackHandler: (() -> Unit)? = null) {
126
144
  }
127
145
  }
128
146
  Row(
129
- modifier = Modifier.height(HEADER_HEIGHT.dp)
147
+ modifier = Modifier.height(layout.headerBarHeight)
130
148
  .fillMaxWidth()
131
149
  .horizontalSafeAreaPadding()
132
150
  .padding(horizontal = Spacing.M),
133
151
  verticalAlignment = Alignment.CenterVertically,
134
152
  horizontalArrangement = Arrangement.SpaceBetween
135
153
  ) {
136
- if(!options.hiddenBack) {
154
+ if (!options.hiddenBack && !useSideBar) {
137
155
  BackButton(
138
156
  borderColor = headerColor.borderColor,
139
157
  backgroundButton = headerColor.backgroundButton,
@@ -158,13 +176,16 @@ internal fun Header(onBackHandler: (() -> Unit)? = null) {
158
176
  Box(Modifier.onGloballyPositioned {
159
177
  if(headerRightWidthPx.intValue != it.size.width) headerRightWidthPx.intValue = it.size.width
160
178
  }){
161
- HeaderRight(options.headerRight, options.tintColor, headerColor)
179
+ if (!(useSideBar && options.headerRight is HeaderRight.Toolkit)) {
180
+ HeaderRight(options.headerRight, options.tintColor, headerColor)
181
+ }
162
182
  }
163
183
  }
164
184
  if (centerTitle) {
165
185
  Box(
166
- modifier = Modifier.height(HEADER_HEIGHT.dp)
186
+ modifier = Modifier.height(layout.headerBarHeight)
167
187
  .fillMaxWidth()
188
+ .horizontalSafeAreaPadding()
168
189
  .padding(horizontal = Spacing.M),
169
190
  contentAlignment = Alignment.Center
170
191
  ) {
@@ -15,8 +15,8 @@ import androidx.compose.ui.graphics.Color
15
15
  import androidx.compose.ui.platform.LocalDensity
16
16
  import androidx.compose.ui.unit.dp
17
17
  import vn.momo.kits.components.Image
18
- import vn.momo.kits.const.AppStatusBar
19
18
  import vn.momo.kits.const.AppTheme
19
+ import vn.momo.kits.layout.getScreenLayout
20
20
  import vn.momo.kits.modifier.conditional
21
21
  import vn.momo.kits.navigation.LocalOptions
22
22
  import vn.momo.kits.navigation.LocalScrollState
@@ -38,7 +38,7 @@ internal fun HeaderBackground() {
38
38
  val scrollState = LocalScrollState.current
39
39
  val backgroundColor = options.backgroundColor ?: AppTheme.current.colors.background.default
40
40
 
41
- val minHeight = AppStatusBar.current + HEADER_HEIGHT.dp
41
+ val minHeight = getScreenLayout().headerHeight
42
42
  val maxHeight = HEADER_BACKGROUND_HEIGHT
43
43
  val opacity by animateFloatAsState(
44
44
  targetValue = (1 - (scrollState.value * 1f / HEADER_HEIGHT * 1f)).coerceIn(0f, 1f),
@@ -23,7 +23,6 @@ import vn.momo.kits.components.Text
23
23
  import vn.momo.kits.const.Spacing
24
24
  import vn.momo.kits.const.Typography
25
25
  import vn.momo.kits.modifier.activeOpacityClickable
26
- import vn.momo.kits.platform.getScreenDimensions
27
26
 
28
27
  @Composable
29
28
  internal fun HeaderJourney(
@@ -33,7 +32,7 @@ internal fun HeaderJourney(
33
32
  if (data !is HeaderTitle.Journey) return
34
33
  if (data.isLoading) return TitleJourneyShimmer()
35
34
 
36
- val maxWidth = getScreenDimensions().width.dp - 172.dp
35
+ val maxWidth = headerTitleMaxWidth()
37
36
  val tint = parseHeaderTint(data.tintColor) ?: tintIconColor
38
37
  val iconTint = parseHeaderTint(data.iconColor) ?: tint
39
38
 
@@ -22,7 +22,6 @@ import vn.momo.kits.components.Text
22
22
  import vn.momo.kits.const.Spacing
23
23
  import vn.momo.kits.const.Typography
24
24
  import vn.momo.kits.modifier.activeOpacityClickable
25
- import vn.momo.kits.platform.getScreenDimensions
26
25
 
27
26
  @Composable
28
27
  internal fun HeaderLocation(
@@ -32,7 +31,7 @@ internal fun HeaderLocation(
32
31
  if (data !is HeaderTitle.Location) return
33
32
  if (data.isLoading) return TitleLocationShimmer()
34
33
 
35
- val maxWidth = getScreenDimensions().width.dp - 172.dp
34
+ val maxWidth = headerTitleMaxWidth()
36
35
  val tint = parseHeaderTint(data.tintColor) ?: tintIconColor
37
36
 
38
37
  Column(
@@ -6,6 +6,7 @@ import androidx.compose.foundation.background
6
6
  import androidx.compose.foundation.border
7
7
  import androidx.compose.foundation.layout.Arrangement
8
8
  import androidx.compose.foundation.layout.Box
9
+ import androidx.compose.foundation.layout.Column
9
10
  import androidx.compose.foundation.layout.Row
10
11
  import androidx.compose.foundation.layout.height
11
12
  import androidx.compose.foundation.layout.offset
@@ -63,7 +64,8 @@ fun HeaderRight(
63
64
  internal fun Toolkit(
64
65
  headerRight: HeaderRight.Toolkit,
65
66
  tintColor: Color? = null,
66
- headerColor: HeaderColor
67
+ headerColor: HeaderColor,
68
+ vertical: Boolean = false,
67
69
  ) {
68
70
  val api = LocalMaxApi.current
69
71
  val context = LocalContext.current
@@ -103,6 +105,23 @@ internal fun Toolkit(
103
105
  }
104
106
  }
105
107
 
108
+ fun onPressHelpCenter() {
109
+ if (context == null) return
110
+ api?.showHelpCenter(
111
+ mapOf(
112
+ "appId" to context.appId,
113
+ "code" to context.appCode,
114
+ "name" to context.appName,
115
+ "icon" to context.appIcon,
116
+ "description" to context.description
117
+ )
118
+ ) {}
119
+ }
120
+
121
+ fun onPressHome() {
122
+ api?.dismissAll { }
123
+ }
124
+
106
125
  val navButtonConfig = getNavigationButtonConfig(
107
126
  headerRight,
108
127
  ::onPressShortcut,
@@ -127,6 +146,37 @@ internal fun Toolkit(
127
146
  }
128
147
  }
129
148
 
149
+ if (vertical) {
150
+ Column(verticalArrangement = Arrangement.spacedBy(Spacing.M)) {
151
+ if (isShowShortcut) {
152
+ SideBarButton(
153
+ icon = icon,
154
+ headerColor = headerColor,
155
+ enabled = !isLoading,
156
+ showBadge = showBadge,
157
+ onClick = navButtonConfig.onPress,
158
+ )
159
+ }
160
+ SideBarGroup(headerColor = headerColor, itemCount = if (context != null) 2 else 1) {
161
+ if (context != null) {
162
+ SideBarGroupItem(
163
+ icon = "help_center",
164
+ headerColor = headerColor,
165
+ automationId = "btn_navigation_help_center",
166
+ onClick = ::onPressHelpCenter,
167
+ )
168
+ }
169
+ SideBarGroupItem(
170
+ icon = "16_basic_home",
171
+ headerColor = headerColor,
172
+ automationId = "btn_navigation_close",
173
+ onClick = ::onPressHome,
174
+ )
175
+ }
176
+ }
177
+ return
178
+ }
179
+
130
180
  Row(
131
181
  verticalAlignment = Alignment.CenterVertically
132
182
  ) {
@@ -155,17 +205,7 @@ internal fun Toolkit(
155
205
  source = "help_center",
156
206
  size = 20.dp,
157
207
  color = headerColor.tintIconColor,
158
- modifier = Modifier.padding(4.dp).activeOpacityClickable {
159
- api?.showHelpCenter(
160
- mapOf(
161
- "appId" to context.appId,
162
- "code" to context.appCode,
163
- "name" to context.appName,
164
- "icon" to context.appIcon,
165
- "description" to context.description
166
- )
167
- ) {}
168
- }
208
+ modifier = Modifier.padding(4.dp).activeOpacityClickable(onClick = ::onPressHelpCenter)
169
209
  )
170
210
  Box(
171
211
  modifier = Modifier
@@ -178,9 +218,7 @@ internal fun Toolkit(
178
218
  source = "16_basic_home",
179
219
  size = 20.dp,
180
220
  color = headerColor.tintIconColor,
181
- modifier = Modifier.padding(4.dp).activeOpacityClickable {
182
- api?.dismissAll { }
183
- }
221
+ modifier = Modifier.padding(4.dp).activeOpacityClickable(onClick = ::onPressHome)
184
222
  )
185
223
  }
186
224
  }
@@ -32,7 +32,6 @@ import vn.momo.kits.const.Typography
32
32
  import vn.momo.kits.const.getFontFamily
33
33
  import vn.momo.kits.modifier.activeOpacityClickable
34
34
  import vn.momo.kits.navigation.component.HeaderTitle.User
35
- import vn.momo.kits.platform.getScreenDimensions
36
35
 
37
36
  @Composable
38
37
  internal fun HeaderUser(
@@ -44,7 +43,7 @@ internal fun HeaderUser(
44
43
  return TitleUserShimmer()
45
44
  }
46
45
 
47
- val maxWidth = getScreenDimensions().width.dp - 172.dp
46
+ val maxWidth = headerTitleMaxWidth()
48
47
 
49
48
  Row(
50
49
  modifier = Modifier
@@ -0,0 +1,169 @@
1
+ package vn.momo.kits.navigation.component
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.border
5
+ import androidx.compose.foundation.layout.Arrangement
6
+ import androidx.compose.foundation.layout.Box
7
+ import androidx.compose.foundation.layout.BoxScope
8
+ import androidx.compose.foundation.layout.Column
9
+ import androidx.compose.foundation.layout.ColumnScope
10
+ import androidx.compose.foundation.layout.Spacer
11
+ import androidx.compose.foundation.layout.absolutePadding
12
+ import androidx.compose.foundation.layout.fillMaxWidth
13
+ import androidx.compose.foundation.layout.height
14
+ import androidx.compose.foundation.layout.offset
15
+ import androidx.compose.foundation.layout.size
16
+ import androidx.compose.foundation.layout.width
17
+ import androidx.compose.foundation.shape.CircleShape
18
+ import androidx.compose.foundation.shape.RoundedCornerShape
19
+ import androidx.compose.runtime.Composable
20
+ import androidx.compose.ui.AbsoluteAlignment
21
+ import androidx.compose.ui.Alignment
22
+ import androidx.compose.ui.Modifier
23
+ import androidx.compose.ui.draw.clip
24
+ import androidx.compose.ui.draw.shadow
25
+ import androidx.compose.ui.graphics.Shape
26
+ import androidx.compose.ui.layout.layout
27
+ import androidx.compose.ui.unit.Dp
28
+ import androidx.compose.ui.unit.constrainHeight
29
+ import androidx.compose.ui.unit.dp
30
+ import vn.momo.kits.components.BadgeDot
31
+ import vn.momo.kits.components.DotSize
32
+ import vn.momo.kits.components.Icon
33
+ import vn.momo.kits.const.Colors
34
+ import vn.momo.kits.const.Radius
35
+ import vn.momo.kits.const.Spacing
36
+ import vn.momo.kits.layout.DuoMetrics
37
+ import vn.momo.kits.layout.SideBarEdge
38
+ import vn.momo.kits.layout.getScreenLayout
39
+ import vn.momo.kits.modifier.activeOpacityClickable
40
+ import vn.momo.kits.modifier.conditional
41
+ import vn.momo.kits.modifier.setAutomationId
42
+ import vn.momo.kits.navigation.LocalNavigator
43
+ import vn.momo.kits.navigation.LocalOptions
44
+
45
+ private val SIDE_BAR_ICON_SIZE = 24.dp
46
+
47
+ // iPhone Duo: back and toolkit leave the bar for a column in the side safe area, as the system bars do.
48
+ // bottomInset is what footer / tab bar / home indicator take from the bottom; the column stays above it.
49
+ @Composable
50
+ internal fun BoxScope.HeaderSideBar(bottomInset: Dp, modifier: Modifier = Modifier) {
51
+ val options = LocalOptions.current
52
+ val navigator = LocalNavigator.current
53
+ val sideBar = getScreenLayout().sideBar ?: return
54
+ val toolkit = options.headerRight as? HeaderRight.Toolkit
55
+ if (options.headerType == HeaderType.None || (options.hiddenBack && toolkit == null)) return
56
+
57
+ val headerColor = getHeaderColor(options.headerType, headerOpacity(), options.tintColor, Colors.black_17)
58
+ val isRight = sideBar.edge == SideBarEdge.RIGHT
59
+
60
+ Column(
61
+ modifier = modifier
62
+ .align(if (isRight) AbsoluteAlignment.TopRight else AbsoluteAlignment.TopLeft)
63
+ .width(sideBar.width)
64
+ .layout { measurable, constraints ->
65
+ val placeable = measurable.measure(constraints.copy(minHeight = 0))
66
+ val maxY = constraints.maxHeight - (bottomInset + Spacing.XL).roundToPx() - placeable.height
67
+ val y = minOf(sideBar.top.roundToPx(), maxY).coerceAtLeast(0)
68
+ layout(placeable.width, constraints.constrainHeight(y + placeable.height)) {
69
+ placeable.place(0, y)
70
+ }
71
+ }
72
+ .absolutePadding(left = if (isRight) Spacing.M else 0.dp, right = if (isRight) 0.dp else Spacing.M),
73
+ horizontalAlignment = if (isRight) AbsoluteAlignment.Left else AbsoluteAlignment.Right,
74
+ verticalArrangement = Arrangement.spacedBy(Spacing.M),
75
+ ) {
76
+ if (options.hiddenBack) {
77
+ // keep the slot so the toolkit does not jump between root and pushed screens
78
+ Spacer(Modifier.size(DuoMetrics.controlSize))
79
+ } else {
80
+ SideBarButton(
81
+ icon = "arrow-back",
82
+ headerColor = headerColor,
83
+ automationId = "btn_navigation_back",
84
+ onClick = { navigator.onBackSafe { } },
85
+ )
86
+ }
87
+ if (toolkit != null) {
88
+ Toolkit(headerRight = toolkit, tintColor = options.tintColor, headerColor = headerColor, vertical = true)
89
+ }
90
+ }
91
+ }
92
+
93
+ @Composable
94
+ internal fun SideBarButton(
95
+ icon: String,
96
+ headerColor: HeaderColor,
97
+ onClick: () -> Unit,
98
+ enabled: Boolean = true,
99
+ showBadge: Boolean = false,
100
+ automationId: String? = null,
101
+ ) {
102
+ Box {
103
+ Box(
104
+ modifier = Modifier
105
+ .size(DuoMetrics.controlSize)
106
+ .sideBarGlass(headerColor, CircleShape)
107
+ .activeOpacityClickable(enabled = enabled, onClick = onClick)
108
+ .conditional(automationId != null) { setAutomationId(automationId.orEmpty()) },
109
+ contentAlignment = Alignment.Center,
110
+ ) {
111
+ Icon(source = icon, size = SIDE_BAR_ICON_SIZE, color = headerColor.tintIconColor)
112
+ }
113
+ if (showBadge) {
114
+ BadgeDot(
115
+ size = DotSize.Small,
116
+ modifier = Modifier.align(Alignment.TopEnd).offset(x = -Spacing.XXS, y = Spacing.XXS),
117
+ )
118
+ }
119
+ }
120
+ }
121
+
122
+ // Capsule grouping related controls, one item per 50pt.
123
+ @Composable
124
+ internal fun SideBarGroup(
125
+ headerColor: HeaderColor,
126
+ itemCount: Int,
127
+ content: @Composable ColumnScope.() -> Unit,
128
+ ) {
129
+ val height = if (itemCount > 1) DuoMetrics.itemPitch * itemCount else DuoMetrics.controlSize
130
+ Column(
131
+ modifier = Modifier
132
+ .width(DuoMetrics.controlSize)
133
+ .height(height)
134
+ .sideBarGlass(headerColor, RoundedCornerShape(Radius.XL)),
135
+ content = content,
136
+ )
137
+ }
138
+
139
+ @Composable
140
+ internal fun ColumnScope.SideBarGroupItem(
141
+ icon: String,
142
+ headerColor: HeaderColor,
143
+ automationId: String,
144
+ onClick: () -> Unit,
145
+ ) {
146
+ Box(
147
+ modifier = Modifier
148
+ .weight(1f)
149
+ .fillMaxWidth()
150
+ .activeOpacityClickable(onClick = onClick)
151
+ .setAutomationId(automationId),
152
+ contentAlignment = Alignment.Center,
153
+ ) {
154
+ Icon(source = icon, size = SIDE_BAR_ICON_SIZE, color = headerColor.tintIconColor)
155
+ }
156
+ }
157
+
158
+ // Dark glass under light icons (banner headers), light glass otherwise. The light one is opaque:
159
+ // Compose has no backdrop blur and a translucent fill shows its own shadow through (RN uses 85% white).
160
+ private fun Modifier.sideBarGlass(headerColor: HeaderColor, shape: Shape): Modifier =
161
+ if (headerColor.tintIconColor == Colors.black_01) {
162
+ clip(shape)
163
+ .background(Colors.black_20.copy(alpha = 0.5f))
164
+ .border(0.5.dp, Colors.black_01.copy(alpha = 0.2f), shape)
165
+ } else {
166
+ shadow(3.dp, shape)
167
+ .background(Colors.black_01)
168
+ .border(0.5.dp, Colors.black_20.copy(alpha = 0.08f), shape)
169
+ }
@@ -95,9 +95,12 @@ fun getAppStatusBarHeight(): Dp {
95
95
  }
96
96
  }
97
97
 
98
+ internal val horizontalSafeAreaInsets: WindowInsets
99
+ @Composable get() = WindowInsets.systemBars.union(WindowInsets.displayCutout).only(WindowInsetsSides.Horizontal)
100
+
98
101
  // Left/right safe area like SwiftUI (landscape camera/notch); consumed, so nested StackScreens don't pad twice.
99
102
  internal fun Modifier.horizontalSafeAreaPadding(): Modifier = composed {
100
- windowInsetsPadding(WindowInsets.systemBars.union(WindowInsets.displayCutout).only(WindowInsetsSides.Horizontal))
103
+ windowInsetsPadding(horizontalSafeAreaInsets)
101
104
  }
102
105
 
103
106
  @Composable
package/gradle.properties CHANGED
@@ -18,7 +18,7 @@ kotlin.apple.xcodeCompatibility.nowarn=true
18
18
  name="ComposeKits"
19
19
  group=vn.momo.kits
20
20
  artifact.id=kits
21
- version=0.167.1-duo.1
21
+ version=0.167.1-beta.4
22
22
 
23
23
  repo=GitLab
24
24
  url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKits'
3
- s.version = '0.167.1-duo.1'
3
+ s.version = '0.167.1-beta.4'
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-duo.1'
3
+ s.version = '0.167.1-beta.4'
4
4
  s.summary = 'Demo browser for MoMoUIKits SwiftUI components'
5
5
  s.homepage = 'https://momo.vn'
6
6
  s.license = { :type => 'MIT' }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.167.1-duo.1-debug",
3
+ "version": "0.167.1-duo.2-debug",
4
4
  "private": false,
5
5
  "dependeNavigationncies": {},
6
6
  "devDependencies": {},