create-expo-stack 2.6.5 → 2.7.0-next.327ab2a

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 (33) hide show
  1. package/README.md +23 -9
  2. package/build/templates/base/App.tsx.ejs +3 -0
  3. package/build/templates/base/babel.config.js.ejs +1 -1
  4. package/build/templates/base/package.json.ejs +13 -3
  5. package/build/templates/base/prettier.config.js.ejs +1 -1
  6. package/build/templates/base/tsconfig.json.ejs +10 -6
  7. package/build/templates/packages/expo-router/drawer/app/_layout.tsx.ejs +4 -1
  8. package/build/templates/packages/expo-router/stack/app/_layout.tsx.ejs +4 -1
  9. package/build/templates/packages/expo-router/tabs/app/_layout.tsx.ejs +4 -1
  10. package/build/templates/packages/nativewindui/app/+not-found.tsx.ejs +18 -0
  11. package/build/templates/packages/nativewindui/app/_layout.tsx.ejs +85 -0
  12. package/build/templates/packages/nativewindui/app/index.tsx.ejs +99 -0
  13. package/build/templates/packages/nativewindui/app/modal.tsx.ejs +32 -0
  14. package/build/templates/packages/nativewindui/components/ThemeToggle.tsx.ejs +39 -0
  15. package/build/templates/packages/nativewindui/components/nativewind-ui/Text.tsx.ejs +55 -0
  16. package/build/templates/packages/nativewindui/expo-env.d.ts.ejs +3 -0
  17. package/build/templates/packages/nativewindui/global.css.ejs +91 -0
  18. package/build/templates/packages/nativewindui/lib/cn.ts.ejs +6 -0
  19. package/build/templates/packages/nativewindui/lib/useColorScheme.tsx.ejs +14 -0
  20. package/build/templates/packages/nativewindui/lib/useHeaderSearchBar.tsx.ejs +31 -0
  21. package/build/templates/packages/nativewindui/metro.config.js.ejs +10 -0
  22. package/build/templates/packages/nativewindui/nativewind-env.d.ts.ejs +1 -0
  23. package/build/templates/packages/nativewindui/tailwind.config.js.ejs +66 -0
  24. package/build/templates/packages/nativewindui/theme/colors.ts.ejs +71 -0
  25. package/build/templates/packages/nativewindui/theme/index.ts.ejs +29 -0
  26. package/build/templates/packages/react-navigation/App.tsx.ejs +4 -1
  27. package/build/types/types.d.ts +2 -2
  28. package/build/types.js +2 -1
  29. package/build/utilities/configureProjectFiles.js +238 -200
  30. package/build/utilities/generateProjectFiles.js +18 -13
  31. package/build/utilities/printOutput.js +5 -5
  32. package/build/utilities/runCLI.js +45 -22
  33. package/package.json +67 -67
package/README.md CHANGED
@@ -164,21 +164,28 @@ Thanks go to these wonderful people:
164
164
  <sub><b>Simon Grimm</b></sub>
165
165
  </a>
166
166
  </td>
167
+ <td align="center">
168
+ <a href="https://github.com/mrzachnugent">
169
+ <img src="https://avatars.githubusercontent.com/u/63797719?v=4" width="100;" alt="mrzachnugent"/>
170
+ <br />
171
+ <sub><b>Zach Nugent</b></sub>
172
+ </a>
173
+ </td>
167
174
  <td align="center">
168
175
  <a href="https://github.com/dannyhw">
169
176
  <img src="https://avatars.githubusercontent.com/u/3481514?v=4" width="100;" alt="dannyhw"/>
170
177
  <br />
171
178
  <sub><b>Daniel Williams</b></sub>
172
179
  </a>
173
- </td>
180
+ </td></tr>
181
+ <tr>
174
182
  <td align="center">
175
183
  <a href="https://github.com/todevmilen">
176
184
  <img src="https://avatars.githubusercontent.com/u/78319110?v=4" width="100;" alt="todevmilen"/>
177
185
  <br />
178
186
  <sub><b>Milen Todev</b></sub>
179
187
  </a>
180
- </td></tr>
181
- <tr>
188
+ </td>
182
189
  <td align="center">
183
190
  <a href="https://github.com/alitnk">
184
191
  <img src="https://avatars.githubusercontent.com/u/35243344?v=4" width="100;" alt="alitnk"/>
@@ -213,15 +220,15 @@ Thanks go to these wonderful people:
213
220
  <br />
214
221
  <sub><b>Andrew Levy</b></sub>
215
222
  </a>
216
- </td>
223
+ </td></tr>
224
+ <tr>
217
225
  <td align="center">
218
226
  <a href="https://github.com/gialencar">
219
227
  <img src="https://avatars.githubusercontent.com/u/11895696?v=4" width="100;" alt="gialencar"/>
220
228
  <br />
221
229
  <sub><b>Gilson Alencar</b></sub>
222
230
  </a>
223
- </td></tr>
224
- <tr>
231
+ </td>
225
232
  <td align="center">
226
233
  <a href="https://github.com/mwarger">
227
234
  <img src="https://avatars.githubusercontent.com/u/686823?v=4" width="100;" alt="mwarger"/>
@@ -256,15 +263,15 @@ Thanks go to these wonderful people:
256
263
  <br />
257
264
  <sub><b>Joar Karlsson</b></sub>
258
265
  </a>
259
- </td>
266
+ </td></tr>
267
+ <tr>
260
268
  <td align="center">
261
269
  <a href="https://github.com/Joehoel">
262
270
  <img src="https://avatars.githubusercontent.com/u/31251240?v=4" width="100;" alt="Joehoel"/>
263
271
  <br />
264
272
  <sub><b>Joël Kuijper</b></sub>
265
273
  </a>
266
- </td></tr>
267
- <tr>
274
+ </td>
268
275
  <td align="center">
269
276
  <a href="https://github.com/asapMaki">
270
277
  <img src="https://avatars.githubusercontent.com/u/30200380?v=4" width="100;" alt="asapMaki"/>
@@ -279,6 +286,13 @@ Thanks go to these wonderful people:
279
286
  <sub><b>Sean Boult</b></sub>
280
287
  </a>
281
288
  </td>
289
+ <td align="center">
290
+ <a href="https://github.com/YounessHassoune">
291
+ <img src="https://avatars.githubusercontent.com/u/36106440?v=4" width="100;" alt="YounessHassoune"/>
292
+ <br />
293
+ <sub><b>YOUNESS HASSOUNE</b></sub>
294
+ </a>
295
+ </td>
282
296
  <td align="center">
283
297
  <a href="https://github.com/bautistaaa">
284
298
  <img src="https://avatars.githubusercontent.com/u/3660667?v=4" width="100;" alt="bautistaaa"/>
@@ -8,6 +8,9 @@ import { StatusBar } from 'expo-status-bar';
8
8
 
9
9
  <% if (props.stylingPackage?.name === "nativewind") { %>
10
10
  import './global.css';
11
+ <% } else if (props.stylingPackage?.name === "nativewinui") { %>
12
+ import './global.css';
13
+ import 'expo-dev-client';
11
14
  <% } else if (props.stylingPackage?.name === "restyle") { %>
12
15
  import { ThemeProvider } from '@shopify/restyle';
13
16
  import { theme } from 'theme';
@@ -17,7 +17,7 @@ module.exports = function(api) {
17
17
  <% } %>
18
18
 
19
19
  return {
20
- <% if (props.stylingPackage?.name === "nativewind") { %>
20
+ <% if (props.stylingPackage?.name === "nativewind" || props.stylingPackage?.name === "nativewindui") { %>
21
21
  presets: [
22
22
  ['babel-preset-expo', { jsxImportSource: 'nativewind' }],
23
23
  'nativewind/babel',
@@ -16,9 +16,19 @@
16
16
  "web": "expo start --web"
17
17
  },
18
18
  "dependencies": {
19
- <% if (props.stylingPackage?.name === "nativewind") { %>
19
+ <% if (props.stylingPackage?.name === "nativewind" || props.stylingPackage?.name === "nativewindui") { %>
20
20
  "nativewind": "^4.0.1",
21
21
  <% } %>
22
+ <% if (props.stylingPackage?.name === "nativewindui") { %>
23
+ "@roninoss/icons": "^0.0.3",
24
+ "@shopify/flash-list": "1.6.3",
25
+ "class-variance-authority": "^0.7.0",
26
+ "clsx": "^2.1.0",
27
+ "expo-dev-client": "~3.3.8",
28
+ "tailwind-merge": "^2.2.1",
29
+ "react-native-uitextview": "^1.1.4",
30
+ "react-native-pager-view": "6.2.3",
31
+ <% } %>
22
32
 
23
33
  <% if (props.stylingPackage?.name === "restyle") { %>
24
34
  "@shopify/restyle": "^2.4.2",
@@ -112,7 +122,7 @@
112
122
  "eslint": "^8.50.0",
113
123
  "eslint-config-universe": "^12.0.0",
114
124
  "prettier": "^3.2.5",
115
- <% if (props.stylingPackage?.name === "nativewind") { %>
125
+ <% if (props.stylingPackage?.name === "nativewind" || props.stylingPackage?.name === "nativewindui") { %>
116
126
  "tailwindcss": "^3.4.0",
117
127
  "prettier-plugin-tailwindcss": "^0.5.11",
118
128
  <% } %>
@@ -124,7 +134,7 @@
124
134
  "eslintConfig": {
125
135
  "extends": "universe/native"
126
136
  },
127
- <% if (props.navigationPackage?.name === 'expo-router') { %>
137
+ <% if (props.navigationPackage?.name === "expo-router") { %>
128
138
  "resolutions": {
129
139
  "expo-modules-core": "~1.11.0"
130
140
  },
@@ -4,7 +4,7 @@ module.exports = {
4
4
  singleQuote: true,
5
5
  bracketSameLine: true,
6
6
  trailingComma: 'es5',
7
- <% if (props.stylingPackage?.name === "nativewind") { %>
7
+ <% if (props.stylingPackage?.name === "nativewind" || props.stylingPackage?.name === "nativewindui") { %>
8
8
  plugins: [require.resolve("prettier-plugin-tailwindcss")],
9
9
  tailwindAttributes: ["className"],
10
10
  <% } %>
@@ -6,12 +6,16 @@
6
6
  ,
7
7
  "baseUrl": ".",
8
8
  "paths": {
9
- <% if (props.navigationPackage?.name === "expo-router" && props.flags.importAlias === true) { %>
10
- "~/*": ["*"]
11
- <% } else if (props.flags.importAlias === true) { %>
12
- "~/*": ["src/*"]
13
- <% } else { %>
14
- "<%= props.flags.importAlias %>": ["src/*"]
9
+ <% if (props.stylingPackage?.name === 'nativewindui') { %>
10
+ "~/*": [ "./*" ]
11
+ <% } else { %>
12
+ <% if (props.navigationPackage?.name === "expo-router" && props.flags.importAlias === true) { %>
13
+ "~/*": ["*"]
14
+ <% } else if (props.flags.importAlias === true) { %>
15
+ "~/*": ["src/*"]
16
+ <% } else { %>
17
+ "<%= props.flags.importAlias %>": ["src/*"]
18
+ <% } %>
15
19
  <% } %>
16
20
  }
17
21
  <% } %>
@@ -1,5 +1,8 @@
1
1
  <% if (props.stylingPackage?.name === "nativewind") { %>
2
- import '../global.css';
2
+ import './global.css';
3
+ <% } else if (props.stylingPackage?.name === "nativewinui") { %>
4
+ import './global.css';
5
+ import 'expo-dev-client';
3
6
  <% } %>
4
7
  <% if (props.stylingPackage?.name === "unistyles") { %>
5
8
  import '../unistyles';
@@ -1,5 +1,8 @@
1
1
  <% if (props.stylingPackage?.name === "nativewind") { %>
2
- import '../global.css';
2
+ import './global.css';
3
+ <% } else if (props.stylingPackage?.name === "nativewinui") { %>
4
+ import './global.css';
5
+ import 'expo-dev-client';
3
6
  <% } %>
4
7
  <% if (props.stylingPackage?.name === "unistyles") { %>
5
8
  import '../unistyles';
@@ -1,5 +1,8 @@
1
1
  <% if (props.stylingPackage?.name === "nativewind") { %>
2
- import '../global.css';
2
+ import './global.css';
3
+ <% } else if (props.stylingPackage?.name === "nativewinui") { %>
4
+ import './global.css';
5
+ import 'expo-dev-client';
3
6
  <% } %>
4
7
  <% if (props.stylingPackage?.name === "unistyles") { %>
5
8
  import '../unistyles';
@@ -0,0 +1,18 @@
1
+ import { Link, Stack } from 'expo-router';
2
+ import { View } from 'react-native';
3
+ import { Text } from '~/components/nativewind-ui/Text';
4
+
5
+ export default function NotFoundScreen() {
6
+ return (
7
+ <>
8
+ <Stack.Screen options={{ title: 'Oops!' }} />
9
+ <View className='flex-1 items-center justify-center p-5 bg-background'>
10
+ <Text variant='largeTitle'>This screen doesn't exist.</Text>
11
+
12
+ <Link href='/' className='m-4 py-4'>
13
+ <Text>Go to home screen!</Text>
14
+ </Link>
15
+ </View>
16
+ </>
17
+ );
18
+ }
@@ -0,0 +1,85 @@
1
+ import '~/global.css';
2
+ import 'expo-dev-client';
3
+ import { ThemeProvider as NavThemeProvider } from '@react-navigation/native';
4
+ import { Icon } from '@roninoss/icons';
5
+ import { Link, Stack } from 'expo-router';
6
+ import { StatusBar } from 'expo-status-bar';
7
+ import { Pressable, View } from 'react-native';
8
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
9
+
10
+ import { ThemeToggle } from '~/components/ThemeToggle';
11
+ import { cn } from '~/lib/cn';
12
+ import { useColorScheme } from '~/lib/useColorScheme';
13
+ import { NAV_THEME } from '~/theme';
14
+
15
+ export {
16
+ // Catch any errors thrown by the Layout component.
17
+ ErrorBoundary,
18
+ } from 'expo-router';
19
+
20
+ export default function RootLayout() {
21
+ const { colorScheme, isDarkColorScheme } = useColorScheme();
22
+
23
+ return (
24
+ <>
25
+ <StatusBar
26
+ key={`root-status-bar-${isDarkColorScheme ? 'light' : 'dark'}`}
27
+ style={isDarkColorScheme ? 'light' : 'dark'}
28
+ />
29
+ <GestureHandlerRootView style={{ flex: 1 }}>
30
+ <NavThemeProvider value={NAV_THEME[colorScheme]}>
31
+ <Stack screenOptions={SCREEN_OPTIONS}>
32
+ <Stack.Screen name="index" options={INDEX_OPTIONS} />
33
+ <Stack.Screen name="top-tabs" options={TOP_TABS_OPTIONS} />
34
+ <Stack.Screen name="drawer" options={DEFAULT_OPTIONS} />
35
+ <Stack.Screen name="bottom-tabs" options={DEFAULT_OPTIONS} />
36
+ <Stack.Screen name="modal" options={MODAL_OPTIONS} />
37
+ </Stack>
38
+ </NavThemeProvider>
39
+ </GestureHandlerRootView>
40
+ </>
41
+ );
42
+ }
43
+
44
+ const SCREEN_OPTIONS = {
45
+ animation: 'ios', // for android
46
+ } as const;
47
+
48
+ const INDEX_OPTIONS = {
49
+ headerLargeTitle: true,
50
+ title: 'NativeWindUI',
51
+ headerRight: () => <SettingsIcon />,
52
+ } as const;
53
+
54
+ function SettingsIcon() {
55
+ const { colors } = useColorScheme();
56
+ return (
57
+ <Link href="/modal" asChild>
58
+ <Pressable className="opacity-80">
59
+ {({ pressed }) => (
60
+ <View className={cn(pressed ? 'opacity-50' : 'opacity-90')}>
61
+ <Icon name="cog-outline" color={colors.foreground} />
62
+ </View>
63
+ )}
64
+ </Pressable>
65
+ </Link>
66
+ );
67
+ }
68
+
69
+ const TOP_TABS_OPTIONS = {
70
+ title: 'Top Tabs',
71
+ headerShadowVisible: false,
72
+ headerBackTitle: 'Back',
73
+ headerRight: () => <ThemeToggle />,
74
+ } as const;
75
+
76
+ const MODAL_OPTIONS = {
77
+ presentation: 'modal',
78
+ animation: 'fade_from_bottom', // for android
79
+ title: 'Settings',
80
+ headerRight: () => <ThemeToggle />,
81
+ } as const;
82
+
83
+ const DEFAULT_OPTIONS = {
84
+ headerShown: false,
85
+ };
@@ -0,0 +1,99 @@
1
+ import { useHeaderHeight } from '@react-navigation/elements';
2
+ import { FlashList } from '@shopify/flash-list';
3
+ import { cssInterop } from 'nativewind';
4
+ import * as React from 'react';
5
+ import { Button as RNButton, ButtonProps, Linking, View, Platform } from 'react-native';
6
+
7
+ import { Text } from '~/components/nativewind-ui/Text';
8
+ import { useColorScheme } from '~/lib/useColorScheme';
9
+ import { useHeaderSearchBar } from '~/lib/useHeaderSearchBar';
10
+
11
+ cssInterop(FlashList, {
12
+ className: 'style',
13
+ contentContainerClassName: 'contentContainerStyle',
14
+ });
15
+
16
+ function DefaultButton({ color, ...props }: ButtonProps) {
17
+ const { colors } = useColorScheme();
18
+ return <RNButton color={color ?? colors.primary} {...props} />;
19
+ }
20
+
21
+ export default function Screen() {
22
+ const searchValue = useHeaderSearchBar();
23
+
24
+ const data = searchValue
25
+ ? COMPONENTS.filter((c) => c.name.toLowerCase().includes(searchValue.toLowerCase()))
26
+ : COMPONENTS;
27
+
28
+ return (
29
+ <FlashList
30
+ contentInsetAdjustmentBehavior="automatic"
31
+ keyboardShouldPersistTaps="handled"
32
+ data={data}
33
+ estimatedItemSize={200}
34
+ contentContainerClassName="py-4"
35
+ centerContent={data.length === 0}
36
+ extraData={searchValue}
37
+ removeClippedSubviews={false} // used for selecting text on android
38
+ keyExtractor={keyExtractor}
39
+ ItemSeparatorComponent={renderItemSeparator}
40
+ renderItem={renderItem}
41
+ ListEmptyComponent={ListEmptyComponent}
42
+ />
43
+ );
44
+ }
45
+
46
+ const SEARCH_BAR_HEIGHT = 52;
47
+
48
+ function ListEmptyComponent() {
49
+ const headerHeight = useHeaderHeight();
50
+ return (
51
+ <>
52
+ {Platform.OS === 'ios' && <View style={{ height: headerHeight + SEARCH_BAR_HEIGHT }} />}
53
+ <View className="flex-1 items-center justify-center px-8">
54
+ <Text variant="title3" className="pb-1 text-center font-bold">
55
+ No Components Installed
56
+ </Text>
57
+ <Text color="tertiary" variant="body" className="pb-4 text-center">
58
+ You can install any of the free components from the NativeWindUI website.
59
+ </Text>
60
+ <DefaultButton
61
+ title="Open NativeWindUI"
62
+ onPress={() => Linking.openURL('https://nativewindui.com')}
63
+ />
64
+ </View>
65
+ </>
66
+ );
67
+ }
68
+
69
+ type ComponentItem = { name: string; component: () => React.JSX.Element };
70
+
71
+ function keyExtractor(item: ComponentItem) {
72
+ return item.name;
73
+ }
74
+
75
+ function renderItemSeparator() {
76
+ return <View className="p-2" />;
77
+ }
78
+
79
+ function renderItem({ item }: { item: ComponentItem }) {
80
+ return (
81
+ <Card title={item.name}>
82
+ <item.component />
83
+ </Card>
84
+ );
85
+ }
86
+
87
+ function Card({ children, title }: { children: React.ReactNode; title: string }) {
88
+ return (
89
+ <View className="px-4">
90
+ <View className="gap-4 rounded-xl border border-border bg-card p-4 pb-6 shadow-sm shadow-black/10 dark:shadow-none">
91
+ <Text className="text-center text-sm font-medium tracking-wider opacity-60">{title}</Text>
92
+ {children}
93
+ </View>
94
+ </View>
95
+ );
96
+ }
97
+
98
+ const COMPONENTS: ComponentItem[] = [];
99
+
@@ -0,0 +1,32 @@
1
+ import { Text } from '~/components/nativewind-ui/Text';
2
+ import { Link } from 'expo-router';
3
+ import { StatusBar } from 'expo-status-bar';
4
+ import { useColorScheme } from 'nativewind';
5
+ import { Platform, View } from 'react-native';
6
+
7
+ export default function ModalScreen() {
8
+ const { colorScheme } = useColorScheme();
9
+ return (
10
+ <>
11
+ <StatusBar
12
+ style={
13
+ Platform.OS === 'ios'
14
+ ? 'light'
15
+ : colorScheme === 'dark'
16
+ ? 'light'
17
+ : 'dark'
18
+ }
19
+ />
20
+ <View className='flex-1 justify-center items-center gap-8 pb-12'>
21
+ <View className='items-center gap-2'>
22
+ <Text variant='largeTitle' className='font-bold'>
23
+ NativeWindUI
24
+ </Text>
25
+ <Link href={'https://nativewindui.com/'}>
26
+ <Text className='text-primary'>https://nativewindui.com/</Text>
27
+ </Link>
28
+ </View>
29
+ </View>
30
+ </>
31
+ );
32
+ }
@@ -0,0 +1,39 @@
1
+ import { Icon } from '@roninoss/icons';
2
+ import { Appearance, Pressable, View } from 'react-native';
3
+ import Animated, { LayoutAnimationConfig, ZoomInRotate } from 'react-native-reanimated';
4
+
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
18
+ onPress={() => {
19
+ // ColorScheme is set with `Appearance` as well for the iOS header search placeholder text: https://github.com/software-mansion/react-native-screens/discussions/1758
20
+ Appearance.setColorScheme(colorScheme === 'dark' ? 'light' : 'dark');
21
+ toggleColorScheme();
22
+ }}
23
+ className="opacity-80">
24
+ {colorScheme === 'dark'
25
+ ? ({ pressed }) => (
26
+ <View className={cn('px-0.5', pressed && 'opacity-50')}>
27
+ <Icon namingScheme="sfSymbol" name="moon.stars" color={COLORS.white} />
28
+ </View>
29
+ )
30
+ : ({ pressed }) => (
31
+ <View className={cn('px-0.5', pressed && 'opacity-50')}>
32
+ <Icon namingScheme="sfSymbol" name="sun.min" color={COLORS.black} />
33
+ </View>
34
+ )}
35
+ </Pressable>
36
+ </Animated.View>
37
+ </LayoutAnimationConfig>
38
+ );
39
+ }
@@ -0,0 +1,55 @@
1
+ import { VariantProps, cva } from 'class-variance-authority';
2
+ import { cssInterop } from 'nativewind';
3
+ import * as React from 'react';
4
+ import { UITextView } from 'react-native-uitextview';
5
+
6
+ import { cn } from '~/lib/cn';
7
+
8
+ cssInterop(UITextView, { className: 'style' });
9
+
10
+ const textVariants = cva('text-foreground', {
11
+ variants: {
12
+ variant: {
13
+ largeTitle: 'text-4xl',
14
+ title1: 'text-2xl',
15
+ title2: 'text-[22px] leading-7',
16
+ title3: 'text-xl',
17
+ heading: 'text-[17px] leading-6 font-semibold',
18
+ body: 'text-[17px] leading-6',
19
+ callout: 'text-base',
20
+ subhead: 'text-[15px] leading-6',
21
+ footnote: 'text-[13px] leading-5',
22
+ caption1: 'text-xs',
23
+ caption2: 'text-[11px] leading-4',
24
+ },
25
+ color: {
26
+ primary: '',
27
+ secondary: 'text-secondary-foreground/90',
28
+ tertiary: 'text-muted-foreground/90',
29
+ quarternary: 'text-muted-foreground/50',
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ variant: 'body',
34
+ color: 'primary',
35
+ },
36
+ });
37
+
38
+ const TextClassContext = React.createContext<string | undefined>(undefined);
39
+
40
+ function Text({
41
+ className,
42
+ variant,
43
+ color,
44
+ ...props
45
+ }: React.ComponentPropsWithoutRef<typeof UITextView> & VariantProps<typeof textVariants>) {
46
+ const textClassName = React.useContext(TextClassContext);
47
+ return (
48
+ <UITextView
49
+ className={cn(textVariants({ variant, color }), textClassName, className)}
50
+ {...props}
51
+ />
52
+ );
53
+ }
54
+
55
+ export { Text, TextClassContext, textVariants };
@@ -0,0 +1,3 @@
1
+ /// <reference types="expo/types" />
2
+
3
+ // NOTE: This file should not be edited and should be in your git ignore
@@ -0,0 +1,91 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 242 242 247;
8
+ --foreground: 0 0 0;
9
+ --card: 255 255 255;
10
+ --card-foreground: 8 28 30;
11
+ --popover: 230 230 235;
12
+ --popover-foreground: 0 0 0;
13
+ --primary: 0 123 254;
14
+ --primary-foreground: 255 255 255;
15
+ --secondary: 45 175 231;
16
+ --secondary-foreground: 255 255 255;
17
+ --muted: 175 176 180;
18
+ --muted-foreground: 142 142 147;
19
+ --accent: 255 40 84;
20
+ --accent-foreground: 255 255 255;
21
+ --destructive: 255 56 43;
22
+ --destructive-foreground: 255 255 255;
23
+ --border: 230 230 235;
24
+ --input: 210 210 215;
25
+ --ring: 230 230 235;
26
+
27
+ --android-background: 249 249 255;
28
+ --android-foreground: 0 0 0;
29
+ --android-card: 255 255 255;
30
+ --android-card-foreground: 24 28 35;
31
+ --android-popover: 215 217 228;
32
+ --android-popover-foreground: 0 0 0;
33
+ --android-primary: 0 112 233;
34
+ --android-primary-foreground: 255 255 255;
35
+ --android-secondary: 176 201 255;
36
+ --android-secondary-foreground: 20 55 108;
37
+ --android-muted: 193 198 215;
38
+ --android-muted-foreground: 113 119 134;
39
+ --android-accent: 169 73 204;
40
+ --android-accent-foreground: 255 255 255;
41
+ --android-destructive: 254 67 54;
42
+ --android-destructive-foreground: 255 255 255;
43
+ --android-border: 215 217 228;
44
+ --android-input: 210 210 215;
45
+ --android-ring: 215 217 228;
46
+ }
47
+
48
+ @media (prefers-color-scheme: dark) {
49
+ :root {
50
+ --background: 0 0 0;
51
+ --foreground: 255 255 255;
52
+ --card: 21 21 24;
53
+ --card-foreground: 255 255 255;
54
+ --popover: 40 40 42;
55
+ --popover-foreground: 255 255 255;
56
+ --primary: 3 133 255;
57
+ --primary-foreground: 255 255 255;
58
+ --secondary: 100 211 254;
59
+ --secondary-foreground: 255 255 255;
60
+ --muted: 70 70 73;
61
+ --muted-foreground: 142 142 147;
62
+ --accent: 255 52 95;
63
+ --accent-foreground: 255 255 255;
64
+ --destructive: 254 67 54;
65
+ --destructive-foreground: 255 255 255;
66
+ --border: 40 40 42;
67
+ --input: 55 55 57;
68
+ --ring: 40 40 42;
69
+
70
+ --android-background: 0 0 0;
71
+ --android-foreground: 255 255 255;
72
+ --android-card: 16 19 27;
73
+ --android-card-foreground: 224 226 237;
74
+ --android-popover: 39 42 50;
75
+ --android-popover-foreground: 224 226 237;
76
+ --android-primary: 3 133 255;
77
+ --android-primary-foreground: 255 255 255;
78
+ --android-secondary: 28 60 114;
79
+ --android-secondary-foreground: 189 209 255;
80
+ --android-muted: 216 226 255;
81
+ --android-muted-foreground: 139 144 160;
82
+ --android-accent: 83 0 111;
83
+ --android-accent-foreground: 238 177 255;
84
+ --android-destructive: 147 0 10;
85
+ --android-destructive-foreground: 255 255 255;
86
+ --android-border: 39 42 50;
87
+ --android-input: 55 55 57;
88
+ --android-ring: 39 42 50;
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,14 @@
1
+ import { useColorScheme as useNativewindColorScheme } from 'nativewind';
2
+
3
+ import { COLORS } from '~/theme/colors';
4
+
5
+ export function useColorScheme() {
6
+ const { colorScheme, setColorScheme, toggleColorScheme } = useNativewindColorScheme();
7
+ return {
8
+ colorScheme: colorScheme ?? 'light',
9
+ isDarkColorScheme: colorScheme === 'dark',
10
+ setColorScheme,
11
+ toggleColorScheme,
12
+ colors: COLORS[colorScheme ?? 'light'],
13
+ };
14
+ }