@momo-kits/native-kits 0.110.1-beta.1 → 0.110.1-beta.30

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.
@@ -3,6 +3,7 @@ plugins {
3
3
  alias(libs.plugins.jetbrains.kotlin.multiplatform)
4
4
  alias(libs.plugins.compose)
5
5
  alias(libs.plugins.kotlin.compose.compiler)
6
+ kotlin("plugin.serialization")
6
7
  id("maven-publish")
7
8
  }
8
9
 
@@ -39,6 +40,7 @@ kotlin {
39
40
  implementation(libs.coil.multiplatform.compose)
40
41
  implementation(libs.coil.multiplatform.core)
41
42
  implementation(libs.coil.multiplatform.network.ktor)
43
+ implementation(libs.jetbrains.serialization.json)
42
44
  }
43
45
  }
44
46
  val androidMain by getting {
@@ -73,11 +73,19 @@ fun HeaderBackground(
73
73
  targetValue = (1 - (scrollState / 200f)).coerceIn(0f, 1f),
74
74
  )
75
75
 
76
+ val backgroundColor = if (scrollState == 0) {
77
+ Color.Transparent
78
+ } else {
79
+ AppTheme.current.colors.background.surface
80
+ }
81
+
82
+
76
83
  when (headerType) {
77
84
  HeaderType.DEFAULT -> {
78
85
  val height = statusBarHeight + 52.dp
79
86
  Box(
80
87
  modifier = Modifier.fillMaxWidth().height(height)
88
+ .background(backgroundColor)
81
89
  .bottomBorder(
82
90
  strokeWidth = 1.dp,
83
91
  color = AppTheme.current.colors.border.default
@@ -101,6 +109,7 @@ fun HeaderBackground(
101
109
  )
102
110
  if (AppTheme.current.assets.headerBackground != null) {
103
111
  Image(
112
+ loading = false,
104
113
  source = AppTheme.current.assets.headerBackground!!,
105
114
  modifier = Modifier.fillMaxWidth().height(height),
106
115
  options = Options(
@@ -113,6 +122,7 @@ fun HeaderBackground(
113
122
  }
114
123
 
115
124
  HeaderType.EXTENDED -> {
125
+
116
126
  Box(
117
127
  modifier = Modifier.fillMaxWidth().height(154.dp)
118
128
  .alpha(opacityAni)
@@ -128,13 +138,19 @@ fun HeaderBackground(
128
138
  )
129
139
  ) {
130
140
  if (AppTheme.current.assets.headerBackground != null) {
131
- Image(
132
- source = AppTheme.current.assets.headerBackground!!,
133
- modifier = Modifier.fillMaxWidth().height(154.dp),
134
- options = Options(
135
- contentScale = ContentScale.FillWidth
141
+ Box(
142
+ modifier = Modifier.fillMaxWidth()
143
+ .background(backgroundColor)
144
+ ) {
145
+ Image(
146
+ loading = false,
147
+ source = AppTheme.current.assets.headerBackground!!,
148
+ modifier = Modifier.fillMaxWidth().height(154.dp),
149
+ options = Options(
150
+ contentScale = ContentScale.FillWidth
151
+ )
136
152
  )
137
- )
153
+ }
138
154
  }
139
155
  }
140
156
  }
@@ -246,7 +262,7 @@ fun Header(
246
262
  }
247
263
  if (inputSearchProps != null) {
248
264
  InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
249
- } else{
265
+ } else {
250
266
  Box(
251
267
  Modifier.weight(1f).graphicsLayer {
252
268
  alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
@@ -1,64 +1,77 @@
1
1
  package vn.momo.kits.application
2
2
 
3
- import androidx.compose.foundation.layout.WindowInsets
4
- import androidx.compose.foundation.layout.asPaddingValues
5
- import androidx.compose.foundation.layout.systemBars
6
3
  import androidx.compose.runtime.Composable
7
4
  import androidx.compose.runtime.CompositionLocalProvider
5
+ import androidx.compose.runtime.LaunchedEffect
6
+ import androidx.compose.runtime.getValue
7
+ import androidx.compose.runtime.mutableStateOf
8
+ import androidx.compose.runtime.remember
9
+ import androidx.compose.runtime.rememberCoroutineScope
10
+ import androidx.compose.runtime.setValue
8
11
  import androidx.compose.runtime.staticCompositionLocalOf
12
+ import androidx.compose.ui.unit.Dp
13
+ import kotlinx.coroutines.launch
14
+ import kotlinx.serialization.json.Json
15
+ import kotlinx.serialization.json.jsonObject
16
+ import kotlinx.serialization.json.jsonPrimitive
9
17
  import vn.momo.kits.const.AppStatusBar
10
18
  import vn.momo.kits.const.AppTheme
11
19
  import vn.momo.kits.const.Theme
20
+ import vn.momo.kits.const.ThemeAssets
12
21
  import vn.momo.kits.const.defaultTheme
13
22
  import vn.momo.kits.platform.disableOverscroll
14
23
  import vn.momo.kits.platform.getStatusBarHeight
15
24
 
16
- val AppNavigator = staticCompositionLocalOf<Navigator> {
17
- error("no navigator provided!")
18
- }
19
-
20
- class Navigator {
21
- fun push(content: @Composable () -> Unit) {
22
- }
23
-
24
- fun present(content: @Composable () -> Unit) {
25
-
26
- }
27
-
28
- fun reset(content: @Composable () -> Unit) {
29
-
30
- }
31
-
32
- fun pop() {
33
- }
25
+ val PlatformApi = staticCompositionLocalOf<Any?> { null }
34
26
 
35
- fun replace(content: @Composable () -> Unit) {
36
- }
37
-
38
- fun popToTop() {
39
- }
40
-
41
- fun showModal(
42
- onClose: () -> Unit = {},
43
- canBackgroundClose: Boolean = true,
44
- content: @Composable () -> Unit,
45
- ) {
46
- }
47
-
48
- fun showBottomSheet(content: @Composable () -> Unit) {
49
- }
27
+ interface ComposeApi {
28
+ fun request(funcName: String, params: String?): String
29
+ fun request(funcName: String, params: String?, onResponse: ((String) -> Unit)?): String
30
+ fun requestCallback(funcName: String, params: String?, onResponse: ((String) -> Unit)?)
31
+ fun removeCallback(id: String)
50
32
  }
51
33
 
52
34
  @Composable
53
35
  fun ApplicationContainer(
54
36
  theme: Theme = defaultTheme,
55
- content: @Composable () -> Unit,
37
+ composeApi: ComposeApi? = null,
38
+ statusBarHeight: Dp? = AppStatusBar.current ?: getStatusBarHeight(),
39
+ content: @Composable () -> Unit
56
40
  ) {
41
+ var appTheme by remember { mutableStateOf(theme) }
42
+ val coroutineScope = rememberCoroutineScope()
43
+
44
+ LaunchedEffect(Unit) {
45
+ try {
46
+ composeApi?.request("getConfig", "DESIGN_SYSTEM") {
47
+ val json = Json { ignoreUnknownKeys = true }
48
+ val response = json.parseToJsonElement(it).jsonObject["response"]
49
+ val headerBar = response
50
+ ?.jsonObject
51
+ ?.get("headerBar")
52
+ ?.jsonPrimitive
53
+ ?.content
54
+ if (headerBar != null && appTheme.assets.headerBackground == null) {
55
+ coroutineScope.launch {
56
+ appTheme = appTheme.copy(
57
+ assets = ThemeAssets(
58
+ headerBackground = headerBar
59
+ )
60
+ )
61
+ }
62
+ }
63
+ }
64
+ }
65
+ catch (e: Exception) {
66
+ print("@@ == NavigationContainer fetch config error $e")
67
+ }
68
+ }
69
+
57
70
  disableOverscroll()
58
71
  CompositionLocalProvider(
59
- AppTheme provides theme,
60
- AppNavigator provides Navigator(),
61
- AppStatusBar provides getStatusBarHeight(),
72
+ AppTheme provides appTheme,
73
+ PlatformApi provides composeApi,
74
+ AppStatusBar provides statusBarHeight,
62
75
  ) {
63
76
  content()
64
77
  }
@@ -87,7 +87,9 @@ fun Screen(
87
87
  )
88
88
 
89
89
  val headerAnimated =
90
- @Composable { animatedHeader?.composable?.invoke(scrollState.value) }
90
+ @Composable {
91
+ animatedHeader?.composable?.invoke(scrollState.value)
92
+ }
91
93
 
92
94
  Box(
93
95
  Modifier.fillMaxSize()
@@ -95,7 +97,10 @@ fun Screen(
95
97
  ) {
96
98
 
97
99
  if (animatedHeader === null) {
98
- HeaderBackground(headerType = headerType, scrollState = scrollState.value)
100
+ HeaderBackground(
101
+ headerType = headerType,
102
+ scrollState = scrollState.value,
103
+ )
99
104
  } else {
100
105
  Box(
101
106
  Modifier.zIndex(2f)
@@ -104,7 +109,7 @@ fun Screen(
104
109
  ) {
105
110
  HeaderBackground(
106
111
  headerType = headerType,
107
- scrollState = scrollState.value
112
+ scrollState = scrollState.value,
108
113
  )
109
114
  }
110
115
  }
@@ -98,6 +98,7 @@ data class InputSearchProps(
98
98
  val keyboardActions: KeyboardActions = KeyboardActions.Default,
99
99
  val modifier: Modifier = Modifier,
100
100
  val iconModifier: Modifier = Modifier,
101
+ val onClearPress: () -> Unit = {}
101
102
  )
102
103
 
103
104
  @Composable
@@ -176,8 +177,8 @@ fun InputSearch(
176
177
  Text(
177
178
  text = inputSearchProps.placeholder,
178
179
  style = TextStyle(
179
- fontSize = 16.sp,
180
- lineHeight = 24.sp,
180
+ fontSize = 14.sp,
181
+ lineHeight = 20.sp,
181
182
  fontWeight = inputSearchProps.fontWeight.value
182
183
  ),
183
184
  maxLines = 1,
@@ -195,7 +196,10 @@ fun InputSearch(
195
196
  size = 16.dp,
196
197
  color = AppTheme.current.colors.text.hint,
197
198
  modifier = Modifier.clickable(
198
- onClick = { inputSearchProps.text.value = "" },
199
+ onClick = {
200
+ inputSearchProps.text.value = ""
201
+ inputSearchProps.onClearPress.invoke()
202
+ },
199
203
  interactionSource = remember { MutableInteractionSource() },
200
204
  indication = null
201
205
  )
@@ -211,20 +215,20 @@ fun InputSearch(
211
215
  )
212
216
  }
213
217
  }
214
- if (inputSearchProps.showButtonText) {
215
- Text(
216
- text = inputSearchProps.buttonText,
217
- style = Typography.actionDefault,
218
- color = AppTheme.current.colors.text.default,
219
- modifier = Modifier.padding(start = Spacing.L).clickable(
220
- interactionSource = remember { MutableInteractionSource() },
221
- indication = null,
222
- onClick = inputSearchProps.onPressButtonText
223
- )
224
- )
225
- }
226
218
  }
227
219
  },
228
220
  )
221
+ if (inputSearchProps.showButtonText) {
222
+ Text(
223
+ text = inputSearchProps.buttonText,
224
+ style = Typography.actionDefault,
225
+ color = AppTheme.current.colors.text.default,
226
+ modifier = Modifier.padding(start = Spacing.L).clickable(
227
+ interactionSource = remember { MutableInteractionSource() },
228
+ indication = null,
229
+ onClick = inputSearchProps.onPressButtonText
230
+ )
231
+ )
232
+ }
229
233
  }
230
234
  }
@@ -4,98 +4,35 @@ import SwiftUI
4
4
  public struct Checkbox: View{
5
5
  @Binding var checked: Bool
6
6
  var disabled: Bool
7
- // var onChange: ((Bool)->Void)?
8
- var onCheckedChange: ((Bool) -> Void)?
9
- var indeterminate: Bool
10
- var title: String
7
+ var onChange: ((Bool)->Void)?
11
8
 
12
-
13
- public init(_ checked: Binding<Bool>,disabled: Bool = false, onCheckedChange: ( (Bool) -> Void)?,
14
- indeterminate: Bool = false,
15
- title: String = ""){
9
+ public init(_ checked: Binding<Bool>,disabled: Bool = false, onChange: ((Bool)->Void)? = nil){
16
10
  self._checked = checked
11
+ self.onChange = onChange
17
12
  self.disabled = disabled
18
- self.onCheckedChange = onCheckedChange
19
- self.indeterminate = indeterminate
20
- self.title = title
21
13
  }
22
14
 
23
15
  func onCheck(){
24
16
  checked.toggle()
25
- onCheckedChange?(checked)
17
+ onChange?(checked)
26
18
  }
27
19
 
28
- public var body: some View {
29
- HStack(spacing: Spacing.S) {
30
- // Checkbox
31
- ZStack {
32
- RoundedRectangle(cornerRadius: Radius.XS)
33
- .fill(backgroundColor)
34
- .frame(width: 20, height: 20)
35
- .overlay(
36
- RoundedRectangle(cornerRadius: Radius.XS)
37
- .stroke(borderColor, lineWidth: Spacing.XXS)
38
- )
39
-
40
- if checked {
41
- Image(systemName: indeterminate ? "minus" : "checkmark")
20
+ public var body: some View{
21
+ return SwiftUI.Button(action: onCheck) {
22
+ HStack {
23
+ if (checked) {
24
+ Image(systemName: "checkmark.square.fill")
42
25
  .resizable()
43
- .foregroundColor(Colors.black20)
44
- .frame(width: 12, height: 12)
26
+ .foregroundColor(disabled ? Colors.black07 : Colors.primary)
27
+ .frame(width: 24, height: 24)
45
28
  }
46
- }
47
- .onTapGesture {
48
- if !disabled {
49
- onCheckedChange?(checked)
50
- }
51
- }
52
-
53
- // Title
54
- if !title.isEmpty {
55
- Text(title)
56
- .font(.description1)
57
- }
58
- }
59
- }
60
-
61
- private var borderColor: Color {
62
- if disabled {
63
- return Colors.black03
64
- } else if checked {
65
- return Colors.primary
66
- } else {
67
- return Colors.text
68
- }
69
- }
70
-
71
- private var backgroundColor: Color {
72
- if disabled && checked {
73
- return Colors.pink08
74
- } else if checked {
75
- return Colors.primary
76
- } else {
77
- return Colors.black01
29
+ }.frame(width: 24, height: 24)
30
+ .overlay(RoundedRectangle(cornerRadius: 4).stroke(Colors.black20,lineWidth: checked ? 0 : 1))
31
+ .background(Colors.black01)
32
+
78
33
  }
34
+ .opacity(disabled ? 0.4 : 1)
35
+ .disabled(disabled)
79
36
  }
80
37
 
81
-
82
-
83
- // public var body: some View{
84
- // return SwiftUI.Button(action: onCheck) {
85
- // HStack {
86
- // if (checked) {
87
- // Image(systemName: "checkmark.square.fill")
88
- // .resizable()
89
- // .foregroundColor(disabled ? Colors.black07 : Colors.primary)
90
- // .frame(width: 24, height: 24)
91
- // }
92
- // }.frame(width: 24, height: 24)
93
- // .overlay(RoundedRectangle(cornerRadius: 4).stroke(Colors.black20,lineWidth: checked ? 0 : 1))
94
- // .background(Colors.black01)
95
- //
96
- // }
97
- // .opacity(disabled ? 0.4 : 1)
98
- // .disabled(disabled)
99
- // }
100
-
101
38
  }
@@ -71,22 +71,12 @@ public struct Input: View {
71
71
  var rightIcon: AnyView?
72
72
  var onChange: ((String) -> Void)?
73
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
74
 
85
75
  func onCancel(){
86
76
  self.value.removeAll()
87
77
  }
88
78
 
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){
79
+ 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){
90
80
  self.placeholder = placeholder
91
81
  self.floatingValue = floatingValue
92
82
  self.errorMessage = errorMessage
@@ -96,16 +86,6 @@ public struct Input: View {
96
86
  self.rightIcon = rightIcon
97
87
  self.floatingIcon = floatingIcon
98
88
  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
89
  }
110
90
 
111
91
  func onChangeText(value: String){
@@ -113,137 +93,57 @@ public struct Input: View {
113
93
  }
114
94
 
115
95
  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
- ImageLoader(url: URL(string: leadingIcon)!)
121
- .frame(width: 20, height: 20)
122
- .foregroundColor(leadingIconColor)
123
- }
124
-
125
- if !isSecure {
126
- TextField("", text: $value, onEditingChanged: { isChange in
127
- self.focused = isChange
128
- })
129
- .disabled(disabled)
130
- .font(fontWeight == .bold ? .headline : .body)
131
- } else {
132
- DotTextField(value: $value)
133
- .disabled(disabled)
96
+ return ZStack (alignment: .topLeading){
97
+ HStack(alignment: .center){
98
+ if (!isSecure){
99
+ TextField("",text: $value, onEditingChanged:{ isChange in
100
+ self.focused = isChange
101
+ })
102
+ .font(.paragraph)
103
+ .padding(.horizontal, 12)
104
+ .accentColor(Colors.pink03)
105
+ .keyboardType(keyboardType)
106
+ .valueChanged(value: value, onChange: onChangeText)
107
+
108
+ HStack{
109
+ SwiftButton(action: onCancel){
110
+ Image(systemName: "x.circle.fill")
111
+ .foregroundColor(Colors.text)
112
+ .frame(width: 16, height: 16)
113
+ .padding(.leading, -4)
114
+ .padding(.trailing, 8)
134
115
  }
135
116
 
136
- if loading {
137
- ActivityIndicator(isAnimating: .constant(true), style: .medium)
138
- .frame(width: 20, height: 20)
139
- } else if !value.isEmpty {
140
- SwiftButton(action: onCancel){
141
- Image(systemName: "x.circle.fill")
142
- .foregroundColor(Colors.text)
143
- .frame(width: 16, height: 16)
144
- .padding(.leading, -4)
145
- .padding(.trailing, 8)
146
- }
147
- }
148
-
149
117
  rightIcon
118
+
150
119
  }
151
- .padding(.horizontal, 12)
152
- .frame(height: size == .small ? 40 : 48)
153
- .background(disabled ? Colors.black01 : Color.white)
154
- .overlay(RoundedRectangle(cornerRadius: 8).stroke(focused ? Colors.pink03 : Colors.border, lineWidth: 1))
155
-
156
- if value.isEmpty {
157
- Text(placeholder + (required ? " *" : ""))
158
- .foregroundColor(Colors.black09)
159
- .padding(.horizontal, 12)
160
- .padding(.top, 12)
161
- .allowsHitTesting(false)
120
+ }else{
121
+ DotTextField(value: $value)
122
+ .padding(.horizontal, 12)
123
+ .accentColor(Colors.pink03)
124
+ SwiftButton(action: onCancel){
125
+ Image(systemName: "x.circle.fill")
126
+ .foregroundColor(Colors.text)
127
+ .frame(width: 16, height: 16)
128
+ .padding(.leading, -4)
129
+ .padding(.trailing, 8)
162
130
  }
163
-
164
- if !floatingValue.isEmpty {
165
- FloatingComponent(floatingValue, floatingIcon: floatingIconURL.map { url in
166
- AnyView(ImageLoader(url: URL(string: url)!)
167
- .frame(width: 20, height: 20)
168
- .background(floatingIconColor))
169
- })
170
- }
171
- }
172
-
173
- if !errorMessage.isEmpty {
174
- Text(errorMessage)
175
- .foregroundColor(.red)
176
- .font(.caption)
177
- } else if let hint = hintText {
178
- Text(hint)
179
- .foregroundColor(Colors.black09)
180
- .font(.caption)
181
131
  }
182
132
  }
183
- }
184
- }
185
-
186
- struct ImageLoader: View {
187
- @ObservedObject private var loader: ImageLoaderObject
188
-
189
- init(url: URL) {
190
- loader = ImageLoaderObject(url: url)
191
- }
192
-
193
- var body: some View {
194
- Group {
195
- if let image = loader.image {
196
- Image(uiImage: image)
197
- .resizable()
198
- .aspectRatio(contentMode: .fit)
199
- } else {
200
- // Use UIActivityIndicatorView for earlier iOS versions
201
- ActivityIndicator(isAnimating: .constant(true), style: .medium)
133
+ .frame(maxWidth: .infinity, minHeight: 48)
134
+ .overlay(RoundedRectangle(cornerRadius: 8).stroke(focused == true ? Colors.pink03 : Colors.border, lineWidth: 1))
135
+ .padding(.horizontal, 1)
136
+ if (value.isEmpty){
137
+ Text(placeholder)
138
+ .font(.paragraph)
139
+ .font(.system(size: 16))
140
+ .foregroundColor(Colors.black09)
141
+ .padding(.leading, 12)
142
+ .padding(.top, 16)
143
+ .allowsHitTesting(false)
202
144
  }
203
- }
145
+ if (!floatingValue.isEmpty) {FloatingComponent(floatingValue, floatingIcon: floatingIcon)}
146
+ }.padding(.bottom, 8)
204
147
  }
205
- }
206
-
207
-
208
- struct ActivityIndicator: UIViewRepresentable {
209
- @Binding var isAnimating: Bool
210
- let style: UIActivityIndicatorView.Style
211
-
212
- func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
213
- return UIActivityIndicatorView(style: style)
214
- }
215
-
216
- func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
217
- isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
218
- }
219
- }
220
-
221
- class ImageLoaderObject: ObservableObject {
222
- @Published var image: UIImage?
223
- private let url: URL
224
148
 
225
- init(url: URL) {
226
- self.url = url
227
- loadImage()
228
- }
229
-
230
- private func loadImage() {
231
- URLSession.shared.dataTask(with: url) { data, _, _ in
232
- if let data = data, let loadedImage = UIImage(data: data) {
233
- DispatchQueue.main.async {
234
- self.image = loadedImage
235
- }
236
- }
237
- }.resume()
238
- }
239
- }
240
-
241
- public enum InputSize {
242
- case small
243
- case large
244
- }
245
-
246
- public enum InputFontWeight {
247
- case regular
248
- case bold
249
149
  }
package/local.properties CHANGED
@@ -4,5 +4,5 @@
4
4
  # Location of the SDK. This is only used by Gradle.
5
5
  # For customization when using a Version Control System, please read the
6
6
  # header note.
7
- #Wed Aug 21 14:20:12 ICT 2024
8
- sdk.dir=/Users/huynhdung/Library/Android/sdk
7
+ #Tue Apr 23 16:40:15 ICT 2024
8
+ sdk.dir=/Users/hung.dao1/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.110.1-beta.1",
3
+ "version": "0.110.1-beta.30",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},
@@ -1,182 +0,0 @@
1
- //
2
- // InputSearch.swift
3
- // Pods
4
- //
5
- // Created by dung.pham2 on 3/12/24.
6
- //
7
- import SwiftUI
8
-
9
- // MARK: - RenderRightIconSearch
10
-
11
- struct RenderRightIconSearch: View {
12
- let loading: Bool
13
- let icon: String
14
- let color: Color
15
- let onClick: () -> Void
16
-
17
- var body: some View {
18
- HStack(spacing: 0) {
19
- if loading {
20
- ActivityIndicator(isAnimating: .constant(true), style: .medium)
21
- .frame(width: 16, height: 16)
22
- .padding(.horizontal, Spacing.S)
23
- }
24
- if !icon.isEmpty {
25
- Divider()
26
- .frame(width: 1)
27
- .background(Colors.primary)
28
- .padding(.leading, Spacing.S)
29
-
30
- Image(systemName: icon)
31
- .foregroundColor(color)
32
- .frame(width: 24, height: 24)
33
- .padding(.leading, Spacing.S)
34
- .onTapGesture(perform: onClick)
35
- }
36
- }
37
- }
38
- }
39
-
40
- // MARK: - InputSearch
41
-
42
- public struct InputSearch: View {
43
- @Binding var text: String
44
- var buttonText: String = ""
45
- var showButtonText: Bool = false
46
- var showBorder: Bool = true
47
- var placeholder: String = ""
48
- var onChangeText: (String) -> Void = { _ in }
49
- var onPressButtonText: () -> Void = {}
50
- var error: String = ""
51
- var disabled: Bool = false
52
- var icon: String = ""
53
- var iconColor: Color = Colors.text
54
- var onRightIconPressed: () -> Void = {}
55
- var onFocus: () -> Void = {}
56
- var onBlur: () -> Void = {}
57
- var loading: Bool = false
58
- var fontWeight: Font.Weight = .regular
59
- var keyboardType: UIKeyboardType = .default
60
-
61
- @State private var isFocused = false
62
- @State private var isBlurred = false
63
-
64
- public init(text: Binding<String>,
65
- buttonText: String = "",
66
- showButtonText: Bool = false,
67
- showBorder: Bool = true,
68
- placeholder: String = "",
69
- onChangeText: @escaping (String) -> Void = { _ in },
70
- onPressButtonText: @escaping () -> Void = {},
71
- error: String = "",
72
- disabled: Bool = false,
73
- icon: String = "",
74
- iconColor: Color = Colors.text,
75
- onRightIconPressed: @escaping () -> Void = {},
76
- onFocus: @escaping () -> Void = {},
77
- onBlur: @escaping () -> Void = {},
78
- loading: Bool = false,
79
- fontWeight: Font.Weight = .regular,
80
- keyboardType: UIKeyboardType = .default) {
81
- self._text = text
82
- self.buttonText = buttonText
83
- self.showButtonText = showButtonText
84
- self.showBorder = showBorder
85
- self.placeholder = placeholder
86
- self.onChangeText = onChangeText
87
- self.onPressButtonText = onPressButtonText
88
- self.error = error
89
- self.disabled = disabled
90
- self.icon = icon
91
- self.iconColor = iconColor
92
- self.onRightIconPressed = onRightIconPressed
93
- self.onFocus = onFocus
94
- self.onBlur = onBlur
95
- self.loading = loading
96
- self.fontWeight = fontWeight
97
- self.keyboardType = keyboardType
98
- }
99
-
100
-
101
- public var body: some View {
102
- VStack(alignment: .leading, spacing: 0) {
103
- HStack(spacing: 0) {
104
- HStack {
105
- Image(systemName: "magnifyingglass")
106
- .foregroundColor(Colors.black12)
107
- .frame(width: 24, height: 24)
108
- .padding(.trailing, Spacing.XS)
109
-
110
- ZStack(alignment: .leading) {
111
- if text.isEmpty {
112
- Text(placeholder)
113
- .foregroundColor(disabled ? Colors.black08 : Colors.black12)
114
- .font(.system(size: 16, weight: fontWeight))
115
- }
116
- TextField("", text: $text, onEditingChanged: { editing in
117
- isFocused = editing
118
- if editing {
119
- onFocus()
120
- } else if isBlurred {
121
- onBlur()
122
- }
123
- if editing && !isBlurred {
124
- isBlurred = true
125
- }
126
- }, onCommit: {})
127
- .disabled(disabled)
128
- .foregroundColor(disabled ? Colors.black08 : Colors.black17)
129
- .font(.system(size: 15, weight: fontWeight))
130
- .keyboardType(keyboardType)
131
- }
132
-
133
- if isFocused && !text.isEmpty {
134
- SwiftButton(action: { text = "" }) {
135
- Image(systemName: "xmark.circle.fill")
136
- .foregroundColor(Colors.black12)
137
- .frame(width: 16, height: 16)
138
- }
139
- .padding(.leading, Spacing.S)
140
- }
141
-
142
- RenderRightIconSearch(loading: loading, icon: icon, color: disabled ? Colors.black08 : iconColor, onClick: onRightIconPressed)
143
- }
144
- .padding(.horizontal, Spacing.M)
145
- .padding(.vertical, Spacing.S)
146
- .background(Colors.black01)
147
- .cornerRadius(Radius.XL)
148
- .overlay(
149
- RoundedRectangle(cornerRadius: Radius.XL)
150
- .stroke(getBorderColor(isFocused: isFocused, error: error, disabled: disabled), lineWidth: showBorder ? 1 : 0)
151
- )
152
- .frame(maxWidth: showButtonText ? .infinity : nil, alignment: .leading)
153
-
154
- if showButtonText {
155
- SwiftButton(action: onPressButtonText) {
156
- Text(buttonText)
157
- .foregroundColor(Colors.black17)
158
- .font(.system(size: 14, weight: .medium))
159
- }
160
- .padding(.leading, Spacing.L)
161
- }
162
- }
163
- }
164
- }
165
- }
166
-
167
- // MARK: - Helper Functions
168
-
169
- func getBorderColor(isFocused: Bool, error: String, disabled: Bool) -> Color {
170
- if disabled {
171
- return Colors.black08
172
- } else if !error.isEmpty {
173
- return Colors.red03
174
- } else if isFocused {
175
- return Colors.primary
176
- } else {
177
- return Colors.black04
178
- }
179
- }
180
-
181
-
182
-
@@ -1,242 +0,0 @@
1
- //
2
- // InputTextArea.swift
3
- // Pods
4
- //
5
- // Created by dung.pham2 on 2/12/24.
6
- //
7
- import SwiftUI
8
-
9
- // Make these constants public
10
- public let MAX_LENGTH = 300
11
- public let DEFAULT_HEIGHT: CGFloat = 104
12
-
13
- struct UITextViewWrapper: UIViewRepresentable {
14
- @Binding var text: String
15
- var onDone: (() -> Void)?
16
- var onFocus: (() -> Void)?
17
- var onBlur: (() -> Void)?
18
-
19
- func makeUIView(context: Context) -> UITextView {
20
- let textView = UITextView()
21
- textView.delegate = context.coordinator
22
- return textView
23
- }
24
-
25
- func updateUIView(_ uiView: UITextView, context: Context) {
26
- uiView.text = text
27
- }
28
-
29
- func makeCoordinator() -> Coordinator {
30
- Coordinator(self)
31
- }
32
-
33
- class Coordinator: NSObject, UITextViewDelegate {
34
- var parent: UITextViewWrapper
35
-
36
- init(_ parent: UITextViewWrapper) {
37
- self.parent = parent
38
- }
39
-
40
- func textViewDidChange(_ textView: UITextView) {
41
- parent.text = textView.text
42
- }
43
-
44
- func textViewDidBeginEditing(_ textView: UITextView) {
45
- parent.onFocus?()
46
- }
47
-
48
- func textViewDidEndEditing(_ textView: UITextView) {
49
- parent.onBlur?()
50
- }
51
-
52
- func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
53
- if text == "\n" {
54
- parent.onDone?()
55
- return false
56
- }
57
- return true
58
- }
59
- }
60
- }
61
-
62
- // Make the struct public
63
- public struct InputTextArea: View {
64
- @Binding var text: String
65
- var maxLength: Int = MAX_LENGTH
66
- var height: CGFloat = DEFAULT_HEIGHT
67
- var floatingValue: String = ""
68
- var floatingValueColor: Color = .gray
69
- var floatingIcon: String = ""
70
- var floatingIconColor: Color = .black
71
- var placeholder: String = ""
72
- var onChangeText: (String) -> Void = { _ in }
73
- var error: String = ""
74
- var errorSpacing: Bool = false
75
- var disabled: Bool = false
76
- var icon: String = ""
77
- var iconColor: Color = .black
78
- var onRightIconPressed: () -> Void = {}
79
- var onFocus: () -> Void = {}
80
- var onBlur: () -> Void = {}
81
- var loading: Bool = false
82
- var required: Bool = false
83
- var fontWeight: Font.Weight = .regular
84
- var keyboardType: UIKeyboardType = .default
85
-
86
- @State private var isFocused = false
87
- @State private var isBlurred = false
88
-
89
- // Make the initializer public
90
- public init(
91
- text: Binding<String>,
92
- maxLength: Int = MAX_LENGTH,
93
- height: CGFloat = DEFAULT_HEIGHT,
94
- floatingValue: String = "",
95
- floatingValueColor: Color = .gray,
96
- floatingIcon: String = "",
97
- floatingIconColor: Color = .black,
98
- placeholder: String = "",
99
- onChangeText: @escaping (String) -> Void = { _ in },
100
- error: String = "",
101
- errorSpacing: Bool = false,
102
- disabled: Bool = false,
103
- icon: String = "",
104
- iconColor: Color = Colors.pink03,
105
- onRightIconPressed: @escaping () -> Void = {},
106
- onFocus: @escaping () -> Void = {},
107
- onBlur: @escaping () -> Void = {},
108
- loading: Bool = false,
109
- required: Bool = false,
110
- fontWeight: Font.Weight = .regular,
111
- keyboardType: UIKeyboardType = .default
112
- ) {
113
- self._text = text
114
- self.maxLength = maxLength
115
- self.height = height
116
- self.floatingValue = floatingValue
117
- self.floatingValueColor = floatingValueColor
118
- self.floatingIcon = floatingIcon
119
- self.floatingIconColor = floatingIconColor
120
- self.placeholder = placeholder
121
- self.onChangeText = onChangeText
122
- self.error = error
123
- self.errorSpacing = errorSpacing
124
- self.disabled = disabled
125
- self.icon = icon
126
- self.iconColor = iconColor
127
- self.onRightIconPressed = onRightIconPressed
128
- self.onFocus = onFocus
129
- self.onBlur = onBlur
130
- self.loading = loading
131
- self.required = required
132
- self.fontWeight = fontWeight
133
- self.keyboardType = keyboardType
134
- }
135
-
136
- public var body: some View {
137
- VStack(alignment: .leading, spacing: 0) {
138
- ZStack(alignment: .topLeading) {
139
- if !floatingValue.isEmpty || !floatingIcon.isEmpty {
140
- HStack(spacing: 4) {
141
- Text(floatingValue)
142
- .font(.caption)
143
- .foregroundColor(disabled ? .gray : floatingValueColor)
144
-
145
- if required {
146
- Text("*")
147
- .font(.caption)
148
- .foregroundColor(.red)
149
- }
150
-
151
- if !floatingIcon.isEmpty {
152
- Image(systemName: floatingIcon)
153
- .font(.caption)
154
- .foregroundColor(disabled ? .gray : floatingIconColor)
155
- }
156
- }
157
- .padding(.horizontal, 8)
158
- .background(Colors.black01)
159
- .offset(x: Spacing.S, y: -height / 10)
160
- .zIndex(10)
161
- }
162
-
163
- VStack {
164
- ZStack(alignment: .topLeading) {
165
- if text.isEmpty {
166
- Text(placeholder)
167
- .foregroundColor(disabled ? .gray : .gray)
168
- .font(.system(size: 16, weight: fontWeight))
169
- .padding(.horizontal, 16)
170
- .padding(.vertical, 12)
171
- }
172
-
173
- UITextViewWrapper(text: $text, onDone: {
174
- // Handle done action if needed
175
- },
176
- onFocus: {
177
- isFocused = true
178
- onFocus()
179
- }, onBlur: {
180
- isFocused = false
181
- isBlurred = true
182
- onBlur()
183
- })
184
- .frame(height: height)
185
- .padding(.horizontal, 12)
186
- .padding(.vertical, 8)
187
- .disabled(disabled) }
188
-
189
- HStack {
190
- Spacer()
191
- Text("\(text.count)/\(maxLength)")
192
- .font(.caption)
193
- .foregroundColor(.gray)
194
- }
195
- .padding(.horizontal, 16)
196
- .padding(.bottom, 12)
197
- }
198
- .background(Color.white)
199
- .cornerRadius(8)
200
- .overlay(
201
- RoundedRectangle(cornerRadius: 8)
202
- .stroke(borderColor, lineWidth: 1)
203
- )
204
- }
205
-
206
- if !error.isEmpty {
207
- Text(error)
208
- .font(.caption)
209
- .foregroundColor(.red)
210
- .padding(.top, errorSpacing ? 8 : 4)
211
- }
212
- }
213
- .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in
214
- if !isBlurred {
215
- isFocused = true
216
- onFocus()
217
- }
218
- }
219
- .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
220
- if isFocused {
221
- isFocused = false
222
- isBlurred = true
223
- onBlur()
224
- }
225
- }
226
- }
227
-
228
- private var borderColor: Color {
229
- if disabled {
230
- return Colors.black03
231
- } else if !error.isEmpty {
232
- return .red
233
- } else if isFocused {
234
- return Colors.pink03
235
- } else {
236
- return Colors.border
237
- }
238
-
239
- }
240
- }
241
-
242
-