@momo-kits/native-kits 0.161.1-beta.15-debug → 0.161.2-beta.1
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/ios/Application/ApplicationEnvironment.swift +2 -6
- package/ios/Input/Input.swift +50 -21
- package/ios/Input/InputPhoneNumber.swift +17 -17
- package/ios/StatusBarTap/StatusBarTap.h +13 -0
- package/ios/StatusBarTap/StatusBarTap.m +75 -0
- package/ios/Typography/Text.swift +19 -14
- package/ios/Typography/Typography.swift +22 -1
- package/ios/native-kits.podspec +2 -1
- package/package.json +1 -1
- package/build.gradle.kts +0 -11
- package/compose/build.gradle.kts +0 -180
- package/compose/build.gradle.kts.backup +0 -180
- package/compose/compose.podspec +0 -47
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -116
- 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/Context.kt +0 -115
- 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 -305
- 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 -720
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -121
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -402
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -85
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -340
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -194
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -123
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -94
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -136
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -224
- 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 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -148
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -188
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -116
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -448
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -172
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -255
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -231
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -233
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -254
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -241
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -92
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -352
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -103
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -70
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -96
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -348
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -256
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -494
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -131
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -215
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -96
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -531
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -92
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -130
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -214
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -590
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -177
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -192
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -205
- 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 -239
- 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 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -270
- 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 -57
- 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/DeprecatedModifier.kt +0 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -50
- 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 -253
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -133
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -99
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -168
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -333
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -552
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -161
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -243
- 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 -187
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -279
- 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 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -370
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -131
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -167
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -45
- 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/Tracking.kt +0 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -176
- package/gradle/libs.versions.toml +0 -58
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/gradle.properties +0 -26
- package/gradlew +0 -252
- package/gradlew.bat +0 -94
- package/local.properties +0 -8
- package/settings.gradle.kts +0 -52
|
@@ -17,7 +17,7 @@ public class MiniAppContext {
|
|
|
17
17
|
public var toolkitConfig: [String: Any] = [:]
|
|
18
18
|
public var providerId: String = "momo"
|
|
19
19
|
public var permissions: [[String: Any]] = []
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
public init(appId: String, appCode: String, appName: Any? = nil, appIcon: String, description: Any? = nil, support: [String: Any] = [:], toolkitConfig: [String: Any] = [:], providerId: String = "momo", permissions: [[String: Any]] = []) {
|
|
22
22
|
self.appId = appId
|
|
23
23
|
self.appCode = appCode
|
|
@@ -37,15 +37,11 @@ public class KitConfig {
|
|
|
37
37
|
public var headerGradient: String? = nil
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
public var IsShowBaseLineDebug = false
|
|
41
|
-
|
|
42
|
-
public var UseFontScaleSystem = true
|
|
43
|
-
|
|
44
40
|
public class ApplicationEnvironment: ObservableObject {
|
|
45
41
|
let applicationContext: MiniAppContext?
|
|
46
42
|
let composeApi: KitComposeApi?
|
|
47
43
|
let config: KitConfig?
|
|
48
|
-
|
|
44
|
+
|
|
49
45
|
public init(applicationContext: MiniAppContext? = nil, composeApi: KitComposeApi? = nil, config: KitConfig? = nil) {
|
|
50
46
|
self.applicationContext = applicationContext
|
|
51
47
|
self.composeApi = composeApi
|
package/ios/Input/Input.swift
CHANGED
|
@@ -4,7 +4,7 @@ import Combine
|
|
|
4
4
|
|
|
5
5
|
public struct Input: View {
|
|
6
6
|
@Binding public var text: String
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
public var placeholder: String
|
|
9
9
|
public var floatingValue: String
|
|
10
10
|
public var floatingIcon: String
|
|
@@ -22,6 +22,7 @@ public struct Input: View {
|
|
|
22
22
|
public var leadingIconColor: Color
|
|
23
23
|
public var loading: Bool
|
|
24
24
|
public var required: Bool
|
|
25
|
+
public var maxLength: Int?
|
|
25
26
|
public var fontWeight: InputFontWeight
|
|
26
27
|
public var keyboardType: UIKeyboardType
|
|
27
28
|
public var autofocus: Bool
|
|
@@ -29,10 +30,10 @@ public struct Input: View {
|
|
|
29
30
|
public var onFocus: (() -> Void)?
|
|
30
31
|
public var onBlur: (() -> Void)?
|
|
31
32
|
public var onRightIconPressed: (() -> Void)?
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
@State private var isFocused: Bool = false
|
|
34
35
|
@State private var isPasswordHidden: Bool = true
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
public init(
|
|
37
38
|
text: Binding<String>,
|
|
38
39
|
placeholder: String = "",
|
|
@@ -52,6 +53,7 @@ public struct Input: View {
|
|
|
52
53
|
leadingIconColor: Color = Colors.black12,
|
|
53
54
|
loading: Bool = false,
|
|
54
55
|
required: Bool = false,
|
|
56
|
+
maxLength: Int? = nil,
|
|
55
57
|
fontWeight: InputFontWeight = .regular,
|
|
56
58
|
keyboardType: UIKeyboardType = .default,
|
|
57
59
|
autofocus: Bool = false,
|
|
@@ -78,6 +80,7 @@ public struct Input: View {
|
|
|
78
80
|
self.leadingIconColor = leadingIconColor
|
|
79
81
|
self.loading = loading
|
|
80
82
|
self.required = required
|
|
83
|
+
self.maxLength = maxLength
|
|
81
84
|
self.fontWeight = fontWeight
|
|
82
85
|
self.keyboardType = keyboardType
|
|
83
86
|
self.autofocus = autofocus
|
|
@@ -93,7 +96,7 @@ public struct Input: View {
|
|
|
93
96
|
get: { self.text },
|
|
94
97
|
set: { newValue in
|
|
95
98
|
self.text = newValue
|
|
96
|
-
self.onChangeText?(newValue)
|
|
99
|
+
self.onChangeText?(limitText(newValue))
|
|
97
100
|
}
|
|
98
101
|
)
|
|
99
102
|
|
|
@@ -115,7 +118,7 @@ public struct Input: View {
|
|
|
115
118
|
.offset(x: Spacing.S, y: -8)
|
|
116
119
|
.zIndex(10)
|
|
117
120
|
}
|
|
118
|
-
|
|
121
|
+
|
|
119
122
|
// Input container
|
|
120
123
|
HStack(alignment: .center, spacing: 0) {
|
|
121
124
|
// Leading icon
|
|
@@ -123,7 +126,7 @@ public struct Input: View {
|
|
|
123
126
|
Icon(source: leadingIcon, size: size == .small ? 24 : 32, color: leadingIconColor)
|
|
124
127
|
.padding(.trailing, Spacing.M)
|
|
125
128
|
}
|
|
126
|
-
|
|
129
|
+
|
|
127
130
|
// Text input field
|
|
128
131
|
ZStack(alignment: .leading) {
|
|
129
132
|
if text.isEmpty {
|
|
@@ -133,7 +136,7 @@ public struct Input: View {
|
|
|
133
136
|
color: getPlaceholderColor()
|
|
134
137
|
)
|
|
135
138
|
}
|
|
136
|
-
|
|
139
|
+
|
|
137
140
|
if secureTextEntry && isPasswordHidden {
|
|
138
141
|
SecureInputField(
|
|
139
142
|
text: $text,
|
|
@@ -142,6 +145,7 @@ public struct Input: View {
|
|
|
142
145
|
fontWeight: fontWeight == .bold ? .bold : .regular,
|
|
143
146
|
textColor: UIColor(getTextColor()),
|
|
144
147
|
isDisabled: disabled || readOnly,
|
|
148
|
+
maxLength: maxLength,
|
|
145
149
|
onFocusChange: { focused in
|
|
146
150
|
handleFocusChange(focused)
|
|
147
151
|
},
|
|
@@ -156,9 +160,15 @@ public struct Input: View {
|
|
|
156
160
|
.foregroundColor(getTextColor())
|
|
157
161
|
.disabled(disabled || readOnly)
|
|
158
162
|
.applyPrimaryCursorColor()
|
|
163
|
+
.onChange(of: text) { newValue in
|
|
164
|
+
let limited = limitText(newValue)
|
|
165
|
+
if limited != newValue {
|
|
166
|
+
text = limited
|
|
167
|
+
}
|
|
168
|
+
}
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
|
-
|
|
171
|
+
|
|
162
172
|
// Clear button (only show when focused and has text)
|
|
163
173
|
if isFocused && !text.isEmpty {
|
|
164
174
|
SwiftUI.Button(action: {
|
|
@@ -169,14 +179,14 @@ public struct Input: View {
|
|
|
169
179
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
170
180
|
}
|
|
171
181
|
}
|
|
172
|
-
|
|
182
|
+
|
|
173
183
|
// Loading indicator
|
|
174
184
|
if loading {
|
|
175
185
|
ActivityIndicator(isAnimating: .constant(true), style: .medium)
|
|
176
186
|
.frame(width: 16, height: 16)
|
|
177
187
|
.padding(.leading, Spacing.S)
|
|
178
188
|
}
|
|
179
|
-
|
|
189
|
+
|
|
180
190
|
// Right icon (password toggle or custom icon)
|
|
181
191
|
if secureTextEntry {
|
|
182
192
|
if !text.isEmpty {
|
|
@@ -197,7 +207,7 @@ public struct Input: View {
|
|
|
197
207
|
}
|
|
198
208
|
}
|
|
199
209
|
.padding(.horizontal, Spacing.M)
|
|
200
|
-
.frame(height: scaleSize(size == .small ? 48 : 56))
|
|
210
|
+
.frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
|
|
201
211
|
.background(
|
|
202
212
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
203
213
|
.fill(Colors.black01)
|
|
@@ -207,7 +217,7 @@ public struct Input: View {
|
|
|
207
217
|
.stroke(borderColor(), lineWidth: 1)
|
|
208
218
|
)
|
|
209
219
|
}
|
|
210
|
-
|
|
220
|
+
|
|
211
221
|
// Error or hint
|
|
212
222
|
ErrorView(
|
|
213
223
|
errorMessage: error,
|
|
@@ -223,9 +233,9 @@ public struct Input: View {
|
|
|
223
233
|
}
|
|
224
234
|
}
|
|
225
235
|
}
|
|
226
|
-
|
|
236
|
+
|
|
227
237
|
// MARK: - Helpers
|
|
228
|
-
|
|
238
|
+
|
|
229
239
|
private func handleFocusChange(_ focused: Bool) {
|
|
230
240
|
isFocused = focused
|
|
231
241
|
if focused {
|
|
@@ -234,12 +244,19 @@ public struct Input: View {
|
|
|
234
244
|
onBlur?()
|
|
235
245
|
}
|
|
236
246
|
}
|
|
237
|
-
|
|
247
|
+
|
|
238
248
|
private func togglePasswordVisibility() {
|
|
239
249
|
isPasswordHidden.toggle()
|
|
240
250
|
onRightIconPressed?()
|
|
241
251
|
}
|
|
242
252
|
|
|
253
|
+
private func limitText(_ value: String) -> String {
|
|
254
|
+
guard let maxLength = maxLength else {
|
|
255
|
+
return value
|
|
256
|
+
}
|
|
257
|
+
return String(value.prefix(maxLength))
|
|
258
|
+
}
|
|
259
|
+
|
|
243
260
|
private func borderColor() -> Color {
|
|
244
261
|
if disabled {
|
|
245
262
|
return Colors.black04 // border.disable
|
|
@@ -252,19 +269,19 @@ public struct Input: View {
|
|
|
252
269
|
}
|
|
253
270
|
return Colors.black04 // border.default
|
|
254
271
|
}
|
|
255
|
-
|
|
272
|
+
|
|
256
273
|
private func getTextColor() -> Color {
|
|
257
274
|
return disabled ? Colors.black09 : Colors.black17
|
|
258
275
|
}
|
|
259
|
-
|
|
276
|
+
|
|
260
277
|
private func getPlaceholderColor() -> Color {
|
|
261
278
|
return disabled ? Colors.black09 : Colors.black12
|
|
262
279
|
}
|
|
263
|
-
|
|
280
|
+
|
|
264
281
|
private func getFloatingColor() -> Color {
|
|
265
282
|
return disabled ? Colors.black09 : Colors.black12
|
|
266
283
|
}
|
|
267
|
-
|
|
284
|
+
|
|
268
285
|
private func getFloatingIconColor() -> Color {
|
|
269
286
|
return disabled ? Colors.black09 : floatingIconColor
|
|
270
287
|
}
|
|
@@ -279,6 +296,7 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
279
296
|
var fontWeight: UIFont.Weight
|
|
280
297
|
var textColor: UIColor
|
|
281
298
|
var isDisabled: Bool
|
|
299
|
+
var maxLength: Int?
|
|
282
300
|
var onFocusChange: (Bool) -> Void
|
|
283
301
|
var onChangeText: ((String) -> Void)?
|
|
284
302
|
|
|
@@ -307,6 +325,7 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
307
325
|
}
|
|
308
326
|
|
|
309
327
|
func updateUIView(_ textField: UITextField, context: Context) {
|
|
328
|
+
context.coordinator.parent = self
|
|
310
329
|
if textField.text != text {
|
|
311
330
|
textField.text = text
|
|
312
331
|
}
|
|
@@ -342,7 +361,7 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
342
361
|
}
|
|
343
362
|
|
|
344
363
|
func textFieldDidEndEditing(_ textField: UITextField) {
|
|
345
|
-
parent.text = textField.text ?? ""
|
|
364
|
+
parent.text = limitText(textField.text ?? "")
|
|
346
365
|
parent.onFocusChange(false)
|
|
347
366
|
}
|
|
348
367
|
|
|
@@ -357,7 +376,10 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
357
376
|
|
|
358
377
|
@objc func textFieldDidChange(_ textField: UITextField) {
|
|
359
378
|
if isResettingText { return }
|
|
360
|
-
let newText = textField.text ?? ""
|
|
379
|
+
let newText = limitText(textField.text ?? "")
|
|
380
|
+
if textField.text != newText {
|
|
381
|
+
textField.text = newText
|
|
382
|
+
}
|
|
361
383
|
parent.text = newText
|
|
362
384
|
parent.onChangeText?(newText)
|
|
363
385
|
}
|
|
@@ -366,6 +388,13 @@ private struct SecureInputField: UIViewRepresentable {
|
|
|
366
388
|
textField.resignFirstResponder()
|
|
367
389
|
return true
|
|
368
390
|
}
|
|
391
|
+
|
|
392
|
+
private func limitText(_ value: String) -> String {
|
|
393
|
+
guard let maxLength = parent.maxLength else {
|
|
394
|
+
return value
|
|
395
|
+
}
|
|
396
|
+
return String(value.prefix(maxLength))
|
|
397
|
+
}
|
|
369
398
|
}
|
|
370
399
|
}
|
|
371
400
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import SwiftUI
|
|
9
9
|
public struct InputPhoneNumber: View {
|
|
10
10
|
@Binding public var text: String
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
public var placeholder: String
|
|
13
13
|
public var size: InputSize
|
|
14
14
|
public var hintText: String
|
|
@@ -22,9 +22,9 @@ public struct InputPhoneNumber: View {
|
|
|
22
22
|
public var onBlur: (() -> Void)?
|
|
23
23
|
public var onRightIconPressed: (() -> Void)?
|
|
24
24
|
public var accessibilityLabel: String?
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
@State private var isFocused: Bool = false
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
public init(
|
|
29
29
|
text: Binding<String>,
|
|
30
30
|
placeholder: String = "0123456789",
|
|
@@ -57,7 +57,7 @@ public struct InputPhoneNumber: View {
|
|
|
57
57
|
self.onRightIconPressed = onRightIconPressed
|
|
58
58
|
self.accessibilityLabel = accessibilityLabel
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
// MARK: - Body
|
|
62
62
|
public var body: some View {
|
|
63
63
|
let textBinding = Binding<String>(
|
|
@@ -67,28 +67,28 @@ public struct InputPhoneNumber: View {
|
|
|
67
67
|
self.onChangeText?(newValue)
|
|
68
68
|
}
|
|
69
69
|
)
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
VStack(alignment: .leading, spacing: 4) {
|
|
72
72
|
HStack(spacing: 0) {
|
|
73
73
|
// 🇻🇳 Flag
|
|
74
74
|
ImageView("https://static.momocdn.net/app/img/icon/ic-qrcode-package/ic_vn_flag.png")
|
|
75
75
|
.frame(width: 24, height: 24)
|
|
76
76
|
.padding(.trailing, Spacing.XS)
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
MomoText("+84", typography: size == .small ? .headerSSemibold : .headerMBold)
|
|
79
79
|
.foregroundColor(Colors.black17)
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
Rectangle()
|
|
82
82
|
.fill(Colors.black04)
|
|
83
83
|
.frame(width: 1, height: size == .small ? 24 : 32)
|
|
84
84
|
.padding(.horizontal, Spacing.M)
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
// Text input
|
|
87
87
|
ZStack(alignment: .leading) {
|
|
88
88
|
if text.isEmpty {
|
|
89
89
|
MomoText(placeholder, typography: size == .small ? .headerSSemibold : .headerMBold, color: Colors.black12)
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
TextField("", text: textBinding, onEditingChanged: { focused in
|
|
93
93
|
handleFocusChange(focused)
|
|
94
94
|
})
|
|
@@ -100,7 +100,7 @@ public struct InputPhoneNumber: View {
|
|
|
100
100
|
.accessibility(identifier: accessibilityLabel ?? "")
|
|
101
101
|
.accessibilityValue(textBinding.wrappedValue.isEmpty ? placeholder : textBinding.wrappedValue)
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
// Clear button
|
|
105
105
|
if isFocused && !text.isEmpty {
|
|
106
106
|
SwiftUI.Button(action: {
|
|
@@ -111,13 +111,13 @@ public struct InputPhoneNumber: View {
|
|
|
111
111
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
// Loading indicator
|
|
116
116
|
if loading {
|
|
117
117
|
ActivityIndicator(isAnimating: .constant(true), style: .medium)
|
|
118
118
|
.frame(width: 16, height: 16)
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
// ✅ Right icon
|
|
122
122
|
if !rightIcon.isEmpty {
|
|
123
123
|
SwiftUI.Button(action: { onRightIconPressed?() }) {
|
|
@@ -127,7 +127,7 @@ public struct InputPhoneNumber: View {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
.padding(.horizontal, Spacing.M)
|
|
130
|
-
.frame(height: scaleSize(size == .small ? 48 : 56))
|
|
130
|
+
.frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
|
|
131
131
|
.background(
|
|
132
132
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
133
133
|
.fill(Colors.black01)
|
|
@@ -136,7 +136,7 @@ public struct InputPhoneNumber: View {
|
|
|
136
136
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
137
137
|
.stroke(borderColor(), lineWidth: isFocused ? 1.5 : 1)
|
|
138
138
|
)
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
// Error or hint
|
|
141
141
|
ErrorView(
|
|
142
142
|
errorMessage: error,
|
|
@@ -145,9 +145,9 @@ public struct InputPhoneNumber: View {
|
|
|
145
145
|
)
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
// MARK: - Helpers
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
private func handleFocusChange(_ focused: Bool) {
|
|
152
152
|
isFocused = focused
|
|
153
153
|
if focused {
|
|
@@ -156,7 +156,7 @@ public struct InputPhoneNumber: View {
|
|
|
156
156
|
onBlur?()
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
private func borderColor() -> Color {
|
|
161
161
|
if !error.isEmpty { return Colors.red03 }
|
|
162
162
|
if isFocused { return Colors.primary }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
/// Posts `MoMoStatusBarTap.notificationName` on every status-bar tap.
|
|
6
|
+
/// The swizzle installs automatically at framework load (`+load`) — calling
|
|
7
|
+
/// `install` is a no-op kept for explicit/manual triggering.
|
|
8
|
+
@interface MoMoStatusBarTap : NSObject
|
|
9
|
+
@property (class, nonatomic, readonly) NSNotificationName notificationName;
|
|
10
|
+
+ (void)install;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import <objc/message.h>
|
|
3
|
+
#import <objc/runtime.h>
|
|
4
|
+
#import "StatusBarTap.h"
|
|
5
|
+
|
|
6
|
+
// Performs the actual swizzle once per process. Safe to call multiple times.
|
|
7
|
+
static void mm_installStatusBarTapSwizzleOnce(void) {
|
|
8
|
+
static dispatch_once_t onceToken;
|
|
9
|
+
dispatch_once(&onceToken, ^{
|
|
10
|
+
Class cls = [UIStatusBarManager class];
|
|
11
|
+
SEL originalSelector = NSSelectorFromString(@"handleTapAction:");
|
|
12
|
+
SEL swizzledSelector = NSSelectorFromString(@"mm_handleTapAction:");
|
|
13
|
+
|
|
14
|
+
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
15
|
+
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
|
16
|
+
if (!originalMethod || !swizzledMethod) return;
|
|
17
|
+
|
|
18
|
+
// Verify the original method matches the (id) -> void shape we expect.
|
|
19
|
+
// Encoding may include byte offsets (e.g. "v32@0:8@16") so we filter
|
|
20
|
+
// digits out before comparing.
|
|
21
|
+
const char *encPtr = method_getTypeEncoding(originalMethod);
|
|
22
|
+
if (encPtr) {
|
|
23
|
+
NSMutableString *enc = [NSMutableString string];
|
|
24
|
+
for (const char *p = encPtr; *p; p++) {
|
|
25
|
+
if (!(*p >= '0' && *p <= '9')) [enc appendFormat:@"%c", *p];
|
|
26
|
+
}
|
|
27
|
+
if (![enc isEqualToString:@"v@:@"]) return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
BOOL didAdd = class_addMethod(cls,
|
|
31
|
+
originalSelector,
|
|
32
|
+
method_getImplementation(swizzledMethod),
|
|
33
|
+
method_getTypeEncoding(swizzledMethod));
|
|
34
|
+
if (didAdd) {
|
|
35
|
+
class_replaceMethod(cls,
|
|
36
|
+
swizzledSelector,
|
|
37
|
+
method_getImplementation(originalMethod),
|
|
38
|
+
method_getTypeEncoding(originalMethod));
|
|
39
|
+
} else {
|
|
40
|
+
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@implementation MoMoStatusBarTap
|
|
46
|
+
+ (NSNotificationName)notificationName { return @"statusBarSelected"; }
|
|
47
|
+
+ (void)install { mm_installStatusBarTapSwizzleOnce(); }
|
|
48
|
+
@end
|
|
49
|
+
|
|
50
|
+
// MARK: - Swizzle target on UIStatusBarManager
|
|
51
|
+
// `mm_handleTapAction:` is the replacement IMP. After the add/exchange,
|
|
52
|
+
// this selector points at the original UIKit IMP — calling it inside
|
|
53
|
+
// the body invokes UIKit's real handler so UIScrollView.scrollsToTop
|
|
54
|
+
// and any other side effects continue to work.
|
|
55
|
+
|
|
56
|
+
@interface UIStatusBarManager (MoMoStatusBarTap)
|
|
57
|
+
@end
|
|
58
|
+
|
|
59
|
+
@implementation UIStatusBarManager (MoMoStatusBarTap)
|
|
60
|
+
|
|
61
|
+
// Auto-install at framework load. Commented out so the swizzle stays
|
|
62
|
+
// opt-in via `[MoMoStatusBarTap install]`. Uncomment to revert to
|
|
63
|
+
// auto-installation before main().
|
|
64
|
+
//
|
|
65
|
+
// + (void)load {
|
|
66
|
+
// mm_installStatusBarTapSwizzleOnce();
|
|
67
|
+
// }
|
|
68
|
+
|
|
69
|
+
- (void)mm_handleTapAction:(id)action {
|
|
70
|
+
[self mm_handleTapAction:action];
|
|
71
|
+
[[NSNotificationCenter defaultCenter] postNotificationName:MoMoStatusBarTap.notificationName
|
|
72
|
+
object:nil];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@end
|
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import SwiftUI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
public func scaleSize(_ size: CGFloat, _ scaleRate: CGFloat? = nil) -> CGFloat {
|
|
4
|
+
let defaultScreenSize: CGFloat = 375
|
|
5
|
+
let maxFontScale: CGFloat = scaleRate ?? 1.5
|
|
6
|
+
let maxDeviceScale: CGFloat = 5
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let deviceWidth = UIScreen.main.bounds.width
|
|
9
|
-
let deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
8
|
+
let deviceWidth = UIScreen.main.bounds.width
|
|
9
|
+
let deviceScale = deviceWidth / defaultScreenSize
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
|
|
12
|
+
let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
|
|
13
|
+
let fontScale = scaledFont.pointSize / defaultFont.pointSize
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let fontSizeScaleOS = fontScale > 1 ? fontScale * size : size
|
|
15
|
+
var fontSizeDeviceScale = size
|
|
16
|
+
var fontSizeOSScale = size
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
|
|
19
|
+
if deviceScale > 1 {
|
|
20
|
+
fontSizeDeviceScale = min(fontSizeDeviceScale * deviceScale, fontSizeDeviceScale + maxDeviceScale)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if fontScale > 1 {
|
|
24
|
+
fontSizeOSScale = min(fontSizeOSScale * fontScale, fontSizeOSScale * maxFontScale)
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
return
|
|
27
|
+
return max(fontSizeDeviceScale, fontSizeOSScale)
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
public enum TypographyStyle {
|
|
@@ -2,7 +2,28 @@ import SwiftUI
|
|
|
2
2
|
|
|
3
3
|
public extension Font {
|
|
4
4
|
static func appFont(size: CGFloat) -> Font {
|
|
5
|
-
|
|
5
|
+
let defaultScreenSize: CGFloat = 375
|
|
6
|
+
let maxFontScale: CGFloat = 1.5
|
|
7
|
+
let maxDeviceScale: CGFloat = 5
|
|
8
|
+
|
|
9
|
+
let deviceWidth = UIScreen.main.bounds.width
|
|
10
|
+
let deviceScale = deviceWidth / defaultScreenSize
|
|
11
|
+
|
|
12
|
+
let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
|
|
13
|
+
let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
|
|
14
|
+
let fontScale = scaledFont.pointSize / defaultFont.pointSize
|
|
15
|
+
|
|
16
|
+
var fontSize = size
|
|
17
|
+
|
|
18
|
+
if deviceScale > 1 {
|
|
19
|
+
fontSize = min(fontSize * deviceScale, fontSize + maxDeviceScale)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if fontScale > 1 {
|
|
23
|
+
fontSize = min(fontSize * fontScale, fontSize * maxFontScale)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return Font.system(size: fontSize)
|
|
6
27
|
}
|
|
7
28
|
|
|
8
29
|
// New supported typography styles
|
package/ios/native-kits.podspec
CHANGED
|
@@ -10,7 +10,8 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.ios.deployment_target = '15.0'
|
|
11
11
|
s.swift_version = '5.0'
|
|
12
12
|
|
|
13
|
-
s.source_files = "**/*.swift"
|
|
13
|
+
s.source_files = "**/*.{swift,m,h}"
|
|
14
|
+
s.public_header_files = "StatusBarTap/*.h"
|
|
14
15
|
s.framework = 'SwiftUI', 'Combine'
|
|
15
16
|
s.dependency 'SDWebImageSwiftUI'
|
|
16
17
|
s.dependency 'lottie-ios'
|
package/package.json
CHANGED
package/build.gradle.kts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
plugins {
|
|
2
|
-
// this is necessary to avoid the plugins to be loaded multiple times
|
|
3
|
-
// in each subproject's classloader
|
|
4
|
-
alias(libs.plugins.android.application) apply false
|
|
5
|
-
alias(libs.plugins.android.library) apply false
|
|
6
|
-
alias(libs.plugins.compose) apply false
|
|
7
|
-
alias(libs.plugins.kotlin.compose.compiler) apply false
|
|
8
|
-
alias(libs.plugins.jetbrains.kotlin.multiplatform) apply false
|
|
9
|
-
alias(libs.plugins.jetbrains.kotlin.serialization) apply false
|
|
10
|
-
alias(libs.plugins.vanniktech.mavenPublish) apply false
|
|
11
|
-
}
|