@momo-kits/native-kits 0.152.4-beta.3 → 0.152.5
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/package.json +7 -6
- package/shared/build.gradle.kts +74 -0
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -114
- package/LICENSE +0 -20
- package/README.md +0 -7
- package/build.gradle.kts +0 -32
- package/compose/MoMoComposeKits.podspec +0 -54
- package/compose/build.gradle.kts +0 -149
- package/compose/src/androidMain/AndroidManifest.xml +0 -2
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -105
- package/compose/src/commonMain/composeResources/files/lottie_circle_loader.json +0 -1
- package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
- package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -715
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -214
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -236
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -77
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -27
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -334
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -345
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -90
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -131
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -143
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -179
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -384
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -160
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -234
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -223
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -236
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -228
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -50
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -34
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -85
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -95
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -64
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -89
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -84
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -208
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -172
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -199
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -237
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -191
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -258
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -94
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -159
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScaleSizeScope.kt +0 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -459
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -169
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -216
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -180
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -251
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -31
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -385
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -38
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -88
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -144
- package/gradle.properties +0 -19
- package/gradlew +0 -240
- package/gradlew.bat +0 -91
- package/ios/Application/ApplicationEnvironment.swift +0 -50
- package/ios/Application/Components.swift +0 -263
- package/ios/Application/ComposeApi.swift +0 -22
- package/ios/Application/FloatingButton.swift +0 -172
- package/ios/Application/HeaderRight.swift +0 -271
- package/ios/Application/Screen.swift +0 -249
- package/ios/Badge/BadgeDot.swift +0 -31
- package/ios/Button/Button.swift +0 -211
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +0 -126
- package/ios/Checkbox/Checkbox.swift +0 -81
- package/ios/Chip/Chip.swift +0 -96
- package/ios/Colors+Radius+Spacing/Colors.swift +0 -172
- package/ios/Colors+Radius+Spacing/Radius.swift +0 -22
- package/ios/Colors+Radius+Spacing/Spacing.swift +0 -12
- package/ios/Extensions/Color++.swift +0 -25
- package/ios/Icon/Icon.swift +0 -51
- package/ios/Image/Image.swift +0 -70
- package/ios/Input/Input.swift +0 -207
- package/ios/Input/InputPhoneNumber.swift +0 -176
- package/ios/Input/InputSearch.swift +0 -238
- package/ios/Input/InputTextArea.swift +0 -242
- package/ios/Lottie/LottieView.swift +0 -86
- package/ios/OTPKeyboard/KeyboardButton.swift +0 -41
- package/ios/OTPKeyboard/OTPKeyboard.swift +0 -145
- package/ios/Popup/PopupDisplay.swift +0 -284
- package/ios/Popup/PopupInput.swift +0 -96
- package/ios/Popup/PopupPromotion.swift +0 -73
- package/ios/PopupView/FullscreenPopup.swift +0 -251
- package/ios/PopupView/Modifiers.swift +0 -158
- package/ios/PopupView/PopupView.swift +0 -289
- package/ios/PopupView/Utils++.swift +0 -281
- package/ios/ScrollIndicator/ScrollIndicator.swift +0 -110
- package/ios/Swipeable/SwipeCell.swift +0 -278
- package/ios/Swipeable/SwipeCellModel.swift +0 -86
- package/ios/Switch/Switch.swift +0 -44
- package/ios/Template/Logo/Logo.swift +0 -75
- package/ios/Template/TrustBanner/TrustBanner.swift +0 -120
- package/ios/Theme.md +0 -18
- package/ios/Typography/Text.swift +0 -140
- package/ios/Typography/Typography.swift +0 -95
- package/ios/native-kits.podspec +0 -18
- package/settings.gradle.kts +0 -25
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
import Foundation
|
|
3
|
-
|
|
4
|
-
public enum Radius {
|
|
5
|
-
public static let XXS: CGFloat = 2
|
|
6
|
-
public static let XS: CGFloat = 4
|
|
7
|
-
public static let S: CGFloat = 8
|
|
8
|
-
public static let M: CGFloat = 12
|
|
9
|
-
public static let L: CGFloat = 16
|
|
10
|
-
public static let XL: CGFloat = 24
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public struct RoundedCorner: Shape {
|
|
14
|
-
|
|
15
|
-
var radius: CGFloat = .infinity
|
|
16
|
-
var corners: UIRectCorner = .allCorners
|
|
17
|
-
|
|
18
|
-
public func path(in rect: CGRect) -> Path {
|
|
19
|
-
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
|
20
|
-
return Path(path.cgPath)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
public enum Spacing {
|
|
4
|
-
public static let XXS: CGFloat = 2
|
|
5
|
-
public static let XS: CGFloat = 4
|
|
6
|
-
public static let S: CGFloat = 8
|
|
7
|
-
public static let M: CGFloat = 12
|
|
8
|
-
public static let L: CGFloat = 16
|
|
9
|
-
public static let XL: CGFloat = 24
|
|
10
|
-
public static let XXL: CGFloat = 32
|
|
11
|
-
public static let XXXL: CGFloat = 48
|
|
12
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
public extension Color {
|
|
4
|
-
init(hex: UInt, alpha: Double = 1) {
|
|
5
|
-
self.init(
|
|
6
|
-
.sRGB,
|
|
7
|
-
red: Double((hex >> 16) & 0xFF) / 255,
|
|
8
|
-
green: Double((hex >> 08) & 0xFF) / 255,
|
|
9
|
-
blue: Double((hex >> 00) & 0xFF) / 255,
|
|
10
|
-
opacity: alpha
|
|
11
|
-
)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
init(hex: String) {
|
|
15
|
-
let scanner = Scanner(string: hex)
|
|
16
|
-
var rgbValue: UInt64 = 0
|
|
17
|
-
scanner.scanHexInt64(&rgbValue)
|
|
18
|
-
|
|
19
|
-
let r = (rgbValue & 0xff0000) >> 16
|
|
20
|
-
let g = (rgbValue & 0xff00) >> 8
|
|
21
|
-
let b = rgbValue & 0xff
|
|
22
|
-
|
|
23
|
-
self.init(red: Double(r) / 0xff, green: Double(g) / 0xff, blue: Double(b) / 0xff)
|
|
24
|
-
}
|
|
25
|
-
}
|
package/ios/Icon/Icon.swift
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
struct IconSource: Codable {
|
|
4
|
-
let uri: String
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
func loadIconSources() -> [String: IconSource] {
|
|
8
|
-
guard let url = Bundle.main.url(forResource: "icon", withExtension: "json") else {
|
|
9
|
-
print("Error: icon.json not found")
|
|
10
|
-
return [:]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
do {
|
|
14
|
-
let data = try Data(contentsOf: url)
|
|
15
|
-
let decoded = try JSONDecoder().decode([String: IconSource].self, from: data)
|
|
16
|
-
return decoded
|
|
17
|
-
} catch {
|
|
18
|
-
print("Error decoding icon.json: \(error)")
|
|
19
|
-
return [:]
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Load the JSON data into a global variable
|
|
24
|
-
let iconSources: [String: IconSource] = loadIconSources()
|
|
25
|
-
|
|
26
|
-
// Icon ViewModel
|
|
27
|
-
public struct Icon: View {
|
|
28
|
-
var source: String
|
|
29
|
-
var size: CGFloat
|
|
30
|
-
var color: Color?
|
|
31
|
-
var accessibilityLabel: String?
|
|
32
|
-
|
|
33
|
-
public init(
|
|
34
|
-
source: String,
|
|
35
|
-
size: CGFloat = 24,
|
|
36
|
-
color: Color? = nil,
|
|
37
|
-
accessibilityLabel: String? = nil
|
|
38
|
-
) {
|
|
39
|
-
self.source = source
|
|
40
|
-
self.size = size
|
|
41
|
-
self.color = color
|
|
42
|
-
self.accessibilityLabel = accessibilityLabel
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public var body: some View {
|
|
46
|
-
if let uri = iconSources[source]?.uri {
|
|
47
|
-
ImageView(uri, color: color).frame(width: size, height: size)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
package/ios/Image/Image.swift
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
import SDWebImageSwiftUI
|
|
5
|
-
import SkeletonUI
|
|
6
|
-
import SwiftUI
|
|
7
|
-
|
|
8
|
-
public struct ImageView: View {
|
|
9
|
-
// MARK: Lifecycle
|
|
10
|
-
|
|
11
|
-
public init(_ url: String, aspectRatio: CGFloat? = nil, contentMode: ContentMode = ContentMode.fit, placeholder: AnyView? = nil, color: Color? = nil) {
|
|
12
|
-
self.url = url
|
|
13
|
-
self.aspectRatio = aspectRatio
|
|
14
|
-
self.contentMode = contentMode
|
|
15
|
-
self.placeholder = placeholder
|
|
16
|
-
self.color = color
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// MARK: Public
|
|
20
|
-
|
|
21
|
-
public var body: some View {
|
|
22
|
-
return WebImage(url: URL(string: url), isAnimating: .constant(true))
|
|
23
|
-
.onFailure { _ in
|
|
24
|
-
error = true
|
|
25
|
-
}
|
|
26
|
-
.onSuccess { _, _, _ in
|
|
27
|
-
error = false
|
|
28
|
-
}
|
|
29
|
-
.resizable()
|
|
30
|
-
.renderingMode(color != nil ? .template : .original)
|
|
31
|
-
.placeholder {
|
|
32
|
-
VStack(alignment: .center, content: {
|
|
33
|
-
if error {
|
|
34
|
-
Image(systemName: "photo.badge.exclamationmark").frame(width: 24, height: 24)
|
|
35
|
-
} else if placeholder != nil {
|
|
36
|
-
placeholder
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
40
|
-
.skeleton(with: !error && placeholder == nil)
|
|
41
|
-
.shape(type: .rectangle)
|
|
42
|
-
}
|
|
43
|
-
.scaledToFit()
|
|
44
|
-
.transition(.fade)
|
|
45
|
-
.aspectRatio(aspectRatio, contentMode: contentMode)
|
|
46
|
-
.foregroundColor(color)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// MARK: Internal
|
|
50
|
-
|
|
51
|
-
var aspectRatio: CGFloat?
|
|
52
|
-
var contentMode: ContentMode
|
|
53
|
-
var placeholder: AnyView?
|
|
54
|
-
var color: Color?
|
|
55
|
-
|
|
56
|
-
@State var error: Bool = false
|
|
57
|
-
var url: String
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private struct ColorMultiplyModifier: ViewModifier {
|
|
61
|
-
let color: Color?
|
|
62
|
-
|
|
63
|
-
func body(content: Content) -> some View {
|
|
64
|
-
if let color {
|
|
65
|
-
content.colorMultiply(color)
|
|
66
|
-
} else {
|
|
67
|
-
content
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
package/ios/Input/Input.swift
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import SwiftUI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
fileprivate struct FloatingComponent: View {
|
|
6
|
-
var floatingValue: String
|
|
7
|
-
var floatingIcon: AnyView?
|
|
8
|
-
|
|
9
|
-
public init (_ floatingValue: String = "", floatingIcon: AnyView? = nil){
|
|
10
|
-
self.floatingValue = floatingValue
|
|
11
|
-
self.floatingIcon = floatingIcon
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public var body: some View {
|
|
15
|
-
return HStack {
|
|
16
|
-
Text(floatingValue)
|
|
17
|
-
.font(.paragraph)
|
|
18
|
-
.foregroundColor(Colors.black09)
|
|
19
|
-
.font(.system(size: 12))
|
|
20
|
-
.padding(.leading, 8)
|
|
21
|
-
.padding(.trailing, 8)
|
|
22
|
-
floatingIcon
|
|
23
|
-
}
|
|
24
|
-
.background(Colors.black01)
|
|
25
|
-
.offset(x: 16, y:-8)
|
|
26
|
-
.zIndex(10)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
struct DotTextField: View{
|
|
31
|
-
@Binding var value: String
|
|
32
|
-
@State var isHide: Bool = true
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
func onToggle(){
|
|
36
|
-
isHide.toggle()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public var body: some View {
|
|
40
|
-
return HStack {
|
|
41
|
-
if (isHide){
|
|
42
|
-
SecureField("", text: $value)
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
TextField("", text: $value)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
SwiftButton(action: onToggle){
|
|
49
|
-
Image(systemName: isHide ? "eye.slash" : "eye")
|
|
50
|
-
.foregroundColor(Colors.text)
|
|
51
|
-
.frame(width: 16, height: 16)
|
|
52
|
-
.padding(.leading, -4)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public struct Input: View {
|
|
62
|
-
@Binding var value: String
|
|
63
|
-
@State var focused: Bool = false
|
|
64
|
-
|
|
65
|
-
var placeholder: String
|
|
66
|
-
var floatingValue: String
|
|
67
|
-
var errorMessage: String
|
|
68
|
-
var isSecure: Bool
|
|
69
|
-
var keyboardType: UIKeyboardType
|
|
70
|
-
var floatingIcon: AnyView?
|
|
71
|
-
var rightIcon: AnyView?
|
|
72
|
-
var onChange: ((String) -> Void)?
|
|
73
|
-
var onBlur: (() -> Void)?
|
|
74
|
-
var floatingIconURL: String?
|
|
75
|
-
var floatingIconColor: Color?
|
|
76
|
-
var size: InputSize
|
|
77
|
-
var fontWeight: InputFontWeight
|
|
78
|
-
var disabled: Bool
|
|
79
|
-
var leadingIcon: String?
|
|
80
|
-
var leadingIconColor: Color?
|
|
81
|
-
var loading: Bool
|
|
82
|
-
var required: Bool
|
|
83
|
-
var hintText: String?
|
|
84
|
-
|
|
85
|
-
func onCancel(){
|
|
86
|
-
self.value.removeAll()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public init(_ value: Binding<String>, placeholder: String = "", floatingValue: String = "", multilines: Bool = false, errorMessage: String = "", isSecure: Bool = false, keyboardType: UIKeyboardType = .default, floatingIcon: AnyView? = nil, rightIcon: AnyView? = nil, onChange: ((String)->Void)? = nil, onBlur: (()->Void)? = nil, floatingIconURL: String? = nil, floatingIconColor: Color? = Colors.pink03, size: InputSize = .small, fontWeight: InputFontWeight = .regular, disabled: Bool = false, leadingIcon: String? = nil, leadingIconColor: Color? = Colors.pink03, loading: Bool = false, required: Bool = false, hintText: String? = nil){
|
|
90
|
-
self.placeholder = placeholder
|
|
91
|
-
self.floatingValue = floatingValue
|
|
92
|
-
self.errorMessage = errorMessage
|
|
93
|
-
self.isSecure = isSecure
|
|
94
|
-
self._value = value
|
|
95
|
-
self.keyboardType = keyboardType
|
|
96
|
-
self.rightIcon = rightIcon
|
|
97
|
-
self.floatingIcon = floatingIcon
|
|
98
|
-
self.onChange = onChange
|
|
99
|
-
self.floatingIconURL = floatingIconURL
|
|
100
|
-
self.floatingIconColor = floatingIconColor
|
|
101
|
-
self.size = size
|
|
102
|
-
self.fontWeight = fontWeight
|
|
103
|
-
self.disabled = disabled
|
|
104
|
-
self.leadingIcon = leadingIcon
|
|
105
|
-
self.leadingIconColor = leadingIconColor
|
|
106
|
-
self.loading = loading
|
|
107
|
-
self.required = required
|
|
108
|
-
self.hintText = hintText
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
func onChangeText(value: String){
|
|
112
|
-
onChange?(value)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
public var body: some View {
|
|
116
|
-
VStack(alignment: .leading, spacing: 4) {
|
|
117
|
-
ZStack(alignment: .topLeading) {
|
|
118
|
-
HStack(alignment: .center) {
|
|
119
|
-
if let leadingIcon = leadingIcon {
|
|
120
|
-
Icon(source: leadingIcon, size: 16, color: leadingIconColor)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if !isSecure {
|
|
124
|
-
TextField("", text: $value, onEditingChanged: { isChange in
|
|
125
|
-
self.focused = isChange
|
|
126
|
-
})
|
|
127
|
-
.disabled(disabled)
|
|
128
|
-
.font(fontWeight == .bold ? .headline : .body)
|
|
129
|
-
} else {
|
|
130
|
-
DotTextField(value: $value)
|
|
131
|
-
.disabled(disabled)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if loading {
|
|
135
|
-
ActivityIndicator(isAnimating: .constant(true), style: .medium)
|
|
136
|
-
.frame(width: 20, height: 20)
|
|
137
|
-
} else if !value.isEmpty {
|
|
138
|
-
SwiftButton(action: onCancel){
|
|
139
|
-
Image(systemName: "x.circle.fill")
|
|
140
|
-
.foregroundColor(Colors.text)
|
|
141
|
-
.frame(width: 16, height: 16)
|
|
142
|
-
.padding(.leading, -4)
|
|
143
|
-
.padding(.trailing, 8)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
rightIcon
|
|
148
|
-
}
|
|
149
|
-
.padding(.horizontal, 12)
|
|
150
|
-
.frame(height: size == .small ? 40 : 48)
|
|
151
|
-
.background(disabled ? Colors.black01 : Color.white)
|
|
152
|
-
.overlay(RoundedRectangle(cornerRadius: 8).stroke(focused ? Colors.pink03 : Colors.border, lineWidth: 1))
|
|
153
|
-
|
|
154
|
-
if value.isEmpty {
|
|
155
|
-
Text(placeholder + (required ? " *" : ""))
|
|
156
|
-
.foregroundColor(Colors.black09)
|
|
157
|
-
.padding(.horizontal, leadingIcon == nil ? 12 : 32)
|
|
158
|
-
.padding(.top, 12)
|
|
159
|
-
.allowsHitTesting(false)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if !floatingValue.isEmpty {
|
|
163
|
-
FloatingComponent(floatingValue, floatingIcon: floatingIconURL.map { url in
|
|
164
|
-
AnyView(
|
|
165
|
-
Icon(source: url, size: 16, color: floatingIconColor)
|
|
166
|
-
)
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if !errorMessage.isEmpty {
|
|
173
|
-
Text(errorMessage)
|
|
174
|
-
.foregroundColor(.red)
|
|
175
|
-
.font(.caption)
|
|
176
|
-
} else if let hint = hintText {
|
|
177
|
-
Text(hint)
|
|
178
|
-
.foregroundColor(Colors.black09)
|
|
179
|
-
.font(.caption)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
struct ActivityIndicator: UIViewRepresentable {
|
|
187
|
-
@Binding var isAnimating: Bool
|
|
188
|
-
let style: UIActivityIndicatorView.Style
|
|
189
|
-
|
|
190
|
-
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
|
|
191
|
-
return UIActivityIndicatorView(style: style)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
|
|
195
|
-
isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
public enum InputSize {
|
|
200
|
-
case small
|
|
201
|
-
case large
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
public enum InputFontWeight {
|
|
205
|
-
case regular
|
|
206
|
-
case bold
|
|
207
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// InputPhoneNumber.swift
|
|
3
|
-
// Pods
|
|
4
|
-
//
|
|
5
|
-
// Created by sophia on 20/10/25.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
import SwiftUI
|
|
9
|
-
|
|
10
|
-
public struct InputPhoneNumber: View {
|
|
11
|
-
@Binding public var text: String
|
|
12
|
-
|
|
13
|
-
public var placeholder: String
|
|
14
|
-
public var size: InputSize
|
|
15
|
-
public var hintText: String
|
|
16
|
-
public var error: String
|
|
17
|
-
public var loading: Bool
|
|
18
|
-
public var rightIcon: String
|
|
19
|
-
public var rightIconColor: Color
|
|
20
|
-
public var onFocus: (() -> Void)?
|
|
21
|
-
public var onBlur: (() -> Void)?
|
|
22
|
-
public var onRightIconPressed: (() -> Void)?
|
|
23
|
-
|
|
24
|
-
@State private var isFocused: Bool = false
|
|
25
|
-
|
|
26
|
-
public init(
|
|
27
|
-
text: Binding<String>,
|
|
28
|
-
placeholder: String = "0123456789",
|
|
29
|
-
size: InputSize = .small,
|
|
30
|
-
hintText: String = "",
|
|
31
|
-
error: String = "",
|
|
32
|
-
loading: Bool = false,
|
|
33
|
-
required: Bool = false,
|
|
34
|
-
rightIcon: String = "",
|
|
35
|
-
rightIconColor: Color = Colors.black12,
|
|
36
|
-
onFocus: (() -> Void)? = nil,
|
|
37
|
-
onBlur: (() -> Void)? = nil,
|
|
38
|
-
onRightIconPressed: (() -> Void)? = nil
|
|
39
|
-
) {
|
|
40
|
-
self._text = text
|
|
41
|
-
self.placeholder = placeholder
|
|
42
|
-
self.size = size
|
|
43
|
-
self.hintText = hintText
|
|
44
|
-
self.error = error
|
|
45
|
-
self.loading = loading
|
|
46
|
-
self.rightIcon = rightIcon
|
|
47
|
-
self.rightIconColor = rightIconColor
|
|
48
|
-
self.onFocus = onFocus
|
|
49
|
-
self.onBlur = onBlur
|
|
50
|
-
self.onRightIconPressed = onRightIconPressed
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// MARK: - Body
|
|
54
|
-
public var body: some View {
|
|
55
|
-
VStack(alignment: .leading, spacing: 4) {
|
|
56
|
-
HStack(spacing: 0) {
|
|
57
|
-
// 🇻🇳 Flag
|
|
58
|
-
ImageView("https://static.momocdn.net/app/img/icon/ic-qrcode-package/ic_vn_flag.png")
|
|
59
|
-
.frame(width: 24, height: 24)
|
|
60
|
-
.padding(.trailing, Spacing.XS)
|
|
61
|
-
|
|
62
|
-
MomoText("+84", typography: size == .small ? .headerSSemibold : .headerMBold)
|
|
63
|
-
.foregroundColor(Colors.black17)
|
|
64
|
-
|
|
65
|
-
Rectangle()
|
|
66
|
-
.fill(Colors.black04)
|
|
67
|
-
.frame(width: 1, height: size == .small ? 24 : 32)
|
|
68
|
-
.padding(.horizontal, Spacing.M)
|
|
69
|
-
|
|
70
|
-
// Text input
|
|
71
|
-
ZStack(alignment: .leading) {
|
|
72
|
-
if text.isEmpty {
|
|
73
|
-
Text(placeholder)
|
|
74
|
-
.foregroundColor(Colors.black12)
|
|
75
|
-
.font(size == .small ? .header_s_semibold : .header_m_bold)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
TextField("", text: $text, onEditingChanged: { focused in
|
|
79
|
-
handleFocusChange(focused)
|
|
80
|
-
})
|
|
81
|
-
.keyboardType(.numberPad)
|
|
82
|
-
.font(size == .small ? .header_s_semibold : .header_m_bold)
|
|
83
|
-
.foregroundColor(Colors.black17)
|
|
84
|
-
.applyPrimaryCursorColor()
|
|
85
|
-
.lineLimit(1)
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Clear button
|
|
90
|
-
if isFocused && !text.isEmpty {
|
|
91
|
-
SwiftUI.Button(action: { text = "" }) {
|
|
92
|
-
Icon(source: "24_navigation_close_circle_full", size: 16, color: Colors.black12)
|
|
93
|
-
.padding(.leading, Spacing.S)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Loading indicator
|
|
98
|
-
if loading {
|
|
99
|
-
if #available(iOS 14.0, *) {
|
|
100
|
-
ProgressView()
|
|
101
|
-
.progressViewStyle(CircularProgressViewStyle(tint: Colors.black17))
|
|
102
|
-
.frame(width: 16, height: 16)
|
|
103
|
-
.padding(.leading, Spacing.S)
|
|
104
|
-
} else {
|
|
105
|
-
Image(systemName: "clock")
|
|
106
|
-
.rotationEffect(.degrees(isFocused ? 360 : 0))
|
|
107
|
-
.animation(Animation.linear(duration: 1).repeatForever(autoreverses: false))
|
|
108
|
-
.frame(width: 16, height: 16)
|
|
109
|
-
.padding(.leading, Spacing.S)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ✅ Right icon
|
|
114
|
-
if !rightIcon.isEmpty {
|
|
115
|
-
SwiftUI.Button(action: { onRightIconPressed?() }) {
|
|
116
|
-
Icon(source: rightIcon, size: 24, color: rightIconColor)
|
|
117
|
-
.padding(.leading, Spacing.S)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
.padding(.horizontal, Spacing.M)
|
|
122
|
-
.frame(height: size == .small ? 48 : 56)
|
|
123
|
-
.overlay(
|
|
124
|
-
RoundedRectangle(cornerRadius: Radius.S)
|
|
125
|
-
.stroke(borderColor(), lineWidth: isFocused ? 1.5 : 1)
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
// Error or hint
|
|
129
|
-
if (!error.isEmpty || !hintText.isEmpty) {
|
|
130
|
-
HStack(spacing: 4) {
|
|
131
|
-
Icon(source: "ic_error", size: 16, color: errorColor())
|
|
132
|
-
MomoText(
|
|
133
|
-
error.isEmpty ? (hintText.isEmpty ? "Không thể chỉnh sửa" : hintText) : error,
|
|
134
|
-
typography: .descriptionDefaultRegular,
|
|
135
|
-
color: errorColor()
|
|
136
|
-
)
|
|
137
|
-
}
|
|
138
|
-
.padding(.top, Spacing.XS)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// MARK: - Helpers
|
|
144
|
-
|
|
145
|
-
private func handleFocusChange(_ focused: Bool) {
|
|
146
|
-
isFocused = focused
|
|
147
|
-
if focused {
|
|
148
|
-
onFocus?()
|
|
149
|
-
} else {
|
|
150
|
-
onBlur?()
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private func borderColor() -> Color {
|
|
155
|
-
if !error.isEmpty { return Colors.red03 }
|
|
156
|
-
if isFocused { return Colors.primary }
|
|
157
|
-
return Colors.black04
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private func errorColor() -> Color {
|
|
161
|
-
!error.isEmpty ? Colors.red03 : Colors.black12
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
private extension View {
|
|
166
|
-
func applyPrimaryCursorColor() -> some View {
|
|
167
|
-
if #available(iOS 15.0, *) {
|
|
168
|
-
// Modern SwiftUI: use .tint() for cursor
|
|
169
|
-
return self.tint(Colors.primary)
|
|
170
|
-
} else {
|
|
171
|
-
// iOS 13–14: return unchanged (no tint support)
|
|
172
|
-
return self
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|