@teardown/cli 1.2.38 → 2.0.41

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.
Files changed (182) hide show
  1. package/bin/teardown.js +11 -1
  2. package/package.json +77 -57
  3. package/src/cli/commands/init.ts +254 -0
  4. package/src/cli/commands/plugins.ts +93 -0
  5. package/src/cli/commands/prebuild.ts +168 -0
  6. package/src/cli/commands/run.ts +727 -0
  7. package/src/cli/commands/start.ts +87 -0
  8. package/src/cli/commands/validate.ts +62 -0
  9. package/src/cli/index.ts +59 -0
  10. package/src/config/index.ts +45 -0
  11. package/src/config/loader.ts +366 -0
  12. package/src/config/schema.ts +235 -0
  13. package/src/config/types.ts +322 -0
  14. package/src/index.ts +177 -0
  15. package/src/pipeline/cache.ts +179 -0
  16. package/src/pipeline/index.ts +10 -0
  17. package/src/pipeline/stages.ts +692 -0
  18. package/src/plugins/base.ts +370 -0
  19. package/src/plugins/capabilities/biometrics.ts +64 -0
  20. package/src/plugins/capabilities/bluetooth.ts +86 -0
  21. package/src/plugins/capabilities/calendar.ts +57 -0
  22. package/src/plugins/capabilities/camera.ts +77 -0
  23. package/src/plugins/capabilities/contacts.ts +57 -0
  24. package/src/plugins/capabilities/deep-linking.ts +124 -0
  25. package/src/plugins/capabilities/firebase.ts +138 -0
  26. package/src/plugins/capabilities/index.ts +96 -0
  27. package/src/plugins/capabilities/location.ts +87 -0
  28. package/src/plugins/capabilities/photo-library.ts +80 -0
  29. package/src/plugins/capabilities/push-notifications.ts +98 -0
  30. package/src/plugins/capabilities/sign-in-with-apple.ts +53 -0
  31. package/src/plugins/context.ts +220 -0
  32. package/src/plugins/index.ts +26 -0
  33. package/src/plugins/resolver.ts +321 -0
  34. package/src/templates/generator.ts +507 -0
  35. package/src/templates/index.ts +9 -0
  36. package/src/templates/paths.ts +25 -0
  37. package/src/transformers/android/gradle.ts +400 -0
  38. package/src/transformers/android/index.ts +19 -0
  39. package/src/transformers/android/manifest.ts +506 -0
  40. package/src/transformers/index.ts +39 -0
  41. package/src/transformers/ios/entitlements.ts +283 -0
  42. package/src/transformers/ios/index.ts +10 -0
  43. package/src/transformers/ios/pbxproj.ts +267 -0
  44. package/src/transformers/ios/plist.ts +198 -0
  45. package/src/utils/fs.ts +429 -0
  46. package/src/utils/index.ts +21 -0
  47. package/src/utils/logger.ts +203 -0
  48. package/templates/.gitignore +63 -0
  49. package/templates/Gemfile +3 -0
  50. package/templates/android/app/build.gradle.kts +97 -0
  51. package/templates/android/app/proguard-rules.pro +10 -0
  52. package/templates/android/app/src/main/AndroidManifest.xml +26 -0
  53. package/templates/android/app/src/main/java/com/appname/MainActivity.kt +22 -0
  54. package/templates/android/app/src/main/java/com/appname/MainApplication.kt +44 -0
  55. package/templates/android/app/src/main/res/values/strings.xml +3 -0
  56. package/templates/android/app/src/main/res/values/styles.xml +7 -0
  57. package/templates/android/build.gradle.kts +44 -0
  58. package/templates/android/gradle.properties +39 -0
  59. package/templates/android/settings.gradle.kts +12 -0
  60. package/templates/babel.config.js +15 -0
  61. package/templates/index.js +7 -0
  62. package/templates/ios/.xcode.env +11 -0
  63. package/templates/ios/AppName/AppDelegate.swift +25 -0
  64. package/templates/ios/AppName/AppName-Bridging-Header.h +4 -0
  65. package/templates/ios/AppName/AppName.entitlements +6 -0
  66. package/templates/ios/AppName/Images.xcassets/AppIcon.appiconset/Contents.json +35 -0
  67. package/templates/ios/AppName/Images.xcassets/Contents.json +6 -0
  68. package/templates/ios/AppName/Info.plist +49 -0
  69. package/templates/ios/AppName/LaunchScreen.storyboard +38 -0
  70. package/templates/ios/AppName.xcodeproj/project.pbxproj +402 -0
  71. package/templates/ios/AppName.xcodeproj/xcshareddata/xcschemes/AppName.xcscheme +78 -0
  72. package/templates/ios/Podfile +35 -0
  73. package/templates/metro.config.js +41 -0
  74. package/templates/package.json +57 -0
  75. package/templates/react-native.config.js +8 -0
  76. package/templates/src/app/index.tsx +34 -0
  77. package/templates/src/assets/fonts/.gitkeep +1 -0
  78. package/templates/src/assets/images/.gitkeep +1 -0
  79. package/templates/src/components/ui/accordion.tsx +114 -0
  80. package/templates/src/components/ui/avatar.tsx +75 -0
  81. package/templates/src/components/ui/button.tsx +93 -0
  82. package/templates/src/components/ui/card.tsx +120 -0
  83. package/templates/src/components/ui/checkbox.tsx +133 -0
  84. package/templates/src/components/ui/chip.tsx +95 -0
  85. package/templates/src/components/ui/dialog.tsx +134 -0
  86. package/templates/src/components/ui/divider.tsx +67 -0
  87. package/templates/src/components/ui/error-view.tsx +82 -0
  88. package/templates/src/components/ui/form-field.tsx +101 -0
  89. package/templates/src/components/ui/index.ts +100 -0
  90. package/templates/src/components/ui/popover.tsx +92 -0
  91. package/templates/src/components/ui/pressable-feedback.tsx +88 -0
  92. package/templates/src/components/ui/radio-group.tsx +153 -0
  93. package/templates/src/components/ui/scroll-shadow.tsx +108 -0
  94. package/templates/src/components/ui/select.tsx +165 -0
  95. package/templates/src/components/ui/skeleton-group.tsx +97 -0
  96. package/templates/src/components/ui/skeleton.tsx +87 -0
  97. package/templates/src/components/ui/spinner.tsx +87 -0
  98. package/templates/src/components/ui/surface.tsx +95 -0
  99. package/templates/src/components/ui/switch.tsx +124 -0
  100. package/templates/src/components/ui/tabs.tsx +154 -0
  101. package/templates/src/components/ui/text-field.tsx +106 -0
  102. package/templates/src/components/ui/toast.tsx +129 -0
  103. package/templates/src/contexts/.gitkeep +2 -0
  104. package/templates/src/core/clients/api/api.client.ts +113 -0
  105. package/templates/src/core/clients/api/index.ts +1 -0
  106. package/templates/src/core/clients/storage/index.ts +1 -0
  107. package/templates/src/core/clients/storage/storage.client.ts +121 -0
  108. package/templates/src/core/constants/index.ts +19 -0
  109. package/templates/src/core/core.ts +40 -0
  110. package/templates/src/core/index.ts +10 -0
  111. package/templates/src/global.css +87 -0
  112. package/templates/src/hooks/index.ts +6 -0
  113. package/templates/src/hooks/use-debounce.ts +23 -0
  114. package/templates/src/hooks/use-mounted.ts +21 -0
  115. package/templates/src/index.ts +28 -0
  116. package/templates/src/lib/index.ts +5 -0
  117. package/templates/src/lib/utils.ts +115 -0
  118. package/templates/src/modules/.gitkeep +6 -0
  119. package/templates/src/navigation/index.ts +8 -0
  120. package/templates/src/navigation/navigation-provider.tsx +36 -0
  121. package/templates/src/navigation/router.tsx +137 -0
  122. package/templates/src/providers/app.provider.tsx +29 -0
  123. package/templates/src/providers/index.ts +5 -0
  124. package/templates/src/routes/(tabs)/_layout.tsx +42 -0
  125. package/templates/src/routes/(tabs)/explore.tsx +161 -0
  126. package/templates/src/routes/(tabs)/home.tsx +138 -0
  127. package/templates/src/routes/(tabs)/profile.tsx +151 -0
  128. package/templates/src/routes/_layout.tsx +18 -0
  129. package/templates/src/routes/settings.tsx +194 -0
  130. package/templates/src/screens/auth/index.ts +6 -0
  131. package/templates/src/screens/auth/login.tsx +165 -0
  132. package/templates/src/screens/auth/register.tsx +203 -0
  133. package/templates/src/screens/home.tsx +204 -0
  134. package/templates/src/screens/index.ts +17 -0
  135. package/templates/src/screens/profile.tsx +210 -0
  136. package/templates/src/screens/settings.tsx +216 -0
  137. package/templates/src/screens/welcome.tsx +101 -0
  138. package/templates/src/styles/index.ts +103 -0
  139. package/templates/src/types/common.ts +71 -0
  140. package/templates/src/types/index.ts +5 -0
  141. package/templates/tsconfig.json +14 -0
  142. package/README.md +0 -15
  143. package/assets/favicon.ico +0 -0
  144. package/dist/commands/dev/dev.js +0 -55
  145. package/dist/commands/init/init-teardown.js +0 -26
  146. package/dist/index.js +0 -20
  147. package/dist/modules/dev/dev-menu/keyboard-handler.js +0 -138
  148. package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js +0 -105
  149. package/dist/modules/dev/dev-server/cdp/cdp.adapter.js +0 -12
  150. package/dist/modules/dev/dev-server/cdp/index.js +0 -18
  151. package/dist/modules/dev/dev-server/cdp/types.js +0 -2
  152. package/dist/modules/dev/dev-server/dev-server-checker.js +0 -72
  153. package/dist/modules/dev/dev-server/dev-server.js +0 -269
  154. package/dist/modules/dev/dev-server/inspector/device.event-reporter.js +0 -165
  155. package/dist/modules/dev/dev-server/inspector/device.js +0 -577
  156. package/dist/modules/dev/dev-server/inspector/inspector.js +0 -204
  157. package/dist/modules/dev/dev-server/inspector/types.js +0 -2
  158. package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js +0 -61
  159. package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js +0 -64
  160. package/dist/modules/dev/dev-server/plugins/devtools.plugin.js +0 -50
  161. package/dist/modules/dev/dev-server/plugins/favicon.plugin.js +0 -19
  162. package/dist/modules/dev/dev-server/plugins/multipart.plugin.js +0 -62
  163. package/dist/modules/dev/dev-server/plugins/systrace.plugin.js +0 -28
  164. package/dist/modules/dev/dev-server/plugins/types.js +0 -2
  165. package/dist/modules/dev/dev-server/plugins/wss/index.js +0 -19
  166. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js +0 -66
  167. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js +0 -128
  168. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js +0 -75
  169. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js +0 -198
  170. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js +0 -120
  171. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js +0 -357
  172. package/dist/modules/dev/dev-server/plugins/wss/types.js +0 -2
  173. package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js +0 -57
  174. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js +0 -26
  175. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js +0 -46
  176. package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js +0 -55
  177. package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js +0 -36
  178. package/dist/modules/dev/dev-server/sybmolicate/types.js +0 -2
  179. package/dist/modules/dev/terminal/base.terminal.reporter.js +0 -78
  180. package/dist/modules/dev/terminal/terminal.reporter.js +0 -76
  181. package/dist/modules/dev/types.js +0 -2
  182. package/dist/modules/dev/utils/log.js +0 -73
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Home Screen
3
+ *
4
+ * Main dashboard/home screen with content feed.
5
+ */
6
+
7
+ import React from "react";
8
+ import { View, ScrollView, Pressable, RefreshControl } from "react-native";
9
+ import {
10
+ Text,
11
+ Avatar,
12
+ Card,
13
+ CardHeader,
14
+ CardContent,
15
+ CardFooter,
16
+ Badge,
17
+ Skeleton,
18
+ SkeletonCircle,
19
+ } from "@/components/ui";
20
+
21
+ interface Post {
22
+ id: string;
23
+ author: {
24
+ name: string;
25
+ avatar?: string;
26
+ isVerified?: boolean;
27
+ };
28
+ content: string;
29
+ timestamp: string;
30
+ likes: number;
31
+ comments: number;
32
+ isLiked?: boolean;
33
+ }
34
+
35
+ interface HomeScreenProps {
36
+ posts?: Post[];
37
+ loading?: boolean;
38
+ refreshing?: boolean;
39
+ onRefresh?: () => void;
40
+ onPostPress?: (post: Post) => void;
41
+ onProfilePress?: () => void;
42
+ onNotificationsPress?: () => void;
43
+ }
44
+
45
+ const mockPosts: Post[] = [
46
+ {
47
+ id: "1",
48
+ author: { name: "Jane Smith", isVerified: true },
49
+ content:
50
+ "Just shipped a new feature using Uniwind! The Tailwind CSS integration for React Native is a game-changer. Build UIs so much faster now!",
51
+ timestamp: "2h ago",
52
+ likes: 42,
53
+ comments: 8,
54
+ isLiked: true,
55
+ },
56
+ {
57
+ id: "2",
58
+ author: { name: "Alex Johnson" },
59
+ content:
60
+ "Working on something exciting with Teardown CLI. The developer experience is incredible - fast builds, great templates, and now with Uniwind support!",
61
+ timestamp: "4h ago",
62
+ likes: 28,
63
+ comments: 5,
64
+ },
65
+ {
66
+ id: "3",
67
+ author: { name: "Sam Wilson", isVerified: true },
68
+ content:
69
+ "Pro tip: Use the prebuilt components from the template as a starting point. They're fully customizable and follow best practices.",
70
+ timestamp: "6h ago",
71
+ likes: 156,
72
+ comments: 23,
73
+ },
74
+ ];
75
+
76
+ export function HomeScreen({
77
+ posts = mockPosts,
78
+ loading = false,
79
+ refreshing = false,
80
+ onRefresh,
81
+ onPostPress,
82
+ onProfilePress,
83
+ onNotificationsPress,
84
+ }: HomeScreenProps): React.JSX.Element {
85
+ return (
86
+ <View className="flex-1 bg-background">
87
+ {/* Header */}
88
+ <View className="flex-row items-center justify-between px-6 py-4 border-b border-border">
89
+ <Pressable onPress={onProfilePress}>
90
+ <Avatar fallback="U" size="sm" />
91
+ </Pressable>
92
+ <Text variant="h4">Home</Text>
93
+ <Pressable onPress={onNotificationsPress} className="relative">
94
+ <Text className="text-xl">🔔</Text>
95
+ <View className="absolute -top-1 -right-1 h-3 w-3 rounded-full bg-destructive" />
96
+ </Pressable>
97
+ </View>
98
+
99
+ {/* Content */}
100
+ <ScrollView
101
+ className="flex-1"
102
+ contentContainerClassName="p-4 gap-4"
103
+ refreshControl={
104
+ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
105
+ }
106
+ >
107
+ {loading ? (
108
+ // Loading skeleton
109
+ <>
110
+ <PostSkeleton />
111
+ <PostSkeleton />
112
+ <PostSkeleton />
113
+ </>
114
+ ) : (
115
+ // Posts
116
+ posts.map((post) => (
117
+ <PostCard
118
+ key={post.id}
119
+ post={post}
120
+ onPress={() => onPostPress?.(post)}
121
+ />
122
+ ))
123
+ )}
124
+ </ScrollView>
125
+ </View>
126
+ );
127
+ }
128
+
129
+ function PostCard({
130
+ post,
131
+ onPress,
132
+ }: {
133
+ post: Post;
134
+ onPress?: () => void;
135
+ }): React.JSX.Element {
136
+ return (
137
+ <Pressable onPress={onPress}>
138
+ <Card>
139
+ <CardHeader className="flex-row items-center gap-3 pb-2">
140
+ <Avatar fallback={post.author.name} size="md" />
141
+ <View className="flex-1">
142
+ <View className="flex-row items-center gap-2">
143
+ <Text variant="large">{post.author.name}</Text>
144
+ {post.author.isVerified && (
145
+ <Badge variant="default" className="h-5">
146
+ <Text className="text-xs text-primary-foreground">✓</Text>
147
+ </Badge>
148
+ )}
149
+ </View>
150
+ <Text variant="muted">{post.timestamp}</Text>
151
+ </View>
152
+ </CardHeader>
153
+
154
+ <CardContent>
155
+ <Text>{post.content}</Text>
156
+ </CardContent>
157
+
158
+ <CardFooter className="gap-6 pt-2">
159
+ <Pressable className="flex-row items-center gap-2">
160
+ <Text className={post.isLiked ? "text-destructive" : ""}>
161
+ {post.isLiked ? "❤️" : "🤍"}
162
+ </Text>
163
+ <Text variant="muted">{post.likes}</Text>
164
+ </Pressable>
165
+
166
+ <Pressable className="flex-row items-center gap-2">
167
+ <Text>💬</Text>
168
+ <Text variant="muted">{post.comments}</Text>
169
+ </Pressable>
170
+
171
+ <Pressable className="flex-row items-center gap-2">
172
+ <Text>📤</Text>
173
+ </Pressable>
174
+ </CardFooter>
175
+ </Card>
176
+ </Pressable>
177
+ );
178
+ }
179
+
180
+ function PostSkeleton(): React.JSX.Element {
181
+ return (
182
+ <Card>
183
+ <CardHeader className="flex-row items-center gap-3 pb-2">
184
+ <SkeletonCircle size={40} />
185
+ <View className="flex-1 gap-2">
186
+ <Skeleton className="h-4 w-32" />
187
+ <Skeleton className="h-3 w-20" />
188
+ </View>
189
+ </CardHeader>
190
+ <CardContent className="gap-2">
191
+ <Skeleton className="h-4 w-full" />
192
+ <Skeleton className="h-4 w-full" />
193
+ <Skeleton className="h-4 w-3/4" />
194
+ </CardContent>
195
+ <CardFooter className="gap-6 pt-2">
196
+ <Skeleton className="h-4 w-12" />
197
+ <Skeleton className="h-4 w-12" />
198
+ <Skeleton className="h-4 w-8" />
199
+ </CardFooter>
200
+ </Card>
201
+ );
202
+ }
203
+
204
+ export default HomeScreen;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Screens Barrel Export
3
+ *
4
+ * Pre-built screens using Uniwind components.
5
+ * Use these as starting points for your app.
6
+ */
7
+
8
+ // Onboarding
9
+ export { WelcomeScreen } from "./welcome";
10
+
11
+ // Authentication
12
+ export { LoginScreen, RegisterScreen } from "./auth";
13
+
14
+ // Main App
15
+ export { HomeScreen } from "./home";
16
+ export { ProfileScreen } from "./profile";
17
+ export { SettingsScreen } from "./settings";
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Profile Screen
3
+ *
4
+ * User profile display with edit capabilities.
5
+ */
6
+
7
+ import React from "react";
8
+ import { View, ScrollView, Pressable } from "react-native";
9
+ import {
10
+ Text,
11
+ Button,
12
+ Avatar,
13
+ Card,
14
+ CardContent,
15
+ Badge,
16
+ Separator,
17
+ } from "@/components/ui";
18
+
19
+ interface ProfileScreenProps {
20
+ user?: {
21
+ name: string;
22
+ email: string;
23
+ avatar?: string;
24
+ bio?: string;
25
+ location?: string;
26
+ joinedDate?: string;
27
+ isPro?: boolean;
28
+ };
29
+ stats?: {
30
+ posts: number;
31
+ followers: number;
32
+ following: number;
33
+ };
34
+ onEditProfile?: () => void;
35
+ onSettings?: () => void;
36
+ onLogout?: () => void;
37
+ }
38
+
39
+ export function ProfileScreen({
40
+ user = {
41
+ name: "John Doe",
42
+ email: "john@example.com",
43
+ bio: "Building amazing apps with React Native and Tailwind CSS",
44
+ location: "San Francisco, CA",
45
+ joinedDate: "January 2024",
46
+ isPro: true,
47
+ },
48
+ stats = {
49
+ posts: 42,
50
+ followers: 1234,
51
+ following: 567,
52
+ },
53
+ onEditProfile,
54
+ onSettings,
55
+ onLogout,
56
+ }: ProfileScreenProps): React.JSX.Element {
57
+ return (
58
+ <ScrollView className="flex-1 bg-background">
59
+ {/* Header */}
60
+ <View className="bg-primary/5 pb-6 pt-4">
61
+ <View className="flex-row items-center justify-between px-6">
62
+ <Text variant="h3">Profile</Text>
63
+ <Pressable onPress={onSettings} className="p-2">
64
+ <Text className="text-xl">⚙️</Text>
65
+ </Pressable>
66
+ </View>
67
+
68
+ {/* Profile Info */}
69
+ <View className="items-center mt-6 px-6">
70
+ <Avatar
71
+ fallback={user.name}
72
+ size="xl"
73
+ className="border-4 border-background"
74
+ />
75
+ <View className="items-center mt-4 gap-1">
76
+ <View className="flex-row items-center gap-2">
77
+ <Text variant="h3">{user.name}</Text>
78
+ {user.isPro && <Badge variant="default">PRO</Badge>}
79
+ </View>
80
+ <Text variant="muted">{user.email}</Text>
81
+ </View>
82
+ </View>
83
+
84
+ {/* Stats */}
85
+ <View className="flex-row justify-center gap-8 mt-6">
86
+ <StatItem label="Posts" value={stats.posts} />
87
+ <StatItem label="Followers" value={stats.followers} />
88
+ <StatItem label="Following" value={stats.following} />
89
+ </View>
90
+
91
+ {/* Actions */}
92
+ <View className="flex-row gap-3 mt-6 px-6">
93
+ <Button variant="outline" className="flex-1" onPress={onEditProfile}>
94
+ Edit Profile
95
+ </Button>
96
+ <Button variant="outline" size="icon">
97
+ <Text>📤</Text>
98
+ </Button>
99
+ </View>
100
+ </View>
101
+
102
+ {/* Content */}
103
+ <View className="p-6 gap-4">
104
+ {/* Bio Card */}
105
+ <Card>
106
+ <CardContent className="gap-4 py-4">
107
+ <View className="flex-row items-center gap-2">
108
+ <Text>📝</Text>
109
+ <Text variant="label">About</Text>
110
+ </View>
111
+ <Text>{user.bio}</Text>
112
+ </CardContent>
113
+ </Card>
114
+
115
+ {/* Details Card */}
116
+ <Card>
117
+ <CardContent className="gap-4 py-4">
118
+ <View className="flex-row items-center gap-2">
119
+ <Text>ℹ️</Text>
120
+ <Text variant="label">Details</Text>
121
+ </View>
122
+
123
+ <View className="gap-3">
124
+ <DetailRow icon="📍" label="Location" value={user.location || "Not set"} />
125
+ <Separator />
126
+ <DetailRow icon="📅" label="Joined" value={user.joinedDate || "Unknown"} />
127
+ </View>
128
+ </CardContent>
129
+ </Card>
130
+
131
+ {/* Quick Actions */}
132
+ <Card>
133
+ <CardContent className="gap-1 py-2">
134
+ <ActionRow icon="🔔" label="Notifications" onPress={() => {}} />
135
+ <Separator />
136
+ <ActionRow icon="🔒" label="Privacy & Security" onPress={() => {}} />
137
+ <Separator />
138
+ <ActionRow icon="❓" label="Help & Support" onPress={() => {}} />
139
+ </CardContent>
140
+ </Card>
141
+
142
+ {/* Logout */}
143
+ <Button variant="destructive" fullWidth onPress={onLogout}>
144
+ Sign Out
145
+ </Button>
146
+ </View>
147
+ </ScrollView>
148
+ );
149
+ }
150
+
151
+ function StatItem({ label, value }: { label: string; value: number }): React.JSX.Element {
152
+ const formatNumber = (num: number): string => {
153
+ if (num >= 1000) {
154
+ return `${(num / 1000).toFixed(1)}k`;
155
+ }
156
+ return num.toString();
157
+ };
158
+
159
+ return (
160
+ <View className="items-center">
161
+ <Text variant="h3">{formatNumber(value)}</Text>
162
+ <Text variant="muted">{label}</Text>
163
+ </View>
164
+ );
165
+ }
166
+
167
+ function DetailRow({
168
+ icon,
169
+ label,
170
+ value,
171
+ }: {
172
+ icon: string;
173
+ label: string;
174
+ value: string;
175
+ }): React.JSX.Element {
176
+ return (
177
+ <View className="flex-row items-center justify-between">
178
+ <View className="flex-row items-center gap-2">
179
+ <Text>{icon}</Text>
180
+ <Text variant="muted">{label}</Text>
181
+ </View>
182
+ <Text>{value}</Text>
183
+ </View>
184
+ );
185
+ }
186
+
187
+ function ActionRow({
188
+ icon,
189
+ label,
190
+ onPress,
191
+ }: {
192
+ icon: string;
193
+ label: string;
194
+ onPress: () => void;
195
+ }): React.JSX.Element {
196
+ return (
197
+ <Pressable
198
+ className="flex-row items-center justify-between py-3 active:bg-muted rounded-lg px-2 -mx-2"
199
+ onPress={onPress}
200
+ >
201
+ <View className="flex-row items-center gap-3">
202
+ <Text className="text-lg">{icon}</Text>
203
+ <Text>{label}</Text>
204
+ </View>
205
+ <Text className="text-muted-foreground">›</Text>
206
+ </Pressable>
207
+ );
208
+ }
209
+
210
+ export default ProfileScreen;
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Settings Screen
3
+ *
4
+ * App settings and preferences.
5
+ */
6
+
7
+ import React, { useState } from "react";
8
+ import { View, ScrollView, Switch, Pressable } from "react-native";
9
+ import { Text, Card, CardContent, Separator, Badge } from "@/components/ui";
10
+
11
+ interface SettingsScreenProps {
12
+ onBack?: () => void;
13
+ version?: string;
14
+ }
15
+
16
+ export function SettingsScreen({
17
+ onBack,
18
+ version = "1.0.0",
19
+ }: SettingsScreenProps): React.JSX.Element {
20
+ const [notifications, setNotifications] = useState(true);
21
+ const [darkMode, setDarkMode] = useState(false);
22
+ const [haptics, setHaptics] = useState(true);
23
+ const [analytics, setAnalytics] = useState(true);
24
+
25
+ return (
26
+ <ScrollView className="flex-1 bg-background">
27
+ {/* Header */}
28
+ <View className="flex-row items-center gap-4 px-6 py-4 border-b border-border">
29
+ <Pressable onPress={onBack} className="p-2 -ml-2">
30
+ <Text className="text-xl">←</Text>
31
+ </Pressable>
32
+ <Text variant="h3">Settings</Text>
33
+ </View>
34
+
35
+ <View className="p-6 gap-6">
36
+ {/* Preferences */}
37
+ <SettingsSection title="Preferences">
38
+ <ToggleRow
39
+ icon="🔔"
40
+ label="Push Notifications"
41
+ description="Receive push notifications"
42
+ value={notifications}
43
+ onValueChange={setNotifications}
44
+ />
45
+ <Separator />
46
+ <ToggleRow
47
+ icon="🌙"
48
+ label="Dark Mode"
49
+ description="Use dark color theme"
50
+ value={darkMode}
51
+ onValueChange={setDarkMode}
52
+ />
53
+ <Separator />
54
+ <ToggleRow
55
+ icon="📳"
56
+ label="Haptic Feedback"
57
+ description="Enable haptic feedback"
58
+ value={haptics}
59
+ onValueChange={setHaptics}
60
+ />
61
+ </SettingsSection>
62
+
63
+ {/* Account */}
64
+ <SettingsSection title="Account">
65
+ <LinkRow icon="👤" label="Edit Profile" onPress={() => {}} />
66
+ <Separator />
67
+ <LinkRow icon="🔐" label="Change Password" onPress={() => {}} />
68
+ <Separator />
69
+ <LinkRow icon="📧" label="Email Preferences" onPress={() => {}} />
70
+ <Separator />
71
+ <LinkRow
72
+ icon="💳"
73
+ label="Subscription"
74
+ badge="PRO"
75
+ onPress={() => {}}
76
+ />
77
+ </SettingsSection>
78
+
79
+ {/* Privacy */}
80
+ <SettingsSection title="Privacy & Data">
81
+ <ToggleRow
82
+ icon="📊"
83
+ label="Analytics"
84
+ description="Help improve the app"
85
+ value={analytics}
86
+ onValueChange={setAnalytics}
87
+ />
88
+ <Separator />
89
+ <LinkRow icon="🛡️" label="Privacy Policy" onPress={() => {}} />
90
+ <Separator />
91
+ <LinkRow icon="📋" label="Terms of Service" onPress={() => {}} />
92
+ <Separator />
93
+ <LinkRow
94
+ icon="🗑️"
95
+ label="Delete Account"
96
+ destructive
97
+ onPress={() => {}}
98
+ />
99
+ </SettingsSection>
100
+
101
+ {/* Support */}
102
+ <SettingsSection title="Support">
103
+ <LinkRow icon="❓" label="Help Center" onPress={() => {}} />
104
+ <Separator />
105
+ <LinkRow icon="💬" label="Contact Support" onPress={() => {}} />
106
+ <Separator />
107
+ <LinkRow icon="⭐" label="Rate the App" onPress={() => {}} />
108
+ </SettingsSection>
109
+
110
+ {/* About */}
111
+ <SettingsSection title="About">
112
+ <View className="flex-row items-center justify-between py-3">
113
+ <View className="flex-row items-center gap-3">
114
+ <Text className="text-lg">📱</Text>
115
+ <Text>Version</Text>
116
+ </View>
117
+ <Text variant="muted">{version}</Text>
118
+ </View>
119
+ <Separator />
120
+ <LinkRow icon="📜" label="Licenses" onPress={() => {}} />
121
+ </SettingsSection>
122
+
123
+ {/* Footer */}
124
+ <View className="items-center py-8">
125
+ <Text variant="muted">Made with ❤️ using Teardown CLI</Text>
126
+ <Text variant="muted" className="mt-1">
127
+ Powered by Uniwind + Tailwind CSS
128
+ </Text>
129
+ </View>
130
+ </View>
131
+ </ScrollView>
132
+ );
133
+ }
134
+
135
+ function SettingsSection({
136
+ title,
137
+ children,
138
+ }: {
139
+ title: string;
140
+ children: React.ReactNode;
141
+ }): React.JSX.Element {
142
+ return (
143
+ <View className="gap-2">
144
+ <Text variant="label" className="text-muted-foreground px-1">
145
+ {title}
146
+ </Text>
147
+ <Card>
148
+ <CardContent className="py-2">{children}</CardContent>
149
+ </Card>
150
+ </View>
151
+ );
152
+ }
153
+
154
+ function ToggleRow({
155
+ icon,
156
+ label,
157
+ description,
158
+ value,
159
+ onValueChange,
160
+ }: {
161
+ icon: string;
162
+ label: string;
163
+ description?: string;
164
+ value: boolean;
165
+ onValueChange: (value: boolean) => void;
166
+ }): React.JSX.Element {
167
+ return (
168
+ <View className="flex-row items-center justify-between py-3">
169
+ <View className="flex-row items-center gap-3 flex-1">
170
+ <Text className="text-lg">{icon}</Text>
171
+ <View className="flex-1">
172
+ <Text>{label}</Text>
173
+ {description && <Text variant="muted">{description}</Text>}
174
+ </View>
175
+ </View>
176
+ <Switch
177
+ value={value}
178
+ onValueChange={onValueChange}
179
+ trackColor={{ false: "#e2e8f0", true: "#3b82f6" }}
180
+ thumbColor="#ffffff"
181
+ />
182
+ </View>
183
+ );
184
+ }
185
+
186
+ function LinkRow({
187
+ icon,
188
+ label,
189
+ badge,
190
+ destructive,
191
+ onPress,
192
+ }: {
193
+ icon: string;
194
+ label: string;
195
+ badge?: string;
196
+ destructive?: boolean;
197
+ onPress: () => void;
198
+ }): React.JSX.Element {
199
+ return (
200
+ <Pressable
201
+ className="flex-row items-center justify-between py-3 active:bg-muted rounded-lg px-2 -mx-2"
202
+ onPress={onPress}
203
+ >
204
+ <View className="flex-row items-center gap-3">
205
+ <Text className="text-lg">{icon}</Text>
206
+ <Text className={destructive ? "text-destructive" : ""}>{label}</Text>
207
+ </View>
208
+ <View className="flex-row items-center gap-2">
209
+ {badge && <Badge variant="default">{badge}</Badge>}
210
+ <Text className="text-muted-foreground">›</Text>
211
+ </View>
212
+ </Pressable>
213
+ );
214
+ }
215
+
216
+ export default SettingsScreen;