@momo-kits/native-kits 0.167.1-duo.16-debug → 0.167.1-duo.17

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 (152) hide show
  1. package/ios/native-kits.podspec +1 -1
  2. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  3. package/package.json +1 -1
  4. package/.claude/settings.local.json +0 -185
  5. package/build.gradle.kts +0 -11
  6. package/compose/build.gradle.kts +0 -204
  7. package/compose/build.gradle.kts.backup +0 -204
  8. package/compose/compose.podspec +0 -47
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
  10. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  11. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
  12. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
  13. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -153
  14. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +0 -6
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -916
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -81
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -115
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -478
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -265
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -235
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -265
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -361
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -108
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -308
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -330
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -207
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -92
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -560
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -501
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -236
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -180
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -16
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -297
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -260
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -338
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -137
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -205
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -708
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -218
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -231
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +0 -98
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +0 -312
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -408
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -103
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -106
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -366
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -37
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -185
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -133
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -74
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +0 -13
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  134. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
  135. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  136. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
  137. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -40
  138. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
  139. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
  140. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
  141. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
  142. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -217
  143. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +0 -94
  144. package/gradle/libs.versions.toml +0 -69
  145. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  146. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  147. package/gradle.properties +0 -26
  148. package/gradlew +0 -252
  149. package/gradlew.bat +0 -94
  150. package/ios-demo/README.md +0 -120
  151. package/local.properties +0 -8
  152. package/settings.gradle.kts +0 -64
@@ -1,916 +0,0 @@
1
- package vn.momo.kits.application
2
-
3
- import androidx.annotation.FloatRange
4
- import androidx.compose.foundation.ScrollState
5
- import androidx.compose.foundation.background
6
- import androidx.compose.foundation.border
7
- import androidx.compose.foundation.gestures.detectTapGestures
8
- import androidx.compose.foundation.interaction.FocusInteraction
9
- import androidx.compose.foundation.interaction.MutableInteractionSource
10
- import androidx.compose.foundation.layout.Arrangement
11
- import androidx.compose.foundation.layout.Box
12
- import androidx.compose.foundation.layout.Row
13
- import androidx.compose.foundation.layout.fillMaxSize
14
- import androidx.compose.foundation.layout.padding
15
- import androidx.compose.foundation.layout.size
16
- import androidx.compose.foundation.rememberScrollState
17
- import androidx.compose.foundation.shape.CircleShape
18
- import androidx.compose.foundation.text.BasicTextField
19
- import androidx.compose.foundation.text.KeyboardActions
20
- import androidx.compose.foundation.text.KeyboardOptions
21
- import androidx.compose.foundation.verticalScroll
22
- import androidx.compose.runtime.Composable
23
- import androidx.compose.runtime.LaunchedEffect
24
- import androidx.compose.runtime.MutableState
25
- import androidx.compose.runtime.Stable
26
- import androidx.compose.runtime.State
27
- import androidx.compose.runtime.derivedStateOf
28
- import androidx.compose.runtime.getValue
29
- import androidx.compose.runtime.mutableStateOf
30
- import androidx.compose.runtime.produceState
31
- import androidx.compose.runtime.remember
32
- import androidx.compose.runtime.rememberUpdatedState
33
- import androidx.compose.runtime.snapshotFlow
34
- import androidx.compose.runtime.staticCompositionLocalOf
35
- import androidx.compose.ui.Alignment
36
- import androidx.compose.ui.Modifier
37
- import androidx.compose.ui.composed
38
- import androidx.compose.ui.draw.clip
39
- import androidx.compose.ui.draw.drawBehind
40
- import androidx.compose.ui.draw.drawWithContent
41
- import androidx.compose.ui.geometry.Offset
42
- import androidx.compose.ui.geometry.Rect
43
- import androidx.compose.ui.graphics.Brush
44
- import androidx.compose.ui.graphics.Color
45
- import androidx.compose.ui.graphics.SolidColor
46
- import androidx.compose.ui.graphics.graphicsLayer
47
- import androidx.compose.ui.input.pointer.pointerInput
48
- import androidx.compose.ui.layout.Layout
49
- import androidx.compose.ui.layout.Measurable
50
- import androidx.compose.ui.layout.MeasurePolicy
51
- import androidx.compose.ui.layout.MeasureResult
52
- import androidx.compose.ui.layout.MeasureScope
53
- import androidx.compose.ui.layout.Placeable
54
- import androidx.compose.ui.layout.layoutId
55
- import androidx.compose.ui.platform.LocalDensity
56
- import androidx.compose.ui.platform.LocalFocusManager
57
- import androidx.compose.ui.platform.LocalSoftwareKeyboardController
58
- import androidx.compose.ui.text.TextStyle
59
- import androidx.compose.ui.text.style.TextOverflow
60
- import androidx.compose.ui.unit.Constraints
61
- import androidx.compose.ui.unit.Dp
62
- import androidx.compose.ui.unit.IntOffset
63
- import androidx.compose.ui.unit.LayoutDirection
64
- import androidx.compose.ui.unit.dp
65
- import androidx.compose.ui.unit.lerp
66
- import androidx.compose.ui.unit.sp
67
- import kotlinx.coroutines.flow.collectLatest
68
- import kotlinx.coroutines.flow.mapNotNull
69
- import vn.momo.kits.components.Icon
70
- import vn.momo.kits.components.Text
71
- import vn.momo.kits.const.AppTheme
72
- import vn.momo.kits.const.Colors
73
- import vn.momo.kits.const.Spacing
74
- import vn.momo.kits.const.Typography
75
- import vn.momo.kits.const.getFontFamily
76
- import vn.momo.kits.layout.DuoMetrics
77
- import vn.momo.kits.layout.ScreenLayout
78
- import vn.momo.kits.layout.SideBarEdge
79
- import vn.momo.kits.layout.getScreenLayout
80
- import vn.momo.kits.utils.horizontalSafeAreaPadding
81
- import vn.momo.kits.modifier.kitsAutomationId
82
- import vn.momo.kits.modifier.noFeedbackClickable
83
- import vn.momo.kits.modifier.setAutomationId
84
- import vn.momo.kits.navigation.component.HEADER_FONT_FAMILY
85
- import vn.momo.kits.navigation.component.HEADER_HEIGHT
86
- import vn.momo.kits.navigation.component.SideBarButton
87
- import vn.momo.kits.utils.getAppStatusBarHeight
88
- import kotlin.math.max
89
- import kotlin.math.roundToInt
90
- import vn.momo.kits.navigation.component.getHeaderColor as getNavigationHeaderColor
91
-
92
-
93
- data class AnimationOption(
94
- val targetBounds: Rect,
95
- val progress: State<Float>,
96
- @param:FloatRange(from = 0.0, to = 1.0)
97
- val opacityLimitFraction: Float = 0f,
98
- ) {
99
- val opacityCap: Float
100
- get() = 1f - opacityLimitFraction
101
-
102
- val animateOpacity: Float
103
- get() {
104
- if (progress.value < opacityLimitFraction) return 0f
105
- return androidx.compose.ui.util.lerp(
106
- 0f,
107
- 1f,
108
- (progress.value - opacityLimitFraction) / (opacityCap),
109
- )
110
- }
111
- }
112
-
113
- val LocalAnimationOption = staticCompositionLocalOf<AnimationOption?> { null }
114
-
115
- @Composable
116
- fun LiteScreen(
117
- scrollable: Boolean = true,
118
- scrollState: ScrollState? = null,
119
- headerType: HeaderType = HeaderType.DEFAULT,
120
- verticalArrangement: Arrangement.Vertical = Arrangement.Top,
121
- horizontalAlignment: Alignment.Horizontal = Alignment.Start,
122
- backgroundColor: Color = AppTheme.current.colors.background.default,
123
- /* Begin of header props */
124
- title: String? = null,
125
- inputSearchProps: LiteInputSearchProps? = null,
126
- goBack: (() -> Unit)? = null,
127
- headerRight: @Composable (() -> Unit)? = null,
128
- useAnimationSearch: Boolean = true,
129
- titlePosition: TitlePosition = TitlePosition.LEFT,
130
- headerRightData: HeaderRightData? = null,
131
- headerTintColor: Color? = null,
132
- headerBackgroundColor: Color? = null,
133
- headerSpaceBetween: Dp? = null,
134
- /* End of header props */
135
-
136
- screenContent: @Composable () -> Unit,
137
- ) {
138
- val content by rememberUpdatedState(screenContent)
139
-
140
- val finalScrollState = scrollState ?: rememberScrollState()
141
-
142
- val contentModifier = remember(
143
- key1 = scrollable,
144
- key2 = finalScrollState,
145
- ) {
146
- var res: Modifier = Modifier
147
- .background(color = backgroundColor)
148
- if (scrollable) {
149
- res = res.verticalScroll(finalScrollState)
150
- }
151
- res
152
- }
153
-
154
- LiteScreenLayout(
155
- scrollState = finalScrollState,
156
- modifier = Modifier
157
- .fillMaxSize()
158
- .hideKeyboardOnTap(),
159
- contentModifier = contentModifier,
160
- verticalArrangement = verticalArrangement,
161
- horizontalAlignment = horizontalAlignment,
162
- title = title,
163
- headerRight = headerRight,
164
- headerType = headerType,
165
- onGoBack = goBack,
166
- inputSearchProps = inputSearchProps,
167
- titlePosition = titlePosition,
168
- useAnimationSearch = useAnimationSearch,
169
- headerRightData = headerRightData,
170
- tintColor = headerTintColor,
171
- headerBackgroundColor = headerBackgroundColor,
172
- headerSpaceBetween = headerSpaceBetween,
173
- ) {
174
- content()
175
- }
176
- }
177
-
178
- private object HeaderId {
179
- private const val PACKAGE_NAME = "vn.momo.compose.kits"
180
- const val CONTENT_ID = "${PACKAGE_NAME}.content"
181
- const val BACKGROUND_ID = "${PACKAGE_NAME}.background"
182
- const val BACK_ID = "${PACKAGE_NAME}.back"
183
- const val HEADER_RIGHT_ID = "${PACKAGE_NAME}.headerRight"
184
- const val INPUT_SEARCH_ID = "${PACKAGE_NAME}.inputSearch"
185
- const val TITLE_ID = "${PACKAGE_NAME}.title"
186
-
187
- val EXTENDED_HEADER_HEIGHT = 154.dp
188
- }
189
-
190
- @Composable
191
- private fun LiteScreenLayout(
192
- scrollState: ScrollState?,
193
- modifier: Modifier = Modifier,
194
- contentModifier: Modifier = Modifier,
195
- verticalArrangement: Arrangement.Vertical = Arrangement.Top,
196
- horizontalAlignment: Alignment.Horizontal = Alignment.Start,
197
- title: String? = null,
198
- tintColor: Color? = null,
199
- headerRightData: HeaderRightData? = null,
200
- headerType: HeaderType = HeaderType.DEFAULT,
201
- titlePosition: TitlePosition = TitlePosition.LEFT,
202
- useAnimationSearch: Boolean = true,
203
- onGoBack: (() -> Unit)? = null,
204
- headerBackgroundColor: Color? = null,
205
- headerSpaceBetween: Dp? = null,
206
- inputSearchProps: LiteInputSearchProps? = null,
207
- headerRight: @Composable (() -> Unit)? = null,
208
- content: @Composable () -> Unit,
209
- ) {
210
- val statusBarHeight = getAppStatusBarHeight()
211
- val screenLayout = getScreenLayout()
212
- val applySafeAreaPadding = screenLayout.sideBar != null
213
- val isHeaderNone = remember(headerType) {
214
- headerType == HeaderType.NONE
215
- }
216
- val theme = AppTheme.current
217
- val density = LocalDensity.current
218
-
219
- val isHeaderExtend = remember(headerType) {
220
- headerType == HeaderType.EXTENDED
221
- }
222
- val backgroundHeight = remember(isHeaderNone, isHeaderExtend, statusBarHeight) {
223
- when {
224
- isHeaderNone -> statusBarHeight
225
- !isHeaderExtend -> statusBarHeight + HEADER_HEIGHT.dp
226
- else -> HeaderId.EXTENDED_HEADER_HEIGHT
227
- }
228
- }
229
- val listGradientColors = remember {
230
- listOf(
231
- Color(0xFFFDCADE),
232
- Color(0x00FDCADE),
233
- )
234
- }
235
-
236
- val headerColor = remember(tintColor, theme) {
237
- if (tintColor == Colors.black_01) HeaderColor(
238
- tintIconColor = tintColor,
239
- backgroundButton = Colors.black_20.copy(alpha = 0.6f),
240
- borderColor = Colors.black_01.copy(alpha = 0.2f)
241
- )
242
- else HeaderColor(
243
- tintIconColor = tintColor ?: theme.colors.text.default,
244
- backgroundButton = Colors.black_01.copy(alpha = 0.6f),
245
- borderColor = Colors.black_20.copy(alpha = 0.2f)
246
- )
247
- }
248
-
249
- val scrollPercentage = produceState(
250
- initialValue = 0f,
251
- key1 = useAnimationSearch,
252
- key2 = scrollState,
253
- key3 = backgroundHeight,
254
- ) {
255
- if (!useAnimationSearch) return@produceState
256
- scrollState ?: return@produceState
257
- val rangePx = with(density) { backgroundHeight.toPx() }
258
- snapshotFlow { scrollState.value }.collectLatest {
259
- value = (it / rangePx).coerceIn(0f, 1f)
260
- }
261
- }
262
-
263
- val titleStyle = remember {
264
- Typography.actionSBold.copy(
265
- fontSize = 15.sp,
266
- lineHeight = 22.sp,
267
- )
268
- }
269
-
270
- val animationOption = LocalAnimationOption.current
271
- val animationOpacityModifier = Modifier.graphicsLayer {
272
- alpha = animationOption?.animateOpacity ?: 1f
273
- }
274
- val sideBarColor = getNavigationHeaderColor(
275
- vn.momo.kits.navigation.component.HeaderType.Default(),
276
- 1f,
277
- null,
278
- Colors.black_17,
279
- )
280
- val titleModifier = Modifier
281
- .kitsAutomationId("title_navigation_header")
282
- .layoutId(HeaderId.TITLE_ID)
283
- .graphicsLayer {
284
- val titleAlpha = if (isHeaderExtend && inputSearchProps != null && useAnimationSearch)
285
- (1 - scrollPercentage.value * 2).coerceIn(0f, 1f)
286
- else 1f
287
- alpha = titleAlpha * (animationOption?.progress?.value ?: 1f)
288
- }
289
-
290
- val policy = remember(
291
- screenLayout,
292
- applySafeAreaPadding,
293
- useAnimationSearch,
294
- isHeaderNone,
295
- isHeaderExtend,
296
- statusBarHeight,
297
- titlePosition,
298
- scrollPercentage,
299
- headerSpaceBetween,
300
- animationOption,
301
- verticalArrangement,
302
- horizontalAlignment,
303
- ) {
304
- LiteScreenLayoutPolicy(
305
- screenLayout = screenLayout,
306
- applySafeAreaPadding = applySafeAreaPadding,
307
- useAnimationSearch = useAnimationSearch,
308
- isHeaderNone = isHeaderNone,
309
- isHeaderExtend = isHeaderExtend,
310
- statusBarHeight = statusBarHeight,
311
- titlePosition = titlePosition,
312
- scrollPercentage = scrollPercentage,
313
- headerSpaceBetween = headerSpaceBetween,
314
- animationOption = animationOption,
315
- verticalArrangement = verticalArrangement,
316
- horizontalAlignment = horizontalAlignment,
317
- )
318
- }
319
-
320
- Layout(
321
- modifier = modifier,
322
- content = {
323
- Box(
324
- modifier = animationOpacityModifier
325
- .layoutId(HeaderId.CONTENT_ID)
326
- .then(contentModifier)
327
- .then(if (applySafeAreaPadding) Modifier.horizontalSafeAreaPadding() else Modifier),
328
- contentAlignment = Alignment.TopCenter,
329
- ) {
330
- content()
331
- }
332
-
333
- if (!isHeaderNone) {
334
- Box(
335
- modifier = Modifier
336
- .layoutId(HeaderId.BACKGROUND_ID)
337
- .then(animationOpacityModifier)
338
- .drawBehind {
339
- val headerHeight = max(
340
- HeaderId.EXTENDED_HEADER_HEIGHT.toPx(),
341
- size.height,
342
- )
343
- headerBackgroundColor?.let {
344
- drawRect(color = it)
345
- } ?: run {
346
- drawRect(color = Colors.black_01)
347
- drawRect(
348
- brush = Brush.linearGradient(
349
- colors = listGradientColors,
350
- start = Offset.Zero,
351
- end = Offset(
352
- x = 0f,
353
- y = headerHeight * (1 - scrollPercentage.value),
354
- ),
355
- )
356
- )
357
- }
358
- },
359
- )
360
- }
361
-
362
- if (!isHeaderNone && onGoBack != null) {
363
- when {
364
- screenLayout.sideBar != null -> {
365
- Box(
366
- modifier = Modifier.layoutId(HeaderId.BACK_ID),
367
- ) {
368
- SideBarButton(
369
- icon = "arrow-back",
370
- headerColor = sideBarColor,
371
- onClick = onGoBack,
372
- automationId = "btn_navigation_back",
373
- )
374
- }
375
- }
376
- else -> {
377
- val coreModifier = Modifier
378
- .layoutId(HeaderId.BACK_ID)
379
- .then(animationOpacityModifier)
380
- .clip(CircleShape)
381
- .noFeedbackClickable(onClick = onGoBack)
382
- .setAutomationId("btn_navigation_back")
383
- inputSearchProps?.customBackIcon?.invoke(coreModifier) ?: Box(
384
- modifier = coreModifier
385
- .size(28.dp)
386
- .border(
387
- width = 0.2.dp,
388
- color = headerColor.borderColor,
389
- shape = CircleShape,
390
- )
391
- .background(color = headerColor.backgroundButton)
392
- .padding(Spacing.XS),
393
- ) {
394
- Icon(
395
- source = "arrow-back",
396
- color = headerColor.tintIconColor,
397
- size = 20.dp,
398
- )
399
- }
400
- }
401
- }
402
- }
403
-
404
- if (!isHeaderNone) {
405
- Box(
406
- modifier = Modifier
407
- .layoutId(HeaderId.HEADER_RIGHT_ID)
408
- .then(animationOpacityModifier)
409
- ) {
410
- if (headerRight != null) {
411
- headerRight()
412
- } else {
413
- HeaderRight(
414
- headerRight = headerRightData,
415
- tintColor = tintColor,
416
- )
417
- }
418
- }
419
- }
420
-
421
- if (!isHeaderNone && inputSearchProps != null) {
422
- LiteInputSearch(
423
- modifier = Modifier.layoutId(HeaderId.INPUT_SEARCH_ID),
424
- inputSearchProps = inputSearchProps,
425
- )
426
- }
427
- if (!isHeaderNone && title != null && (inputSearchProps == null || isHeaderExtend)) {
428
- Text(
429
- text = title,
430
- color = headerColor.tintIconColor,
431
- style = titleStyle,
432
- fontFamily = HEADER_FONT_FAMILY,
433
- modifier = titleModifier,
434
- maxLines = 1,
435
- overflow = TextOverflow.Ellipsis
436
- )
437
- }
438
- },
439
- measurePolicy = policy,
440
- )
441
- }
442
-
443
- private class LiteScreenLayoutPolicy(
444
- private val screenLayout: ScreenLayout,
445
- private val applySafeAreaPadding: Boolean,
446
- private val useAnimationSearch: Boolean,
447
- private val isHeaderNone: Boolean,
448
- private val isHeaderExtend: Boolean,
449
- private val statusBarHeight: Dp,
450
- private val scrollPercentage: State<Float>,
451
- private val titlePosition: TitlePosition,
452
- private val headerSpaceBetween: Dp? = null,
453
- private val animationOption: AnimationOption?,
454
- private val verticalArrangement: Arrangement.Vertical,
455
- private val horizontalAlignment: Alignment.Horizontal,
456
- ) : MeasurePolicy {
457
-
458
- val searchStartPosition: IntOffset by lazy {
459
- if (animationOption == null) return@lazy IntOffset.Zero
460
- val offset = animationOption.targetBounds.topLeft
461
- IntOffset(
462
- x = offset.x.roundToInt(),
463
- y = offset.y.roundToInt(),
464
- )
465
- }
466
-
467
- override fun MeasureScope.measure(
468
- measurables: List<Measurable>,
469
- constraints: Constraints
470
- ): MeasureResult {
471
- val spacing12 = Spacing.M.roundToPx()
472
- val spaceBetween = headerSpaceBetween?.roundToPx() ?: spacing12
473
- val statusBarPx = statusBarHeight.roundToPx()
474
- val headerRowDefault = HEADER_HEIGHT.dp.roundToPx()
475
- val scrollPercent = scrollPercentage.value
476
-
477
- val contentMeasurable = measurables.find { it.layoutId == HeaderId.CONTENT_ID }
478
-
479
- val insetLeft = if (applySafeAreaPadding) screenLayout.insetLeft.roundToPx() else 0
480
- val insetRight = if (applySafeAreaPadding) screenLayout.insetRight.roundToPx() else 0
481
- val safeWidth = (constraints.maxWidth - insetLeft - insetRight).coerceAtLeast(0)
482
- val realConstraints = constraints.copy(
483
- minWidth = 0,
484
- minHeight = 0,
485
- maxWidth = (safeWidth - spacing12 * 2)
486
- .coerceAtLeast(0),
487
- )
488
- val backIconPlaceable =
489
- measurables.find { it.layoutId == HeaderId.BACK_ID }?.measure(realConstraints)
490
- val headerRightPlaceable =
491
- measurables.find { it.layoutId == HeaderId.HEADER_RIGHT_ID }?.measure(
492
- realConstraints.copy(
493
- maxWidth = realConstraints.maxWidth / 2,
494
- )
495
- )
496
- val headerBackWidth = if (screenLayout.sideBar == null) backIconPlaceable.safeWidth else 0
497
- val baseInputSearchConstraints = if (isHeaderExtend) {
498
- val minWidth =
499
- if (useAnimationSearch) realConstraints.maxWidth - headerBackWidth - headerRightPlaceable.safeWidth - spaceBetween * 2
500
- else realConstraints.maxWidth
501
- realConstraints.copy(
502
- maxWidth = (realConstraints.maxWidth * (1 - scrollPercent)).toInt()
503
- .coerceAtLeast(minWidth)
504
- )
505
- } else {
506
- var spaceConsumed = 0
507
- if (headerBackWidth != 0) spaceConsumed += headerBackWidth + spaceBetween
508
- if (headerRightPlaceable.safeWidth != 0) spaceConsumed += headerRightPlaceable.safeWidth + spaceBetween
509
- realConstraints.copy(
510
- maxWidth = realConstraints.maxWidth - spaceConsumed
511
- )
512
- }
513
- val inputSearchConstraints = baseInputSearchConstraints.withAnimationTargetBounds()
514
- val inputSearchPlaceable = measurables.find { it.layoutId == HeaderId.INPUT_SEARCH_ID }
515
- ?.measure(inputSearchConstraints)
516
- val titlePlaceable = measurables.find { it.layoutId == HeaderId.TITLE_ID }?.measure(
517
- constraints = realConstraints.copy(
518
- maxWidth = realConstraints.maxWidth - headerBackWidth - headerRightPlaceable.safeWidth - spaceBetween * 2
519
- )
520
- )
521
-
522
- /**
523
- * replicate logic from [vn.momo.kits.navigation.component.HeaderBackground]
524
- * */
525
- var defaultHeight = statusBarPx + headerRowDefault
526
- if (isHeaderExtend) {
527
- defaultHeight = 154.dp.roundToPx()
528
- }
529
- val headerHeight = when {
530
- isHeaderNone -> statusBarPx
531
- !useAnimationSearch && !isHeaderExtend -> defaultHeight
532
- else -> {
533
- val collapsableSpace = defaultHeight - statusBarPx - headerRowDefault
534
- (defaultHeight - scrollPercent * collapsableSpace).toInt()
535
- }
536
- }
537
-
538
- val layoutWidth = constraints.maxWidth
539
- val layoutHeight = constraints.maxHeight
540
- val backgroundInsetLeft = if (!applySafeAreaPadding && screenLayout.sideBar != null) screenLayout.insetLeft.roundToPx() else 0
541
- val contentHeight = (layoutHeight - headerHeight).coerceAtLeast(0)
542
- val contentPlaceable = contentMeasurable?.measure(
543
- constraints.copy(
544
- minWidth = 0,
545
- minHeight = contentHeight,
546
- maxHeight = contentHeight,
547
- )
548
- )
549
- val backgroundPlaceable = measurables.find { it.layoutId == HeaderId.BACKGROUND_ID }
550
- ?.measure(
551
- Constraints.fixed(
552
- width = layoutWidth,
553
- height = headerHeight,
554
- )
555
- )
556
- val childrenHeights = intArrayOf(
557
- headerHeight,
558
- contentPlaceable.safeHeight,
559
- )
560
- val childrenY = IntArray(childrenHeights.size)
561
- with(verticalArrangement) {
562
- arrange(
563
- totalSize = layoutHeight,
564
- sizes = childrenHeights,
565
- outPositions = childrenY,
566
- )
567
- }
568
- val headerY = childrenY[0]
569
- val contentY = childrenY[1]
570
-
571
- return layout(
572
- width = layoutWidth,
573
- height = layoutHeight,
574
- ) {
575
- val progress = animationOption?.progress?.value ?: 1f
576
-
577
- val startX = insetLeft + spacing12
578
- val startY = headerY + statusBarPx
579
- var curX = startX
580
- var curY = startY
581
-
582
- contentPlaceable?.place(
583
- x = horizontalAlignment.align(
584
- size = contentPlaceable.width,
585
- space = layoutWidth,
586
- layoutDirection = layoutDirection,
587
- ),
588
- y = contentY,
589
- )
590
-
591
- backgroundPlaceable?.place(
592
- x = -backgroundInsetLeft,
593
- y = headerY,
594
- )
595
-
596
- if (backIconPlaceable != null) {
597
- val sideBar = screenLayout.sideBar
598
- if (sideBar == null) {
599
- backIconPlaceable.place(
600
- x = startX,
601
- y = startY + backIconPlaceable.verticalCenterOffset(headerRowDefault),
602
- )
603
- curX += backIconPlaceable.safeWidth + spaceBetween
604
- } else {
605
- val x = when (sideBar.edge) {
606
- SideBarEdge.LEFT -> insetLeft - screenLayout.insetLeft.roundToPx() + sideBar.width.roundToPx() - spacing12 - backIconPlaceable.width
607
- SideBarEdge.RIGHT -> layoutWidth + (if (applySafeAreaPadding) 0 else screenLayout.insetRight.roundToPx()) - sideBar.width.roundToPx() + spacing12
608
- }
609
- backIconPlaceable.place(
610
- x = x,
611
- y = sideBar.top.roundToPx() + (DuoMetrics.controlSize.roundToPx() - backIconPlaceable.height) / 2,
612
- )
613
- }
614
- }
615
- headerRightPlaceable?.place(
616
- x = layoutWidth - insetRight - spacing12 - headerRightPlaceable.safeWidth,
617
- y = startY + headerRightPlaceable.verticalCenterOffset(headerRowDefault),
618
- )
619
-
620
- val titleOffset = IntOffset(
621
- x = if (titlePosition == TitlePosition.LEFT) curX
622
- else insetLeft + titlePlaceable.horizontalCenterOffset(
623
- space = safeWidth - spacing12 * 2,
624
- layoutDirection = layoutDirection,
625
- ),
626
- y = startY + titlePlaceable.verticalCenterOffset(headerRowDefault),
627
- )
628
-
629
- titlePlaceable?.place(titleOffset)
630
-
631
- if ((backIconPlaceable != null && screenLayout.sideBar == null) || headerRightPlaceable != null || titlePlaceable != null) {
632
- curY += headerRowDefault
633
- }
634
-
635
- val inputSearchOffset = if (isHeaderExtend) {
636
- val baseY = curY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault)
637
- val y = (baseY * (1 - scrollPercent)).toInt().coerceAtLeast(
638
- startY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault)
639
- )
640
- IntOffset(
641
- x = startX + ((headerBackWidth + spaceBetween) * (scrollPercent * 2f).coerceIn(
642
- 0f, 1f
643
- )).toInt(),
644
- y = y,
645
- )
646
- } else {
647
- IntOffset(
648
- x = curX,
649
- y = startY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault),
650
- )
651
- }
652
- val finalPosition = lerp(
653
- searchStartPosition,
654
- inputSearchOffset,
655
- progress,
656
- )
657
-
658
- inputSearchPlaceable?.place(
659
- finalPosition
660
- )
661
- }
662
- }
663
-
664
- private val Placeable?.safeHeight
665
- get() = this?.height ?: 0
666
- private val Placeable?.safeWidth
667
- get() = this?.width ?: 0
668
-
669
- private fun Constraints.withAnimationTargetBounds(): Constraints {
670
- val option = animationOption ?: return this
671
- val progress = option.progress.value
672
- if (progress >= 1f) return this
673
-
674
- val targetWidth = option.targetBounds.width.roundToInt().coerceAtLeast(0)
675
- val targetHeight = option.targetBounds.height.roundToInt().coerceAtLeast(0)
676
- val animatedMinWidth = lerpPx(targetWidth, minWidth, progress)
677
- .coerceInBounds(maxWidth)
678
- val animatedMaxWidth = lerpMaxPx(targetWidth, maxWidth, progress)
679
- .coerceAtLeast(animatedMinWidth)
680
- val animatedMinHeight = lerpPx(targetHeight, minHeight, progress)
681
- .coerceInBounds(maxHeight)
682
- val animatedMaxHeight = lerpMaxPx(targetHeight, maxHeight, progress)
683
- .coerceAtLeast(animatedMinHeight)
684
-
685
- return copy(
686
- minWidth = animatedMinWidth,
687
- maxWidth = animatedMaxWidth,
688
- minHeight = animatedMinHeight,
689
- maxHeight = animatedMaxHeight,
690
- )
691
- }
692
-
693
- private fun lerpPx(
694
- start: Int,
695
- stop: Int,
696
- fraction: Float,
697
- ): Int = androidx.compose.ui.util.lerp(
698
- start.toFloat(),
699
- stop.toFloat(),
700
- fraction,
701
- ).roundToInt()
702
-
703
- private fun lerpMaxPx(
704
- start: Int,
705
- stop: Int,
706
- fraction: Float,
707
- ): Int {
708
- if (stop == Constraints.Infinity) return Constraints.Infinity
709
- return lerpPx(start, stop, fraction)
710
- }
711
-
712
- private fun Int.coerceInBounds(max: Int): Int {
713
- if (max == Constraints.Infinity) return coerceAtLeast(0)
714
- return coerceIn(0, max)
715
- }
716
-
717
- private fun Placeable?.verticalCenterOffset(space: Int): Int {
718
- if (this == null) return 0
719
- return Alignment.CenterVertically.align(safeHeight, space)
720
- }
721
-
722
- private fun Placeable?.horizontalCenterOffset(
723
- space: Int,
724
- layoutDirection: LayoutDirection
725
- ): Int {
726
- if (this == null) return 0
727
- return Alignment.CenterHorizontally.align(safeWidth, space, layoutDirection)
728
- }
729
- }
730
-
731
- private val EMPTY_FUNC = {}
732
-
733
- @Stable
734
- data class LiteInputSearchProps(
735
- val textFieldState: MutableState<String>,
736
- val onValueChange: (String) -> Unit,
737
- val onClear: () -> Unit = EMPTY_FUNC,
738
- val clearCondition: (() -> Boolean)? = null,
739
- val modifier: Modifier = Modifier,
740
- val onFocused: (() -> Unit) = EMPTY_FUNC,
741
- val keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
742
- val keyboardActions: KeyboardActions = KeyboardActions.Default,
743
- val onKeyboardAction: (() -> Unit) = EMPTY_FUNC,
744
-
745
- val btnText: String? = null,
746
- val isShowBtnText: Boolean = !btnText.isNullOrEmpty(),
747
- val onPressBtnText: (() -> Unit) = EMPTY_FUNC,
748
-
749
- val disabled: Boolean = false,
750
-
751
- val placeHolder: String? = null,
752
-
753
- val cursorBrush: Brush? = null,
754
- val customBackIcon: @Composable ((Modifier) -> Unit)? = null,
755
- val customSearchIcon: @Composable (() -> Unit)? = null,
756
- val customPlaceHolder: @Composable (() -> Unit)? = null,
757
- val customTextStyle: TextStyle? = null,
758
- val customIconClear: @Composable (() -> Unit)? = null,
759
- val iconRightTextField: @Composable ((Modifier) -> Unit)? = null,
760
- )
761
-
762
- @Composable
763
- private fun LiteInputSearch(
764
- modifier: Modifier = Modifier,
765
- inputSearchProps: LiteInputSearchProps? = null,
766
- ) {
767
- inputSearchProps ?: return
768
- val theme = AppTheme.current
769
-
770
- val isFocused = remember { mutableStateOf(false) }
771
- val interactionSource = remember { MutableInteractionSource() }
772
- val textState by remember { inputSearchProps.textFieldState }
773
-
774
- val isShowBtnText by remember(inputSearchProps.isShowBtnText, inputSearchProps.btnText) {
775
- derivedStateOf {
776
- inputSearchProps.isShowBtnText && !inputSearchProps.btnText.isNullOrEmpty()
777
- }
778
- }
779
- val inputFieldFontFamily = getFontFamily(theme.font, Typography.bodyDefaultRegular.fontWeight)
780
- val inputFieldStyle = remember(theme, inputFieldFontFamily) {
781
- Typography.bodyDefaultRegular.copy(
782
- color = theme.colors.text.default,
783
- fontFamily = inputFieldFontFamily,
784
- )
785
- }
786
-
787
- LaunchedEffect(inputSearchProps.onFocused) {
788
- interactionSource.interactions.mapNotNull { it as? FocusInteraction }.collectLatest {
789
- val isFocus = it is FocusInteraction.Focus
790
- isFocused.value = isFocus
791
- if (isFocus) inputSearchProps.onFocused()
792
- }
793
- }
794
-
795
- Row(
796
- modifier = modifier,
797
- verticalAlignment = Alignment.CenterVertically,
798
- ) {
799
- val textFieldModifier = remember(inputSearchProps.modifier) {
800
- inputSearchProps.modifier
801
- .weight(1f)
802
- }
803
- BasicTextField(
804
- value = textState,
805
- onValueChange = inputSearchProps.onValueChange,
806
- enabled = !inputSearchProps.disabled,
807
- keyboardOptions = inputSearchProps.keyboardOptions,
808
- keyboardActions = inputSearchProps.keyboardActions,
809
- modifier = textFieldModifier,
810
- textStyle = inputSearchProps.customTextStyle ?: inputFieldStyle,
811
- singleLine = true,
812
- cursorBrush = inputSearchProps.cursorBrush ?: SolidColor(Color.Black),
813
- interactionSource = interactionSource,
814
- decorationBox = { innerTextField ->
815
- val isShowClear by remember(inputSearchProps.clearCondition, isFocused.value) {
816
- derivedStateOf {
817
- inputSearchProps.clearCondition?.invoke() == true || (isFocused.value && textState.isNotEmpty())
818
- }
819
- }
820
- val placeHolder by produceState<String?>(null, inputSearchProps.placeHolder) {
821
- if (inputSearchProps.placeHolder.isNullOrEmpty()) return@produceState
822
- snapshotFlow { textState }.collectLatest {
823
- value = if (it.isEmpty()) inputSearchProps.placeHolder else null
824
- }
825
- }
826
- val iconRightModifier = remember {
827
- Modifier
828
- .padding(start = Spacing.L)
829
- .drawWithContent {
830
- val offsetX = -Spacing.S.toPx()
831
- drawLine(
832
- start = Offset(
833
- x = offsetX,
834
- y = 0f,
835
- ),
836
- end = Offset(
837
- x = offsetX,
838
- y = size.height,
839
- ),
840
- color = theme.colors.primary,
841
- strokeWidth = 1.dp.toPx(),
842
- )
843
- drawContent()
844
- }
845
- }
846
-
847
- Row(
848
- modifier = Modifier
849
- .padding(
850
- horizontal = Spacing.M,
851
- vertical = Spacing.S,
852
- ),
853
- horizontalArrangement = Arrangement.Start,
854
- verticalAlignment = Alignment.CenterVertically,
855
- ) {
856
- inputSearchProps.customSearchIcon?.invoke() ?: Icon(
857
- source = "navigation_search",
858
- modifier = Modifier.padding(end = Spacing.XS),
859
- size = 24.dp,
860
- color = theme.colors.text.hint
861
- )
862
- Box(
863
- modifier = Modifier.weight(1f),
864
- contentAlignment = Alignment.CenterStart,
865
- ) {
866
- if (!placeHolder.isNullOrEmpty()) {
867
- inputSearchProps.customPlaceHolder?.invoke() ?: Text(
868
- text = placeHolder ?: "",
869
- style = inputSearchProps.customTextStyle
870
- ?: Typography.bodyDefaultRegular,
871
- maxLines = 1,
872
- color = theme.colors.text.hint,
873
- overflow = TextOverflow.Ellipsis
874
- )
875
- }
876
- innerTextField()
877
- }
878
-
879
- if (isShowClear) {
880
- inputSearchProps.customIconClear?.invoke() ?: Icon(
881
- source = "24_navigation_close_circle_full",
882
- size = 16.dp,
883
- color = theme.colors.text.hint,
884
- modifier = Modifier.padding(start = Spacing.XS)
885
- .noFeedbackClickable(onClick = inputSearchProps.onClear),
886
- )
887
- }
888
-
889
- inputSearchProps.iconRightTextField?.invoke(iconRightModifier)
890
- }
891
- }
892
- )
893
-
894
- if (isShowBtnText) {
895
- Text(
896
- text = inputSearchProps.btnText ?: "",
897
- style = Typography.actionDefaultBold,
898
- color = theme.colors.text.default,
899
- modifier = Modifier.padding(start = Spacing.L)
900
- .noFeedbackClickable(onClick = inputSearchProps.onPressBtnText)
901
- )
902
- }
903
- }
904
- }
905
-
906
- fun Modifier.hideKeyboardOnTap() = composed {
907
- val focusManager = LocalFocusManager.current
908
- val keyboardManager = LocalSoftwareKeyboardController.current
909
-
910
- pointerInput(Unit) {
911
- detectTapGestures {
912
- keyboardManager?.hide()
913
- focusManager.clearFocus()
914
- }
915
- }
916
- }