@highbeek/create-rnstarterkit 1.0.2-beta.10 → 1.0.2-beta.11
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/LICENSE +21 -0
- package/README.md +254 -0
- package/dist/bin/create-rnstarterkit.js +6 -0
- package/dist/src/generators/appGenerator.js +1241 -107
- package/dist/templates/cli-base/App.tsx +199 -21
- package/dist/templates/cli-base/assets/images/icon.png +0 -0
- package/dist/templates/cli-base/assets/images/partial-react-logo.png +0 -0
- package/dist/templates/cli-base/assets/images/react-logo.png +0 -0
- package/dist/templates/cli-base/jest.config.js +4 -0
- package/dist/templates/cli-base/package.json +5 -3
- package/dist/templates/cli-base/tsconfig.json +1 -0
- package/dist/templates/expo-base/app/_layout.tsx +6 -3
- package/dist/templates/expo-base/app/index.tsx +164 -5
- package/dist/templates/expo-base/package.json +5 -2
- package/dist/templates/optional/auth-context/components/layout/ScreenLayout.tsx +46 -0
- package/dist/templates/optional/auth-context/navigation/ProtectedStack.tsx +33 -5
- package/dist/templates/optional/auth-context/screens/HomeScreen.tsx +4 -3
- package/dist/templates/optional/auth-context/screens/LoginScreen.tsx +4 -3
- package/dist/templates/optional/auth-context/screens/ProfileScreen.tsx +4 -3
- package/dist/templates/optional/auth-context/screens/RegisterScreen.tsx +4 -3
- package/dist/templates/optional/auth-context/screens/SettingsScreen.tsx +4 -3
- package/dist/templates/optional/auth-context/screens/WelcomeScreen.tsx +174 -0
- package/dist/templates/optional/auth-redux/components/layout/ScreenLayout.tsx +46 -0
- package/dist/templates/optional/auth-redux/navigation/ProtectedStack.tsx +39 -2
- package/dist/templates/optional/auth-redux/screens/HomeScreen.tsx +4 -3
- package/dist/templates/optional/auth-redux/screens/LoginScreen.tsx +4 -3
- package/dist/templates/optional/auth-redux/screens/ProfileScreen.tsx +7 -10
- package/dist/templates/optional/auth-redux/screens/RegisterScreen.tsx +4 -3
- package/dist/templates/optional/auth-redux/screens/SettingsScreen.tsx +6 -9
- package/dist/templates/optional/auth-redux/screens/WelcomeScreen.tsx +174 -0
- package/dist/templates/optional/auth-zustand/components/layout/ScreenLayout.tsx +46 -0
- package/dist/templates/optional/auth-zustand/navigation/ProtectedStack.tsx +34 -6
- package/dist/templates/optional/auth-zustand/screens/HomeScreen.tsx +4 -3
- package/dist/templates/optional/auth-zustand/screens/LoginScreen.tsx +4 -3
- package/dist/templates/optional/auth-zustand/screens/ProfileScreen.tsx +4 -3
- package/dist/templates/optional/auth-zustand/screens/RegisterScreen.tsx +4 -3
- package/dist/templates/optional/auth-zustand/screens/SettingsScreen.tsx +4 -3
- package/dist/templates/optional/auth-zustand/screens/WelcomeScreen.tsx +174 -0
- package/dist/templates/optional/ci/.github/workflows/ci.yml +32 -0
- package/dist/templates/optional/error-boundary/components/ErrorBoundary.tsx +83 -0
- package/dist/templates/optional/formik/components/formik/FormikInput.tsx +45 -0
- package/dist/templates/optional/formik/components/formik/LoginForm.tsx +60 -0
- package/dist/templates/optional/formik/schemas/auth.schema.ts +17 -0
- package/dist/templates/optional/mmkv/utils/storage.ts +17 -0
- package/dist/templates/optional/react-hook-form/components/rhf/LoginForm.tsx +63 -0
- package/dist/templates/optional/react-hook-form/components/rhf/RHFInput.tsx +50 -0
- package/dist/templates/optional/react-hook-form/schemas/auth.schema.ts +29 -0
- package/dist/templates/optional/react-query/hooks/useAppMutation.ts +16 -0
- package/dist/templates/optional/react-query/hooks/useAppQuery.ts +12 -0
- package/dist/templates/optional/react-query/services/queryClient.ts +14 -0
- package/dist/templates/optional/redux/store/hooks.ts +6 -0
- package/dist/templates/optional/redux/store/store.ts +11 -0
- package/dist/templates/optional/swr/hooks/useSWRFetch.ts +14 -0
- package/dist/templates/optional/swr/providers/SWRProvider.tsx +21 -0
- package/dist/templates/optional/tsconfig.json +17 -0
- package/dist/templates/optional/zustand/store/appStore.ts +13 -0
- package/package.json +1 -1
- package/dist/templates/expo-base/components/ui/collapsible.tsx +0 -45
- package/dist/templates/expo-base/components/ui/icon-symbol.ios.tsx +0 -32
- package/dist/templates/expo-base/components/ui/icon-symbol.tsx +0 -41
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
type UseMutationOptions,
|
|
4
|
+
type UseMutationResult,
|
|
5
|
+
} from "@tanstack/react-query";
|
|
6
|
+
|
|
7
|
+
export function useAppMutation<
|
|
8
|
+
TData = unknown,
|
|
9
|
+
TError = Error,
|
|
10
|
+
TVariables = void,
|
|
11
|
+
TContext = unknown,
|
|
12
|
+
>(
|
|
13
|
+
options: UseMutationOptions<TData, TError, TVariables, TContext>,
|
|
14
|
+
): UseMutationResult<TData, TError, TVariables, TContext> {
|
|
15
|
+
return useMutation<TData, TError, TVariables, TContext>(options);
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useQuery,
|
|
3
|
+
type UseQueryOptions,
|
|
4
|
+
type QueryKey,
|
|
5
|
+
type UseQueryResult,
|
|
6
|
+
} from "@tanstack/react-query";
|
|
7
|
+
|
|
8
|
+
export function useAppQuery<TData, TError = Error>(
|
|
9
|
+
options: UseQueryOptions<TData, TError, TData, QueryKey>,
|
|
10
|
+
): UseQueryResult<TData, TError> {
|
|
11
|
+
return useQuery<TData, TError, TData, QueryKey>(options);
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
2
|
+
|
|
3
|
+
export const queryClient = new QueryClient({
|
|
4
|
+
defaultOptions: {
|
|
5
|
+
queries: {
|
|
6
|
+
retry: 2,
|
|
7
|
+
staleTime: 1000 * 60 * 5, // 5 minutes
|
|
8
|
+
gcTime: 1000 * 60 * 10, // 10 minutes
|
|
9
|
+
},
|
|
10
|
+
mutations: {
|
|
11
|
+
retry: 0,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
2
|
+
import type { TypedUseSelectorHook } from "react-redux";
|
|
3
|
+
import type { RootState, AppDispatch } from "./store";
|
|
4
|
+
|
|
5
|
+
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
|
6
|
+
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { configureStore } from "@reduxjs/toolkit";
|
|
2
|
+
|
|
3
|
+
export const store = configureStore({
|
|
4
|
+
reducer: {
|
|
5
|
+
// Add your slice reducers here
|
|
6
|
+
// example: counter: counterReducer,
|
|
7
|
+
},
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export type RootState = ReturnType<typeof store.getState>;
|
|
11
|
+
export type AppDispatch = typeof store.dispatch;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import useSWR, { type SWRConfiguration, type SWRResponse } from "swr";
|
|
2
|
+
|
|
3
|
+
const defaultFetcher = async (url: string): Promise<unknown> => {
|
|
4
|
+
const res = await fetch(url);
|
|
5
|
+
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
|
|
6
|
+
return res.json();
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function useSWRFetch<TData = unknown, TError = Error>(
|
|
10
|
+
key: string | null,
|
|
11
|
+
config?: SWRConfiguration<TData, TError>,
|
|
12
|
+
): SWRResponse<TData, TError> {
|
|
13
|
+
return useSWR<TData, TError>(key, defaultFetcher as (key: string) => Promise<TData>, config);
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SWRConfig } from "swr";
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function SWRProvider({ children }: Props) {
|
|
9
|
+
return (
|
|
10
|
+
<SWRConfig
|
|
11
|
+
value={{
|
|
12
|
+
revalidateOnFocus: true,
|
|
13
|
+
revalidateOnReconnect: true,
|
|
14
|
+
shouldRetryOnError: true,
|
|
15
|
+
errorRetryCount: 3,
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</SWRConfig>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"jsx": "react-native",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noUnusedLocals": true,
|
|
8
|
+
"noUnusedParameters": true,
|
|
9
|
+
"noFallthroughCasesInSwitch": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"types": ["jest", "node"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
16
|
+
"exclude": ["node_modules", "**/Pods", "dist"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
|
|
3
|
+
type AppState = {
|
|
4
|
+
// Add your global state here
|
|
5
|
+
// example: count: number;
|
|
6
|
+
// example: increment: () => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const useAppStore = create<AppState>(() => ({
|
|
10
|
+
// Initialize state here
|
|
11
|
+
// example: count: 0,
|
|
12
|
+
// example: increment: () => set((state) => ({ count: state.count + 1 })),
|
|
13
|
+
}));
|
package/package.json
CHANGED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { PropsWithChildren, useState } from 'react';
|
|
2
|
-
import { StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { ThemedText } from '@/components/themed-text';
|
|
5
|
-
import { ThemedView } from '@/components/themed-view';
|
|
6
|
-
import { IconSymbol } from '@/components/ui/icon-symbol';
|
|
7
|
-
import { Colors } from '@/constants/theme';
|
|
8
|
-
import { useColorScheme } from '@/hooks/use-color-scheme';
|
|
9
|
-
|
|
10
|
-
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
|
|
11
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
12
|
-
const theme = useColorScheme() ?? 'light';
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<ThemedView>
|
|
16
|
-
<TouchableOpacity
|
|
17
|
-
style={styles.heading}
|
|
18
|
-
onPress={() => setIsOpen((value) => !value)}
|
|
19
|
-
activeOpacity={0.8}>
|
|
20
|
-
<IconSymbol
|
|
21
|
-
name="chevron.right"
|
|
22
|
-
size={18}
|
|
23
|
-
weight="medium"
|
|
24
|
-
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
|
|
25
|
-
style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }}
|
|
26
|
-
/>
|
|
27
|
-
|
|
28
|
-
<ThemedText type="defaultSemiBold">{title}</ThemedText>
|
|
29
|
-
</TouchableOpacity>
|
|
30
|
-
{isOpen && <ThemedView style={styles.content}>{children}</ThemedView>}
|
|
31
|
-
</ThemedView>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const styles = StyleSheet.create({
|
|
36
|
-
heading: {
|
|
37
|
-
flexDirection: 'row',
|
|
38
|
-
alignItems: 'center',
|
|
39
|
-
gap: 6,
|
|
40
|
-
},
|
|
41
|
-
content: {
|
|
42
|
-
marginTop: 6,
|
|
43
|
-
marginLeft: 24,
|
|
44
|
-
},
|
|
45
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
|
|
2
|
-
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export function IconSymbol({
|
|
5
|
-
name,
|
|
6
|
-
size = 24,
|
|
7
|
-
color,
|
|
8
|
-
style,
|
|
9
|
-
weight = 'regular',
|
|
10
|
-
}: {
|
|
11
|
-
name: SymbolViewProps['name'];
|
|
12
|
-
size?: number;
|
|
13
|
-
color: string;
|
|
14
|
-
style?: StyleProp<ViewStyle>;
|
|
15
|
-
weight?: SymbolWeight;
|
|
16
|
-
}) {
|
|
17
|
-
return (
|
|
18
|
-
<SymbolView
|
|
19
|
-
weight={weight}
|
|
20
|
-
tintColor={color}
|
|
21
|
-
resizeMode="scaleAspectFit"
|
|
22
|
-
name={name}
|
|
23
|
-
style={[
|
|
24
|
-
{
|
|
25
|
-
width: size,
|
|
26
|
-
height: size,
|
|
27
|
-
},
|
|
28
|
-
style,
|
|
29
|
-
]}
|
|
30
|
-
/>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// Fallback for using MaterialIcons on Android and web.
|
|
2
|
-
|
|
3
|
-
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
|
4
|
-
import { SymbolWeight, SymbolViewProps } from 'expo-symbols';
|
|
5
|
-
import { ComponentProps } from 'react';
|
|
6
|
-
import { OpaqueColorValue, type StyleProp, type TextStyle } from 'react-native';
|
|
7
|
-
|
|
8
|
-
type IconMapping = Record<SymbolViewProps['name'], ComponentProps<typeof MaterialIcons>['name']>;
|
|
9
|
-
type IconSymbolName = keyof typeof MAPPING;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Add your SF Symbols to Material Icons mappings here.
|
|
13
|
-
* - see Material Icons in the [Icons Directory](https://icons.expo.fyi).
|
|
14
|
-
* - see SF Symbols in the [SF Symbols](https://developer.apple.com/sf-symbols/) app.
|
|
15
|
-
*/
|
|
16
|
-
const MAPPING = {
|
|
17
|
-
'house.fill': 'home',
|
|
18
|
-
'paperplane.fill': 'send',
|
|
19
|
-
'chevron.left.forwardslash.chevron.right': 'code',
|
|
20
|
-
'chevron.right': 'chevron-right',
|
|
21
|
-
} as IconMapping;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* An icon component that uses native SF Symbols on iOS, and Material Icons on Android and web.
|
|
25
|
-
* This ensures a consistent look across platforms, and optimal resource usage.
|
|
26
|
-
* Icon `name`s are based on SF Symbols and require manual mapping to Material Icons.
|
|
27
|
-
*/
|
|
28
|
-
export function IconSymbol({
|
|
29
|
-
name,
|
|
30
|
-
size = 24,
|
|
31
|
-
color,
|
|
32
|
-
style,
|
|
33
|
-
}: {
|
|
34
|
-
name: IconSymbolName;
|
|
35
|
-
size?: number;
|
|
36
|
-
color: string | OpaqueColorValue;
|
|
37
|
-
style?: StyleProp<TextStyle>;
|
|
38
|
-
weight?: SymbolWeight;
|
|
39
|
-
}) {
|
|
40
|
-
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
|
|
41
|
-
}
|