expo-bbase 1.6.1 → 1.7.1
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/index.js +248 -324
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -37,11 +37,12 @@ __export(src_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(src_exports);
|
|
39
39
|
var import_chalk = __toESM(require("chalk"));
|
|
40
|
-
var
|
|
40
|
+
var import_commander = require("commander");
|
|
41
|
+
var import_execa = require("execa");
|
|
42
|
+
var import_fs_extra2 = __toESM(require("fs-extra"));
|
|
41
43
|
var import_ora = __toESM(require("ora"));
|
|
42
44
|
var import_path2 = __toESM(require("path"));
|
|
43
|
-
var
|
|
44
|
-
var import_commander = require("commander");
|
|
45
|
+
var import_prompts = __toESM(require("prompts"));
|
|
45
46
|
|
|
46
47
|
// src/commands/create.ts
|
|
47
48
|
function registerCreateCommand(program) {
|
|
@@ -2527,19 +2528,6 @@ var uiReusablesModule = {
|
|
|
2527
2528
|
},
|
|
2528
2529
|
devDependencies: {},
|
|
2529
2530
|
files: [
|
|
2530
|
-
// ─── lib/utils.ts ────────────────────────────────────────────────────
|
|
2531
|
-
{
|
|
2532
|
-
path: "lib/utils.ts",
|
|
2533
|
-
content: lines(
|
|
2534
|
-
'import { type ClassValue, clsx } from "clsx";',
|
|
2535
|
-
'import { twMerge } from "tailwind-merge";',
|
|
2536
|
-
"",
|
|
2537
|
-
"export function cn(...inputs: ClassValue[]) {",
|
|
2538
|
-
" return twMerge(clsx(inputs));",
|
|
2539
|
-
"}",
|
|
2540
|
-
""
|
|
2541
|
-
)
|
|
2542
|
-
},
|
|
2543
2531
|
// ─── components/ui/text.tsx ──────────────────────────────────────────
|
|
2544
2532
|
{
|
|
2545
2533
|
path: "components/ui/text.tsx",
|
|
@@ -3152,8 +3140,8 @@ import { Stack } from "expo-router";
|
|
|
3152
3140
|
import * as SplashScreen from "expo-splash-screen";
|
|
3153
3141
|
import { useEffect } from "react";
|
|
3154
3142
|
import { useColorScheme } from "react-native";
|
|
3155
|
-
|
|
3156
|
-
import {
|
|
3143
|
+
import { PortalHost } from "@rn-primitives/portal";
|
|
3144
|
+
import { NAV_THEME } from "@/lib/theme";
|
|
3157
3145
|
|
|
3158
3146
|
SplashScreen.preventAutoHideAsync();
|
|
3159
3147
|
|
|
@@ -3174,11 +3162,12 @@ export default function RootLayout() {
|
|
|
3174
3162
|
}
|
|
3175
3163
|
|
|
3176
3164
|
return (
|
|
3177
|
-
<ThemeProvider value={colorScheme === "dark" ?
|
|
3165
|
+
<ThemeProvider value={colorScheme === "dark" ? NAV_THEME.dark : NAV_THEME.light}>
|
|
3178
3166
|
<Stack>
|
|
3179
3167
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
3180
3168
|
<Stack.Screen name="+not-found" />
|
|
3181
3169
|
</Stack>
|
|
3170
|
+
<PortalHost />
|
|
3182
3171
|
</ThemeProvider>
|
|
3183
3172
|
);
|
|
3184
3173
|
}
|
|
@@ -3190,19 +3179,10 @@ export default function RootLayout() {
|
|
|
3190
3179
|
content: `import { Tabs } from "expo-router";
|
|
3191
3180
|
import { Platform } from "react-native";
|
|
3192
3181
|
|
|
3193
|
-
import { Colors } from "@/constants/Colors";
|
|
3194
|
-
import { useColorScheme } from "@/hooks/useColorScheme";
|
|
3195
|
-
|
|
3196
3182
|
export default function TabLayout() {
|
|
3197
|
-
const colorScheme = useColorScheme();
|
|
3198
|
-
|
|
3199
3183
|
return (
|
|
3200
3184
|
<Tabs
|
|
3201
3185
|
screenOptions={{
|
|
3202
|
-
tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
|
|
3203
|
-
headerStyle: {
|
|
3204
|
-
backgroundColor: Colors[colorScheme ?? "light"].background,
|
|
3205
|
-
},
|
|
3206
3186
|
headerShadowVisible: false,
|
|
3207
3187
|
tabBarStyle: Platform.select({
|
|
3208
3188
|
ios: {
|
|
@@ -3216,14 +3196,14 @@ export default function TabLayout() {
|
|
|
3216
3196
|
name="index"
|
|
3217
3197
|
options={{
|
|
3218
3198
|
title: "Home",
|
|
3219
|
-
tabBarIcon: () =>
|
|
3199
|
+
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
|
|
3220
3200
|
}}
|
|
3221
3201
|
/>
|
|
3222
3202
|
<Tabs.Screen
|
|
3223
3203
|
name="explore"
|
|
3224
3204
|
options={{
|
|
3225
3205
|
title: "Explore",
|
|
3226
|
-
tabBarIcon: () =>
|
|
3206
|
+
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
|
|
3227
3207
|
}}
|
|
3228
3208
|
/>
|
|
3229
3209
|
</Tabs>
|
|
@@ -3234,258 +3214,152 @@ export default function TabLayout() {
|
|
|
3234
3214
|
// ─── app/(tabs)/index.tsx ───────────────────────────────────────────
|
|
3235
3215
|
{
|
|
3236
3216
|
path: "app/(tabs)/index.tsx",
|
|
3237
|
-
content: `import {
|
|
3238
|
-
import { HelloWave } from "@/components/HelloWave";
|
|
3239
|
-
import { ThemedText } from "@/components/Themed";
|
|
3240
|
-
import { ThemedView } from "@/components/Themed";
|
|
3241
|
-
import { Link } from "expo-router";
|
|
3217
|
+
content: `import { Text, View } from "react-native";
|
|
3242
3218
|
|
|
3243
3219
|
export default function HomeScreen() {
|
|
3244
3220
|
return (
|
|
3245
|
-
<
|
|
3246
|
-
<
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
</ThemedView>
|
|
3250
|
-
<ThemedView style={styles.stepContainer}>
|
|
3251
|
-
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
|
3252
|
-
<ThemedText>
|
|
3253
|
-
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
|
3254
|
-
Press{" "}
|
|
3255
|
-
<ThemedText type="defaultSemiBold">
|
|
3256
|
-
{Platform.select({ ios: "cmd + d", android: "cmd + m" })}
|
|
3257
|
-
</ThemedText>{" "}
|
|
3258
|
-
to open developer tools.
|
|
3259
|
-
</ThemedText>
|
|
3260
|
-
</ThemedView>
|
|
3261
|
-
<ThemedView style={styles.stepContainer}>
|
|
3262
|
-
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
|
3263
|
-
<ThemedText>
|
|
3264
|
-
Tap the Explore tab to learn more about what's included in this starter.
|
|
3265
|
-
</ThemedText>
|
|
3266
|
-
<Link href="/explore">
|
|
3267
|
-
<ThemedText type="link">Go to Explore \u2192</ThemedText>
|
|
3268
|
-
</Link>
|
|
3269
|
-
</ThemedView>
|
|
3270
|
-
</ThemedView>
|
|
3221
|
+
<View className="flex-1 items-center justify-center p-6">
|
|
3222
|
+
<Text className="text-foreground text-2xl font-bold">${projectName}</Text>
|
|
3223
|
+
<Text className="text-muted-foreground mt-2">Welcome to your new app</Text>
|
|
3224
|
+
</View>
|
|
3271
3225
|
);
|
|
3272
3226
|
}
|
|
3273
|
-
|
|
3274
|
-
const styles = StyleSheet.create({
|
|
3275
|
-
container: {
|
|
3276
|
-
flex: 1,
|
|
3277
|
-
alignItems: "center",
|
|
3278
|
-
justifyContent: "center",
|
|
3279
|
-
},
|
|
3280
|
-
titleContainer: {
|
|
3281
|
-
flexDirection: "row",
|
|
3282
|
-
alignItems: "center",
|
|
3283
|
-
gap: 8,
|
|
3284
|
-
},
|
|
3285
|
-
stepContainer: {
|
|
3286
|
-
gap: 8,
|
|
3287
|
-
marginBottom: 8,
|
|
3288
|
-
},
|
|
3289
|
-
});
|
|
3290
3227
|
`
|
|
3291
3228
|
},
|
|
3292
3229
|
// ─── app/(tabs)/explore.tsx ─────────────────────────────────────────
|
|
3293
3230
|
{
|
|
3294
3231
|
path: "app/(tabs)/explore.tsx",
|
|
3295
|
-
content: `import {
|
|
3296
|
-
import { ThemedText } from "@/components/Themed";
|
|
3297
|
-
import { ThemedView } from "@/components/Themed";
|
|
3232
|
+
content: `import { Text, View } from "react-native";
|
|
3298
3233
|
|
|
3299
3234
|
export default function ExploreScreen() {
|
|
3300
3235
|
return (
|
|
3301
|
-
<
|
|
3302
|
-
<
|
|
3303
|
-
<
|
|
3304
|
-
|
|
3305
|
-
</ThemedText>
|
|
3306
|
-
</ThemedView>
|
|
3236
|
+
<View className="flex-1 items-center justify-center p-6">
|
|
3237
|
+
<Text className="text-foreground text-2xl font-bold">Explore</Text>
|
|
3238
|
+
<Text className="text-muted-foreground mt-2">Discover new features</Text>
|
|
3239
|
+
</View>
|
|
3307
3240
|
);
|
|
3308
3241
|
}
|
|
3309
|
-
|
|
3310
|
-
const styles = StyleSheet.create({
|
|
3311
|
-
container: {
|
|
3312
|
-
flex: 1,
|
|
3313
|
-
alignItems: "center",
|
|
3314
|
-
justifyContent: "center",
|
|
3315
|
-
},
|
|
3316
|
-
subtitle: {
|
|
3317
|
-
fontSize: 16,
|
|
3318
|
-
textAlign: "center",
|
|
3319
|
-
marginTop: 8,
|
|
3320
|
-
},
|
|
3321
|
-
});
|
|
3322
3242
|
`
|
|
3323
3243
|
},
|
|
3324
3244
|
// ─── app/+not-found.tsx ─────────────────────────────────────────────
|
|
3325
3245
|
{
|
|
3326
3246
|
path: "app/+not-found.tsx",
|
|
3327
3247
|
content: `import { Link, Stack } from "expo-router";
|
|
3328
|
-
import {
|
|
3329
|
-
import { ThemedText } from "@/components/Themed";
|
|
3330
|
-
import { ThemedView } from "@/components/Themed";
|
|
3248
|
+
import { Text, View } from "react-native";
|
|
3331
3249
|
|
|
3332
3250
|
export default function NotFoundScreen() {
|
|
3333
3251
|
return (
|
|
3334
3252
|
<>
|
|
3335
3253
|
<Stack.Screen options={{ title: "Oops!" }} />
|
|
3336
|
-
<
|
|
3337
|
-
<
|
|
3338
|
-
<Link href="/"
|
|
3339
|
-
<
|
|
3254
|
+
<View className="flex-1 items-center justify-center p-5">
|
|
3255
|
+
<Text className="text-foreground text-2xl font-bold">This screen doesn't exist.</Text>
|
|
3256
|
+
<Link href="/" className="mt-4 py-4">
|
|
3257
|
+
<Text className="text-primary underline">Go to home screen!</Text>
|
|
3340
3258
|
</Link>
|
|
3341
|
-
</
|
|
3259
|
+
</View>
|
|
3342
3260
|
</>
|
|
3343
3261
|
);
|
|
3344
3262
|
}
|
|
3345
|
-
|
|
3346
|
-
const styles = StyleSheet.create({
|
|
3347
|
-
container: {
|
|
3348
|
-
flex: 1,
|
|
3349
|
-
alignItems: "center",
|
|
3350
|
-
justifyContent: "center",
|
|
3351
|
-
padding: 20,
|
|
3352
|
-
},
|
|
3353
|
-
link: {
|
|
3354
|
-
marginTop: 15,
|
|
3355
|
-
paddingVertical: 15,
|
|
3356
|
-
},
|
|
3357
|
-
});
|
|
3358
3263
|
`
|
|
3359
3264
|
},
|
|
3360
|
-
// ───
|
|
3265
|
+
// ─── lib/utils.ts (rnr official cn helper) ───────────────────────────
|
|
3361
3266
|
{
|
|
3362
|
-
path: "
|
|
3363
|
-
content: `import {
|
|
3364
|
-
import {
|
|
3365
|
-
import { Colors } from "@/constants/Colors";
|
|
3366
|
-
|
|
3367
|
-
/** Themed text component that adapts to light/dark mode */
|
|
3368
|
-
export function ThemedText({
|
|
3369
|
-
style,
|
|
3370
|
-
type = "default",
|
|
3371
|
-
...rest
|
|
3372
|
-
}: TextProps & { type?: "default" | "title" | "defaultSemiBold" | "subtitle" | "link" }) {
|
|
3373
|
-
const colorScheme = useColorScheme();
|
|
3374
|
-
const color = Colors[colorScheme ?? "light"].text;
|
|
3375
|
-
|
|
3376
|
-
return (
|
|
3377
|
-
<Text
|
|
3378
|
-
style={[
|
|
3379
|
-
{ color },
|
|
3380
|
-
type === "default" ? { fontSize: 16, lineHeight: 24 } : undefined,
|
|
3381
|
-
type === "title" ? { fontSize: 28, fontWeight: "bold", lineHeight: 32 } : undefined,
|
|
3382
|
-
type === "defaultSemiBold" ? { fontSize: 16, lineHeight: 24, fontWeight: "600" } : undefined,
|
|
3383
|
-
type === "subtitle" ? { fontSize: 20, fontWeight: "bold" } : undefined,
|
|
3384
|
-
type === "link" ? { fontSize: 16, lineHeight: 24, color: Colors[colorScheme ?? "light"].tint } : undefined,
|
|
3385
|
-
style,
|
|
3386
|
-
]}
|
|
3387
|
-
{...rest}
|
|
3388
|
-
/>
|
|
3389
|
-
);
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
/** Themed view component that adapts to light/dark mode */
|
|
3393
|
-
export function ThemedView({ style, ...rest }: ViewProps) {
|
|
3394
|
-
const colorScheme = useColorScheme();
|
|
3395
|
-
const backgroundColor = Colors[colorScheme ?? "light"].background;
|
|
3267
|
+
path: "lib/utils.ts",
|
|
3268
|
+
content: `import { clsx, type ClassValue } from "clsx";
|
|
3269
|
+
import { twMerge } from "tailwind-merge";
|
|
3396
3270
|
|
|
3397
|
-
|
|
3271
|
+
export function cn(...inputs: ClassValue[]) {
|
|
3272
|
+
return twMerge(clsx(inputs));
|
|
3398
3273
|
}
|
|
3399
3274
|
`
|
|
3400
3275
|
},
|
|
3401
|
-
// ───
|
|
3276
|
+
// ─── lib/theme.ts (rnr official theme) ───────────────────────────────
|
|
3402
3277
|
{
|
|
3403
|
-
path: "
|
|
3404
|
-
content: `import {
|
|
3405
|
-
import { Animated, Easing } from "react-native";
|
|
3406
|
-
import { ThemedText } from "./Themed";
|
|
3407
|
-
|
|
3408
|
-
export function HelloWave() {
|
|
3409
|
-
const rotationAnim = new Animated.Value(0);
|
|
3410
|
-
|
|
3411
|
-
useEffect(() => {
|
|
3412
|
-
Animated.loop(
|
|
3413
|
-
Animated.sequence([
|
|
3414
|
-
Animated.timing(rotationAnim, {
|
|
3415
|
-
toValue: 1,
|
|
3416
|
-
duration: 150,
|
|
3417
|
-
easing: Easing.linear,
|
|
3418
|
-
useNativeDriver: true,
|
|
3419
|
-
}),
|
|
3420
|
-
Animated.timing(rotationAnim, {
|
|
3421
|
-
toValue: 0,
|
|
3422
|
-
duration: 150,
|
|
3423
|
-
easing: Easing.linear,
|
|
3424
|
-
useNativeDriver: true,
|
|
3425
|
-
}),
|
|
3426
|
-
])
|
|
3427
|
-
).start();
|
|
3428
|
-
}, [rotationAnim]);
|
|
3278
|
+
path: "lib/theme.ts",
|
|
3279
|
+
content: `import { DarkTheme, DefaultTheme, type Theme } from '@react-navigation/native';
|
|
3429
3280
|
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3281
|
+
export const THEME = {
|
|
3282
|
+
light: {
|
|
3283
|
+
background: 'hsl(0 0% 100%)',
|
|
3284
|
+
foreground: 'hsl(0 0% 3.9%)',
|
|
3285
|
+
card: 'hsl(0 0% 100%)',
|
|
3286
|
+
cardForeground: 'hsl(0 0% 3.9%)',
|
|
3287
|
+
popover: 'hsl(0 0% 100%)',
|
|
3288
|
+
popoverForeground: 'hsl(0 0% 3.9%)',
|
|
3289
|
+
primary: 'hsl(0 0% 9%)',
|
|
3290
|
+
primaryForeground: 'hsl(0 0% 98%)',
|
|
3291
|
+
secondary: 'hsl(0 0% 96.1%)',
|
|
3292
|
+
secondaryForeground: 'hsl(0 0% 9%)',
|
|
3293
|
+
muted: 'hsl(0 0% 96.1%)',
|
|
3294
|
+
mutedForeground: 'hsl(0 0% 45.1%)',
|
|
3295
|
+
accent: 'hsl(0 0% 96.1%)',
|
|
3296
|
+
accentForeground: 'hsl(0 0% 9%)',
|
|
3297
|
+
destructive: 'hsl(0 84.2% 60.2%)',
|
|
3298
|
+
border: 'hsl(0 0% 89.8%)',
|
|
3299
|
+
input: 'hsl(0 0% 89.8%)',
|
|
3300
|
+
ring: 'hsl(0 0% 63%)',
|
|
3301
|
+
radius: '0.625rem',
|
|
3302
|
+
chart1: 'hsl(12 76% 61%)',
|
|
3303
|
+
chart2: 'hsl(173 58% 39%)',
|
|
3304
|
+
chart3: 'hsl(197 37% 24%)',
|
|
3305
|
+
chart4: 'hsl(43 74% 66%)',
|
|
3306
|
+
chart5: 'hsl(27 87% 67%)',
|
|
3307
|
+
},
|
|
3308
|
+
dark: {
|
|
3309
|
+
background: 'hsl(0 0% 3.9%)',
|
|
3310
|
+
foreground: 'hsl(0 0% 98%)',
|
|
3311
|
+
card: 'hsl(0 0% 3.9%)',
|
|
3312
|
+
cardForeground: 'hsl(0 0% 98%)',
|
|
3313
|
+
popover: 'hsl(0 0% 3.9%)',
|
|
3314
|
+
popoverForeground: 'hsl(0 0% 98%)',
|
|
3315
|
+
primary: 'hsl(0 0% 98%)',
|
|
3316
|
+
primaryForeground: 'hsl(0 0% 9%)',
|
|
3317
|
+
secondary: 'hsl(0 0% 14.9%)',
|
|
3318
|
+
secondaryForeground: 'hsl(0 0% 98%)',
|
|
3319
|
+
muted: 'hsl(0 0% 14.9%)',
|
|
3320
|
+
mutedForeground: 'hsl(0 0% 63.9%)',
|
|
3321
|
+
accent: 'hsl(0 0% 14.9%)',
|
|
3322
|
+
accentForeground: 'hsl(0 0% 98%)',
|
|
3323
|
+
destructive: 'hsl(0 70.9% 59.4%)',
|
|
3324
|
+
border: 'hsl(0 0% 14.9%)',
|
|
3325
|
+
input: 'hsl(0 0% 14.9%)',
|
|
3326
|
+
ring: 'hsl(300 0% 45%)',
|
|
3327
|
+
radius: '0.625rem',
|
|
3328
|
+
chart1: 'hsl(220 70% 50%)',
|
|
3329
|
+
chart2: 'hsl(160 60% 45%)',
|
|
3330
|
+
chart3: 'hsl(30 80% 55%)',
|
|
3331
|
+
chart4: 'hsl(280 65% 60%)',
|
|
3332
|
+
chart5: 'hsl(340 75% 55%)',
|
|
3333
|
+
},
|
|
3334
|
+
};
|
|
3453
3335
|
|
|
3454
|
-
|
|
3455
|
-
* Returns the current color scheme (light or dark).
|
|
3456
|
-
* Defaults to "light" if the system preference is not available.
|
|
3457
|
-
*/
|
|
3458
|
-
export function useColorScheme(): "light" | "dark" {
|
|
3459
|
-
return useRNColorScheme() ?? "light";
|
|
3460
|
-
}
|
|
3461
|
-
`
|
|
3462
|
-
},
|
|
3463
|
-
// ─── src/constants/Colors.ts ─────────────────────────────────────────
|
|
3464
|
-
{
|
|
3465
|
-
path: "constants/Colors.ts",
|
|
3466
|
-
content: `/**
|
|
3467
|
-
* Color tokens for light and dark themes.
|
|
3468
|
-
* Used by Themed components and navigation theming.
|
|
3469
|
-
*/
|
|
3470
|
-
export const Colors = {
|
|
3336
|
+
export const NAV_THEME: Record<'light' | 'dark', Theme> = {
|
|
3471
3337
|
light: {
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3338
|
+
...DefaultTheme,
|
|
3339
|
+
colors: {
|
|
3340
|
+
background: THEME.light.background,
|
|
3341
|
+
border: THEME.light.border,
|
|
3342
|
+
card: THEME.light.card,
|
|
3343
|
+
notification: THEME.light.destructive,
|
|
3344
|
+
primary: THEME.light.primary,
|
|
3345
|
+
text: THEME.light.foreground,
|
|
3346
|
+
},
|
|
3477
3347
|
},
|
|
3478
3348
|
dark: {
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3349
|
+
...DarkTheme,
|
|
3350
|
+
colors: {
|
|
3351
|
+
background: THEME.dark.background,
|
|
3352
|
+
border: THEME.dark.border,
|
|
3353
|
+
card: THEME.dark.card,
|
|
3354
|
+
notification: THEME.dark.destructive,
|
|
3355
|
+
primary: THEME.dark.primary,
|
|
3356
|
+
text: THEME.dark.foreground,
|
|
3357
|
+
},
|
|
3484
3358
|
},
|
|
3485
3359
|
};
|
|
3486
3360
|
`
|
|
3487
3361
|
},
|
|
3488
|
-
// ───
|
|
3362
|
+
// ─── types/index.ts ─────────────────────────────────────────────────
|
|
3489
3363
|
{
|
|
3490
3364
|
path: "types/index.ts",
|
|
3491
3365
|
content: `/** Global type definitions */
|
|
@@ -3551,61 +3425,109 @@ export {};
|
|
|
3551
3425
|
}
|
|
3552
3426
|
`
|
|
3553
3427
|
},
|
|
3554
|
-
// ───
|
|
3428
|
+
// ─── components.json (rnr CLI compatibility) ─────────────────────────
|
|
3429
|
+
{
|
|
3430
|
+
path: "components.json",
|
|
3431
|
+
content: `{
|
|
3432
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3433
|
+
"style": "new-york",
|
|
3434
|
+
"rsc": false,
|
|
3435
|
+
"tsx": true,
|
|
3436
|
+
"tailwind": {
|
|
3437
|
+
"config": "tailwind.config.js",
|
|
3438
|
+
"css": "global.css",
|
|
3439
|
+
"baseColor": "neutral",
|
|
3440
|
+
"cssVariables": true
|
|
3441
|
+
},
|
|
3442
|
+
"aliases": {
|
|
3443
|
+
"components": "@/components",
|
|
3444
|
+
"utils": "@/lib/utils",
|
|
3445
|
+
"ui": "@/components/ui",
|
|
3446
|
+
"lib": "@/lib",
|
|
3447
|
+
"hooks": "@/hooks"
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
`
|
|
3451
|
+
},
|
|
3452
|
+
// ─── tailwind.config.js (rnr official) ──────────────────────────────
|
|
3555
3453
|
{
|
|
3556
3454
|
path: "tailwind.config.js",
|
|
3557
|
-
content:
|
|
3455
|
+
content: `const { hairlineWidth } = require('nativewind/theme');
|
|
3456
|
+
|
|
3457
|
+
/** @type {import('tailwindcss').Config} */
|
|
3558
3458
|
module.exports = {
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
"./modules/**/*.{js,jsx,ts,tsx}",
|
|
3563
|
-
],
|
|
3564
|
-
presets: [require("nativewind/preset")],
|
|
3459
|
+
darkMode: 'class',
|
|
3460
|
+
content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}'],
|
|
3461
|
+
presets: [require('nativewind/preset')],
|
|
3565
3462
|
theme: {
|
|
3566
3463
|
extend: {
|
|
3567
3464
|
colors: {
|
|
3568
|
-
border:
|
|
3569
|
-
input:
|
|
3570
|
-
ring:
|
|
3571
|
-
background:
|
|
3572
|
-
foreground:
|
|
3465
|
+
border: 'hsl(var(--border))',
|
|
3466
|
+
input: 'hsl(var(--input))',
|
|
3467
|
+
ring: 'hsl(var(--ring))',
|
|
3468
|
+
background: 'hsl(var(--background))',
|
|
3469
|
+
foreground: 'hsl(var(--foreground))',
|
|
3573
3470
|
primary: {
|
|
3574
|
-
DEFAULT:
|
|
3575
|
-
foreground:
|
|
3471
|
+
DEFAULT: 'hsl(var(--primary))',
|
|
3472
|
+
foreground: 'hsl(var(--primary-foreground))',
|
|
3576
3473
|
},
|
|
3577
3474
|
secondary: {
|
|
3578
|
-
DEFAULT:
|
|
3579
|
-
foreground:
|
|
3475
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
3476
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
3580
3477
|
},
|
|
3581
3478
|
destructive: {
|
|
3582
|
-
DEFAULT:
|
|
3583
|
-
foreground:
|
|
3479
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
3480
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
3584
3481
|
},
|
|
3585
3482
|
muted: {
|
|
3586
|
-
DEFAULT:
|
|
3587
|
-
foreground:
|
|
3483
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
3484
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
3588
3485
|
},
|
|
3589
3486
|
accent: {
|
|
3590
|
-
DEFAULT:
|
|
3591
|
-
foreground:
|
|
3487
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
3488
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
3592
3489
|
},
|
|
3593
3490
|
popover: {
|
|
3594
|
-
DEFAULT:
|
|
3595
|
-
foreground:
|
|
3491
|
+
DEFAULT: 'hsl(var(--popover))',
|
|
3492
|
+
foreground: 'hsl(var(--popover-foreground))',
|
|
3596
3493
|
},
|
|
3597
3494
|
card: {
|
|
3598
|
-
DEFAULT:
|
|
3599
|
-
foreground:
|
|
3495
|
+
DEFAULT: 'hsl(var(--card))',
|
|
3496
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
3600
3497
|
},
|
|
3601
3498
|
},
|
|
3499
|
+
borderRadius: {
|
|
3500
|
+
lg: 'var(--radius)',
|
|
3501
|
+
md: 'calc(var(--radius) - 2px)',
|
|
3502
|
+
sm: 'calc(var(--radius) - 4px)',
|
|
3503
|
+
},
|
|
3504
|
+
borderWidth: {
|
|
3505
|
+
hairline: hairlineWidth(),
|
|
3506
|
+
},
|
|
3507
|
+
keyframes: {
|
|
3508
|
+
'accordion-down': {
|
|
3509
|
+
from: { height: '0' },
|
|
3510
|
+
to: { height: 'var(--radix-accordion-content-height)' },
|
|
3511
|
+
},
|
|
3512
|
+
'accordion-up': {
|
|
3513
|
+
from: { height: 'var(--radix-accordion-content-height)' },
|
|
3514
|
+
to: { height: '0' },
|
|
3515
|
+
},
|
|
3516
|
+
},
|
|
3517
|
+
animation: {
|
|
3518
|
+
'accordion-down': 'accordion-down 0.2s ease-out',
|
|
3519
|
+
'accordion-up': 'accordion-up 0.2s ease-out',
|
|
3520
|
+
},
|
|
3602
3521
|
},
|
|
3603
3522
|
},
|
|
3604
|
-
|
|
3523
|
+
future: {
|
|
3524
|
+
hoverOnlyWhenSupported: true,
|
|
3525
|
+
},
|
|
3526
|
+
plugins: [require('tailwindcss-animate')],
|
|
3605
3527
|
};
|
|
3606
3528
|
`
|
|
3607
3529
|
},
|
|
3608
|
-
// ─── metro.config.js
|
|
3530
|
+
// ─── metro.config.js (rnr official: inlineRem: 16) ──────────────────
|
|
3609
3531
|
{
|
|
3610
3532
|
path: "metro.config.js",
|
|
3611
3533
|
content: `const { getDefaultConfig } = require("expo/metro-config");
|
|
@@ -3613,7 +3535,7 @@ const { withNativeWind } = require("nativewind/metro");
|
|
|
3613
3535
|
|
|
3614
3536
|
const config = getDefaultConfig(__dirname);
|
|
3615
3537
|
|
|
3616
|
-
module.exports = withNativeWind(config, { input: "./global.css" });
|
|
3538
|
+
module.exports = withNativeWind(config, { input: "./global.css", inlineRem: 16 });
|
|
3617
3539
|
`
|
|
3618
3540
|
},
|
|
3619
3541
|
// ─── babel.config.js ─────────────────────────────────────────────────
|
|
@@ -3631,7 +3553,7 @@ module.exports = withNativeWind(config, { input: "./global.css" });
|
|
|
3631
3553
|
};
|
|
3632
3554
|
`
|
|
3633
3555
|
},
|
|
3634
|
-
// ─── global.css (
|
|
3556
|
+
// ─── global.css (rnr official CSS variables) ─────────────────────────
|
|
3635
3557
|
{
|
|
3636
3558
|
path: "global.css",
|
|
3637
3559
|
content: `@tailwind base;
|
|
@@ -3641,46 +3563,55 @@ module.exports = withNativeWind(config, { input: "./global.css" });
|
|
|
3641
3563
|
@layer base {
|
|
3642
3564
|
:root {
|
|
3643
3565
|
--background: 0 0% 100%;
|
|
3644
|
-
--foreground:
|
|
3566
|
+
--foreground: 0 0% 3.9%;
|
|
3645
3567
|
--card: 0 0% 100%;
|
|
3646
|
-
--card-foreground:
|
|
3568
|
+
--card-foreground: 0 0% 3.9%;
|
|
3647
3569
|
--popover: 0 0% 100%;
|
|
3648
|
-
--popover-foreground:
|
|
3649
|
-
--primary:
|
|
3570
|
+
--popover-foreground: 0 0% 3.9%;
|
|
3571
|
+
--primary: 0 0% 9%;
|
|
3650
3572
|
--primary-foreground: 0 0% 98%;
|
|
3651
|
-
--secondary:
|
|
3652
|
-
--secondary-foreground:
|
|
3653
|
-
--muted:
|
|
3654
|
-
--muted-foreground:
|
|
3655
|
-
--accent:
|
|
3656
|
-
--accent-foreground:
|
|
3573
|
+
--secondary: 0 0% 96.1%;
|
|
3574
|
+
--secondary-foreground: 0 0% 9%;
|
|
3575
|
+
--muted: 0 0% 96.1%;
|
|
3576
|
+
--muted-foreground: 0 0% 45.1%;
|
|
3577
|
+
--accent: 0 0% 96.1%;
|
|
3578
|
+
--accent-foreground: 0 0% 9%;
|
|
3657
3579
|
--destructive: 0 84.2% 60.2%;
|
|
3658
|
-
--
|
|
3659
|
-
--
|
|
3660
|
-
--
|
|
3661
|
-
--
|
|
3580
|
+
--border: 0 0% 89.8%;
|
|
3581
|
+
--input: 0 0% 89.8%;
|
|
3582
|
+
--ring: 0 0% 63%;
|
|
3583
|
+
--radius: 0.625rem;
|
|
3584
|
+
--chart-1: 12 76% 61%;
|
|
3585
|
+
--chart-2: 173 58% 39%;
|
|
3586
|
+
--chart-3: 197 37% 24%;
|
|
3587
|
+
--chart-4: 43 74% 66%;
|
|
3588
|
+
--chart-5: 27 87% 67%;
|
|
3662
3589
|
}
|
|
3663
3590
|
|
|
3664
|
-
.dark {
|
|
3665
|
-
--background:
|
|
3591
|
+
.dark:root {
|
|
3592
|
+
--background: 0 0% 3.9%;
|
|
3666
3593
|
--foreground: 0 0% 98%;
|
|
3667
|
-
--card:
|
|
3594
|
+
--card: 0 0% 3.9%;
|
|
3668
3595
|
--card-foreground: 0 0% 98%;
|
|
3669
|
-
--popover:
|
|
3596
|
+
--popover: 0 0% 3.9%;
|
|
3670
3597
|
--popover-foreground: 0 0% 98%;
|
|
3671
3598
|
--primary: 0 0% 98%;
|
|
3672
|
-
--primary-foreground:
|
|
3673
|
-
--secondary:
|
|
3599
|
+
--primary-foreground: 0 0% 9%;
|
|
3600
|
+
--secondary: 0 0% 14.9%;
|
|
3674
3601
|
--secondary-foreground: 0 0% 98%;
|
|
3675
|
-
--muted:
|
|
3676
|
-
--muted-foreground:
|
|
3677
|
-
--accent:
|
|
3602
|
+
--muted: 0 0% 14.9%;
|
|
3603
|
+
--muted-foreground: 0 0% 63.9%;
|
|
3604
|
+
--accent: 0 0% 14.9%;
|
|
3678
3605
|
--accent-foreground: 0 0% 98%;
|
|
3679
|
-
--destructive: 0
|
|
3680
|
-
--
|
|
3681
|
-
--
|
|
3682
|
-
--
|
|
3683
|
-
--
|
|
3606
|
+
--destructive: 0 70.9% 59.4%;
|
|
3607
|
+
--border: 0 0% 14.9%;
|
|
3608
|
+
--input: 0 0% 14.9%;
|
|
3609
|
+
--ring: 300 0% 45%;
|
|
3610
|
+
--chart-1: 220 70% 50%;
|
|
3611
|
+
--chart-2: 160 60% 45%;
|
|
3612
|
+
--chart-3: 30 80% 55%;
|
|
3613
|
+
--chart-4: 280 65% 60%;
|
|
3614
|
+
--chart-5: 340 75% 55%;
|
|
3684
3615
|
}
|
|
3685
3616
|
}
|
|
3686
3617
|
`
|
|
@@ -3738,14 +3669,15 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3738
3669
|
{
|
|
3739
3670
|
path: "app/_layout.tsx",
|
|
3740
3671
|
content: lines(
|
|
3672
|
+
'import "../global.css";',
|
|
3741
3673
|
'import { DarkTheme, DefaultTheme, ThemeProvider } from "@react-navigation/native";',
|
|
3742
3674
|
'import { useFonts } from "expo-font";',
|
|
3743
3675
|
'import { Stack } from "expo-router";',
|
|
3744
3676
|
'import * as SplashScreen from "expo-splash-screen";',
|
|
3745
3677
|
'import { useEffect } from "react";',
|
|
3746
3678
|
'import { useColorScheme } from "react-native";',
|
|
3747
|
-
"",
|
|
3748
|
-
'import {
|
|
3679
|
+
'import { PortalHost } from "@rn-primitives/portal";',
|
|
3680
|
+
'import { NAV_THEME } from "@/lib/theme";',
|
|
3749
3681
|
"",
|
|
3750
3682
|
"SplashScreen.preventAutoHideAsync();",
|
|
3751
3683
|
"",
|
|
@@ -3766,12 +3698,13 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3766
3698
|
" }",
|
|
3767
3699
|
"",
|
|
3768
3700
|
" return (",
|
|
3769
|
-
' <ThemeProvider value={colorScheme === "dark" ?
|
|
3701
|
+
' <ThemeProvider value={colorScheme === "dark" ? NAV_THEME.dark : NAV_THEME.light}>',
|
|
3770
3702
|
" <Stack>",
|
|
3771
3703
|
' <Stack.Screen name="login" options={{ headerShown: false }} />',
|
|
3772
3704
|
' <Stack.Screen name="(tabs)" options={{ headerShown: false }} />',
|
|
3773
3705
|
' <Stack.Screen name="+not-found" />',
|
|
3774
3706
|
" </Stack>",
|
|
3707
|
+
" <PortalHost />",
|
|
3775
3708
|
" </ThemeProvider>",
|
|
3776
3709
|
" );",
|
|
3777
3710
|
"}",
|
|
@@ -3802,19 +3735,10 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3802
3735
|
'import { Tabs } from "expo-router";',
|
|
3803
3736
|
'import { Platform } from "react-native";',
|
|
3804
3737
|
"",
|
|
3805
|
-
'import { Colors } from "@/constants/Colors";',
|
|
3806
|
-
'import { useColorScheme } from "@/hooks/useColorScheme";',
|
|
3807
|
-
"",
|
|
3808
3738
|
"export default function TabLayout() {",
|
|
3809
|
-
" const colorScheme = useColorScheme();",
|
|
3810
|
-
"",
|
|
3811
3739
|
" return (",
|
|
3812
3740
|
" <Tabs",
|
|
3813
3741
|
" screenOptions={{",
|
|
3814
|
-
' tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,',
|
|
3815
|
-
" headerStyle: {",
|
|
3816
|
-
' backgroundColor: Colors[colorScheme ?? "light"].background,',
|
|
3817
|
-
" },",
|
|
3818
3742
|
" headerShadowVisible: false,",
|
|
3819
3743
|
" tabBarStyle: Platform.select({",
|
|
3820
3744
|
" ios: {",
|
|
@@ -3825,24 +3749,24 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3825
3749
|
" }}",
|
|
3826
3750
|
" >",
|
|
3827
3751
|
" <Tabs.Screen",
|
|
3828
|
-
' name="
|
|
3752
|
+
' name="index"',
|
|
3829
3753
|
" options={{",
|
|
3830
3754
|
' title: "Home",',
|
|
3831
|
-
|
|
3755
|
+
' tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,',
|
|
3832
3756
|
" }}",
|
|
3833
3757
|
" />",
|
|
3834
3758
|
" <Tabs.Screen",
|
|
3835
|
-
' name="
|
|
3759
|
+
' name="explore"',
|
|
3836
3760
|
" options={{",
|
|
3837
|
-
' title: "
|
|
3838
|
-
|
|
3761
|
+
' title: "Explore",',
|
|
3762
|
+
' tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />',
|
|
3839
3763
|
" }}",
|
|
3840
3764
|
" />",
|
|
3841
3765
|
" <Tabs.Screen",
|
|
3842
3766
|
' name="mine"',
|
|
3843
3767
|
" options={{",
|
|
3844
3768
|
' title: "Mine",',
|
|
3845
|
-
|
|
3769
|
+
' tabBarIcon: ({ color }) => <IconSymbol size={28} name="chevron.right" color={color} />',
|
|
3846
3770
|
" }}",
|
|
3847
3771
|
" />",
|
|
3848
3772
|
" </Tabs>",
|
|
@@ -3851,9 +3775,9 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3851
3775
|
""
|
|
3852
3776
|
)
|
|
3853
3777
|
},
|
|
3854
|
-
// ─── app/(tabs)/
|
|
3778
|
+
// ─── app/(tabs)/index.tsx ──────────────────────────────────────────
|
|
3855
3779
|
{
|
|
3856
|
-
path: "app/(tabs)/
|
|
3780
|
+
path: "app/(tabs)/index.tsx",
|
|
3857
3781
|
content: lines(
|
|
3858
3782
|
'import { Button } from "@/components/ui/button";',
|
|
3859
3783
|
"import {",
|
|
@@ -3934,9 +3858,9 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3934
3858
|
""
|
|
3935
3859
|
)
|
|
3936
3860
|
},
|
|
3937
|
-
// ─── app/(tabs)/
|
|
3861
|
+
// ─── app/(tabs)/explore.tsx ────────────────────────────────────────
|
|
3938
3862
|
{
|
|
3939
|
-
path: "app/(tabs)/
|
|
3863
|
+
path: "app/(tabs)/explore.tsx",
|
|
3940
3864
|
content: lines(
|
|
3941
3865
|
'import { Text } from "@/components/ui/text";',
|
|
3942
3866
|
'import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";',
|
|
@@ -3948,10 +3872,10 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
3948
3872
|
" description: `Description for item ${i + 1}`,",
|
|
3949
3873
|
"}));",
|
|
3950
3874
|
"",
|
|
3951
|
-
"export default function
|
|
3875
|
+
"export default function ExploreScreen() {",
|
|
3952
3876
|
" return (",
|
|
3953
3877
|
' <ScrollView className="flex-1 p-4">',
|
|
3954
|
-
' <Text variant="h3" className="mb-4">
|
|
3878
|
+
' <Text variant="h3" className="mb-4">Explore</Text>',
|
|
3955
3879
|
' <View className="gap-3">',
|
|
3956
3880
|
" {ITEMS.map((item) => (",
|
|
3957
3881
|
" <Card key={item.id}>",
|
|
@@ -4011,7 +3935,7 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
4011
3935
|
""
|
|
4012
3936
|
)
|
|
4013
3937
|
},
|
|
4014
|
-
// ───
|
|
3938
|
+
// ─── components/SignInForm.tsx ────────────────────────────────────
|
|
4015
3939
|
{
|
|
4016
3940
|
path: "components/SignInForm.tsx",
|
|
4017
3941
|
content: lines(
|
|
@@ -4040,7 +3964,7 @@ function generateLoginTabsTemplates(projectName) {
|
|
|
4040
3964
|
"",
|
|
4041
3965
|
" function onSubmit() {",
|
|
4042
3966
|
" // TODO: Submit form and navigate to protected screen if successful",
|
|
4043
|
-
' router.replace("/(tabs)
|
|
3967
|
+
' router.replace("/(tabs)");',
|
|
4044
3968
|
" }",
|
|
4045
3969
|
"",
|
|
4046
3970
|
" return (",
|
|
@@ -4200,6 +4124,7 @@ function generateBasePackageJson(projectName) {
|
|
|
4200
4124
|
// ─── Styling ──────────────────────────────────────────────────
|
|
4201
4125
|
nativewind: "^4.1.0",
|
|
4202
4126
|
tailwindcss: "^3.4.0",
|
|
4127
|
+
"tailwindcss-animate": "^1.0.7",
|
|
4203
4128
|
"react-native-svg": "15.12.1",
|
|
4204
4129
|
// ─── Network ─────────────────────────────────────────────────
|
|
4205
4130
|
"@tanstack/react-query": "^5.60.0",
|
|
@@ -4261,8 +4186,7 @@ function generateBasePackageJson(projectName) {
|
|
|
4261
4186
|
}
|
|
4262
4187
|
|
|
4263
4188
|
// src/index.ts
|
|
4264
|
-
var
|
|
4265
|
-
var CLI_VERSION = "1.6.1";
|
|
4189
|
+
var CLI_VERSION = "1.7.1";
|
|
4266
4190
|
var CONFIG_FILE = ".expo-bbase.json";
|
|
4267
4191
|
async function run() {
|
|
4268
4192
|
const program = new import_commander.Command();
|
|
@@ -4309,12 +4233,12 @@ async function createProject(projectName) {
|
|
|
4309
4233
|
message: "Choose a UI template",
|
|
4310
4234
|
choices: [
|
|
4311
4235
|
{
|
|
4312
|
-
title: `${import_chalk.default.bold("Login + Tabs")} \u2014 Login page,
|
|
4236
|
+
title: `${import_chalk.default.bold("Login + Tabs")} \u2014 Login page, Index/Explore/Mine tabs with rnr components`,
|
|
4313
4237
|
value: "login-tabs",
|
|
4314
4238
|
description: "Pre-built login form, 3-tab layout with Button & AlertDialog demos"
|
|
4315
4239
|
},
|
|
4316
4240
|
{
|
|
4317
|
-
title: `${import_chalk.default.bold("Default")} \u2014 Blank tabs (
|
|
4241
|
+
title: `${import_chalk.default.bold("Default")} \u2014 Blank tabs (Index + Explore)`,
|
|
4318
4242
|
value: "default",
|
|
4319
4243
|
description: "Minimal starter with basic tab navigation"
|
|
4320
4244
|
}
|