@momo-kits/native-kits 0.167.1-duo-search.1-debug → 0.167.1-duo-search.2-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +4 -1
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +134 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +20 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +9 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +11 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +4 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +10 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +7 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +13 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +13 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +3 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +14 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +19 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +5 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +7 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +11 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +8 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +2 -1
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +11 -0
- package/ios/Application/ComposeApi.swift +2 -1
- package/ios/Application/{Components.swift → LegacyHeader.swift} +6 -62
- package/ios/Application/Screen.swift +3 -2
- package/ios/Avatar/Avatar.swift +4 -3
- package/ios/Badge/Badge.swift +6 -4
- package/ios/Badge/BadgeDot.swift +1 -1
- package/ios/Badge/BadgeRibbon.swift +0 -1
- package/ios/Button/Button.swift +15 -12
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +12 -20
- package/ios/Carousel/Carousel.swift +29 -12
- package/ios/Checkbox/Checkbox.swift +7 -3
- package/ios/Chip/Chip.swift +5 -4
- package/ios/Collapse/Collapse.swift +70 -19
- package/ios/Colors+Radius+Spacing/Colors.swift +9 -0
- package/ios/DateTimePicker/DateTimePicker.swift +54 -20
- package/ios/DateTimePicker/WheelPicker.swift +103 -105
- package/ios/Divider/Divider.swift +37 -4
- package/ios/Extensions/Color++.swift +18 -0
- package/ios/Extensions/SkeletonUICompat.swift +11 -0
- package/ios/Icon/Icon.swift +7 -1
- package/ios/IconButton/IconButton.swift +15 -7
- package/ios/Image/Image.swift +7 -34
- package/ios/Information/Information.swift +27 -9
- package/ios/Input/ErrorView.swift +2 -2
- package/ios/Input/Input.swift +160 -147
- package/ios/Input/InputPhoneNumber.swift +12 -9
- package/ios/Input/InputSearch.swift +102 -75
- package/ios/Input/InputTextArea.swift +128 -145
- package/ios/InputDropDown/InputDropDown.swift +10 -7
- package/ios/InputMoney/InputMoney.swift +33 -11
- package/ios/InputOTP/InputOTP.swift +22 -12
- package/ios/Layout/Card.swift +50 -0
- package/ios/Layout/GridContext.swift +123 -3
- package/ios/Layout/Item.swift +5 -4
- package/ios/Layout/Section.swift +4 -100
- package/ios/Loader/Loader.swift +5 -9
- package/ios/Lottie/LottieView.swift +10 -0
- package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +65 -9
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTab.swift +60 -34
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +11 -6
- package/ios/{Application → Navigation/Component}/FloatingButton.swift +14 -3
- package/ios/Navigation/Component/Header.swift +493 -0
- package/ios/Navigation/Component/HeaderBackground.swift +134 -0
- package/ios/Navigation/Component/HeaderJourney.swift +73 -0
- package/ios/Navigation/Component/HeaderLocation.swift +48 -0
- package/ios/Navigation/Component/HeaderRight.swift +386 -0
- package/ios/Navigation/Component/HeaderTitle.swift +36 -0
- package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +20 -23
- package/ios/{Application/Navigation/component → Navigation/Component}/SideBar.swift +49 -28
- package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +5 -5
- package/ios/Navigation/HostBackGestureBridge.swift +57 -0
- package/ios/Navigation/Navigation.swift +190 -0
- package/ios/{Application/Navigation → Navigation}/NavigationContainer.swift +46 -41
- package/ios/{Application/Navigation → Navigation}/Navigator.swift +65 -9
- package/ios/{Application → Navigation}/StackScreen.swift +236 -103
- package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
- package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
- package/ios/Pagination/PaginationScroll.swift +2 -2
- package/ios/Popup/PopupDisplay.swift +79 -159
- package/ios/Popup/PopupInput.swift +10 -13
- package/ios/Popup/PopupLayout.swift +97 -2
- package/ios/Popup/PopupNotify.swift +27 -55
- package/ios/Popup/PopupPromotion.swift +22 -50
- package/ios/PopupView/FullscreenPopup.swift +13 -19
- package/ios/PopupView/PopupView.swift +1 -1
- package/ios/PopupView/Utils++.swift +0 -8
- package/ios/ProgressInfo/ProgressInfo.swift +4 -2
- package/ios/Radio/Radio.swift +2 -1
- package/ios/Rating/Rating.swift +9 -1
- package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
- package/ios/Skeleton/Skeleton.swift +22 -27
- package/ios/Slider/Slider.swift +16 -18
- package/ios/Stepper/Stepper.swift +6 -1
- package/ios/Steps/Steps.swift +8 -6
- package/ios/SuggestAction/SuggestAction.swift +5 -0
- package/ios/Swipeable/SwipeCell.swift +10 -6
- package/ios/Switch/Switch.swift +22 -20
- package/ios/TabView/TabView.swift +102 -21
- package/ios/Tag/Tag.swift +15 -4
- package/ios/Template/Logo/Logo.swift +2 -1
- package/ios/Template/TrustBanner/TrustBanner.swift +41 -27
- package/ios/Title/Title.swift +6 -17
- package/ios/Tooltip/Tooltip.swift +29 -14
- package/ios/Typography/Text.swift +61 -19
- package/ios/Uploader/Uploader.swift +3 -1
- package/ios/native-kits.podspec +2 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
- package/package.json +1 -1
- package/ios/Application/HeaderRight.swift +0 -324
- package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
- package/ios/Application/Navigation/HeaderTitle.swift +0 -57
- package/ios/Application/Navigation/NavigationOptions.swift +0 -109
- package/ios/Application/Navigation/NavigatorManager.swift +0 -29
- package/ios/Application/Navigation/component/DuoScrollGradient.swift +0 -54
- package/ios/Application/Navigation/component/Header.swift +0 -183
- package/ios/Application/Navigation/component/HeaderBackground.swift +0 -84
- package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
- package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
- package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -280
- /package/ios/{Application/Layout → Layout}/ScreenLayout.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoBarCompression.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoTabBar.swift +0 -0
- /package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +0 -0
package/CLAUDE.md
CHANGED
|
@@ -56,7 +56,10 @@ Publishing is automated (`publish.sh` + GitLab CI on `[ci build]` / `main`). Do
|
|
|
56
56
|
|
|
57
57
|
## SwiftUI kit (`ios/`)
|
|
58
58
|
|
|
59
|
-
-
|
|
59
|
+
- **Layout mirrors Compose:** `ios/Navigation/` follows `navigation/` file for file (`NavigationContainer`, `Navigator`, `Navigation` (options + per-screen `Navigation`), `StackScreen` (incl. `NavigationFooter`), `BottomSheet`, `ModalScreen`, `HostBackGestureBridge`, `BottomTab/`, `Component/`, `Tracking/`); `ios/Layout/ScreenLayout.swift` mirrors `layout/`. `ios/Application/` keeps only context (`ApplicationEnvironment`), `Localize*`, `MaxApi` and the deprecated `Screen` / `LegacyHeader` (Compose `application/`). Change a navigation piece on both sides together.
|
|
60
|
+
- **File basenames must be unique across the pod** — Swift fails with "filename used twice" even in different folders (hence `LegacyHeader.swift` next to `Navigation/Component/Header.swift`). New folders under `ios/` must be added to `source_files` in `ios/native-kits.podspec`.
|
|
61
|
+
- Screens update their own chrome at runtime through `@EnvironmentObject var navigation: Navigation` → `setOptions { $0.title = … }` (Compose `LocalNavigation`); bottom tabs keep one `Navigation` per tab. The host back bridge is `HostBackGestureBridge.shared` (`NavigatorManager` is a deprecated alias); a bottom tab off its first tab routes back to the first tab (`Navigator.tabBackHandler`, keyed by the hosting screen).
|
|
62
|
+
- The pod's minimum is **iOS 15**, but the navigation shell (`NavigationContainer`, `Navigator`, `HostBackGestureBridge`, `BottomTab`, overplay views) is **iOS 16+** (`@available(iOS 16.0, *)`) because it is built on `NavigationStack`. Keep components outside that shell iOS 15-compatible.
|
|
60
63
|
- `present` opens one `fullScreenCover` that hosts its own `NavigationStack` (`Navigator.presentedPath`): pushes and pops act on the presented flow while it is up, and each overplay (modal / bottom sheet / snackbar) renders in the context it was shown over (`OverplayItem.presentedId`).
|
|
61
64
|
- Icons are compiled in: `ios/Icon/Icons.swift` is generated from Compose `utils/Icons.kt` by `node scripts/gen-ios-icons.mjs` — don't hand-edit it. A host `icon.json` in the main bundle only adds keys the kit lacks.
|
|
62
65
|
- Bundled assets (colors, Lottie JSON) live in `ios/Resources` and ship in the `MoMoUIKitsResources` bundle; load them through `MoMoUIKitsResources.bundle`, never `Bundle.main`.
|
package/compose/build.gradle.kts
CHANGED
package/compose/compose.podspec
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.FloatRange
|
|
4
|
-
import androidx.compose.
|
|
5
|
-
import androidx.compose.foundation
|
|
4
|
+
import androidx.compose.foundation.ScrollState
|
|
5
|
+
import androidx.compose.foundation.background
|
|
6
|
+
import androidx.compose.foundation.border
|
|
6
7
|
import androidx.compose.foundation.gestures.detectTapGestures
|
|
7
8
|
import androidx.compose.foundation.interaction.FocusInteraction
|
|
8
9
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
9
|
-
import androidx.compose.foundation.layout
|
|
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
|
|
10
17
|
import androidx.compose.foundation.shape.CircleShape
|
|
11
18
|
import androidx.compose.foundation.text.BasicTextField
|
|
12
19
|
import androidx.compose.foundation.text.KeyboardActions
|
|
13
20
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
14
|
-
import androidx.compose.
|
|
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
|
|
15
35
|
import androidx.compose.ui.Alignment
|
|
16
36
|
import androidx.compose.ui.Modifier
|
|
17
37
|
import androidx.compose.ui.composed
|
|
@@ -25,13 +45,25 @@ import androidx.compose.ui.graphics.Color
|
|
|
25
45
|
import androidx.compose.ui.graphics.SolidColor
|
|
26
46
|
import androidx.compose.ui.graphics.graphicsLayer
|
|
27
47
|
import androidx.compose.ui.input.pointer.pointerInput
|
|
28
|
-
import androidx.compose.ui.layout
|
|
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
|
|
29
55
|
import androidx.compose.ui.platform.LocalDensity
|
|
30
56
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
31
57
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
32
58
|
import androidx.compose.ui.text.TextStyle
|
|
33
59
|
import androidx.compose.ui.text.style.TextOverflow
|
|
34
|
-
import androidx.compose.ui.unit
|
|
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
|
|
35
67
|
import kotlinx.coroutines.flow.collectLatest
|
|
36
68
|
import kotlinx.coroutines.flow.mapNotNull
|
|
37
69
|
import vn.momo.kits.components.Icon
|
|
@@ -41,15 +73,21 @@ import vn.momo.kits.const.Colors
|
|
|
41
73
|
import vn.momo.kits.const.Spacing
|
|
42
74
|
import vn.momo.kits.const.Typography
|
|
43
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
|
|
44
81
|
import vn.momo.kits.modifier.kitsAutomationId
|
|
45
82
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
46
83
|
import vn.momo.kits.modifier.setAutomationId
|
|
47
84
|
import vn.momo.kits.navigation.component.HEADER_FONT_FAMILY
|
|
48
85
|
import vn.momo.kits.navigation.component.HEADER_HEIGHT
|
|
86
|
+
import vn.momo.kits.navigation.component.SideBarButton
|
|
49
87
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
50
|
-
import vn.momo.kits.utils.horizontalSafeAreaPadding
|
|
51
88
|
import kotlin.math.max
|
|
52
89
|
import kotlin.math.roundToInt
|
|
90
|
+
import vn.momo.kits.navigation.component.getHeaderColor as getNavigationHeaderColor
|
|
53
91
|
|
|
54
92
|
|
|
55
93
|
data class AnimationOption(
|
|
@@ -117,8 +155,7 @@ fun LiteScreen(
|
|
|
117
155
|
scrollState = finalScrollState,
|
|
118
156
|
modifier = Modifier
|
|
119
157
|
.fillMaxSize()
|
|
120
|
-
.hideKeyboardOnTap()
|
|
121
|
-
.horizontalSafeAreaPadding(),
|
|
158
|
+
.hideKeyboardOnTap(),
|
|
122
159
|
contentModifier = contentModifier,
|
|
123
160
|
verticalArrangement = verticalArrangement,
|
|
124
161
|
horizontalAlignment = horizontalAlignment,
|
|
@@ -171,6 +208,8 @@ private fun LiteScreenLayout(
|
|
|
171
208
|
content: @Composable () -> Unit,
|
|
172
209
|
) {
|
|
173
210
|
val statusBarHeight = getAppStatusBarHeight()
|
|
211
|
+
val screenLayout = getScreenLayout()
|
|
212
|
+
val applySafeAreaPadding = screenLayout.sideBar != null
|
|
174
213
|
val isHeaderNone = remember(headerType) {
|
|
175
214
|
headerType == HeaderType.NONE
|
|
176
215
|
}
|
|
@@ -232,6 +271,12 @@ private fun LiteScreenLayout(
|
|
|
232
271
|
val animationOpacityModifier = Modifier.graphicsLayer {
|
|
233
272
|
alpha = animationOption?.animateOpacity ?: 1f
|
|
234
273
|
}
|
|
274
|
+
val sideBarColor = getNavigationHeaderColor(
|
|
275
|
+
vn.momo.kits.navigation.component.HeaderType.Default(),
|
|
276
|
+
1f,
|
|
277
|
+
null,
|
|
278
|
+
Colors.black_17,
|
|
279
|
+
)
|
|
235
280
|
val titleModifier = Modifier
|
|
236
281
|
.kitsAutomationId("title_navigation_header")
|
|
237
282
|
.layoutId(HeaderId.TITLE_ID)
|
|
@@ -243,6 +288,8 @@ private fun LiteScreenLayout(
|
|
|
243
288
|
}
|
|
244
289
|
|
|
245
290
|
val policy = remember(
|
|
291
|
+
screenLayout,
|
|
292
|
+
applySafeAreaPadding,
|
|
246
293
|
useAnimationSearch,
|
|
247
294
|
isHeaderNone,
|
|
248
295
|
isHeaderExtend,
|
|
@@ -255,6 +302,8 @@ private fun LiteScreenLayout(
|
|
|
255
302
|
horizontalAlignment,
|
|
256
303
|
) {
|
|
257
304
|
LiteScreenLayoutPolicy(
|
|
305
|
+
screenLayout = screenLayout,
|
|
306
|
+
applySafeAreaPadding = applySafeAreaPadding,
|
|
258
307
|
useAnimationSearch = useAnimationSearch,
|
|
259
308
|
isHeaderNone = isHeaderNone,
|
|
260
309
|
isHeaderExtend = isHeaderExtend,
|
|
@@ -269,13 +318,13 @@ private fun LiteScreenLayout(
|
|
|
269
318
|
}
|
|
270
319
|
|
|
271
320
|
Layout(
|
|
272
|
-
modifier = modifier
|
|
273
|
-
.animateContentSize(),
|
|
321
|
+
modifier = modifier,
|
|
274
322
|
content = {
|
|
275
323
|
Box(
|
|
276
324
|
modifier = animationOpacityModifier
|
|
277
325
|
.layoutId(HeaderId.CONTENT_ID)
|
|
278
|
-
.then(contentModifier)
|
|
326
|
+
.then(contentModifier)
|
|
327
|
+
.then(if (applySafeAreaPadding) Modifier.horizontalSafeAreaPadding() else Modifier),
|
|
279
328
|
contentAlignment = Alignment.TopCenter,
|
|
280
329
|
) {
|
|
281
330
|
content()
|
|
@@ -311,28 +360,44 @@ private fun LiteScreenLayout(
|
|
|
311
360
|
}
|
|
312
361
|
|
|
313
362
|
if (!isHeaderNone && onGoBack != null) {
|
|
314
|
-
|
|
315
|
-
.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
+
}
|
|
336
401
|
}
|
|
337
402
|
}
|
|
338
403
|
|
|
@@ -376,6 +441,8 @@ private fun LiteScreenLayout(
|
|
|
376
441
|
}
|
|
377
442
|
|
|
378
443
|
private class LiteScreenLayoutPolicy(
|
|
444
|
+
private val screenLayout: ScreenLayout,
|
|
445
|
+
private val applySafeAreaPadding: Boolean,
|
|
379
446
|
private val useAnimationSearch: Boolean,
|
|
380
447
|
private val isHeaderNone: Boolean,
|
|
381
448
|
private val isHeaderExtend: Boolean,
|
|
@@ -409,10 +476,13 @@ private class LiteScreenLayoutPolicy(
|
|
|
409
476
|
|
|
410
477
|
val contentMeasurable = measurables.find { it.layoutId == HeaderId.CONTENT_ID }
|
|
411
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)
|
|
412
482
|
val realConstraints = constraints.copy(
|
|
413
483
|
minWidth = 0,
|
|
414
484
|
minHeight = 0,
|
|
415
|
-
maxWidth = (
|
|
485
|
+
maxWidth = (safeWidth - spacing12 * 2)
|
|
416
486
|
.coerceAtLeast(0),
|
|
417
487
|
)
|
|
418
488
|
val backIconPlaceable =
|
|
@@ -423,9 +493,10 @@ private class LiteScreenLayoutPolicy(
|
|
|
423
493
|
maxWidth = realConstraints.maxWidth / 2,
|
|
424
494
|
)
|
|
425
495
|
)
|
|
496
|
+
val headerBackWidth = if (screenLayout.sideBar == null) backIconPlaceable.safeWidth else 0
|
|
426
497
|
val baseInputSearchConstraints = if (isHeaderExtend) {
|
|
427
498
|
val minWidth =
|
|
428
|
-
if (useAnimationSearch) realConstraints.maxWidth -
|
|
499
|
+
if (useAnimationSearch) realConstraints.maxWidth - headerBackWidth - headerRightPlaceable.safeWidth - spaceBetween * 2
|
|
429
500
|
else realConstraints.maxWidth
|
|
430
501
|
realConstraints.copy(
|
|
431
502
|
maxWidth = (realConstraints.maxWidth * (1 - scrollPercent)).toInt()
|
|
@@ -433,7 +504,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
433
504
|
)
|
|
434
505
|
} else {
|
|
435
506
|
var spaceConsumed = 0
|
|
436
|
-
if (
|
|
507
|
+
if (headerBackWidth != 0) spaceConsumed += headerBackWidth + spaceBetween
|
|
437
508
|
if (headerRightPlaceable.safeWidth != 0) spaceConsumed += headerRightPlaceable.safeWidth + spaceBetween
|
|
438
509
|
realConstraints.copy(
|
|
439
510
|
maxWidth = realConstraints.maxWidth - spaceConsumed
|
|
@@ -444,7 +515,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
444
515
|
?.measure(inputSearchConstraints)
|
|
445
516
|
val titlePlaceable = measurables.find { it.layoutId == HeaderId.TITLE_ID }?.measure(
|
|
446
517
|
constraints = realConstraints.copy(
|
|
447
|
-
maxWidth = realConstraints.maxWidth -
|
|
518
|
+
maxWidth = realConstraints.maxWidth - headerBackWidth - headerRightPlaceable.safeWidth - spaceBetween * 2
|
|
448
519
|
)
|
|
449
520
|
)
|
|
450
521
|
|
|
@@ -466,6 +537,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
466
537
|
|
|
467
538
|
val layoutWidth = constraints.maxWidth
|
|
468
539
|
val layoutHeight = constraints.maxHeight
|
|
540
|
+
val backgroundInsetLeft = if (!applySafeAreaPadding && screenLayout.sideBar != null) screenLayout.insetLeft.roundToPx() else 0
|
|
469
541
|
val contentHeight = (layoutHeight - headerHeight).coerceAtLeast(0)
|
|
470
542
|
val contentPlaceable = contentMeasurable?.measure(
|
|
471
543
|
constraints.copy(
|
|
@@ -502,7 +574,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
502
574
|
) {
|
|
503
575
|
val progress = animationOption?.progress?.value ?: 1f
|
|
504
576
|
|
|
505
|
-
val startX = spacing12
|
|
577
|
+
val startX = insetLeft + spacing12
|
|
506
578
|
val startY = headerY + statusBarPx
|
|
507
579
|
var curX = startX
|
|
508
580
|
var curY = startY
|
|
@@ -517,27 +589,38 @@ private class LiteScreenLayoutPolicy(
|
|
|
517
589
|
)
|
|
518
590
|
|
|
519
591
|
backgroundPlaceable?.place(
|
|
520
|
-
x =
|
|
592
|
+
x = -backgroundInsetLeft,
|
|
521
593
|
y = headerY,
|
|
522
594
|
)
|
|
523
595
|
|
|
524
596
|
if (backIconPlaceable != null) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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
|
+
}
|
|
530
614
|
}
|
|
531
|
-
|
|
532
615
|
headerRightPlaceable?.place(
|
|
533
|
-
x = layoutWidth - spacing12 - headerRightPlaceable.safeWidth,
|
|
616
|
+
x = layoutWidth - insetRight - spacing12 - headerRightPlaceable.safeWidth,
|
|
534
617
|
y = startY + headerRightPlaceable.verticalCenterOffset(headerRowDefault),
|
|
535
618
|
)
|
|
536
619
|
|
|
537
620
|
val titleOffset = IntOffset(
|
|
538
621
|
x = if (titlePosition == TitlePosition.LEFT) curX
|
|
539
|
-
else titlePlaceable.horizontalCenterOffset(
|
|
540
|
-
space =
|
|
622
|
+
else insetLeft + titlePlaceable.horizontalCenterOffset(
|
|
623
|
+
space = safeWidth - spacing12 * 2,
|
|
541
624
|
layoutDirection = layoutDirection,
|
|
542
625
|
),
|
|
543
626
|
y = startY + titlePlaceable.verticalCenterOffset(headerRowDefault),
|
|
@@ -545,7 +628,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
545
628
|
|
|
546
629
|
titlePlaceable?.place(titleOffset)
|
|
547
630
|
|
|
548
|
-
if (backIconPlaceable != null || headerRightPlaceable != null || titlePlaceable != null) {
|
|
631
|
+
if ((backIconPlaceable != null && screenLayout.sideBar == null) || headerRightPlaceable != null || titlePlaceable != null) {
|
|
549
632
|
curY += headerRowDefault
|
|
550
633
|
}
|
|
551
634
|
|
|
@@ -555,7 +638,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
555
638
|
startY + inputSearchPlaceable.verticalCenterOffset(headerRowDefault)
|
|
556
639
|
)
|
|
557
640
|
IntOffset(
|
|
558
|
-
x = startX + ((
|
|
641
|
+
x = startX + ((headerBackWidth + spaceBetween) * (scrollPercent * 2f).coerceIn(
|
|
559
642
|
0f, 1f
|
|
560
643
|
)).toInt(),
|
|
561
644
|
y = y,
|
|
@@ -17,31 +17,30 @@ import vn.momo.kits.application.IsShowBaseLineDebug
|
|
|
17
17
|
import vn.momo.kits.const.*
|
|
18
18
|
import vn.momo.kits.modifier.conditional
|
|
19
19
|
|
|
20
|
+
private val badgePrimaryColors = listOf(
|
|
21
|
+
Color(0xFFF0F0F0),
|
|
22
|
+
Color(0xFFEB2F96),
|
|
23
|
+
Color(0xFF962AF0),
|
|
24
|
+
Color(0xFF4E4BFF),
|
|
25
|
+
Color(0xFF007AFF),
|
|
26
|
+
Color(0xFF13C2C2),
|
|
27
|
+
Color(0xFF34C759),
|
|
28
|
+
Color(0xFFA0D911),
|
|
29
|
+
Color(0xFFFFCC00),
|
|
30
|
+
Color(0xFFFA8C16),
|
|
31
|
+
Color(0xFFFA541C),
|
|
32
|
+
Color(0xFFF5222D)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
private val badgeNumberRegex = "^\\d+$".toRegex()
|
|
20
36
|
|
|
21
37
|
@Composable
|
|
22
38
|
fun Badge(label: String = "Label", backgroundColor: Color? = null, modifier: Modifier = Modifier) {
|
|
23
|
-
|
|
24
|
-
Color(0xFFF0F0F0),
|
|
25
|
-
Color(0xFFEB2F96),
|
|
26
|
-
Color(0xFF962AF0),
|
|
27
|
-
Color(0xFF4E4BFF),
|
|
28
|
-
Color(0xFF007AFF),
|
|
29
|
-
Color(0xFF13C2C2),
|
|
30
|
-
Color(0xFF34C759),
|
|
31
|
-
Color(0xFFA0D911),
|
|
32
|
-
Color(0xFFFFCC00),
|
|
33
|
-
Color(0xFFFA8C16),
|
|
34
|
-
Color(0xFFFA541C),
|
|
35
|
-
Color(0xFFF5222D)
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
fun isNumber(label: String): Boolean {
|
|
39
|
-
val numberRegex = "^\\d+$".toRegex()
|
|
40
|
-
return numberRegex.matches(label)
|
|
41
|
-
}
|
|
39
|
+
fun isNumber(label: String): Boolean = badgeNumberRegex.matches(label)
|
|
42
40
|
|
|
43
41
|
fun formatTitle(label: String): String {
|
|
44
|
-
|
|
42
|
+
// Digits too long for Int are well over 99; toInt() would throw.
|
|
43
|
+
if (isNumber(label) && (label.toIntOrNull() ?: Int.MAX_VALUE) > 99) {
|
|
45
44
|
return "99+"
|
|
46
45
|
}
|
|
47
46
|
return label
|
|
@@ -54,7 +53,7 @@ fun Badge(label: String = "Label", backgroundColor: Color? = null, modifier: Mod
|
|
|
54
53
|
AppTheme.current.colors.warning.primary
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
if (backgroundColor != null &&
|
|
56
|
+
if (backgroundColor != null && badgePrimaryColors.contains(backgroundColor)) {
|
|
58
57
|
badgeColor = backgroundColor
|
|
59
58
|
}
|
|
60
59
|
val scaleSize = scaleSize(16f)
|
|
@@ -146,7 +146,8 @@ fun RenderIcon(
|
|
|
146
146
|
) {
|
|
147
147
|
val iconSize = remember(size) { getIconSize(size) }
|
|
148
148
|
val margin = remember(size) { getIconSpace(size) }
|
|
149
|
-
|
|
149
|
+
// null = untinted; Color.Unspecified would tint with a transparent color and hide the icon.
|
|
150
|
+
val color = if (useTintColor) textColor else null
|
|
150
151
|
|
|
151
152
|
val modifier = Modifier.padding(
|
|
152
153
|
start = if (isIconLeft) 0.dp else margin,
|
|
@@ -43,6 +43,8 @@ fun Carousel(
|
|
|
43
43
|
val pagerState = rememberPagerState(initialPage = startPage) { virtualPageCount }
|
|
44
44
|
|
|
45
45
|
val realIndex: (Int) -> Int = { page -> page % itemCount }
|
|
46
|
+
val currentOnSnapToItem by rememberUpdatedState(onSnapToItem)
|
|
47
|
+
val currentOnScrollIndexChanged by rememberUpdatedState(onScrollIndexChanged)
|
|
46
48
|
|
|
47
49
|
var isUserScrolling by remember { mutableStateOf(false) }
|
|
48
50
|
|
|
@@ -70,8 +72,8 @@ fun Carousel(
|
|
|
70
72
|
LaunchedEffect(pagerState) {
|
|
71
73
|
snapshotFlow { pagerState.currentPage }.collect { page ->
|
|
72
74
|
val real = realIndex(page)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
currentOnSnapToItem(real)
|
|
76
|
+
currentOnScrollIndexChanged(real)
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -77,7 +77,7 @@ fun Chip(
|
|
|
77
77
|
horizontalArrangement = Arrangement.spacedBy(iconSpacing.dp)
|
|
78
78
|
) {
|
|
79
79
|
if (iconLeft != null) {
|
|
80
|
-
Icon(source = iconLeft, size =
|
|
80
|
+
Icon(source = iconLeft, size = iconSize.dp, color = leftTint)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
if (!label.isNullOrEmpty()) {
|
|
@@ -90,7 +90,7 @@ fun Information(
|
|
|
90
90
|
width = 0.5.dp,
|
|
91
91
|
shape = RoundedCornerShape(Radius.S),
|
|
92
92
|
color = borderColor
|
|
93
|
-
).background(color = backgroundColor)
|
|
93
|
+
).background(color = backgroundColor, shape = RoundedCornerShape(Radius.S))
|
|
94
94
|
.conditional(IsShowBaseLineDebug) {
|
|
95
95
|
border(1.dp, Colors.blue_03)
|
|
96
96
|
}
|
|
@@ -16,6 +16,7 @@ import androidx.compose.ui.Alignment
|
|
|
16
16
|
import androidx.compose.ui.Modifier
|
|
17
17
|
import androidx.compose.ui.focus.onFocusChanged
|
|
18
18
|
import androidx.compose.ui.graphics.Color
|
|
19
|
+
import androidx.compose.ui.graphics.SolidColor
|
|
19
20
|
import androidx.compose.ui.text.AnnotatedString
|
|
20
21
|
import androidx.compose.ui.text.SpanStyle
|
|
21
22
|
import androidx.compose.ui.text.TextStyle
|
|
@@ -214,7 +215,7 @@ fun Input(
|
|
|
214
215
|
|
|
215
216
|
// Memoized color calculations
|
|
216
217
|
val theme = AppTheme.current
|
|
217
|
-
val colors = remember(disabled, theme) {
|
|
218
|
+
val colors = remember(disabled, theme, iconColor) {
|
|
218
219
|
if (disabled) {
|
|
219
220
|
val disabledColor = theme.colors.text.disable
|
|
220
221
|
Triple(disabledColor, disabledColor, disabledColor)
|
|
@@ -241,8 +242,9 @@ fun Input(
|
|
|
241
242
|
val lineHeight = 24.sp
|
|
242
243
|
val scaleFontSize = scaleSize(fontSize)
|
|
243
244
|
val scaleLineHeight = scaleSize(lineHeight)
|
|
245
|
+
val scaledHeight = scaleSize(size.values.height)
|
|
244
246
|
|
|
245
|
-
val textStyle = remember(textColor, fontWeight) {
|
|
247
|
+
val textStyle = remember(textColor, fontWeight, scaleFontSize, scaleLineHeight) {
|
|
246
248
|
TextStyle(
|
|
247
249
|
color = textColor,
|
|
248
250
|
fontSize = scaleFontSize,
|
|
@@ -268,7 +270,7 @@ fun Input(
|
|
|
268
270
|
|
|
269
271
|
val passwordFontFamily = getFontFamily(AppTheme.current.font, FontWeight.Normal)
|
|
270
272
|
val passwordFontSize = scaleSize(24.sp)
|
|
271
|
-
val visualTransformation = remember(secureTextEntry, inputState.passHidden, passwordFontFamily) {
|
|
273
|
+
val visualTransformation = remember(secureTextEntry, inputState.passHidden, passwordFontFamily, passwordFontSize) {
|
|
272
274
|
if (secureTextEntry && !inputState.passHidden)
|
|
273
275
|
PasswordVisualTransformation(fontFamily = passwordFontFamily, fontSize = passwordFontSize)
|
|
274
276
|
else
|
|
@@ -287,8 +289,9 @@ fun Input(
|
|
|
287
289
|
textStyle = textStyle,
|
|
288
290
|
visualTransformation = visualTransformation,
|
|
289
291
|
keyboardOptions = keyboardOptionsConfig,
|
|
292
|
+
cursorBrush = SolidColor(theme.colors.primary),
|
|
290
293
|
modifier = inputModifier
|
|
291
|
-
.height(
|
|
294
|
+
.height(scaledHeight)
|
|
292
295
|
.onFocusChanged { focusState ->
|
|
293
296
|
val wasFocused = inputState.isFocused
|
|
294
297
|
inputState = inputState.copy(
|
|
@@ -313,7 +316,7 @@ fun Input(
|
|
|
313
316
|
floatingIcon = floatingIcon,
|
|
314
317
|
titleColor = floatingTitleColor,
|
|
315
318
|
iconColor = floatingIconTintColor,
|
|
316
|
-
offsetY = -
|
|
319
|
+
offsetY = -scaledHeight / 2,
|
|
317
320
|
required = required,
|
|
318
321
|
)
|
|
319
322
|
|
|
@@ -359,7 +362,7 @@ fun Input(
|
|
|
359
362
|
}
|
|
360
363
|
|
|
361
364
|
// Clear button
|
|
362
|
-
if (inputState.isFocused && text.value.isNotEmpty()) {
|
|
365
|
+
if (!readOnly && inputState.isFocused && text.value.isNotEmpty()) {
|
|
363
366
|
Row(Modifier.padding(horizontal = Spacing.XS)) {
|
|
364
367
|
Icon(
|
|
365
368
|
source = "24_navigation_close_circle_full",
|
|
@@ -27,6 +27,7 @@ import androidx.compose.ui.Alignment
|
|
|
27
27
|
import androidx.compose.ui.Modifier
|
|
28
28
|
import androidx.compose.ui.focus.onFocusChanged
|
|
29
29
|
import androidx.compose.ui.graphics.Color
|
|
30
|
+
import androidx.compose.ui.graphics.SolidColor
|
|
30
31
|
import androidx.compose.ui.semantics.contentDescription
|
|
31
32
|
import androidx.compose.ui.semantics.semantics
|
|
32
33
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -43,7 +44,9 @@ import vn.momo.kits.application.IsShowBaseLineDebug
|
|
|
43
44
|
import vn.momo.kits.const.Colors
|
|
44
45
|
import vn.momo.kits.const.Typography
|
|
45
46
|
import vn.momo.kits.const.getFontFamily
|
|
47
|
+
import vn.momo.kits.const.scaleSize
|
|
46
48
|
import vn.momo.kits.modifier.conditional
|
|
49
|
+
import vn.momo.kits.modifier.setAutomationId
|
|
47
50
|
|
|
48
51
|
private const val MONEY_CURRENCY = "đ"
|
|
49
52
|
|
|
@@ -134,7 +137,6 @@ fun InputMoney(
|
|
|
134
137
|
val current = if (digitsOf(field.text) == digits) field else moneyDisplay(digits).let {
|
|
135
138
|
TextFieldValue(it, TextRange(caretFromDigitIndex(it, digits.length)))
|
|
136
139
|
}
|
|
137
|
-
var isBlurred = false
|
|
138
140
|
val (textColor, placeholderColor, iconTintColor, floatingTitleColor, floatingIconTintColor) =
|
|
139
141
|
getInputColors(disabled, iconColor, floatingValueColor, floatingIconColor)
|
|
140
142
|
|
|
@@ -153,19 +155,16 @@ fun InputMoney(
|
|
|
153
155
|
value = current,
|
|
154
156
|
textStyle = TextStyle(
|
|
155
157
|
color = textColor,
|
|
156
|
-
fontSize = 20.sp,
|
|
157
|
-
lineHeight = 24.sp,
|
|
158
|
+
fontSize = scaleSize(20.sp),
|
|
159
|
+
lineHeight = scaleSize(24.sp),
|
|
158
160
|
fontWeight = fontWeight.value,
|
|
159
161
|
fontFamily = getFontFamily(AppTheme.current.font, fontWeight.value)
|
|
160
162
|
),
|
|
161
163
|
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = keyboardType),
|
|
164
|
+
cursorBrush = SolidColor(AppTheme.current.colors.primary),
|
|
162
165
|
modifier = Modifier.height(size.values.height).onFocusChanged {
|
|
166
|
+
if (it.isFocused) onFocus() else if (isFocused) onBlur()
|
|
163
167
|
isFocused = it.isFocused
|
|
164
|
-
if (it.isFocused) {
|
|
165
|
-
onFocus()
|
|
166
|
-
}
|
|
167
|
-
if (!it.isFocused && isBlurred) onBlur()
|
|
168
|
-
if (it.isFocused && !isBlurred) isBlurred = true
|
|
169
168
|
},
|
|
170
169
|
onValueChange = { value ->
|
|
171
170
|
if (value.text == current.text) {
|
|
@@ -223,7 +222,7 @@ fun InputMoney(
|
|
|
223
222
|
color = leadingIconColor
|
|
224
223
|
)
|
|
225
224
|
}
|
|
226
|
-
Box(Modifier.weight(9f)
|
|
225
|
+
Box(Modifier.weight(9f), contentAlignment = Alignment.CenterStart) {
|
|
227
226
|
if (text.value.isEmpty()) {
|
|
228
227
|
Text(
|
|
229
228
|
text = placeholder,
|
|
@@ -234,9 +233,9 @@ fun InputMoney(
|
|
|
234
233
|
),
|
|
235
234
|
color = placeholderColor
|
|
236
235
|
)
|
|
237
|
-
} else {
|
|
238
|
-
innerTextField()
|
|
239
236
|
}
|
|
237
|
+
// Composed even when empty so the caret shows over the placeholder.
|
|
238
|
+
innerTextField()
|
|
240
239
|
}
|
|
241
240
|
if (isFocused && text.value.isNotEmpty()) {
|
|
242
241
|
Row {
|
|
@@ -252,7 +251,7 @@ fun InputMoney(
|
|
|
252
251
|
},
|
|
253
252
|
interactionSource = remember { MutableInteractionSource() },
|
|
254
253
|
indication = null
|
|
255
|
-
)
|
|
254
|
+
).setAutomationId("ic_clear")
|
|
256
255
|
)
|
|
257
256
|
}
|
|
258
257
|
}
|