create-expo-stack 2.4.3 → 2.5.0-next.00da55e
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/README.md +213 -156
- package/build/commands/create-expo-stack.js +62 -56
- package/build/templates/base/App.tsx.ejs +51 -91
- package/build/templates/base/app.json.ejs +6 -0
- package/build/templates/base/components/BackButton.tsx.ejs +23 -0
- package/build/templates/base/components/Button.tsx.ejs +40 -0
- package/build/templates/base/components/EditScreenInfo.tsx.ejs +55 -0
- package/build/templates/base/components/HeaderButton.tsx.ejs +28 -0
- package/build/templates/base/components/ScreenContent.tsx.ejs +38 -0
- package/build/templates/base/components/TabBarIcon.tsx.ejs +15 -0
- package/build/templates/base/package.json.ejs +17 -7
- package/build/templates/base/prettier.config.js.ejs +11 -0
- package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/_layout.tsx.ejs +1 -13
- package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/index.tsx.ejs +18 -84
- package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/two.tsx.ejs +18 -84
- package/build/templates/packages/expo-router/drawer/app/(drawer)/_layout.tsx.ejs +4 -18
- package/build/templates/packages/expo-router/drawer/app/(drawer)/index.tsx.ejs +12 -80
- package/build/templates/packages/expo-router/drawer/app/_layout.tsx.ejs +4 -0
- package/build/templates/packages/expo-router/drawer/app/modal.tsx.ejs +16 -92
- package/build/templates/packages/expo-router/stack/app/_layout.tsx.ejs +3 -0
- package/build/templates/packages/expo-router/stack/app/details.tsx.ejs +17 -171
- package/build/templates/packages/expo-router/stack/app/index.tsx.ejs +23 -187
- package/build/templates/packages/expo-router/tabs/app/(tabs)/_layout.tsx.ejs +6 -50
- package/build/templates/packages/expo-router/tabs/app/(tabs)/index.tsx.ejs +18 -84
- package/build/templates/packages/expo-router/tabs/app/(tabs)/two.tsx.ejs +18 -83
- package/build/templates/packages/expo-router/tabs/app/_layout.tsx.ejs +3 -0
- package/build/templates/packages/expo-router/tabs/app/modal.tsx.ejs +17 -92
- package/build/templates/packages/i18next/components/InternalizationExample.tsx.ejs +23 -0
- package/build/templates/packages/i18next/core/i18n/fallbackChecker.ts.ejs +13 -0
- package/build/templates/packages/i18next/core/i18n/init.ts.ejs +24 -0
- package/build/templates/packages/i18next/core/i18n/languageDetector.ts.ejs +13 -0
- package/build/templates/packages/i18next/translation/en.json.ejs +8 -0
- package/build/templates/packages/i18next/translation/fr.json.ejs +8 -0
- package/build/templates/packages/i18next/translation/index.ts.ejs +20 -0
- package/build/templates/packages/nativewind/components/BackButton.tsx.ejs +18 -0
- package/build/templates/packages/nativewind/components/Button.tsx.ejs +14 -0
- package/build/templates/packages/nativewind/components/EditScreenInfo.tsx.ejs +40 -0
- package/build/templates/packages/nativewind/components/ScreenContent.tsx.ejs +25 -0
- package/build/templates/packages/react-navigation/App.tsx.ejs +4 -1
- package/build/templates/packages/react-navigation/navigation/drawer-navigator.tsx.ejs +14 -26
- package/build/templates/packages/react-navigation/navigation/index.tsx.ejs +2 -101
- package/build/templates/packages/react-navigation/navigation/tab-navigator.tsx.ejs +8 -62
- package/build/templates/packages/react-navigation/screens/details.tsx.ejs +22 -108
- package/build/templates/packages/react-navigation/screens/home.tsx.ejs +3 -82
- package/build/templates/packages/react-navigation/screens/modal.tsx.ejs +16 -104
- package/build/templates/packages/react-navigation/screens/one.tsx.ejs +2 -97
- package/build/templates/packages/react-navigation/screens/overview.tsx.ejs +37 -182
- package/build/templates/packages/react-navigation/screens/two.tsx.ejs +3 -98
- package/build/templates/packages/restyle/components/BackButton.tsx.ejs +15 -0
- package/build/templates/packages/restyle/components/Button.tsx.ejs +32 -0
- package/build/templates/packages/restyle/components/EditScreenInfo.tsx.ejs +29 -0
- package/build/templates/packages/restyle/components/ScreenContent.tsx.ejs +20 -0
- package/build/templates/packages/tamagui/components/BackButton.tsx.ejs +19 -0
- package/build/templates/packages/tamagui/components/Button.tsx.ejs +9 -0
- package/build/templates/packages/tamagui/components/EditScreenInfo.tsx.ejs +29 -0
- package/build/templates/packages/tamagui/components/ScreenContent.tsx.ejs +22 -0
- package/build/templates/packages/unistyles/components/BackButton.tsx.ejs +26 -0
- package/build/templates/packages/unistyles/components/Button.tsx.ejs +12 -0
- package/build/templates/packages/unistyles/components/EditScreenInfo.tsx.ejs +61 -0
- package/build/templates/packages/unistyles/components/ScreenContent.tsx.ejs +24 -0
- package/build/templates/packages/unistyles/theme.ts.ejs +30 -46
- package/build/types/types.d.ts +3 -2
- package/build/types/utilities/configureProjectFiles.d.ts +1 -1
- package/build/types/utilities/generateProjectFiles.d.ts +1 -1
- package/build/types/utilities/getPackageManager.d.ts +1 -0
- package/build/types/utilities/validateProjectName.d.ts +1 -1
- package/build/types.js +3 -2
- package/build/utilities/configureProjectFiles.js +86 -19
- package/build/utilities/generateProjectFiles.js +8 -4
- package/build/utilities/getPackageManager.js +9 -2
- package/build/utilities/printOutput.js +4 -2
- package/build/utilities/renderTitle.js +8 -1
- package/build/utilities/runCLI.js +124 -34
- package/build/utilities/showHelp.js +4 -1
- package/build/utilities/validateProjectName.js +14 -8
- package/package.json +66 -66
- package/build/templates/base/.prettierrc +0 -7
- package/build/templates/packages/expo-router/drawer/components/edit-screen-info.tsx.ejs +0 -153
- package/build/templates/packages/expo-router/index.js +0 -4
- package/build/templates/packages/expo-router/index.ts +0 -1
- package/build/templates/packages/expo-router/tabs/components/edit-screen-info.tsx.ejs +0 -153
- package/build/templates/packages/react-navigation/components/edit-screen-info.tsx.ejs +0 -180
- package/build/types/templates/packages/expo-router/index.d.ts +0 -1
- /package/build/templates/packages/expo-router/drawer/app/{[...unmatched].tsx.ejs → +not-found.tsx.ejs} +0 -0
- /package/build/templates/packages/expo-router/stack/app/{[...unmatched].tsx.ejs → +not-found.tsx.ejs} +0 -0
- /package/build/templates/packages/expo-router/tabs/app/{[...unmatched].tsx.ejs → +not-found.tsx.ejs} +0 -0
|
@@ -1,87 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<% } else if (props.stylingPackage?.name === "tamagui") { %>
|
|
4
|
-
import { YStack, H2, Separator, Theme } from "tamagui";
|
|
5
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
6
|
-
import { Box, Text } from 'theme';
|
|
7
|
-
<% } else if (props.stylingPackage?.name === "unistyles") { %>
|
|
8
|
-
import { useStyles } from 'react-native-unistyles'
|
|
9
|
-
import { Text, View } from 'react-native';
|
|
10
|
-
<% } else { %>
|
|
11
|
-
import { StyleSheet, Text, View } from "react-native";
|
|
12
|
-
<% } %>
|
|
1
|
+
import { Stack } from 'expo-router';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
13
3
|
|
|
14
|
-
import
|
|
4
|
+
import { ScreenContent } from '~/components/ScreenContent';
|
|
15
5
|
|
|
16
|
-
export default function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
</View>
|
|
26
|
-
);
|
|
27
|
-
<% } else if (props.stylingPackage?.name === "nativewind") { %>
|
|
28
|
-
return (
|
|
29
|
-
<View className={styles.container}>
|
|
30
|
-
<Text className={styles.title}>Tab Two</Text>
|
|
31
|
-
<View className={styles.separator} />
|
|
32
|
-
<EditScreenInfo path="app/(tabs)/index.tsx" />
|
|
33
|
-
</View>
|
|
34
|
-
);
|
|
35
|
-
<% } else if (props.stylingPackage?.name === "tamagui") { %>
|
|
36
|
-
return (
|
|
37
|
-
<Theme name="light">
|
|
38
|
-
<YStack flex={1} alignItems="center" justifyContent="center">
|
|
39
|
-
<H2>Tab Two</H2>
|
|
40
|
-
<Separator />
|
|
41
|
-
<EditScreenInfo path="app/(tabs)/index.tsx" />
|
|
42
|
-
</YStack>
|
|
43
|
-
</Theme>
|
|
44
|
-
);
|
|
45
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
46
|
-
return (
|
|
47
|
-
<Box flex={1} alignItems="center" justifyContent="center">
|
|
48
|
-
<Text variant="title">Tab Two</Text>
|
|
49
|
-
<Box height={1} marginVertical="l_32" width="80%" />
|
|
50
|
-
<EditScreenInfo path="app/(tabs)/two.tsx" />
|
|
51
|
-
</Box>
|
|
52
|
-
);
|
|
53
|
-
<% } else { %>
|
|
54
|
-
return (
|
|
55
|
-
<View style={styles.container}>
|
|
56
|
-
<Text style={styles.title}>Tab Two</Text>
|
|
57
|
-
<View style={styles.separator} />
|
|
58
|
-
<EditScreenInfo path="app/(tabs)/two.tsx" />
|
|
59
|
-
</View>
|
|
60
|
-
);
|
|
61
|
-
<% } %>
|
|
6
|
+
export default function Home() {
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<Stack.Screen options={{ title: 'Tab Two' }} />
|
|
10
|
+
<View style={styles.container}>
|
|
11
|
+
<ScreenContent path="app/(tabs)/two.tsx" title="Tab Two" />
|
|
12
|
+
</View>
|
|
13
|
+
</>
|
|
14
|
+
);
|
|
62
15
|
}
|
|
63
16
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<% } else if (props.stylingPackage?.name === "stylesheet") { %>
|
|
71
|
-
const styles = StyleSheet.create({
|
|
72
|
-
container: {
|
|
73
|
-
alignItems: "center",
|
|
74
|
-
flex: 1,
|
|
75
|
-
justifyContent: "center",
|
|
76
|
-
},
|
|
77
|
-
separator: {
|
|
78
|
-
height: 1,
|
|
79
|
-
marginVertical: 30,
|
|
80
|
-
width: "80%",
|
|
81
|
-
},
|
|
82
|
-
title: {
|
|
83
|
-
fontSize: 20,
|
|
84
|
-
fontWeight: "bold",
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
<% } %>
|
|
17
|
+
const styles = StyleSheet.create({
|
|
18
|
+
container: {
|
|
19
|
+
flex: 1,
|
|
20
|
+
padding: 24,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -4,6 +4,9 @@ import '../global.css';
|
|
|
4
4
|
<% if (props.stylingPackage?.name === "unistyles") { %>
|
|
5
5
|
import '../unistyles';
|
|
6
6
|
<% } %>
|
|
7
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
8
|
+
import '../translation';
|
|
9
|
+
<% } %>
|
|
7
10
|
|
|
8
11
|
<% if (props.stylingPackage?.name === "tamagui") { %>
|
|
9
12
|
import React, { useEffect } from "react";
|
|
@@ -1,95 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { YStack, Paragraph, Separator, Theme } from "tamagui";
|
|
5
|
-
import { Platform } from 'react-native'
|
|
6
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
7
|
-
import { Platform } from 'react-native';
|
|
8
|
-
import { Box, Text } from 'theme';
|
|
9
|
-
<% } else if (props.stylingPackage?.name === "unistyles") { %>
|
|
10
|
-
import { useStyles } from 'react-native-unistyles'
|
|
11
|
-
import { Platform, Text, View } from 'react-native';
|
|
12
|
-
<% } else { %>
|
|
13
|
-
import { Platform, StyleSheet, Text, View } from "react-native";
|
|
14
|
-
<% } %>
|
|
15
|
-
import { StatusBar } from "expo-status-bar";
|
|
16
|
-
|
|
17
|
-
import EditScreenInfo from "../components/edit-screen-info";
|
|
1
|
+
import { ScreenContent } from 'components/ScreenContent';
|
|
2
|
+
import { StatusBar } from 'expo-status-bar';
|
|
3
|
+
import { Platform } from 'react-native';
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
5
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
6
|
+
import { InternalizationExample } from 'components/InternalizationExample';
|
|
7
|
+
<% } %>
|
|
22
8
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<StatusBar style={Platform.OS === "ios" ? "light" : "auto"} />
|
|
35
|
-
<Text className={styles.title}>Modal</Text>
|
|
36
|
-
<View className={styles.separator} />
|
|
37
|
-
<EditScreenInfo path="app/modal.tsx" />
|
|
38
|
-
</View>
|
|
39
|
-
);
|
|
40
|
-
<% } else if (props.stylingPackage?.name === "tamagui") { %>
|
|
41
|
-
return (
|
|
42
|
-
<Theme name="light">
|
|
43
|
-
<YStack flex={1} alignItems="center" justifyContent="center">
|
|
44
|
-
<StatusBar style={Platform.OS === "ios" ? "light" : "auto"} />
|
|
45
|
-
<Paragraph>Modal</Paragraph>
|
|
46
|
-
<Separator />
|
|
47
|
-
<EditScreenInfo path="app/modal.tsx" />
|
|
48
|
-
</YStack>
|
|
49
|
-
</Theme>
|
|
50
|
-
);
|
|
51
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
52
|
-
return (
|
|
53
|
-
<Box flex={1} alignItems="center" justifyContent="center">
|
|
54
|
-
<StatusBar style={Platform.OS === 'ios' ? 'light' : 'auto'} />
|
|
55
|
-
<Text variant="title">Modal</Text>
|
|
56
|
-
<Box height={1} marginVertical="l_32" width="80%" />
|
|
57
|
-
<EditScreenInfo path="app/modal.tsx" />
|
|
58
|
-
</Box>
|
|
59
|
-
);
|
|
60
|
-
<% } else { %>
|
|
61
|
-
return (
|
|
62
|
-
<View style={styles.container}>
|
|
63
|
-
<StatusBar style={Platform.OS === "ios" ? "light" : "auto"} />
|
|
64
|
-
<Text style={styles.title}>Modal</Text>
|
|
65
|
-
<View style={styles.separator} />
|
|
66
|
-
<EditScreenInfo path="app/modal.tsx" />
|
|
67
|
-
</View>
|
|
68
|
-
);
|
|
69
|
-
<% } %>
|
|
9
|
+
export default function Modal() {
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<ScreenContent path="app/modal.tsx" title="Modal">
|
|
13
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
14
|
+
<InternalizationExample />
|
|
15
|
+
<% } %>
|
|
16
|
+
</ScreenContent>
|
|
17
|
+
<StatusBar style={Platform.OS === 'ios' ? 'light' : 'auto'} />
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
70
20
|
}
|
|
71
|
-
|
|
72
|
-
<% if (props.stylingPackage?.name === "nativewind") { %>
|
|
73
|
-
const styles = {
|
|
74
|
-
container: `items-center flex-1 justify-center`,
|
|
75
|
-
separator: `h-[1px] my-7 w-4/5 bg-gray-200`,
|
|
76
|
-
title: `text-xl font-bold`
|
|
77
|
-
};
|
|
78
|
-
<% } else if (props.stylingPackage?.name === "stylesheet") { %>
|
|
79
|
-
const styles = StyleSheet.create({
|
|
80
|
-
container: {
|
|
81
|
-
alignItems: "center",
|
|
82
|
-
flex: 1,
|
|
83
|
-
justifyContent: "center"
|
|
84
|
-
},
|
|
85
|
-
separator: {
|
|
86
|
-
height: 1,
|
|
87
|
-
marginVertical: 30,
|
|
88
|
-
width: "80%"
|
|
89
|
-
},
|
|
90
|
-
title: {
|
|
91
|
-
fontSize: 20,
|
|
92
|
-
fontWeight: "bold"
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
<% } %>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button, StyleSheet, View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
export const InternalizationExample = () => {
|
|
6
|
+
const { t, i18n } = useTranslation();
|
|
7
|
+
|
|
8
|
+
const toggleLanguage = (locale: 'en' | 'fr') => {
|
|
9
|
+
i18n.changeLanguage(locale);
|
|
10
|
+
};
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<View style={styles.content}>
|
|
14
|
+
<Button title={t('button.french')} onPress={() => toggleLanguage('fr')} />
|
|
15
|
+
<Button title={t('button.english')} onPress={() => toggleLanguage('en')} />
|
|
16
|
+
</View>
|
|
17
|
+
</>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const styles = StyleSheet.create({
|
|
22
|
+
content: { gap: 20, padding: 20 },
|
|
23
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Resource } from 'i18next';
|
|
2
|
+
|
|
3
|
+
export const fallbackChecker = (resources: Resource, fallbackLng: string) => {
|
|
4
|
+
const languages = Object.keys(resources);
|
|
5
|
+
const hasFallback = languages.find((key) => fallbackLng === key);
|
|
6
|
+
|
|
7
|
+
if (!hasFallback) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
`fallbackLng "${fallbackLng}", is not present in your resources, please check your config, languages available: ${languages.join(', ')}`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return fallbackLng;
|
|
13
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import i18n, { Resource } from 'i18next';
|
|
2
|
+
import { initReactI18next } from 'react-i18next';
|
|
3
|
+
|
|
4
|
+
import { fallbackChecker } from './fallbackChecker';
|
|
5
|
+
import { languageDetector } from './languageDetector';
|
|
6
|
+
|
|
7
|
+
type Init18n = {
|
|
8
|
+
resources: Resource;
|
|
9
|
+
fallbackLng: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const init18n = ({ resources, fallbackLng }: Init18n) => {
|
|
13
|
+
return i18n
|
|
14
|
+
.use(languageDetector)
|
|
15
|
+
.use(initReactI18next)
|
|
16
|
+
.init({
|
|
17
|
+
resources,
|
|
18
|
+
fallbackLng: fallbackChecker(resources, fallbackLng),
|
|
19
|
+
compatibilityJSON: 'v3', // By default React Native projects does not support Intl
|
|
20
|
+
interpolation: {
|
|
21
|
+
escapeValue: false,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as Localization from 'expo-localization';
|
|
2
|
+
import { LanguageDetectorModule } from 'i18next';
|
|
3
|
+
|
|
4
|
+
export const languageDetector: LanguageDetectorModule = {
|
|
5
|
+
type: 'languageDetector',
|
|
6
|
+
detect: () => {
|
|
7
|
+
const locales = Localization.getLocales();
|
|
8
|
+
const firstLanguageCode = locales[0].languageCode ?? 'en';
|
|
9
|
+
return firstLanguageCode;
|
|
10
|
+
},
|
|
11
|
+
init: () => {},
|
|
12
|
+
cacheUserLanguage: () => {},
|
|
13
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"button": {
|
|
3
|
+
"french": "Changer la langue en français",
|
|
4
|
+
"english": "Changer la langue en anglais"
|
|
5
|
+
},
|
|
6
|
+
"getStarted": "Ouvrez le code de cet écran :",
|
|
7
|
+
"changeCode": "Modifiez n'importe quel texte, enregistrez le fichier et votre application sera automatiquement mise à jour."
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { init18n } from 'core/i18n/init';
|
|
2
|
+
import en from 'translation/en.json';
|
|
3
|
+
import fr from 'translation/fr.json';
|
|
4
|
+
|
|
5
|
+
export const resources = {
|
|
6
|
+
en: {
|
|
7
|
+
translation: en,
|
|
8
|
+
},
|
|
9
|
+
fr: {
|
|
10
|
+
translation: fr,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const fallbackLng = 'en';
|
|
15
|
+
|
|
16
|
+
export type LanguageCode = keyof typeof resources;
|
|
17
|
+
|
|
18
|
+
const i18n = init18n({ resources, fallbackLng });
|
|
19
|
+
|
|
20
|
+
export default i18n;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Feather } from '@expo/vector-icons';
|
|
2
|
+
import { Text, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export const BackButton = ({ onPress }: { onPress: () => void }) => {
|
|
5
|
+
return (
|
|
6
|
+
<View className={styles.backButton}>
|
|
7
|
+
<Feather name="chevron-left" size={16} color="#007AFF" />
|
|
8
|
+
<Text className={styles.backButtonText} onPress={onPress}>
|
|
9
|
+
Back
|
|
10
|
+
</Text>
|
|
11
|
+
</View>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const styles = {
|
|
16
|
+
backButton: 'flex-row',
|
|
17
|
+
backButtonText: 'text-blue-500 ml-1',
|
|
18
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Text, TouchableOpacity } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const Button = ({ onPress, title }: { onPress: () => void; title: string }) => {
|
|
4
|
+
return (
|
|
5
|
+
<TouchableOpacity className={styles.button} onPress={onPress}>
|
|
6
|
+
<Text className={styles.buttonText}>{title}</Text>
|
|
7
|
+
</TouchableOpacity>
|
|
8
|
+
);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const styles = {
|
|
12
|
+
button: 'items-center bg-indigo-500 rounded-[28px] shadow-md p-4',
|
|
13
|
+
buttonText: 'text-white text-lg font-semibold text-center',
|
|
14
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Text, View } from 'react-native';
|
|
2
|
+
|
|
3
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
<% } %>
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const EditScreenInfo = ({ path }: { path: string }) => {
|
|
9
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
const title = t('getStarted');
|
|
12
|
+
const description = t('changeCode')
|
|
13
|
+
<% } else { %>
|
|
14
|
+
const title = "Open up the code for this screen:"
|
|
15
|
+
const description = "Change any of the text, save the file, and your app will automatically update."
|
|
16
|
+
<% } %>
|
|
17
|
+
return (
|
|
18
|
+
<View>
|
|
19
|
+
<View className={styles.getStartedContainer}>
|
|
20
|
+
<Text className={styles.getStartedText}>{title}</Text>
|
|
21
|
+
<View className={styles.codeHighlightContainer + styles.homeScreenFilename}>
|
|
22
|
+
<Text>{path}</Text>
|
|
23
|
+
</View>
|
|
24
|
+
<Text className={styles.getStartedText}>
|
|
25
|
+
{description}
|
|
26
|
+
</Text>
|
|
27
|
+
</View>
|
|
28
|
+
</View>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const styles = {
|
|
33
|
+
codeHighlightContainer: `rounded-md px-1`,
|
|
34
|
+
getStartedContainer: `items-center mx-12`,
|
|
35
|
+
getStartedText: `text-lg leading-6 text-center`,
|
|
36
|
+
helpContainer: `items-center mx-5 mt-4`,
|
|
37
|
+
helpLink: `py-4`,
|
|
38
|
+
helpLinkText: `text-center`,
|
|
39
|
+
homeScreenFilename: `my-2`,
|
|
40
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Text, View } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { EditScreenInfo } from './EditScreenInfo';
|
|
4
|
+
|
|
5
|
+
type ScreenContentProps = {
|
|
6
|
+
title: string;
|
|
7
|
+
path: string;
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const ScreenContent = ({ title, path, children} : ScreenContentProps) => {
|
|
12
|
+
return (
|
|
13
|
+
<View className={styles.container}>
|
|
14
|
+
<Text className={styles.title}>{title}</Text>
|
|
15
|
+
<View className={styles.separator} />
|
|
16
|
+
<EditScreenInfo path={path} />
|
|
17
|
+
{children}
|
|
18
|
+
</View>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
const styles = {
|
|
22
|
+
container: `items-center flex-1 justify-center`,
|
|
23
|
+
separator: `h-[1px] my-7 w-4/5 bg-gray-200`,
|
|
24
|
+
title: `text-xl font-bold`,
|
|
25
|
+
};
|
|
@@ -4,6 +4,9 @@ import './global.css';
|
|
|
4
4
|
<% if (props.stylingPackage?.name === "unistyles") { %>
|
|
5
5
|
import './unistyles';
|
|
6
6
|
<% } %>
|
|
7
|
+
<% if (props.internalizationPackage?.name === "i18next") { %>
|
|
8
|
+
import './translation';
|
|
9
|
+
<% } %>
|
|
7
10
|
import "react-native-gesture-handler";
|
|
8
11
|
<% if (props.stylingPackage?.name === "tamagui") { %>
|
|
9
12
|
import React, { useEffect } from "react";
|
|
@@ -19,7 +22,7 @@ import "react-native-gesture-handler";
|
|
|
19
22
|
import { theme } from 'theme';
|
|
20
23
|
<% } %>
|
|
21
24
|
|
|
22
|
-
import RootStack from "./
|
|
25
|
+
import RootStack from "./navigation";
|
|
23
26
|
|
|
24
27
|
export default function App() {
|
|
25
28
|
<% if (props.stylingPackage?.name === "tamagui") { %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ionicons, MaterialIcons } from '@expo/vector-icons';
|
|
2
2
|
import { createDrawerNavigator } from '@react-navigation/drawer';
|
|
3
|
-
import { Pressable } from 'react-native';
|
|
4
3
|
import { StackScreenProps } from '@react-navigation/stack';
|
|
4
|
+
import { HeaderButton } from 'components/HeaderButton';
|
|
5
5
|
|
|
6
6
|
import { RootStackParamList } from '.';
|
|
7
7
|
import TabNavigator from './tab-navigator';
|
|
@@ -12,39 +12,27 @@ type Props = StackScreenProps<RootStackParamList, 'DrawerNavigator'>;
|
|
|
12
12
|
const Drawer = createDrawerNavigator();
|
|
13
13
|
|
|
14
14
|
export default function DrawerNavigator({ navigation }: Props) {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return (
|
|
16
|
+
<Drawer.Navigator>
|
|
17
17
|
<Drawer.Screen
|
|
18
18
|
name="Home"
|
|
19
19
|
component={Home}
|
|
20
20
|
options={{
|
|
21
|
-
drawerIcon: ({ size, color }) =>
|
|
21
|
+
drawerIcon: ({ size, color }) => (
|
|
22
|
+
<Ionicons name="home-outline" size={size} color={color} />
|
|
23
|
+
),
|
|
22
24
|
}}
|
|
23
25
|
/>
|
|
24
|
-
|
|
26
|
+
<Drawer.Screen
|
|
27
|
+
name="Tabs"
|
|
28
|
+
component={TabNavigator}
|
|
25
29
|
options={{
|
|
26
|
-
headerRight: () => (
|
|
27
|
-
<Pressable onPress={() => navigation.navigate('Modal')}>
|
|
28
|
-
{({ pressed }) => (
|
|
29
|
-
<FontAwesome
|
|
30
|
-
name="info-circle"
|
|
31
|
-
size={25}
|
|
32
|
-
color="gray"
|
|
33
|
-
style={[
|
|
34
|
-
{
|
|
35
|
-
marginRight: 16,
|
|
36
|
-
opacity: pressed ? 0.5 : 1,
|
|
37
|
-
},
|
|
38
|
-
]}
|
|
39
|
-
/>
|
|
40
|
-
)}
|
|
41
|
-
</Pressable>
|
|
42
|
-
),
|
|
30
|
+
headerRight: () => <HeaderButton onPress={() => navigation.navigate('Modal')} />,
|
|
43
31
|
drawerIcon: ({ size, color }) => (
|
|
44
32
|
<MaterialIcons name="border-bottom" size={size} color={color} />
|
|
45
33
|
),
|
|
46
34
|
}}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
35
|
+
/>
|
|
36
|
+
</Drawer.Navigator>
|
|
37
|
+
);
|
|
50
38
|
}
|
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
<% if (props.navigationPackage?.options.type === 'stack') { %>
|
|
2
|
-
import { Feather } from "@expo/vector-icons";
|
|
3
2
|
import { NavigationContainer } from "@react-navigation/native";
|
|
4
3
|
import { createStackNavigator } from "@react-navigation/stack";
|
|
5
|
-
<% if (props.stylingPackage?.name === "nativewind") { %>
|
|
6
|
-
import { Text, View } from "react-native";
|
|
7
|
-
<% } else if (props.stylingPackage?.name === "tamagui") { %>
|
|
8
|
-
import { Button, Text } from "tamagui";
|
|
9
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
10
|
-
import { Box, Text, useTheme } from 'theme';
|
|
11
|
-
<% } else if (props.stylingPackage?.name === "unistyles") { %>
|
|
12
|
-
import { createStyleSheet, useStyles } from 'react-native-unistyles'
|
|
13
|
-
import { Text, View } from 'react-native';
|
|
14
|
-
<% } else { %>
|
|
15
|
-
import { Text, View, StyleSheet } from "react-native";
|
|
16
|
-
<% } %>
|
|
17
4
|
|
|
18
5
|
import Overview from "../screens/overview";
|
|
19
6
|
import Details from "../screens/details";
|
|
7
|
+
import { BackButton } from '../components/BackButton';
|
|
20
8
|
|
|
21
9
|
export type RootStackParamList = {
|
|
22
10
|
Overview: undefined;
|
|
@@ -26,14 +14,7 @@
|
|
|
26
14
|
const Stack = createStackNavigator<RootStackParamList>();
|
|
27
15
|
|
|
28
16
|
export default function RootStack() {
|
|
29
|
-
<% if (props.stylingPackage?.name === "restyle") { %>
|
|
30
|
-
const { colors } = useTheme();
|
|
31
|
-
<% } %>
|
|
32
17
|
|
|
33
|
-
<% if (props.stylingPackage?.name === "unistyles") { %>
|
|
34
|
-
const { styles, theme } = useStyles(stylesheet);
|
|
35
|
-
<% } %>
|
|
36
|
-
|
|
37
18
|
return (
|
|
38
19
|
<NavigationContainer>
|
|
39
20
|
<Stack.Navigator initialRouteName="Overview">
|
|
@@ -41,95 +22,15 @@
|
|
|
41
22
|
<Stack.Screen
|
|
42
23
|
name="Details"
|
|
43
24
|
component={Details}
|
|
44
|
-
<% if (props.stylingPackage?.name === "nativewind") { %>
|
|
45
25
|
options={({ navigation }) => ({
|
|
46
|
-
|
|
47
|
-
<View className={styles.backButton}>
|
|
48
|
-
<Feather name="chevron-left" size={16} color="#007AFF" />
|
|
49
|
-
<Text className={styles.backButtonText} onPress={navigation.goBack}>Back</Text>
|
|
50
|
-
</View>
|
|
51
|
-
)
|
|
26
|
+
headerLeft: () => <BackButton onPress={navigation.goBack} />,
|
|
52
27
|
})}
|
|
53
|
-
<% } else if (props.stylingPackage?.name === "tamagui") { %>
|
|
54
|
-
options={({ navigation }) => ({
|
|
55
|
-
headerLeft: () => (
|
|
56
|
-
<Button
|
|
57
|
-
unstyled
|
|
58
|
-
flexDirection="row"
|
|
59
|
-
backgroundColor="transparent"
|
|
60
|
-
pressStyle={{ opacity: 0.5 }}
|
|
61
|
-
paddingLeft={20}
|
|
62
|
-
onPress={navigation.goBack}
|
|
63
|
-
icon={<Feather name="chevron-left" size={16} color="#007AFF" />}
|
|
64
|
-
>
|
|
65
|
-
<Text color="#007AFF">Back</Text>
|
|
66
|
-
</Button>
|
|
67
|
-
),
|
|
68
|
-
})}
|
|
69
|
-
<% } else if (props.stylingPackage?.name === "restyle") { %>
|
|
70
|
-
options={({ navigation }) => ({
|
|
71
|
-
headerLeft: () => (
|
|
72
|
-
<Box flexDirection="row" paddingLeft="m_16">
|
|
73
|
-
<Feather name="chevron-left" size={16} color={colors.blue} />
|
|
74
|
-
<Text marginLeft="xs_4" color="blue" onPress={navigation.goBack}>
|
|
75
|
-
Back
|
|
76
|
-
</Text>
|
|
77
|
-
</Box>
|
|
78
|
-
),
|
|
79
|
-
})}
|
|
80
|
-
<% } else if (props.stylingPackage?.name === "unistyles") { %>
|
|
81
|
-
options={({ navigation }) => ({
|
|
82
|
-
headerLeft: () => (
|
|
83
|
-
<View style={styles.backButton}>
|
|
84
|
-
<Feather name="chevron-left" size={16} color={theme.colors.azureRadiance} />
|
|
85
|
-
<Text style={styles.backButtonText} onPress={navigation.goBack}>Back</Text>
|
|
86
|
-
</View>
|
|
87
|
-
)
|
|
88
|
-
})}
|
|
89
|
-
<% } else { %>
|
|
90
|
-
options={({ navigation }) => ({
|
|
91
|
-
headerLeft: () => (
|
|
92
|
-
<View style={styles.backButton}>
|
|
93
|
-
<Feather name="chevron-left" size={16} color="#007AFF" />
|
|
94
|
-
<Text style={styles.backButtonText} onPress={navigation.goBack}>Back</Text>
|
|
95
|
-
</View>
|
|
96
|
-
)
|
|
97
|
-
})}
|
|
98
|
-
<% } %>
|
|
99
28
|
/>
|
|
100
29
|
</Stack.Navigator>
|
|
101
30
|
</NavigationContainer>
|
|
102
31
|
);
|
|
103
32
|
}
|
|
104
33
|
|
|
105
|
-
<% if (props.stylingPackage?.name === "nativewind") { %>
|
|
106
|
-
const styles = {
|
|
107
|
-
backButton: "flex-row",
|
|
108
|
-
backButtonText: "text-blue-500 ml-1"
|
|
109
|
-
};
|
|
110
|
-
<% } else if (props.stylingPackage?.name === "unistyles") { %>
|
|
111
|
-
const stylesheet = createStyleSheet((theme) => ({
|
|
112
|
-
backButton: {
|
|
113
|
-
flexDirection: 'row',
|
|
114
|
-
paddingLeft: 20,
|
|
115
|
-
},
|
|
116
|
-
backButtonText: {
|
|
117
|
-
color: theme.colors.azureRadiance,
|
|
118
|
-
marginLeft: 4,
|
|
119
|
-
},
|
|
120
|
-
}));
|
|
121
|
-
<% } else if (props.stylingPackage?.name === "stylesheet") { %>
|
|
122
|
-
const styles = StyleSheet.create({
|
|
123
|
-
backButton: {
|
|
124
|
-
flexDirection: "row",
|
|
125
|
-
paddingLeft: 20,
|
|
126
|
-
},
|
|
127
|
-
backButtonText: {
|
|
128
|
-
color: "#007AFF",
|
|
129
|
-
marginLeft: 4
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
<% } %>
|
|
133
34
|
<% } else if (props.navigationPackage?.options.type === 'tabs') { %>
|
|
134
35
|
import { NavigationContainer } from "@react-navigation/native";
|
|
135
36
|
import { createStackNavigator } from "@react-navigation/stack";
|