@idealyst/cli 1.2.29 → 1.2.31
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/dist/constants.js +1 -1
- package/dist/generators/core/mobile.js +21 -19
- package/dist/generators/core/mobile.js.map +1 -1
- package/dist/generators/core/shared.js +21 -12
- package/dist/generators/core/shared.js.map +1 -1
- package/dist/generators/core/web.js +69 -12
- package/dist/generators/core/web.js.map +1 -1
- package/dist/templates/copier.js +6 -4
- package/dist/templates/copier.js.map +1 -1
- package/dist/templates/core/mobile/src/App.tsx +8 -0
- package/dist/templates/core/mobile/src/utils/trpc.ts +7 -0
- package/dist/templates/core/shared/src/components/App.tsx +13 -0
- package/dist/templates/core/shared/src/components/index.ts +1 -0
- package/dist/templates/core/shared/src/index.ts +10 -0
- package/dist/templates/core/shared/src/layouts/AppLayout.tsx +218 -0
- package/dist/templates/core/shared/src/navigation/AppRouter.tsx +103 -0
- package/dist/templates/core/shared/src/navigation/index.ts +1 -0
- package/dist/templates/core/shared/src/screens/ExploreScreen.tsx +240 -0
- package/dist/templates/core/shared/src/screens/HomeScreen.tsx +151 -0
- package/dist/templates/core/shared/src/screens/ProfileScreen.tsx +222 -0
- package/dist/templates/core/shared/src/screens/SettingsScreen.tsx +218 -0
- package/dist/templates/core/shared/src/screens/index.ts +4 -0
- package/dist/templates/core/shared/src/styles.ts +45 -0
- package/dist/templates/core/web/index.html +25 -0
- package/dist/templates/core/web/public/vite.svg +10 -0
- package/dist/templates/core/web/src/App.tsx +12 -0
- package/dist/templates/core/web/src/main.tsx +16 -0
- package/dist/templates/core/workspace/gitignore.template +78 -0
- package/dist/templates/core/workspace/package.json +24 -0
- package/dist/templates/core/workspace/react-native.config.js +19 -0
- package/dist/templates/core/workspace/tsconfig.json +17 -0
- package/dist/templates/core/workspace/yarnrc.yml.template +6 -0
- package/dist/types/constants.d.ts +5 -5
- package/package.json +3 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Screen,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
Card,
|
|
7
|
+
Button,
|
|
8
|
+
Icon,
|
|
9
|
+
Avatar,
|
|
10
|
+
Badge,
|
|
11
|
+
Divider,
|
|
12
|
+
List,
|
|
13
|
+
ListItem,
|
|
14
|
+
} from '@idealyst/components';
|
|
15
|
+
import { useNavigator } from '@idealyst/navigation';
|
|
16
|
+
|
|
17
|
+
export const ProfileScreen: React.FC = () => {
|
|
18
|
+
const { navigate } = useNavigator();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Screen background="primary" padding="lg" scrollable>
|
|
22
|
+
<View gap="lg">
|
|
23
|
+
{/* Profile Header */}
|
|
24
|
+
<Card type="elevated" padding="lg">
|
|
25
|
+
<View style={{ alignItems: 'center', gap: 16 }}>
|
|
26
|
+
<View style={{ position: 'relative' }}>
|
|
27
|
+
<Avatar
|
|
28
|
+
size="xl"
|
|
29
|
+
src={{ uri: 'https://i.pravatar.cc/150?img=68' }}
|
|
30
|
+
fallback="JD"
|
|
31
|
+
/>
|
|
32
|
+
</View>
|
|
33
|
+
|
|
34
|
+
<View style={{ alignItems: 'center', gap: 4 }}>
|
|
35
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
36
|
+
<Text typography="h4">Jane Doe</Text>
|
|
37
|
+
<Badge intent="primary" size="sm">
|
|
38
|
+
Verified
|
|
39
|
+
</Badge>
|
|
40
|
+
</View>
|
|
41
|
+
<Text color="secondary">@janedoe</Text>
|
|
42
|
+
<Text typography="caption" color="secondary" style={{ textAlign: 'center' }}>
|
|
43
|
+
Senior Developer at Idealyst. Building cross-platform apps with
|
|
44
|
+
React Native.
|
|
45
|
+
</Text>
|
|
46
|
+
</View>
|
|
47
|
+
|
|
48
|
+
<View style={{ flexDirection: 'row', gap: 12 }}>
|
|
49
|
+
<Button
|
|
50
|
+
style={{ flex: 1 }}
|
|
51
|
+
intent="primary"
|
|
52
|
+
leftIcon={'pencil-outline'}
|
|
53
|
+
>
|
|
54
|
+
Edit Profile
|
|
55
|
+
</Button>
|
|
56
|
+
<Button
|
|
57
|
+
style={{ flex: 1 }}
|
|
58
|
+
type="outlined"
|
|
59
|
+
intent="neutral"
|
|
60
|
+
leftIcon={'share-outline'}
|
|
61
|
+
>
|
|
62
|
+
Share
|
|
63
|
+
</Button>
|
|
64
|
+
</View>
|
|
65
|
+
</View>
|
|
66
|
+
|
|
67
|
+
<Divider />
|
|
68
|
+
|
|
69
|
+
{/* Stats */}
|
|
70
|
+
<View
|
|
71
|
+
style={{
|
|
72
|
+
flexDirection: 'row',
|
|
73
|
+
justifyContent: 'space-around',
|
|
74
|
+
paddingVertical: 16,
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<View style={{ alignItems: 'center' }}>
|
|
78
|
+
<Text typography="h4">1.2k</Text>
|
|
79
|
+
<Text typography="caption" color="secondary">
|
|
80
|
+
Followers
|
|
81
|
+
</Text>
|
|
82
|
+
</View>
|
|
83
|
+
<View style={{ alignItems: 'center' }}>
|
|
84
|
+
<Text typography="h4">856</Text>
|
|
85
|
+
<Text typography="caption" color="secondary">
|
|
86
|
+
Following
|
|
87
|
+
</Text>
|
|
88
|
+
</View>
|
|
89
|
+
<View style={{ alignItems: 'center' }}>
|
|
90
|
+
<Text typography="h4">42</Text>
|
|
91
|
+
<Text typography="caption" color="secondary">
|
|
92
|
+
Projects
|
|
93
|
+
</Text>
|
|
94
|
+
</View>
|
|
95
|
+
</View>
|
|
96
|
+
</Card>
|
|
97
|
+
|
|
98
|
+
{/* Achievements */}
|
|
99
|
+
<View gap="md">
|
|
100
|
+
<View
|
|
101
|
+
style={{
|
|
102
|
+
flexDirection: 'row',
|
|
103
|
+
alignItems: 'center',
|
|
104
|
+
justifyContent: 'space-between',
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<Text typography="subtitle1">Achievements</Text>
|
|
108
|
+
<Text typography="caption" color="primary">
|
|
109
|
+
View All
|
|
110
|
+
</Text>
|
|
111
|
+
</View>
|
|
112
|
+
<View style={{ flexDirection: 'row', gap: 12 }}>
|
|
113
|
+
<Card
|
|
114
|
+
type="outlined"
|
|
115
|
+
padding="md"
|
|
116
|
+
style={{ flex: 1, alignItems: 'center' }}
|
|
117
|
+
>
|
|
118
|
+
<View
|
|
119
|
+
style={{
|
|
120
|
+
width: 48,
|
|
121
|
+
height: 48,
|
|
122
|
+
borderRadius: 24,
|
|
123
|
+
backgroundColor: '#fef3c7',
|
|
124
|
+
alignItems: 'center',
|
|
125
|
+
justifyContent: 'center',
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<Icon name="trophy" size={24} color="#f59e0b" />
|
|
129
|
+
</View>
|
|
130
|
+
<Text typography="caption" weight="medium">
|
|
131
|
+
Top Contributor
|
|
132
|
+
</Text>
|
|
133
|
+
</Card>
|
|
134
|
+
<Card
|
|
135
|
+
type="outlined"
|
|
136
|
+
padding="md"
|
|
137
|
+
style={{ flex: 1, alignItems: 'center' }}
|
|
138
|
+
>
|
|
139
|
+
<View
|
|
140
|
+
style={{
|
|
141
|
+
width: 48,
|
|
142
|
+
height: 48,
|
|
143
|
+
borderRadius: 24,
|
|
144
|
+
backgroundColor: '#dbeafe',
|
|
145
|
+
alignItems: 'center',
|
|
146
|
+
justifyContent: 'center',
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<Icon name="star" size={24} color="#3b82f6" />
|
|
150
|
+
</View>
|
|
151
|
+
<Text typography="caption" weight="medium">
|
|
152
|
+
Rising Star
|
|
153
|
+
</Text>
|
|
154
|
+
</Card>
|
|
155
|
+
<Card
|
|
156
|
+
type="outlined"
|
|
157
|
+
padding="md"
|
|
158
|
+
style={{ flex: 1, alignItems: 'center' }}
|
|
159
|
+
>
|
|
160
|
+
<View
|
|
161
|
+
style={{
|
|
162
|
+
width: 48,
|
|
163
|
+
height: 48,
|
|
164
|
+
borderRadius: 24,
|
|
165
|
+
backgroundColor: '#dcfce7',
|
|
166
|
+
alignItems: 'center',
|
|
167
|
+
justifyContent: 'center',
|
|
168
|
+
}}
|
|
169
|
+
>
|
|
170
|
+
<Icon name="rocket-launch" size={24} color="#22c55e" />
|
|
171
|
+
</View>
|
|
172
|
+
<Text typography="caption" weight="medium">
|
|
173
|
+
Early Adopter
|
|
174
|
+
</Text>
|
|
175
|
+
</Card>
|
|
176
|
+
</View>
|
|
177
|
+
</View>
|
|
178
|
+
|
|
179
|
+
{/* Menu */}
|
|
180
|
+
<View gap="md">
|
|
181
|
+
<Text typography="subtitle1">Account</Text>
|
|
182
|
+
<Card type="outlined">
|
|
183
|
+
<List>
|
|
184
|
+
<ListItem
|
|
185
|
+
label="Settings"
|
|
186
|
+
leading={<Icon name="cog-outline" size={24} />}
|
|
187
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
188
|
+
onPress={() => navigate({ path: '/settings' })}
|
|
189
|
+
/>
|
|
190
|
+
<ListItem
|
|
191
|
+
label="Notifications"
|
|
192
|
+
leading={<Icon name="bell-outline" size={24} />}
|
|
193
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
194
|
+
/>
|
|
195
|
+
<ListItem
|
|
196
|
+
label="Privacy & Security"
|
|
197
|
+
leading={<Icon name="shield-check-outline" size={24} />}
|
|
198
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
199
|
+
/>
|
|
200
|
+
<ListItem
|
|
201
|
+
label="Help & Support"
|
|
202
|
+
leading={<Icon name="help-circle-outline" size={24} />}
|
|
203
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
204
|
+
/>
|
|
205
|
+
</List>
|
|
206
|
+
</Card>
|
|
207
|
+
</View>
|
|
208
|
+
|
|
209
|
+
{/* Logout */}
|
|
210
|
+
<Button
|
|
211
|
+
type="outlined"
|
|
212
|
+
intent="danger"
|
|
213
|
+
leftIcon={'logout'}
|
|
214
|
+
>
|
|
215
|
+
Log Out
|
|
216
|
+
</Button>
|
|
217
|
+
</View>
|
|
218
|
+
</Screen>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export default ProfileScreen;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Screen,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
Card,
|
|
7
|
+
Button,
|
|
8
|
+
Icon,
|
|
9
|
+
Switch,
|
|
10
|
+
Divider,
|
|
11
|
+
List,
|
|
12
|
+
ListItem,
|
|
13
|
+
} from '@idealyst/components';
|
|
14
|
+
import { useNavigator } from '@idealyst/navigation';
|
|
15
|
+
import { UnistylesRuntime } from 'react-native-unistyles';
|
|
16
|
+
|
|
17
|
+
export const SettingsScreen: React.FC = () => {
|
|
18
|
+
const { goBack, canGoBack } = useNavigator();
|
|
19
|
+
const [theme, setTheme] = useState(UnistylesRuntime.themeName || 'light');
|
|
20
|
+
const isDarkMode = theme === 'dark';
|
|
21
|
+
|
|
22
|
+
const handleThemeToggle = () => {
|
|
23
|
+
const newTheme = isDarkMode ? 'light' : 'dark';
|
|
24
|
+
setTheme(newTheme);
|
|
25
|
+
UnistylesRuntime.setTheme(newTheme);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const selectTheme = (theme: 'light' | 'dark') => {
|
|
29
|
+
setTheme(theme);
|
|
30
|
+
UnistylesRuntime.setTheme(theme);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Screen background="primary" padding="lg" scrollable>
|
|
35
|
+
<View gap="lg">
|
|
36
|
+
{/* Header with back button */}
|
|
37
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
38
|
+
{canGoBack() && (
|
|
39
|
+
<Button
|
|
40
|
+
type="text"
|
|
41
|
+
size="sm"
|
|
42
|
+
onPress={() => goBack()}
|
|
43
|
+
leftIcon={<Icon name="arrow-left" size={20} />}
|
|
44
|
+
>
|
|
45
|
+
Back
|
|
46
|
+
</Button>
|
|
47
|
+
)}
|
|
48
|
+
<Text typography="h3">Settings</Text>
|
|
49
|
+
</View>
|
|
50
|
+
|
|
51
|
+
{/* Appearance Section */}
|
|
52
|
+
<View gap="md">
|
|
53
|
+
<Text typography="subtitle1" color="secondary">
|
|
54
|
+
APPEARANCE
|
|
55
|
+
</Text>
|
|
56
|
+
|
|
57
|
+
<Card type="outlined">
|
|
58
|
+
{/* Dark Mode Toggle */}
|
|
59
|
+
<View
|
|
60
|
+
padding="md"
|
|
61
|
+
style={{
|
|
62
|
+
flexDirection: 'row',
|
|
63
|
+
alignItems: 'center',
|
|
64
|
+
justifyContent: 'space-between',
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12, flex: 1 }}>
|
|
68
|
+
<View
|
|
69
|
+
radius="md"
|
|
70
|
+
style={{
|
|
71
|
+
width: 40,
|
|
72
|
+
height: 40,
|
|
73
|
+
alignItems: 'center',
|
|
74
|
+
justifyContent: 'center',
|
|
75
|
+
backgroundColor: isDarkMode ? '#312e81' : '#fef3c7',
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
<Icon
|
|
79
|
+
name={isDarkMode ? 'moon-waning-crescent' : 'white-balance-sunny'}
|
|
80
|
+
size={22}
|
|
81
|
+
color={isDarkMode ? '#a5b4fc' : '#f59e0b'}
|
|
82
|
+
/>
|
|
83
|
+
</View>
|
|
84
|
+
<View style={{ flex: 1 }}>
|
|
85
|
+
<Text weight="medium">Dark Mode</Text>
|
|
86
|
+
<Text typography="caption" color="secondary">
|
|
87
|
+
{isDarkMode ? 'Currently using dark theme' : 'Currently using light theme'}
|
|
88
|
+
</Text>
|
|
89
|
+
</View>
|
|
90
|
+
</View>
|
|
91
|
+
<Switch checked={isDarkMode} onChange={handleThemeToggle} intent="primary" />
|
|
92
|
+
</View>
|
|
93
|
+
|
|
94
|
+
<Divider />
|
|
95
|
+
|
|
96
|
+
{/* Theme Preview Cards */}
|
|
97
|
+
<View padding="md" style={{ flexDirection: 'row', gap: 12 }}>
|
|
98
|
+
{/* Light Theme */}
|
|
99
|
+
<Card
|
|
100
|
+
type="outlined"
|
|
101
|
+
clickable
|
|
102
|
+
onPress={() => selectTheme('light')}
|
|
103
|
+
intent={theme === 'light' ? 'primary' : 'neutral'}
|
|
104
|
+
style={{ flex: 1, padding: 0, overflow: 'hidden' }}
|
|
105
|
+
>
|
|
106
|
+
<View style={{ padding: 12, gap: 8, backgroundColor: '#ffffff' }}>
|
|
107
|
+
<View style={{ height: 8, borderRadius: 4, backgroundColor: '#e5e5e5' }} />
|
|
108
|
+
<View
|
|
109
|
+
style={{ height: 8, borderRadius: 4, backgroundColor: '#e5e5e5', width: '80%' }}
|
|
110
|
+
/>
|
|
111
|
+
<View
|
|
112
|
+
style={{ height: 8, borderRadius: 4, backgroundColor: '#3b82f6', width: '60%' }}
|
|
113
|
+
/>
|
|
114
|
+
</View>
|
|
115
|
+
<View background="secondary" padding="sm" style={{ alignItems: 'center' }}>
|
|
116
|
+
<Text typography="caption" weight="medium">
|
|
117
|
+
Light
|
|
118
|
+
</Text>
|
|
119
|
+
</View>
|
|
120
|
+
</Card>
|
|
121
|
+
|
|
122
|
+
{/* Dark Theme */}
|
|
123
|
+
<Card
|
|
124
|
+
type="outlined"
|
|
125
|
+
clickable
|
|
126
|
+
onPress={() => selectTheme('dark')}
|
|
127
|
+
intent={theme === 'dark' ? 'primary' : 'neutral'}
|
|
128
|
+
style={{ flex: 1, padding: 0, overflow: 'hidden' }}
|
|
129
|
+
>
|
|
130
|
+
<View style={{ padding: 12, gap: 8, backgroundColor: '#1a1a1a' }}>
|
|
131
|
+
<View style={{ height: 8, borderRadius: 4, backgroundColor: '#333333' }} />
|
|
132
|
+
<View
|
|
133
|
+
style={{ height: 8, borderRadius: 4, backgroundColor: '#333333', width: '80%' }}
|
|
134
|
+
/>
|
|
135
|
+
<View
|
|
136
|
+
style={{ height: 8, borderRadius: 4, backgroundColor: '#3b82f6', width: '60%' }}
|
|
137
|
+
/>
|
|
138
|
+
</View>
|
|
139
|
+
<View background="secondary" padding="sm" style={{ alignItems: 'center' }}>
|
|
140
|
+
<Text typography="caption" weight="medium">
|
|
141
|
+
Dark
|
|
142
|
+
</Text>
|
|
143
|
+
</View>
|
|
144
|
+
</Card>
|
|
145
|
+
</View>
|
|
146
|
+
</Card>
|
|
147
|
+
</View>
|
|
148
|
+
|
|
149
|
+
{/* Preferences Section */}
|
|
150
|
+
<View gap="md">
|
|
151
|
+
<Text typography="subtitle1" color="secondary">
|
|
152
|
+
PREFERENCES
|
|
153
|
+
</Text>
|
|
154
|
+
|
|
155
|
+
<Card type="outlined">
|
|
156
|
+
<List>
|
|
157
|
+
<ListItem
|
|
158
|
+
label="Notifications"
|
|
159
|
+
leading={<Icon name="bell-outline" size={24} />}
|
|
160
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
161
|
+
/>
|
|
162
|
+
<ListItem
|
|
163
|
+
label="Language"
|
|
164
|
+
leading={<Icon name="translate" size={24} />}
|
|
165
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
166
|
+
/>
|
|
167
|
+
<ListItem
|
|
168
|
+
label="Accessibility"
|
|
169
|
+
leading={<Icon name="human" size={24} />}
|
|
170
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
171
|
+
/>
|
|
172
|
+
</List>
|
|
173
|
+
</Card>
|
|
174
|
+
</View>
|
|
175
|
+
|
|
176
|
+
{/* About Section */}
|
|
177
|
+
<View gap="md">
|
|
178
|
+
<Text typography="subtitle1" color="secondary">
|
|
179
|
+
ABOUT
|
|
180
|
+
</Text>
|
|
181
|
+
|
|
182
|
+
<Card type="outlined">
|
|
183
|
+
<List>
|
|
184
|
+
<ListItem
|
|
185
|
+
label="Privacy Policy"
|
|
186
|
+
leading={<Icon name="shield-check-outline" size={24} />}
|
|
187
|
+
trailing={<Icon name="open-in-new" size={20} />}
|
|
188
|
+
/>
|
|
189
|
+
<ListItem
|
|
190
|
+
label="Terms of Service"
|
|
191
|
+
leading={<Icon name="file-document-outline" size={24} />}
|
|
192
|
+
trailing={<Icon name="open-in-new" size={20} />}
|
|
193
|
+
/>
|
|
194
|
+
<ListItem
|
|
195
|
+
label="Licenses"
|
|
196
|
+
leading={<Icon name="license" size={24} />}
|
|
197
|
+
trailing={<Icon name="chevron-right" size={20} />}
|
|
198
|
+
/>
|
|
199
|
+
</List>
|
|
200
|
+
</Card>
|
|
201
|
+
</View>
|
|
202
|
+
|
|
203
|
+
{/* Version Info */}
|
|
204
|
+
<View style={{ alignItems: 'center', paddingVertical: 24, gap: 4 }}>
|
|
205
|
+
<Icon name="application-outline" size={32} textColor='primary' />
|
|
206
|
+
<Text typography="caption" color="secondary">
|
|
207
|
+
{{appDisplayName}}
|
|
208
|
+
</Text>
|
|
209
|
+
<Text typography="caption" color="secondary">
|
|
210
|
+
Version {{version}} | Theme: {theme}
|
|
211
|
+
</Text>
|
|
212
|
+
</View>
|
|
213
|
+
</View>
|
|
214
|
+
</Screen>
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
export default SettingsScreen;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { lightTheme, darkTheme, fromTheme } from '@idealyst/theme';
|
|
2
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
+
|
|
4
|
+
// Build themes using fromTheme() for proper babel plugin analysis
|
|
5
|
+
export const customLightTheme = fromTheme(lightTheme).build();
|
|
6
|
+
|
|
7
|
+
// Define AppTheme type based on customLightTheme (dark theme should conform)
|
|
8
|
+
type AppTheme = typeof customLightTheme
|
|
9
|
+
|
|
10
|
+
export const customDarkTheme: AppTheme = fromTheme(darkTheme).build();
|
|
11
|
+
|
|
12
|
+
// Register theme in Idealyst Theme Registry for type safety
|
|
13
|
+
declare module '@idealyst/theme' {
|
|
14
|
+
interface CustomThemeRegistry {
|
|
15
|
+
theme: AppTheme;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Extend UnistylesThemes type declaration
|
|
20
|
+
declare module 'react-native-unistyles' {
|
|
21
|
+
export interface UnistylesThemes {
|
|
22
|
+
light: AppTheme;
|
|
23
|
+
dark: AppTheme;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Configure Unistyles with standard Idealyst themes
|
|
28
|
+
StyleSheet.configure({
|
|
29
|
+
themes: {
|
|
30
|
+
light: customLightTheme,
|
|
31
|
+
dark: customDarkTheme,
|
|
32
|
+
},
|
|
33
|
+
settings: {
|
|
34
|
+
initialTheme: 'light',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Export theme names for easy reference
|
|
39
|
+
export const availableThemes = ['light', 'dark'] as const;
|
|
40
|
+
export type AvailableTheme = (typeof availableThemes)[number];
|
|
41
|
+
|
|
42
|
+
// Helper function to toggle theme
|
|
43
|
+
export function toggleTheme(currentTheme: string): AvailableTheme {
|
|
44
|
+
return currentTheme === 'light' ? 'dark' : 'light';
|
|
45
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>{{appDisplayName}}</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
html, body, #root {
|
|
13
|
+
margin: 0;
|
|
14
|
+
padding: 0;
|
|
15
|
+
height: 100%;
|
|
16
|
+
width: 100%;
|
|
17
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div id="root"></div>
|
|
23
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />
|
|
5
|
+
<stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:1" />
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect width="100" height="100" rx="20" fill="url(#grad)"/>
|
|
9
|
+
<text x="50" y="65" font-family="Arial, sans-serif" font-size="45" font-weight="bold" fill="white" text-anchor="middle">I</text>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Initialize unistyles BEFORE anything else
|
|
2
|
+
// import '@{{workspaceScope}}/shared/styles';
|
|
3
|
+
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import ReactDOM from 'react-dom/client';
|
|
6
|
+
import App from './App';
|
|
7
|
+
|
|
8
|
+
// Render the app
|
|
9
|
+
const container = document.getElementById('root')!;
|
|
10
|
+
const root = ReactDOM.createRoot(container);
|
|
11
|
+
|
|
12
|
+
root.render(
|
|
13
|
+
<React.StrictMode>
|
|
14
|
+
<App />
|
|
15
|
+
</React.StrictMode>
|
|
16
|
+
);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# AI/Tool configs
|
|
2
|
+
.claude/
|
|
3
|
+
.serena/
|
|
4
|
+
.playwright/
|
|
5
|
+
|
|
6
|
+
# Dependencies
|
|
7
|
+
node_modules/
|
|
8
|
+
.yarn/*
|
|
9
|
+
!.yarn/patches
|
|
10
|
+
!.yarn/plugins
|
|
11
|
+
!.yarn/releases
|
|
12
|
+
!.yarn/sdks
|
|
13
|
+
!.yarn/versions
|
|
14
|
+
|
|
15
|
+
# Build outputs
|
|
16
|
+
dist/
|
|
17
|
+
build/
|
|
18
|
+
.cache/
|
|
19
|
+
*.tsbuildinfo
|
|
20
|
+
|
|
21
|
+
# Environment
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
.env.*.local
|
|
25
|
+
|
|
26
|
+
# IDE
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
29
|
+
*.swp
|
|
30
|
+
*.swo
|
|
31
|
+
|
|
32
|
+
# OS
|
|
33
|
+
.DS_Store
|
|
34
|
+
Thumbs.db
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
coverage/
|
|
38
|
+
.jest/
|
|
39
|
+
|
|
40
|
+
# Mobile
|
|
41
|
+
ios/Pods/
|
|
42
|
+
android/.gradle/
|
|
43
|
+
android/app/build/
|
|
44
|
+
*.keystore
|
|
45
|
+
*.jks
|
|
46
|
+
|
|
47
|
+
# Logs
|
|
48
|
+
*.log
|
|
49
|
+
npm-debug.log*
|
|
50
|
+
yarn-debug.log*
|
|
51
|
+
yarn-error.log*
|
|
52
|
+
|
|
53
|
+
# Misc
|
|
54
|
+
*.tmp
|
|
55
|
+
*.bak
|
|
56
|
+
|
|
57
|
+
# Turborepo
|
|
58
|
+
.turbo/
|
|
59
|
+
|
|
60
|
+
# Linting
|
|
61
|
+
.eslintcache
|
|
62
|
+
|
|
63
|
+
# SSL
|
|
64
|
+
*.pem
|
|
65
|
+
|
|
66
|
+
# Deployment
|
|
67
|
+
.vercel/
|
|
68
|
+
.netlify/
|
|
69
|
+
|
|
70
|
+
# Expo
|
|
71
|
+
.expo/
|
|
72
|
+
.expo-shared/
|
|
73
|
+
|
|
74
|
+
# Metro
|
|
75
|
+
.metro-health-check*
|
|
76
|
+
|
|
77
|
+
# Watchman
|
|
78
|
+
.watchman-*
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@{{workspaceScope}}/{{projectName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"private": true,
|
|
5
|
+
"packageManager": "yarn@4.1.0",
|
|
6
|
+
"workspaces": [
|
|
7
|
+
"packages/*"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "yarn workspace @{{workspaceScope}}/web dev",
|
|
11
|
+
"build": "yarn workspace @{{workspaceScope}}/web build",
|
|
12
|
+
"preview": "yarn workspace @{{workspaceScope}}/web preview",
|
|
13
|
+
"start:mobile": "yarn workspace @{{workspaceScope}}/mobile start",
|
|
14
|
+
"android": "yarn workspace @{{workspaceScope}}/mobile android",
|
|
15
|
+
"ios": "yarn workspace @{{workspaceScope}}/mobile ios"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"concurrently": "^9.0.0",
|
|
19
|
+
"jest": "^29.7.0",
|
|
20
|
+
"@types/jest": "^29.5.0",
|
|
21
|
+
"ts-jest": "^29.1.0",
|
|
22
|
+
"typescript": "^5.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native configuration for monorepo setup
|
|
3
|
+
*
|
|
4
|
+
* This file tells the React Native CLI where to find the mobile project
|
|
5
|
+
* and its dependencies in a Yarn workspace monorepo structure.
|
|
6
|
+
*/
|
|
7
|
+
module.exports = {
|
|
8
|
+
project: {
|
|
9
|
+
android: {
|
|
10
|
+
sourceDir: './packages/mobile/android',
|
|
11
|
+
appName: 'app',
|
|
12
|
+
packageName: '{{androidPackageName}}',
|
|
13
|
+
},
|
|
14
|
+
ios: {
|
|
15
|
+
sourceDir: './packages/mobile/ios',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
// Dependencies are auto-detected from node_modules
|
|
19
|
+
};
|