@mr.dj2u/create-expo-stack 2.21.3-mrdj.0

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 (191) hide show
  1. package/README.md +435 -0
  2. package/bin/create-expo-stack.js +2 -0
  3. package/build/cli.js +49 -0
  4. package/build/commands/create-expo-stack.js +471 -0
  5. package/build/constants.js +39 -0
  6. package/build/templates/base/.gitignore.ejs +26 -0
  7. package/build/templates/base/.npmrc.ejs +1 -0
  8. package/build/templates/base/App.tsx.ejs +66 -0
  9. package/build/templates/base/app.json.ejs +69 -0
  10. package/build/templates/base/assets/adaptive-icon.png +0 -0
  11. package/build/templates/base/assets/favicon.png +0 -0
  12. package/build/templates/base/assets/icon.png +0 -0
  13. package/build/templates/base/assets/splash.png +0 -0
  14. package/build/templates/base/babel.config.js.ejs +38 -0
  15. package/build/templates/base/components/BackButton.tsx.ejs +23 -0
  16. package/build/templates/base/components/Button.tsx.ejs +42 -0
  17. package/build/templates/base/components/Container.tsx.ejs +14 -0
  18. package/build/templates/base/components/EditScreenInfo.tsx.ejs +44 -0
  19. package/build/templates/base/components/HeaderButton.tsx.ejs +31 -0
  20. package/build/templates/base/components/ScreenContent.tsx.ejs +40 -0
  21. package/build/templates/base/components/TabBarIcon.tsx.ejs +15 -0
  22. package/build/templates/base/eslint.config.js.ejs +15 -0
  23. package/build/templates/base/package.json.ejs +191 -0
  24. package/build/templates/base/prettier.config.js.ejs +11 -0
  25. package/build/templates/base/tsconfig.json.ejs +39 -0
  26. package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/_layout.tsx.ejs +40 -0
  27. package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/index.tsx.ejs +15 -0
  28. package/build/templates/packages/expo-router/drawer/app/(drawer)/(tabs)/two.tsx.ejs +15 -0
  29. package/build/templates/packages/expo-router/drawer/app/(drawer)/_layout.tsx.ejs +65 -0
  30. package/build/templates/packages/expo-router/drawer/app/(drawer)/index.tsx.ejs +15 -0
  31. package/build/templates/packages/expo-router/drawer/app/+html.tsx.ejs +49 -0
  32. package/build/templates/packages/expo-router/drawer/app/+not-found.tsx.ejs +100 -0
  33. package/build/templates/packages/expo-router/drawer/app/_layout.tsx.ejs +91 -0
  34. package/build/templates/packages/expo-router/drawer/app/modal.tsx.ejs +21 -0
  35. package/build/templates/packages/expo-router/expo-env.d.ts +4 -0
  36. package/build/templates/packages/expo-router/index.js.ejs +4 -0
  37. package/build/templates/packages/expo-router/metro.config.js.ejs +24 -0
  38. package/build/templates/packages/expo-router/stack/app/+html.tsx.ejs +49 -0
  39. package/build/templates/packages/expo-router/stack/app/+not-found.tsx.ejs +113 -0
  40. package/build/templates/packages/expo-router/stack/app/_layout.tsx.ejs +63 -0
  41. package/build/templates/packages/expo-router/stack/app/details.tsx.ejs +56 -0
  42. package/build/templates/packages/expo-router/stack/app/index.tsx.ejs +73 -0
  43. package/build/templates/packages/expo-router/tabs/app/(tabs)/_layout.tsx.ejs +52 -0
  44. package/build/templates/packages/expo-router/tabs/app/(tabs)/index.tsx.ejs +37 -0
  45. package/build/templates/packages/expo-router/tabs/app/(tabs)/two.tsx.ejs +37 -0
  46. package/build/templates/packages/expo-router/tabs/app/+html.tsx.ejs +49 -0
  47. package/build/templates/packages/expo-router/tabs/app/+not-found.tsx.ejs +110 -0
  48. package/build/templates/packages/expo-router/tabs/app/_layout.tsx.ejs +84 -0
  49. package/build/templates/packages/expo-router/tabs/app/modal.tsx.ejs +21 -0
  50. package/build/templates/packages/firebase/.env.ejs +8 -0
  51. package/build/templates/packages/firebase/metro.config.js.ejs +14 -0
  52. package/build/templates/packages/firebase/utils/firebase.ts.ejs +26 -0
  53. package/build/templates/packages/i18next/components/InternalizationExample.tsx.ejs +23 -0
  54. package/build/templates/packages/i18next/core/i18n/fallbackChecker.ts.ejs +13 -0
  55. package/build/templates/packages/i18next/core/i18n/init.ts.ejs +24 -0
  56. package/build/templates/packages/i18next/core/i18n/languageDetector.ts.ejs +13 -0
  57. package/build/templates/packages/i18next/translation/en.json.ejs +8 -0
  58. package/build/templates/packages/i18next/translation/fr.json.ejs +8 -0
  59. package/build/templates/packages/i18next/translation/index.ts.ejs +20 -0
  60. package/build/templates/packages/nativewind/components/BackButton.tsx.ejs +22 -0
  61. package/build/templates/packages/nativewind/components/Button.tsx.ejs +21 -0
  62. package/build/templates/packages/nativewind/components/Container.tsx.ejs +13 -0
  63. package/build/templates/packages/nativewind/components/EditScreenInfo.tsx.ejs +40 -0
  64. package/build/templates/packages/nativewind/components/ScreenContent.tsx.ejs +27 -0
  65. package/build/templates/packages/nativewind/global.css +3 -0
  66. package/build/templates/packages/nativewind/metro.config.js +7 -0
  67. package/build/templates/packages/nativewind/nativewind-env.d.ts +2 -0
  68. package/build/templates/packages/nativewind/tailwind.config.js.ejs +15 -0
  69. package/build/templates/packages/nativewindui/components/Container.tsx.ejs +14 -0
  70. package/build/templates/packages/nativewindui/components/EditScreenInfo.tsx.ejs +45 -0
  71. package/build/templates/packages/nativewindui/components/HeaderButton.tsx.ejs +31 -0
  72. package/build/templates/packages/nativewindui/components/ScreenContent.tsx.ejs +40 -0
  73. package/build/templates/packages/nativewindui/components/TabBarIcon.tsx.ejs +15 -0
  74. package/build/templates/packages/nativewindui/components/nativewindui/Icon/Icon.ios.tsx.ejs +52 -0
  75. package/build/templates/packages/nativewindui/components/nativewindui/Icon/Icon.tsx.ejs +58 -0
  76. package/build/templates/packages/nativewindui/components/nativewindui/Icon/index.ts.ejs +16 -0
  77. package/build/templates/packages/nativewindui/components/nativewindui/Icon/types.ts.ejs +18 -0
  78. package/build/templates/packages/nativewindui/components/nativewindui/ThemeToggle.tsx.ejs +33 -0
  79. package/build/templates/packages/nativewindui/drawer/app/(drawer)/(tabs)/_layout.tsx.ejs +28 -0
  80. package/build/templates/packages/nativewindui/drawer/app/(drawer)/(tabs)/index.tsx.ejs +15 -0
  81. package/build/templates/packages/nativewindui/drawer/app/(drawer)/(tabs)/two.tsx.ejs +15 -0
  82. package/build/templates/packages/nativewindui/drawer/app/(drawer)/_layout.tsx.ejs +35 -0
  83. package/build/templates/packages/nativewindui/drawer/app/(drawer)/index.tsx.ejs +535 -0
  84. package/build/templates/packages/nativewindui/drawer/app/+html.tsx.ejs +46 -0
  85. package/build/templates/packages/nativewindui/drawer/app/+not-found.tsx.ejs +83 -0
  86. package/build/templates/packages/nativewindui/drawer/app/_layout.tsx.ejs +75 -0
  87. package/build/templates/packages/nativewindui/drawer/app/modal.tsx.ejs +33 -0
  88. package/build/templates/packages/nativewindui/global.css.ejs +91 -0
  89. package/build/templates/packages/nativewindui/lib/cn.ts.ejs +6 -0
  90. package/build/templates/packages/nativewindui/lib/useColorScheme.tsx.ejs +21 -0
  91. package/build/templates/packages/nativewindui/nativewind-env.d.ts.ejs +1 -0
  92. package/build/templates/packages/nativewindui/stack/app/+html.tsx.ejs +46 -0
  93. package/build/templates/packages/nativewindui/stack/app/+not-found.tsx.ejs +18 -0
  94. package/build/templates/packages/nativewindui/stack/app/_layout.tsx.ejs +78 -0
  95. package/build/templates/packages/nativewindui/stack/app/index.tsx.ejs +487 -0
  96. package/build/templates/packages/nativewindui/stack/app/modal.tsx.ejs +33 -0
  97. package/build/templates/packages/nativewindui/tabs/app/(tabs)/_layout.tsx.ejs +35 -0
  98. package/build/templates/packages/nativewindui/tabs/app/(tabs)/index.tsx.ejs +537 -0
  99. package/build/templates/packages/nativewindui/tabs/app/(tabs)/two.tsx.ejs +22 -0
  100. package/build/templates/packages/nativewindui/tabs/app/+html.tsx.ejs +46 -0
  101. package/build/templates/packages/nativewindui/tabs/app/+not-found.tsx.ejs +90 -0
  102. package/build/templates/packages/nativewindui/tabs/app/_layout.tsx.ejs +78 -0
  103. package/build/templates/packages/nativewindui/tabs/app/modal.tsx.ejs +21 -0
  104. package/build/templates/packages/nativewindui/tailwind.config.js.ejs +67 -0
  105. package/build/templates/packages/nativewindui/theme/colors.ts.ejs +123 -0
  106. package/build/templates/packages/nativewindui/theme/index.ts.ejs +32 -0
  107. package/build/templates/packages/nativewindui/theme/with-opacity.ts.ejs +155 -0
  108. package/build/templates/packages/react-navigation/App.tsx.ejs +73 -0
  109. package/build/templates/packages/react-navigation/navigation/drawer-navigator.tsx.ejs +31 -0
  110. package/build/templates/packages/react-navigation/navigation/index.tsx.ejs +108 -0
  111. package/build/templates/packages/react-navigation/navigation/tab-navigator.tsx.ejs +38 -0
  112. package/build/templates/packages/react-navigation/screens/details.tsx.ejs +41 -0
  113. package/build/templates/packages/react-navigation/screens/home.tsx.ejs +5 -0
  114. package/build/templates/packages/react-navigation/screens/modal.tsx.ejs +20 -0
  115. package/build/templates/packages/react-navigation/screens/one.tsx.ejs +5 -0
  116. package/build/templates/packages/react-navigation/screens/overview.tsx.ejs +54 -0
  117. package/build/templates/packages/react-navigation/screens/two.tsx.ejs +5 -0
  118. package/build/templates/packages/restyle/components/BackButton.tsx.ejs +19 -0
  119. package/build/templates/packages/restyle/components/Button.tsx.ejs +32 -0
  120. package/build/templates/packages/restyle/components/Container.tsx.ejs +16 -0
  121. package/build/templates/packages/restyle/components/EditScreenInfo.tsx.ejs +38 -0
  122. package/build/templates/packages/restyle/components/ScreenContent.tsx.ejs +30 -0
  123. package/build/templates/packages/restyle/theme.ts.ejs +51 -0
  124. package/build/templates/packages/supabase/.env.ejs +2 -0
  125. package/build/templates/packages/supabase/utils/supabase.ts.ejs +14 -0
  126. package/build/templates/packages/tamagui/components/BackButton.tsx.ejs +12 -0
  127. package/build/templates/packages/tamagui/components/Button.tsx.ejs +17 -0
  128. package/build/templates/packages/tamagui/components/Container.tsx.ejs +12 -0
  129. package/build/templates/packages/tamagui/components/EditScreenInfo.tsx.ejs +27 -0
  130. package/build/templates/packages/tamagui/components/ScreenContent.tsx.ejs +23 -0
  131. package/build/templates/packages/tamagui/tamagui.config.ts.ejs +14 -0
  132. package/build/templates/packages/unistyles/breakpoints.ts.ejs +9 -0
  133. package/build/templates/packages/unistyles/components/BackButton.tsx.ejs +28 -0
  134. package/build/templates/packages/unistyles/components/Button.tsx.ejs +42 -0
  135. package/build/templates/packages/unistyles/components/Container.tsx.ejs +17 -0
  136. package/build/templates/packages/unistyles/components/EditScreenInfo.tsx.ejs +53 -0
  137. package/build/templates/packages/unistyles/components/ScreenContent.tsx.ejs +43 -0
  138. package/build/templates/packages/unistyles/theme.ts.ejs +34 -0
  139. package/build/templates/packages/unistyles/unistyles.ts.ejs +27 -0
  140. package/build/templates/packages/uniwind/global.css +2 -0
  141. package/build/templates/packages/uniwind/metro.config.js.ejs +10 -0
  142. package/build/templates/packages/vexo-analytics/.env.ejs +7 -0
  143. package/build/templates/packages/zustand/store/store.ts.ejs +15 -0
  144. package/build/types/cli.d.ts +4 -0
  145. package/build/types/commands/create-expo-stack.d.ts +3 -0
  146. package/build/types/constants.d.ts +10 -0
  147. package/build/types/types.d.ts +33 -0
  148. package/build/types/utilities/bumpVersion.d.ts +1 -0
  149. package/build/types/utilities/clearNavigationPackages.d.ts +2 -0
  150. package/build/types/utilities/clearStylingPackages.d.ts +2 -0
  151. package/build/types/utilities/configAnalytics.d.ts +18 -0
  152. package/build/types/utilities/configStorage.d.ts +8 -0
  153. package/build/types/utilities/configureProjectFiles.d.ts +3 -0
  154. package/build/types/utilities/copyBaseAssets.d.ts +2 -0
  155. package/build/types/utilities/generateNWUI.d.ts +3 -0
  156. package/build/types/utilities/generateProjectFiles.d.ts +5 -0
  157. package/build/types/utilities/getPackageManager.d.ts +8 -0
  158. package/build/types/utilities/index.d.ts +10 -0
  159. package/build/types/utilities/printOutput.d.ts +3 -0
  160. package/build/types/utilities/publishToGitHub.d.ts +2 -0
  161. package/build/types/utilities/renderTitle.d.ts +2 -0
  162. package/build/types/utilities/runCLI.d.ts +3 -0
  163. package/build/types/utilities/runEasConfigure.d.ts +3 -0
  164. package/build/types/utilities/runIgnite.d.ts +3 -0
  165. package/build/types/utilities/showHelp.d.ts +1 -0
  166. package/build/types/utilities/systemCommand.d.ts +14 -0
  167. package/build/types/utilities/usePackage.d.ts +2 -0
  168. package/build/types/utilities/validateProjectName.d.ts +4 -0
  169. package/build/types.js +39 -0
  170. package/build/utilities/bumpVersion.js +21 -0
  171. package/build/utilities/clearNavigationPackages.js +11 -0
  172. package/build/utilities/clearStylingPackages.js +11 -0
  173. package/build/utilities/configAnalytics.js +70 -0
  174. package/build/utilities/configStorage.js +50 -0
  175. package/build/utilities/configureProjectFiles.js +380 -0
  176. package/build/utilities/copyBaseAssets.js +21 -0
  177. package/build/utilities/generateNWUI.js +54 -0
  178. package/build/utilities/generateProjectFiles.js +106 -0
  179. package/build/utilities/getPackageManager.js +103 -0
  180. package/build/utilities/index.js +27 -0
  181. package/build/utilities/printOutput.js +251 -0
  182. package/build/utilities/publishToGitHub.js +173 -0
  183. package/build/utilities/renderTitle.js +55 -0
  184. package/build/utilities/runCLI.js +437 -0
  185. package/build/utilities/runEasConfigure.js +83 -0
  186. package/build/utilities/runIgnite.js +26 -0
  187. package/build/utilities/showHelp.js +85 -0
  188. package/build/utilities/systemCommand.js +40 -0
  189. package/build/utilities/usePackage.js +8 -0
  190. package/build/utilities/validateProjectName.js +42 -0
  191. package/package.json +77 -0
@@ -0,0 +1,21 @@
1
+ import { forwardRef } from 'react';
2
+ import { Text, TouchableOpacity, TouchableOpacityProps, View } from 'react-native';
3
+
4
+ interface ButtonProps extends TouchableOpacityProps {
5
+ title: string;
6
+ }
7
+
8
+ export const Button = forwardRef<View, ButtonProps>(({ title, ...touchableProps }, ref) => {
9
+ return (
10
+ <TouchableOpacity ref={ref} {...touchableProps} className={`${styles.button} ${touchableProps.className}`}>
11
+ <Text className={styles.buttonText}>{title}</Text>
12
+ </TouchableOpacity>
13
+ );
14
+ });
15
+
16
+ Button.displayName = 'Button';
17
+
18
+ const styles = {
19
+ button: 'items-center bg-indigo-500 rounded-[28px] shadow-md p-4',
20
+ buttonText: 'text-white text-lg font-semibold text-center',
21
+ };
@@ -0,0 +1,13 @@
1
+ import { View } from 'react-native';
2
+
3
+ interface ContainerProps {
4
+ children: React.ReactNode;
5
+ }
6
+
7
+ export const Container: React.FC<ContainerProps> = ({ children }) => {
8
+ return <View className={styles.container}>{children}</View>;
9
+ };
10
+
11
+ const styles = {
12
+ container: "flex flex-1 p-safe bg-white",
13
+ };
@@ -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
+ interface EditScreenInfoProps {
8
+ path: string;
9
+ }
10
+
11
+ export const EditScreenInfo: React.FC<EditScreenInfoProps> = ({ path }) => {
12
+ <% if (props.internalizationPackage?.name === "i18next") { %>
13
+ const { t } = useTranslation();
14
+ const title = t('getStarted');
15
+ const description = t('changeCode')
16
+ <% } else { %>
17
+ const title = "Open up the code for this screen:"
18
+ const description = "Change any of the text, save the file, and your app will automatically update."
19
+ <% } %>
20
+ return (
21
+ <View>
22
+ <View className={styles.getStartedContainer}>
23
+ <Text className={styles.getStartedText}>{title}</Text>
24
+ <View className={`${styles.codeHighlightContainer} ${styles.homeScreenFilename}`}>
25
+ <Text>{path}</Text>
26
+ </View>
27
+ <Text className={styles.getStartedText}>
28
+ {description}
29
+ </Text>
30
+ </View>
31
+ </View>
32
+ );
33
+ };
34
+
35
+ const styles = {
36
+ codeHighlightContainer: `rounded-md px-1`,
37
+ getStartedContainer: `items-center mx-12`,
38
+ getStartedText: `text-lg leading-6 text-center`,
39
+ homeScreenFilename: `my-2`,
40
+ };
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import { Text, View } from 'react-native';
3
+
4
+ import { EditScreenInfo } from './EditScreenInfo';
5
+
6
+ interface ScreenContentProps {
7
+ title: string;
8
+ path: string;
9
+ children?: React.ReactNode;
10
+ }
11
+
12
+ export const ScreenContent: React.FC<ScreenContentProps> = ({ title, path, children }) => {
13
+ return (
14
+ <View className={styles.container}>
15
+ <Text className={styles.title}>{title}</Text>
16
+ <View className={styles.separator} />
17
+ <EditScreenInfo path={path} />
18
+ {children}
19
+ </View>
20
+ );
21
+ };
22
+
23
+ const styles = {
24
+ container: `items-center flex-1 justify-center bg-white`,
25
+ separator: `h-[1px] my-7 w-4/5 bg-gray-200`,
26
+ title: `text-xl font-bold`,
27
+ };
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,7 @@
1
+ const { getDefaultConfig } = require('expo/metro-config');
2
+ const { withNativeWind } = require('nativewind/metro');
3
+
4
+ // eslint-disable-next-line no-undef
5
+ const config = getDefaultConfig(__dirname);
6
+
7
+ module.exports = withNativeWind(config, { input: './global.css' });
@@ -0,0 +1,2 @@
1
+ // @ts-ignore
2
+ /// <reference types="nativewind/types" />
@@ -0,0 +1,15 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ <% if (props.navigationPackage?.name === "react-navigation") { %>
4
+ content: ["./App.{js,ts,tsx}", "./components/**/*.{js,ts,tsx}", "./screens/**/*.{js,ts,tsx}", "./navigation/**/*.{js,ts,tsx}"],
5
+ <% } else if (props.navigationPackage?.name === "expo-router") { %>
6
+ content: ["./app/**/*.{js,ts,tsx}", "./components/**/*.{js,ts,tsx}"],
7
+ <% } else { %>
8
+ content: ["./App.{js,ts,tsx}", "./components/**/*.{js,ts,tsx}"],
9
+ <% } %>
10
+ presets: [require("nativewind/preset")],
11
+ theme: {
12
+ extend: {},
13
+ },
14
+ plugins: [],
15
+ }
@@ -0,0 +1,14 @@
1
+ import { StyleSheet, SafeAreaView } from 'react-native';
2
+
3
+ export const Container = ({ children }: { children: React.ReactNode }) => {
4
+ return <SafeAreaView style={styles.container}>{children}</SafeAreaView>;
5
+ };
6
+
7
+ const styles = StyleSheet.create({
8
+ container: {
9
+ flex: 1,
10
+ padding: 24,
11
+ backgroundColor: 'white',
12
+ },
13
+ });
14
+
@@ -0,0 +1,45 @@
1
+ import { StyleSheet, View } from 'react-native';
2
+
3
+ import { Text } from '@/components/nativewindui/Text';
4
+
5
+ <% if (props.internalizationPackage?.name === "i18next") { %>
6
+ import { useTranslation } from 'react-i18next';
7
+ <% } %>
8
+
9
+ export default function EditScreenInfo({ path }: { path: string }) {
10
+ <% if (props.internalizationPackage?.name === "i18next") { %>
11
+ const { t } = useTranslation();
12
+ const title = t('getStarted');
13
+ const description = t('changeCode')
14
+ <% } else { %>
15
+ const title = "Open up the code for this screen:"
16
+ const description = "Change any of the text, save the file, and your app will automatically update."
17
+ <% } %>
18
+ return (
19
+ <View style={styles.getStartedContainer}>
20
+ <Text variant="heading" className="text-center">
21
+ {title}
22
+ </Text>
23
+ <View style={[styles.codeHighlightContainer, styles.homeScreenFilename]}>
24
+ <Text>{path}</Text>
25
+ </View>
26
+ <Text variant="body" className="text-center">
27
+ {description}
28
+ </Text>
29
+ </View>
30
+ );
31
+ }
32
+
33
+ const styles = StyleSheet.create({
34
+ codeHighlightContainer: {
35
+ borderRadius: 3,
36
+ paddingHorizontal: 4,
37
+ },
38
+ getStartedContainer: {
39
+ alignItems: 'center',
40
+ marginHorizontal: 50,
41
+ },
42
+ homeScreenFilename: {
43
+ marginVertical: 7,
44
+ },
45
+ });
@@ -0,0 +1,31 @@
1
+ import { forwardRef } from 'react';
2
+ import FontAwesome from '@expo/vector-icons/FontAwesome';
3
+ import { Pressable, StyleSheet } from 'react-native';
4
+
5
+ export const HeaderButton = forwardRef<typeof Pressable, { onPress?: () => void; }>(({ onPress }, ref) => {
6
+ return (
7
+ <Pressable onPress={onPress}>
8
+ {({ pressed }) => (
9
+ <FontAwesome
10
+ name="info-circle"
11
+ size={25}
12
+ color="gray"
13
+ style={[
14
+ styles.headerRight,
15
+ {
16
+ opacity: pressed ? 0.5 : 1,
17
+ },
18
+ ]}
19
+ />
20
+ )}
21
+ </Pressable>
22
+ );
23
+ });
24
+
25
+ HeaderButton.displayName = 'HeaderButton';
26
+
27
+ export const styles = StyleSheet.create({
28
+ headerRight: {
29
+ marginRight: 15,
30
+ },
31
+ });
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+
4
+ import { Text } from '@/components/nativewindui/Text';
5
+
6
+ import EditScreenInfo from './EditScreenInfo';
7
+
8
+ type ScreenContentProps = {
9
+ title: string;
10
+ path: string;
11
+ children?: React.ReactNode;
12
+ };
13
+
14
+ export const ScreenContent = ({ title, path, children }: ScreenContentProps) => {
15
+ return (
16
+ <View style={styles.container}>
17
+ <Text variant="title1" className="text-center">
18
+ {title}
19
+ </Text>
20
+ <View style={styles.separator} />
21
+ <EditScreenInfo path={path} />
22
+ {children}
23
+ </View>
24
+ );
25
+ };
26
+
27
+ const styles = StyleSheet.create({
28
+ container: {
29
+ alignItems: 'center',
30
+ backgroundColor: 'white',
31
+ flex: 1,
32
+ justifyContent: 'center',
33
+ },
34
+ separator: {
35
+ backgroundColor: '#d1d5db',
36
+ height: 1,
37
+ marginVertical: 30,
38
+ width: '80%',
39
+ },
40
+ });
@@ -0,0 +1,15 @@
1
+ import FontAwesome from '@expo/vector-icons/FontAwesome';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ export const TabBarIcon = (props: {
5
+ name: React.ComponentProps<typeof FontAwesome>['name'];
6
+ color: string;
7
+ }) => {
8
+ return <FontAwesome size={28} style={styles.tabBarIcon} {...props} />;
9
+ };
10
+
11
+ export const styles = StyleSheet.create({
12
+ tabBarIcon: {
13
+ marginBottom: -3,
14
+ },
15
+ });
@@ -0,0 +1,52 @@
1
+ import { SymbolView } from 'expo-symbols';
2
+
3
+ import type { IconProps } from './types';
4
+
5
+ import { useColorScheme } from '@/lib/useColorScheme';
6
+
7
+ function Icon({
8
+ materialCommunityIcon: _materialCommunityIcon,
9
+ materialIcon: _materialIcon,
10
+ sfSymbol,
11
+ name,
12
+ color,
13
+ size = 24,
14
+ ...props
15
+ }: IconProps) {
16
+ const { colors } = useColorScheme();
17
+ return (
18
+ <SymbolView
19
+ name={name ?? 'questionmark'}
20
+ tintColor={rgbaToHex(color ?? colors.foreground)}
21
+ size={size}
22
+ resizeMode="scaleAspectFit"
23
+ {...props}
24
+ {...sfSymbol}
25
+ />
26
+ );
27
+ }
28
+
29
+ export { Icon };
30
+
31
+ // TODO: seems like the need to convert rgba to hex color is a bug in expo-symbols, accordion to the docs, it should accept a hex color, but it doesn't.
32
+
33
+ function rgbaToHex(color: string): string {
34
+ if (!color) return 'black';
35
+ const rgbaRegex =
36
+ /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(\d*\.?\d+))?\s*\)$/i;
37
+ const match = color.match(rgbaRegex);
38
+
39
+ if (!match) {
40
+ return color;
41
+ }
42
+
43
+ const [, rStr, gStr, bStr, aStr] = match;
44
+ const r = Math.min(255, parseInt(rStr));
45
+ const g = Math.min(255, parseInt(gStr));
46
+ const b = Math.min(255, parseInt(bStr));
47
+ const a = aStr !== undefined ? Math.round(parseFloat(aStr) * 255) : 255;
48
+
49
+ const toHex = (n: number) => n.toString(16).padStart(2, '0');
50
+
51
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}${a < 255 ? toHex(a) : ''}`;
52
+ }
@@ -0,0 +1,58 @@
1
+ import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
2
+ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
3
+ import {
4
+ SF_SYMBOLS_TO_MATERIAL_COMMUNITY_ICONS,
5
+ SF_SYMBOLS_TO_MATERIAL_ICONS,
6
+ } from 'rn-icon-mapper';
7
+
8
+ import type { IconProps } from './types';
9
+
10
+ import { useColorScheme } from '@/lib/useColorScheme';
11
+
12
+ function Icon({
13
+ name,
14
+ materialCommunityIcon,
15
+ materialIcon,
16
+ sfSymbol: _sfSymbol,
17
+ size = 24,
18
+ ...props
19
+ }: IconProps) {
20
+ const { colors } = useColorScheme();
21
+ const defaultColor = colors.foreground;
22
+
23
+ if (materialCommunityIcon) {
24
+ return (
25
+ <MaterialCommunityIcons
26
+ size={size}
27
+ color={defaultColor}
28
+ {...props}
29
+ {...materialCommunityIcon}
30
+ />
31
+ );
32
+ }
33
+ if (materialIcon) {
34
+ return <MaterialIcons size={size} color={defaultColor} {...props} {...materialIcon} />;
35
+ }
36
+ const materialCommunityIconName =
37
+ SF_SYMBOLS_TO_MATERIAL_COMMUNITY_ICONS[
38
+ name as keyof typeof SF_SYMBOLS_TO_MATERIAL_COMMUNITY_ICONS
39
+ ];
40
+ if (materialCommunityIconName) {
41
+ return (
42
+ <MaterialCommunityIcons
43
+ name={materialCommunityIconName}
44
+ size={size}
45
+ color={defaultColor}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+ const materialIconName =
51
+ SF_SYMBOLS_TO_MATERIAL_ICONS[name as keyof typeof SF_SYMBOLS_TO_MATERIAL_ICONS];
52
+ if (materialIconName) {
53
+ return <MaterialIcons name={materialIconName} size={size} color={defaultColor} {...props} />;
54
+ }
55
+ return <MaterialCommunityIcons name="help" size={size} color={defaultColor} {...props} />;
56
+ }
57
+
58
+ export { Icon };
@@ -0,0 +1,16 @@
1
+ import { cssInterop } from 'nativewind';
2
+
3
+ import { Icon } from './Icon';
4
+
5
+ cssInterop(Icon, {
6
+ className: {
7
+ target: 'style',
8
+ nativeStyleToProp: {
9
+ color: 'color',
10
+ height: 'size',
11
+ width: 'size',
12
+ },
13
+ },
14
+ });
15
+
16
+ export { Icon };
@@ -0,0 +1,18 @@
1
+ import type MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
2
+ import type MaterialIcons from '@expo/vector-icons/MaterialIcons';
3
+ import type { SymbolViewProps } from 'expo-symbols';
4
+ import type { IconMapper } from 'rn-icon-mapper';
5
+
6
+ type MaterialCommunityIconsProps = React.ComponentProps<typeof MaterialCommunityIcons>;
7
+ type MaterialIconsProps = React.ComponentProps<typeof MaterialIcons>;
8
+
9
+ type Style = SymbolViewProps['style'] &
10
+ MaterialIconsProps['style'] &
11
+ MaterialCommunityIconsProps['style'];
12
+
13
+ type IconProps = IconMapper<SymbolViewProps, MaterialIconsProps, MaterialCommunityIconsProps> & {
14
+ style?: Style;
15
+ className?: string;
16
+ };
17
+
18
+ export type { IconProps };
@@ -0,0 +1,33 @@
1
+ import { Pressable, View } from 'react-native';
2
+ import Animated, { LayoutAnimationConfig, ZoomInRotate } from 'react-native-reanimated';
3
+
4
+ import { Icon } from '@/components/nativewindui/Icon';
5
+ import { cn } from '@/lib/cn';
6
+ import { useColorScheme } from '@/lib/useColorScheme';
7
+ import { COLORS } from '@/theme/colors';
8
+
9
+ export function ThemeToggle() {
10
+ const { colorScheme, toggleColorScheme } = useColorScheme();
11
+ return (
12
+ <LayoutAnimationConfig skipEntering>
13
+ <Animated.View
14
+ className="items-center justify-center"
15
+ key={`toggle-${colorScheme}`}
16
+ entering={ZoomInRotate}>
17
+ <Pressable onPress={toggleColorScheme} className="opacity-80">
18
+ {colorScheme === 'dark'
19
+ ? ({ pressed }) => (
20
+ <View className={cn('px-0.5', pressed && 'opacity-50')}>
21
+ <Icon name="moon.stars" color={COLORS.white} />
22
+ </View>
23
+ )
24
+ : ({ pressed }) => (
25
+ <View className={cn('px-0.5', pressed && 'opacity-50')}>
26
+ <Icon name="sun.min" color={COLORS.black} />
27
+ </View>
28
+ )}
29
+ </Pressable>
30
+ </Animated.View>
31
+ </LayoutAnimationConfig>
32
+ );
33
+ }
@@ -0,0 +1,28 @@
1
+ import { Tabs } from 'expo-router';
2
+
3
+ import { TabBarIcon } from '@/components/TabBarIcon';
4
+
5
+ export default function TabLayout() {
6
+ return (
7
+ <Tabs
8
+ screenOptions={{
9
+ headerShown: false,
10
+ tabBarActiveTintColor: 'black',
11
+ }}>
12
+ <Tabs.Screen
13
+ name="index"
14
+ options={{
15
+ title: 'Tab One',
16
+ tabBarIcon: ({ color }) => <TabBarIcon name="code" color={color} />,
17
+ }}
18
+ />
19
+ <Tabs.Screen
20
+ name="two"
21
+ options={{
22
+ title: 'Tab Two',
23
+ tabBarIcon: ({ color }) => <TabBarIcon name="code" color={color} />,
24
+ }}
25
+ />
26
+ </Tabs>
27
+ );
28
+ }
@@ -0,0 +1,15 @@
1
+ import { Stack } from 'expo-router';
2
+
3
+ import { Container } from '@/components/Container';
4
+ import { ScreenContent } from '@/components/ScreenContent';
5
+
6
+ export default function Home() {
7
+ return (
8
+ <>
9
+ <Stack.Screen options={{ title: 'Tab One' }} />
10
+ <Container>
11
+ <ScreenContent path="app/(drawer)/(tabs)/index.tsx" title="Tab One" />
12
+ </Container>
13
+ </>
14
+ );
15
+ }
@@ -0,0 +1,15 @@
1
+ import { Stack } from 'expo-router';
2
+
3
+ import { Container } from '@/components/Container';
4
+ import { ScreenContent } from '@/components/ScreenContent';
5
+
6
+ export default function Home() {
7
+ return (
8
+ <>
9
+ <Stack.Screen options={{ title: 'Tab Two' }} />
10
+ <Container>
11
+ <ScreenContent path="app/(drawer)/(tabs)/two.tsx" title="Tab Two" />
12
+ </Container>
13
+ </>
14
+ );
15
+ }
@@ -0,0 +1,35 @@
1
+ import { Ionicons, MaterialIcons } from '@expo/vector-icons';
2
+ import { Link } from 'expo-router';
3
+ import { Drawer } from 'expo-router/drawer';
4
+
5
+ import { HeaderButton } from '../../components/HeaderButton';
6
+
7
+ const DrawerLayout = () => (
8
+ <Drawer>
9
+ <Drawer.Screen
10
+ name="index"
11
+ options={{
12
+ headerTitle: 'Home',
13
+ drawerLabel: 'Home',
14
+ drawerIcon: ({ size, color }) => <Ionicons name="home-outline" size={size} color={color} />,
15
+ }}
16
+ />
17
+ <Drawer.Screen
18
+ name="(tabs)"
19
+ options={{
20
+ headerTitle: 'Tabs',
21
+ drawerLabel: 'Tabs',
22
+ drawerIcon: ({ size, color }) => (
23
+ <MaterialIcons name="border-bottom" size={size} color={color} />
24
+ ),
25
+ headerRight: () => (
26
+ <Link href="/modal" asChild>
27
+ <HeaderButton />
28
+ </Link>
29
+ ),
30
+ }}
31
+ />
32
+ </Drawer>
33
+ );
34
+
35
+ export default DrawerLayout;