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

add react-native-animate (#8) #11

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
7 changes: 7 additions & 0 deletions .jvmopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-server
-Xms512M
-Xmx3G
-Xss1M
-XX:NewRatio=8
#-Dio.netty.tryReflectionSetAccessible=true
#--add-opens java.base/jdk.internal.misc=ALL-UNNAMED
22 changes: 22 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,28 @@ lazy val `react-native` = project
}
)

/** Note: This can't use scalajs-bundler (at least I don't know how),
* so we run yarn ourselves with an external package.json.
*/
lazy val `react-native-animations` = project
.enablePlugins(ScalablyTypedConverterExternalNpmPlugin)
.configure(baseSettings)
.settings(
scalaJSLinkerConfig := scalaJSLinkerConfig.value.withModuleKind(ModuleKind.CommonJSModule),
scalaJSUseMainModuleInitializer := false,
/* ScalablyTypedConverterExternalNpmPlugin requires that we define how to install node dependencies and where they are */
externalNpm := {
Process("yarn", baseDirectory.value).!
baseDirectory.value
},
stFlavour := Flavour.Japgolly,
stStdlib := List("es5"),
run := {
(Compile / fastOptJS).value
Process("expo start", baseDirectory.value).!
}
)

// specify versions for all of reacts dependencies to compile less since we have many demos here
lazy val reactNpmDeps: Project => Project =
_.settings(
Expand Down
11 changes: 11 additions & 0 deletions react-native-animations/.expo-shared/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
> Why do I have a folder named ".expo-shared" in my project?
The ".expo-shared" folder is created when running commands that produce state that is intended to be shared with all developers on the project. For example, "npx expo-optimize".

> What does the "assets.json" file contain?
The "assets.json" file describes the assets that have been optimized through "expo-optimize" and do not need to be processed again.

> Should I commit the ".expo-shared" folder?
Yes, you should share the ".expo-shared" folder with your collaborators.
1 change: 1 addition & 0 deletions react-native-animations/.expo-shared/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
19 changes: 19 additions & 0 deletions react-native-animations/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import {Text, View} from 'react-native';

let app;
if (__DEV__) {
app = require("./target/scala-2.13/react-native-animations-fastopt.js").app;
} else {
// module.exports = () => {
// return <View style={{flex: 1, justifyContent: "center", alignItems: "center"}}>
// <Text style={{textAlign: "center"}}>
// Scala.js opt mode has not been enabled in App.js, please uncomment the code for it.
// </Text>
// </View>;
// }

// uncomment the following line to enable opt building
// app = require("./target/scala-2.13/react-native-animations-opt.js").app;
}
export default app;
34 changes: 34 additions & 0 deletions react-native-animations/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"expo": {
"name": "react-native-animations",
"description": "A template setting up Expo with Slinky and Scala.js",
"slug": "react-native-animations",
"privacy": "public",
"sdkVersion": "39.0.0",
"platforms": [
"ios",
"android",
"web"
],
"packagerOpts": {
"config": "metro.config.js"
},
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}
Binary file added react-native-animations/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added react-native-animations/assets/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions react-native-animations/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
14 changes: 14 additions & 0 deletions react-native-animations/fastopt-noparse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var transformer = require('metro-react-native-babel-transformer')

module.exports.transform = function ({ src, filename, options }) {
options = options || {};
if (filename.indexOf('fastopt') > -1) {
return {
code: src,
filename
}
}
else {
return transformer.transform({ src, filename, options });
}
}
11 changes: 11 additions & 0 deletions react-native-animations/metro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
transformer: {
babelTransformerPath: require("path").resolve("./fastopt-noparse.js"),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
};
36 changes: 36 additions & 0 deletions react-native-animations/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"license": "MIT",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.10",
"@react-navigation/drawer": "^5.12.4",
"@react-navigation/native": "^5.9.3",
"expo": "^39.0.5",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-39.0.1.tar.gz",
"react-native-gesture-handler": "^1.10.3",
"react-native-reanimated": "^2.0.0",
"react-native-screens": "^2.18.1",
"typescript": "^4.1.5"
},
"devDependencies": {
"@types/node": "^13.13.45",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.1",
"@types/react-native": "^0.63.50",
"@types/react-router-native": "^5.1.0",
"babel-preset-expo": "^8.3.0",
"expo-cli": "^4.1.6",
"react-native-web": "^0.15.0",
"react-proxy": "^1.1.8"
},
"private": true
}
132 changes: 132 additions & 0 deletions react-native-animations/src/main/scala/demo/AnimatedIconApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package demo

import demo.facade.AnimatedView
import japgolly.scalajs.react.component.ScalaFn.Component
import japgolly.scalajs.react.{CallbackTo, CtorType, ScalaFnComponent}
import typings.react.mod.useState
import typings.reactNative.components.{TouchableWithoutFeedback, View}
import typings.reactNative.mod.Animated.{InterpolationConfigType, SpringAnimationConfig, TimingAnimationConfig}
import typings.reactNative.mod._
import typings.reactNative.reactNativeStrings

import scala.scalajs.js

// https://cheesecakelabs.com/blog/first-steps-with-react-native-animations/
object AnimatedIconApp {

private def commonStyle: ViewStyle = ViewStyle()
.setWidth("60%")
.setBorderRadius(10)
.setBackgroundColor("black")

val component: Component[Unit, CtorType.Nullary] = ScalaFnComponent[Unit] { _ =>
val js.Tuple2(activated, setActivated) = useState(false)
val js.Tuple2(animation, _) = useState(new Animated.Value(0))
val js.Tuple2(jsAnimation, _) = useState(new Animated.Value(0))
val js.Tuple2(rotation, _) = useState(new Animated.Value(0))

val startAnimation = () => {
val toValue = if (activated) 0 else 1
setActivated(!activated)
Animated
.parallel(
js.Array(
Animated
.timing(
animation,
TimingAnimationConfig(
toValue,
true
).setDuration(300)
),
Animated
.spring(
rotation,
SpringAnimationConfig(
toValue,
true
).setFriction(2)
.setTension(140)
),
Animated.timing(
jsAnimation,
TimingAnimationConfig(
toValue,
false
).setDuration(300)
)
)
)
.start()
}

val upper = js.Array(
js.Dynamic.literal(
translateY = animation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array(0, 25)))
.asInstanceOf[js.Dynamic]
),
js.Dynamic.literal(
rotate = rotation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array("0deg", "-45deg")))
.asInstanceOf[js.Dynamic]
)
)

val middle = jsAnimation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array(10, 0)))
.asInstanceOf[js.Dynamic]

val lower = js.Array(
js.Dynamic.literal(
translateY = animation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array(0, -25)))
.asInstanceOf[TranslateYTransform]
),
js.Dynamic.literal(
rotate = rotation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array("0deg", "45deg")))
.asInstanceOf[RotateTransform]
)
)

View.style(
ViewStyle()
.setFlex(1)
.setBackgroundColor("#fff")
.setAlignItems(FlexAlignType.center)
.setJustifyContent(reactNativeStrings.center)
)(
TouchableWithoutFeedback().onPress((_) => CallbackTo[Unit](startAnimation()))(
AnimatedView.component(
ViewProps()
.setStyle(
ViewStyle()
.setDisplay(reactNativeStrings.flex)
.setFlexDirection(reactNativeStrings.column)
.setJustifyContent(reactNativeStrings.`space-between`)
.setAlignItems(reactNativeStrings.center)
.setWidth(100)
.setHeight(100)
.setPaddingVertical(20)
.setBorderRadius(50)
.setBackgroundColor(jsAnimation
.interpolate(InterpolationConfigType(js.Array(0, 1), js.Array("green", "red")))
.asInstanceOf[OpaqueColorValue])
)
)(
AnimatedView.component(
ViewProps().setStyle(commonStyle.setHeight(10).set("transform", upper))
)(),
AnimatedView.component(
ViewProps().setStyle(commonStyle.set("height", middle))
)(),
AnimatedView.component(
ViewProps().setStyle(commonStyle.setHeight(10).set("transform", lower))
)()
)
)
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package demo

import demo.facade.AnimatedView
import japgolly.scalajs.react.component.ScalaFn.Component
import japgolly.scalajs.react.{CallbackTo, CtorType, ScalaFnComponent}
import typings.react.mod.useState
import typings.reactNative.components.{TouchableWithoutFeedback, View}
import typings.reactNative.mod.Animated.TimingAnimationConfig
import typings.reactNative.mod.{Animated, FlexAlignType, ViewProps, ViewStyle}
import typings.reactNative.reactNativeStrings

import scala.scalajs.js

object AnimatedIconEasyApp {

private def commonStyle: ViewStyle = ViewStyle()
.setWidth("60%")
.setHeight(10)
.setBorderRadius(10)
.setBackgroundColor("black")

val component: Component[Unit, CtorType.Nullary] = ScalaFnComponent[Unit] { _ =>
val js.Tuple2(activated, setActivated) = useState(false)
val js.Tuple2(upperAnimation, _) = useState(new Animated.Value(0))
val js.Tuple2(lowerAnimation, _) = useState(new Animated.Value(0))

val startAnimation = () => {
setActivated(!activated)

Animated
.timing(
upperAnimation,
TimingAnimationConfig(
if (activated) 0 else 25,
true
).setDuration(300)
)
.start()

Animated
.timing(
lowerAnimation,
TimingAnimationConfig(
if (activated) 0 else -25,
true
).setDuration(300)
)
.start()
}

View.style(
ViewStyle()
.setFlex(1)
.setBackgroundColor("#fff")
.setAlignItems(FlexAlignType.center)
.setJustifyContent(reactNativeStrings.center)
)(
TouchableWithoutFeedback().onPress((_) => CallbackTo[Unit](startAnimation()))(
View.style(
ViewStyle()
.setDisplay(reactNativeStrings.flex)
.setFlexDirection(reactNativeStrings.column)
.setJustifyContent(reactNativeStrings.`space-between`)
.setAlignItems(reactNativeStrings.center)
.setWidth(100)
.setHeight(100)
.setPaddingVertical(20)
.setBorderRadius(50)
.setBackgroundColor("green")
)(
AnimatedView.component(
ViewProps().setStyle(commonStyle.set("transform", js.Array(js.Dynamic.literal(translateY = upperAnimation))))
)(),
AnimatedView.component(
ViewProps().setStyle(commonStyle)
)(),
AnimatedView.component(
ViewProps().setStyle(commonStyle.set("transform", js.Array(js.Dynamic.literal(translateY = lowerAnimation))))
)()
)
)
)
}

}
Loading