Skip to content

Commit

Permalink
feat(template): add Animations and Gestures to template
Browse files Browse the repository at this point in the history
Remove workaround to download template required in 0.75.0. release-npm
  • Loading branch information
tobua committed Aug 15, 2024
1 parent 48dd336 commit 4496b36
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 22 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
},
"dependencies": {
"@react-native-community/cli": "^14.0.0",
"@react-native/babel-preset": "^0.75.0",
"@react-native/eslint-config": "^0.75.0",
"@react-native/metro-config": "^0.75.0",
"@react-native/typescript-config": "^0.75.0",
"@react-native/babel-preset": "^0.75.1",
"@react-native/eslint-config": "^0.75.1",
"@react-native/metro-config": "^0.75.1",
"@react-native/typescript-config": "^0.75.1",
"arg": "^5.0.2",
"command-exists": "^1.2.9",
"deepmerge": "^4.3.1",
Expand All @@ -57,7 +57,7 @@
"@types/semver": "^7.5.8",
"jest-fixture": "^4.1.0",
"padua": "^4.0.1",
"react-native": "^0.75.0",
"react-native": "^0.75.1",
"vitest": "^2.0.5"
},
"peerDependencies": {
Expand Down
6 changes: 1 addition & 5 deletions template-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import semverSort from 'semver-sort'
import { rmSync, readdirSync, renameSync, existsSync, mkdirSync } from 'node:fs'
import { join } from 'node:path'
import { execSync } from 'node:child_process'
import { gte } from 'semver'
import { log } from './helper'
import { NativeOptions } from './types'

Expand Down Expand Up @@ -44,17 +43,14 @@ export const cacheTemplate = (nativeOptions: NativeOptions) => {

// DOC https://github.com/react-native-community/cli/blob/master/packages/cli/src/commands/init/index.ts
try {
const separateTemplate = gte(nativeOptions.version, '0.75.0')
const usesBun = typeof Bun !== 'undefined'

execSync(
`${usesBun ? 'bunx' : 'npx'} @react-native-community/cli init ${
nativeOptions.appName
} --skip-install --install-pods false --skip-git-init true --version ${
nativeOptions.version
} --directory "${join(directory, nativeOptions.appName)}"${
separateTemplate ? ' --template @react-native-community/template' : ''
}${usesBun ? ' --pm bun' : ''}`,
} --directory "${join(directory, nativeOptions.appName)}"${usesBun ? ' --pm bun' : ''}`,
{
cwd: process.cwd(),
encoding: 'utf8',
Expand Down
84 changes: 84 additions & 0 deletions template/app/markup/Animation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { LegacyRef, MutableRefObject, useEffect, useRef } from 'react'
import { Text, View, Animated } from 'react-native'
import { createStyles } from 'responsive-react-native'
import { Color, Space } from '../style'

const styles = createStyles({
wrapper: {
flexDirection: 'row',
gap: Space.medium,
},
box: {
justifyContent: 'center',
padding: Space.medium,
borderRadius: Space.medium,
backgroundColor: Color.highlight,
},
text: {
fontFamily: { ios: 'Courier', android: 'monospace' },
},
})

function animateNativeProps(view?: MutableRefObject<View | undefined>) {
if (!view?.current) {
return null
}

let opacity = 0
let increasing = true

return setInterval(() => {
if (increasing) {
opacity += 0.01
if (opacity >= 1) {
increasing = false
}
} else {
opacity -= 0.01
if (opacity <= 0) {
increasing = true
}
}

view.current?.setNativeProps({
style: { opacity },
})
}, 10)
}

export function Animation() {
const firstBox = useRef<View>()
const opacityValue = useRef(new Animated.Value(0)).current

useEffect(() => {
const intervalId = animateNativeProps(firstBox)

Animated.loop(
Animated.sequence([
Animated.timing(opacityValue, {
toValue: 1,
duration: 1500,
useNativeDriver: true,
}),
Animated.timing(opacityValue, {
toValue: 0,
duration: 1500,
useNativeDriver: true,
}),
])
).start()

return () => (intervalId ? clearInterval(intervalId) : undefined)
}, [opacityValue])

return (
<View style={styles.wrapper}>
<View ref={firstBox as LegacyRef<View>} style={styles.box}>
<Text style={styles.text}>setNativeProps</Text>
</View>
<Animated.View style={[styles.box, { opacity: opacityValue }]}>
<Text style={styles.text}>Animated.Value</Text>
</Animated.View>
</View>
)
}
48 changes: 48 additions & 0 deletions template/app/markup/Gesture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { LegacyRef, useRef } from 'react'
import { PanResponder, Text, View } from 'react-native'
import { createStyles } from 'responsive-react-native'
import { Color, Font, Space } from '../style'

const styles = createStyles({
wrapper: {
flexDirection: 'row',
gap: Space.medium,
},
box: {
justifyContent: 'center',
padding: Space.medium,
borderRadius: Space.medium,
backgroundColor: Color.highlight,
},
})

export function Gesture() {
const box = useRef<View>()
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (_event, gestureState) => {
box.current?.setNativeProps({
style: {
transform: [{ translateX: gestureState.dx }, { translateY: gestureState.dy }],
},
})
},
onPanResponderRelease: () => {
box.current?.setNativeProps({
style: {
transform: [{ translateX: 0 }, { translateY: 0 }],
},
})
},
})
).current

return (
<View style={styles.wrapper}>
<View ref={box as LegacyRef<View>} {...panResponder.panHandlers} style={styles.box}>
<Text style={Font.bold}>Drag around!</Text>
</View>
</View>
)
}
4 changes: 2 additions & 2 deletions template/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
"mobx": "^6.13.1",
"mobx-react-lite": "^4.0.7",
"react": "^18.3.1",
"react-native": "^0.75.0",
"react-native": "^0.75.1",
"reactigation": "^4.0.3",
"responsive-react-native": "^1.0.5"
"responsive-react-native": "^1.0.6"
},
"devDependencies": {
"@testing-library/jest-native": "^5.4.3",
Expand Down
6 changes: 6 additions & 0 deletions template/app/screen/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { createStyles } from 'responsive-react-native'
import { Screen } from '../markup/Screen'
import { Button } from '../markup/Button'
import { Header } from '../markup/Header'
import { Animation } from '../markup/Animation'
import { Gesture } from '../markup/Gesture'
import { Label } from '../label'
import logo from '../logo.png'
import { Font, Space, Color } from '../style'
Expand Down Expand Up @@ -36,6 +38,10 @@ export function Overview() {
Welcome to <Text style={Font.highlight}>numic</Text>!
</Text>
<Text style={Font.text}>Running in {__DEV__ ? 'Debug' : 'Release'} Mode</Text>
<Text style={Font.title}>Animations</Text>
<Animation />
<Text style={Font.title}>Gestures</Text>
<Gesture />
</Screen>
)
}
6 changes: 3 additions & 3 deletions template/app/screen/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ export const Settings = observer(() => {
<Text style={Font.bold}>{translate('settingsLanguage', undefined, Data.language)}</Text>
<View style={styles.switch}>
<LanguageOption
name={readableLanguage[Language.en]}
name={readableLanguage[Language.en].local}
active={Data.language === Language.en}
onPress={() => Data.setLanguage(Language.en)}
/>
<LanguageOption
name={readableLanguage[Language.es]}
name={readableLanguage[Language.es].local}
active={Data.language === Language.es}
onPress={() => Data.setLanguage(Language.es)}
/>
<LanguageOption
name={readableLanguage[Language.zh]}
name={readableLanguage[Language.zh].local}
active={Data.language === Language.zh}
onPress={() => Data.setLanguage(Language.zh)}
/>
Expand Down
2 changes: 1 addition & 1 deletion template/app/test/app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ test('App renders without crashing.', async () => {
title = app.getByLabelText(Label.screenTitle)
expect(title).toHaveTextContent('Settings')
// Switch language.
const spanishButton = app.getByText(readableLanguage[Language.es])
const spanishButton = app.getByText(readableLanguage[Language.es].local)
fireEvent.press(spanishButton)
title = app.getByLabelText(Label.screenTitle)
expect(title).toHaveTextContent('Ajustes')
Expand Down
9 changes: 4 additions & 5 deletions template/app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"extends": "@react-native/typescript-config/tsconfig.json",
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "Bundler"
}
"extends": "@react-native/typescript-config/tsconfig.json",
"compilerOptions": {
"module": "ESNext"
}
}

2 changes: 1 addition & 1 deletion template/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"react": "^18.3.1",
"react-native": "^0.75.0"
"react-native": "^0.75.1"
},
"type": "module",
"devDependencies": {
Expand Down

0 comments on commit 4496b36

Please sign in to comment.