@momo-kits/native-kits 0.167.1-duo.18-debug → 0.167.1-duo.18

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 (148) hide show
  1. package/package.json +1 -1
  2. package/build.gradle.kts +0 -11
  3. package/compose/build.gradle.kts +0 -204
  4. package/compose/build.gradle.kts.backup +0 -204
  5. package/compose/compose.podspec +0 -47
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
  9. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
  10. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -153
  11. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +0 -6
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -916
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -81
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -115
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -86
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -478
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -265
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -235
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -265
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -361
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -108
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -308
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -330
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -207
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -92
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -560
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -501
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -236
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -180
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -20
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -194
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -283
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -309
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -338
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -137
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -205
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -713
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -218
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -231
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +0 -98
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +0 -312
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -447
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -103
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -106
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -379
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -39
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -192
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -133
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -74
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +0 -13
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
  134. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -78
  135. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
  136. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
  137. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
  138. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
  139. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -217
  140. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +0 -94
  141. package/gradle/libs.versions.toml +0 -69
  142. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  143. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  144. package/gradle.properties +0 -26
  145. package/gradlew +0 -252
  146. package/gradlew.bat +0 -94
  147. package/ios-demo/README.md +0 -120
  148. 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.headerFontFamily
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 = headerFontFamily,
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
- }