@teardown/cli 2.0.65 → 2.0.67
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/package.json +2 -2
- package/src/templates/generator.ts +66 -42
- package/templates/{src/index.tsx → index.tsx} +5 -2
- package/templates/metro.config.js +7 -35
- package/templates/src/components/ui/accordion.tsx +23 -21
- package/templates/src/components/ui/card.tsx +28 -26
- package/templates/src/components/ui/checkbox.tsx +12 -10
- package/templates/src/components/ui/dialog.tsx +30 -28
- package/templates/src/components/ui/divider.tsx +6 -6
- package/templates/src/components/ui/form-field.tsx +2 -2
- package/templates/src/components/ui/pressable-feedback.tsx +2 -2
- package/templates/src/components/ui/radio-group.tsx +37 -35
- package/templates/src/components/ui/scroll-shadow.tsx +4 -4
- package/templates/src/components/ui/select.tsx +31 -29
- package/templates/src/components/ui/skeleton-group.tsx +2 -2
- package/templates/src/components/ui/skeleton.tsx +2 -2
- package/templates/src/components/ui/spinner.tsx +2 -2
- package/templates/src/components/ui/tabs.tsx +25 -23
- package/templates/src/global.css +86 -70
- package/templates/src/navigation/navigation-provider.tsx +8 -1
- package/templates/src/navigation/router.tsx +12 -95
- package/templates/src/providers/app.provider.tsx +8 -12
- package/templates/src/routes/_layout.tsx +2 -4
- package/templates/src/routes/home.tsx +112 -0
- package/templates/tsconfig.json +10 -12
- package/templates/index.ts +0 -11
- package/templates/src/components/ui/index.ts +0 -100
- package/templates/src/routes/(tabs)/_layout.tsx +0 -42
- package/templates/src/routes/(tabs)/explore.tsx +0 -161
- package/templates/src/routes/(tabs)/home.tsx +0 -138
- package/templates/src/routes/(tabs)/profile.tsx +0 -114
- package/templates/src/routes/settings.tsx +0 -184
- package/templates/src/screens/auth/index.ts +0 -6
- package/templates/src/screens/auth/login.tsx +0 -165
- package/templates/src/screens/auth/register.tsx +0 -203
- package/templates/src/screens/home.tsx +0 -204
- package/templates/src/screens/index.ts +0 -17
- package/templates/src/screens/profile.tsx +0 -210
- package/templates/src/screens/settings.tsx +0 -216
- package/templates/src/screens/welcome.tsx +0 -101
|
@@ -6,17 +6,24 @@
|
|
|
6
6
|
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { NavigationContainer } from "@react-navigation/native";
|
|
9
|
+
import config from "../../../teardown.config";
|
|
9
10
|
|
|
10
11
|
interface NavigationProviderProps {
|
|
11
12
|
children: React.ReactNode;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Get the deep link scheme from config.
|
|
17
|
+
* Uses `scheme` if specified, otherwise falls back to `slug`.
|
|
18
|
+
*/
|
|
19
|
+
const scheme = config.scheme ?? config.slug;
|
|
20
|
+
|
|
14
21
|
/**
|
|
15
22
|
* Linking configuration for deep links.
|
|
16
23
|
* Routes are automatically generated by @teardown/navigation-metro.
|
|
17
24
|
*/
|
|
18
25
|
const linking = {
|
|
19
|
-
prefixes: [
|
|
26
|
+
prefixes: [`${scheme}://`],
|
|
20
27
|
config: {
|
|
21
28
|
screens: {
|
|
22
29
|
"(tabs)": {
|
|
@@ -2,62 +2,38 @@
|
|
|
2
2
|
* Router Component
|
|
3
3
|
*
|
|
4
4
|
* Renders the navigation structure based on the file-based routes.
|
|
5
|
-
*
|
|
5
|
+
* Uses a simple stack navigator with Home as the initial route.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
|
-
import { View } from "react-native";
|
|
10
9
|
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
11
|
-
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
|
12
|
-
import { Text } from "@/components/ui";
|
|
13
10
|
|
|
14
11
|
// Import screen definitions
|
|
15
|
-
import HomeScreen from "@/routes/
|
|
16
|
-
import ExploreScreen from "@/routes/(tabs)/explore";
|
|
17
|
-
import ProfileScreen from "@/routes/(tabs)/profile";
|
|
18
|
-
import SettingsScreen from "@/routes/settings";
|
|
12
|
+
import HomeScreen from "@/routes/home";
|
|
19
13
|
|
|
20
|
-
// Create
|
|
14
|
+
// Create navigator
|
|
21
15
|
const Stack = createNativeStackNavigator();
|
|
22
|
-
const Tab = createBottomTabNavigator();
|
|
23
16
|
|
|
24
17
|
// Theme colors using CSS variable-friendly values
|
|
25
18
|
const theme = {
|
|
26
|
-
primary: "hsl(221, 83%, 53%)",
|
|
27
19
|
background: "hsl(0, 0%, 100%)",
|
|
28
20
|
foreground: "hsl(224, 71%, 4%)",
|
|
29
|
-
muted: "hsl(220, 14%, 96%)",
|
|
30
|
-
mutedForeground: "hsl(220, 9%, 46%)",
|
|
31
|
-
border: "hsl(220, 13%, 91%)",
|
|
32
21
|
};
|
|
33
22
|
|
|
34
23
|
/**
|
|
35
|
-
*
|
|
36
|
-
*/
|
|
37
|
-
function TabIcon({ icon, focused }: { icon: string; focused: boolean }): React.JSX.Element {
|
|
38
|
-
return (
|
|
39
|
-
<View className={`items-center justify-center ${focused ? "opacity-100" : "opacity-50"}`}>
|
|
40
|
-
<Text className="text-xl">{icon}</Text>
|
|
41
|
-
</View>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Tab Navigator
|
|
24
|
+
* Root Router
|
|
47
25
|
*
|
|
48
|
-
*
|
|
26
|
+
* Stack navigator with Home as the initial route.
|
|
49
27
|
*/
|
|
50
|
-
function
|
|
28
|
+
export function Router(): React.JSX.Element {
|
|
51
29
|
return (
|
|
52
|
-
<
|
|
30
|
+
<Stack.Navigator
|
|
31
|
+
initialRouteName="home"
|
|
53
32
|
screenOptions={{
|
|
54
33
|
headerShown: true,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
tabBarStyle: {
|
|
34
|
+
animation: "slide_from_right",
|
|
35
|
+
contentStyle: {
|
|
58
36
|
backgroundColor: theme.background,
|
|
59
|
-
borderTopColor: theme.border,
|
|
60
|
-
borderTopWidth: 1,
|
|
61
37
|
},
|
|
62
38
|
headerStyle: {
|
|
63
39
|
backgroundColor: theme.background,
|
|
@@ -68,69 +44,10 @@ function TabNavigator(): React.JSX.Element {
|
|
|
68
44
|
},
|
|
69
45
|
}}
|
|
70
46
|
>
|
|
71
|
-
<
|
|
47
|
+
<Stack.Screen
|
|
72
48
|
name="home"
|
|
73
49
|
component={HomeScreen.component}
|
|
74
|
-
options={
|
|
75
|
-
title: "Home",
|
|
76
|
-
tabBarLabel: "Home",
|
|
77
|
-
tabBarIcon: ({ focused }) => <TabIcon icon="🏠" focused={focused} />,
|
|
78
|
-
}}
|
|
79
|
-
/>
|
|
80
|
-
<Tab.Screen
|
|
81
|
-
name="explore"
|
|
82
|
-
component={ExploreScreen.component}
|
|
83
|
-
options={{
|
|
84
|
-
title: "Explore",
|
|
85
|
-
tabBarLabel: "Explore",
|
|
86
|
-
tabBarIcon: ({ focused }) => <TabIcon icon="🔍" focused={focused} />,
|
|
87
|
-
}}
|
|
88
|
-
/>
|
|
89
|
-
<Tab.Screen
|
|
90
|
-
name="profile"
|
|
91
|
-
component={ProfileScreen.component}
|
|
92
|
-
options={{
|
|
93
|
-
title: "Profile",
|
|
94
|
-
tabBarLabel: "Profile",
|
|
95
|
-
tabBarIcon: ({ focused }) => <TabIcon icon="👤" focused={focused} />,
|
|
96
|
-
}}
|
|
97
|
-
/>
|
|
98
|
-
</Tab.Navigator>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Root Router
|
|
104
|
-
*
|
|
105
|
-
* Stack navigator with tabs as the initial route.
|
|
106
|
-
*/
|
|
107
|
-
export function Router(): React.JSX.Element {
|
|
108
|
-
return (
|
|
109
|
-
<Stack.Navigator
|
|
110
|
-
initialRouteName="(tabs)"
|
|
111
|
-
screenOptions={{
|
|
112
|
-
headerShown: false,
|
|
113
|
-
animation: "slide_from_right",
|
|
114
|
-
contentStyle: {
|
|
115
|
-
backgroundColor: theme.background,
|
|
116
|
-
},
|
|
117
|
-
}}
|
|
118
|
-
>
|
|
119
|
-
<Stack.Screen name="(tabs)" component={TabNavigator} />
|
|
120
|
-
<Stack.Screen
|
|
121
|
-
name="settings"
|
|
122
|
-
component={SettingsScreen.component}
|
|
123
|
-
options={{
|
|
124
|
-
title: "Settings",
|
|
125
|
-
headerShown: true,
|
|
126
|
-
headerStyle: {
|
|
127
|
-
backgroundColor: theme.background,
|
|
128
|
-
},
|
|
129
|
-
headerTitleStyle: {
|
|
130
|
-
color: theme.foreground,
|
|
131
|
-
fontWeight: "600",
|
|
132
|
-
},
|
|
133
|
-
}}
|
|
50
|
+
options={HomeScreen.options}
|
|
134
51
|
/>
|
|
135
52
|
</Stack.Navigator>
|
|
136
53
|
);
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Add new providers here to wrap the entire app.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import { HeroUINativeProvider } from "heroui-native";
|
|
9
|
+
import type React from "react";
|
|
10
|
+
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
9
11
|
import { NavigationProvider } from "@/navigation";
|
|
10
12
|
|
|
11
13
|
interface AppProvidersProps {
|
|
@@ -14,16 +16,10 @@ interface AppProvidersProps {
|
|
|
14
16
|
|
|
15
17
|
export function AppProviders({ children }: AppProvidersProps): React.JSX.Element {
|
|
16
18
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{children}
|
|
23
|
-
</AuthProvider>
|
|
24
|
-
</ThemeProvider>
|
|
25
|
-
*/}
|
|
26
|
-
{children}
|
|
27
|
-
</NavigationProvider>
|
|
19
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
20
|
+
<HeroUINativeProvider>
|
|
21
|
+
<NavigationProvider>{children}</NavigationProvider>
|
|
22
|
+
</HeroUINativeProvider>
|
|
23
|
+
</GestureHandlerRootView>
|
|
28
24
|
);
|
|
29
25
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Root Stack Layout
|
|
3
3
|
*
|
|
4
|
-
* Defines the root navigation structure using a stack navigator.
|
|
5
|
-
* The tabs group is nested inside this stack, allowing for
|
|
6
|
-
* full-screen modals and other stack-based navigation.
|
|
4
|
+
* Defines the root navigation structure using a simple stack navigator.
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
7
|
import { defineLayout } from "@teardown/navigation/primitives";
|
|
10
8
|
|
|
11
9
|
export default defineLayout({
|
|
12
10
|
type: "stack",
|
|
13
|
-
initialRouteName: "
|
|
11
|
+
initialRouteName: "home",
|
|
14
12
|
screenOptions: {
|
|
15
13
|
headerShown: false,
|
|
16
14
|
animation: "slide_from_right",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Home Screen
|
|
3
|
+
*
|
|
4
|
+
* The main landing screen of the app.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineScreen } from "@teardown/navigation/primitives";
|
|
8
|
+
import type React from "react";
|
|
9
|
+
import { ScrollView, Text, View } from "react-native";
|
|
10
|
+
import { Button } from "@/components/ui/button";
|
|
11
|
+
import { Card } from "@/components/ui/card";
|
|
12
|
+
import { APP_NAME } from "@/core/constants";
|
|
13
|
+
|
|
14
|
+
function HomeScreen(): React.JSX.Element {
|
|
15
|
+
return (
|
|
16
|
+
<ScrollView className="flex-1 bg-background" contentContainerClassName="p-6 gap-6">
|
|
17
|
+
{/* Hero Section */}
|
|
18
|
+
<View className="items-center gap-4 py-8">
|
|
19
|
+
<View className="h-20 w-20 items-center justify-center rounded-2xl bg-primary">
|
|
20
|
+
<Text className="text-3xl font-bold text-primary-foreground">T</Text>
|
|
21
|
+
</View>
|
|
22
|
+
<View className="items-center gap-2">
|
|
23
|
+
<Text className="text-2xl font-bold text-foreground text-center">
|
|
24
|
+
Welcome to {APP_NAME}
|
|
25
|
+
</Text>
|
|
26
|
+
<Text className="text-base text-muted-foreground text-center">
|
|
27
|
+
Your React Native app is ready to go
|
|
28
|
+
</Text>
|
|
29
|
+
</View>
|
|
30
|
+
</View>
|
|
31
|
+
|
|
32
|
+
{/* Quick Actions */}
|
|
33
|
+
<Card>
|
|
34
|
+
<Card.Header>
|
|
35
|
+
<Text className="text-lg font-semibold text-foreground">Quick Actions</Text>
|
|
36
|
+
</Card.Header>
|
|
37
|
+
<Card.Body className="gap-3">
|
|
38
|
+
<Button onPress={() => console.log("Primary action")} fullWidth>
|
|
39
|
+
Get Started
|
|
40
|
+
</Button>
|
|
41
|
+
<Button variant="bordered" onPress={() => console.log("Secondary action")} fullWidth>
|
|
42
|
+
Learn More
|
|
43
|
+
</Button>
|
|
44
|
+
</Card.Body>
|
|
45
|
+
</Card>
|
|
46
|
+
|
|
47
|
+
{/* Features */}
|
|
48
|
+
<View className="gap-4">
|
|
49
|
+
<Text className="text-lg font-semibold text-foreground">Features</Text>
|
|
50
|
+
<FeatureCard
|
|
51
|
+
icon="🔒"
|
|
52
|
+
title="Type-Safe Navigation"
|
|
53
|
+
description="Routes are fully typed with TypeScript"
|
|
54
|
+
/>
|
|
55
|
+
<FeatureCard
|
|
56
|
+
icon="📁"
|
|
57
|
+
title="File-Based Routing"
|
|
58
|
+
description="Routes generated from file structure"
|
|
59
|
+
/>
|
|
60
|
+
<FeatureCard
|
|
61
|
+
icon="🎨"
|
|
62
|
+
title="HeroUI Components"
|
|
63
|
+
description="Beautiful pre-built UI components"
|
|
64
|
+
/>
|
|
65
|
+
</View>
|
|
66
|
+
|
|
67
|
+
{/* Getting Started */}
|
|
68
|
+
<Card className="bg-primary/5 border-primary/20">
|
|
69
|
+
<Card.Body className="py-4">
|
|
70
|
+
<Text className="text-base font-semibold text-foreground">Getting Started</Text>
|
|
71
|
+
<Text className="text-sm text-muted-foreground mt-2">
|
|
72
|
+
1. Explore the components in src/components/ui/{"\n"}
|
|
73
|
+
2. Add new routes in src/routes/{"\n"}
|
|
74
|
+
3. Customize the theme in global.css{"\n"}
|
|
75
|
+
4. Build your app!
|
|
76
|
+
</Text>
|
|
77
|
+
</Card.Body>
|
|
78
|
+
</Card>
|
|
79
|
+
</ScrollView>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function FeatureCard({
|
|
84
|
+
icon,
|
|
85
|
+
title,
|
|
86
|
+
description,
|
|
87
|
+
}: {
|
|
88
|
+
icon: string;
|
|
89
|
+
title: string;
|
|
90
|
+
description: string;
|
|
91
|
+
}): React.JSX.Element {
|
|
92
|
+
return (
|
|
93
|
+
<Card>
|
|
94
|
+
<Card.Body className="flex-row items-center gap-4">
|
|
95
|
+
<View className="h-12 w-12 items-center justify-center rounded-xl bg-muted">
|
|
96
|
+
<Text className="text-2xl">{icon}</Text>
|
|
97
|
+
</View>
|
|
98
|
+
<View className="flex-1">
|
|
99
|
+
<Text className="text-base font-medium text-foreground">{title}</Text>
|
|
100
|
+
<Text className="text-sm text-muted-foreground">{description}</Text>
|
|
101
|
+
</View>
|
|
102
|
+
</Card.Body>
|
|
103
|
+
</Card>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default defineScreen({
|
|
108
|
+
component: HomeScreen,
|
|
109
|
+
options: {
|
|
110
|
+
title: "Home",
|
|
111
|
+
},
|
|
112
|
+
});
|
package/templates/tsconfig.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"include": ["src/**/*", ".teardown/**/*"],
|
|
13
|
-
"exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"]
|
|
2
|
+
"extends": "@react-native/typescript-config/tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"jsx": "react-native",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"paths": {
|
|
7
|
+
"@/*": ["./src/*"]
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/**/*", ".teardown/**/*"],
|
|
11
|
+
"exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"]
|
|
14
12
|
}
|
package/templates/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* App Entry Point
|
|
3
|
-
*
|
|
4
|
-
* This file registers the root component with React Native's AppRegistry.
|
|
5
|
-
* The app is wrapped with DevClientProvider for development tools.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { AppRegistry } from "react-native";
|
|
9
|
-
import { Root } from "./src";
|
|
10
|
-
|
|
11
|
-
AppRegistry.registerComponent("<%= appName %>", () => Root);
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI Components Barrel Export (HeroUI Native)
|
|
3
|
-
*
|
|
4
|
-
* All components are wrappers around HeroUI Native components,
|
|
5
|
-
* allowing for future customization and modifications.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Accordion
|
|
9
|
-
export { Accordion, AccordionItem, type AccordionProps, type AccordionItemProps } from "./accordion";
|
|
10
|
-
|
|
11
|
-
// Avatar
|
|
12
|
-
export { Avatar, type AvatarProps } from "./avatar";
|
|
13
|
-
|
|
14
|
-
// Button
|
|
15
|
-
export { Button, type ButtonProps } from "./button";
|
|
16
|
-
|
|
17
|
-
// Card
|
|
18
|
-
export {
|
|
19
|
-
Card,
|
|
20
|
-
CardHeader,
|
|
21
|
-
CardBody,
|
|
22
|
-
CardFooter,
|
|
23
|
-
type CardProps,
|
|
24
|
-
type CardHeaderProps,
|
|
25
|
-
type CardBodyProps,
|
|
26
|
-
type CardFooterProps,
|
|
27
|
-
} from "./card";
|
|
28
|
-
|
|
29
|
-
// Checkbox
|
|
30
|
-
export { Checkbox, CheckboxGroup, type CheckboxProps, type CheckboxGroupProps } from "./checkbox";
|
|
31
|
-
|
|
32
|
-
// Chip
|
|
33
|
-
export { Chip, type ChipProps } from "./chip";
|
|
34
|
-
|
|
35
|
-
// Dialog
|
|
36
|
-
export {
|
|
37
|
-
Dialog,
|
|
38
|
-
DialogHeader,
|
|
39
|
-
DialogBody,
|
|
40
|
-
DialogFooter,
|
|
41
|
-
type DialogProps,
|
|
42
|
-
type DialogHeaderProps,
|
|
43
|
-
type DialogBodyProps,
|
|
44
|
-
type DialogFooterProps,
|
|
45
|
-
} from "./dialog";
|
|
46
|
-
|
|
47
|
-
// Divider
|
|
48
|
-
export { Divider, type DividerProps } from "./divider";
|
|
49
|
-
|
|
50
|
-
// Error View
|
|
51
|
-
export { ErrorView, type ErrorViewProps } from "./error-view";
|
|
52
|
-
|
|
53
|
-
// Form Field
|
|
54
|
-
export { FormField, type FormFieldProps } from "./form-field";
|
|
55
|
-
|
|
56
|
-
// Popover
|
|
57
|
-
export { Popover, type PopoverProps } from "./popover";
|
|
58
|
-
|
|
59
|
-
// Pressable Feedback
|
|
60
|
-
export { PressableFeedback, type PressableFeedbackProps } from "./pressable-feedback";
|
|
61
|
-
|
|
62
|
-
// Radio Group
|
|
63
|
-
export { Radio, RadioGroup, type RadioProps, type RadioGroupProps } from "./radio-group";
|
|
64
|
-
|
|
65
|
-
// Scroll Shadow
|
|
66
|
-
export { ScrollShadow, type ScrollShadowProps } from "./scroll-shadow";
|
|
67
|
-
|
|
68
|
-
// Select
|
|
69
|
-
export { Select, SelectItem, type SelectProps, type SelectItemProps } from "./select";
|
|
70
|
-
|
|
71
|
-
// Skeleton
|
|
72
|
-
export { Skeleton, type SkeletonProps } from "./skeleton";
|
|
73
|
-
|
|
74
|
-
// Skeleton Group
|
|
75
|
-
export { SkeletonGroup, type SkeletonGroupProps } from "./skeleton-group";
|
|
76
|
-
|
|
77
|
-
// Spinner
|
|
78
|
-
export { Spinner, type SpinnerProps } from "./spinner";
|
|
79
|
-
|
|
80
|
-
// Surface
|
|
81
|
-
export { Surface, type SurfaceProps } from "./surface";
|
|
82
|
-
|
|
83
|
-
// Switch
|
|
84
|
-
export { Switch, type SwitchProps } from "./switch";
|
|
85
|
-
|
|
86
|
-
// Tabs
|
|
87
|
-
export { Tabs, Tab, type TabsProps, type TabProps } from "./tabs";
|
|
88
|
-
|
|
89
|
-
// Text Field
|
|
90
|
-
export {
|
|
91
|
-
TextField,
|
|
92
|
-
type TextFieldProps,
|
|
93
|
-
type TextFieldLabelProps,
|
|
94
|
-
type TextFieldInputProps,
|
|
95
|
-
type TextFieldDescriptionProps,
|
|
96
|
-
type TextFieldErrorMessageProps,
|
|
97
|
-
} from "./text-field";
|
|
98
|
-
|
|
99
|
-
// Toast
|
|
100
|
-
export { Toast, type ToastProps } from "./toast";
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tabs Layout
|
|
3
|
-
*
|
|
4
|
-
* Defines the bottom tab navigation with three screens:
|
|
5
|
-
* - Home: Main dashboard/landing screen
|
|
6
|
-
* - Explore: Discovery and search functionality
|
|
7
|
-
* - Profile: User profile and settings access
|
|
8
|
-
*
|
|
9
|
-
* Theme colors are defined using HSL values that match the global.css theme.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { defineLayout } from "@teardown/navigation/primitives";
|
|
13
|
-
|
|
14
|
-
// Theme colors matching global.css
|
|
15
|
-
const theme = {
|
|
16
|
-
primary: "hsl(221, 83%, 53%)",
|
|
17
|
-
background: "hsl(0, 0%, 100%)",
|
|
18
|
-
foreground: "hsl(224, 71%, 4%)",
|
|
19
|
-
mutedForeground: "hsl(220, 9%, 46%)",
|
|
20
|
-
border: "hsl(220, 13%, 91%)",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export default defineLayout({
|
|
24
|
-
type: "tabs",
|
|
25
|
-
screenOptions: {
|
|
26
|
-
headerShown: true,
|
|
27
|
-
tabBarActiveTintColor: theme.primary,
|
|
28
|
-
tabBarInactiveTintColor: theme.mutedForeground,
|
|
29
|
-
tabBarStyle: {
|
|
30
|
-
backgroundColor: theme.background,
|
|
31
|
-
borderTopColor: theme.border,
|
|
32
|
-
borderTopWidth: 1,
|
|
33
|
-
},
|
|
34
|
-
headerStyle: {
|
|
35
|
-
backgroundColor: theme.background,
|
|
36
|
-
},
|
|
37
|
-
headerTitleStyle: {
|
|
38
|
-
color: theme.foreground,
|
|
39
|
-
fontWeight: "600",
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
});
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Explore Screen
|
|
3
|
-
*
|
|
4
|
-
* Discovery and search functionality screen.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React, { useState } from "react";
|
|
8
|
-
import { View, ScrollView, Pressable } from "react-native";
|
|
9
|
-
import { defineScreen } from "@teardown/navigation/primitives";
|
|
10
|
-
import {
|
|
11
|
-
Text,
|
|
12
|
-
Input,
|
|
13
|
-
Card,
|
|
14
|
-
CardHeader,
|
|
15
|
-
CardTitle,
|
|
16
|
-
CardDescription,
|
|
17
|
-
CardContent,
|
|
18
|
-
Badge,
|
|
19
|
-
} from "@/components/ui";
|
|
20
|
-
|
|
21
|
-
interface Category {
|
|
22
|
-
id: string;
|
|
23
|
-
title: string;
|
|
24
|
-
description: string;
|
|
25
|
-
icon: string;
|
|
26
|
-
color: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const categories: Category[] = [
|
|
30
|
-
{
|
|
31
|
-
id: "1",
|
|
32
|
-
title: "Getting Started",
|
|
33
|
-
description: "Learn the basics of your new app",
|
|
34
|
-
icon: "🚀",
|
|
35
|
-
color: "bg-blue-500/10",
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: "2",
|
|
39
|
-
title: "Documentation",
|
|
40
|
-
description: "Read the full documentation",
|
|
41
|
-
icon: "📚",
|
|
42
|
-
color: "bg-green-500/10",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: "3",
|
|
46
|
-
title: "Examples",
|
|
47
|
-
description: "Browse example implementations",
|
|
48
|
-
icon: "💡",
|
|
49
|
-
color: "bg-yellow-500/10",
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: "4",
|
|
53
|
-
title: "Community",
|
|
54
|
-
description: "Join the community discussions",
|
|
55
|
-
icon: "👥",
|
|
56
|
-
color: "bg-purple-500/10",
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: "5",
|
|
60
|
-
title: "Templates",
|
|
61
|
-
description: "Start with pre-built templates",
|
|
62
|
-
icon: "📋",
|
|
63
|
-
color: "bg-pink-500/10",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: "6",
|
|
67
|
-
title: "Integrations",
|
|
68
|
-
description: "Connect with other services",
|
|
69
|
-
icon: "🔗",
|
|
70
|
-
color: "bg-orange-500/10",
|
|
71
|
-
},
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
function ExploreScreen(): React.JSX.Element {
|
|
75
|
-
const [searchQuery, setSearchQuery] = useState("");
|
|
76
|
-
|
|
77
|
-
const filteredCategories = categories.filter(
|
|
78
|
-
(cat) =>
|
|
79
|
-
cat.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
80
|
-
cat.description.toLowerCase().includes(searchQuery.toLowerCase())
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<View className="flex-1 bg-background">
|
|
85
|
-
{/* Search Header */}
|
|
86
|
-
<View className="px-6 py-4 border-b border-border">
|
|
87
|
-
<Input
|
|
88
|
-
placeholder="Search categories..."
|
|
89
|
-
value={searchQuery}
|
|
90
|
-
onChangeText={setSearchQuery}
|
|
91
|
-
/>
|
|
92
|
-
</View>
|
|
93
|
-
|
|
94
|
-
<ScrollView className="flex-1" contentContainerClassName="p-6 gap-6">
|
|
95
|
-
{/* Section Header */}
|
|
96
|
-
<View className="gap-2">
|
|
97
|
-
<Text variant="h2">Explore</Text>
|
|
98
|
-
<Text variant="muted">Discover new content and features</Text>
|
|
99
|
-
</View>
|
|
100
|
-
|
|
101
|
-
{/* Popular Tags */}
|
|
102
|
-
<View className="gap-3">
|
|
103
|
-
<Text variant="label">POPULAR TAGS</Text>
|
|
104
|
-
<View className="flex-row flex-wrap gap-2">
|
|
105
|
-
<Badge variant="secondary">React Native</Badge>
|
|
106
|
-
<Badge variant="secondary">Navigation</Badge>
|
|
107
|
-
<Badge variant="secondary">TypeScript</Badge>
|
|
108
|
-
<Badge variant="secondary">Tailwind</Badge>
|
|
109
|
-
<Badge variant="outline">Animations</Badge>
|
|
110
|
-
<Badge variant="outline">State</Badge>
|
|
111
|
-
</View>
|
|
112
|
-
</View>
|
|
113
|
-
|
|
114
|
-
{/* Categories Grid */}
|
|
115
|
-
<View className="gap-4">
|
|
116
|
-
<Text variant="label">CATEGORIES</Text>
|
|
117
|
-
<View className="gap-3">
|
|
118
|
-
{filteredCategories.map((category) => (
|
|
119
|
-
<CategoryCard key={category.id} category={category} />
|
|
120
|
-
))}
|
|
121
|
-
</View>
|
|
122
|
-
</View>
|
|
123
|
-
|
|
124
|
-
{filteredCategories.length === 0 && (
|
|
125
|
-
<View className="items-center py-8">
|
|
126
|
-
<Text className="text-4xl mb-4">🔍</Text>
|
|
127
|
-
<Text variant="large">No results found</Text>
|
|
128
|
-
<Text variant="muted">Try a different search term</Text>
|
|
129
|
-
</View>
|
|
130
|
-
)}
|
|
131
|
-
</ScrollView>
|
|
132
|
-
</View>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function CategoryCard({ category }: { category: Category }): React.JSX.Element {
|
|
137
|
-
return (
|
|
138
|
-
<Pressable>
|
|
139
|
-
<Card>
|
|
140
|
-
<CardContent className="flex-row items-center gap-4 py-4">
|
|
141
|
-
<View className={`h-12 w-12 items-center justify-center rounded-xl ${category.color}`}>
|
|
142
|
-
<Text className="text-2xl">{category.icon}</Text>
|
|
143
|
-
</View>
|
|
144
|
-
<View className="flex-1">
|
|
145
|
-
<CardTitle className="text-base">{category.title}</CardTitle>
|
|
146
|
-
<CardDescription>{category.description}</CardDescription>
|
|
147
|
-
</View>
|
|
148
|
-
<Text className="text-muted-foreground">›</Text>
|
|
149
|
-
</CardContent>
|
|
150
|
-
</Card>
|
|
151
|
-
</Pressable>
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export default defineScreen({
|
|
156
|
-
component: ExploreScreen,
|
|
157
|
-
options: {
|
|
158
|
-
title: "Explore",
|
|
159
|
-
tabBarLabel: "Explore",
|
|
160
|
-
},
|
|
161
|
-
});
|