create-croissant 0.1.46 → 0.1.48

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 (51) hide show
  1. package/package.json +1 -1
  2. package/template/apps/platform/src/routes/api/auth/$.ts +1 -1
  3. package/template/apps/platform/src/routes/api/rpc.$.ts +2 -2
  4. package/template/package.json +2 -7
  5. package/template/tsconfig.json +1 -2
  6. package/template/.github/dependabot.yml +0 -15
  7. package/template/.github/workflows/ci.yml +0 -143
  8. package/template/.github/workflows/dependabot-automerge.yml +0 -23
  9. package/template/.husky/pre-push +0 -11
  10. package/template/apps/mobile/.vscode/extensions.json +0 -1
  11. package/template/apps/mobile/.vscode/settings.json +0 -7
  12. package/template/apps/mobile/README.md +0 -50
  13. package/template/apps/mobile/app/(tabs)/_layout.tsx +0 -43
  14. package/template/apps/mobile/app/(tabs)/account.tsx +0 -147
  15. package/template/apps/mobile/app/(tabs)/explore.tsx +0 -345
  16. package/template/apps/mobile/app/(tabs)/index.tsx +0 -112
  17. package/template/apps/mobile/app/_layout.tsx +0 -43
  18. package/template/apps/mobile/app/index.tsx +0 -129
  19. package/template/apps/mobile/app/login.tsx +0 -135
  20. package/template/apps/mobile/app/signup.tsx +0 -144
  21. package/template/apps/mobile/app.json +0 -56
  22. package/template/apps/mobile/assets/images/android-icon-background.png +0 -0
  23. package/template/apps/mobile/assets/images/android-icon-foreground.png +0 -0
  24. package/template/apps/mobile/assets/images/android-icon-monochrome.png +0 -0
  25. package/template/apps/mobile/assets/images/favicon.png +0 -0
  26. package/template/apps/mobile/assets/images/icon.png +0 -0
  27. package/template/apps/mobile/assets/images/partial-react-logo.png +0 -0
  28. package/template/apps/mobile/assets/images/react-logo.png +0 -0
  29. package/template/apps/mobile/assets/images/react-logo@2x.png +0 -0
  30. package/template/apps/mobile/assets/images/react-logo@3x.png +0 -0
  31. package/template/apps/mobile/assets/images/splash-icon.png +0 -0
  32. package/template/apps/mobile/components/external-link.tsx +0 -25
  33. package/template/apps/mobile/components/haptic-tab.tsx +0 -18
  34. package/template/apps/mobile/components/hello-wave.tsx +0 -20
  35. package/template/apps/mobile/components/parallax-scroll-view.tsx +0 -81
  36. package/template/apps/mobile/components/themed-text.tsx +0 -60
  37. package/template/apps/mobile/components/themed-view.tsx +0 -14
  38. package/template/apps/mobile/components/ui/button.tsx +0 -86
  39. package/template/apps/mobile/components/ui/collapsible.tsx +0 -46
  40. package/template/apps/mobile/components/ui/icon-symbol.ios.tsx +0 -32
  41. package/template/apps/mobile/components/ui/icon-symbol.tsx +0 -41
  42. package/template/apps/mobile/components/ui/input.tsx +0 -56
  43. package/template/apps/mobile/constants/theme.ts +0 -53
  44. package/template/apps/mobile/hooks/use-color-scheme.ts +0 -1
  45. package/template/apps/mobile/hooks/use-color-scheme.web.ts +0 -21
  46. package/template/apps/mobile/hooks/use-theme-color.ts +0 -21
  47. package/template/apps/mobile/lib/auth-client.ts +0 -14
  48. package/template/apps/mobile/lib/orpc.ts +0 -28
  49. package/template/apps/mobile/package.json +0 -57
  50. package/template/apps/mobile/scripts/reset-project.js +0 -112
  51. package/template/apps/mobile/tsconfig.json +0 -13
@@ -1,135 +0,0 @@
1
- import { useState } from "react";
2
- import { View, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, Text } from "react-native";
3
- import { useRouter } from "expo-router";
4
- import { authClient } from "@/lib/auth-client";
5
- import { Button } from "@/components/ui/button";
6
- import { Input } from "@/components/ui/input";
7
-
8
- export default function LoginScreen() {
9
- const router = useRouter();
10
- const [email, setEmail] = useState("");
11
- const [password, setPassword] = useState("");
12
- const [loading, setLoading] = useState(false);
13
- const [error, setError] = useState<string | null>(null);
14
-
15
- const handleLogin = async () => {
16
- if (!email || !password) {
17
- setError("Please fill in all fields");
18
- return;
19
- }
20
-
21
- setLoading(true);
22
- setError(null);
23
- try {
24
- const { error } = await authClient.signIn.email({
25
- email,
26
- password,
27
- });
28
-
29
- if (error) {
30
- setError(error.message || "Invalid credentials");
31
- } else {
32
- router.replace("/(tabs)");
33
- }
34
- } catch (err) {
35
- setError(err instanceof Error ? err.message : "An error occurred during login");
36
- } finally {
37
- setLoading(false);
38
- }
39
- };
40
-
41
- return (
42
- <KeyboardAvoidingView
43
- behavior={Platform.OS === "ios" ? "padding" : "height"}
44
- style={styles.container}
45
- >
46
- <ScrollView contentContainerStyle={styles.scrollContent}>
47
- <View style={styles.header}>
48
- <Text style={styles.title}>Welcome Back</Text>
49
- <Text style={styles.subtitle}>Sign in to your account</Text>
50
- </View>
51
-
52
- <View style={styles.form}>
53
- <Input
54
- label="Email"
55
- placeholder="email@example.com"
56
- value={email}
57
- onChangeText={setEmail}
58
- autoCapitalize="none"
59
- keyboardType="email-address"
60
- />
61
-
62
- <Input
63
- label="Password"
64
- placeholder="••••••••"
65
- value={password}
66
- onChangeText={setPassword}
67
- secureTextEntry
68
- />
69
-
70
- {error && <Text style={styles.errorText}>{error}</Text>}
71
-
72
- <Button
73
- onPress={handleLogin}
74
- loading={loading}
75
- >
76
- Sign In
77
- </Button>
78
-
79
- <View style={styles.footer}>
80
- <Text style={styles.footerText}>Don't have an account? </Text>
81
- <Text
82
- style={styles.link}
83
- onPress={() => router.push("/signup")}
84
- >
85
- Sign Up
86
- </Text>
87
- </View>
88
- </View>
89
- </ScrollView>
90
- </KeyboardAvoidingView>
91
- );
92
- }
93
-
94
- const styles = StyleSheet.create({
95
- container: {
96
- flex: 1,
97
- backgroundColor: "#fff",
98
- },
99
- scrollContent: {
100
- flexGrow: 1,
101
- padding: 24,
102
- justifyContent: "center",
103
- },
104
- header: {
105
- marginBottom: 40,
106
- },
107
- title: {
108
- fontSize: 32,
109
- fontWeight: "bold",
110
- marginBottom: 8,
111
- },
112
- subtitle: {
113
- fontSize: 16,
114
- color: "#666",
115
- },
116
- form: {
117
- gap: 20,
118
- },
119
- errorText: {
120
- color: "#ef4444",
121
- fontSize: 14,
122
- },
123
- footer: {
124
- flexDirection: "row",
125
- justifyContent: "center",
126
- marginTop: 20,
127
- },
128
- footerText: {
129
- color: "#666",
130
- },
131
- link: {
132
- color: "#000",
133
- fontWeight: "bold",
134
- },
135
- });
@@ -1,144 +0,0 @@
1
- import { useState } from "react";
2
- import { View, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, Text } from "react-native";
3
- import { useRouter } from "expo-router";
4
- import { authClient } from "@/lib/auth-client";
5
- import { Button } from "@/components/ui/button";
6
- import { Input } from "@/components/ui/input";
7
-
8
- export default function SignupScreen() {
9
- const router = useRouter();
10
- const [name, setName] = useState("");
11
- const [email, setEmail] = useState("");
12
- const [password, setPassword] = useState("");
13
- const [loading, setLoading] = useState(false);
14
- const [error, setError] = useState<string | null>(null);
15
-
16
- const handleSignup = async () => {
17
- if (!name || !email || !password) {
18
- setError("Please fill in all fields");
19
- return;
20
- }
21
-
22
- setLoading(true);
23
- setError(null);
24
- try {
25
- const { error } = await authClient.signUp.email({
26
- email,
27
- password,
28
- name,
29
- });
30
-
31
- if (error) {
32
- setError(error.message || "An error occurred during signup");
33
- } else {
34
- router.replace("/(tabs)");
35
- }
36
- } catch (err) {
37
- setError(err instanceof Error ? err.message : "An error occurred during signup");
38
- } finally {
39
- setLoading(false);
40
- }
41
- };
42
-
43
- return (
44
- <KeyboardAvoidingView
45
- behavior={Platform.OS === "ios" ? "padding" : "height"}
46
- style={styles.container}
47
- >
48
- <ScrollView contentContainerStyle={styles.scrollContent}>
49
- <View style={styles.header}>
50
- <Text style={styles.title}>Create Account</Text>
51
- <Text style={styles.subtitle}>Join the Croissant Stack</Text>
52
- </View>
53
-
54
- <View style={styles.form}>
55
- <Input
56
- label="Name"
57
- placeholder="John Doe"
58
- value={name}
59
- onChangeText={setName}
60
- />
61
-
62
- <Input
63
- label="Email"
64
- placeholder="email@example.com"
65
- value={email}
66
- onChangeText={setEmail}
67
- autoCapitalize="none"
68
- keyboardType="email-address"
69
- />
70
-
71
- <Input
72
- label="Password"
73
- placeholder="••••••••"
74
- value={password}
75
- onChangeText={setPassword}
76
- secureTextEntry
77
- />
78
-
79
- {error && <Text style={styles.errorText}>{error}</Text>}
80
-
81
- <Button
82
- onPress={handleSignup}
83
- loading={loading}
84
- >
85
- Sign Up
86
- </Button>
87
-
88
- <View style={styles.footer}>
89
- <Text style={styles.footerText}>Already have an account? </Text>
90
- <Text
91
- style={styles.link}
92
- onPress={() => router.push("/login")}
93
- >
94
- Sign In
95
- </Text>
96
- </View>
97
- </View>
98
- </ScrollView>
99
- </KeyboardAvoidingView>
100
- );
101
- }
102
-
103
- const styles = StyleSheet.create({
104
- container: {
105
- flex: 1,
106
- backgroundColor: "#fff",
107
- },
108
- scrollContent: {
109
- flexGrow: 1,
110
- padding: 24,
111
- justifyContent: "center",
112
- },
113
- header: {
114
- marginBottom: 40,
115
- },
116
- title: {
117
- fontSize: 32,
118
- fontWeight: "bold",
119
- marginBottom: 8,
120
- },
121
- subtitle: {
122
- fontSize: 16,
123
- color: "#666",
124
- },
125
- form: {
126
- gap: 20,
127
- },
128
- errorText: {
129
- color: "#ef4444",
130
- fontSize: 14,
131
- },
132
- footer: {
133
- flexDirection: "row",
134
- justifyContent: "center",
135
- marginTop: 20,
136
- },
137
- footerText: {
138
- color: "#666",
139
- },
140
- link: {
141
- color: "#000",
142
- fontWeight: "bold",
143
- },
144
- });
@@ -1,56 +0,0 @@
1
- {
2
- "expo": {
3
- "name": "mobile",
4
- "slug": "mobile",
5
- "version": "1.0.0",
6
- "orientation": "portrait",
7
- "icon": "./assets/images/icon.png",
8
- "scheme": "mobile",
9
- "userInterfaceStyle": "automatic",
10
- "newArchEnabled": true,
11
- "ios": {
12
- "supportsTablet": true,
13
- "infoPlist": {
14
- "NSAppTransportSecurity": {
15
- "NSAllowsLocalNetworking": true
16
- }
17
- }
18
- },
19
- "android": {
20
- "adaptiveIcon": {
21
- "backgroundColor": "#E6F4FE",
22
- "foregroundImage": "./assets/images/android-icon-foreground.png",
23
- "backgroundImage": "./assets/images/android-icon-background.png",
24
- "monochromeImage": "./assets/images/android-icon-monochrome.png"
25
- },
26
- "edgeToEdgeEnabled": true,
27
- "predictiveBackGestureEnabled": false
28
- },
29
- "web": {
30
- "output": "single",
31
- "favicon": "./assets/images/favicon.png",
32
- "bundler": "metro"
33
- },
34
- "plugins": [
35
- "expo-router",
36
- [
37
- "expo-splash-screen",
38
- {
39
- "image": "./assets/images/splash-icon.png",
40
- "imageWidth": 200,
41
- "resizeMode": "contain",
42
- "backgroundColor": "#ffffff",
43
- "dark": {
44
- "backgroundColor": "#000000"
45
- }
46
- }
47
- ],
48
- "expo-font",
49
- "expo-image",
50
- "expo-web-browser"
51
- ],
52
- "experiments": {
53
- "typedRoutes": true
54
- }
55
- }
56
- }
@@ -1,25 +0,0 @@
1
- import { Href, Link } from "expo-router";
2
- import { openBrowserAsync, WebBrowserPresentationStyle } from "expo-web-browser";
3
- import { type ComponentProps } from "react";
4
-
5
- type Props = Omit<ComponentProps<typeof Link>, "href"> & { href: Href & string };
6
-
7
- export function ExternalLink({ href, ...rest }: Props) {
8
- return (
9
- <Link
10
- target="_blank"
11
- {...rest}
12
- href={href}
13
- onPress={async (event) => {
14
- if (process.env.EXPO_OS !== "web") {
15
- // Prevent the default behavior of linking to the default browser on native.
16
- event.preventDefault();
17
- // Open the link in an in-app browser.
18
- await openBrowserAsync(href, {
19
- presentationStyle: WebBrowserPresentationStyle.AUTOMATIC,
20
- });
21
- }
22
- }}
23
- />
24
- );
25
- }
@@ -1,18 +0,0 @@
1
- import { BottomTabBarButtonProps } from "@react-navigation/bottom-tabs";
2
- import { PlatformPressable } from "@react-navigation/elements";
3
- import * as Haptics from "expo-haptics";
4
-
5
- export function HapticTab(props: BottomTabBarButtonProps) {
6
- return (
7
- <PlatformPressable
8
- {...props}
9
- onPressIn={(ev) => {
10
- if (process.env.EXPO_OS === "ios") {
11
- // Add a soft haptic feedback when pressing down on the tabs.
12
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
13
- }
14
- props.onPressIn?.(ev);
15
- }}
16
- />
17
- );
18
- }
@@ -1,20 +0,0 @@
1
- import Animated from "react-native-reanimated";
2
-
3
- export function HelloWave() {
4
- return (
5
- <Animated.Text
6
- style={{
7
- fontSize: 28,
8
- lineHeight: 32,
9
- marginTop: -6,
10
- animationName: {
11
- "50%": { transform: [{ rotate: "25deg" }] },
12
- },
13
- animationIterationCount: 4,
14
- animationDuration: "300ms",
15
- }}
16
- >
17
- 👋
18
- </Animated.Text>
19
- );
20
- }
@@ -1,81 +0,0 @@
1
- import type { PropsWithChildren, ReactElement } from "react";
2
- import { StyleSheet } from "react-native";
3
- import Animated, {
4
- interpolate,
5
- useAnimatedRef,
6
- useAnimatedStyle,
7
- useScrollOffset,
8
- } from "react-native-reanimated";
9
-
10
- import { ThemedView } from "@/components/themed-view";
11
- import { useColorScheme } from "@/hooks/use-color-scheme";
12
- import { useThemeColor } from "@/hooks/use-theme-color";
13
-
14
- const HEADER_HEIGHT = 250;
15
-
16
- type Props = PropsWithChildren<{
17
- headerImage: ReactElement;
18
- headerBackgroundColor: { dark: string; light: string };
19
- }>;
20
-
21
- export default function ParallaxScrollView({
22
- children,
23
- headerImage,
24
- headerBackgroundColor,
25
- }: Props) {
26
- const backgroundColor = useThemeColor({}, "background");
27
- const colorScheme = useColorScheme() ?? "light";
28
- const scrollRef = useAnimatedRef<Animated.ScrollView>();
29
- const scrollOffset = useScrollOffset(scrollRef);
30
- const headerAnimatedStyle = useAnimatedStyle(() => {
31
- return {
32
- transform: [
33
- {
34
- translateY: interpolate(
35
- scrollOffset.value,
36
- [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
37
- [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75],
38
- ),
39
- },
40
- {
41
- scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
42
- },
43
- ],
44
- };
45
- });
46
-
47
- return (
48
- <Animated.ScrollView
49
- ref={scrollRef}
50
- style={{ backgroundColor, flex: 1 }}
51
- scrollEventThrottle={16}
52
- >
53
- <Animated.View
54
- style={[
55
- styles.header,
56
- { backgroundColor: headerBackgroundColor[colorScheme] },
57
- headerAnimatedStyle,
58
- ]}
59
- >
60
- {headerImage}
61
- </Animated.View>
62
- <ThemedView style={styles.content}>{children}</ThemedView>
63
- </Animated.ScrollView>
64
- );
65
- }
66
-
67
- const styles = StyleSheet.create({
68
- container: {
69
- flex: 1,
70
- },
71
- header: {
72
- height: HEADER_HEIGHT,
73
- overflow: "hidden",
74
- },
75
- content: {
76
- flex: 1,
77
- padding: 32,
78
- gap: 16,
79
- overflow: "hidden",
80
- },
81
- });
@@ -1,60 +0,0 @@
1
- import { StyleSheet, Text, type TextProps } from "react-native";
2
-
3
- import { useThemeColor } from "@/hooks/use-theme-color";
4
-
5
- export type ThemedTextProps = TextProps & {
6
- lightColor?: string;
7
- darkColor?: string;
8
- type?: "default" | "title" | "defaultSemiBold" | "subtitle" | "link";
9
- };
10
-
11
- export function ThemedText({
12
- style,
13
- lightColor,
14
- darkColor,
15
- type = "default",
16
- ...rest
17
- }: ThemedTextProps) {
18
- const color = useThemeColor({ light: lightColor, dark: darkColor }, "text");
19
-
20
- return (
21
- <Text
22
- style={[
23
- { color },
24
- type === "default" ? styles.default : undefined,
25
- type === "title" ? styles.title : undefined,
26
- type === "defaultSemiBold" ? styles.defaultSemiBold : undefined,
27
- type === "subtitle" ? styles.subtitle : undefined,
28
- type === "link" ? styles.link : undefined,
29
- style,
30
- ]}
31
- {...rest}
32
- />
33
- );
34
- }
35
-
36
- const styles = StyleSheet.create({
37
- default: {
38
- fontSize: 16,
39
- lineHeight: 24,
40
- },
41
- defaultSemiBold: {
42
- fontSize: 16,
43
- lineHeight: 24,
44
- fontWeight: "600",
45
- },
46
- title: {
47
- fontSize: 32,
48
- fontWeight: "bold",
49
- lineHeight: 32,
50
- },
51
- subtitle: {
52
- fontSize: 20,
53
- fontWeight: "bold",
54
- },
55
- link: {
56
- lineHeight: 30,
57
- fontSize: 16,
58
- color: "#0a7ea4",
59
- },
60
- });
@@ -1,14 +0,0 @@
1
- import { View, type ViewProps } from "react-native";
2
-
3
- import { useThemeColor } from "@/hooks/use-theme-color";
4
-
5
- export type ThemedViewProps = ViewProps & {
6
- lightColor?: string;
7
- darkColor?: string;
8
- };
9
-
10
- export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
11
- const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, "background");
12
-
13
- return <View style={[{ backgroundColor }, style]} {...otherProps} />;
14
- }
@@ -1,86 +0,0 @@
1
- import React from "react";
2
- import { TouchableOpacity, Text, StyleSheet, ActivityIndicator, ViewStyle, StyleProp } from "react-native";
3
-
4
- interface ButtonProps {
5
- onPress: () => void;
6
- children: React.ReactNode;
7
- disabled?: boolean;
8
- loading?: boolean;
9
- variant?: "primary" | "secondary" | "outline" | "destructive";
10
- style?: StyleProp<ViewStyle>;
11
- }
12
-
13
- export function Button({
14
- onPress,
15
- children,
16
- disabled,
17
- loading,
18
- variant = "primary",
19
- style
20
- }: ButtonProps) {
21
- const containerStyle = [
22
- styles.button,
23
- styles[variant],
24
- disabled && styles.disabled,
25
- style,
26
- ];
27
-
28
- const textStyle = [
29
- styles.text,
30
- variant === "outline" && styles.outlineText,
31
- disabled && styles.disabledText,
32
- ];
33
-
34
- return (
35
- <TouchableOpacity
36
- style={containerStyle}
37
- onPress={onPress}
38
- disabled={disabled || loading}
39
- >
40
- {loading ? (
41
- <ActivityIndicator color={variant === "outline" ? "#000" : "#fff"} />
42
- ) : (
43
- <Text style={textStyle}>{children}</Text>
44
- )}
45
- </TouchableOpacity>
46
- );
47
- }
48
-
49
- const styles = StyleSheet.create({
50
- button: {
51
- height: 48,
52
- borderRadius: 8,
53
- justifyContent: "center",
54
- alignItems: "center",
55
- paddingHorizontal: 16,
56
- },
57
- primary: {
58
- backgroundColor: "#000",
59
- },
60
- secondary: {
61
- backgroundColor: "#f0f0f0",
62
- },
63
- outline: {
64
- backgroundColor: "transparent",
65
- borderWidth: 1,
66
- borderColor: "#e0e0e0",
67
- },
68
- destructive: {
69
- backgroundColor: "#ef4444",
70
- },
71
- disabled: {
72
- backgroundColor: "#ccc",
73
- borderColor: "#ccc",
74
- },
75
- text: {
76
- color: "#fff",
77
- fontSize: 16,
78
- fontWeight: "600",
79
- },
80
- outlineText: {
81
- color: "#000",
82
- },
83
- disabledText: {
84
- color: "#999",
85
- },
86
- });