@momo-kits/native-kits 0.89.33 → 0.110.1-beta.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.
@@ -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 {
@@ -50,7 +50,6 @@ import vn.momo.kits.const.AppTheme
50
50
  import vn.momo.kits.const.Colors
51
51
  import vn.momo.kits.const.Spacing
52
52
  import vn.momo.kits.const.Typography
53
- import vn.momo.kits.modifier.shadow
54
53
  import vn.momo.kits.platform.getStatusBarHeight
55
54
  import vn.momo.kits.utils.bottomBorder
56
55
 
@@ -67,7 +66,6 @@ data class AnimatedHeader(
67
66
  @Composable
68
67
  fun HeaderBackground(
69
68
  headerType: HeaderType = HeaderType.DEFAULT,
70
- useShadow: Boolean? = true,
71
69
  scrollState: Int
72
70
  ) {
73
71
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
@@ -75,11 +73,19 @@ fun HeaderBackground(
75
73
  targetValue = (1 - (scrollState / 200f)).coerceIn(0f, 1f),
76
74
  )
77
75
 
76
+ val backgroundColor = if (scrollState == 0) {
77
+ Color.Transparent
78
+ } else {
79
+ AppTheme.current.colors.background.surface
80
+ }
81
+
82
+
78
83
  when (headerType) {
79
84
  HeaderType.DEFAULT -> {
80
85
  val height = statusBarHeight + 52.dp
81
86
  Box(
82
87
  modifier = Modifier.fillMaxWidth().height(height)
88
+ .background(backgroundColor)
83
89
  .bottomBorder(
84
90
  strokeWidth = 1.dp,
85
91
  color = AppTheme.current.colors.border.default
@@ -103,6 +109,7 @@ fun HeaderBackground(
103
109
  )
104
110
  if (AppTheme.current.assets.headerBackground != null) {
105
111
  Image(
112
+ loading = false,
106
113
  source = AppTheme.current.assets.headerBackground!!,
107
114
  modifier = Modifier.fillMaxWidth().height(height),
108
115
  options = Options(
@@ -115,6 +122,7 @@ fun HeaderBackground(
115
122
  }
116
123
 
117
124
  HeaderType.EXTENDED -> {
125
+
118
126
  Box(
119
127
  modifier = Modifier.fillMaxWidth().height(154.dp)
120
128
  .alpha(opacityAni)
@@ -130,31 +138,28 @@ fun HeaderBackground(
130
138
  )
131
139
  ) {
132
140
  if (AppTheme.current.assets.headerBackground != null) {
133
- Image(
134
- source = AppTheme.current.assets.headerBackground!!,
135
- modifier = Modifier.fillMaxWidth().height(154.dp),
136
- options = Options(
137
- 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
+ )
138
152
  )
139
- )
153
+ }
140
154
  }
141
155
  }
142
156
  }
157
+
143
158
  else -> {
144
159
  Box(modifier = Modifier.fillMaxWidth())
145
160
  }
146
161
  }
147
- Box(
148
- modifier = Modifier.fillMaxWidth().height(statusBarHeight + 52.dp)
149
- .alpha(1 - opacityAni)
150
- .background(Colors.black_01)
151
- .then(
152
- if (useShadow == true) Modifier.shadow() else Modifier.bottomBorder(
153
- 1.dp,
154
- Colors.black_04
155
- )
156
- )
157
- )
162
+
158
163
  }
159
164
 
160
165
  @Composable
@@ -163,10 +168,9 @@ fun Header(
163
168
  titlePosition: TitlePosition,
164
169
  title: String,
165
170
  headerRight: @Composable (() -> Unit)? = null,
166
- goBack: (() -> Unit)?,
171
+ goBack: (() -> Unit)? = null,
167
172
  opacity: Float? = null,
168
173
  animatedHeader: AnimatedHeader? = null,
169
- useSearchInput: Boolean? = false,
170
174
  scrollState: Int = 0,
171
175
  inputSearchProps: InputSearchProps?
172
176
  ) {
@@ -206,7 +210,7 @@ fun Header(
206
210
  horizontalArrangement = Arrangement.SpaceBetween
207
211
  ) {
208
212
  Box {
209
- if (goBack !== null) {
213
+ if (goBack != null) {
210
214
  Box(
211
215
  modifier = Modifier
212
216
  .size(28.dp)
@@ -238,12 +242,11 @@ fun Header(
238
242
  }
239
243
  }
240
244
  }
241
- if (useSearchInput == false) {
242
- Box(Modifier.graphicsLayer {
243
- alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
244
- }) {
245
- headerRight?.invoke()
246
- }
245
+
246
+ Box(Modifier.graphicsLayer {
247
+ alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
248
+ }) {
249
+ headerRight?.invoke()
247
250
  }
248
251
  }
249
252
 
@@ -254,13 +257,12 @@ fun Header(
254
257
  .padding(horizontal = Spacing.M),
255
258
  verticalAlignment = Alignment.CenterVertically,
256
259
  ) {
257
- if (goBack !== null) {
260
+ if (goBack != null && titlePosition == TitlePosition.LEFT) {
258
261
  Spacer(Modifier.width(40.dp))
259
262
  }
260
- if (useSearchInput == true && inputSearchProps != null) {
263
+ if (inputSearchProps != null) {
261
264
  InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
262
- }
263
- else{
265
+ } else {
264
266
  Box(
265
267
  Modifier.weight(1f).graphicsLayer {
266
268
  alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
@@ -292,7 +294,7 @@ fun HeaderTitle(
292
294
  modifier = Modifier.then(modifier).zIndex(1f),
293
295
  text = title,
294
296
  textAlign = textAlign,
295
- style = Typography.headerDefault,
297
+ style = Typography.actionS,
296
298
  color = color,
297
299
  maxLines = 1
298
300
  )
@@ -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
  }
@@ -56,7 +56,7 @@ fun Screen(
56
56
  horizontalAlignment: Alignment.Horizontal = Alignment.Start,
57
57
  title: String = "Stack",
58
58
  titlePosition: TitlePosition = TitlePosition.LEFT,
59
- goBack: (() -> Unit) = { },
59
+ goBack: (() -> Unit)? = null,
60
60
  scrollable: Boolean = true,
61
61
  scrollState: ScrollState = rememberScrollState(),
62
62
  onContentLayout: ((LayoutCoordinates) -> Unit)? = null,
@@ -66,8 +66,6 @@ fun Screen(
66
66
  fabProps: FabProps? = null,
67
67
  animatedHeader: AnimatedHeader? = null,
68
68
  layoutOffset: Dp = 56.dp,
69
- useShadow: Boolean? = true,
70
- useSearchInput: Boolean? = false,
71
69
  inputSearchProps: InputSearchProps? = null,
72
70
  content: @Composable () -> Unit,
73
71
  ) {
@@ -89,7 +87,9 @@ fun Screen(
89
87
  )
90
88
 
91
89
  val headerAnimated =
92
- @Composable { animatedHeader?.composable?.invoke(scrollState.value) }
90
+ @Composable {
91
+ animatedHeader?.composable?.invoke(scrollState.value)
92
+ }
93
93
 
94
94
  Box(
95
95
  Modifier.fillMaxSize()
@@ -97,17 +97,19 @@ fun Screen(
97
97
  ) {
98
98
 
99
99
  if (animatedHeader === null) {
100
- HeaderBackground(headerType = headerType, scrollState = scrollState.value)
100
+ HeaderBackground(
101
+ headerType = headerType,
102
+ scrollState = scrollState.value,
103
+ )
101
104
  } else {
102
105
  Box(
103
- Modifier.zIndex(5f)
106
+ Modifier.zIndex(2f)
104
107
  .background(Color.White.copy(alpha = opacity))
105
108
  .graphicsLayer { alpha = opacity }
106
109
  ) {
107
110
  HeaderBackground(
108
111
  headerType = headerType,
109
- useShadow = useShadow,
110
- scrollState = scrollState.value
112
+ scrollState = scrollState.value,
111
113
  )
112
114
  }
113
115
  }
@@ -120,7 +122,6 @@ fun Screen(
120
122
  goBack = goBack,
121
123
  opacity = opacity,
122
124
  animatedHeader = animatedHeader,
123
- useSearchInput = useSearchInput,
124
125
  inputSearchProps = inputSearchProps,
125
126
  scrollState = scrollState.value
126
127
  )
@@ -1,13 +1,17 @@
1
1
  package vn.momo.kits.components
2
2
 
3
+ import androidx.compose.foundation.layout.Box
3
4
  import androidx.compose.foundation.layout.size
4
5
  import androidx.compose.runtime.Composable
5
6
  import androidx.compose.ui.Modifier
6
7
  import androidx.compose.ui.graphics.Color
7
8
  import androidx.compose.ui.graphics.ColorFilter
8
9
  import androidx.compose.ui.layout.ContentScale
10
+ import androidx.compose.ui.semantics.contentDescription
11
+ import androidx.compose.ui.semantics.semantics
9
12
  import androidx.compose.ui.unit.Dp
10
13
  import androidx.compose.ui.unit.dp
14
+ import coil3.compose.AsyncImage
11
15
  import vn.momo.kits.const.AppTheme
12
16
  import vn.momo.kits.utils.Icons
13
17
 
@@ -23,14 +27,14 @@ fun Icon(
23
27
  } else {
24
28
  Icons[source] ?: ""
25
29
  }
26
- Image(
27
- modifier = modifier.size(size),
28
- source = icon,
29
- loading = false,
30
- options = Options(
30
+ Box(modifier = modifier.size(size).semantics {contentDescription = "img|$icon"}) {
31
+ AsyncImage(
32
+ modifier = Modifier.matchParentSize(),
33
+ model = icon,
34
+ contentDescription = null,
31
35
  contentScale = ContentScale.Fit,
32
- colorFilter = color?.let { ColorFilter.tint(it) }
33
- ),
34
- )
36
+ colorFilter = color?.let { ColorFilter.tint(it) },
37
+ )
38
+ }
35
39
  }
36
40
 
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.size
15
15
  import androidx.compose.foundation.layout.width
16
16
  import androidx.compose.foundation.shape.RoundedCornerShape
17
17
  import androidx.compose.foundation.text.BasicTextField
18
+ import androidx.compose.foundation.text.KeyboardActions
18
19
  import androidx.compose.foundation.text.KeyboardOptions
19
20
  import androidx.compose.material3.CircularProgressIndicator
20
21
  import androidx.compose.runtime.Composable
@@ -29,6 +30,7 @@ import androidx.compose.ui.focus.onFocusChanged
29
30
  import androidx.compose.ui.graphics.Color
30
31
  import androidx.compose.ui.text.TextStyle
31
32
  import androidx.compose.ui.text.input.KeyboardType
33
+ import androidx.compose.ui.text.style.TextOverflow
32
34
  import androidx.compose.ui.unit.dp
33
35
  import androidx.compose.ui.unit.sp
34
36
  import vn.momo.kits.const.AppTheme
@@ -44,6 +46,7 @@ fun RenderRightIconSearch(
44
46
  icon: String,
45
47
  color: Color,
46
48
  onClick: () -> Unit,
49
+ iconModifier: Modifier = Modifier
47
50
  ) {
48
51
  if (loading) {
49
52
  Box(Modifier.padding(horizontal = Spacing.S)) {
@@ -64,7 +67,7 @@ fun RenderRightIconSearch(
64
67
  source = icon,
65
68
  color = color,
66
69
  size = 24.dp,
67
- modifier = Modifier.padding(start = Spacing.S, end = 0.dp).clickable(
70
+ modifier = iconModifier.padding(start = Spacing.S, end = 0.dp).clickable(
68
71
  onClick = onClick,
69
72
  interactionSource = remember { MutableInteractionSource() },
70
73
  indication = null
@@ -90,6 +93,12 @@ data class InputSearchProps(
90
93
  val fontWeight: InputFontWeight = InputFontWeight.REGULAR,
91
94
  val keyboardType: KeyboardType = KeyboardType.Text,
92
95
  val backgroundColor: Color = Colors.black_01,
96
+ val clearCondition: (() -> Boolean)? = null,
97
+ val keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
98
+ val keyboardActions: KeyboardActions = KeyboardActions.Default,
99
+ val modifier: Modifier = Modifier,
100
+ val iconModifier: Modifier = Modifier,
101
+ val onClearPress: () -> Unit = {}
93
102
  )
94
103
 
95
104
  @Composable
@@ -98,7 +107,6 @@ fun InputSearch(
98
107
  text = remember { mutableStateOf("") },
99
108
  iconColor = AppTheme.current.colors.text.default
100
109
  ),
101
-
102
110
  ) {
103
111
  var isFocused by remember { mutableStateOf(false) }
104
112
  var isBlurred = false
@@ -124,8 +132,9 @@ fun InputSearch(
124
132
  lineHeight = 20.sp,
125
133
  fontWeight = inputSearchProps.fontWeight.value
126
134
  ),
127
- keyboardOptions = KeyboardOptions.Default.copy(keyboardType = inputSearchProps.keyboardType),
128
- modifier = Modifier.height(36.dp).onFocusChanged {
135
+ keyboardOptions = inputSearchProps.keyboardOptions.copy(keyboardType = inputSearchProps.keyboardType),
136
+ keyboardActions = inputSearchProps.keyboardActions,
137
+ modifier = inputSearchProps.modifier.height(36.dp).onFocusChanged {
129
138
  isFocused = it.isFocused
130
139
  if (it.isFocused) {
131
140
  inputSearchProps.onFocus()
@@ -137,7 +146,12 @@ fun InputSearch(
137
146
  decorationBox = { innerTextField ->
138
147
  Row(verticalAlignment = Alignment.CenterVertically) {
139
148
  Row(
140
- modifier = Modifier.weight(inputSearchProps.showButtonText.ifTrue(8f, 1f))
149
+ modifier = Modifier.weight(
150
+ inputSearchProps.showButtonText.ifTrue(
151
+ 8f,
152
+ 1f
153
+ )
154
+ )
141
155
  .background(
142
156
  inputSearchProps.backgroundColor,
143
157
  RoundedCornerShape(Radius.XL)
@@ -152,7 +166,6 @@ fun InputSearch(
152
166
  ),
153
167
  verticalAlignment = Alignment.CenterVertically
154
168
  ) {
155
- //leading icon
156
169
  Icon(
157
170
  source = "navigation_search",
158
171
  modifier = Modifier.padding(end = Spacing.XS),
@@ -168,12 +181,14 @@ fun InputSearch(
168
181
  lineHeight = 24.sp,
169
182
  fontWeight = inputSearchProps.fontWeight.value
170
183
  ),
171
- color = placeholderColor
184
+ maxLines = 1,
185
+ color = placeholderColor,
186
+ overflow = TextOverflow.Ellipsis
172
187
  )
173
188
  }
174
189
  innerTextField()
175
190
  }
176
- if (isFocused && inputSearchProps.text.value.isNotEmpty()) {
191
+ if (inputSearchProps.clearCondition?.invoke() == true || (isFocused && inputSearchProps.text.value.isNotEmpty())) {
177
192
  Row {
178
193
  Spacer(Modifier.width(Spacing.XS))
179
194
  Icon(
@@ -181,7 +196,10 @@ fun InputSearch(
181
196
  size = 16.dp,
182
197
  color = AppTheme.current.colors.text.hint,
183
198
  modifier = Modifier.clickable(
184
- onClick = { inputSearchProps.text.value = "" },
199
+ onClick = {
200
+ inputSearchProps.text.value = ""
201
+ inputSearchProps.onClearPress.invoke()
202
+ },
185
203
  interactionSource = remember { MutableInteractionSource() },
186
204
  indication = null
187
205
  )
@@ -192,7 +210,8 @@ fun InputSearch(
192
210
  inputSearchProps.loading,
193
211
  inputSearchProps.icon,
194
212
  iconTintColor,
195
- inputSearchProps.onRightIconPressed
213
+ inputSearchProps.onRightIconPressed,
214
+ iconModifier = inputSearchProps.iconModifier
196
215
  )
197
216
  }
198
217
  }
@@ -5,34 +5,77 @@ public struct Checkbox: View{
5
5
  @Binding var checked: Bool
6
6
  var disabled: Bool
7
7
  var onChange: ((Bool)->Void)?
8
-
9
- public init(_ checked: Binding<Bool>,disabled: Bool = false, onChange: ((Bool)->Void)? = nil){
8
+ var indeterminate: Bool
9
+ var title: String
10
+
11
+
12
+ public init(_ checked: Binding<Bool>,disabled: Bool = false, onChange: ( (Bool) -> Void)?,
13
+ indeterminate: Bool = false,
14
+ title: String = ""){
10
15
  self._checked = checked
11
- self.onChange = onChange
12
16
  self.disabled = disabled
17
+ self.onChange = onChange
18
+ self.indeterminate = indeterminate
19
+ self.title = title
13
20
  }
14
-
21
+
15
22
  func onCheck(){
16
23
  checked.toggle()
17
24
  onChange?(checked)
18
25
  }
19
-
20
- public var body: some View{
21
- return SwiftUI.Button(action: onCheck) {
22
- HStack {
23
- if (checked) {
24
- Image(systemName: "checkmark.square.fill")
26
+
27
+ public var body: some View {
28
+ HStack(spacing: Spacing.S) {
29
+ // Checkbox
30
+ ZStack {
31
+ RoundedRectangle(cornerRadius: Radius.XS)
32
+ .fill(backgroundColor)
33
+ .frame(width: 20, height: 20)
34
+ .overlay(
35
+ RoundedRectangle(cornerRadius: Radius.XS)
36
+ .stroke(borderColor, lineWidth: Spacing.XXS)
37
+ )
38
+
39
+ if checked {
40
+ Image(systemName: indeterminate ? "minus" : "checkmark")
25
41
  .resizable()
26
- .foregroundColor(disabled ? Colors.black07 : Colors.primary)
27
- .frame(width: 24, height: 24)
42
+ .foregroundColor(Colors.black01)
43
+ .frame(width: 12, height: 12)
28
44
  }
29
- }.frame(width: 24, height: 24)
30
- .overlay(RoundedRectangle(cornerRadius: 4).stroke(Colors.black20,lineWidth: checked ? 0 : 1))
31
- .background(Colors.black01)
32
-
45
+ }
46
+ .onTapGesture {
47
+ if !disabled {
48
+ onChange?(checked)
49
+ }
50
+ }
51
+
52
+ // Title
53
+ if !title.isEmpty {
54
+ Text(title)
55
+ .font(.description1)
56
+ }
33
57
  }
34
- .opacity(disabled ? 0.4 : 1)
35
- .disabled(disabled)
36
58
  }
37
-
59
+
60
+ private var borderColor: Color {
61
+ if disabled {
62
+ return Colors.black03
63
+ } else if checked {
64
+ return Colors.primary
65
+ } else {
66
+ return Colors.text
67
+ }
68
+ }
69
+
70
+ private var backgroundColor: Color {
71
+ if disabled && checked {
72
+ return Colors.pink08
73
+ } else if checked {
74
+ return Colors.primary
75
+ } else {
76
+ return Colors.black01
77
+ }
78
+ }
79
+
80
+
38
81
  }
@@ -0,0 +1,53 @@
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)
48
+ .frame(width: size, height: size)
49
+ .foregroundColor(color)
50
+ }
51
+ }
52
+ }
53
+
@@ -71,12 +71,22 @@ 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?
74
84
 
75
85
  func onCancel(){
76
86
  self.value.removeAll()
77
87
  }
78
88
 
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){
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){
80
90
  self.placeholder = placeholder
81
91
  self.floatingValue = floatingValue
82
92
  self.errorMessage = errorMessage
@@ -86,6 +96,16 @@ public struct Input: View {
86
96
  self.rightIcon = rightIcon
87
97
  self.floatingIcon = floatingIcon
88
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
89
109
  }
90
110
 
91
111
  func onChangeText(value: String){
@@ -93,57 +113,95 @@ public struct Input: View {
93
113
  }
94
114
 
95
115
  public var body: some View {
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)
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)
115
121
  }
116
122
 
117
- rightIcon
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
+ }
118
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
119
148
  }
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)
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
+
130
169
  }
131
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
+ }
132
181
  }
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)
144
- }
145
- if (!floatingValue.isEmpty) {FloatingComponent(floatingValue, floatingIcon: floatingIcon)}
146
- }.padding(.bottom, 8)
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)
147
192
  }
148
-
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
149
207
  }
@@ -0,0 +1,182 @@
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
+
@@ -0,0 +1,242 @@
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
+
@@ -4,18 +4,61 @@ public extension Font {
4
4
  static func appFont(size: CGFloat) -> Font {
5
5
  return Font.custom("SFProText", size: size)
6
6
  }
7
-
8
- static let h1 = appFont(size: 36).weight(.semibold)
7
+
8
+ // New supported typography styles
9
+ static let headline_default_bold = appFont(size: 24).weight(.bold)
10
+ static let header_m_bold = appFont(size: 18).weight(.bold)
11
+ static let header_default_bold = appFont(size: 16).weight(.bold)
12
+ static let header_s_semibold = appFont(size: 14).weight(.semibold)
13
+ static let header_xs_semibold = appFont(size: 12).weight(.semibold)
14
+ static let body_default_regular = appFont(size: 14).weight(.regular)
15
+ static let description_default_regular = appFont(size: 12).weight(.regular)
16
+ static let description_xs_regular = appFont(size: 10).weight(.regular)
17
+ static let label_default_medium = appFont(size: 14).weight(.medium)
18
+ static let label_s_medium = appFont(size: 12).weight(.medium)
19
+ static let label_xs_medium = appFont(size: 10).weight(.medium)
20
+ static let action_default_bold = appFont(size: 16).weight(.bold)
21
+ static let action_s_bold = appFont(size: 14).weight(.bold)
22
+ static let action_xs_bold = appFont(size: 12).weight(.bold)
23
+ static let action_xxs_bold = appFont(size: 10).weight(.bold)
24
+
25
+ // Legacy styles
26
+ static let headline_default = appFont(size: 28).weight(.semibold)
27
+ static let headline_s = appFont(size: 24).weight(.semibold)
28
+ static let headline_l = appFont(size: 32).weight(.semibold)
29
+ static let headline_xl = appFont(size: 36).weight(.semibold)
30
+ static let title_default = appFont(size: 20).weight(.bold)
31
+ static let title_xs = appFont(size: 16).weight(.bold)
32
+ static let title_s = appFont(size: 18).weight(.bold)
33
+ static let header_default = appFont(size: 15).weight(.semibold)
34
+ static let header_xs = appFont(size: 12).weight(.semibold)
35
+ static let header_s = appFont(size: 14).weight(.semibold)
36
+ static let paragraph_default = appFont(size: 15).weight(.regular)
37
+ static let paragraph_bold = appFont(size: 15).weight(.bold)
38
+ static let description_default = appFont(size: 14).weight(.regular)
39
+ static let description_xs = appFont(size: 10).weight(.regular)
40
+ static let description_s = appFont(size: 12).weight(.regular)
41
+ static let label_default = appFont(size: 14).weight(.medium)
42
+ static let label_xxs = appFont(size: 8).weight(.medium)
43
+ static let label_xs = appFont(size: 10).weight(.medium)
44
+ static let label_s = appFont(size: 12).weight(.medium)
45
+ static let action_default = appFont(size: 16).weight(.bold)
46
+ static let action_xxs = appFont(size: 10).weight(.bold)
47
+ static let action_xs = appFont(size: 12).weight(.bold)
48
+ static let action_s = appFont(size: 15).weight(.bold)
49
+
50
+ // deprecated
51
+ static let h1 = appFont(size: 36).weight(.semibold) //headline_xl
9
52
  static let h2 = appFont(size: 32).weight(.semibold)
10
53
  static let h3 = appFont(size: 28).weight(.semibold)
11
54
  static let h4 = appFont(size: 24).weight(.semibold)
12
55
  static let title1 = appFont(size: 20).weight(.bold)
13
56
  static let title2 = appFont(size: 18).weight(.bold)
14
57
  static let title3 = appFont(size: 16).weight(.bold)
15
- static let headerText1 = appFont(size: 15).weight(.semibold)
58
+ static let headerText1 = appFont(size: 15).weight(.semibold) //header_default
16
59
  static let headerText2 = appFont(size: 14).weight(.semibold)
17
60
  static let headerText3 = appFont(size: 12).weight(.semibold)
18
- static let paragraph = appFont(size: 15).weight(.regular)
61
+ static let paragraph = appFont(size: 15).weight(.regular) //paragraph_default
19
62
  static let description1 = appFont(size: 14).weight(.regular)
20
63
  static let description2 = appFont(size: 12).weight(.regular)
21
64
  static let description3 = appFont(size: 10).weight(.regular)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.89.33",
3
+ "version": "0.110.1-beta.5",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},