@momo-kits/native-kits 0.163.1-beta.8-debug → 0.163.1-beta.9-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 +1 -1
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +30 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +5 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +8 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +63 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +32 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +93 -75
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +26 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +23 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +11 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +26 -3
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +15 -2
- package/ios/Application/Components.swift +50 -44
- package/ios/Application/FloatingButton.swift +10 -9
- package/ios/Application/HeaderRight.swift +79 -45
- package/ios/Application/Localize.swift +277 -0
- package/ios/Application/MaxApi.swift +18 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
- package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
- package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
- package/ios/Application/Navigation/HeaderTitle.swift +57 -0
- package/ios/Application/Navigation/HeaderUser.swift +209 -0
- package/ios/Application/Navigation/NavigationContainer.swift +200 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +385 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
- package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
- package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
- package/ios/Application/Navigation/component/Header.swift +178 -0
- package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
- package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +501 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +11 -14
- package/ios/Badge/BadgeRibbon.swift +92 -21
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +124 -29
- package/ios/Carousel/Carousel.swift +196 -0
- package/ios/Checkbox/Checkbox.swift +23 -28
- package/ios/Chip/Chip.swift +56 -33
- package/ios/Collapse/Collapse.swift +192 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
- package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
- package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
- package/ios/DateTimePicker/DateTimePicker.swift +212 -0
- package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
- package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
- package/ios/DateTimePicker/WheelPicker.swift +165 -0
- package/ios/Divider/Divider.swift +16 -0
- package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +10 -1
- package/ios/IconButton/IconButton.swift +140 -0
- package/ios/Image/Image.swift +16 -3
- package/ios/Information/Information.swift +3 -1
- package/ios/Input/ErrorView.swift +3 -1
- package/ios/Input/Input.swift +72 -33
- package/ios/Input/InputPhoneNumber.swift +33 -21
- package/ios/Input/InputSearch.swift +107 -48
- package/ios/Input/InputTextArea.swift +134 -64
- package/ios/InputDropDown/InputDropDown.swift +201 -0
- package/ios/InputMoney/InputMoney.swift +347 -0
- package/ios/InputOTP/InputOTP.swift +210 -0
- package/ios/Loader/Loader.swift +113 -0
- package/ios/MoMoUIKits.podspec +5 -0
- package/ios/Pagination/PaginationDot.swift +61 -0
- package/ios/Pagination/PaginationNumber.swift +35 -0
- package/ios/Pagination/PaginationScroll.swift +101 -0
- package/ios/Pagination/PaginationWhiteDot.swift +37 -0
- package/ios/Popup/PopupDisplay.swift +11 -20
- package/ios/Popup/PopupInput.swift +2 -8
- package/ios/Popup/PopupNotify.swift +218 -0
- package/ios/Popup/PopupPromotion.swift +16 -8
- package/ios/ProgressInfo/ProgressInfo.swift +296 -0
- package/ios/Radio/Radio.swift +69 -0
- package/ios/Rating/Rating.swift +82 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
- package/ios/Skeleton/Skeleton.swift +99 -0
- package/ios/Slider/Slider.swift +237 -0
- package/ios/Stepper/Stepper.swift +220 -0
- package/ios/Steps/Steps.swift +467 -0
- package/ios/SuggestAction/SuggestAction.swift +99 -0
- package/ios/Swipeable/SwipeCell.swift +187 -0
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/Switch/Switch.swift +53 -28
- package/ios/TabView/TabView.swift +534 -0
- package/ios/Tag/Tag.swift +98 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
- package/ios/Title/Title.swift +269 -0
- package/ios/Tooltip/Tooltip.swift +485 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +79 -5
- package/ios/Typography/Typography.swift +3 -0
- package/ios/Uploader/Uploader.swift +174 -0
- package/ios/native-kits.podspec +61 -8
- package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
- package/ios-demo/README.md +120 -0
- package/ios-demo/Resources/dot_loading.json +558 -0
- package/ios-demo/Resources/icon.json +4052 -0
- package/ios-demo/Resources/lottie_circle_loader.json +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +63 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
- package/local.properties +2 -2
- package/package.json +1 -1
- package/publish.sh +53 -0
- package/scripts/gen-ios-color.mjs +136 -0
- package/.claude/settings.local.json +0 -62
package/ios/Input/Input.swift
CHANGED
|
@@ -3,12 +3,14 @@ import SwiftUI
|
|
|
3
3
|
import Combine
|
|
4
4
|
|
|
5
5
|
public struct Input: View {
|
|
6
|
+
@Environment(\.appTheme) private var theme
|
|
6
7
|
@Binding public var text: String
|
|
7
8
|
|
|
8
9
|
public var placeholder: String
|
|
9
10
|
public var floatingValue: String
|
|
11
|
+
public var floatingValueColor: Color?
|
|
10
12
|
public var floatingIcon: String
|
|
11
|
-
public var floatingIconColor: Color
|
|
13
|
+
public var floatingIconColor: Color?
|
|
12
14
|
public var size: InputSize
|
|
13
15
|
public var hintText: String
|
|
14
16
|
public var error: String
|
|
@@ -17,9 +19,9 @@ public struct Input: View {
|
|
|
17
19
|
public var readOnly: Bool
|
|
18
20
|
public var secureTextEntry: Bool
|
|
19
21
|
public var rightIcon: String
|
|
20
|
-
public var rightIconColor: Color
|
|
22
|
+
public var rightIconColor: Color?
|
|
21
23
|
public var leadingIcon: String
|
|
22
|
-
public var leadingIconColor: Color
|
|
24
|
+
public var leadingIconColor: Color?
|
|
23
25
|
public var loading: Bool
|
|
24
26
|
public var required: Bool
|
|
25
27
|
public var maxLength: Int?
|
|
@@ -33,13 +35,16 @@ public struct Input: View {
|
|
|
33
35
|
|
|
34
36
|
@State private var isFocused: Bool = false
|
|
35
37
|
@State private var isPasswordHidden: Bool = true
|
|
38
|
+
@FocusState private var isFieldFocused: Bool
|
|
39
|
+
@State private var floatingLabelHeight: CGFloat = 16
|
|
36
40
|
|
|
37
41
|
public init(
|
|
38
42
|
text: Binding<String>,
|
|
39
43
|
placeholder: String = "",
|
|
40
44
|
floatingValue: String = "",
|
|
45
|
+
floatingValueColor: Color? = nil,
|
|
41
46
|
floatingIcon: String = "",
|
|
42
|
-
floatingIconColor: Color =
|
|
47
|
+
floatingIconColor: Color? = nil,
|
|
43
48
|
size: InputSize = .small,
|
|
44
49
|
hintText: String = "",
|
|
45
50
|
error: String = "",
|
|
@@ -48,9 +53,9 @@ public struct Input: View {
|
|
|
48
53
|
readOnly: Bool = false,
|
|
49
54
|
secureTextEntry: Bool = false,
|
|
50
55
|
rightIcon: String = "",
|
|
51
|
-
rightIconColor: Color =
|
|
56
|
+
rightIconColor: Color? = nil,
|
|
52
57
|
leadingIcon: String = "",
|
|
53
|
-
leadingIconColor: Color =
|
|
58
|
+
leadingIconColor: Color? = nil,
|
|
54
59
|
loading: Bool = false,
|
|
55
60
|
required: Bool = false,
|
|
56
61
|
maxLength: Int? = nil,
|
|
@@ -65,6 +70,7 @@ public struct Input: View {
|
|
|
65
70
|
self._text = text
|
|
66
71
|
self.placeholder = placeholder
|
|
67
72
|
self.floatingValue = floatingValue
|
|
73
|
+
self.floatingValueColor = floatingValueColor
|
|
68
74
|
self.floatingIcon = floatingIcon
|
|
69
75
|
self.floatingIconColor = floatingIconColor
|
|
70
76
|
self.size = size
|
|
@@ -95,8 +101,13 @@ public struct Input: View {
|
|
|
95
101
|
let textBinding = Binding<String>(
|
|
96
102
|
get: { self.text },
|
|
97
103
|
set: { newValue in
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
// Trim atomically before publishing, mirroring Kotlin's `onValueChange`
|
|
105
|
+
// (`newText.take(maxLength)` before the state ever updates) — avoids a
|
|
106
|
+
// render with the untrimmed value that a separate `.onChange` correction
|
|
107
|
+
// would otherwise briefly show.
|
|
108
|
+
let limited = limitText(newValue)
|
|
109
|
+
self.text = limited
|
|
110
|
+
self.onChangeText?(limited)
|
|
100
111
|
}
|
|
101
112
|
)
|
|
102
113
|
|
|
@@ -107,15 +118,26 @@ public struct Input: View {
|
|
|
107
118
|
HStack(spacing: Spacing.XS) {
|
|
108
119
|
MomoText(floatingValue, typography: .labelSMedium, color: getFloatingColor())
|
|
109
120
|
if required {
|
|
110
|
-
MomoText("*", typography: .labelSMedium, color:
|
|
121
|
+
MomoText("*", typography: .labelSMedium, color: theme.colors.error.primary)
|
|
111
122
|
}
|
|
112
123
|
if !floatingIcon.isEmpty {
|
|
113
124
|
Icon(source: floatingIcon, size: 16, color: getFloatingIconColor())
|
|
114
125
|
}
|
|
115
126
|
}
|
|
116
127
|
.padding(.horizontal, Spacing.S)
|
|
117
|
-
.background(
|
|
118
|
-
|
|
128
|
+
.background(
|
|
129
|
+
GeometryReader { geo in
|
|
130
|
+
Color.clear.onAppear { floatingLabelHeight = geo.size.height }
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
.background(theme.colors.background.surface)
|
|
134
|
+
// Kotlin centers the label within the (box-height-tall) decorationBox
|
|
135
|
+
// by default, then applies `offsetY = -size.values.height / 2` — net
|
|
136
|
+
// effect: the label ends up centered exactly on the box's top border
|
|
137
|
+
// (spanning -labelHeight/2 ... +labelHeight/2 around y=0). Our ZStack
|
|
138
|
+
// anchors top-leading instead, so reproducing that requires offsetting
|
|
139
|
+
// by half the label's OWN measured height, not half the box height.
|
|
140
|
+
.offset(x: Spacing.S, y: -floatingLabelHeight / 2)
|
|
119
141
|
.zIndex(10)
|
|
120
142
|
}
|
|
121
143
|
|
|
@@ -123,7 +145,7 @@ public struct Input: View {
|
|
|
123
145
|
HStack(alignment: .center, spacing: 0) {
|
|
124
146
|
// Leading icon
|
|
125
147
|
if !leadingIcon.isEmpty {
|
|
126
|
-
Icon(source: leadingIcon, size: size == .small ? 24 : 32, color:
|
|
148
|
+
Icon(source: leadingIcon, size: size == .small ? 24 : 32, color: getLeadingIconColor())
|
|
127
149
|
.padding(.trailing, Spacing.M)
|
|
128
150
|
}
|
|
129
151
|
|
|
@@ -144,8 +166,10 @@ public struct Input: View {
|
|
|
144
166
|
fontSize: scaleSize(14),
|
|
145
167
|
fontWeight: fontWeight == .bold ? .bold : .regular,
|
|
146
168
|
textColor: UIColor(getTextColor()),
|
|
169
|
+
cursorColor: UIColor(theme.colors.primary),
|
|
147
170
|
isDisabled: disabled || readOnly,
|
|
148
171
|
maxLength: maxLength,
|
|
172
|
+
autofocus: autofocus,
|
|
149
173
|
onFocusChange: { focused in
|
|
150
174
|
handleFocusChange(focused)
|
|
151
175
|
},
|
|
@@ -160,12 +184,10 @@ public struct Input: View {
|
|
|
160
184
|
.ignoreBoldTextSetting()
|
|
161
185
|
.foregroundColor(getTextColor())
|
|
162
186
|
.disabled(disabled || readOnly)
|
|
163
|
-
.
|
|
164
|
-
.
|
|
165
|
-
|
|
166
|
-
if
|
|
167
|
-
text = limited
|
|
168
|
-
}
|
|
187
|
+
.applyCursorColor(theme.colors.primary)
|
|
188
|
+
.focused($isFieldFocused)
|
|
189
|
+
.onAppear {
|
|
190
|
+
if autofocus { isFieldFocused = true }
|
|
169
191
|
}
|
|
170
192
|
}
|
|
171
193
|
}
|
|
@@ -176,7 +198,7 @@ public struct Input: View {
|
|
|
176
198
|
text = ""
|
|
177
199
|
onChangeText?("")
|
|
178
200
|
}) {
|
|
179
|
-
Icon(source: "24_navigation_close_circle_full", size: 16, color:
|
|
201
|
+
Icon(source: "24_navigation_close_circle_full", size: 16, color: theme.colors.text.hint)
|
|
180
202
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
181
203
|
}
|
|
182
204
|
}
|
|
@@ -195,14 +217,14 @@ public struct Input: View {
|
|
|
195
217
|
Icon(
|
|
196
218
|
source: isPasswordHidden ? "24_security_eye_off" : "24_security_eye_open",
|
|
197
219
|
size: 24,
|
|
198
|
-
color:
|
|
220
|
+
color: getRightIconColor()
|
|
199
221
|
)
|
|
200
222
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_show_hide")
|
|
201
223
|
}
|
|
202
224
|
}
|
|
203
225
|
} else if !rightIcon.isEmpty {
|
|
204
226
|
SwiftUI.Button(action: { onRightIconPressed?() }) {
|
|
205
|
-
Icon(source: rightIcon, size: 24, color:
|
|
227
|
+
Icon(source: rightIcon, size: 24, color: getRightIconColor())
|
|
206
228
|
.padding(.leading, Spacing.S)
|
|
207
229
|
}
|
|
208
230
|
}
|
|
@@ -211,7 +233,7 @@ public struct Input: View {
|
|
|
211
233
|
.frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
|
|
212
234
|
.background(
|
|
213
235
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
214
|
-
.fill(
|
|
236
|
+
.fill(theme.colors.background.surface)
|
|
215
237
|
)
|
|
216
238
|
.overlay(
|
|
217
239
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
@@ -260,31 +282,39 @@ public struct Input: View {
|
|
|
260
282
|
|
|
261
283
|
private func borderColor() -> Color {
|
|
262
284
|
if disabled {
|
|
263
|
-
return
|
|
285
|
+
return theme.colors.border.disable
|
|
264
286
|
}
|
|
265
287
|
if !error.isEmpty {
|
|
266
|
-
return
|
|
288
|
+
return theme.colors.error.primary
|
|
267
289
|
}
|
|
268
290
|
if isFocused {
|
|
269
|
-
return
|
|
291
|
+
return theme.colors.primary
|
|
270
292
|
}
|
|
271
|
-
return
|
|
293
|
+
return theme.colors.border.default
|
|
272
294
|
}
|
|
273
295
|
|
|
274
296
|
private func getTextColor() -> Color {
|
|
275
|
-
return disabled ?
|
|
297
|
+
return disabled ? theme.colors.text.disable : theme.colors.text.default
|
|
276
298
|
}
|
|
277
299
|
|
|
278
300
|
private func getPlaceholderColor() -> Color {
|
|
279
|
-
return disabled ?
|
|
301
|
+
return disabled ? theme.colors.text.disable : theme.colors.text.hint
|
|
280
302
|
}
|
|
281
303
|
|
|
282
304
|
private func getFloatingColor() -> Color {
|
|
283
|
-
return disabled ?
|
|
305
|
+
return disabled ? theme.colors.text.disable : (floatingValueColor ?? theme.colors.text.hint)
|
|
284
306
|
}
|
|
285
307
|
|
|
286
308
|
private func getFloatingIconColor() -> Color {
|
|
287
|
-
return disabled ?
|
|
309
|
+
return disabled ? theme.colors.text.disable : (floatingIconColor ?? theme.colors.text.default)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private func getLeadingIconColor() -> Color {
|
|
313
|
+
return disabled ? theme.colors.text.disable : (leadingIconColor ?? theme.colors.text.hint)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private func getRightIconColor() -> Color {
|
|
317
|
+
return disabled ? theme.colors.text.disable : (rightIconColor ?? theme.colors.text.default)
|
|
288
318
|
}
|
|
289
319
|
}
|
|
290
320
|
|
|
@@ -296,8 +326,10 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
296
326
|
var fontSize: CGFloat
|
|
297
327
|
var fontWeight: UIFont.Weight
|
|
298
328
|
var textColor: UIColor
|
|
329
|
+
var cursorColor: UIColor
|
|
299
330
|
var isDisabled: Bool
|
|
300
331
|
var maxLength: Int?
|
|
332
|
+
var autofocus: Bool = false
|
|
301
333
|
var onFocusChange: (Bool) -> Void
|
|
302
334
|
var onChangeText: ((String) -> Void)?
|
|
303
335
|
|
|
@@ -316,12 +348,17 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
316
348
|
textField.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
|
317
349
|
textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
|
318
350
|
textField.text = text
|
|
319
|
-
textField.tintColor =
|
|
351
|
+
textField.tintColor = cursorColor
|
|
320
352
|
textField.addTarget(
|
|
321
353
|
context.coordinator,
|
|
322
354
|
action: #selector(Coordinator.textFieldDidChange(_:)),
|
|
323
355
|
for: .editingChanged
|
|
324
356
|
)
|
|
357
|
+
if autofocus {
|
|
358
|
+
DispatchQueue.main.async {
|
|
359
|
+
textField.becomeFirstResponder()
|
|
360
|
+
}
|
|
361
|
+
}
|
|
325
362
|
return textField
|
|
326
363
|
}
|
|
327
364
|
|
|
@@ -331,6 +368,8 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
331
368
|
textField.text = text
|
|
332
369
|
}
|
|
333
370
|
textField.isEnabled = !isDisabled
|
|
371
|
+
textField.textColor = textColor
|
|
372
|
+
textField.tintColor = cursorColor
|
|
334
373
|
if textField.keyboardType != keyboardType {
|
|
335
374
|
textField.keyboardType = keyboardType
|
|
336
375
|
textField.reloadInputViews()
|
|
@@ -401,9 +440,9 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
401
440
|
|
|
402
441
|
// MARK: - Helper Extension
|
|
403
442
|
private extension View {
|
|
404
|
-
func
|
|
443
|
+
func applyCursorColor(_ color: Color) -> some View {
|
|
405
444
|
if #available(iOS 15.0, *) {
|
|
406
|
-
return self.tint(
|
|
445
|
+
return self.tint(color)
|
|
407
446
|
} else {
|
|
408
447
|
return self
|
|
409
448
|
}
|
|
@@ -7,23 +7,27 @@
|
|
|
7
7
|
|
|
8
8
|
import SwiftUI
|
|
9
9
|
public struct InputPhoneNumber: View {
|
|
10
|
+
@Environment(\.appTheme) private var theme
|
|
10
11
|
@Binding public var text: String
|
|
11
12
|
|
|
12
13
|
public var placeholder: String
|
|
13
14
|
public var size: InputSize
|
|
14
15
|
public var hintText: String
|
|
15
16
|
public var error: String
|
|
17
|
+
public var errorSpacing: Bool
|
|
16
18
|
public var loading: Bool
|
|
19
|
+
public var required: Bool
|
|
17
20
|
public var rightIcon: String
|
|
18
|
-
public var rightIconColor: Color
|
|
21
|
+
public var rightIconColor: Color?
|
|
19
22
|
public var autofocus: Bool
|
|
20
23
|
public var onChangeText: ((String) -> Void)?
|
|
21
24
|
public var onFocus: (() -> Void)?
|
|
22
25
|
public var onBlur: (() -> Void)?
|
|
23
26
|
public var onRightIconPressed: (() -> Void)?
|
|
24
27
|
public var accessibilityLabel: String?
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
@State private var isFocused: Bool = false
|
|
30
|
+
@FocusState private var isFieldFocused: Bool
|
|
27
31
|
|
|
28
32
|
public init(
|
|
29
33
|
text: Binding<String>,
|
|
@@ -31,10 +35,11 @@ public struct InputPhoneNumber: View {
|
|
|
31
35
|
size: InputSize = .small,
|
|
32
36
|
hintText: String = "",
|
|
33
37
|
error: String = "",
|
|
38
|
+
errorSpacing: Bool = false,
|
|
34
39
|
loading: Bool = false,
|
|
35
40
|
required: Bool = false,
|
|
36
41
|
rightIcon: String = "",
|
|
37
|
-
rightIconColor: Color =
|
|
42
|
+
rightIconColor: Color? = nil,
|
|
38
43
|
autofocus: Bool = false,
|
|
39
44
|
onChangeText: ((String) -> Void)? = nil,
|
|
40
45
|
onFocus: (() -> Void)? = nil,
|
|
@@ -47,7 +52,9 @@ public struct InputPhoneNumber: View {
|
|
|
47
52
|
self.size = size
|
|
48
53
|
self.hintText = hintText
|
|
49
54
|
self.error = error
|
|
55
|
+
self.errorSpacing = errorSpacing
|
|
50
56
|
self.loading = loading
|
|
57
|
+
self.required = required
|
|
51
58
|
self.rightIcon = rightIcon
|
|
52
59
|
self.rightIconColor = rightIconColor
|
|
53
60
|
self.autofocus = autofocus
|
|
@@ -76,28 +83,36 @@ public struct InputPhoneNumber: View {
|
|
|
76
83
|
.padding(.trailing, Spacing.XS)
|
|
77
84
|
|
|
78
85
|
MomoText("+84", typography: size == .small ? .headerSSemibold : .headerMBold)
|
|
79
|
-
.foregroundColor(
|
|
86
|
+
.foregroundColor(theme.colors.text.default)
|
|
80
87
|
|
|
81
88
|
Rectangle()
|
|
82
|
-
.fill(
|
|
89
|
+
.fill(theme.colors.border.default)
|
|
83
90
|
.frame(width: 1, height: size == .small ? 24 : 32)
|
|
84
91
|
.padding(.horizontal, Spacing.M)
|
|
85
92
|
|
|
86
93
|
// Text input
|
|
87
94
|
ZStack(alignment: .leading) {
|
|
88
95
|
if text.isEmpty {
|
|
89
|
-
MomoText(
|
|
96
|
+
MomoText(
|
|
97
|
+
placeholder + (required ? " *" : ""),
|
|
98
|
+
typography: size == .small ? .headerSSemibold : .headerMBold,
|
|
99
|
+
color: theme.colors.text.hint
|
|
100
|
+
)
|
|
90
101
|
}
|
|
91
|
-
|
|
102
|
+
|
|
92
103
|
TextField("", text: textBinding, onEditingChanged: { focused in
|
|
93
104
|
handleFocusChange(focused)
|
|
94
105
|
})
|
|
95
106
|
.keyboardType(.numberPad)
|
|
96
107
|
.font(size == .small ? .header_s_semibold : .header_m_bold)
|
|
97
108
|
.ignoreBoldTextSetting()
|
|
98
|
-
.foregroundColor(
|
|
99
|
-
.
|
|
109
|
+
.foregroundColor(theme.colors.text.default)
|
|
110
|
+
.applyCursorColor(theme.colors.primary)
|
|
100
111
|
.lineLimit(1)
|
|
112
|
+
.focused($isFieldFocused)
|
|
113
|
+
.onAppear {
|
|
114
|
+
if autofocus { isFieldFocused = true }
|
|
115
|
+
}
|
|
101
116
|
.accessibility(identifier: accessibilityLabel ?? "")
|
|
102
117
|
.accessibilityValue(textBinding.wrappedValue.isEmpty ? placeholder : textBinding.wrappedValue)
|
|
103
118
|
}
|
|
@@ -108,7 +123,7 @@ public struct InputPhoneNumber: View {
|
|
|
108
123
|
text = ""
|
|
109
124
|
onChangeText?("")
|
|
110
125
|
}) {
|
|
111
|
-
Icon(source: "24_navigation_close_circle_full", size: 16, color:
|
|
126
|
+
Icon(source: "24_navigation_close_circle_full", size: 16, color: theme.colors.text.hint)
|
|
112
127
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
113
128
|
}
|
|
114
129
|
}
|
|
@@ -122,7 +137,7 @@ public struct InputPhoneNumber: View {
|
|
|
122
137
|
// ✅ Right icon
|
|
123
138
|
if !rightIcon.isEmpty {
|
|
124
139
|
SwiftUI.Button(action: { onRightIconPressed?() }) {
|
|
125
|
-
Icon(source: rightIcon, size: 24, color: rightIconColor)
|
|
140
|
+
Icon(source: rightIcon, size: 24, color: rightIconColor ?? theme.colors.text.default)
|
|
126
141
|
.padding(.leading, Spacing.S)
|
|
127
142
|
}
|
|
128
143
|
}
|
|
@@ -131,7 +146,7 @@ public struct InputPhoneNumber: View {
|
|
|
131
146
|
.frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
|
|
132
147
|
.background(
|
|
133
148
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
134
|
-
.fill(
|
|
149
|
+
.fill(theme.colors.background.surface)
|
|
135
150
|
)
|
|
136
151
|
.overlay(
|
|
137
152
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
@@ -141,7 +156,7 @@ public struct InputPhoneNumber: View {
|
|
|
141
156
|
// Error or hint
|
|
142
157
|
ErrorView(
|
|
143
158
|
errorMessage: error,
|
|
144
|
-
errorSpacing:
|
|
159
|
+
errorSpacing: errorSpacing,
|
|
145
160
|
hintText: hintText
|
|
146
161
|
)
|
|
147
162
|
}
|
|
@@ -159,21 +174,18 @@ public struct InputPhoneNumber: View {
|
|
|
159
174
|
}
|
|
160
175
|
|
|
161
176
|
private func borderColor() -> Color {
|
|
162
|
-
if !error.isEmpty { return
|
|
163
|
-
if isFocused { return
|
|
164
|
-
return
|
|
177
|
+
if !error.isEmpty { return theme.colors.error.primary }
|
|
178
|
+
if isFocused { return theme.colors.primary }
|
|
179
|
+
return theme.colors.border.default
|
|
165
180
|
}
|
|
166
181
|
}
|
|
167
182
|
|
|
168
183
|
private extension View {
|
|
169
|
-
func
|
|
184
|
+
func applyCursorColor(_ color: Color) -> some View {
|
|
170
185
|
if #available(iOS 15.0, *) {
|
|
171
|
-
|
|
172
|
-
return self.tint(Colors.primary)
|
|
186
|
+
return self.tint(color)
|
|
173
187
|
} else {
|
|
174
|
-
// iOS 13–14: return unchanged (no tint support)
|
|
175
188
|
return self
|
|
176
189
|
}
|
|
177
190
|
}
|
|
178
191
|
}
|
|
179
|
-
|