@momo-kits/native-kits 0.157.1-skill.3-debug → 0.157.1-skill.6-debug
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/.claude/skills/momo-native-kits-skills/README.md +52 -0
- package/.claude/skills/momo-native-kits-skills/SKILL.md +32 -0
- package/.claude/skills/momo-native-kits-skills/data-display/SKILL.md +42 -0
- package/.claude/skills/momo-native-kits-skills/feedback/SKILL.md +43 -0
- package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/feedback}/references/popup.md +3 -10
- package/.claude/skills/momo-native-kits-skills/form-controls/SKILL.md +42 -0
- package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/form-controls}/references/button.md +2 -3
- package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/form-controls}/references/input.md +3 -7
- package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/form-controls}/references/radio.md +9 -9
- package/.claude/skills/momo-native-kits-skills/layout/SKILL.md +39 -0
- package/.claude/skills/momo-native-kits-skills/navigation/SKILL.md +38 -0
- package/.claude/skills/momo-native-kits-skills/output/test-report.json +12 -0
- package/.claude/skills/momo-native-kits-skills/output/validation-result.json +108 -0
- package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills}/references/constants.md +81 -6
- package/.claude/skills/momo-native-kits-skills/references/design-guidelines.md +130 -0
- package/.claude/skills/momo-native-kits-skills/references/developer/android-compose.md +29 -0
- package/.claude/skills/momo-native-kits-skills/references/developer/code-convention.md +118 -0
- package/.claude/skills/momo-native-kits-skills/references/developer/compose-multiplatform.md +29 -0
- package/.claude/skills/momo-native-kits-skills/scripts/logger.js +63 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/badge.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/bottomtab.js +19 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/button.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/card.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/checkbox.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/chip.js +59 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/divider.js +19 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/global.js +61 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/index.js +54 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/input.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/navigation.js +48 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/popup.js +45 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/radio.js +105 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/skeleton.js +20 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/snackbar.js +32 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/state.js +21 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/switch.js +45 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/text.js +19 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/tooltip.js +45 -0
- package/.claude/skills/momo-native-kits-skills/scripts/rules/trustbanner.js +22 -0
- package/.claude/skills/momo-native-kits-skills/scripts/test-on-device.sh +117 -0
- package/.claude/skills/momo-native-kits-skills/scripts/test-runner.js +167 -0
- package/.claude/skills/momo-native-kits-skills/scripts/validate-kits.js +131 -0
- package/.momo-agent.json +13 -0
- package/compose/build.gradle.kts +1 -1
- package/gradle.properties +1 -1
- package/package.json +1 -1
- package/.claude/momo-native-kits-skill/SKILL.md +0 -51
- package/.claude/momo-native-kits-skill/evals/evals.json +0 -95
- package/.claude/momo-native-kits-skill/workspace/iteration-1/benchmark.json +0 -20
- package/.claude/momo-native-kits-skill/workspace/iteration-1/benchmark.md +0 -13
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-0-button/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-0-button/with_skill/outputs/ButtonExample.kt +0 -55
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-0-button/without_skill/outputs/ButtonExample.kt +0 -45
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-1-input/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-1-input/with_skill/outputs/InputPhoneExample.kt +0 -40
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-1-input/without_skill/outputs/InputPhoneExample.kt +0 -42
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-2-bottomtab/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-2-bottomtab/with_skill/outputs/BottomTabExample.kt +0 -236
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-2-bottomtab/without_skill/outputs/BottomTabExample.kt +0 -152
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-3-checkbox/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-3-checkbox/with_skill/outputs/CheckBoxExample.kt +0 -49
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-3-checkbox/without_skill/outputs/CheckBoxExample.kt +0 -123
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-4-datetimepicker/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-4-datetimepicker/with_skill/outputs/DateTimePickerExample.kt +0 -318
- package/.claude/momo-native-kits-skill/workspace/iteration-1/eval-4-datetimepicker/without_skill/outputs/DateTimePickerExample.kt +0 -330
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-card/with_skill/outputs/CardExample.kt +0 -124
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-card/without_skill/outputs/CardExample.kt +0 -71
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-loginform/with_skill/outputs/LoginFormExample.kt +0 -134
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-loginform/without_skill/outputs/LoginFormExample.kt +0 -199
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-navcontainer/with_skill/outputs/NavigationContainerExample.kt +0 -224
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-navcontainer/without_skill/outputs/NavigationContainerExample.kt +0 -225
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-popup/with_skill/outputs/PopupExample.kt +0 -79
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-popup/without_skill/outputs/PopupExample.kt +0 -169
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-setoptions/eval_metadata.json +0 -6
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-setoptions/with_skill/outputs/SetOptionsExample.kt +0 -255
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-setoptions/without_skill/outputs/SetOptionsExample.kt +0 -212
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-skeleton/with_skill/outputs/SkeletonExample.kt +0 -199
- package/.claude/momo-native-kits-skill/workspace/iteration-2/eval-skeleton/without_skill/outputs/SkeletonExample.kt +0 -229
- package/.claude/momo-native-kits-skill/workspace/iteration-3/benchmark.json +0 -20
- package/.claude/momo-native-kits-skill/workspace/iteration-3/benchmark.md +0 -13
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-button/eval_metadata.json +0 -22
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-button/with_skill/outputs/PrimaryButtonExample.kt +0 -38
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-button/with_skill/timing.json +0 -5
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-button/without_skill/outputs/PrimaryButtonExample.kt +0 -83
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-button/without_skill/timing.json +0 -5
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/eval_metadata.json +0 -22
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/with_skill/outputs/NavigationContainerExample.kt +0 -547
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/with_skill/timing.json +0 -5
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/without_skill/outputs/MoMoNavigationContainer.kt +0 -519
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/without_skill/timing.json +0 -5
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-setoptions/eval_metadata.json +0 -27
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-setoptions/with_skill/outputs/SetOptionsExample.kt +0 -429
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-setoptions/with_skill/timing.json +0 -5
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-setoptions/without_skill/outputs/SetOptionsExample.kt +0 -353
- package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-setoptions/without_skill/timing.json +0 -5
- package/.claude/settings.local.json +0 -41
- package/local.properties +0 -8
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/data-display}/references/badge.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/data-display}/references/chip.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/data-display}/references/skeleton.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/data-display}/references/text.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/feedback}/references/snackbar.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/feedback}/references/tooltip.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/feedback}/references/trustbanner.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/form-controls}/references/checkbox.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/form-controls}/references/switch.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/layout}/references/card.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/layout}/references/divider.md +0 -0
- /package/.claude/{momo-native-kits-skill → skills/momo-native-kits-skills/navigation}/references/navigation.md +0 -0
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
package com.example.datetimepicker
|
|
2
|
-
|
|
3
|
-
import android.app.DatePickerDialog
|
|
4
|
-
import android.app.TimePickerDialog
|
|
5
|
-
import androidx.compose.foundation.layout.Column
|
|
6
|
-
import androidx.compose.foundation.layout.Spacer
|
|
7
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
8
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
9
|
-
import androidx.compose.foundation.layout.height
|
|
10
|
-
import androidx.compose.foundation.layout.padding
|
|
11
|
-
import androidx.compose.material3.Button
|
|
12
|
-
import androidx.compose.material3.MaterialTheme
|
|
13
|
-
import androidx.compose.material3.OutlinedButton
|
|
14
|
-
import androidx.compose.material3.OutlinedTextField
|
|
15
|
-
import androidx.compose.material3.Scaffold
|
|
16
|
-
import androidx.compose.material3.Text
|
|
17
|
-
import androidx.compose.material3.TextButton
|
|
18
|
-
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
19
|
-
import androidx.compose.material3.TopAppBar
|
|
20
|
-
import androidx.compose.runtime.Composable
|
|
21
|
-
import androidx.compose.runtime.getValue
|
|
22
|
-
import androidx.compose.runtime.mutableStateOf
|
|
23
|
-
import androidx.compose.runtime.remember
|
|
24
|
-
import androidx.compose.runtime.setValue
|
|
25
|
-
import androidx.compose.ui.Modifier
|
|
26
|
-
import androidx.compose.ui.platform.LocalContext
|
|
27
|
-
import androidx.compose.ui.unit.dp
|
|
28
|
-
import java.text.SimpleDateFormat
|
|
29
|
-
import java.util.Calendar
|
|
30
|
-
import java.util.Date
|
|
31
|
-
import java.util.Locale
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* DateTimePicker Example in Jetpack Compose
|
|
35
|
-
*
|
|
36
|
-
* This example demonstrates different ways to use DatePicker and TimePicker
|
|
37
|
-
* dialogs in Android Jetpack Compose applications.
|
|
38
|
-
*/
|
|
39
|
-
@OptIn(ExperimentalMaterial3Api::class)
|
|
40
|
-
@Composable
|
|
41
|
-
fun DateTimePickerScreen() {
|
|
42
|
-
// State for selected date and time
|
|
43
|
-
var selectedDate by remember { mutableStateOf<Long?>(null) }
|
|
44
|
-
var selectedTime by remember { mutableStateOf<Long?>(null) }
|
|
45
|
-
|
|
46
|
-
// Formatters for displaying date and time
|
|
47
|
-
val dateFormatter = remember { SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()) }
|
|
48
|
-
val timeFormatter = remember { SimpleDateFormat("HH:mm", Locale.getDefault()) }
|
|
49
|
-
val dateTimeFormatter = remember { SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault()) }
|
|
50
|
-
|
|
51
|
-
// Calendar instance for dialogs
|
|
52
|
-
val calendar = remember { Calendar.getInstance() }
|
|
53
|
-
|
|
54
|
-
// Context for showing dialogs
|
|
55
|
-
val context = LocalContext.current
|
|
56
|
-
|
|
57
|
-
Scaffold(
|
|
58
|
-
topBar = {
|
|
59
|
-
TopAppBar(
|
|
60
|
-
title = { Text("DateTimePicker Example") }
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
) { paddingValues ->
|
|
64
|
-
Column(
|
|
65
|
-
modifier = Modifier
|
|
66
|
-
.fillMaxSize()
|
|
67
|
-
.padding(paddingValues)
|
|
68
|
-
.padding(16.dp)
|
|
69
|
-
) {
|
|
70
|
-
Text(
|
|
71
|
-
text = "Date & Time Selection",
|
|
72
|
-
style = MaterialTheme.typography.headlineSmall
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
Spacer(modifier = Modifier.height(24.dp))
|
|
76
|
-
|
|
77
|
-
// ===== Date Picker Example =====
|
|
78
|
-
Text(
|
|
79
|
-
text = "Date Picker",
|
|
80
|
-
style = MaterialTheme.typography.titleMedium
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
84
|
-
|
|
85
|
-
OutlinedTextField(
|
|
86
|
-
value = selectedDate?.let { dateFormatter.format(Date(it)) } ?: "",
|
|
87
|
-
onValueChange = { },
|
|
88
|
-
label = { Text("Select Date") },
|
|
89
|
-
readOnly = true,
|
|
90
|
-
modifier = Modifier.fillMaxWidth(),
|
|
91
|
-
trailingIcon = {
|
|
92
|
-
TextButton(onClick = {
|
|
93
|
-
// Show DatePickerDialog
|
|
94
|
-
val datePickerDialog = DatePickerDialog(
|
|
95
|
-
context,
|
|
96
|
-
{ _, year, month, dayOfMonth ->
|
|
97
|
-
calendar.set(year, month, dayOfMonth)
|
|
98
|
-
selectedDate = calendar.timeInMillis
|
|
99
|
-
},
|
|
100
|
-
calendar.get(Calendar.YEAR),
|
|
101
|
-
calendar.get(Calendar.MONTH),
|
|
102
|
-
calendar.get(Calendar.DAY_OF_MONTH)
|
|
103
|
-
)
|
|
104
|
-
datePickerDialog.show()
|
|
105
|
-
}) {
|
|
106
|
-
Text("Pick")
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
Spacer(modifier = Modifier.height(16.dp))
|
|
112
|
-
|
|
113
|
-
// ===== Time Picker Example =====
|
|
114
|
-
Text(
|
|
115
|
-
text = "Time Picker",
|
|
116
|
-
style = MaterialTheme.typography.titleMedium
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
120
|
-
|
|
121
|
-
OutlinedTextField(
|
|
122
|
-
value = selectedTime?.let {
|
|
123
|
-
val cal = Calendar.getInstance().apply { timeInMillis = it }
|
|
124
|
-
String.format(
|
|
125
|
-
Locale.getDefault(),
|
|
126
|
-
"%02d:%02d",
|
|
127
|
-
cal.get(Calendar.HOUR_OF_DAY),
|
|
128
|
-
cal.get(Calendar.MINUTE)
|
|
129
|
-
)
|
|
130
|
-
} ?: "",
|
|
131
|
-
onValueChange = { },
|
|
132
|
-
label = { Text("Select Time") },
|
|
133
|
-
readOnly = true,
|
|
134
|
-
modifier = Modifier.fillMaxWidth(),
|
|
135
|
-
trailingIcon = {
|
|
136
|
-
TextButton(onClick = {
|
|
137
|
-
// Show TimePickerDialog
|
|
138
|
-
val timePickerDialog = TimePickerDialog(
|
|
139
|
-
context,
|
|
140
|
-
{ _, hourOfDay, minute ->
|
|
141
|
-
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
|
|
142
|
-
calendar.set(Calendar.MINUTE, minute)
|
|
143
|
-
selectedTime = calendar.timeInMillis
|
|
144
|
-
},
|
|
145
|
-
calendar.get(Calendar.HOUR_OF_DAY),
|
|
146
|
-
calendar.get(Calendar.MINUTE),
|
|
147
|
-
true // 24-hour format
|
|
148
|
-
)
|
|
149
|
-
timePickerDialog.show()
|
|
150
|
-
}) {
|
|
151
|
-
Text("Pick")
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
Spacer(modifier = Modifier.height(16.dp))
|
|
157
|
-
|
|
158
|
-
// ===== Combined Date & Time Example =====
|
|
159
|
-
Text(
|
|
160
|
-
text = "Date & Time Picker",
|
|
161
|
-
style = MaterialTheme.typography.titleMedium
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
165
|
-
|
|
166
|
-
OutlinedTextField(
|
|
167
|
-
value = if (selectedDate != null && selectedTime != null) {
|
|
168
|
-
val combinedCal = Calendar.getInstance().apply {
|
|
169
|
-
timeInMillis = selectedDate!!
|
|
170
|
-
val timeCal = Calendar.getInstance().apply { timeInMillis = selectedTime!! }
|
|
171
|
-
set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY))
|
|
172
|
-
set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE))
|
|
173
|
-
}
|
|
174
|
-
dateTimeFormatter.format(Date(combinedCal.timeInMillis))
|
|
175
|
-
} else if (selectedDate != null) {
|
|
176
|
-
dateFormatter.format(Date(selectedDate!!))
|
|
177
|
-
} else {
|
|
178
|
-
""
|
|
179
|
-
},
|
|
180
|
-
onValueChange = { },
|
|
181
|
-
label = { Text("Select Date & Time") },
|
|
182
|
-
readOnly = true,
|
|
183
|
-
modifier = Modifier.fillMaxWidth(),
|
|
184
|
-
trailingIcon = {
|
|
185
|
-
TextButton(onClick = {
|
|
186
|
-
// First show DatePicker, then TimePicker
|
|
187
|
-
val datePickerDialog = DatePickerDialog(
|
|
188
|
-
context,
|
|
189
|
-
{ _, year, month, dayOfMonth ->
|
|
190
|
-
calendar.set(year, month, dayOfMonth)
|
|
191
|
-
selectedDate = calendar.timeInMillis
|
|
192
|
-
|
|
193
|
-
// After date is selected, show time picker
|
|
194
|
-
val timePickerDialog = TimePickerDialog(
|
|
195
|
-
context,
|
|
196
|
-
{ _, hourOfDay, minute ->
|
|
197
|
-
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
|
|
198
|
-
calendar.set(Calendar.MINUTE, minute)
|
|
199
|
-
selectedTime = calendar.timeInMillis
|
|
200
|
-
},
|
|
201
|
-
calendar.get(Calendar.HOUR_OF_DAY),
|
|
202
|
-
calendar.get(Calendar.MINUTE),
|
|
203
|
-
true
|
|
204
|
-
)
|
|
205
|
-
timePickerDialog.show()
|
|
206
|
-
},
|
|
207
|
-
calendar.get(Calendar.YEAR),
|
|
208
|
-
calendar.get(Calendar.MONTH),
|
|
209
|
-
calendar.get(Calendar.DAY_OF_MONTH)
|
|
210
|
-
)
|
|
211
|
-
datePickerDialog.show()
|
|
212
|
-
}) {
|
|
213
|
-
Text("Pick")
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
Spacer(modifier = Modifier.height(32.dp))
|
|
219
|
-
|
|
220
|
-
// ===== Display Selected Values =====
|
|
221
|
-
Text(
|
|
222
|
-
text = "Selected Values:",
|
|
223
|
-
style = MaterialTheme.typography.titleMedium
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
227
|
-
|
|
228
|
-
Text(
|
|
229
|
-
text = "Date: ${selectedDate?.let { dateFormatter.format(Date(it)) } ?: "Not selected"}"
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
Text(
|
|
233
|
-
text = "Time: ${selectedTime?.let {
|
|
234
|
-
val cal = Calendar.getInstance().apply { timeInMillis = it }
|
|
235
|
-
String.format(Locale.getDefault(), "%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE))
|
|
236
|
-
} ?: "Not selected"}"
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
Spacer(modifier = Modifier.height(24.dp))
|
|
240
|
-
|
|
241
|
-
// ===== Clear Button =====
|
|
242
|
-
OutlinedButton(
|
|
243
|
-
onClick = {
|
|
244
|
-
selectedDate = null
|
|
245
|
-
selectedTime = null
|
|
246
|
-
},
|
|
247
|
-
modifier = Modifier.fillMaxWidth()
|
|
248
|
-
) {
|
|
249
|
-
Text("Clear Selection")
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Alternative approach using Material3 DatePicker and TimePicker composables
|
|
257
|
-
* (Available in newer versions of Material3)
|
|
258
|
-
*/
|
|
259
|
-
@OptIn(ExperimentalMaterial3Api::class)
|
|
260
|
-
@Composable
|
|
261
|
-
fun DateTimePickerWithMaterial3(
|
|
262
|
-
onDateTimeSelected: (Long) -> Unit = {}
|
|
263
|
-
) {
|
|
264
|
-
// This requires Material3 1.1.0+ and shows inline pickers
|
|
265
|
-
// For full implementation, use the datePicker and timePicker state APIs
|
|
266
|
-
|
|
267
|
-
var showDatePicker by remember { mutableStateOf(false) }
|
|
268
|
-
var showTimePicker by remember { mutableStateOf(false) }
|
|
269
|
-
var selectedDateMillis by remember { mutableStateOf<Long?>(null) }
|
|
270
|
-
|
|
271
|
-
Column(
|
|
272
|
-
modifier = Modifier
|
|
273
|
-
.fillMaxSize()
|
|
274
|
-
.padding(16.dp)
|
|
275
|
-
) {
|
|
276
|
-
Button(
|
|
277
|
-
onClick = { showDatePicker = true },
|
|
278
|
-
modifier = Modifier.fillMaxWidth()
|
|
279
|
-
) {
|
|
280
|
-
Text("Show Date Picker Dialog")
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
284
|
-
|
|
285
|
-
Button(
|
|
286
|
-
onClick = { showTimePicker = true },
|
|
287
|
-
modifier = Modifier.fillMaxWidth(),
|
|
288
|
-
enabled = selectedDateMillis != null
|
|
289
|
-
) {
|
|
290
|
-
Text("Show Time Picker Dialog")
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Note: Material3 also provides DatePicker and TimePicker composables
|
|
294
|
-
// that can be used inline (not as dialogs) for more customization
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Example of custom DatePickerDialog styling
|
|
300
|
-
*/
|
|
301
|
-
@Composable
|
|
302
|
-
fun StyledDatePickerExample() {
|
|
303
|
-
val context = LocalContext.current
|
|
304
|
-
val calendar = remember { Calendar.getInstance() }
|
|
305
|
-
|
|
306
|
-
Button(
|
|
307
|
-
onClick = {
|
|
308
|
-
val dialog = DatePickerDialog(
|
|
309
|
-
context,
|
|
310
|
-
{ _, year, month, dayOfMonth ->
|
|
311
|
-
// Handle date selection
|
|
312
|
-
calendar.set(year, month, dayOfMonth)
|
|
313
|
-
println("Selected date: ${calendar.time}")
|
|
314
|
-
},
|
|
315
|
-
calendar.get(Calendar.YEAR),
|
|
316
|
-
calendar.get(Calendar.MONTH),
|
|
317
|
-
calendar.get(Calendar.DAY_OF_MONTH)
|
|
318
|
-
).apply {
|
|
319
|
-
// Customize dialog
|
|
320
|
-
datePicker.firstDayOfWeek = Calendar.MONDAY
|
|
321
|
-
// Set min/max date if needed
|
|
322
|
-
// datePicker.minDate = ...
|
|
323
|
-
// datePicker.maxDate = ...
|
|
324
|
-
}
|
|
325
|
-
dialog.show()
|
|
326
|
-
}
|
|
327
|
-
) {
|
|
328
|
-
Text("Styled Date Picker")
|
|
329
|
-
}
|
|
330
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
package com.example
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.Column
|
|
4
|
-
import androidx.compose.foundation.layout.Row
|
|
5
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
6
|
-
import androidx.compose.foundation.layout.padding
|
|
7
|
-
import androidx.compose.foundation.layout.size
|
|
8
|
-
import androidx.compose.runtime.Composable
|
|
9
|
-
import androidx.compose.ui.Modifier
|
|
10
|
-
import androidx.compose.ui.unit.dp
|
|
11
|
-
import vn.momo.kits.components.Card
|
|
12
|
-
import vn.momo.kits.components.Image
|
|
13
|
-
import vn.momo.kits.components.Text
|
|
14
|
-
import vn.momo.kits.components.Title
|
|
15
|
-
import vn.momo.kits.components.TitleType
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Example: Card component to display a list item with image and title
|
|
19
|
-
*
|
|
20
|
-
* This demonstrates how to create a card in MoMo Native Kits that displays
|
|
21
|
-
* a list item with an image on the left and a title on the right.
|
|
22
|
-
*/
|
|
23
|
-
@Composable
|
|
24
|
-
fun ListItemCardExample() {
|
|
25
|
-
Card(
|
|
26
|
-
onClick = {
|
|
27
|
-
// Handle item click
|
|
28
|
-
},
|
|
29
|
-
modifier = Modifier
|
|
30
|
-
.fillMaxWidth()
|
|
31
|
-
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
32
|
-
) {
|
|
33
|
-
Row(
|
|
34
|
-
modifier = Modifier.padding(12.dp)
|
|
35
|
-
) {
|
|
36
|
-
// Image on the left
|
|
37
|
-
Image(
|
|
38
|
-
source = "https://example.com/image.jpg",
|
|
39
|
-
modifier = Modifier.size(48.dp)
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
// Title on the right
|
|
43
|
-
Column(
|
|
44
|
-
modifier = Modifier.padding(start = 12.dp)
|
|
45
|
-
) {
|
|
46
|
-
Title(
|
|
47
|
-
text = "Item Title",
|
|
48
|
-
type = TitleType.TITLE_4
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Alternative example: Card with image and title with description
|
|
57
|
-
*/
|
|
58
|
-
@Composable
|
|
59
|
-
fun ListItemCardWithDescriptionExample() {
|
|
60
|
-
Card(
|
|
61
|
-
onClick = {
|
|
62
|
-
// Handle item click
|
|
63
|
-
},
|
|
64
|
-
modifier = Modifier
|
|
65
|
-
.fillMaxWidth()
|
|
66
|
-
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
67
|
-
) {
|
|
68
|
-
Row(
|
|
69
|
-
modifier = Modifier.padding(12.dp)
|
|
70
|
-
) {
|
|
71
|
-
// Image on the left
|
|
72
|
-
Image(
|
|
73
|
-
source = "https://example.com/avatar.jpg",
|
|
74
|
-
modifier = Modifier.size(56.dp)
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
// Title and description on the right
|
|
78
|
-
Column(
|
|
79
|
-
modifier = Modifier.padding(start = 12.dp)
|
|
80
|
-
) {
|
|
81
|
-
Title(
|
|
82
|
-
text = "User Profile",
|
|
83
|
-
type = TitleType.TITLE_4
|
|
84
|
-
)
|
|
85
|
-
Text(
|
|
86
|
-
text = "View and edit your profile information",
|
|
87
|
-
modifier = Modifier.padding(top = 4.dp)
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Example: Static card with image and title (non-clickable)
|
|
96
|
-
*/
|
|
97
|
-
@Composable
|
|
98
|
-
fun StaticListItemCardExample() {
|
|
99
|
-
Card(
|
|
100
|
-
modifier = Modifier
|
|
101
|
-
.fillMaxWidth()
|
|
102
|
-
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
103
|
-
) {
|
|
104
|
-
Row(
|
|
105
|
-
modifier = Modifier.padding(12.dp)
|
|
106
|
-
) {
|
|
107
|
-
// Image on the left
|
|
108
|
-
Image(
|
|
109
|
-
source = "https://example.com/icon.png",
|
|
110
|
-
modifier = Modifier.size(40.dp)
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
// Title on the right
|
|
114
|
-
Column(
|
|
115
|
-
modifier = Modifier.padding(start = 12.dp)
|
|
116
|
-
) {
|
|
117
|
-
Title(
|
|
118
|
-
text = "Settings",
|
|
119
|
-
type = TitleType.TITLE_4
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
package com.example.card
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.Row
|
|
4
|
-
import androidx.compose.foundation.layout.Spacer
|
|
5
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
6
|
-
import androidx.compose.foundation.layout.padding
|
|
7
|
-
import androidx.compose.foundation.layout.size
|
|
8
|
-
import androidx.compose.foundation.layout.width
|
|
9
|
-
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
10
|
-
import androidx.compose.material3.Card
|
|
11
|
-
import androidx.compose.material3.CardDefaults
|
|
12
|
-
import androidx.compose.material3.Text
|
|
13
|
-
import androidx.compose.runtime.Composable
|
|
14
|
-
import androidx.compose.ui.Alignment
|
|
15
|
-
import androidx.compose.ui.Modifier
|
|
16
|
-
import androidx.compose.ui.draw.clip
|
|
17
|
-
import androidx.compose.ui.layout.ContentScale
|
|
18
|
-
import androidx.compose.ui.unit.dp
|
|
19
|
-
import coil.compose.AsyncImage
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A card component to display a list item with image and title
|
|
23
|
-
*/
|
|
24
|
-
@Composable
|
|
25
|
-
fun ListItemCard(
|
|
26
|
-
imageUrl: String,
|
|
27
|
-
title: String,
|
|
28
|
-
modifier: Modifier = Modifier
|
|
29
|
-
) {
|
|
30
|
-
Card(
|
|
31
|
-
modifier = modifier
|
|
32
|
-
.fillMaxWidth()
|
|
33
|
-
.padding(8.dp),
|
|
34
|
-
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
|
|
35
|
-
shape = RoundedCornerShape(12.dp)
|
|
36
|
-
) {
|
|
37
|
-
Row(
|
|
38
|
-
modifier = Modifier
|
|
39
|
-
.fillMaxWidth()
|
|
40
|
-
.padding(12.dp),
|
|
41
|
-
verticalAlignment = Alignment.CenterVertically
|
|
42
|
-
) {
|
|
43
|
-
// Image
|
|
44
|
-
AsyncImage(
|
|
45
|
-
model = imageUrl,
|
|
46
|
-
contentDescription = title,
|
|
47
|
-
modifier = Modifier
|
|
48
|
-
.size(60.dp)
|
|
49
|
-
.clip(RoundedCornerShape(8.dp)),
|
|
50
|
-
contentScale = ContentScale.Crop
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
Spacer(modifier = Modifier.width(16.dp))
|
|
54
|
-
|
|
55
|
-
// Title
|
|
56
|
-
Text(
|
|
57
|
-
text = title,
|
|
58
|
-
modifier = Modifier.weight(1f)
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Example usage
|
|
65
|
-
@Composable
|
|
66
|
-
fun CardExample() {
|
|
67
|
-
ListItemCard(
|
|
68
|
-
imageUrl = "https://example.com/image.jpg",
|
|
69
|
-
title = "Sample Item Title"
|
|
70
|
-
)
|
|
71
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.screens
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.Arrangement
|
|
4
|
-
import androidx.compose.foundation.layout.Column
|
|
5
|
-
import androidx.compose.foundation.layout.Spacer
|
|
6
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
7
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
8
|
-
import androidx.compose.foundation.layout.height
|
|
9
|
-
import androidx.compose.foundation.layout.padding
|
|
10
|
-
import androidx.compose.foundation.rememberScrollState
|
|
11
|
-
import androidx.compose.foundation.verticalScroll
|
|
12
|
-
import androidx.compose.runtime.Composable
|
|
13
|
-
import androidx.compose.runtime.MutableState
|
|
14
|
-
import androidx.compose.runtime.getValue
|
|
15
|
-
import androidx.compose.runtime.mutableStateOf
|
|
16
|
-
import androidx.compose.runtime.remember
|
|
17
|
-
import androidx.compose.runtime.setValue
|
|
18
|
-
import androidx.compose.ui.Alignment
|
|
19
|
-
import androidx.compose.ui.Modifier
|
|
20
|
-
import androidx.compose.ui.text.input.KeyboardType
|
|
21
|
-
import androidx.compose.ui.unit.dp
|
|
22
|
-
import vn.momo.kits.components.Button
|
|
23
|
-
import vn.momo.kits.components.ButtonType
|
|
24
|
-
import vn.momo.kits.components.Input
|
|
25
|
-
import vn.momo.kits.components.InputPhoneNumber
|
|
26
|
-
import vn.momo.kits.components.Size
|
|
27
|
-
|
|
28
|
-
@Composable
|
|
29
|
-
fun LoginFormExample() {
|
|
30
|
-
val phoneNumber: MutableState<String> = remember { mutableStateOf("") }
|
|
31
|
-
val password: MutableState<String> = remember { mutableStateOf("") }
|
|
32
|
-
var isLoading by remember { mutableStateOf(false) }
|
|
33
|
-
var phoneError by remember { mutableStateOf("") }
|
|
34
|
-
var passwordError by remember { mutableStateOf("") }
|
|
35
|
-
|
|
36
|
-
Column(
|
|
37
|
-
modifier = Modifier
|
|
38
|
-
.fillMaxSize()
|
|
39
|
-
.padding(horizontal = 16.dp)
|
|
40
|
-
.verticalScroll(rememberScrollState()),
|
|
41
|
-
horizontalAlignment = Alignment.CenterHorizontally,
|
|
42
|
-
verticalArrangement = Arrangement.spacedBy(16.dp)
|
|
43
|
-
) {
|
|
44
|
-
Spacer(modifier = Modifier.height(48.dp))
|
|
45
|
-
|
|
46
|
-
// Phone number input
|
|
47
|
-
InputPhoneNumber(
|
|
48
|
-
text = phoneNumber,
|
|
49
|
-
onChangeText = {
|
|
50
|
-
phoneNumber.value = it
|
|
51
|
-
phoneError = "" // Clear error on typing
|
|
52
|
-
},
|
|
53
|
-
floatingValue = "Số điện thoại",
|
|
54
|
-
placeholder = "Nhập số điện thoại",
|
|
55
|
-
error = phoneError,
|
|
56
|
-
countryCode = "+84",
|
|
57
|
-
modifier = Modifier.fillMaxWidth()
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
// Password input
|
|
61
|
-
Input(
|
|
62
|
-
text = password,
|
|
63
|
-
onChangeText = {
|
|
64
|
-
password.value = it
|
|
65
|
-
passwordError = "" // Clear error on typing
|
|
66
|
-
},
|
|
67
|
-
floatingValue = "Mật khẩu",
|
|
68
|
-
placeholder = "Nhập mật khẩu",
|
|
69
|
-
password = true,
|
|
70
|
-
keyboardType = KeyboardType.Password,
|
|
71
|
-
error = passwordError,
|
|
72
|
-
modifier = Modifier.fillMaxWidth()
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
Spacer(modifier = Modifier.height(8.dp))
|
|
76
|
-
|
|
77
|
-
// Forgot password button
|
|
78
|
-
Button(
|
|
79
|
-
onClick = { /* Navigate to forgot password */ },
|
|
80
|
-
title = "Quên mật khẩu?",
|
|
81
|
-
type = ButtonType.TEXT
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
Spacer(modifier = Modifier.height(16.dp))
|
|
85
|
-
|
|
86
|
-
// Login button
|
|
87
|
-
Button(
|
|
88
|
-
onClick = {
|
|
89
|
-
// Validate inputs
|
|
90
|
-
var hasError = false
|
|
91
|
-
|
|
92
|
-
if (phoneNumber.value.isEmpty()) {
|
|
93
|
-
phoneError = "Vui lòng nhập số điện thoại"
|
|
94
|
-
hasError = true
|
|
95
|
-
} else if (phoneNumber.value.length < 10) {
|
|
96
|
-
phoneError = "Số điện thoại không hợp lệ"
|
|
97
|
-
hasError = true
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (password.value.isEmpty()) {
|
|
101
|
-
passwordError = "Vui lòng nhập mật khẩu"
|
|
102
|
-
hasError = true
|
|
103
|
-
} else if (password.value.length < 6) {
|
|
104
|
-
passwordError = "Mật khẩu phải có ít nhất 6 ký tự"
|
|
105
|
-
hasError = true
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (!hasError) {
|
|
109
|
-
isLoading = true
|
|
110
|
-
// Perform login logic here
|
|
111
|
-
// login(phoneNumber.value, password.value)
|
|
112
|
-
isLoading = false
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
title = "Đăng nhập",
|
|
116
|
-
type = ButtonType.PRIMARY,
|
|
117
|
-
size = Size.LARGE,
|
|
118
|
-
isFull = true,
|
|
119
|
-
loading = isLoading,
|
|
120
|
-
modifier = Modifier.fillMaxWidth()
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
Spacer(modifier = Modifier.height(16.dp))
|
|
124
|
-
|
|
125
|
-
// Register link
|
|
126
|
-
Button(
|
|
127
|
-
onClick = { /* Navigate to register */ },
|
|
128
|
-
title = "Chưa có tài khoản? Đăng ký ngay",
|
|
129
|
-
type = ButtonType.TEXT
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
Spacer(modifier = Modifier.height(48.dp))
|
|
133
|
-
}
|
|
134
|
-
}
|