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: add web support #1107

Merged
merged 15 commits into from
Oct 22, 2023
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ While the packager is running and you have an iOS device or simulator connected
npm run run:ios
```

### Developing on Web

First, you have to install all dependencies:

```
yarn
```

After that, you have to build the library. You have to do that each time you want to see the changes in the example app, as currently, we don't support hot reloading in the demo app.

```
yarn setup
```

Finally, you can run the demo. Then you can go to the link printed in the terminal to see the demo.

```
yarn paper:web
```

### Style & Linting

This codebase adheres to the [Airbnb Styleguide](https://github.com/airbnb/javascript) and is
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ Go to your ios folder and run:
pod install
```

### Web

- Install `lottie-react-native` (latest):

```
yarn add lottie-react-native
```

- Add dependencies for web players:

```
yarn add @dotlottie/react-player @lottiefiles/react-lottie-player
```

### Windows (React Native >= 0.63)

<details>
Expand Down
4 changes: 4 additions & 0 deletions apps/paper/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module.exports = {
root: true,
extends: '@react-native',
parser: '@babel/eslint-parser',
parserOptions: {
requireConfigFile: false,
},
};
File renamed without changes.
8 changes: 8 additions & 0 deletions apps/paper/index.web.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {AppRegistry} from 'react-native';
import LottieAnimatedExample from './src/LottieAnimatedExample';

AppRegistry.registerComponent('example', () => LottieAnimatedExample);

AppRegistry.runApplication('example', {
rootTag: document.getElementById('root'),
});
8 changes: 4 additions & 4 deletions apps/paper/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ PODS:
- React-jsinspector (0.72.3)
- React-logger (0.72.3):
- glog
- react-native-slider (4.4.2):
- react-native-slider (4.4.3):
- React-Core
- React-NativeModulesApple (0.72.3):
- hermes-engine
Expand Down Expand Up @@ -491,7 +491,7 @@ PODS:
- React-jsi (= 0.72.3)
- React-logger (= 0.72.3)
- React-perflogger (= 0.72.3)
- RNCPicker (2.4.10):
- RNCPicker (2.5.0):
- React-Core
- SocketRocket (0.6.1)
- Yoga (1.14.0)
Expand Down Expand Up @@ -707,7 +707,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 59d1eb03af7d30b7d66589c410f13151271e8006
React-jsinspector: b511447170f561157547bc0bef3f169663860be7
React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4
React-NativeModulesApple: c57f3efe0df288a6532b726ad2d0322a9bf38472
React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5
React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17
Expand All @@ -725,7 +725,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: 837c1bebd2f84572db17698cd702ceaf585b0d9a
React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3
ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9
RNCPicker: 0bc2f0a29abcca7b7ed44a2d036aac9ab6d25700
RNCPicker: 32ca102146bc7d34a8b93a998d9938d9f9ec7898
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
35 changes: 31 additions & 4 deletions apps/paper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,59 @@
"android": "react-native run-android",
"build:android": "cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a",
"ios": "bundle install && pod install --project-directory=ios && react-native run-ios",
"web": "webpack serve",
"start": "react-native start",
"test": "jest",
"lint": "eslint .",
"vscpp": "start windows/cppwinrt/Example.sln",
"vssharp": "start windows/csharp/Example.sln"
},
"dependencies": {
"@dotlottie/react-player": "^1.6.1",
"@lottiefiles/react-lottie-player": "^3.5.3",
"@react-native-community/slider": "^4.4.2",
"@react-native-picker/picker": "^2.4.10",
"lottie-react-native": "workspace:*",
"react": "18.2.0",
"react-dom": "^18.2.0",
"react-native": "0.72.3",
"react-native-dropdown-picker": "^5.4.6",
"react-native-windows": "0.71.18"
"react-native-web": "^0.19.8",
"react-native-windows": "0.71.18",
"react-scripts": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/core": "^7.22.17",
"@babel/preset-env": "^7.22.15",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.22.15",
"@babel/runtime": "^7.22.5",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.9",
"@react-native/metro-config": "0.72.9",
"@tsconfig/react-native": "^3.0.0",
"@types/jest": "^29.5.2",
"@types/react": "^18.2.12",
"@types/react-test-renderer": "^18.0.0",
"babel-loader": "^9.1.3",
"babel-plugin-react-native-web": "^0.19.8",
"eslint": "^8.43.0",
"metro-react-native-babel-preset": "0.76.7",
"typescript": "^5.1.3"
"typescript": "^5.1.3",
"url-loader": "^4.1.1",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
27 changes: 27 additions & 0 deletions apps/paper/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Demo Project</title>
<style>
html,
body {
height: 100%;
}
body {
overflow: hidden;
}
#root {
display: flex;
height: 100%;
max-width: 750px;
margin: 0 auto;
background-color: #f5f5f5;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
</html>
20 changes: 13 additions & 7 deletions apps/paper/src/ExamplePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {Platform} from 'react-native';
import {Platform, View} from 'react-native';
import {Picker} from '@react-native-picker/picker';
import {Example} from './utils';

Expand All @@ -10,18 +10,24 @@ interface Props {
}

export const ExamplePicker = ({example, examples, onChange}: Props) => {
const webStyle = {
height: 50,
borderRadius: 10,
paddingHorizontal: 10,
paddingVertical: 5,
};

const viewStyle = {
marginBottom: Platform.OS === 'ios' ? -30 : 0,
};

return (
<Picker
selectedValue={example.name}
onValueChange={(value: string) => {
onChange(examples.find(ex => ex.name === value)!);
}}
style={{
marginBottom: Platform.select({
ios: -30,
android: 0,
}),
}}>
style={Platform.OS === 'web' ? webStyle : viewStyle}>
{examples.map(ex => (
<Picker.Item key={ex.name} label={ex.name} value={ex.name} />
))}
Expand Down
5 changes: 5 additions & 0 deletions apps/paper/src/LottieAnimatedExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const LottieAnimatedExample = () => {
console.log('Animation failure ', message);
};

const onAnimationLoop = () => {
console.log('Animation looped');
};

const onPlayPress = () => {
if (isPlaying) {
anim.current?.pause();
Expand Down Expand Up @@ -103,6 +107,7 @@ const LottieAnimatedExample = () => {
hardwareAccelerationAndroid={true}
onAnimationFailure={onAnimationFailure}
onAnimationFinish={onAnimationFinish}
onAnimationLoop={onAnimationLoop}
enableMergePathsAndroidForKitKatAndAbove
renderMode={renderMode}
resizeMode={'contain'}
Expand Down
Binary file added apps/paper/src/animations/animation_test.lottie
Binary file not shown.
3 changes: 0 additions & 3 deletions apps/paper/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ export const EXAMPLES = [
makeExample('Pin Jump', () => require('./animations/PinJump.json')),
makeExample('Twitter Heart', () => require('./animations/TwitterHeart.json')),
makeExample('Watermelon', () => require('./animations/Watermelon.json')),
makeExample('Motion Corpse', () =>
require('./animations/MotionCorpse-Jrcanest.json'),
),
makeExample('Remote load', () => ({
uri: 'https://raw.githubusercontent.com/lottie-react-native/lottie-react-native/master/apps/paper/src/animations/Watermelon.json',
})),
Expand Down
88 changes: 88 additions & 0 deletions apps/paper/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const path = require('path');

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const appDirectory = path.resolve(__dirname);

const {presets} = require(`${appDirectory}/babel.config.js`);
const {resolver} = require('./metro.config.js');

const compileNodeModules = ['react-native-dropdown-picker', 'react-native'].map(
moduleName => path.resolve(appDirectory, `node_modules/${moduleName}`),
);

const babelLoaderConfiguration = {
test: /\.js$|tsx?$/,
include: [
path.resolve(__dirname, 'index.web.js'),
path.resolve(__dirname, 'src'),
...compileNodeModules,
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets,
plugins: ['react-native-web'],
},
},
};

module.exports = {
mode: 'development',
entry: {
app: './index.web.js',
},
stats: {warnings: false},
output: {
path: path.resolve(appDirectory, 'dist'),
publicPath: '/',
filename: 'output.bundle.js',
},
resolve: {
extensions: [
'.web.tsx',
'.web.ts',
'.tsx',
'.ts',
'.web.js',
'.js',
'.lottie',
'.json',
],
alias: {
...resolver.extraNodeModules,
'react-native': 'react-native-web',
},
symlinks: false,
modules: ['node_modules', 'src'],
},
module: {
rules: [
babelLoaderConfiguration,
{
test: /\.lottie$/,
type: 'asset/resource',
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
watch: true,
watchOptions: {
followSymlinks: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
// See: https://github.com/necolas/react-native-web/issues/349
__DEV__: JSON.stringify(true),
}),
],
};
Loading