@momo-kits/native-kits 0.152.4-beta.9 → 0.152.4-scale.3
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/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +246 -78
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +3 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +21 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +12 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +22 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +6 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +4 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +19 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +24 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +25 -18
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +42 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +106 -36
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScaleSizeScope.kt +8 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +34 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +11 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +125 -0
- package/ios/Badge/Badge.swift +0 -6
- package/ios/Badge/BadgeRibbon.swift +77 -9
- package/ios/Button/Button.swift +7 -7
- package/local.properties +8 -0
- package/package.json +1 -1
|
@@ -115,11 +115,11 @@ internal fun StackScreen(
|
|
|
115
115
|
HeaderBackground()
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
Box(Modifier.zIndex(
|
|
118
|
+
Box(Modifier.zIndex(5f)) {
|
|
119
119
|
Header()
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
Column (Modifier.zIndex(
|
|
122
|
+
Column (Modifier.zIndex(6f)) {
|
|
123
123
|
SearchAnimated(isScrollInProgress = scrollInProcess)
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -127,14 +127,15 @@ internal fun StackScreen(
|
|
|
127
127
|
MainContent(content = content)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
Box(Modifier.zIndex(
|
|
131
|
-
|
|
130
|
+
Box(Modifier.zIndex(4f).align(Alignment.BottomCenter)) {
|
|
131
|
+
FooterContent()
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
Box(Modifier.zIndex(
|
|
135
|
-
|
|
136
|
-
OverplayComponentRegistry.OverlayComponent()
|
|
134
|
+
Box(Modifier.zIndex(7f)){
|
|
135
|
+
FloatingContent()
|
|
137
136
|
}
|
|
137
|
+
|
|
138
|
+
OverplayView(bottomTabIndex = bottomTabIndex, id = id)
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
}
|
|
@@ -191,9 +192,9 @@ fun ColumnScope.MainContent(content: @Composable ()-> Unit){
|
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
if (options.footerComponent != null){
|
|
194
|
-
val
|
|
195
|
-
val
|
|
196
|
-
|
|
195
|
+
val footerHeight = LocalFooterHeightPx.current
|
|
196
|
+
val footerHeightDp = with(density) { footerHeight.value.toDp() }
|
|
197
|
+
Spacer(Modifier.height(footerHeightDp))
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
200
|
|
|
@@ -217,6 +218,29 @@ fun ScreenContent(content: @Composable () -> Unit){
|
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
@Composable
|
|
222
|
+
fun FooterContent(){
|
|
223
|
+
val options = LocalOptions.current
|
|
224
|
+
if (options.footerComponent != null){
|
|
225
|
+
val isKeyboardVisible = isKeyboardVisible()
|
|
226
|
+
val bottomPadding = min(AppNavigationBar.current, if (isKeyboardVisible) 0.dp else 21.dp)
|
|
227
|
+
Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@Composable
|
|
232
|
+
fun OverplayView(bottomTabIndex: Int, id: Int){
|
|
233
|
+
val overplayType = OverplayComponentRegistry.getOverplayType()
|
|
234
|
+
|
|
235
|
+
if (overplayType != null) {
|
|
236
|
+
Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 8f).fillMaxSize()){
|
|
237
|
+
if (bottomTabIndex != -1) return@Box
|
|
238
|
+
if (OverplayComponentRegistry.currentRootId() != id) return@Box
|
|
239
|
+
OverplayComponentRegistry.OverlayComponent()
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
220
244
|
@Composable
|
|
221
245
|
fun Footer(footerComponent: @Composable (() -> Unit)?, bottomPadding: Dp) {
|
|
222
246
|
if (footerComponent == null) return
|
|
@@ -4,6 +4,7 @@ import androidx.compose.animation.core.FastOutSlowInEasing
|
|
|
4
4
|
import androidx.compose.animation.core.animateDpAsState
|
|
5
5
|
import androidx.compose.animation.core.tween
|
|
6
6
|
import androidx.compose.foundation.background
|
|
7
|
+
import androidx.compose.foundation.border
|
|
7
8
|
import androidx.compose.foundation.layout.Arrangement
|
|
8
9
|
import androidx.compose.foundation.layout.Box
|
|
9
10
|
import androidx.compose.foundation.layout.Column
|
|
@@ -39,6 +40,7 @@ import vn.momo.kits.const.Colors
|
|
|
39
40
|
import vn.momo.kits.const.Radius
|
|
40
41
|
import vn.momo.kits.const.Spacing
|
|
41
42
|
import vn.momo.kits.const.Typography
|
|
43
|
+
import vn.momo.kits.const.scaleSize
|
|
42
44
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
43
45
|
import vn.momo.kits.platform.getScreenDimensions
|
|
44
46
|
|
|
@@ -71,6 +73,7 @@ fun BottomTabBar(
|
|
|
71
73
|
animationSpec = tween(durationMillis = 250, easing = FastOutSlowInEasing),
|
|
72
74
|
label = "IndicatorX"
|
|
73
75
|
)
|
|
76
|
+
val bottomTabBarHeight = scaleSize(BOTTOM_TAB_BAR_HEIGHT.toFloat())
|
|
74
77
|
|
|
75
78
|
Box(
|
|
76
79
|
contentAlignment = Alignment.BottomCenter
|
|
@@ -156,17 +159,15 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
|
156
159
|
) {
|
|
157
160
|
Icon(
|
|
158
161
|
source = item.icon,
|
|
162
|
+
modifier = Modifier.weight(1f),
|
|
159
163
|
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
overflow = TextOverflow.Ellipsis
|
|
168
|
-
)
|
|
169
|
-
}
|
|
164
|
+
Text(
|
|
165
|
+
text = item.label,
|
|
166
|
+
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint,
|
|
167
|
+
style = Typography.labelXsMedium,
|
|
168
|
+
maxLines = 1,
|
|
169
|
+
overflow = TextOverflow.Ellipsis
|
|
170
|
+
)
|
|
170
171
|
}
|
|
171
172
|
if(item.badgeLabel != null){
|
|
172
173
|
Box(modifier = Modifier
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.tween
|
|
5
|
+
import androidx.compose.foundation.layout.Box
|
|
6
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
7
|
+
import androidx.compose.foundation.layout.offset
|
|
8
|
+
import androidx.compose.runtime.Composable
|
|
9
|
+
import androidx.compose.runtime.DisposableEffect
|
|
10
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
11
|
+
import androidx.compose.runtime.getValue
|
|
12
|
+
import androidx.compose.runtime.mutableStateOf
|
|
13
|
+
import androidx.compose.runtime.remember
|
|
14
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
15
|
+
import androidx.compose.runtime.setValue
|
|
16
|
+
import androidx.compose.ui.Modifier
|
|
17
|
+
import androidx.compose.ui.layout.onGloballyPositioned
|
|
18
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
19
|
+
import androidx.compose.ui.unit.IntOffset
|
|
20
|
+
import androidx.compose.ui.unit.dp
|
|
21
|
+
import androidx.compose.ui.unit.min
|
|
22
|
+
import kotlinx.coroutines.delay
|
|
23
|
+
import kotlinx.coroutines.launch
|
|
24
|
+
import vn.momo.kits.const.AppNavigationBar
|
|
25
|
+
import vn.momo.kits.navigation.LocalFooterHeightPx
|
|
26
|
+
import vn.momo.kits.navigation.LocalNavigator
|
|
27
|
+
import vn.momo.kits.navigation.LocalOptions
|
|
28
|
+
import vn.momo.kits.navigation.OverplayComponentRegistry
|
|
29
|
+
|
|
30
|
+
sealed class SnackBar(open val duration: Long? = null) {
|
|
31
|
+
data class Custom(
|
|
32
|
+
val content: @Composable () -> Unit,
|
|
33
|
+
override val duration: Long? = 3000L
|
|
34
|
+
) : SnackBar(duration)
|
|
35
|
+
|
|
36
|
+
data class Toast(
|
|
37
|
+
override val duration: Long? = 3000L
|
|
38
|
+
) : SnackBar(duration)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Composable
|
|
42
|
+
fun SnackBar(
|
|
43
|
+
data: SnackBar,
|
|
44
|
+
onDismiss: (() -> Unit)?
|
|
45
|
+
) {
|
|
46
|
+
val navigator = LocalNavigator.current
|
|
47
|
+
val options = LocalOptions.current
|
|
48
|
+
val density = LocalDensity.current
|
|
49
|
+
val footerHeightPxState = LocalFooterHeightPx.current
|
|
50
|
+
val navigationBar = AppNavigationBar.current
|
|
51
|
+
|
|
52
|
+
val footerHeight = if (options.footerComponent != null) {
|
|
53
|
+
footerHeightPxState.value
|
|
54
|
+
} else {
|
|
55
|
+
with(density){ min(navigationBar, 21.dp).toPx() }
|
|
56
|
+
}.toInt()
|
|
57
|
+
|
|
58
|
+
var startPosition by remember { mutableStateOf(Float.MAX_VALUE) }
|
|
59
|
+
val targetPosition = 0f
|
|
60
|
+
|
|
61
|
+
var offsetY by remember { mutableStateOf(Animatable(startPosition)) }
|
|
62
|
+
val coroutineScope = rememberCoroutineScope()
|
|
63
|
+
|
|
64
|
+
suspend fun openEvent() {
|
|
65
|
+
offsetY.snapTo(startPosition)
|
|
66
|
+
offsetY.animateTo(
|
|
67
|
+
targetValue = targetPosition,
|
|
68
|
+
animationSpec = tween(
|
|
69
|
+
durationMillis = 350,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fun closeEvent() {
|
|
75
|
+
coroutineScope.launch {
|
|
76
|
+
offsetY.animateTo(
|
|
77
|
+
targetValue = startPosition,
|
|
78
|
+
animationSpec = tween(
|
|
79
|
+
durationMillis = 200,
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
navigator.hideSnackBar()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
LaunchedEffect(startPosition) {
|
|
87
|
+
if (startPosition != Float.MAX_VALUE){
|
|
88
|
+
openEvent()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
LaunchedEffect(data.duration) {
|
|
93
|
+
val duration = data.duration
|
|
94
|
+
if (duration != null) {
|
|
95
|
+
delay(duration)
|
|
96
|
+
navigator.hideSnackBar()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
DisposableEffect(Unit) {
|
|
101
|
+
OverplayComponentRegistry.bindClose {
|
|
102
|
+
closeEvent()
|
|
103
|
+
}
|
|
104
|
+
onDispose {
|
|
105
|
+
onDismiss?.invoke()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
Box(
|
|
110
|
+
modifier = Modifier
|
|
111
|
+
.offset { IntOffset(0, offsetY.value.toInt() - footerHeight) }
|
|
112
|
+
.onGloballyPositioned {
|
|
113
|
+
if (startPosition != it.size.height.toFloat()) {
|
|
114
|
+
startPosition = it.size.height.toFloat()
|
|
115
|
+
offsetY = Animatable(startPosition)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
.fillMaxWidth()
|
|
119
|
+
) {
|
|
120
|
+
when (data) {
|
|
121
|
+
is SnackBar.Custom -> data.content()
|
|
122
|
+
is SnackBar.Toast -> {}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
package/ios/Badge/Badge.swift
CHANGED
|
@@ -64,12 +64,6 @@ public struct Badge: View {
|
|
|
64
64
|
.stroke(Colors.black01, lineWidth: 1)
|
|
65
65
|
)
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
// Helper function for scaling sizes
|
|
69
|
-
// TODO: Implement proper scaling logic based on your design system
|
|
70
|
-
private func scaleSize(_ size: CGFloat) -> CGFloat {
|
|
71
|
-
return size
|
|
72
|
-
}
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
// MARK: - Preview
|
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
import SwiftUI
|
|
2
2
|
|
|
3
|
+
// MARK: - Custom Shape for Rounded Corners
|
|
4
|
+
struct RoundedCorners: Shape {
|
|
5
|
+
var topLeft: CGFloat = 0.0
|
|
6
|
+
var topRight: CGFloat = 0.0
|
|
7
|
+
var bottomLeft: CGFloat = 0.0
|
|
8
|
+
var bottomRight: CGFloat = 0.0
|
|
9
|
+
|
|
10
|
+
func path(in rect: CGRect) -> Path {
|
|
11
|
+
var path = Path()
|
|
12
|
+
|
|
13
|
+
let width = rect.size.width
|
|
14
|
+
let height = rect.size.height
|
|
15
|
+
|
|
16
|
+
// Start from top left
|
|
17
|
+
path.move(to: CGPoint(x: topLeft, y: 0))
|
|
18
|
+
|
|
19
|
+
// Top edge and top right corner
|
|
20
|
+
path.addLine(to: CGPoint(x: width - topRight, y: 0))
|
|
21
|
+
if topRight > 0 {
|
|
22
|
+
path.addArc(
|
|
23
|
+
center: CGPoint(x: width - topRight, y: topRight),
|
|
24
|
+
radius: topRight,
|
|
25
|
+
startAngle: Angle(degrees: -90),
|
|
26
|
+
endAngle: Angle(degrees: 0),
|
|
27
|
+
clockwise: false
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Right edge and bottom right corner
|
|
32
|
+
path.addLine(to: CGPoint(x: width, y: height - bottomRight))
|
|
33
|
+
if bottomRight > 0 {
|
|
34
|
+
path.addArc(
|
|
35
|
+
center: CGPoint(x: width - bottomRight, y: height - bottomRight),
|
|
36
|
+
radius: bottomRight,
|
|
37
|
+
startAngle: Angle(degrees: 0),
|
|
38
|
+
endAngle: Angle(degrees: 90),
|
|
39
|
+
clockwise: false
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Bottom edge and bottom left corner
|
|
44
|
+
path.addLine(to: CGPoint(x: bottomLeft, y: height))
|
|
45
|
+
if bottomLeft > 0 {
|
|
46
|
+
path.addArc(
|
|
47
|
+
center: CGPoint(x: bottomLeft, y: height - bottomLeft),
|
|
48
|
+
radius: bottomLeft,
|
|
49
|
+
startAngle: Angle(degrees: 90),
|
|
50
|
+
endAngle: Angle(degrees: 180),
|
|
51
|
+
clockwise: false
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Left edge and top left corner
|
|
56
|
+
path.addLine(to: CGPoint(x: 0, y: topLeft))
|
|
57
|
+
if topLeft > 0 {
|
|
58
|
+
path.addArc(
|
|
59
|
+
center: CGPoint(x: topLeft, y: topLeft),
|
|
60
|
+
radius: topLeft,
|
|
61
|
+
startAngle: Angle(degrees: 180),
|
|
62
|
+
endAngle: Angle(degrees: 270),
|
|
63
|
+
clockwise: false
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
path.closeSubpath()
|
|
68
|
+
return path
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
3
72
|
public enum RibbonPosition {
|
|
4
73
|
case topLeft
|
|
5
74
|
case topRight
|
|
@@ -76,14 +145,13 @@ public struct BadgeRibbon: View {
|
|
|
76
145
|
.frame(height: RibbonConstants.roundHeight)
|
|
77
146
|
.padding(.trailing, RibbonConstants.roundPaddingEnd)
|
|
78
147
|
.background(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)
|
|
148
|
+
RoundedCorners(
|
|
149
|
+
topLeft: 0,
|
|
150
|
+
topRight: RibbonConstants.roundRightRadius,
|
|
151
|
+
bottomLeft: 0,
|
|
152
|
+
bottomRight: RibbonConstants.roundRightRadius
|
|
153
|
+
)
|
|
154
|
+
.fill(backgroundColor)
|
|
87
155
|
)
|
|
88
156
|
}
|
|
89
157
|
|
|
@@ -139,7 +207,7 @@ private struct RibbonConstants {
|
|
|
139
207
|
static let ribbonHeight: CGFloat = 20
|
|
140
208
|
static let roundHeight: CGFloat = 16
|
|
141
209
|
static let skewBodyHeight: CGFloat = 16
|
|
142
|
-
static let roundRightRadius: CGFloat =
|
|
210
|
+
static let roundRightRadius: CGFloat = 8
|
|
143
211
|
static let roundPaddingEnd: CGFloat = 6
|
|
144
212
|
static let skewTailWidth: CGFloat = 8
|
|
145
213
|
static let skewTailHeight: CGFloat = 16
|
package/ios/Button/Button.swift
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
-
import SwiftUI
|
|
3
2
|
import Lottie
|
|
3
|
+
import SwiftUI
|
|
4
4
|
|
|
5
5
|
// MARK: - ButtonType
|
|
6
6
|
|
|
@@ -33,7 +33,7 @@ public extension ButtonType {
|
|
|
33
33
|
func backgroundColor(loading: Bool) -> Color {
|
|
34
34
|
switch self {
|
|
35
35
|
case .disabled: return Colors.black05.opacity(loading ? 0.75 : 1)
|
|
36
|
-
case .primary:
|
|
36
|
+
case .primary: return Colors.primary.opacity(loading ? 0.75 : 1)
|
|
37
37
|
case .secondary: return Colors.card.opacity(loading ? 0.75 : 1)
|
|
38
38
|
case .outline: return Colors.card.opacity(loading ? 0.75 : 1)
|
|
39
39
|
case .tonal: return Colors.primaryLight.opacity(loading ? 0.75 : 1)
|
|
@@ -116,13 +116,13 @@ extension ButtonSize {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
public struct Button: View {
|
|
119
|
-
|
|
120
119
|
var title: String
|
|
121
120
|
var action: () -> Void
|
|
122
121
|
var type: ButtonType
|
|
123
122
|
var size: ButtonSize
|
|
124
123
|
var iconLeft: AnyView?
|
|
125
124
|
var iconRight: AnyView?
|
|
125
|
+
var isFull: Bool
|
|
126
126
|
var loading: Bool
|
|
127
127
|
|
|
128
128
|
public init(
|
|
@@ -132,6 +132,7 @@ public struct Button: View {
|
|
|
132
132
|
size: ButtonSize = .large,
|
|
133
133
|
iconLeft: AnyView? = nil,
|
|
134
134
|
iconRight: AnyView? = nil,
|
|
135
|
+
isFull: Bool = true,
|
|
135
136
|
loading: Bool = false
|
|
136
137
|
) {
|
|
137
138
|
self.title = title
|
|
@@ -140,6 +141,7 @@ public struct Button: View {
|
|
|
140
141
|
self.size = size
|
|
141
142
|
self.iconLeft = iconLeft
|
|
142
143
|
self.iconRight = iconRight
|
|
144
|
+
self.isFull = isFull
|
|
143
145
|
self.loading = loading
|
|
144
146
|
}
|
|
145
147
|
|
|
@@ -156,7 +158,6 @@ public struct Button: View {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
public var body: some View {
|
|
159
|
-
|
|
160
161
|
let loadingOnLeft = shouldLoadingOnLeft(iconLeft, iconRight)
|
|
161
162
|
|
|
162
163
|
let bg = type.backgroundColor(loading: loading)
|
|
@@ -165,12 +166,11 @@ public struct Button: View {
|
|
|
165
166
|
let borderWidth = type.borderWidth
|
|
166
167
|
|
|
167
168
|
SwiftUI.Button(action: {
|
|
168
|
-
if !loading
|
|
169
|
+
if !loading, type != .disabled {
|
|
169
170
|
action()
|
|
170
171
|
}
|
|
171
172
|
}) {
|
|
172
173
|
HStack(spacing: size.iconSpacing) {
|
|
173
|
-
|
|
174
174
|
if loading && loadingOnLeft {
|
|
175
175
|
LottieView(name: "lottie_circle_loader", loopMode: .loop)
|
|
176
176
|
.frame(width: size.iconSize, height: size.iconSize)
|
|
@@ -195,7 +195,7 @@ public struct Button: View {
|
|
|
195
195
|
iconRight.frame(width: size.iconSize, height: size.iconSize)
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
.frame(maxWidth: .infinity)
|
|
198
|
+
.frame(maxWidth: isFull ? .infinity : nil)
|
|
199
199
|
.padding(.horizontal, size.padding)
|
|
200
200
|
.frame(height: size.height)
|
|
201
201
|
.background(bg)
|
package/local.properties
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
+
# as it contains information specific to your local configuration.
|
|
3
|
+
#
|
|
4
|
+
# Location of the SDK. This is only used by Gradle.
|
|
5
|
+
# For customization when using a Version Control System, please read the
|
|
6
|
+
# header note.
|
|
7
|
+
#Wed Sep 10 18:28:25 ICT 2025
|
|
8
|
+
sdk.dir=/Users/phuc/Library/Android/sdk
|