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

feat(cli): expo-router option #2727

Merged
merged 16 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions boilerplate/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ buck-out/
bin/Exponent.app
/android
/ios
expo-env.d.ts

## Secrets
npm-debug.*
Expand Down
9 changes: 6 additions & 3 deletions boilerplate/app/components/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ interface ListItemActionProps {
* @param {ListItemProps} props - The props for the `ListItem` component.
* @returns {JSX.Element} The rendered `ListItem` component.
*/
export function ListItem(props: ListItemProps) {
export const ListItem = React.forwardRef<View, ListItemProps>(function ListItem(
props: ListItemProps,
ref,
) {
const {
bottomSeparator,
children,
Expand Down Expand Up @@ -138,7 +141,7 @@ export function ListItem(props: ListItemProps) {
const $touchableStyles = [$styles.row, $touchableStyle, { minHeight: height }, style]

return (
<View style={themed($containerStyles)}>
<View ref={ref} style={themed($containerStyles)}>
<TouchableOpacity {...TouchableOpacityProps} style={$touchableStyles}>
<ListItemAction
side="left"
Expand All @@ -162,7 +165,7 @@ export function ListItem(props: ListItemProps) {
</TouchableOpacity>
</View>
)
}
})

/**
* @param {ListItemActionProps} props - The props for the `ListItemAction` component.
Expand Down
49 changes: 49 additions & 0 deletions boilerplate/src/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react"
import { ViewStyle } from "react-native"
import { Slot, SplashScreen } from "expo-router"
import { GestureHandlerRootView } from "react-native-gesture-handler"
// @mst replace-next-line
import { useInitialRootStore } from "src/models"
import { useFonts } from "@expo-google-fonts/space-grotesk"
import { customFontsToLoad } from "src/theme"

SplashScreen.preventAutoHideAsync()

if (__DEV__) {
// Load Reactotron configuration in development. We don't want to
// include this in our production bundle, so we are using `if (__DEV__)`
// to only execute this in development.
require("src/devtools/ReactotronConfig.ts")
}

export { ErrorBoundary } from "src/components/ErrorBoundary/ErrorBoundary"

export default function Root() {
// @mst remove-block-start
// Wait for stores to load and render our layout inside of it so we have access
// to auth info etc
const { rehydrated } = useInitialRootStore()
// @mst remove-block-end

const [fontsLoaded, fontError] = useFonts(customFontsToLoad)

const loaded = fontsLoaded && rehydrated

React.useEffect(() => {
if (fontError) throw fontError
}, [fontError])

React.useEffect(() => {
if (loaded) {
SplashScreen.hideAsync()
}
}, [loaded])

if (!loaded) {
return null
}

return <GestureHandlerRootView style={$root}><Slot /></GestureHandlerRootView>
}

const $root: ViewStyle = { flex: 1 }
79 changes: 79 additions & 0 deletions boilerplate/src/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// @mst replace-next-line
import { observer } from "mobx-react-lite"
import React from "react"
import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native"
import { Text } from "src/components"
import { isRTL } from "../i18n"
import { colors, spacing } from "../theme"
import { useSafeAreaInsetsStyle } from "../utils/useSafeAreaInsetsStyle"

const welcomeLogo = require("../../assets/images/logo.png")
const welcomeFace = require("../../assets/images/welcome-face.png")

// @mst replace-next-line export default function WelcomeScreen() {
export default observer(function WelcomeScreen() {
const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"])

return (
<View style={$container}>
<View style={$topContainer}>
<Image style={$welcomeLogo} source={welcomeLogo} resizeMode="contain" />
<Text
testID="welcome-heading"
style={$welcomeHeading}
tx="welcomeScreen.readyForLaunch"
preset="heading"
/>
<Text tx="welcomeScreen.exciting" preset="subheading" />
<Image style={$welcomeFace} source={welcomeFace} resizeMode="contain" />
</View>

<View style={[$bottomContainer, $bottomContainerInsets]}>
<Text tx="welcomeScreen.postscript" size="md" />
</View>
</View>
)
// @mst replace-next-line }
})

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
}

const $topContainer: ViewStyle = {
flexShrink: 1,
flexGrow: 1,
flexBasis: "57%",
justifyContent: "center",
paddingHorizontal: spacing.lg,
}

const $bottomContainer: ViewStyle = {
flexShrink: 1,
flexGrow: 0,
flexBasis: "43%",
backgroundColor: colors.palette.neutral100,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
paddingHorizontal: spacing.lg,
justifyContent: "space-around",
}
const $welcomeLogo: ImageStyle = {
height: 88,
width: "100%",
marginBottom: spacing.xxl,
}

const $welcomeFace: ImageStyle = {
height: 169,
width: 269,
position: "absolute",
bottom: -47,
right: -80,
transform: [{ scaleX: isRTL ? -1 : 1 }],
}

const $welcomeHeading: TextStyle = {
marginBottom: spacing.md,
}
2 changes: 1 addition & 1 deletion boilerplate/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"module": "commonjs"
}
},
"include": ["index.js", "App.tsx", "app", "types", "plugins", "app.config.ts"],
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"],
"exclude": ["node_modules", "test/**/*"]
}
5 changes: 3 additions & 2 deletions docs/cli/Ignite-CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,13 @@ Starts the interactive prompt for generating a new Ignite project. Any options n
- `--overwrite` overwrite the target directory if it exists
- `--targetPath` string, specify a target directory where the project should be created
- `--removeDemo` will remove the boilerplate demo code after project creation
- `--mst` flag to specify whether to include MobX-State-Tree in project (can only be set to `false` if `--removeDemo=true`)
- `--state` string, one of `mst` or `none` to include MobX-State-Tree in project (can only be set to `none` if `--removeDemo=true`)
- `--useCache` flag specifying to use dependency cache for quicker installs
- `--no-timeout` flag to disable the timeout protection (useful for slow internet connections)
- `--yes` accept all prompt defaults
- `--workflow` string, one of `expo`, `cng` or `manual` for project initialization
- `--workflow` string, one of `cng` or `manual` for project initialization
- `--experimental` comma separated string, indicates experimental features (which may or may not be stable) to turn on during installation. **A CNG workflow is require for these flags** `--workflow=cng`
- `expo-router` converts the project to [Expo Router](https://docs.expo.dev/router/introduction/) from React Navigation
- `new-arch` enables [The New Architecture](https://reactnative.dev/docs/new-architecture-intro)
- `expo-canary` uses Expo's highly experimental canary release instead of the la test stable SDK
- `expo-beta` uses Expo's latest beta SDK available instead of the latest stable SDK
Expand Down
4 changes: 2 additions & 2 deletions docs/concept/MobX-State-Tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ We also recognize no state management solution is perfect. MST has some known do

### Remove MST Option

We understand that state management is a highly opinionated topic with various options available. To accommodate this, we've added an option in Ignite CLI to remove MobX-State-Tree if you choose so! When Igniting a new project, provide `--mst=false` to remove MobX-State-Tree code from the boilerplate. This option only works when also removing demo code.
We understand that state management is a highly opinionated topic with various options available. To accommodate this, we've added an option in Ignite CLI to remove MobX-State-Tree if you choose so! When Igniting a new project, provide `--state=none` to remove MobX-State-Tree code from the boilerplate. This option only works when also removing demo code.

```
npx ignite-cli@latest new PizzaApp --removeDemo=true --mst=false
npx ignite-cli@latest new PizzaApp --removeDemo=true --state=none
```

## Learning MobX-State-Tree
Expand Down
Loading