Skip to content

Commit a998fec

Browse files
committed
[wip] add react-strict-animated library
Note: still working on the build/package structure so not quite ready for review yet This introduces a new package to the RSD repo that provides a subset of React Native's API that works on both web and native, and built with integration of react-strict-dom in mind. The native implementation is largely a thin passthrough to the proper Animated API and some settings pre-configured (such as `useAnimatedDriver` always being enabled). The web side is a new Animated implementation that ends up being driven by the Web Animations API.
1 parent 8e0de4f commit a998fec

29 files changed

+2742
-18
lines changed

flow-typed/environments/web-animations.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ type DocumentTimelineOptions = {|
6767
|};
6868

6969
type EffectTiming = {|
70+
delay: number,
7071
direction: PlaybackDirection,
72+
duration: number | string,
7173
easing: string,
7274
fill: FillMode,
7375
iterations: number,
@@ -81,14 +83,14 @@ type GetAnimationsOptions = {|
8183

8284
type KeyframeAnimationOptions = {|
8385
...KeyframeEffectOptions,
84-
id: string,
85-
timeline: AnimationTimeline | null,
86+
id?: string,
87+
timeline?: AnimationTimeline | null,
8688
|};
8789

8890
type KeyframeEffectOptions = {|
89-
...EffectTiming,
90-
composite: CompositeOperation,
91-
pseudoElement: string | null,
91+
...Partial<EffectTiming>,
92+
composite?: CompositeOperation,
93+
pseudoElement?: string | null,
9294
|};
9395

9496
type Keyframe = {

package-lock.json

Lines changed: 37 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/animated/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Meta Platforms, Inc. and affiliates.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/animated/package.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "react-strict-animated",
3+
"version": "0.0.1",
4+
"description": "A subset of React Native's Animated API supported on web and native.",
5+
"exports": {
6+
".": {
7+
"react-native": {
8+
"types": "./dist/native/index.d.ts",
9+
"default": "./dist/native/index.js"
10+
},
11+
"default": {
12+
"types": "./dist/web/index.d.ts",
13+
"default": "./dist/web/index.js"
14+
}
15+
},
16+
"./package.json": "./package.json"
17+
},
18+
"files": [
19+
"dist/*",
20+
"LICENSE",
21+
"package.json"
22+
],
23+
"sideEffects": false,
24+
"scripts": {
25+
"build": "rollup --config ./tools/rollup.config.mjs",
26+
"clean": "del-cli \"./dist/*\"",
27+
"prebuild": "npm run clean && generate-types -i src/ -o dist"
28+
},
29+
"dependencies": {
30+
"react-strict-dom": "*"
31+
},
32+
"devDependencies": {
33+
"@rollup/plugin-babel": "^6.0.4",
34+
"@rollup/plugin-commonjs": "^26.0.1",
35+
"@rollup/plugin-node-resolve": "^15.2.3",
36+
"react": "~19.0.0",
37+
"react-dom": "~19.0.0",
38+
"rollup": "^4.22.4"
39+
},
40+
"peerDependencies": {
41+
"react": "^19.0.0",
42+
"react-dom": "^19.0.0",
43+
"react-native": ">=0.79.5"
44+
}
45+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
*/
9+
10+
/* eslint-disable no-unreachable */
11+
12+
import type { AnimatedStyleValue } from '../shared/SharedAnimatedTypes';
13+
import type { Text, View } from 'react-native';
14+
import type { ImageProps } from 'react-native/Libraries/Image/ImageProps';
15+
import type { html } from 'react-strict-dom';
16+
17+
import * as React from 'react';
18+
import { Animated } from 'react-native';
19+
20+
import { compat, css } from 'react-strict-dom';
21+
22+
const styles = css.create({
23+
defaults: {
24+
boxSizing: 'content-box',
25+
position: 'static'
26+
}
27+
});
28+
29+
export component AnimatedDiv(
30+
animatedStyle?: AnimatedStyleValue<Animated.Node>,
31+
children?: React.Node,
32+
ref?: React.RefSetter<React.RefOf<html.div>>,
33+
...htmlProps: Omit<React.PropsOf<html.div>, 'children'>
34+
) {
35+
return (
36+
// $FlowFixMe[prop-missing] - RSD missing ref type on compat.native API
37+
<compat.native
38+
{...htmlProps}
39+
as="div"
40+
ref={ref}
41+
style={[styles.defaults, htmlProps.style]}
42+
>
43+
{(nativeProps: React.PropsOf<View>) => {
44+
return (
45+
<Animated.View
46+
{...nativeProps}
47+
style={[nativeProps.style, animatedStyle]}
48+
>
49+
{nativeProps.children}
50+
</Animated.View>
51+
);
52+
}}
53+
</compat.native>
54+
);
55+
}
56+
57+
export component AnimatedSpan(
58+
animatedStyle: AnimatedStyleValue<Animated.Node>,
59+
children?: React.Node,
60+
ref?: React.RefSetter<React.RefOf<html.span>>,
61+
...htmlProps: Omit<React.PropsOf<html.span>, 'children'>
62+
) {
63+
return (
64+
// $FlowFixMe[prop-missing] - RSD missing ref type on compat.native API
65+
<compat.native
66+
{...htmlProps}
67+
as="span"
68+
ref={ref}
69+
style={[styles.defaults, htmlProps.style]}
70+
>
71+
{(nativeProps: React.PropsOf<Text>) => {
72+
return (
73+
<Animated.Text
74+
{...nativeProps}
75+
style={[nativeProps.style, animatedStyle]}
76+
>
77+
{children}
78+
</Animated.Text>
79+
);
80+
}}
81+
</compat.native>
82+
);
83+
}
84+
85+
export component AnimatedImg(
86+
animatedStyle: AnimatedStyleValue<Animated.Node>,
87+
ref?: React.RefSetter<React.RefOf<html.img>>,
88+
...htmlProps: React.PropsOf<html.img>
89+
) {
90+
return (
91+
// $FlowFixMe[prop-missing] - RSD missing ref type on compat.native API
92+
<compat.native
93+
{...htmlProps}
94+
as="img"
95+
ref={ref}
96+
style={[styles.defaults, htmlProps.style]}
97+
>
98+
{(nativeProps: ImageProps) => {
99+
return (
100+
<Animated.Image
101+
{...nativeProps}
102+
style={[nativeProps.style, animatedStyle]}
103+
/>
104+
);
105+
}}
106+
</compat.native>
107+
);
108+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
*/
9+
10+
/* eslint-disable no-unreachable */
11+
12+
import type {
13+
InterpolationConfig,
14+
ParallelConfig,
15+
SpringAnimationConfig,
16+
TimingAnimationConfig
17+
} from '../shared/SharedAnimatedTypes';
18+
import type { CompositeAnimation } from 'react-native/Libraries/Animated/Animated';
19+
20+
import { AnimatedDiv, AnimatedImg, AnimatedSpan } from './components';
21+
22+
import {
23+
Animated,
24+
useAnimatedValue as rn_useAnimatedValue
25+
} from 'react-native';
26+
27+
export type AnimatedValue = Animated.Value;
28+
export type {
29+
CompositeAnimation,
30+
SpringAnimationConfig,
31+
TimingAnimationConfig,
32+
InterpolationConfig
33+
};
34+
35+
function useAnimatedValue(initialValue: number): Animated.Value {
36+
return rn_useAnimatedValue(initialValue, { useNativeDriver: true });
37+
}
38+
39+
export const Animation = {
40+
useValue: useAnimatedValue,
41+
42+
parallel: (
43+
animations: Array<CompositeAnimation>,
44+
config?: ParallelConfig
45+
): CompositeAnimation => {
46+
return Animated.parallel(animations, config);
47+
},
48+
sequence: (animations: Array<CompositeAnimation>): CompositeAnimation => {
49+
return Animated.sequence(animations);
50+
},
51+
delay: (time: number): CompositeAnimation => {
52+
return Animated.delay(time);
53+
},
54+
55+
timing: (
56+
value: Animated.Value,
57+
config: TimingAnimationConfig
58+
): CompositeAnimation => {
59+
return Animated.timing(value, { ...config, useNativeDriver: true });
60+
},
61+
spring: (
62+
value: Animated.Value,
63+
config: SpringAnimationConfig
64+
): CompositeAnimation => {
65+
return Animated.spring(value, { ...config, useNativeDriver: true });
66+
},
67+
68+
interpolate: <TOutput: string | number>(
69+
value: Animated.Node,
70+
config: InterpolationConfig<TOutput>
71+
): Animated.Node => {
72+
return new Animated.Interpolation(value, config);
73+
}
74+
};
75+
76+
export const animated = {
77+
div: AnimatedDiv,
78+
img: AnimatedImg,
79+
span: AnimatedSpan
80+
};

0 commit comments

Comments
 (0)