Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mjs and ts config #26

Merged
merged 4 commits into from
Dec 27, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Format
pontusab committed Dec 27, 2024
commit 3870c20896608fd6d701d47944574e643d96c43e
4 changes: 2 additions & 2 deletions biome.json
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
"enabled": true
},
"linter": {
"ignore": ["node_modules"],
"ignore": ["node_modules", ".next", "*.json"],
"enabled": true,
"rules": {
"recommended": true,
@@ -22,6 +22,6 @@
},
"formatter": {
"indentStyle": "space",
"ignore": ["test/resources", "test/snapshots"]
"ignore": ["test/resources", "test/snapshots", "*.json", ".next"]
}
}
4 changes: 2 additions & 2 deletions examples/android/locales/es.xml
Original file line number Diff line number Diff line change
@@ -41,8 +41,8 @@
<item quantity="other">%d canciones en cola</item>
</plurals>
<plurals name="notification_likes">
<item quantity="one">A %d persona le gustó tu publicación</item>
<item quantity="other">A %d personas les gustó tu publicación</item>
<item quantity="one">%d persona le gustó tu publicación</item>
<item quantity="other">%d personas les gustó tu publicación</item>
</plurals>
<plurals name="game_achievements">
<item quantity="one">%d logro desbloqueado</item>
2 changes: 1 addition & 1 deletion examples/expo/app.json
Original file line number Diff line number Diff line change
@@ -46,4 +46,4 @@
"es": "./locales/native/es.json"
}
}
}
}
35 changes: 20 additions & 15 deletions examples/expo/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
import { Tabs } from 'expo-router';
import React from 'react';
import { Platform } from 'react-native';
import { Tabs } from "expo-router";
import React from "react";
import { Platform } from "react-native";

import { HapticTab } from '@/components/HapticTab';
import { IconSymbol } from '@/components/ui/IconSymbol';
import TabBarBackground from '@/components/ui/TabBarBackground';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { HapticTab } from "@/components/HapticTab";
import { IconSymbol } from "@/components/ui/IconSymbol";
import TabBarBackground from "@/components/ui/TabBarBackground";
import { Colors } from "@/constants/Colors";
import { useColorScheme } from "@/hooks/useColorScheme";

export default function TabLayout() {
const colorScheme = useColorScheme();

return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
headerShown: false,
tabBarButton: HapticTab,
tabBarBackground: TabBarBackground,
tabBarStyle: Platform.select({
ios: {
// Use a transparent background on iOS to show the blur effect
position: 'absolute',
position: "absolute",
},
default: {},
}),
}}>
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
title: "Home",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="house.fill" color={color} />
),
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
title: "Explore",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="paperplane.fill" color={color} />
),
}}
/>
</Tabs>
82 changes: 51 additions & 31 deletions examples/expo/app/(tabs)/explore.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
import { StyleSheet, Image, Platform } from 'react-native';
import { StyleSheet, Image, Platform } from "react-native";

import { Collapsible } from '@/components/Collapsible';
import { ExternalLink } from '@/components/ExternalLink';
import ParallaxScrollView from '@/components/ParallaxScrollView';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol';
import { Collapsible } from "@/components/Collapsible";
import { ExternalLink } from "@/components/ExternalLink";
import ParallaxScrollView from "@/components/ParallaxScrollView";
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";
import { IconSymbol } from "@/components/ui/IconSymbol";

export default function TabTwoScreen() {
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
headerBackgroundColor={{ light: "#D0D0D0", dark: "#353636" }}
headerImage={
<IconSymbol
size={310}
color="#808080"
name="chevron.left.forwardslash.chevron.right"
style={styles.headerImage}
/>
}>
}
>
<ThemedView style={styles.titleContainer}>
<ThemedText type="title">Explore</ThemedText>
</ThemedView>
<ThemedText>This app includes example code to help you get started.</ThemedText>
<ThemedText>
This app includes example code to help you get started.
</ThemedText>
<Collapsible title="File-based routing">
<ThemedText>
This app has two screens:{' '}
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '}
This app has two screens:{" "}
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText>{" "}
and{" "}
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
</ThemedText>
<ThemedText>
The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '}
The layout file in{" "}
<ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{" "}
sets up the tab navigator.
</ThemedText>
<ExternalLink href="https://docs.expo.dev/router/introduction">
@@ -39,25 +44,31 @@ export default function TabTwoScreen() {
</Collapsible>
<Collapsible title="Android, iOS, and web support">
<ThemedText>
You can open this project on Android, iOS, and the web. To open the web version, press{' '}
<ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project.
You can open this project on Android, iOS, and the web. To open the
web version, press <ThemedText type="defaultSemiBold">w</ThemedText>{" "}
in the terminal running this project.
</ThemedText>
</Collapsible>
<Collapsible title="Images">
<ThemedText>
For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '}
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
different screen densities
For static images, you can use the{" "}
<ThemedText type="defaultSemiBold">@2x</ThemedText> and{" "}
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to
provide files for different screen densities
</ThemedText>
<Image source={require('@/assets/images/react-logo.png')} style={{ alignSelf: 'center' }} />
<Image
source={require("@/assets/images/react-logo.png")}
style={{ alignSelf: "center" }}
/>
<ExternalLink href="https://reactnative.dev/docs/images">
<ThemedText type="link">Learn more</ThemedText>
</ExternalLink>
</Collapsible>
<Collapsible title="Custom fonts">
<ThemedText>
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText> to see how to load{' '}
<ThemedText style={{ fontFamily: 'SpaceMono' }}>
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText>{" "}
to see how to load{" "}
<ThemedText style={{ fontFamily: "SpaceMono" }}>
custom fonts such as this one.
</ThemedText>
</ThemedText>
@@ -67,25 +78,34 @@ export default function TabTwoScreen() {
</Collapsible>
<Collapsible title="Light and dark mode components">
<ThemedText>
This template has light and dark mode support. The{' '}
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect
what the user's current color scheme is, and so you can adjust UI colors accordingly.
This template has light and dark mode support. The{" "}
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook
lets you inspect what the user's current color scheme is, and so you
can adjust UI colors accordingly.
</ThemedText>
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
<ThemedText type="link">Learn more</ThemedText>
</ExternalLink>
</Collapsible>
<Collapsible title="Animations">
<ThemedText>
This template includes an example of an animated component. The{' '}
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses
the powerful <ThemedText type="defaultSemiBold">react-native-reanimated</ThemedText>{' '}
This template includes an example of an animated component. The{" "}
<ThemedText type="defaultSemiBold">
components/HelloWave.tsx
</ThemedText>{" "}
component uses the powerful{" "}
<ThemedText type="defaultSemiBold">
react-native-reanimated
</ThemedText>{" "}
library to create a waving hand animation.
</ThemedText>
{Platform.select({
ios: (
<ThemedText>
The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '}
The{" "}
<ThemedText type="defaultSemiBold">
components/ParallaxScrollView.tsx
</ThemedText>{" "}
component provides a parallax effect for the header image.
</ThemedText>
),
@@ -97,13 +117,13 @@ export default function TabTwoScreen() {

const styles = StyleSheet.create({
headerImage: {
color: '#808080',
color: "#808080",
bottom: -90,
left: -35,
position: 'absolute',
position: "absolute",
},
titleContainer: {
flexDirection: 'row',
flexDirection: "row",
gap: 8,
},
});
48 changes: 26 additions & 22 deletions examples/expo/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,56 @@
import { Image, StyleSheet, Platform } from 'react-native';
import { Image, StyleSheet, Platform } from "react-native";

import { HelloWave } from '@/components/HelloWave';
import ParallaxScrollView from '@/components/ParallaxScrollView';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { HelloWave } from "@/components/HelloWave";
import ParallaxScrollView from "@/components/ParallaxScrollView";
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";

export default function HomeScreen() {
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
headerImage={
<Image
source={require('@/assets/images/partial-react-logo.png')}
source={require("@/assets/images/partial-react-logo.png")}
style={styles.reactLogo}
/>
}>
}
>
<ThemedView style={styles.titleContainer}>
<ThemedText type="title">Welcome!</ThemedText>
<HelloWave />
</ThemedView>
<ThemedView style={styles.stepContainer}>
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
<ThemedText>
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
Press{' '}
Edit{" "}
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText>{" "}
to see changes. Press{" "}
<ThemedText type="defaultSemiBold">
{Platform.select({
ios: 'cmd + d',
android: 'cmd + m',
web: 'F12'
ios: "cmd + d",
android: "cmd + m",
web: "F12",
})}
</ThemedText>{' '}
</ThemedText>{" "}
to open developer tools.
</ThemedText>
</ThemedView>
<ThemedView style={styles.stepContainer}>
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
<ThemedText>
Tap the Explore tab to learn more about what's included in this starter app.
Tap the Explore tab to learn more about what's included in this
starter app.
</ThemedText>
</ThemedView>
<ThemedView style={styles.stepContainer}>
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
<ThemedText>
When you're ready, run{' '}
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
When you're ready, run{" "}
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText>{" "}
to get a fresh <ThemedText type="defaultSemiBold">app</ThemedText>{" "}
directory. This will move the current{" "}
<ThemedText type="defaultSemiBold">app</ThemedText> to{" "}
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
</ThemedText>
</ThemedView>
@@ -56,8 +60,8 @@ export default function HomeScreen() {

const styles = StyleSheet.create({
titleContainer: {
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
gap: 8,
},
stepContainer: {
@@ -69,6 +73,6 @@ const styles = StyleSheet.create({
width: 290,
bottom: 0,
left: 0,
position: 'absolute',
position: "absolute",
},
});
14 changes: 7 additions & 7 deletions examples/expo/app/+not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Link, Stack } from 'expo-router';
import { StyleSheet } from 'react-native';
import { Link, Stack } from "expo-router";
import { StyleSheet } from "react-native";

import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";

export default function NotFoundScreen() {
return (
<>
<Stack.Screen options={{ title: 'Oops!' }} />
<Stack.Screen options={{ title: "Oops!" }} />
<ThemedView style={styles.container}>
<ThemedText type="title">This screen doesn't exist.</ThemedText>
<Link href="/" style={styles.link}>
@@ -21,8 +21,8 @@ export default function NotFoundScreen() {
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignItems: "center",
justifyContent: "center",
padding: 20,
},
link: {
24 changes: 14 additions & 10 deletions examples/expo/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import 'react-native-reanimated';
import {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import { useEffect } from "react";
import "react-native-reanimated";

import { useColorScheme } from '@/hooks/useColorScheme';
import { useColorScheme } from "@/hooks/useColorScheme";

// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});

useEffect(() => {
@@ -28,7 +32,7 @@ export default function RootLayout() {
}

return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
32 changes: 18 additions & 14 deletions examples/expo/components/Collapsible.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { PropsWithChildren, useState } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { PropsWithChildren, useState } from "react";
import { StyleSheet, TouchableOpacity } from "react-native";

import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";
import { IconSymbol } from "@/components/ui/IconSymbol";
import { Colors } from "@/constants/Colors";
import { useColorScheme } from "@/hooks/useColorScheme";

export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
export function Collapsible({
children,
title,
}: PropsWithChildren & { title: string }) {
const [isOpen, setIsOpen] = useState(false);
const theme = useColorScheme() ?? 'light';
const theme = useColorScheme() ?? "light";

return (
<ThemedView>
<TouchableOpacity
style={styles.heading}
onPress={() => setIsOpen((value) => !value)}
activeOpacity={0.8}>
activeOpacity={0.8}
>
<IconSymbol
name="chevron.right"
size={18}
weight="medium"
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }}
color={theme === "light" ? Colors.light.icon : Colors.dark.icon}
style={{ transform: [{ rotate: isOpen ? "90deg" : "0deg" }] }}
/>

<ThemedText type="defaultSemiBold">{title}</ThemedText>
@@ -34,8 +38,8 @@ export function Collapsible({ children, title }: PropsWithChildren & { title: st

const styles = StyleSheet.create({
heading: {
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
gap: 6,
},
content: {
12 changes: 6 additions & 6 deletions examples/expo/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Link } from 'expo-router';
import { openBrowserAsync } from 'expo-web-browser';
import { type ComponentProps } from 'react';
import { Platform } from 'react-native';
import { Link } from "expo-router";
import { openBrowserAsync } from "expo-web-browser";
import { type ComponentProps } from "react";
import { Platform } from "react-native";

type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: string };
type Props = Omit<ComponentProps<typeof Link>, "href"> & { href: string };

export function ExternalLink({ href, ...rest }: Props) {
return (
@@ -12,7 +12,7 @@ export function ExternalLink({ href, ...rest }: Props) {
{...rest}
href={href}
onPress={async (event) => {
if (Platform.OS !== 'web') {
if (Platform.OS !== "web") {
// Prevent the default behavior of linking to the default browser on native.
event.preventDefault();
// Open the link in an in-app browser.
8 changes: 4 additions & 4 deletions examples/expo/components/HapticTab.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
import { PlatformPressable } from '@react-navigation/elements';
import * as Haptics from 'expo-haptics';
import { BottomTabBarButtonProps } from "@react-navigation/bottom-tabs";
import { PlatformPressable } from "@react-navigation/elements";
import * as Haptics from "expo-haptics";

export function HapticTab(props: BottomTabBarButtonProps) {
return (
<PlatformPressable
{...props}
onPressIn={(ev) => {
if (process.env.EXPO_OS === 'ios') {
if (process.env.EXPO_OS === "ios") {
// Add a soft haptic feedback when pressing down on the tabs.
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}
15 changes: 9 additions & 6 deletions examples/expo/components/HelloWave.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { useEffect } from 'react';
import { StyleSheet } from 'react-native';
import { useEffect } from "react";
import { StyleSheet } from "react-native";
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withRepeat,
withSequence,
} from 'react-native-reanimated';
} from "react-native-reanimated";

import { ThemedText } from '@/components/ThemedText';
import { ThemedText } from "@/components/ThemedText";

export function HelloWave() {
const rotationAnimation = useSharedValue(0);

useEffect(() => {
rotationAnimation.value = withRepeat(
withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
4 // Run the animation 4 times
withSequence(
withTiming(25, { duration: 150 }),
withTiming(0, { duration: 150 }),
),
4, // Run the animation 4 times
);
}, []);

32 changes: 19 additions & 13 deletions examples/expo/components/ParallaxScrollView.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { PropsWithChildren, ReactElement } from 'react';
import { StyleSheet } from 'react-native';
import type { PropsWithChildren, ReactElement } from "react";
import { StyleSheet } from "react-native";
import Animated, {
interpolate,
useAnimatedRef,
useAnimatedStyle,
useScrollViewOffset,
} from 'react-native-reanimated';
} from "react-native-reanimated";

import { ThemedView } from '@/components/ThemedView';
import { useBottomTabOverflow } from '@/components/ui/TabBarBackground';
import { useColorScheme } from '@/hooks/useColorScheme';
import { ThemedView } from "@/components/ThemedView";
import { useBottomTabOverflow } from "@/components/ui/TabBarBackground";
import { useColorScheme } from "@/hooks/useColorScheme";

const HEADER_HEIGHT = 250;

@@ -23,7 +23,7 @@ export default function ParallaxScrollView({
headerImage,
headerBackgroundColor,
}: Props) {
const colorScheme = useColorScheme() ?? 'light';
const colorScheme = useColorScheme() ?? "light";
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef);
const bottom = useBottomTabOverflow();
@@ -34,11 +34,15 @@ export default function ParallaxScrollView({
translateY: interpolate(
scrollOffset.value,
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75],
),
},
{
scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
scale: interpolate(
scrollOffset.value,
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
[2, 1, 1],
),
},
],
};
@@ -50,13 +54,15 @@ export default function ParallaxScrollView({
ref={scrollRef}
scrollEventThrottle={16}
scrollIndicatorInsets={{ bottom }}
contentContainerStyle={{ paddingBottom: bottom }}>
contentContainerStyle={{ paddingBottom: bottom }}
>
<Animated.View
style={[
styles.header,
{ backgroundColor: headerBackgroundColor[colorScheme] },
headerAnimatedStyle,
]}>
]}
>
{headerImage}
</Animated.View>
<ThemedView style={styles.content}>{children}</ThemedView>
@@ -71,12 +77,12 @@ const styles = StyleSheet.create({
},
header: {
height: HEADER_HEIGHT,
overflow: 'hidden',
overflow: "hidden",
},
content: {
flex: 1,
padding: 32,
gap: 16,
overflow: 'hidden',
overflow: "hidden",
},
});
28 changes: 14 additions & 14 deletions examples/expo/components/ThemedText.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import { Text, type TextProps, StyleSheet } from 'react-native';
import { Text, type TextProps, StyleSheet } from "react-native";

import { useThemeColor } from '@/hooks/useThemeColor';
import { useThemeColor } from "@/hooks/useThemeColor";

export type ThemedTextProps = TextProps & {
lightColor?: string;
darkColor?: string;
type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
type?: "default" | "title" | "defaultSemiBold" | "subtitle" | "link";
};

export function ThemedText({
style,
lightColor,
darkColor,
type = 'default',
type = "default",
...rest
}: ThemedTextProps) {
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
const color = useThemeColor({ light: lightColor, dark: darkColor }, "text");

return (
<Text
style={[
{ color },
type === 'default' ? styles.default : undefined,
type === 'title' ? styles.title : undefined,
type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined,
type === 'subtitle' ? styles.subtitle : undefined,
type === 'link' ? styles.link : undefined,
type === "default" ? styles.default : undefined,
type === "title" ? styles.title : undefined,
type === "defaultSemiBold" ? styles.defaultSemiBold : undefined,
type === "subtitle" ? styles.subtitle : undefined,
type === "link" ? styles.link : undefined,
style,
]}
{...rest}
@@ -41,20 +41,20 @@ const styles = StyleSheet.create({
defaultSemiBold: {
fontSize: 16,
lineHeight: 24,
fontWeight: '600',
fontWeight: "600",
},
title: {
fontSize: 32,
fontWeight: 'bold',
fontWeight: "bold",
lineHeight: 32,
},
subtitle: {
fontSize: 20,
fontWeight: 'bold',
fontWeight: "bold",
},
link: {
lineHeight: 30,
fontSize: 16,
color: '#0a7ea4',
color: "#0a7ea4",
},
});
16 changes: 12 additions & 4 deletions examples/expo/components/ThemedView.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { View, type ViewProps } from 'react-native';
import { View, type ViewProps } from "react-native";

import { useThemeColor } from '@/hooks/useThemeColor';
import { useThemeColor } from "@/hooks/useThemeColor";

export type ThemedViewProps = ViewProps & {
lightColor?: string;
darkColor?: string;
};

export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
export function ThemedView({
style,
lightColor,
darkColor,
...otherProps
}: ThemedViewProps) {
const backgroundColor = useThemeColor(
{ light: lightColor, dark: darkColor },
"background",
);

return <View style={[{ backgroundColor }, style]} {...otherProps} />;
}
10 changes: 6 additions & 4 deletions examples/expo/components/__tests__/ThemedText-test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as React from 'react';
import renderer from 'react-test-renderer';
import * as React from "react";
import renderer from "react-test-renderer";

import { ThemedText } from '../ThemedText';
import { ThemedText } from "../ThemedText";

it(`renders correctly`, () => {
const tree = renderer.create(<ThemedText>Snapshot test!</ThemedText>).toJSON();
const tree = renderer
.create(<ThemedText>Snapshot test!</ThemedText>)
.toJSON();

expect(tree).toMatchSnapshot();
});
8 changes: 4 additions & 4 deletions examples/expo/components/ui/IconSymbol.ios.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
import { StyleProp, ViewStyle } from 'react-native';
import { SymbolView, SymbolViewProps, SymbolWeight } from "expo-symbols";
import { StyleProp, ViewStyle } from "react-native";

export function IconSymbol({
name,
size = 24,
color,
style,
weight = 'regular',
weight = "regular",
}: {
name: SymbolViewProps['name'];
name: SymbolViewProps["name"];
size?: number;
color: string;
style?: StyleProp<ViewStyle>;
29 changes: 18 additions & 11 deletions examples/expo/components/ui/IconSymbol.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
// This file is a fallback for using MaterialIcons on Android and web.

import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { SymbolWeight } from 'expo-symbols';
import React from 'react';
import { OpaqueColorValue, StyleProp, ViewStyle } from 'react-native';
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import { SymbolWeight } from "expo-symbols";
import React from "react";
import { OpaqueColorValue, StyleProp, ViewStyle } from "react-native";

// Add your SFSymbol to MaterialIcons mappings here.
const MAPPING = {
// See MaterialIcons here: https://icons.expo.fyi
// See SF Symbols in the SF Symbols app on Mac.
'house.fill': 'home',
'paperplane.fill': 'send',
'chevron.left.forwardslash.chevron.right': 'code',
'chevron.right': 'chevron-right',
"house.fill": "home",
"paperplane.fill": "send",
"chevron.left.forwardslash.chevron.right": "code",
"chevron.right": "chevron-right",
} as Partial<
Record<
import('expo-symbols').SymbolViewProps['name'],
React.ComponentProps<typeof MaterialIcons>['name']
import("expo-symbols").SymbolViewProps["name"],
React.ComponentProps<typeof MaterialIcons>["name"]
>
>;

@@ -39,5 +39,12 @@ export function IconSymbol({
style?: StyleProp<ViewStyle>;
weight?: SymbolWeight;
}) {
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
return (
<MaterialIcons
color={color}
size={size}
name={MAPPING[name]}
style={style}
/>
);
}
8 changes: 4 additions & 4 deletions examples/expo/components/ui/TabBarBackground.ios.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { BlurView } from 'expo-blur';
import { StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
import { BlurView } from "expo-blur";
import { StyleSheet } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";

export default function BlurTabBarBackground() {
return (
20 changes: 10 additions & 10 deletions examples/expo/constants/Colors.ts
Original file line number Diff line number Diff line change
@@ -3,24 +3,24 @@
* There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
*/

const tintColorLight = '#0a7ea4';
const tintColorDark = '#fff';
const tintColorLight = "#0a7ea4";
const tintColorDark = "#fff";

export const Colors = {
light: {
text: '#11181C',
background: '#fff',
text: "#11181C",
background: "#fff",
tint: tintColorLight,
icon: '#687076',
tabIconDefault: '#687076',
icon: "#687076",
tabIconDefault: "#687076",
tabIconSelected: tintColorLight,
},
dark: {
text: '#ECEDEE',
background: '#151718',
text: "#ECEDEE",
background: "#151718",
tint: tintColorDark,
icon: '#9BA1A6',
tabIconDefault: '#9BA1A6',
icon: "#9BA1A6",
tabIconDefault: "#9BA1A6",
tabIconSelected: tintColorDark,
},
};
2 changes: 1 addition & 1 deletion examples/expo/hooks/useColorScheme.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { useColorScheme } from 'react-native';
export { useColorScheme } from "react-native";
6 changes: 3 additions & 3 deletions examples/expo/hooks/useColorScheme.web.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { useColorScheme as useRNColorScheme } from 'react-native';
import { useEffect, useState } from "react";
import { useColorScheme as useRNColorScheme } from "react-native";

/**
* To support static rendering, this value needs to be re-calculated on the client side for web
@@ -17,5 +17,5 @@ export function useColorScheme() {
return colorScheme;
}

return 'light';
return "light";
}
8 changes: 4 additions & 4 deletions examples/expo/hooks/useThemeColor.ts
Original file line number Diff line number Diff line change
@@ -3,14 +3,14 @@
* https://docs.expo.dev/guides/color-schemes/
*/

import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { Colors } from "@/constants/Colors";
import { useColorScheme } from "@/hooks/useColorScheme";

export function useThemeColor(
props: { light?: string; dark?: string },
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
colorName: keyof typeof Colors.light & keyof typeof Colors.dark,
) {
const theme = useColorScheme() ?? 'light';
const theme = useColorScheme() ?? "light";
const colorFromProps = props[theme];

if (colorFromProps) {
14 changes: 7 additions & 7 deletions examples/expo/locales/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// For more information on Expo Localization and usage: https://docs.expo.dev/guides/localization
import { getLocales } from 'expo-localization';
import { I18n } from 'i18n-js';
import { getLocales } from "expo-localization";
import { I18n } from "i18n-js";

const translations = {
en: require('./en.json'),
es: require('./es.json')
}
en: require("./en.json"),
es: require("./es.json"),
};

const i18n = new I18n(translations);

i18n.locale = getLocales().at(0)?.languageCode ?? 'en';
i18n.locale = getLocales().at(0)?.languageCode ?? "en";

i18n.enableFallback = true;

export default i18n;
export default i18n;
2 changes: 1 addition & 1 deletion examples/expo/scripts/reset-project.js
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ const moveDirectories = async () => {

console.log("\n✅ Project reset complete. Next steps:");
console.log(
"1. Run `npx expo start` to start a development server.\n2. Edit app/index.tsx to edit the main screen.\n3. Delete the /app-example directory when you're done referencing it."
"1. Run `npx expo start` to start a development server.\n2. Edit app/index.tsx to edit the main screen.\n3. Delete the /app-example directory when you're done referencing it.",
);
} catch (error) {
console.error(`Error during script execution: ${error}`);
11 changes: 2 additions & 9 deletions examples/expo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -3,15 +3,8 @@
"compilerOptions": {
"strict": true,
"paths": {
"@/*": [
"./*"
]
"@/*": ["./*"]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts"
]
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}
2 changes: 1 addition & 1 deletion examples/i18next/languine.config.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ export default defineConfig({
},
files: {
json: {
include: ["locales"],
include: ["locales/[locale].json"],
},
},
llm: {
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "languine",
"version": "0.6.8",
"version": "0.6.9",
"type": "module",
"bin": "dist/index.js",
"main": "dist/config.js",
26 changes: 16 additions & 10 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -67,6 +67,8 @@ function getDefaultPattern(format: string) {
}

export async function init(preset?: string) {
let configType = "ts";

try {
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
} catch (error) {
@@ -78,17 +80,19 @@ export async function init(preset?: string) {

intro("Let's set up your i18n configuration");

const configType = (await select({
message: "What type of config file would you like to use?",
options: [
{ value: "ts", label: "TypeScript", hint: "recommended" },
{ value: "mjs", label: "JavaScript" },
],
})) as "ts" | "mjs";
if (!preset) {
configType = (await select({
message: "What type of config file would you like to use?",
options: [
{ value: "ts", label: "TypeScript", hint: "recommended" },
{ value: "mjs", label: "JavaScript" },
],
})) as "ts" | "mjs";

// Install dependencies only if we're using TypeScript for types in config
if (configType === "ts") {
await installDependencies();
// Install dependencies only if we're using TypeScript for types in config
if (configType === "ts") {
await installDependencies();
}
}

const sourceLanguage = (await select({
@@ -155,6 +159,8 @@ export async function init(preset?: string) {
filesPatterns = Array.isArray(presetConfig.filesPattern)
? presetConfig.filesPattern
: [presetConfig.filesPattern];

configType = presetConfig.configType;
}

const provider = (await select<Provider>({
1 change: 1 addition & 0 deletions packages/cli/src/presets/expo.ts
Original file line number Diff line number Diff line change
@@ -107,6 +107,7 @@ export async function expo(options: PresetOptions) {

return {
fileFormat: "json",
configType: "ts",
filesPattern: ["locales/native/[locale].json", "locales/[locale].json"],
};
}
4 changes: 2 additions & 2 deletions packages/cli/src/utils.ts
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ export function generateConfig({
filesPatterns: string[];
provider: string;
model: string;
configType: "ts" | "mjs";
configType: string;
}) {
const formatKey = fileFormat.includes("-") ? `"${fileFormat}"` : fileFormat;

@@ -111,7 +111,7 @@ export function generateConfig({
export default defineConfig(${configBody})`;
}

export async function configFile(configType?: "ts" | "mjs") {
export async function configFile(configType?: string) {
const files = await fs.readdir(process.cwd());
const configFile = files.find(
(file: string) =>