@momo-kits/native-kits 0.161.2-search-header.1-debug → 0.161.3-beta.1-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 (27) hide show
  1. package/compose/build.gradle.kts +1 -1
  2. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +14 -8
  3. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +26 -21
  4. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -4
  5. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +12 -27
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +28 -1
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +1 -1
  8. package/example/ios/Example.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +1 -1
  9. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  10. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +5 -5
  11. package/gradle/libs.versions.toml +1 -1
  12. package/gradle.properties +1 -1
  13. package/ios/Application/ApplicationEnvironment.swift +6 -2
  14. package/ios/Input/Input.swift +19 -19
  15. package/ios/Input/InputPhoneNumber.swift +17 -17
  16. package/ios/Typography/Text.swift +14 -19
  17. package/ios/Typography/Typography.swift +1 -22
  18. package/local.properties +2 -2
  19. package/package.json +1 -1
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
  21. package/example/ios/Example.xcodeproj/xcuserdata/vunh.xcuserdatad/xcschemes/ios.xcscheme +0 -36
  22. /package/example/ios/Example.xcworkspace/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +0 -0
  23. /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/MoMoUIKits.xcscheme +0 -0
  24. /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/Pods-Example.xcscheme +0 -0
  25. /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SDWebImage.xcscheme +0 -0
  26. /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SDWebImageSwiftUI.xcscheme +0 -0
  27. /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SkeletonUI.xcscheme +0 -0
@@ -40,7 +40,7 @@ kotlin {
40
40
  }
41
41
 
42
42
  cocoapods {
43
- version = "0.161.2-search-header.1-debug"
43
+ version = "0.161.3-beta.1-debug"
44
44
  summary = "IOS Shared module"
45
45
  homepage = "https://momo.vn"
46
46
  ios.deploymentTarget = "15.0"
@@ -1,12 +1,15 @@
1
1
  package vn.momo.kits.application
2
2
 
3
3
  import androidx.compose.runtime.Immutable
4
+ import androidx.compose.runtime.mutableStateOf
4
5
  import androidx.compose.runtime.staticCompositionLocalOf
5
6
  import vn.momo.kits.components.TrustBannerData
6
7
 
7
8
  @Immutable
8
9
  data class FeatureFlags(
9
- val showBaseLineDebug: Boolean? = false,
10
+ val isBaselineEnabled: Boolean? = false,
11
+ val isWhiteList: Boolean? = false,
12
+ val allowFontScale: Boolean? = true,
10
13
  )
11
14
 
12
15
  @Immutable
@@ -28,7 +31,6 @@ data class MiniAppContext(
28
31
  val providerId: String = "",
29
32
  val permissions: List<Map<String, Any>>? = emptyList(),
30
33
  val features: FeatureFlags? = null,
31
- val scaleSizeMaxRate: Float? = null,
32
34
  ) {
33
35
  companion object {
34
36
 
@@ -60,7 +62,6 @@ data class MiniAppContext(
60
62
  providerId = parent.providerId.ifBlank { child.providerId },
61
63
  permissions = if (!parent.permissions.isNullOrEmpty()) parent.permissions else child.permissions,
62
64
  features = mergeFeatureFlags(parent.features, child.features),
63
- scaleSizeMaxRate = parent.scaleSizeMaxRate ?: child.scaleSizeMaxRate,
64
65
  )
65
66
  }
66
67
 
@@ -74,7 +75,7 @@ data class MiniAppContext(
74
75
  if (child == null) return parent
75
76
 
76
77
  return FeatureFlags(
77
- showBaseLineDebug = parent.showBaseLineDebug ?: child.showBaseLineDebug
78
+ isBaselineEnabled = parent.isBaselineEnabled ?: child.isBaselineEnabled
78
79
  )
79
80
  }
80
81
  }
@@ -88,12 +89,19 @@ data class ComponentInformation(
88
89
  val action: String? = null
89
90
  )
90
91
 
91
- var IsShowBaseLineDebug = false
92
-
93
92
  val ApplicationContext = staticCompositionLocalOf<MiniAppContext?> {
94
93
  null
95
94
  }
96
95
 
96
+ var IsShowBaseLineDebug = false
97
+
98
+ private val UseFontScaleSystemState = mutableStateOf(true)
99
+ var UseFontScaleSystem: Boolean
100
+ get() = UseFontScaleSystemState.value
101
+ set(value) {
102
+ UseFontScaleSystemState.value = value
103
+ }
104
+
97
105
  val AppConfig = staticCompositionLocalOf<KitConfig?> {
98
106
  null
99
107
  }
@@ -105,5 +113,3 @@ val AppLanguage = staticCompositionLocalOf<String?> {
105
113
  val LocalComponentInformation = staticCompositionLocalOf<ComponentInformation?> {
106
114
  null
107
115
  }
108
-
109
- val ScaleSizeMaxRate = staticCompositionLocalOf<Float?> { null }
@@ -69,9 +69,10 @@ import androidx.compose.ui.unit.LayoutDirection
69
69
  import androidx.compose.ui.unit.dp
70
70
  import androidx.compose.ui.unit.sp
71
71
  import androidx.compose.runtime.staticCompositionLocalOf
72
- import androidx.compose.ui.draw.drawWithCache
72
+ import androidx.compose.ui.graphics.Color.Companion
73
73
  import androidx.compose.ui.graphics.SolidColor
74
74
  import androidx.compose.ui.unit.lerp
75
+ import kotlinx.coroutines.flow.StateFlow
75
76
  import kotlinx.coroutines.flow.collectLatest
76
77
  import kotlinx.coroutines.flow.mapNotNull
77
78
  import vn.momo.kits.components.Icon
@@ -80,11 +81,11 @@ import vn.momo.kits.const.AppTheme
80
81
  import vn.momo.kits.const.Colors
81
82
  import vn.momo.kits.const.Spacing
82
83
  import vn.momo.kits.const.Typography
84
+ import vn.momo.kits.modifier.conditional
83
85
  import vn.momo.kits.modifier.kitsAutomationId
84
86
  import vn.momo.kits.modifier.noFeedbackClickable
85
87
  import vn.momo.kits.modifier.setAutomationId
86
88
  import vn.momo.kits.modifier.shadow
87
- import vn.momo.kits.navigation.component.HEADER_HEIGHT
88
89
  import vn.momo.kits.utils.getAppStatusBarHeight
89
90
  import kotlin.math.max
90
91
  import kotlin.math.roundToInt
@@ -440,7 +441,6 @@ private class LiteScreenLayoutPolicy(
440
441
  val spacing12 = Spacing.M.roundToPx()
441
442
  val spaceBetween = headerSpaceBetween?.roundToPx() ?: spacing12
442
443
  val statusBarPx = statusBarHeight.roundToPx()
443
- val headerRowDefault = HEADER_HEIGHT.dp.roundToPx()
444
444
  val scrollPercent = scrollPercentage.value
445
445
 
446
446
  val contentMeasurable = measurables.find { it.layoutId == HeaderId.CONTENT_ID }
@@ -484,20 +484,26 @@ private class LiteScreenLayoutPolicy(
484
484
  )
485
485
  )
486
486
 
487
- /**
488
- * replicate logic from [vn.momo.kits.navigation.component.HeaderBackground]
489
- * */
490
- var defaultHeight = statusBarPx + headerRowDefault
487
+ val firstRowMaxHeight = buildList {
488
+ add(backIconPlaceable.safeHeight)
489
+ add(headerRightPlaceable.safeHeight)
490
+ if (!isHeaderExtend) {
491
+ add(inputSearchPlaceable.safeHeight)
492
+ }
493
+ add(HEADER_HEIGHT.dp.roundToPx())
494
+ if (isHeaderExtend) {
495
+ add(titlePlaceable.safeHeight)
496
+ }
497
+ }.max()
498
+
499
+ var defaultHeight = statusBarPx + spacing12 + firstRowMaxHeight + spacing12
491
500
  if (isHeaderExtend) {
492
- defaultHeight = 154.dp.roundToPx()
501
+ defaultHeight += inputSearchPlaceable.safeHeight + spacing12
493
502
  }
494
503
  val headerHeight = when {
495
504
  isHeaderNone -> statusBarPx
496
505
  !useAnimationSearch && !isHeaderExtend -> defaultHeight
497
- else -> {
498
- val collapsableSpace = defaultHeight - statusBarPx - headerRowDefault
499
- (defaultHeight - scrollPercent * collapsableSpace).toInt()
500
- }
506
+ else -> (defaultHeight - scrollPercent * (defaultHeight - statusBarPx - HEADER_HEIGHT.dp.roundToPx())).toInt()
501
507
  }
502
508
 
503
509
  val layoutWidth = constraints.maxWidth
@@ -560,14 +566,14 @@ private class LiteScreenLayoutPolicy(
560
566
  if (backIconPlaceable != null) {
561
567
  backIconPlaceable.place(
562
568
  x = startX,
563
- y = startY + backIconPlaceable.verticalCenterOffset(headerRowDefault),
569
+ y = startY + backIconPlaceable.verticalCenterOffset(firstRowMaxHeight),
564
570
  )
565
571
  curX += backIconPlaceable.safeWidth + spaceBetween
566
572
  }
567
573
 
568
574
  headerRightPlaceable?.place(
569
575
  x = layoutWidth - spacing12 - headerRightPlaceable.safeWidth,
570
- y = startY + headerRightPlaceable.verticalCenterOffset(headerRowDefault),
576
+ y = startY + headerRightPlaceable.verticalCenterOffset(firstRowMaxHeight),
571
577
  )
572
578
 
573
579
  val titleOffset = IntOffset(
@@ -576,19 +582,19 @@ private class LiteScreenLayoutPolicy(
576
582
  space = layoutWidth,
577
583
  layoutDirection = layoutDirection,
578
584
  ),
579
- y = startY + titlePlaceable.verticalCenterOffset(headerRowDefault),
585
+ y = startY + titlePlaceable.verticalCenterOffset(firstRowMaxHeight),
580
586
  )
581
587
 
582
588
  titlePlaceable?.place(titleOffset)
583
589
 
584
590
  if (backIconPlaceable != null || headerRightPlaceable != null || titlePlaceable != null) {
585
- curY += headerRowDefault
591
+ curY += firstRowMaxHeight
586
592
  }
587
593
 
588
594
  val inputSearchOffset = if (isHeaderExtend) {
589
- val baseY = curY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault)
595
+ val baseY = curY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight)
590
596
  val y = (baseY * (1 - scrollPercent)).toInt().coerceAtLeast(
591
- startY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault)
597
+ startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight)
592
598
  )
593
599
  IntOffset(
594
600
  x = startX + ((backIconPlaceable.safeWidth + spaceBetween) * (scrollPercent * 2f).coerceIn(
@@ -599,7 +605,7 @@ private class LiteScreenLayoutPolicy(
599
605
  } else {
600
606
  IntOffset(
601
607
  x = curX,
602
- y = startY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault),
608
+ y = startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight),
603
609
  )
604
610
  }
605
611
  val finalPosition = lerp(
@@ -817,8 +823,7 @@ private fun LiteInputSearch(
817
823
  if (!placeHolder.isNullOrEmpty()) {
818
824
  inputSearchProps.customPlaceHolder?.invoke() ?: Text(
819
825
  text = placeHolder ?: "",
820
- style = inputSearchProps.customTextStyle
821
- ?: Typography.bodyDefaultRegular,
826
+ style = inputSearchProps.customTextStyle ?: Typography.bodyDefaultRegular,
822
827
  maxLines = 1,
823
828
  color = theme.colors.text.hint,
824
829
  overflow = TextOverflow.Ellipsis
@@ -21,10 +21,6 @@ import androidx.compose.ui.graphics.Color
21
21
  import androidx.compose.ui.graphics.PathEffect
22
22
  import androidx.compose.ui.graphics.StrokeCap
23
23
  import androidx.compose.ui.unit.dp
24
- import io.ktor.util.Platform
25
- import vn.momo.kits.application.IsShowBaseLineDebug
26
- import vn.momo.kits.const.Colors
27
- import vn.momo.kits.modifier.conditional
28
24
  import vn.momo.kits.platform.getPlatformName
29
25
  import vn.momo.kits.platform.getStatusBarHeight
30
26
 
@@ -7,15 +7,11 @@ import androidx.compose.ui.text.TextStyle
7
7
  import androidx.compose.ui.text.font.FontFamily
8
8
  import androidx.compose.ui.text.font.FontWeight
9
9
  import androidx.compose.ui.text.style.TextDecoration
10
- import androidx.compose.ui.unit.Dp
11
- import androidx.compose.ui.unit.TextUnit
12
- import androidx.compose.ui.unit.TextUnitType
13
- import androidx.compose.ui.unit.dp
14
- import androidx.compose.ui.unit.sp
10
+ import androidx.compose.ui.unit.*
15
11
  import org.jetbrains.compose.resources.Font
16
12
  import org.jetbrains.compose.resources.FontResource
17
13
  import org.jetbrains.compose.resources.InternalResourceApi
18
- import vn.momo.kits.application.ScaleSizeMaxRate
14
+ import vn.momo.kits.application.UseFontScaleSystem
19
15
  import vn.momo.kits.platform.getScreenDimensions
20
16
  import vn.momo.uikits.resources.Res
21
17
  import vn.momo.uikits.resources.momosignature
@@ -33,34 +29,23 @@ import kotlin.math.max
33
29
  import kotlin.math.min
34
30
 
35
31
  const val DEFAULT_SCREEN_SIZE = 375f
36
- const val MAX_FONT_SCALE = 1.5f
37
- const val MAX_DEVICE_SCALE = 5
32
+ const val MAX_FONT_SCALE = 1.2f
38
33
 
39
34
  @Composable
40
35
  fun scaleSize(size: Float): Float {
41
- val scaleSizeMaxRate: Float = ScaleSizeMaxRate.current ?: MAX_FONT_SCALE
42
- val deviceWidth = getScreenDimensions().width
43
- val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
36
+ if (UseFontScaleSystem) {
37
+ val deviceWidth = getScreenDimensions().width
38
+ val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
39
+ val fontScale = LocalDensity.current.fontScale
44
40
 
45
- val density = LocalDensity.current
46
- val fontScale = density.fontScale
47
-
48
- var fontSizeScaleDevice = size
49
- var fontSizeScaleOS = size
41
+ val maxSize = size * MAX_FONT_SCALE
42
+ val fontSizeScaleDevice = if (deviceScale > 1) deviceScale * size else size
43
+ val fontSizeScaleOS = if (fontScale > 1) fontScale * size else size
50
44
 
51
- if (deviceScale > 1) {
52
- fontSizeScaleDevice =
53
- min(deviceScale * fontSizeScaleDevice, fontSizeScaleDevice + MAX_DEVICE_SCALE)
45
+ return min(max(fontSizeScaleDevice, fontSizeScaleOS), maxSize)
54
46
  }
55
47
 
56
- if (fontScale > 1) {
57
- fontSizeScaleOS = min(fontScale * fontSizeScaleOS, fontSizeScaleOS * scaleSizeMaxRate)
58
- }
59
-
60
- return max(
61
- fontSizeScaleDevice,
62
- fontSizeScaleOS
63
- )
48
+ return size
64
49
  }
65
50
 
66
51
  @Composable
@@ -9,6 +9,9 @@ import androidx.navigation.compose.NavHost
9
9
  import androidx.navigation.compose.composable
10
10
  import androidx.navigation.compose.rememberNavController
11
11
  import androidx.navigation.toRoute
12
+ import kotlinx.coroutines.flow.catch
13
+ import kotlinx.coroutines.flow.distinctUntilChanged
14
+ import kotlinx.coroutines.flow.map
12
15
  import vn.momo.kits.application.*
13
16
  import vn.momo.kits.const.*
14
17
  import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
@@ -54,6 +57,19 @@ fun NavigationContainer(
54
57
  DynamicScreenRegistry.bind(screenId, initialScreenName, initialScreen, options)
55
58
  val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
56
59
 
60
+ LaunchedEffect(maxApi) {
61
+ val api = maxApi ?: return@LaunchedEffect
62
+ runCatching {
63
+ api.observer("use_font_scale")
64
+ .map { parseUseFontScale(it) }
65
+ .distinctUntilChanged()
66
+ .catch { /* ignore observer errors, keep current value */ }
67
+ .collect { enabled ->
68
+ UseFontScaleSystem = enabled
69
+ }
70
+ }
71
+ }
72
+
57
73
  ProvideNavigationEventDispatcherOwner {
58
74
  CompositionLocalProvider(
59
75
  LocalNavigator provides navigator,
@@ -64,7 +80,6 @@ fun NavigationContainer(
64
80
  ApplicationContext provides mergedContext,
65
81
  AppConfig provides config,
66
82
  AppLanguage provides language,
67
- ScaleSizeMaxRate provides mergedContext?.scaleSizeMaxRate,
68
83
  ) {
69
84
  LaunchedEffect(Unit) {
70
85
  setNavigator?.invoke(navigator)
@@ -143,3 +158,15 @@ fun NavigationContainer(
143
158
  val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
144
159
  error("No MaxApi provided")
145
160
  }
161
+
162
+ private fun parseUseFontScale(raw: Any?): Boolean = when (raw) {
163
+ null -> true
164
+ is Boolean -> raw
165
+ is String -> raw.isBlank() || !raw.equals("false", ignoreCase = true)
166
+ is Number -> raw.toInt() != 0
167
+ is Map<*, *> -> {
168
+ val nested = raw["response"] ?: raw["value"] ?: raw["data"]
169
+ if (nested === raw) true else parseUseFontScale(nested)
170
+ }
171
+ else -> true
172
+ }
@@ -274,7 +274,7 @@ fun ScreenContent(content: @Composable () -> Unit) {
274
274
  Box(Modifier.fillMaxWidth().aspectRatio(animatedHeader.aspectRatio.value)) {
275
275
  animatedHeader.composable.invoke(scrollState.value)
276
276
  }
277
- Box(Modifier.offset(x = 0.dp, y = AppStatusBar.current + HEADER_HEIGHT.dp + animatedHeader.layoutOffSet)) {
277
+ Box(Modifier.padding(top = AppStatusBar.current + HEADER_HEIGHT.dp + animatedHeader.layoutOffSet)) {
278
278
  content()
279
279
  }
280
280
  }
@@ -4,7 +4,7 @@
4
4
  <dict>
5
5
  <key>SchemeUserState</key>
6
6
  <dict>
7
- <key>ios.xcscheme</key>
7
+ <key>Example.xcscheme_^#shared#^_</key>
8
8
  <dict>
9
9
  <key>orderHint</key>
10
10
  <integer>0</integer>
@@ -9,35 +9,35 @@
9
9
  <key>isShown</key>
10
10
  <false />
11
11
  <key>orderHint</key>
12
- <integer>1</integer>
12
+ <integer>0</integer>
13
13
  </dict>
14
14
  <key>Pods-Example.xcscheme</key>
15
15
  <dict>
16
16
  <key>isShown</key>
17
17
  <false />
18
18
  <key>orderHint</key>
19
- <integer>2</integer>
19
+ <integer>1</integer>
20
20
  </dict>
21
21
  <key>SDWebImage.xcscheme</key>
22
22
  <dict>
23
23
  <key>isShown</key>
24
24
  <false />
25
25
  <key>orderHint</key>
26
- <integer>3</integer>
26
+ <integer>2</integer>
27
27
  </dict>
28
28
  <key>SDWebImageSwiftUI.xcscheme</key>
29
29
  <dict>
30
30
  <key>isShown</key>
31
31
  <false />
32
32
  <key>orderHint</key>
33
- <integer>4</integer>
33
+ <integer>3</integer>
34
34
  </dict>
35
35
  <key>SkeletonUI.xcscheme</key>
36
36
  <dict>
37
37
  <key>isShown</key>
38
38
  <false />
39
39
  <key>orderHint</key>
40
- <integer>5</integer>
40
+ <integer>4</integer>
41
41
  </dict>
42
42
  </dict>
43
43
  <key>SuppressBuildableAutocreation</key>
@@ -19,7 +19,7 @@ androidx-appcompat = "1.7.0"
19
19
  material = "1.10.0"
20
20
  maxapi = "0.1.1"
21
21
  vanniktechMavenPublish = "0.34.0"
22
- kits = "0.159.1-beta.7"
22
+ kits = "0.160.1-beta.6"
23
23
  nativemaxapi = "0.0.6"
24
24
 
25
25
  [libraries]
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.161.2-search-header.1
21
+ version=0.161.3-beta.1
22
22
 
23
23
  repo=GitLab
24
24
  url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
@@ -17,7 +17,7 @@ public class MiniAppContext {
17
17
  public var toolkitConfig: [String: Any] = [:]
18
18
  public var providerId: String = "momo"
19
19
  public var permissions: [[String: Any]] = []
20
-
20
+
21
21
  public init(appId: String, appCode: String, appName: Any? = nil, appIcon: String, description: Any? = nil, support: [String: Any] = [:], toolkitConfig: [String: Any] = [:], providerId: String = "momo", permissions: [[String: Any]] = []) {
22
22
  self.appId = appId
23
23
  self.appCode = appCode
@@ -37,11 +37,15 @@ public class KitConfig {
37
37
  public var headerGradient: String? = nil
38
38
  }
39
39
 
40
+ public var IsShowBaseLineDebug = false
41
+
42
+ public var UseFontScaleSystem = true
43
+
40
44
  public class ApplicationEnvironment: ObservableObject {
41
45
  let applicationContext: MiniAppContext?
42
46
  let composeApi: KitComposeApi?
43
47
  let config: KitConfig?
44
-
48
+
45
49
  public init(applicationContext: MiniAppContext? = nil, composeApi: KitComposeApi? = nil, config: KitConfig? = nil) {
46
50
  self.applicationContext = applicationContext
47
51
  self.composeApi = composeApi
@@ -4,7 +4,7 @@ import Combine
4
4
 
5
5
  public struct Input: View {
6
6
  @Binding public var text: String
7
-
7
+
8
8
  public var placeholder: String
9
9
  public var floatingValue: String
10
10
  public var floatingIcon: String
@@ -30,10 +30,10 @@ public struct Input: View {
30
30
  public var onFocus: (() -> Void)?
31
31
  public var onBlur: (() -> Void)?
32
32
  public var onRightIconPressed: (() -> Void)?
33
-
33
+
34
34
  @State private var isFocused: Bool = false
35
35
  @State private var isPasswordHidden: Bool = true
36
-
36
+
37
37
  public init(
38
38
  text: Binding<String>,
39
39
  placeholder: String = "",
@@ -118,7 +118,7 @@ public struct Input: View {
118
118
  .offset(x: Spacing.S, y: -8)
119
119
  .zIndex(10)
120
120
  }
121
-
121
+
122
122
  // Input container
123
123
  HStack(alignment: .center, spacing: 0) {
124
124
  // Leading icon
@@ -126,7 +126,7 @@ public struct Input: View {
126
126
  Icon(source: leadingIcon, size: size == .small ? 24 : 32, color: leadingIconColor)
127
127
  .padding(.trailing, Spacing.M)
128
128
  }
129
-
129
+
130
130
  // Text input field
131
131
  ZStack(alignment: .leading) {
132
132
  if text.isEmpty {
@@ -136,7 +136,7 @@ public struct Input: View {
136
136
  color: getPlaceholderColor()
137
137
  )
138
138
  }
139
-
139
+
140
140
  if secureTextEntry && isPasswordHidden {
141
141
  SecureInputField(
142
142
  text: $text,
@@ -168,7 +168,7 @@ public struct Input: View {
168
168
  }
169
169
  }
170
170
  }
171
-
171
+
172
172
  // Clear button (only show when focused and has text)
173
173
  if isFocused && !text.isEmpty {
174
174
  SwiftUI.Button(action: {
@@ -179,14 +179,14 @@ public struct Input: View {
179
179
  .padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
180
180
  }
181
181
  }
182
-
182
+
183
183
  // Loading indicator
184
184
  if loading {
185
185
  ActivityIndicator(isAnimating: .constant(true), style: .medium)
186
186
  .frame(width: 16, height: 16)
187
187
  .padding(.leading, Spacing.S)
188
188
  }
189
-
189
+
190
190
  // Right icon (password toggle or custom icon)
191
191
  if secureTextEntry {
192
192
  if !text.isEmpty {
@@ -207,7 +207,7 @@ public struct Input: View {
207
207
  }
208
208
  }
209
209
  .padding(.horizontal, Spacing.M)
210
- .frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
210
+ .frame(height: scaleSize(size == .small ? 48 : 56))
211
211
  .background(
212
212
  RoundedRectangle(cornerRadius: Radius.S)
213
213
  .fill(Colors.black01)
@@ -217,7 +217,7 @@ public struct Input: View {
217
217
  .stroke(borderColor(), lineWidth: 1)
218
218
  )
219
219
  }
220
-
220
+
221
221
  // Error or hint
222
222
  ErrorView(
223
223
  errorMessage: error,
@@ -233,9 +233,9 @@ public struct Input: View {
233
233
  }
234
234
  }
235
235
  }
236
-
236
+
237
237
  // MARK: - Helpers
238
-
238
+
239
239
  private func handleFocusChange(_ focused: Bool) {
240
240
  isFocused = focused
241
241
  if focused {
@@ -244,7 +244,7 @@ public struct Input: View {
244
244
  onBlur?()
245
245
  }
246
246
  }
247
-
247
+
248
248
  private func togglePasswordVisibility() {
249
249
  isPasswordHidden.toggle()
250
250
  onRightIconPressed?()
@@ -256,7 +256,7 @@ public struct Input: View {
256
256
  }
257
257
  return String(value.prefix(maxLength))
258
258
  }
259
-
259
+
260
260
  private func borderColor() -> Color {
261
261
  if disabled {
262
262
  return Colors.black04 // border.disable
@@ -269,19 +269,19 @@ public struct Input: View {
269
269
  }
270
270
  return Colors.black04 // border.default
271
271
  }
272
-
272
+
273
273
  private func getTextColor() -> Color {
274
274
  return disabled ? Colors.black09 : Colors.black17
275
275
  }
276
-
276
+
277
277
  private func getPlaceholderColor() -> Color {
278
278
  return disabled ? Colors.black09 : Colors.black12
279
279
  }
280
-
280
+
281
281
  private func getFloatingColor() -> Color {
282
282
  return disabled ? Colors.black09 : Colors.black12
283
283
  }
284
-
284
+
285
285
  private func getFloatingIconColor() -> Color {
286
286
  return disabled ? Colors.black09 : floatingIconColor
287
287
  }
@@ -8,7 +8,7 @@
8
8
  import SwiftUI
9
9
  public struct InputPhoneNumber: View {
10
10
  @Binding public var text: String
11
-
11
+
12
12
  public var placeholder: String
13
13
  public var size: InputSize
14
14
  public var hintText: String
@@ -22,9 +22,9 @@ public struct InputPhoneNumber: View {
22
22
  public var onBlur: (() -> Void)?
23
23
  public var onRightIconPressed: (() -> Void)?
24
24
  public var accessibilityLabel: String?
25
-
25
+
26
26
  @State private var isFocused: Bool = false
27
-
27
+
28
28
  public init(
29
29
  text: Binding<String>,
30
30
  placeholder: String = "0123456789",
@@ -57,7 +57,7 @@ public struct InputPhoneNumber: View {
57
57
  self.onRightIconPressed = onRightIconPressed
58
58
  self.accessibilityLabel = accessibilityLabel
59
59
  }
60
-
60
+
61
61
  // MARK: - Body
62
62
  public var body: some View {
63
63
  let textBinding = Binding<String>(
@@ -67,28 +67,28 @@ public struct InputPhoneNumber: View {
67
67
  self.onChangeText?(newValue)
68
68
  }
69
69
  )
70
-
70
+
71
71
  VStack(alignment: .leading, spacing: 4) {
72
72
  HStack(spacing: 0) {
73
73
  // 🇻🇳 Flag
74
74
  ImageView("https://static.momocdn.net/app/img/icon/ic-qrcode-package/ic_vn_flag.png")
75
75
  .frame(width: 24, height: 24)
76
76
  .padding(.trailing, Spacing.XS)
77
-
77
+
78
78
  MomoText("+84", typography: size == .small ? .headerSSemibold : .headerMBold)
79
79
  .foregroundColor(Colors.black17)
80
-
80
+
81
81
  Rectangle()
82
82
  .fill(Colors.black04)
83
83
  .frame(width: 1, height: size == .small ? 24 : 32)
84
84
  .padding(.horizontal, Spacing.M)
85
-
85
+
86
86
  // Text input
87
87
  ZStack(alignment: .leading) {
88
88
  if text.isEmpty {
89
89
  MomoText(placeholder, typography: size == .small ? .headerSSemibold : .headerMBold, color: Colors.black12)
90
90
  }
91
-
91
+
92
92
  TextField("", text: textBinding, onEditingChanged: { focused in
93
93
  handleFocusChange(focused)
94
94
  })
@@ -100,7 +100,7 @@ public struct InputPhoneNumber: View {
100
100
  .accessibility(identifier: accessibilityLabel ?? "")
101
101
  .accessibilityValue(textBinding.wrappedValue.isEmpty ? placeholder : textBinding.wrappedValue)
102
102
  }
103
-
103
+
104
104
  // Clear button
105
105
  if isFocused && !text.isEmpty {
106
106
  SwiftUI.Button(action: {
@@ -111,13 +111,13 @@ public struct InputPhoneNumber: View {
111
111
  .padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
112
112
  }
113
113
  }
114
-
114
+
115
115
  // Loading indicator
116
116
  if loading {
117
117
  ActivityIndicator(isAnimating: .constant(true), style: .medium)
118
118
  .frame(width: 16, height: 16)
119
119
  }
120
-
120
+
121
121
  // ✅ Right icon
122
122
  if !rightIcon.isEmpty {
123
123
  SwiftUI.Button(action: { onRightIconPressed?() }) {
@@ -127,7 +127,7 @@ public struct InputPhoneNumber: View {
127
127
  }
128
128
  }
129
129
  .padding(.horizontal, Spacing.M)
130
- .frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
130
+ .frame(height: scaleSize(size == .small ? 48 : 56))
131
131
  .background(
132
132
  RoundedRectangle(cornerRadius: Radius.S)
133
133
  .fill(Colors.black01)
@@ -136,7 +136,7 @@ public struct InputPhoneNumber: View {
136
136
  RoundedRectangle(cornerRadius: Radius.S)
137
137
  .stroke(borderColor(), lineWidth: isFocused ? 1.5 : 1)
138
138
  )
139
-
139
+
140
140
  // Error or hint
141
141
  ErrorView(
142
142
  errorMessage: error,
@@ -145,9 +145,9 @@ public struct InputPhoneNumber: View {
145
145
  )
146
146
  }
147
147
  }
148
-
148
+
149
149
  // MARK: - Helpers
150
-
150
+
151
151
  private func handleFocusChange(_ focused: Bool) {
152
152
  isFocused = focused
153
153
  if focused {
@@ -156,7 +156,7 @@ public struct InputPhoneNumber: View {
156
156
  onBlur?()
157
157
  }
158
158
  }
159
-
159
+
160
160
  private func borderColor() -> Color {
161
161
  if !error.isEmpty { return Colors.red03 }
162
162
  if isFocused { return Colors.primary }
@@ -1,30 +1,25 @@
1
1
  import SwiftUI
2
2
 
3
- public func scaleSize(_ size: CGFloat, _ scaleRate: CGFloat? = nil) -> CGFloat {
4
- let defaultScreenSize: CGFloat = 375
5
- let maxFontScale: CGFloat = scaleRate ?? 1.5
6
- let maxDeviceScale: CGFloat = 5
3
+ private let DEFAULT_SCREEN_SIZE: CGFloat = 375
4
+ private let MAX_FONT_SCALE: CGFloat = 1.2
7
5
 
8
- let deviceWidth = UIScreen.main.bounds.width
9
- let deviceScale = deviceWidth / defaultScreenSize
6
+ public func scaleSize(_ size: CGFloat) -> CGFloat {
7
+ if UseFontScaleSystem {
8
+ let deviceWidth = UIScreen.main.bounds.width
9
+ let deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
10
10
 
11
- let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
12
- let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
13
- let fontScale = scaledFont.pointSize / defaultFont.pointSize
11
+ let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
12
+ let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
13
+ let fontScale = scaledFont.pointSize / defaultFont.pointSize
14
14
 
15
- var fontSizeDeviceScale = size
16
- var fontSizeOSScale = size
15
+ let maxSize = size * MAX_FONT_SCALE
16
+ let fontSizeScaleDevice = deviceScale > 1 ? deviceScale * size : size
17
+ let fontSizeScaleOS = fontScale > 1 ? fontScale * size : size
17
18
 
18
-
19
- if deviceScale > 1 {
20
- fontSizeDeviceScale = min(fontSizeDeviceScale * deviceScale, fontSizeDeviceScale + maxDeviceScale)
21
- }
22
-
23
- if fontScale > 1 {
24
- fontSizeOSScale = min(fontSizeOSScale * fontScale, fontSizeOSScale * maxFontScale)
19
+ return min(max(fontSizeScaleDevice, fontSizeScaleOS), maxSize)
25
20
  }
26
21
 
27
- return max(fontSizeDeviceScale, fontSizeOSScale)
22
+ return size
28
23
  }
29
24
 
30
25
  public enum TypographyStyle {
@@ -2,28 +2,7 @@ import SwiftUI
2
2
 
3
3
  public extension Font {
4
4
  static func appFont(size: CGFloat) -> Font {
5
- let defaultScreenSize: CGFloat = 375
6
- let maxFontScale: CGFloat = 1.5
7
- let maxDeviceScale: CGFloat = 5
8
-
9
- let deviceWidth = UIScreen.main.bounds.width
10
- let deviceScale = deviceWidth / defaultScreenSize
11
-
12
- let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
13
- let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
14
- let fontScale = scaledFont.pointSize / defaultFont.pointSize
15
-
16
- var fontSize = size
17
-
18
- if deviceScale > 1 {
19
- fontSize = min(fontSize * deviceScale, fontSize + maxDeviceScale)
20
- }
21
-
22
- if fontScale > 1 {
23
- fontSize = min(fontSize * fontScale, fontSize * maxFontScale)
24
- }
25
-
26
- return Font.system(size: fontSize)
5
+ return Font.system(size: scaleSize(size))
27
6
  }
28
7
 
29
8
  // New supported typography styles
package/local.properties CHANGED
@@ -4,5 +4,5 @@
4
4
  # Location of the SDK. This is only used by Gradle.
5
5
  # For customization when using a Version Control System, please read the
6
6
  # header note.
7
- #Fri Mar 07 10:22:24 ICT 2025
8
- sdk.dir=/Users/vunh/Library/Android/sdk
7
+ #Wed Aug 21 14:20:12 ICT 2024
8
+ sdk.dir=/Users/huynhdung/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.161.2-search-header.1-debug",
3
+ "version": "0.161.3-beta.1-debug",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},
@@ -1,17 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.runtime.Composable
4
- import androidx.compose.runtime.CompositionLocalProvider
5
- import vn.momo.kits.application.ScaleSizeMaxRate
6
-
7
- @Composable
8
- fun ScaleSizeScope(
9
- scaleSizeMaxRate: Float? = null,
10
- content: @Composable () -> Unit
11
- ) {
12
- CompositionLocalProvider(
13
- ScaleSizeMaxRate provides scaleSizeMaxRate,
14
- ) {
15
- content()
16
- }
17
- }
@@ -1,36 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Scheme
3
- version = "1.3">
4
- <BuildAction>
5
- <BuildActionEntries>
6
- <BuildActionEntry
7
- buildForRunning = "YES">
8
- <BuildableReference
9
- BuildableIdentifier = "primary"
10
- BlueprintIdentifier = "A6A920D22B2ADD1E00C1A11F"
11
- BuildableName = "Example"
12
- BlueprintName = "Example"
13
- ReferencedContainer = "container:Example.xcodeproj">
14
- </BuildableReference>
15
- </BuildActionEntry>
16
- </BuildActionEntries>
17
- </BuildAction>
18
- <LaunchAction
19
- useCustomWorkingDirectory = "NO"
20
- buildConfiguration = "Debug"
21
- allowLocationSimulation = "YES">
22
- <BuildableProductRunnable>
23
- <BuildableReference
24
- BuildableIdentifier = "primary"
25
- BlueprintIdentifier = "A6A920D22B2ADD1E00C1A11F"
26
- BuildableName = "Example"
27
- BlueprintName = "Example"
28
- ReferencedContainer = "container:Example.xcodeproj">
29
- </BuildableReference>
30
- </BuildableProductRunnable>
31
- <LocationScenarioReference
32
- identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
33
- referenceType = "1">
34
- </LocationScenarioReference>
35
- </LaunchAction>
36
- </Scheme>