@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,38 +0,0 @@
|
|
|
1
|
-
package com.example
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
4
|
-
import androidx.compose.foundation.layout.padding
|
|
5
|
-
import androidx.compose.runtime.Composable
|
|
6
|
-
import androidx.compose.ui.Modifier
|
|
7
|
-
import androidx.compose.ui.unit.dp
|
|
8
|
-
import vn.momo.kits.components.Button
|
|
9
|
-
import vn.momo.kits.components.ButtonType
|
|
10
|
-
import vn.momo.kits.components.Size
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Primary Button with text 'Đăng nhập'
|
|
14
|
-
*
|
|
15
|
-
* This example demonstrates how to create a primary button in MoMo Native Kits
|
|
16
|
-
* with the Vietnamese text "Đăng nhập" (Login).
|
|
17
|
-
*
|
|
18
|
-
* Key components used:
|
|
19
|
-
* - Button from vn.momo.kits.components
|
|
20
|
-
* - ButtonType.PRIMARY for the primary action style
|
|
21
|
-
* - Size.LARGE for appropriate touch target size
|
|
22
|
-
*/
|
|
23
|
-
@Composable
|
|
24
|
-
fun PrimaryButtonExample() {
|
|
25
|
-
Button(
|
|
26
|
-
onClick = {
|
|
27
|
-
// Handle login action
|
|
28
|
-
// Example: Perform authentication
|
|
29
|
-
},
|
|
30
|
-
title = "Đăng nhập",
|
|
31
|
-
type = ButtonType.PRIMARY,
|
|
32
|
-
size = Size.LARGE,
|
|
33
|
-
isFull = true,
|
|
34
|
-
modifier = Modifier
|
|
35
|
-
.fillMaxWidth()
|
|
36
|
-
.padding(horizontal = 16.dp)
|
|
37
|
-
)
|
|
38
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.example
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
4
|
-
import androidx.compose.foundation.layout.padding
|
|
5
|
-
import androidx.compose.material3.MaterialTheme
|
|
6
|
-
import androidx.compose.material3.Surface
|
|
7
|
-
import androidx.compose.runtime.Composable
|
|
8
|
-
import androidx.compose.runtime.getValue
|
|
9
|
-
import androidx.compose.runtime.mutableStateOf
|
|
10
|
-
import androidx.compose.runtime.remember
|
|
11
|
-
import androidx.compose.runtime.setValue
|
|
12
|
-
import androidx.compose.ui.Modifier
|
|
13
|
-
import androidx.compose.ui.unit.dp
|
|
14
|
-
import vn.momo.kits.components.Button
|
|
15
|
-
import vn.momo.kits.components.ButtonType
|
|
16
|
-
import vn.momo.kits.components.Size
|
|
17
|
-
import vn.momo.kits.const.AppTheme
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Example demonstrating how to create a primary button with Vietnamese text 'Đăng nhập'
|
|
21
|
-
* (meaning "Login" in Vietnamese) using MoMo Native Kits.
|
|
22
|
-
*
|
|
23
|
-
* The Button component supports:
|
|
24
|
-
* - Multiple button types: PRIMARY, SECONDARY, TONAL, OUTLINE, DANGER, TEXT, DISABLED
|
|
25
|
-
* - Multiple sizes: LARGE, MEDIUM, SMALL
|
|
26
|
-
* - Optional icons on left or right
|
|
27
|
-
* - Loading state
|
|
28
|
-
* - Full-width or auto-width variants
|
|
29
|
-
*/
|
|
30
|
-
@Composable
|
|
31
|
-
fun PrimaryButtonLoginExample() {
|
|
32
|
-
// Track click state for demonstration
|
|
33
|
-
var clickCount by remember { mutableStateOf(0) }
|
|
34
|
-
|
|
35
|
-
// Primary button with Vietnamese text 'Đăng nhập' (Login)
|
|
36
|
-
// Uses default ButtonType.PRIMARY which has the primary color background
|
|
37
|
-
Button(
|
|
38
|
-
onClick = { clickCount++ },
|
|
39
|
-
title = "Đăng nhập", // Vietnamese for "Login"
|
|
40
|
-
type = ButtonType.PRIMARY,
|
|
41
|
-
size = Size.LARGE,
|
|
42
|
-
isFull = true,
|
|
43
|
-
modifier = Modifier
|
|
44
|
-
.fillMaxWidth()
|
|
45
|
-
.padding(horizontal = 16.dp)
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Alternative example showing full usage with all parameters
|
|
51
|
-
*/
|
|
52
|
-
@Composable
|
|
53
|
-
fun PrimaryButtonFullExample() {
|
|
54
|
-
var isLoading by remember { mutableStateOf(false) }
|
|
55
|
-
|
|
56
|
-
Button(
|
|
57
|
-
onClick = { /* Handle login action */ },
|
|
58
|
-
title = "Đăng nhập",
|
|
59
|
-
type = ButtonType.PRIMARY, // Primary button style (colored background)
|
|
60
|
-
size = Size.LARGE, // Large size (48dp height)
|
|
61
|
-
iconLeft = "ic_login", // Optional left icon
|
|
62
|
-
iconRight = "", // No right icon
|
|
63
|
-
loading = isLoading, // Loading state
|
|
64
|
-
useTintColor = true, // Apply text color to icon
|
|
65
|
-
isFull = true, // Full width button
|
|
66
|
-
modifier = Modifier
|
|
67
|
-
.fillMaxWidth()
|
|
68
|
-
.padding(16.dp)
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Minimal example - only required parameters
|
|
74
|
-
*/
|
|
75
|
-
@Composable
|
|
76
|
-
fun PrimaryButtonMinimalExample() {
|
|
77
|
-
// Using only the required parameters
|
|
78
|
-
// type defaults to ButtonType.PRIMARY
|
|
79
|
-
Button(
|
|
80
|
-
onClick = { /* Handle click */ },
|
|
81
|
-
title = "Đăng nhập"
|
|
82
|
-
)
|
|
83
|
-
}
|
package/.claude/momo-native-kits-skill/workspace/iteration-3/eval-navcontainer/eval_metadata.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"eval_id": 2,
|
|
3
|
-
"eval_name": "navigation-container",
|
|
4
|
-
"prompt": "How to implement NavigationContainer in MoMo app? Show me the correct pattern",
|
|
5
|
-
"assertions": [
|
|
6
|
-
{
|
|
7
|
-
"text": "Uses NavigationContainer from vn.momo.kits.navigation",
|
|
8
|
-
"passed": true,
|
|
9
|
-
"evidence": "import vn.momo.kits.navigation.NavigationContainer"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"text": "Uses initialScreen parameter",
|
|
13
|
-
"passed": true,
|
|
14
|
-
"evidence": "initialScreen = { ... }"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"text": "Uses NavigationOptions",
|
|
18
|
-
"passed": true,
|
|
19
|
-
"evidence": "options = NavigationOptions(...)"
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.examples
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.background
|
|
4
|
-
import androidx.compose.foundation.clickable
|
|
5
|
-
import androidx.compose.foundation.layout.Arrangement
|
|
6
|
-
import androidx.compose.foundation.layout.Box
|
|
7
|
-
import androidx.compose.foundation.layout.Column
|
|
8
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
9
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
10
|
-
import androidx.compose.foundation.layout.padding
|
|
11
|
-
import androidx.compose.foundation.layout.size
|
|
12
|
-
import androidx.compose.foundation.lazy.LazyColumn
|
|
13
|
-
import androidx.compose.foundation.rememberScrollState
|
|
14
|
-
import androidx.compose.foundation.shape.CircleShape
|
|
15
|
-
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
16
|
-
import androidx.compose.foundation.verticalScroll
|
|
17
|
-
import androidx.compose.material3.Text
|
|
18
|
-
import androidx.compose.runtime.Composable
|
|
19
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
20
|
-
import androidx.compose.runtime.getValue
|
|
21
|
-
import androidx.compose.runtime.mutableStateOf
|
|
22
|
-
import androidx.compose.runtime.remember
|
|
23
|
-
import androidx.compose.runtime.setValue
|
|
24
|
-
import androidx.compose.ui.Alignment
|
|
25
|
-
import androidx.compose.ui.Modifier
|
|
26
|
-
import androidx.compose.ui.draw.clip
|
|
27
|
-
import androidx.compose.ui.graphics.Color
|
|
28
|
-
import androidx.compose.ui.unit.dp
|
|
29
|
-
import vn.momo.kits.navigation.LocalNavigation
|
|
30
|
-
import vn.momo.kits.navigation.LocalNavigator
|
|
31
|
-
import vn.momo.kits.navigation.NavigationContainer
|
|
32
|
-
import vn.momo.kits.navigation.NavigationOptions
|
|
33
|
-
import vn.momo.kits.navigation.ScrollData
|
|
34
|
-
import vn.momo.kits.navigation.component.HeaderBackProps
|
|
35
|
-
import vn.momo.kits.navigation.component.HeaderRight
|
|
36
|
-
import vn.momo.kits.navigation.component.HeaderTitle
|
|
37
|
-
import vn.momo.kits.navigation.component.HeaderType
|
|
38
|
-
import vn.momo.kits.navigation.component.InputSearchProps
|
|
39
|
-
import vn.momo.kits.navigation.component.PopupAction
|
|
40
|
-
import vn.momo.kits.navigation.component.PopupNotifyProps
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* NavigationContainer Example for MoMo App
|
|
44
|
-
*
|
|
45
|
-
* This file demonstrates the correct pattern for implementing NavigationContainer
|
|
46
|
-
* in a MoMo Native Kits application.
|
|
47
|
-
*
|
|
48
|
-
* KEY POINTS:
|
|
49
|
-
* - ONE NavigationContainer per Fragment/Activity
|
|
50
|
-
* - Use setOptions in LaunchedEffect(Unit) for dynamic configuration
|
|
51
|
-
* - Use LocalNavigation.current for setOptions (header, scroll, footer)
|
|
52
|
-
* - Use LocalNavigator.current for push/pop/present/showModal/showBottomSheet
|
|
53
|
-
*/
|
|
54
|
-
@Composable
|
|
55
|
-
fun NavigationContainerExample() {
|
|
56
|
-
// Single NavigationContainer - root of the app/fragment
|
|
57
|
-
NavigationContainer(
|
|
58
|
-
initialScreen = {
|
|
59
|
-
HomeScreen()
|
|
60
|
-
},
|
|
61
|
-
options = NavigationOptions(
|
|
62
|
-
headerTitle = HeaderTitle.Default("MoMo App"),
|
|
63
|
-
headerType = HeaderType.Default,
|
|
64
|
-
headerRight = {
|
|
65
|
-
HeaderRight.Toolkit(useShortcut = true)
|
|
66
|
-
},
|
|
67
|
-
hiddenBack = false
|
|
68
|
-
)
|
|
69
|
-
) {
|
|
70
|
-
// All screens are pushed within this container
|
|
71
|
-
// The container manages the navigation stack
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Home Screen - Initial screen in NavigationContainer
|
|
77
|
-
*
|
|
78
|
-
* Demonstrates:
|
|
79
|
-
* - Using LaunchedEffect(Unit) for setOptions
|
|
80
|
-
* - Connecting scroll state for header animation
|
|
81
|
-
* - Navigation to other screens
|
|
82
|
-
*/
|
|
83
|
-
@Composable
|
|
84
|
-
fun HomeScreen() {
|
|
85
|
-
val navigator = LocalNavigator.current
|
|
86
|
-
val navigation = LocalNavigation.current
|
|
87
|
-
|
|
88
|
-
// Use LaunchedEffect(Unit) for setOptions - NOT in composable root
|
|
89
|
-
LaunchedEffect(Unit) {
|
|
90
|
-
navigation.setOptions(
|
|
91
|
-
headerTitle = HeaderTitle.Default("Trang chủ"),
|
|
92
|
-
headerType = HeaderType.Default
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Connect scroll state for header animation
|
|
97
|
-
val scrollState = rememberScrollState()
|
|
98
|
-
LaunchedEffect(Unit) {
|
|
99
|
-
navigation.setOptions(
|
|
100
|
-
scrollData = ScrollData(
|
|
101
|
-
scrollState = scrollState
|
|
102
|
-
)
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
LazyColumn(
|
|
107
|
-
modifier = Modifier
|
|
108
|
-
.fillMaxSize()
|
|
109
|
-
.padding(horizontal = 16.dp),
|
|
110
|
-
state = scrollState,
|
|
111
|
-
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
112
|
-
) {
|
|
113
|
-
item {
|
|
114
|
-
Modifier.padding(top = 16.dp)
|
|
115
|
-
Text(
|
|
116
|
-
text = "Navigation Examples",
|
|
117
|
-
style = androidx.compose.material3.MaterialTheme.typography.headlineMedium,
|
|
118
|
-
modifier = Modifier.padding(vertical = 8.dp)
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Navigation examples
|
|
123
|
-
item {
|
|
124
|
-
NavigationItem(
|
|
125
|
-
title = "Basic Screen",
|
|
126
|
-
description = "Navigate to a simple screen with push/pop",
|
|
127
|
-
onClick = { navigator.push({ BasicScreen() }) }
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
item {
|
|
132
|
-
NavigationItem(
|
|
133
|
-
title = "Extended Header",
|
|
134
|
-
description = "Header with search input",
|
|
135
|
-
onClick = { navigator.push({ SearchScreen() }) }
|
|
136
|
-
)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
item {
|
|
140
|
-
NavigationItem(
|
|
141
|
-
title = "Animated Header",
|
|
142
|
-
description = "Collapsing header with image",
|
|
143
|
-
onClick = { navigator.push({ AnimatedHeaderScreen() }) }
|
|
144
|
-
)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
item {
|
|
148
|
-
NavigationItem(
|
|
149
|
-
title = "Footer Component",
|
|
150
|
-
description = "Screen with footer button",
|
|
151
|
-
onClick = { navigator.push({ FooterScreen() }) }
|
|
152
|
-
)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
item {
|
|
156
|
-
NavigationItem(
|
|
157
|
-
title = "Prevent Back",
|
|
158
|
-
description = "Confirmation dialog on back press",
|
|
159
|
-
onClick = { navigator.push({ PreventBackScreen() }) }
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
item {
|
|
164
|
-
NavigationItem(
|
|
165
|
-
title = "Modal Screen",
|
|
166
|
-
description = "Present screen as modal",
|
|
167
|
-
onClick = { navigator.present({ ModalScreen() }) }
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
item {
|
|
172
|
-
NavigationItem(
|
|
173
|
-
title = "Bottom Sheet",
|
|
174
|
-
description = "Show content in bottom sheet",
|
|
175
|
-
onClick = { navigator.showBottomSheet({ BottomSheetContent() }) }
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
item {
|
|
180
|
-
NavigationItem(
|
|
181
|
-
title = "Dynamic Title",
|
|
182
|
-
description = "Change header title dynamically",
|
|
183
|
-
onClick = { navigator.push({ DynamicTitleScreen() }) }
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
item {
|
|
188
|
-
Modifier.padding(bottom = 16.dp)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Basic Screen - Simple navigation example
|
|
195
|
-
*/
|
|
196
|
-
@Composable
|
|
197
|
-
fun BasicScreen() {
|
|
198
|
-
val navigator = LocalNavigator.current
|
|
199
|
-
val navigation = LocalNavigation.current
|
|
200
|
-
|
|
201
|
-
LaunchedEffect(Unit) {
|
|
202
|
-
navigation.setOptions(
|
|
203
|
-
headerTitle = HeaderTitle.Default("Basic Screen"),
|
|
204
|
-
headerType = HeaderType.Default
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
Column(
|
|
209
|
-
modifier = Modifier
|
|
210
|
-
.fillMaxSize()
|
|
211
|
-
.padding(16.dp),
|
|
212
|
-
horizontalAlignment = Alignment.CenterHorizontally,
|
|
213
|
-
verticalArrangement = Arrangement.Center
|
|
214
|
-
) {
|
|
215
|
-
Text(
|
|
216
|
-
text = "This is a basic screen",
|
|
217
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
Text(
|
|
221
|
-
text = "Tap the back button or use navigator.pop()",
|
|
222
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium,
|
|
223
|
-
modifier = Modifier.padding(top = 8.dp)
|
|
224
|
-
)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Search Screen - Extended header with search input
|
|
230
|
-
*/
|
|
231
|
-
@Composable
|
|
232
|
-
fun SearchScreen() {
|
|
233
|
-
val navigation = LocalNavigation.current
|
|
234
|
-
val searchText = remember { mutableStateOf("") }
|
|
235
|
-
var searchResults by remember { mutableStateOf(listOf<String>()) }
|
|
236
|
-
|
|
237
|
-
LaunchedEffect(Unit) {
|
|
238
|
-
navigation.setOptions(
|
|
239
|
-
headerTitle = HeaderTitle.Default("Search"),
|
|
240
|
-
headerType = HeaderType.Extended(
|
|
241
|
-
useAnimated = true,
|
|
242
|
-
inputSearchProps = InputSearchProps(
|
|
243
|
-
text = searchText,
|
|
244
|
-
placeholder = "Search...",
|
|
245
|
-
onChangeText = { query ->
|
|
246
|
-
searchText.value = query
|
|
247
|
-
// Simulate search
|
|
248
|
-
searchResults = listOf("Result 1", "Result 2", "Result 3")
|
|
249
|
-
.filter { it.contains(query, ignoreCase = true) }
|
|
250
|
-
}
|
|
251
|
-
)
|
|
252
|
-
)
|
|
253
|
-
)
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
LazyColumn(
|
|
257
|
-
modifier = Modifier
|
|
258
|
-
.fillMaxSize()
|
|
259
|
-
.padding(16.dp)
|
|
260
|
-
) {
|
|
261
|
-
if (searchText.value.isNotEmpty()) {
|
|
262
|
-
items(searchResults.size) { index ->
|
|
263
|
-
Text(
|
|
264
|
-
text = searchResults[index],
|
|
265
|
-
modifier = Modifier
|
|
266
|
-
.fillMaxWidth()
|
|
267
|
-
.padding(vertical = 8.dp)
|
|
268
|
-
)
|
|
269
|
-
}
|
|
270
|
-
} else {
|
|
271
|
-
item {
|
|
272
|
-
Text(
|
|
273
|
-
text = "Enter search query above",
|
|
274
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium
|
|
275
|
-
)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Animated Header Screen - Collapsing header with image
|
|
283
|
-
*/
|
|
284
|
-
@Composable
|
|
285
|
-
fun AnimatedHeaderScreen() {
|
|
286
|
-
val navigation = LocalNavigation.current
|
|
287
|
-
|
|
288
|
-
LaunchedEffect(Unit) {
|
|
289
|
-
navigation.setOptions(
|
|
290
|
-
headerTitle = HeaderTitle.Default("Animated Header"),
|
|
291
|
-
headerType = HeaderType.Animated(
|
|
292
|
-
isSurface = true,
|
|
293
|
-
aspectRatio = vn.momo.kits.navigation.component.AnimatedHeaderRatio.RATIO_16_9,
|
|
294
|
-
composable = {
|
|
295
|
-
Box(
|
|
296
|
-
modifier = Modifier
|
|
297
|
-
.fillMaxSize()
|
|
298
|
-
.background(Color(0xFF6200EE)),
|
|
299
|
-
contentAlignment = Alignment.Center
|
|
300
|
-
) {
|
|
301
|
-
Text(
|
|
302
|
-
text = "Header Image Area",
|
|
303
|
-
color = Color.White
|
|
304
|
-
)
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
)
|
|
308
|
-
)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
Column(
|
|
312
|
-
modifier = Modifier
|
|
313
|
-
.fillMaxSize()
|
|
314
|
-
.padding(16.dp)
|
|
315
|
-
) {
|
|
316
|
-
Text(
|
|
317
|
-
text = "Content below animated header",
|
|
318
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
319
|
-
)
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Footer Screen - Screen with footer component
|
|
325
|
-
*/
|
|
326
|
-
@Composable
|
|
327
|
-
fun FooterScreen() {
|
|
328
|
-
val navigation = LocalNavigation.current
|
|
329
|
-
|
|
330
|
-
LaunchedEffect(Unit) {
|
|
331
|
-
navigation.setOptions(
|
|
332
|
-
headerTitle = HeaderTitle.Default("Footer Screen"),
|
|
333
|
-
headerType = HeaderType.Default,
|
|
334
|
-
footerComponent = {
|
|
335
|
-
Box(
|
|
336
|
-
modifier = Modifier
|
|
337
|
-
.fillMaxWidth()
|
|
338
|
-
.background(Color.White)
|
|
339
|
-
.padding(16.dp)
|
|
340
|
-
) {
|
|
341
|
-
Text(
|
|
342
|
-
text = "Footer Button",
|
|
343
|
-
modifier = Modifier
|
|
344
|
-
.fillMaxWidth()
|
|
345
|
-
.background(Color(0xFF6200EE), RoundedCornerShape(8.dp))
|
|
346
|
-
.padding(12.dp)
|
|
347
|
-
.clickable { /* Handle click */ },
|
|
348
|
-
color = Color.White,
|
|
349
|
-
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
Column(
|
|
357
|
-
modifier = Modifier
|
|
358
|
-
.fillMaxSize()
|
|
359
|
-
.padding(16.dp)
|
|
360
|
-
) {
|
|
361
|
-
Text(
|
|
362
|
-
text = "Main content area",
|
|
363
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
364
|
-
)
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Prevent Back Screen - Confirmation dialog on back press
|
|
370
|
-
*/
|
|
371
|
-
@Composable
|
|
372
|
-
fun PreventBackScreen() {
|
|
373
|
-
val navigator = LocalNavigator.current
|
|
374
|
-
val navigation = LocalNavigation.current
|
|
375
|
-
|
|
376
|
-
LaunchedEffect(Unit) {
|
|
377
|
-
navigation.setOptions(
|
|
378
|
-
headerTitle = HeaderTitle.Default("Prevent Back"),
|
|
379
|
-
headerType = HeaderType.Default,
|
|
380
|
-
headerBackProps = HeaderBackProps(
|
|
381
|
-
preventBack = PopupNotifyProps(
|
|
382
|
-
onIconClose = { navigator.pop() },
|
|
383
|
-
primary = PopupAction(
|
|
384
|
-
title = "Go back",
|
|
385
|
-
onPress = { navigator.pop() }
|
|
386
|
-
),
|
|
387
|
-
secondary = PopupAction(
|
|
388
|
-
title = "Stay",
|
|
389
|
-
onPress = { /* Do nothing - stay on screen */ }
|
|
390
|
-
)
|
|
391
|
-
)
|
|
392
|
-
)
|
|
393
|
-
)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
Column(
|
|
397
|
-
modifier = Modifier
|
|
398
|
-
.fillMaxSize()
|
|
399
|
-
.padding(16.dp),
|
|
400
|
-
verticalArrangement = Arrangement.Center,
|
|
401
|
-
horizontalAlignment = Alignment.CenterHorizontally
|
|
402
|
-
) {
|
|
403
|
-
Text(
|
|
404
|
-
text = "Try pressing the back button",
|
|
405
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
406
|
-
)
|
|
407
|
-
Text(
|
|
408
|
-
text = "A confirmation dialog will appear",
|
|
409
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium,
|
|
410
|
-
modifier = Modifier.padding(top = 8.dp)
|
|
411
|
-
)
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* Modal Screen - Presented as modal
|
|
417
|
-
*/
|
|
418
|
-
@Composable
|
|
419
|
-
fun ModalScreen() {
|
|
420
|
-
val navigator = LocalNavigator.current
|
|
421
|
-
val navigation = LocalNavigation.current
|
|
422
|
-
|
|
423
|
-
LaunchedEffect(Unit) {
|
|
424
|
-
navigation.setOptions(
|
|
425
|
-
headerTitle = HeaderTitle.Default("Modal Screen"),
|
|
426
|
-
headerType = HeaderType.Default
|
|
427
|
-
)
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
Column(
|
|
431
|
-
modifier = Modifier
|
|
432
|
-
.fillMaxSize()
|
|
433
|
-
.padding(16.dp),
|
|
434
|
-
verticalArrangement = Arrangement.Center,
|
|
435
|
-
horizontalAlignment = Alignment.CenterHorizontally
|
|
436
|
-
) {
|
|
437
|
-
Text(
|
|
438
|
-
text = "This is a modal screen",
|
|
439
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
440
|
-
)
|
|
441
|
-
Text(
|
|
442
|
-
text = "Tap outside or back to dismiss",
|
|
443
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium,
|
|
444
|
-
modifier = Modifier.padding(top = 8.dp)
|
|
445
|
-
)
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Bottom Sheet Content - Shown in bottom sheet
|
|
451
|
-
*/
|
|
452
|
-
@Composable
|
|
453
|
-
fun BottomSheetContent() {
|
|
454
|
-
Column(
|
|
455
|
-
modifier = Modifier
|
|
456
|
-
.fillMaxWidth()
|
|
457
|
-
.padding(24.dp)
|
|
458
|
-
) {
|
|
459
|
-
Text(
|
|
460
|
-
text = "Bottom Sheet",
|
|
461
|
-
style = androidx.compose.material3.MaterialTheme.typography.headlineSmall
|
|
462
|
-
)
|
|
463
|
-
Text(
|
|
464
|
-
text = "This content is shown in a bottom sheet",
|
|
465
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium,
|
|
466
|
-
modifier = Modifier.padding(top = 8.dp)
|
|
467
|
-
)
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* Dynamic Title Screen - Change header title dynamically
|
|
473
|
-
*/
|
|
474
|
-
@Composable
|
|
475
|
-
fun DynamicTitleScreen() {
|
|
476
|
-
val navigation = LocalNavigation.current
|
|
477
|
-
var title by remember { mutableStateOf("Dynamic Title") }
|
|
478
|
-
|
|
479
|
-
LaunchedEffect(Unit) {
|
|
480
|
-
navigation.setOptions(
|
|
481
|
-
headerTitle = HeaderTitle.Default(title)
|
|
482
|
-
)
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Update title when it changes
|
|
486
|
-
LaunchedEffect(title) {
|
|
487
|
-
navigation.setOptions(
|
|
488
|
-
headerTitle = HeaderTitle.Default(title)
|
|
489
|
-
)
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
Column(
|
|
493
|
-
modifier = Modifier
|
|
494
|
-
.fillMaxSize()
|
|
495
|
-
.padding(16.dp)
|
|
496
|
-
) {
|
|
497
|
-
Text(
|
|
498
|
-
text = "Current title: $title",
|
|
499
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyLarge
|
|
500
|
-
)
|
|
501
|
-
|
|
502
|
-
// Example buttons to change title
|
|
503
|
-
listOf("Home", "Settings", "Profile", "Account").forEach { newTitle ->
|
|
504
|
-
Text(
|
|
505
|
-
text = newTitle,
|
|
506
|
-
modifier = Modifier
|
|
507
|
-
.fillMaxWidth()
|
|
508
|
-
.padding(vertical = 8.dp)
|
|
509
|
-
.clip(RoundedCornerShape(8.dp))
|
|
510
|
-
.background(Color(0xFFEEEEEE))
|
|
511
|
-
.padding(12.dp)
|
|
512
|
-
.clickable { title = newTitle },
|
|
513
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium
|
|
514
|
-
)
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Reusable Navigation Item for the example list
|
|
521
|
-
*/
|
|
522
|
-
@Composable
|
|
523
|
-
fun NavigationItem(
|
|
524
|
-
title: String,
|
|
525
|
-
description: String,
|
|
526
|
-
onClick: () -> Unit
|
|
527
|
-
) {
|
|
528
|
-
Column(
|
|
529
|
-
modifier = Modifier
|
|
530
|
-
.fillMaxWidth()
|
|
531
|
-
.clip(RoundedCornerShape(12.dp))
|
|
532
|
-
.background(Color(0xFFF5F5F5))
|
|
533
|
-
.clickable { onClick() }
|
|
534
|
-
.padding(16.dp)
|
|
535
|
-
) {
|
|
536
|
-
Text(
|
|
537
|
-
text = title,
|
|
538
|
-
style = androidx.compose.material3.MaterialTheme.typography.titleMedium
|
|
539
|
-
)
|
|
540
|
-
Text(
|
|
541
|
-
text = description,
|
|
542
|
-
style = androidx.compose.material3.MaterialTheme.typography.bodySmall,
|
|
543
|
-
color = Color.Gray,
|
|
544
|
-
modifier = Modifier.padding(top = 4.dp)
|
|
545
|
-
)
|
|
546
|
-
}
|
|
547
|
-
}
|