yeet
This commit is contained in:
712
node_modules/react-native/Libraries/Animated/examples/demo.html
generated
vendored
Normal file
712
node_modules/react-native/Libraries/Animated/examples/demo.html
generated
vendored
Normal file
@ -0,0 +1,712 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
|
||||
<title>Animated</title>
|
||||
<link href="./style.css" rel="stylesheet" type="text/css">
|
||||
<script src="https://fb.me/react-with-addons-0.13.3.js"></script>
|
||||
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
|
||||
<script src="../release/dist/animated.js"></script>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<script>
|
||||
var TOTAL_EXAMPLES = 0;
|
||||
function example() {
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
var last = scripts[scripts.length - 2];
|
||||
last.className = 'Example' + (++TOTAL_EXAMPLES);
|
||||
}
|
||||
</script>
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
|
||||
var HorizontalPan = function(anim, config) {
|
||||
config = config || {};
|
||||
return {
|
||||
onMouseDown: function(event) {
|
||||
anim.stopAnimation(startValue => {
|
||||
config.onStart && config.onStart();
|
||||
var startPosition = event.clientX;
|
||||
var lastTime = Date.now();
|
||||
var lastPosition = event.clientX;
|
||||
var velocity = 0;
|
||||
|
||||
function updateVelocity(event) {
|
||||
var now = Date.now();
|
||||
if (event.clientX === lastPosition || now === lastTime) {
|
||||
return;
|
||||
}
|
||||
velocity = (event.clientX - lastPosition) / (now - lastTime);
|
||||
lastTime = now;
|
||||
lastPosition = event.clientX;
|
||||
}
|
||||
|
||||
var moveListener, upListener;
|
||||
window.addEventListener('mousemove', moveListener = (event) => {
|
||||
var value = startValue + (event.clientX - startPosition);
|
||||
anim.setValue(value);
|
||||
updateVelocity(event);
|
||||
});
|
||||
window.addEventListener('mouseup', upListener = (event) => {
|
||||
updateVelocity(event);
|
||||
window.removeEventListener('mousemove', moveListener);
|
||||
window.removeEventListener('mouseup', upListener);
|
||||
config.onEnd && config.onEnd({velocity});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var EXAMPLE_COUNT = 0;
|
||||
function examplify(Component) {
|
||||
if (EXAMPLE_COUNT) {
|
||||
var previousScript = document.getElementsByClassName('Example' + EXAMPLE_COUNT)[0].innerText;
|
||||
} else {
|
||||
var previousScript = `
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0), // ignore
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div // ignore
|
||||
style={{left: this.state.anim}} // ignore
|
||||
className="circle"
|
||||
/>
|
||||
);
|
||||
},
|
||||
}));
|
||||
`;
|
||||
}
|
||||
|
||||
var script = document.getElementsByClassName('Example' + ++EXAMPLE_COUNT)[0];
|
||||
|
||||
var previousLines = {};
|
||||
previousScript.split(/\n/g).forEach(line => { previousLines[line.trim()] = 1; });
|
||||
var code = document.createElement('div');
|
||||
script.parentNode.insertBefore(code, script);
|
||||
|
||||
var Example = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<div className="code">
|
||||
<div className="example">
|
||||
<button
|
||||
className="reset"
|
||||
onClick={() => this.forceUpdate()}>
|
||||
Reset
|
||||
</button>
|
||||
<Component key={Math.random()} />
|
||||
</div>
|
||||
<hr />
|
||||
<pre>{'React.createClass({'}</pre>
|
||||
{script.innerText
|
||||
.trim()
|
||||
.split(/\n/g)
|
||||
.slice(1, -1)
|
||||
.map(line =>
|
||||
<pre
|
||||
className={!previousLines[line.trim()] && 'highlight'}>
|
||||
{line}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
<pre>{'});'}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
React.render(<Example />, code);
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<h1>Animated</h1>
|
||||
<p>Animations have for a long time been a weak point of the React ecosystem. The <code>Animated</code> library aims at solving this problem. It embraces the declarative aspect of React and obtains performance by using raw DOM manipulation behind the scenes instead of the usual diff.</p>
|
||||
|
||||
<h2>Animated.Value</h2>
|
||||
|
||||
<p>The basic building block of this library is <code>Animated.Value</code>. This is a variable that's going to drive the animation. You use it like a normal value in <code>style</code> attribute. Only animated components such as <code>Animated.div</code> will understand it.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(100),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{left: this.state.anim}}
|
||||
className="circle"
|
||||
/>
|
||||
);
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>setValue</h2>
|
||||
|
||||
<p>As you can see, the value is being used inside of <code>render()</code> as you would expect. However, you don't call <code>setState()</code> in order to update the value. Instead, you can call <code>setValue()</code> directly on the value itself. We are using a form of data binding.</p>
|
||||
|
||||
<p>The <code>Animated.div</code> component when rendered tracks which animated values it received. This way, whenever that value changes, we don't need to re-render the entire component, we can directly update the specific style attribute that changed.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{left: this.state.anim}}
|
||||
className="circle"
|
||||
onClick={this.handleClick}>
|
||||
Click
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
this.state.anim.setValue(400);
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>Animated.timing</h2>
|
||||
|
||||
<p>Now that we understand how the system works, let's play with some animations! The hello world of animations is to move the element somewhere else. To do that, we're going to animate the value from the current value 0 to the value 400.</p>
|
||||
|
||||
<p>On every frame (via <code>requestAnimationFrame</code>), the <code>timing</code> animation is going to figure out the new value based on the current time, update the animated value which in turn is going to update the corresponding DOM node.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{left: this.state.anim}}
|
||||
className="circle"
|
||||
onClick={this.handleClick}>
|
||||
Click
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
Animated.timing(this.state.anim, {toValue: 400}).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>Interrupt Animations</h2>
|
||||
|
||||
<p>As a developer, the mental model is that most animations are fire and forget. When the user presses the button, you want it to shrink to 80% and when she releases, you want it to go back to 100%.</p>
|
||||
|
||||
<p>There are multiple challenges to implement this correctly. You need to stop the current animation, grab the current value and restart an animation from there. As this is pretty tedious to do manually, <code>Animated</code> will do that automatically for you.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(1),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{transform: [{scale: this.state.anim}]}}
|
||||
className="circle"
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseUp={this.handleMouseUp}>
|
||||
Press
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleMouseDown: function() {
|
||||
Animated.timing(this.state.anim, { toValue: 0.8 }).start();
|
||||
},
|
||||
handleMouseUp: function() {
|
||||
Animated.timing(this.state.anim, { toValue: 1 }).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>Animated.spring</h2>
|
||||
|
||||
<p>Unfortunately, the <code>timing</code> animation doesn't feel good. The main reason is that no matter how far you are in the animation, it will trigger a new one with always the same duration.</p>
|
||||
|
||||
<p>The commonly used solution for this problem is to use the equation of a real-world spring. Imagine that you attach a spring to the target value, stretch it to the current value and let it go. The spring movement is going to be the same as the update.</p>
|
||||
|
||||
<p>It turns out that this model is useful in a very wide range of animations. I highly recommend you to always start with a <code>spring</code> animation instead of a <code>timing</code> animation. It will make your interface feels much better.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(1),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{transform: [{scale: this.state.anim}]}}
|
||||
className="circle"
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseUp={this.handleMouseUp}>
|
||||
Press
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleMouseDown: function() {
|
||||
Animated.spring(this.state.anim, { toValue: 0.8 }).start();
|
||||
},
|
||||
handleMouseUp: function() {
|
||||
Animated.spring(this.state.anim, { toValue: 1 }).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>interpolate</h2>
|
||||
|
||||
<p>It is very common to animate multiple attributes during the same animation. The usual way to implement it is to start a separate animation for each of the attribute. The downside is that you now have to manage a different state per attribute which is not ideal.</p>
|
||||
|
||||
<p>With <code>Animated</code>, you can use a single state variable and render it in multiple attributes. When the value is updated, all the places will reflect the change.</p>
|
||||
|
||||
<p>In the following example, we're going to model the animation with a variable where 1 means fully visible and 0 means fully hidden. We can pass it directly to the scale attribute as the ranges match. But for the rotation, we need to convert [0 ; 1] range to [260deg ; 0deg]. This is where <code>interpolate()</code> comes handy.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(1),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{
|
||||
transform: [
|
||||
{rotate: this.state.anim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['260deg', '0deg']
|
||||
})},
|
||||
{scale: this.state.anim},
|
||||
]
|
||||
}}
|
||||
className="circle"
|
||||
onClick={this.handleClick}>
|
||||
Click
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
Animated.spring(this.state.anim, {toValue: 0}).start();
|
||||
}
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>stopAnimation</h2>
|
||||
|
||||
<p>The reason why we can get away with not calling <code>render()</code> and instead modify the DOM directly on updates is because the animated values are <strong>opaque</strong>. In render, <strong>you cannot know the current value</strong>, which prevents you from being able to modify the structure of the DOM.</p>
|
||||
|
||||
<p><code>Animated</code> can offload the animation to a different thread (CoreAnimation, CSS transitions, main thread...) and we don't have a good way to know the real value. If you try to query the value then modify it, you are going to be out of sync and the result will look terrible.</p>
|
||||
|
||||
<p>There's however one exception: when you want to stop the current animation. You need to know where it stopped in order to continue from there. We cannot know the value synchronously so we give it via a callback in <code>stopAnimation</code>. It will not suffer from being out of sync since the animation is no longer running.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0)
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => this.handleClick(-1)}><</button>
|
||||
<Animated.div
|
||||
style={{
|
||||
transform: [
|
||||
{rotate: this.state.anim.interpolate({
|
||||
inputRange: [0, 4],
|
||||
outputRange: ['0deg', '360deg']
|
||||
})},
|
||||
],
|
||||
position: 'relative'
|
||||
}}
|
||||
className="circle"
|
||||
/>
|
||||
<button onClick={() => this.handleClick(+1)}>></button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleClick: function(delta) {
|
||||
this.state.anim.stopAnimation(value => {
|
||||
Animated.spring(this.state.anim, {
|
||||
toValue: Math.round(value) + delta
|
||||
}).start();
|
||||
});
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
|
||||
<h1>Gesture-based Animations</h1>
|
||||
|
||||
<p>Most animations libraries only deal with time-based animations. But, as we move to mobile, a lot of animations are also gesture driven. Even more problematic, they often switch between both modes: once the gesture is over, you start a time-based animation using the same interpolations.</p>
|
||||
|
||||
<p><code>Animated</code> has been designed with this use case in mind. The key aspect is that there are three distinct and separate concepts: inputs, value, output. The same value can be updated either from a time-based animation or a gesture-based one. Because we use this intermediate representation for the animation, we can keep the same rendering as output.</p>
|
||||
|
||||
<h2>HorizontalPan</h2>
|
||||
|
||||
<p>The code needed to drag elements around is very messy with the DOM APIs. On mousedown, you need to register a mousemove listener on window otherwise you may drop touches if you move too fast. <code>removeEventListener</code> takes the same arguments as <code>addEventListener</code> instead of an id like <code>clearTimeout</code>. It's also really easy to forget to remove a listener and have a leak. And finally, you need to store the current position and value at the beginning and update only compared to it.</p>
|
||||
|
||||
<p>We introduce a little helper called <code>HorizontalPan</code> which handles all this annoying code for us. It takes an <code>Animated.Value</code> as first argument and returns the event handlers required for it to work. We just have to bind this value to the <code>left</code> attribute and we're good to go.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{left: this.state.anim}}
|
||||
className="circle"
|
||||
{...HorizontalPan(this.state.anim)}>
|
||||
Drag
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>Animated.decay</h2>
|
||||
|
||||
<p>One of the big breakthrough of the iPhone is the fact that when you release the finger while scrolling, it will not abruptly stop but instead keep going for some time.</p>
|
||||
|
||||
<p>In order to implement this effect, we are using a second real-world simulation: an object moving on an icy surface. All it needs is two values: the current velocity and a deceleration coefficient. It is implemented by <code>Animated.decay</code>.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{left: this.state.anim}}
|
||||
className="circle"
|
||||
{...HorizontalPan(this.state.anim, {
|
||||
onEnd: this.handleEnd
|
||||
})}>
|
||||
Throw
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
handleEnd: function({velocity}) {
|
||||
Animated.decay(this.state.anim, {velocity}).start();
|
||||
}
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>Animation Chaining</h2>
|
||||
|
||||
<p>The target for an animation is usually a number but sometimes it is convenient to use another value as a target. This way, the first value will track the second. Using a spring animation, we can get a nice trailing effect.</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
var anims = [0, 1, 2, 3, 4].map((_, i) => new Animated.Value(0));
|
||||
Animated.spring(anims[0], {toValue: anims[1]}).start();
|
||||
Animated.spring(anims[1], {toValue: anims[2]}).start();
|
||||
Animated.spring(anims[2], {toValue: anims[3]}).start();
|
||||
Animated.spring(anims[3], {toValue: anims[4]}).start();
|
||||
return {
|
||||
anims: anims,
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.anims.map((anim, i) =>
|
||||
<Animated.div
|
||||
style={{left: anim}}
|
||||
className="circle"
|
||||
{...(i === 4 && HorizontalPan(anim, {
|
||||
onEnd: this.handleEnd
|
||||
}))}>
|
||||
{i === 4 && 'Drag'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleEnd: function({velocity}) {
|
||||
Animated.decay(this.state.anims[4], {velocity}).start();
|
||||
}
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<h2>addListener</h2>
|
||||
|
||||
<p>As I said earlier, if you track a spring</p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
var anims = [0, 1, 2, 3, 4].map((_, i) => new Animated.Value(i * 100));
|
||||
anims[0].addListener(this.handleChange);
|
||||
return {
|
||||
selected: null,
|
||||
anims: anims,
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.anims.map((anim, i) =>
|
||||
<Animated.div
|
||||
style={{
|
||||
left: anim,
|
||||
opacity: i === 0 || i === this.state.selected ? 1 : 0.5
|
||||
}}
|
||||
className="circle"
|
||||
{...(i === 0 && HorizontalPan(anim, { onEnd: this.handleEnd }))}>
|
||||
{i === 0 && 'Drag'}
|
||||
{i === this.state.selected && 'Selected!'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleChange: function({value}) {
|
||||
var selected = null;
|
||||
this.state.anims.forEach((_, i) => {
|
||||
if (i !== 0 && i * 100 - 50 < value && value <= i * 100 + 50) {
|
||||
selected = i;
|
||||
}
|
||||
});
|
||||
if (selected !== this.state.selected) {
|
||||
this.select(selected)
|
||||
}
|
||||
},
|
||||
select(selected) {
|
||||
this.setState({selected}, () => {
|
||||
this.state.anims.forEach((anim, i) => {
|
||||
if (i === 0) { return; }
|
||||
if (selected === i) {
|
||||
Animated.spring(anim, {toValue: this.state.anims[0]}).start();
|
||||
} else {
|
||||
Animated.spring(anim, {toValue: i * 100}).start();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
handleEnd() {
|
||||
this.select(null);
|
||||
Animated.spring(this.state.anims[0], {toValue: 0}).start();
|
||||
}
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
|
||||
<h2>Animated.sequence</h2>
|
||||
|
||||
<p>It is very common to animate </p>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anims: [0, 1, 2, 3, 4].map((_, i) => new Animated.Value(0.2)),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.anims.map((anim, i) =>
|
||||
<Animated.div
|
||||
style={{opacity: anim, position: 'relative'}}
|
||||
className="circle"
|
||||
onClick={i === 0 && this.handleClick}>
|
||||
{i === 0 && 'Click'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
this.state.anims.forEach(anim => { anim.setValue(0.2); });
|
||||
Animated.sequence(
|
||||
this.state.anims.map(anim => Animated.spring(anim, { toValue: 1 }))
|
||||
).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anims: [0, 1, 2, 3, 4].map((_, i) => new Animated.Value(0.2)),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.anims.map((anim, i) =>
|
||||
<Animated.div
|
||||
style={{opacity: anim, position: 'relative'}}
|
||||
className="circle"
|
||||
onClick={i === 0 && this.handleClick}>
|
||||
{i === 0 && 'Click'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
this.state.anims.forEach(anim => { anim.setValue(0.2); });
|
||||
Animated.stagger(
|
||||
100,
|
||||
this.state.anims.map(anim => Animated.spring(anim, { toValue: 1 }))
|
||||
).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anims: [0, 1, 2, 3, 4].map((_, i) => new Animated.Value(0.2)),
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.anims.map((anim, i) =>
|
||||
<Animated.div
|
||||
style={{opacity: anim, position: 'relative'}}
|
||||
className="circle"
|
||||
onClick={i === 0 && this.handleClick}>
|
||||
{i === 0 && 'Click'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleClick: function() {
|
||||
this.state.anims.forEach(anim => { anim.setValue(0.2); });
|
||||
Animated.sequence([
|
||||
Animated.parallel(
|
||||
this.state.anims.map(anim => Animated.spring(anim, { toValue: 1 }))
|
||||
),
|
||||
Animated.stagger(
|
||||
100,
|
||||
this.state.anims.map(anim => Animated.spring(anim, { toValue: 0.2 }))
|
||||
),
|
||||
]).start();
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0),
|
||||
};
|
||||
},
|
||||
handleClick: function() {
|
||||
var rec = () => {
|
||||
Animated.sequence([
|
||||
Animated.timing(this.state.anim, {toValue: -1, duration: 150}),
|
||||
Animated.timing(this.state.anim, {toValue: 1, duration: 150}),
|
||||
]).start(rec);
|
||||
};
|
||||
rec();
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Animated.div
|
||||
style={{
|
||||
left: this.state.anim.interpolate({
|
||||
inputRange: [-1, -0.5, 0.5, 1],
|
||||
outputRange: [0, 5, 0, 5]
|
||||
}),
|
||||
transform: [
|
||||
{rotate: this.state.anim.interpolate({
|
||||
inputRange: [-1, 1],
|
||||
outputRange: ['-10deg', '10deg']
|
||||
})}
|
||||
]
|
||||
}}
|
||||
className="circle"
|
||||
onClick={this.handleClick}>
|
||||
Click
|
||||
</Animated.div>
|
||||
);
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
<script type="text/jsx;harmony=true;stripTypes=true">
|
||||
examplify(React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
anim: new Animated.Value(0)
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div
|
||||
style={{overflow: 'scroll', height: 60}}
|
||||
onScroll={Animated.event([
|
||||
{target: {scrollLeft: this.state.anim}}
|
||||
])}>
|
||||
<div style={{width: 1000, height: 1}} />
|
||||
{[0, 1, 2, 3, 4].map(i =>
|
||||
<Animated.div
|
||||
style={{
|
||||
left: this.state.anim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, (i + 1)]
|
||||
}),
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
className="circle">
|
||||
{i === 4 && 'H-Scroll'}
|
||||
</Animated.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
}));
|
||||
</script><script>example();</script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
node_modules/react-native/Libraries/Animated/examples/pic1.jpg
generated
vendored
Normal file
BIN
node_modules/react-native/Libraries/Animated/examples/pic1.jpg
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
node_modules/react-native/Libraries/Animated/examples/pic2.jpg
generated
vendored
Normal file
BIN
node_modules/react-native/Libraries/Animated/examples/pic2.jpg
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
node_modules/react-native/Libraries/Animated/examples/pic3.jpg
generated
vendored
Normal file
BIN
node_modules/react-native/Libraries/Animated/examples/pic3.jpg
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
88
node_modules/react-native/Libraries/Animated/examples/style.css
generated
vendored
Normal file
88
node_modules/react-native/Libraries/Animated/examples/style.css
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
html, h1, h2 {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.circle {
|
||||
margin: 2px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
box-shadow: 0 1px 2px #999;
|
||||
text-shadow: 0 1px 2px #999;
|
||||
background-image: url(pic1.jpg);
|
||||
background-size: cover;
|
||||
line-height: 80px;
|
||||
vertical-align: bottom;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.circle:nth-child(2) {
|
||||
background-image: url(pic2.jpg);
|
||||
}
|
||||
|
||||
.circle:nth-child(3) {
|
||||
background-image: url(pic3.jpg);
|
||||
}
|
||||
|
||||
div.code {
|
||||
box-shadow: 0 1px 2px #999;
|
||||
width: 600px;
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
div.code .reset {
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.code pre {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid #D9D9D9;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.example > span {
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.example {
|
||||
position: relative;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.code pre {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: rgb(228, 254, 253);
|
||||
}
|
2
node_modules/react-native/Libraries/Animated/release/.npmignore
generated
vendored
Normal file
2
node_modules/react-native/Libraries/Animated/release/.npmignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/dist/
|
||||
/node_modules/
|
155
node_modules/react-native/Libraries/Animated/release/gulpfile.js
generated
vendored
Normal file
155
node_modules/react-native/Libraries/Animated/release/gulpfile.js
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var babel = require('gulp-babel');
|
||||
var babelPluginDEV = require('fbjs-scripts/babel/dev-expression');
|
||||
var babelPluginModules = require('fbjs-scripts/babel/rewrite-modules');
|
||||
var del = require('del');
|
||||
var derequire = require('gulp-derequire');
|
||||
var flatten = require('gulp-flatten');
|
||||
var gulp = require('gulp');
|
||||
var gulpUtil = require('gulp-util');
|
||||
var header = require('gulp-header');
|
||||
var objectAssign = require('object-assign');
|
||||
var runSequence = require('run-sequence');
|
||||
var webpackStream = require('webpack-stream');
|
||||
|
||||
var DEVELOPMENT_HEADER =
|
||||
['/**', ' * Animated v<%= version %>', ' */'].join('\n') + '\n';
|
||||
var PRODUCTION_HEADER =
|
||||
[
|
||||
'/**',
|
||||
' * Animated v<%= version %>',
|
||||
' *',
|
||||
' * Copyright (c) 2013-present, Facebook, Inc.',
|
||||
' *',
|
||||
' * This source code is licensed under the MIT license found in the',
|
||||
' * LICENSE file in the root directory of this source tree.',
|
||||
' */',
|
||||
].join('\n') + '\n';
|
||||
|
||||
var babelOpts = {
|
||||
nonStandard: true,
|
||||
loose: ['es6.classes'],
|
||||
stage: 1,
|
||||
plugins: [babelPluginDEV, babelPluginModules],
|
||||
_moduleMap: objectAssign({}, require('fbjs/module-map'), {
|
||||
React: 'react',
|
||||
}),
|
||||
};
|
||||
|
||||
var buildDist = function(opts) {
|
||||
var webpackOpts = {
|
||||
debug: opts.debug,
|
||||
externals: {
|
||||
react: 'React',
|
||||
},
|
||||
module: {
|
||||
loaders: [{test: /\.js$/, loader: 'babel'}],
|
||||
},
|
||||
output: {
|
||||
filename: opts.output,
|
||||
library: 'Animated',
|
||||
},
|
||||
plugins: [
|
||||
new webpackStream.webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(
|
||||
opts.debug ? 'development' : 'production',
|
||||
),
|
||||
}),
|
||||
new webpackStream.webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpackStream.webpack.optimize.DedupePlugin(),
|
||||
],
|
||||
};
|
||||
if (!opts.debug) {
|
||||
webpackOpts.plugins.push(
|
||||
new webpackStream.webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
hoist_vars: true,
|
||||
screw_ie8: true,
|
||||
warnings: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
return webpackStream(webpackOpts, null, function(err, stats) {
|
||||
if (err) {
|
||||
throw new gulpUtil.PluginError('webpack', err);
|
||||
}
|
||||
if (stats.compilation.errors.length) {
|
||||
throw new gulpUtil.PluginError('webpack', stats.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var paths = {
|
||||
dist: 'dist',
|
||||
entry: 'lib/AnimatedWeb.js',
|
||||
lib: 'lib',
|
||||
src: [
|
||||
'*src/**/*.js',
|
||||
'!src/**/__tests__/**/*.js',
|
||||
'!src/**/__mocks__/**/*.js',
|
||||
],
|
||||
};
|
||||
|
||||
gulp.task('clean', function(cb) {
|
||||
del([paths.dist, paths.lib], cb);
|
||||
});
|
||||
|
||||
gulp.task('modules', function() {
|
||||
return gulp
|
||||
.src(paths.src, {cwd: '../'})
|
||||
.pipe(babel(babelOpts))
|
||||
.pipe(flatten())
|
||||
.pipe(gulp.dest(paths.lib));
|
||||
});
|
||||
|
||||
gulp.task('dist', ['modules'], function() {
|
||||
var distOpts = {
|
||||
debug: true,
|
||||
output: 'animated.js',
|
||||
};
|
||||
return gulp
|
||||
.src(paths.entry)
|
||||
.pipe(buildDist(distOpts))
|
||||
.pipe(derequire())
|
||||
.pipe(
|
||||
header(DEVELOPMENT_HEADER, {
|
||||
version: process.env.npm_package_version,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest(paths.dist));
|
||||
});
|
||||
|
||||
gulp.task('dist:min', ['modules'], function() {
|
||||
var distOpts = {
|
||||
debug: false,
|
||||
output: 'animated.min.js',
|
||||
};
|
||||
return gulp
|
||||
.src(paths.entry)
|
||||
.pipe(buildDist(distOpts))
|
||||
.pipe(
|
||||
header(PRODUCTION_HEADER, {
|
||||
version: process.env.npm_package_version,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest(paths.dist));
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch(paths.src, ['modules']);
|
||||
});
|
||||
|
||||
gulp.task('default', function(cb) {
|
||||
runSequence('clean', 'modules', ['dist', 'dist:min'], cb);
|
||||
});
|
34
node_modules/react-native/Libraries/Animated/release/package.json
generated
vendored
Normal file
34
node_modules/react-native/Libraries/Animated/release/package.json
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "react-animated",
|
||||
"description": "Animated provides powerful mechanisms for animating your React views",
|
||||
"version": "0.1.0",
|
||||
"keywords": [
|
||||
"react",
|
||||
"animated",
|
||||
"animation"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "Animated.js",
|
||||
"dependencies": {
|
||||
"fbjs": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^5.8.25",
|
||||
"babel-loader": "^5.3.2",
|
||||
"del": "^1.2.0",
|
||||
"fbjs-scripts": "^1.1.0",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-babel": "^5.1.0",
|
||||
"gulp-derequire": "^2.1.0",
|
||||
"gulp-flatten": "^0.1.0",
|
||||
"gulp-header": "^1.2.2",
|
||||
"gulp-util": "^3.0.6",
|
||||
"object-assign": "^3.0.0",
|
||||
"run-sequence": "^1.1.2",
|
||||
"webpack": "1.11.0",
|
||||
"webpack-stream": "^2.1.0"
|
||||
}
|
||||
}
|
49
node_modules/react-native/Libraries/Animated/src/Animated.js
generated
vendored
Normal file
49
node_modules/react-native/Libraries/Animated/src/Animated.js
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Platform from '../../Utilities/Platform';
|
||||
const View = require('../../Components/View/View');
|
||||
const React = require('react');
|
||||
import type {AnimatedComponentType} from './createAnimatedComponent';
|
||||
|
||||
const AnimatedMock = require('./AnimatedMock');
|
||||
const AnimatedImplementation = require('./AnimatedImplementation');
|
||||
|
||||
//TODO(T57411659): Remove the bridgeless check when Animated perf regressions are fixed.
|
||||
const Animated = ((Platform.isTesting || global.RN$Bridgeless
|
||||
? AnimatedMock
|
||||
: AnimatedImplementation): typeof AnimatedMock);
|
||||
|
||||
module.exports = {
|
||||
get FlatList(): any {
|
||||
return require('./components/AnimatedFlatList');
|
||||
},
|
||||
get Image(): any {
|
||||
return require('./components/AnimatedImage');
|
||||
},
|
||||
get ScrollView(): any {
|
||||
return require('./components/AnimatedScrollView');
|
||||
},
|
||||
get SectionList(): any {
|
||||
return require('./components/AnimatedSectionList');
|
||||
},
|
||||
get Text(): any {
|
||||
return require('./components/AnimatedText');
|
||||
},
|
||||
get View(): AnimatedComponentType<
|
||||
React.ElementConfig<typeof View>,
|
||||
React.ElementRef<typeof View>,
|
||||
> {
|
||||
return require('./components/AnimatedView');
|
||||
},
|
||||
...Animated,
|
||||
};
|
233
node_modules/react-native/Libraries/Animated/src/AnimatedEvent.js
generated
vendored
Normal file
233
node_modules/react-native/Libraries/Animated/src/AnimatedEvent.js
generated
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('./nodes/AnimatedValue');
|
||||
const NativeAnimatedHelper = require('./NativeAnimatedHelper');
|
||||
const ReactNative = require('../../Renderer/shims/ReactNative');
|
||||
|
||||
const invariant = require('invariant');
|
||||
|
||||
const {shouldUseNativeDriver} = require('./NativeAnimatedHelper');
|
||||
|
||||
export type Mapping = {[key: string]: Mapping, ...} | AnimatedValue;
|
||||
export type EventConfig = {
|
||||
listener?: ?Function,
|
||||
useNativeDriver: boolean,
|
||||
};
|
||||
|
||||
function attachNativeEvent(
|
||||
viewRef: any,
|
||||
eventName: string,
|
||||
argMapping: $ReadOnlyArray<?Mapping>,
|
||||
): {detach: () => void} {
|
||||
// Find animated values in `argMapping` and create an array representing their
|
||||
// key path inside the `nativeEvent` object. Ex.: ['contentOffset', 'x'].
|
||||
const eventMappings = [];
|
||||
|
||||
const traverse = (value, path) => {
|
||||
if (value instanceof AnimatedValue) {
|
||||
value.__makeNative();
|
||||
|
||||
eventMappings.push({
|
||||
nativeEventPath: path,
|
||||
animatedValueTag: value.__getNativeTag(),
|
||||
});
|
||||
} else if (typeof value === 'object') {
|
||||
for (const key in value) {
|
||||
traverse(value[key], path.concat(key));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
invariant(
|
||||
argMapping[0] && argMapping[0].nativeEvent,
|
||||
'Native driven events only support animated values contained inside `nativeEvent`.',
|
||||
);
|
||||
|
||||
// Assume that the event containing `nativeEvent` is always the first argument.
|
||||
traverse(argMapping[0].nativeEvent, []);
|
||||
|
||||
const viewTag = ReactNative.findNodeHandle(viewRef);
|
||||
if (viewTag != null) {
|
||||
eventMappings.forEach(mapping => {
|
||||
NativeAnimatedHelper.API.addAnimatedEventToView(
|
||||
viewTag,
|
||||
eventName,
|
||||
mapping,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
detach() {
|
||||
if (viewTag != null) {
|
||||
eventMappings.forEach(mapping => {
|
||||
NativeAnimatedHelper.API.removeAnimatedEventFromView(
|
||||
viewTag,
|
||||
eventName,
|
||||
mapping.animatedValueTag,
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function validateMapping(argMapping, args) {
|
||||
const validate = (recMapping, recEvt, key) => {
|
||||
if (recMapping instanceof AnimatedValue) {
|
||||
invariant(
|
||||
typeof recEvt === 'number',
|
||||
'Bad mapping of event key ' +
|
||||
key +
|
||||
', should be number but got ' +
|
||||
typeof recEvt,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (typeof recEvt === 'number') {
|
||||
invariant(
|
||||
recMapping instanceof AnimatedValue,
|
||||
'Bad mapping of type ' +
|
||||
typeof recMapping +
|
||||
' for key ' +
|
||||
key +
|
||||
', event value must map to AnimatedValue',
|
||||
);
|
||||
return;
|
||||
}
|
||||
invariant(
|
||||
typeof recMapping === 'object',
|
||||
'Bad mapping of type ' + typeof recMapping + ' for key ' + key,
|
||||
);
|
||||
invariant(
|
||||
typeof recEvt === 'object',
|
||||
'Bad event of type ' + typeof recEvt + ' for key ' + key,
|
||||
);
|
||||
for (const mappingKey in recMapping) {
|
||||
validate(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
|
||||
}
|
||||
};
|
||||
|
||||
invariant(
|
||||
args.length >= argMapping.length,
|
||||
'Event has less arguments than mapping',
|
||||
);
|
||||
argMapping.forEach((mapping, idx) => {
|
||||
validate(mapping, args[idx], 'arg' + idx);
|
||||
});
|
||||
}
|
||||
|
||||
class AnimatedEvent {
|
||||
_argMapping: $ReadOnlyArray<?Mapping>;
|
||||
_listeners: Array<Function> = [];
|
||||
_callListeners: Function;
|
||||
_attachedEvent: ?{detach: () => void, ...};
|
||||
__isNative: boolean;
|
||||
|
||||
constructor(argMapping: $ReadOnlyArray<?Mapping>, config: EventConfig) {
|
||||
this._argMapping = argMapping;
|
||||
|
||||
if (config == null) {
|
||||
console.warn('Animated.event now requires a second argument for options');
|
||||
config = {useNativeDriver: false};
|
||||
}
|
||||
|
||||
if (config.listener) {
|
||||
this.__addListener(config.listener);
|
||||
}
|
||||
this._callListeners = this._callListeners.bind(this);
|
||||
this._attachedEvent = null;
|
||||
this.__isNative = shouldUseNativeDriver(config);
|
||||
}
|
||||
|
||||
__addListener(callback: Function): void {
|
||||
this._listeners.push(callback);
|
||||
}
|
||||
|
||||
__removeListener(callback: Function): void {
|
||||
this._listeners = this._listeners.filter(listener => listener !== callback);
|
||||
}
|
||||
|
||||
__attach(viewRef: any, eventName: string) {
|
||||
invariant(
|
||||
this.__isNative,
|
||||
'Only native driven events need to be attached.',
|
||||
);
|
||||
|
||||
this._attachedEvent = attachNativeEvent(
|
||||
viewRef,
|
||||
eventName,
|
||||
this._argMapping,
|
||||
);
|
||||
}
|
||||
|
||||
__detach(viewTag: any, eventName: string) {
|
||||
invariant(
|
||||
this.__isNative,
|
||||
'Only native driven events need to be detached.',
|
||||
);
|
||||
|
||||
this._attachedEvent && this._attachedEvent.detach();
|
||||
}
|
||||
|
||||
__getHandler(): any | ((...args: any) => void) {
|
||||
if (this.__isNative) {
|
||||
if (__DEV__) {
|
||||
let validatedMapping = false;
|
||||
return (...args: any) => {
|
||||
if (!validatedMapping) {
|
||||
validateMapping(this._argMapping, args);
|
||||
validatedMapping = true;
|
||||
}
|
||||
this._callListeners(...args);
|
||||
};
|
||||
} else {
|
||||
return this._callListeners;
|
||||
}
|
||||
}
|
||||
|
||||
let validatedMapping = false;
|
||||
return (...args: any) => {
|
||||
if (__DEV__ && !validatedMapping) {
|
||||
validateMapping(this._argMapping, args);
|
||||
validatedMapping = true;
|
||||
}
|
||||
|
||||
const traverse = (recMapping, recEvt, key) => {
|
||||
if (recMapping instanceof AnimatedValue) {
|
||||
if (typeof recEvt === 'number') {
|
||||
recMapping.setValue(recEvt);
|
||||
}
|
||||
} else if (typeof recMapping === 'object') {
|
||||
for (const mappingKey in recMapping) {
|
||||
/* $FlowFixMe(>=0.120.0) This comment suppresses an error found
|
||||
* when Flow v0.120 was deployed. To see the error, delete this
|
||||
* comment and run Flow. */
|
||||
traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
|
||||
}
|
||||
}
|
||||
};
|
||||
this._argMapping.forEach((mapping, idx) => {
|
||||
traverse(mapping, args[idx], 'arg' + idx);
|
||||
});
|
||||
|
||||
this._callListeners(...args);
|
||||
};
|
||||
}
|
||||
|
||||
_callListeners(...args: any) {
|
||||
this._listeners.forEach(listener => listener(...args));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {AnimatedEvent, attachNativeEvent};
|
712
node_modules/react-native/Libraries/Animated/src/AnimatedImplementation.js
generated
vendored
Normal file
712
node_modules/react-native/Libraries/Animated/src/AnimatedImplementation.js
generated
vendored
Normal file
@ -0,0 +1,712 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @preventMunge
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {AnimatedEvent, attachNativeEvent} = require('./AnimatedEvent');
|
||||
const AnimatedAddition = require('./nodes/AnimatedAddition');
|
||||
const AnimatedDiffClamp = require('./nodes/AnimatedDiffClamp');
|
||||
const AnimatedDivision = require('./nodes/AnimatedDivision');
|
||||
const AnimatedInterpolation = require('./nodes/AnimatedInterpolation');
|
||||
const AnimatedModulo = require('./nodes/AnimatedModulo');
|
||||
const AnimatedMultiplication = require('./nodes/AnimatedMultiplication');
|
||||
const AnimatedNode = require('./nodes/AnimatedNode');
|
||||
const AnimatedProps = require('./nodes/AnimatedProps');
|
||||
const AnimatedSubtraction = require('./nodes/AnimatedSubtraction');
|
||||
const AnimatedTracking = require('./nodes/AnimatedTracking');
|
||||
const AnimatedValue = require('./nodes/AnimatedValue');
|
||||
const AnimatedValueXY = require('./nodes/AnimatedValueXY');
|
||||
const DecayAnimation = require('./animations/DecayAnimation');
|
||||
const SpringAnimation = require('./animations/SpringAnimation');
|
||||
const TimingAnimation = require('./animations/TimingAnimation');
|
||||
|
||||
const createAnimatedComponent = require('./createAnimatedComponent');
|
||||
|
||||
import type {
|
||||
AnimationConfig,
|
||||
EndCallback,
|
||||
EndResult,
|
||||
} from './animations/Animation';
|
||||
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
||||
import type {DecayAnimationConfig} from './animations/DecayAnimation';
|
||||
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
||||
import type {Mapping, EventConfig} from './AnimatedEvent';
|
||||
|
||||
export type CompositeAnimation = {
|
||||
start: (callback?: ?EndCallback) => void,
|
||||
stop: () => void,
|
||||
reset: () => void,
|
||||
_startNativeLoop: (iterations?: number) => void,
|
||||
_isUsingNativeDriver: () => boolean,
|
||||
...
|
||||
};
|
||||
|
||||
const add = function(
|
||||
a: AnimatedNode | number,
|
||||
b: AnimatedNode | number,
|
||||
): AnimatedAddition {
|
||||
return new AnimatedAddition(a, b);
|
||||
};
|
||||
|
||||
const subtract = function(
|
||||
a: AnimatedNode | number,
|
||||
b: AnimatedNode | number,
|
||||
): AnimatedSubtraction {
|
||||
return new AnimatedSubtraction(a, b);
|
||||
};
|
||||
|
||||
const divide = function(
|
||||
a: AnimatedNode | number,
|
||||
b: AnimatedNode | number,
|
||||
): AnimatedDivision {
|
||||
return new AnimatedDivision(a, b);
|
||||
};
|
||||
|
||||
const multiply = function(
|
||||
a: AnimatedNode | number,
|
||||
b: AnimatedNode | number,
|
||||
): AnimatedMultiplication {
|
||||
return new AnimatedMultiplication(a, b);
|
||||
};
|
||||
|
||||
const modulo = function(a: AnimatedNode, modulus: number): AnimatedModulo {
|
||||
return new AnimatedModulo(a, modulus);
|
||||
};
|
||||
|
||||
const diffClamp = function(
|
||||
a: AnimatedNode,
|
||||
min: number,
|
||||
max: number,
|
||||
): AnimatedDiffClamp {
|
||||
return new AnimatedDiffClamp(a, min, max);
|
||||
};
|
||||
|
||||
const _combineCallbacks = function(
|
||||
callback: ?EndCallback,
|
||||
config: {...AnimationConfig, ...},
|
||||
) {
|
||||
if (callback && config.onComplete) {
|
||||
return (...args) => {
|
||||
config.onComplete && config.onComplete(...args);
|
||||
callback && callback(...args);
|
||||
};
|
||||
} else {
|
||||
return callback || config.onComplete;
|
||||
}
|
||||
};
|
||||
|
||||
const maybeVectorAnim = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: Object,
|
||||
anim: (value: AnimatedValue, config: Object) => CompositeAnimation,
|
||||
): ?CompositeAnimation {
|
||||
if (value instanceof AnimatedValueXY) {
|
||||
const configX = {...config};
|
||||
const configY = {...config};
|
||||
for (const key in config) {
|
||||
const {x, y} = config[key];
|
||||
if (x !== undefined && y !== undefined) {
|
||||
configX[key] = x;
|
||||
configY[key] = y;
|
||||
}
|
||||
}
|
||||
const aX = anim((value: AnimatedValueXY).x, configX);
|
||||
const aY = anim((value: AnimatedValueXY).y, configY);
|
||||
// We use `stopTogether: false` here because otherwise tracking will break
|
||||
// because the second animation will get stopped before it can update.
|
||||
return parallel([aX, aY], {stopTogether: false});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const spring = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: SpringAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
const start = function(
|
||||
animatedValue: AnimatedValue | AnimatedValueXY,
|
||||
configuration: SpringAnimationConfig,
|
||||
callback?: ?EndCallback,
|
||||
): void {
|
||||
callback = _combineCallbacks(callback, configuration);
|
||||
const singleValue: any = animatedValue;
|
||||
const singleConfig: any = configuration;
|
||||
singleValue.stopTracking();
|
||||
if (configuration.toValue instanceof AnimatedNode) {
|
||||
singleValue.track(
|
||||
new AnimatedTracking(
|
||||
singleValue,
|
||||
configuration.toValue,
|
||||
SpringAnimation,
|
||||
singleConfig,
|
||||
callback,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
singleValue.animate(new SpringAnimation(singleConfig), callback);
|
||||
}
|
||||
};
|
||||
return (
|
||||
maybeVectorAnim(value, config, spring) || {
|
||||
start: function(callback?: ?EndCallback): void {
|
||||
start(value, config, callback);
|
||||
},
|
||||
|
||||
stop: function(): void {
|
||||
value.stopAnimation();
|
||||
},
|
||||
|
||||
reset: function(): void {
|
||||
value.resetAnimation();
|
||||
},
|
||||
|
||||
_startNativeLoop: function(iterations?: number): void {
|
||||
const singleConfig = {...config, iterations};
|
||||
start(value, singleConfig);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return config.useNativeDriver || false;
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const timing = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: TimingAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
const start = function(
|
||||
animatedValue: AnimatedValue | AnimatedValueXY,
|
||||
configuration: TimingAnimationConfig,
|
||||
callback?: ?EndCallback,
|
||||
): void {
|
||||
callback = _combineCallbacks(callback, configuration);
|
||||
const singleValue: any = animatedValue;
|
||||
const singleConfig: any = configuration;
|
||||
singleValue.stopTracking();
|
||||
if (configuration.toValue instanceof AnimatedNode) {
|
||||
singleValue.track(
|
||||
new AnimatedTracking(
|
||||
singleValue,
|
||||
configuration.toValue,
|
||||
TimingAnimation,
|
||||
singleConfig,
|
||||
callback,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
singleValue.animate(new TimingAnimation(singleConfig), callback);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
maybeVectorAnim(value, config, timing) || {
|
||||
start: function(callback?: ?EndCallback): void {
|
||||
start(value, config, callback);
|
||||
},
|
||||
|
||||
stop: function(): void {
|
||||
value.stopAnimation();
|
||||
},
|
||||
|
||||
reset: function(): void {
|
||||
value.resetAnimation();
|
||||
},
|
||||
|
||||
_startNativeLoop: function(iterations?: number): void {
|
||||
const singleConfig = {...config, iterations};
|
||||
start(value, singleConfig);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return config.useNativeDriver || false;
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const decay = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: DecayAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
const start = function(
|
||||
animatedValue: AnimatedValue | AnimatedValueXY,
|
||||
configuration: DecayAnimationConfig,
|
||||
callback?: ?EndCallback,
|
||||
): void {
|
||||
callback = _combineCallbacks(callback, configuration);
|
||||
const singleValue: any = animatedValue;
|
||||
const singleConfig: any = configuration;
|
||||
singleValue.stopTracking();
|
||||
singleValue.animate(new DecayAnimation(singleConfig), callback);
|
||||
};
|
||||
|
||||
return (
|
||||
maybeVectorAnim(value, config, decay) || {
|
||||
start: function(callback?: ?EndCallback): void {
|
||||
start(value, config, callback);
|
||||
},
|
||||
|
||||
stop: function(): void {
|
||||
value.stopAnimation();
|
||||
},
|
||||
|
||||
reset: function(): void {
|
||||
value.resetAnimation();
|
||||
},
|
||||
|
||||
_startNativeLoop: function(iterations?: number): void {
|
||||
const singleConfig = {...config, iterations};
|
||||
start(value, singleConfig);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return config.useNativeDriver || false;
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const sequence = function(
|
||||
animations: Array<CompositeAnimation>,
|
||||
): CompositeAnimation {
|
||||
let current = 0;
|
||||
return {
|
||||
start: function(callback?: ?EndCallback) {
|
||||
const onComplete = function(result) {
|
||||
if (!result.finished) {
|
||||
callback && callback(result);
|
||||
return;
|
||||
}
|
||||
|
||||
current++;
|
||||
|
||||
if (current === animations.length) {
|
||||
callback && callback(result);
|
||||
return;
|
||||
}
|
||||
|
||||
animations[current].start(onComplete);
|
||||
};
|
||||
|
||||
if (animations.length === 0) {
|
||||
callback && callback({finished: true});
|
||||
} else {
|
||||
animations[current].start(onComplete);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (current < animations.length) {
|
||||
animations[current].stop();
|
||||
}
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
animations.forEach((animation, idx) => {
|
||||
if (idx <= current) {
|
||||
animation.reset();
|
||||
}
|
||||
});
|
||||
current = 0;
|
||||
},
|
||||
|
||||
_startNativeLoop: function() {
|
||||
throw new Error(
|
||||
'Loops run using the native driver cannot contain Animated.sequence animations',
|
||||
);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
type ParallelConfig = {
|
||||
// If one is stopped, stop all. default: true
|
||||
stopTogether?: boolean,
|
||||
...
|
||||
};
|
||||
const parallel = function(
|
||||
animations: Array<CompositeAnimation>,
|
||||
config?: ?ParallelConfig,
|
||||
): CompositeAnimation {
|
||||
let doneCount = 0;
|
||||
// Make sure we only call stop() at most once for each animation
|
||||
const hasEnded = {};
|
||||
const stopTogether = !(config && config.stopTogether === false);
|
||||
|
||||
const result = {
|
||||
start: function(callback?: ?EndCallback) {
|
||||
if (doneCount === animations.length) {
|
||||
callback && callback({finished: true});
|
||||
return;
|
||||
}
|
||||
|
||||
animations.forEach((animation, idx) => {
|
||||
const cb = function(endResult) {
|
||||
hasEnded[idx] = true;
|
||||
doneCount++;
|
||||
if (doneCount === animations.length) {
|
||||
doneCount = 0;
|
||||
callback && callback(endResult);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!endResult.finished && stopTogether) {
|
||||
result.stop();
|
||||
}
|
||||
};
|
||||
|
||||
if (!animation) {
|
||||
cb({finished: true});
|
||||
} else {
|
||||
animation.start(cb);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
stop: function(): void {
|
||||
animations.forEach((animation, idx) => {
|
||||
!hasEnded[idx] && animation.stop();
|
||||
hasEnded[idx] = true;
|
||||
});
|
||||
},
|
||||
|
||||
reset: function(): void {
|
||||
animations.forEach((animation, idx) => {
|
||||
animation.reset();
|
||||
hasEnded[idx] = false;
|
||||
doneCount = 0;
|
||||
});
|
||||
},
|
||||
|
||||
_startNativeLoop: function() {
|
||||
throw new Error(
|
||||
'Loops run using the native driver cannot contain Animated.parallel animations',
|
||||
);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const delay = function(time: number): CompositeAnimation {
|
||||
// Would be nice to make a specialized implementation
|
||||
return timing(new AnimatedValue(0), {
|
||||
toValue: 0,
|
||||
delay: time,
|
||||
duration: 0,
|
||||
useNativeDriver: false,
|
||||
});
|
||||
};
|
||||
|
||||
const stagger = function(
|
||||
time: number,
|
||||
animations: Array<CompositeAnimation>,
|
||||
): CompositeAnimation {
|
||||
return parallel(
|
||||
animations.map((animation, i) => {
|
||||
return sequence([delay(time * i), animation]);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
type LoopAnimationConfig = {
|
||||
iterations: number,
|
||||
resetBeforeIteration?: boolean,
|
||||
...
|
||||
};
|
||||
|
||||
const loop = function(
|
||||
animation: CompositeAnimation,
|
||||
{iterations = -1, resetBeforeIteration = true}: LoopAnimationConfig = {},
|
||||
): CompositeAnimation {
|
||||
let isFinished = false;
|
||||
let iterationsSoFar = 0;
|
||||
return {
|
||||
start: function(callback?: ?EndCallback) {
|
||||
const restart = function(result: EndResult = {finished: true}): void {
|
||||
if (
|
||||
isFinished ||
|
||||
iterationsSoFar === iterations ||
|
||||
result.finished === false
|
||||
) {
|
||||
callback && callback(result);
|
||||
} else {
|
||||
iterationsSoFar++;
|
||||
resetBeforeIteration && animation.reset();
|
||||
animation.start(restart);
|
||||
}
|
||||
};
|
||||
if (!animation || iterations === 0) {
|
||||
callback && callback({finished: true});
|
||||
} else {
|
||||
if (animation._isUsingNativeDriver()) {
|
||||
animation._startNativeLoop(iterations);
|
||||
} else {
|
||||
restart(); // Start looping recursively on the js thread
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
stop: function(): void {
|
||||
isFinished = true;
|
||||
animation.stop();
|
||||
},
|
||||
|
||||
reset: function(): void {
|
||||
iterationsSoFar = 0;
|
||||
isFinished = false;
|
||||
animation.reset();
|
||||
},
|
||||
|
||||
_startNativeLoop: function() {
|
||||
throw new Error(
|
||||
'Loops run using the native driver cannot contain Animated.loop animations',
|
||||
);
|
||||
},
|
||||
|
||||
_isUsingNativeDriver: function(): boolean {
|
||||
return animation._isUsingNativeDriver();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
function forkEvent(
|
||||
event: ?AnimatedEvent | ?Function,
|
||||
listener: Function,
|
||||
): AnimatedEvent | Function {
|
||||
if (!event) {
|
||||
return listener;
|
||||
} else if (event instanceof AnimatedEvent) {
|
||||
event.__addListener(listener);
|
||||
return event;
|
||||
} else {
|
||||
return (...args) => {
|
||||
typeof event === 'function' && event(...args);
|
||||
listener(...args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function unforkEvent(
|
||||
event: ?AnimatedEvent | ?Function,
|
||||
listener: Function,
|
||||
): void {
|
||||
if (event && event instanceof AnimatedEvent) {
|
||||
event.__removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
const event = function(
|
||||
argMapping: $ReadOnlyArray<?Mapping>,
|
||||
config: EventConfig,
|
||||
): any {
|
||||
const animatedEvent = new AnimatedEvent(argMapping, config);
|
||||
if (animatedEvent.__isNative) {
|
||||
return animatedEvent;
|
||||
} else {
|
||||
return animatedEvent.__getHandler();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The `Animated` library is designed to make animations fluid, powerful, and
|
||||
* easy to build and maintain. `Animated` focuses on declarative relationships
|
||||
* between inputs and outputs, with configurable transforms in between, and
|
||||
* simple `start`/`stop` methods to control time-based animation execution.
|
||||
* If additional transforms are added, be sure to include them in
|
||||
* AnimatedMock.js as well.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* Standard value class for driving animations. Typically initialized with
|
||||
* `new Animated.Value(0);`
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#value
|
||||
*/
|
||||
Value: AnimatedValue,
|
||||
/**
|
||||
* 2D value class for driving 2D animations, such as pan gestures.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html
|
||||
*/
|
||||
ValueXY: AnimatedValueXY,
|
||||
/**
|
||||
* Exported to use the Interpolation type in flow.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#interpolation
|
||||
*/
|
||||
Interpolation: AnimatedInterpolation,
|
||||
/**
|
||||
* Exported for ease of type checking. All animated values derive from this
|
||||
* class.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#node
|
||||
*/
|
||||
Node: AnimatedNode,
|
||||
|
||||
/**
|
||||
* Animates a value from an initial velocity to zero based on a decay
|
||||
* coefficient.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#decay
|
||||
*/
|
||||
decay,
|
||||
/**
|
||||
* Animates a value along a timed easing curve. The Easing module has tons of
|
||||
* predefined curves, or you can use your own function.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#timing
|
||||
*/
|
||||
timing,
|
||||
/**
|
||||
* Animates a value according to an analytical spring model based on
|
||||
* damped harmonic oscillation.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#spring
|
||||
*/
|
||||
spring,
|
||||
|
||||
/**
|
||||
* Creates a new Animated value composed from two Animated values added
|
||||
* together.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#add
|
||||
*/
|
||||
add,
|
||||
|
||||
/**
|
||||
* Creates a new Animated value composed by subtracting the second Animated
|
||||
* value from the first Animated value.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#subtract
|
||||
*/
|
||||
subtract,
|
||||
|
||||
/**
|
||||
* Creates a new Animated value composed by dividing the first Animated value
|
||||
* by the second Animated value.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#divide
|
||||
*/
|
||||
divide,
|
||||
|
||||
/**
|
||||
* Creates a new Animated value composed from two Animated values multiplied
|
||||
* together.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#multiply
|
||||
*/
|
||||
multiply,
|
||||
|
||||
/**
|
||||
* Creates a new Animated value that is the (non-negative) modulo of the
|
||||
* provided Animated value.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#modulo
|
||||
*/
|
||||
modulo,
|
||||
|
||||
/**
|
||||
* Create a new Animated value that is limited between 2 values. It uses the
|
||||
* difference between the last value so even if the value is far from the
|
||||
* bounds it will start changing when the value starts getting closer again.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#diffclamp
|
||||
*/
|
||||
diffClamp,
|
||||
|
||||
/**
|
||||
* Starts an animation after the given delay.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#delay
|
||||
*/
|
||||
delay,
|
||||
/**
|
||||
* Starts an array of animations in order, waiting for each to complete
|
||||
* before starting the next. If the current running animation is stopped, no
|
||||
* following animations will be started.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#sequence
|
||||
*/
|
||||
sequence,
|
||||
/**
|
||||
* Starts an array of animations all at the same time. By default, if one
|
||||
* of the animations is stopped, they will all be stopped. You can override
|
||||
* this with the `stopTogether` flag.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#parallel
|
||||
*/
|
||||
parallel,
|
||||
/**
|
||||
* Array of animations may run in parallel (overlap), but are started in
|
||||
* sequence with successive delays. Nice for doing trailing effects.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#stagger
|
||||
*/
|
||||
stagger,
|
||||
/**
|
||||
* Loops a given animation continuously, so that each time it reaches the
|
||||
* end, it resets and begins again from the start.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#loop
|
||||
*/
|
||||
loop,
|
||||
|
||||
/**
|
||||
* Takes an array of mappings and extracts values from each arg accordingly,
|
||||
* then calls `setValue` on the mapped outputs.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#event
|
||||
*/
|
||||
event,
|
||||
|
||||
/**
|
||||
* Make any React component Animatable. Used to create `Animated.View`, etc.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#createanimatedcomponent
|
||||
*/
|
||||
createAnimatedComponent,
|
||||
|
||||
/**
|
||||
* Imperative API to attach an animated value to an event on a view. Prefer
|
||||
* using `Animated.event` with `useNativeDrive: true` if possible.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#attachnativeevent
|
||||
*/
|
||||
attachNativeEvent,
|
||||
|
||||
/**
|
||||
* Advanced imperative API for snooping on animated events that are passed in
|
||||
* through props. Use values directly where possible.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animated.html#forkevent
|
||||
*/
|
||||
forkEvent,
|
||||
unforkEvent,
|
||||
|
||||
/**
|
||||
* Expose Event class, so it can be used as a type for type checkers.
|
||||
*/
|
||||
Event: AnimatedEvent,
|
||||
|
||||
__PropsOnlyForTests: AnimatedProps,
|
||||
};
|
156
node_modules/react-native/Libraries/Animated/src/AnimatedMock.js
generated
vendored
Normal file
156
node_modules/react-native/Libraries/Animated/src/AnimatedMock.js
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {AnimatedEvent, attachNativeEvent} = require('./AnimatedEvent');
|
||||
const AnimatedImplementation = require('./AnimatedImplementation');
|
||||
const AnimatedInterpolation = require('./nodes/AnimatedInterpolation');
|
||||
const AnimatedNode = require('./nodes/AnimatedNode');
|
||||
const AnimatedProps = require('./nodes/AnimatedProps');
|
||||
const AnimatedValue = require('./nodes/AnimatedValue');
|
||||
const AnimatedValueXY = require('./nodes/AnimatedValueXY');
|
||||
|
||||
const createAnimatedComponent = require('./createAnimatedComponent');
|
||||
|
||||
import type {EndCallback} from './animations/Animation';
|
||||
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
||||
import type {DecayAnimationConfig} from './animations/DecayAnimation';
|
||||
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
||||
import type {Mapping, EventConfig} from './AnimatedEvent';
|
||||
|
||||
/**
|
||||
* Animations are a source of flakiness in snapshot testing. This mock replaces
|
||||
* animation functions from AnimatedImplementation with empty animations for
|
||||
* predictability in tests.
|
||||
*/
|
||||
export type CompositeAnimation = {
|
||||
start: (callback?: ?EndCallback) => void,
|
||||
stop: () => void,
|
||||
reset: () => void,
|
||||
_startNativeLoop: (iterations?: number) => void,
|
||||
_isUsingNativeDriver: () => boolean,
|
||||
...
|
||||
};
|
||||
|
||||
const emptyAnimation = {
|
||||
start: () => {},
|
||||
stop: () => {},
|
||||
reset: () => {},
|
||||
_startNativeLoop: () => {},
|
||||
_isUsingNativeDriver: () => {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
const spring = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: SpringAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
const anyValue: any = value;
|
||||
return {
|
||||
...emptyAnimation,
|
||||
start: (callback?: ?EndCallback): void => {
|
||||
anyValue.setValue(config.toValue);
|
||||
callback && callback({finished: true});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const timing = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: TimingAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
const anyValue: any = value;
|
||||
return {
|
||||
...emptyAnimation,
|
||||
start: (callback?: ?EndCallback): void => {
|
||||
anyValue.setValue(config.toValue);
|
||||
callback && callback({finished: true});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const decay = function(
|
||||
value: AnimatedValue | AnimatedValueXY,
|
||||
config: DecayAnimationConfig,
|
||||
): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
const sequence = function(
|
||||
animations: Array<CompositeAnimation>,
|
||||
): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
type ParallelConfig = {stopTogether?: boolean, ...};
|
||||
const parallel = function(
|
||||
animations: Array<CompositeAnimation>,
|
||||
config?: ?ParallelConfig,
|
||||
): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
const delay = function(time: number): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
const stagger = function(
|
||||
time: number,
|
||||
animations: Array<CompositeAnimation>,
|
||||
): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
type LoopAnimationConfig = {
|
||||
iterations: number,
|
||||
resetBeforeIteration?: boolean,
|
||||
...
|
||||
};
|
||||
|
||||
const loop = function(
|
||||
animation: CompositeAnimation,
|
||||
{iterations = -1}: LoopAnimationConfig = {},
|
||||
): CompositeAnimation {
|
||||
return emptyAnimation;
|
||||
};
|
||||
|
||||
const event = function(argMapping: Array<?Mapping>, config: EventConfig): any {
|
||||
return null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
Value: AnimatedValue,
|
||||
ValueXY: AnimatedValueXY,
|
||||
Interpolation: AnimatedInterpolation,
|
||||
Node: AnimatedNode,
|
||||
decay,
|
||||
timing,
|
||||
spring,
|
||||
add: AnimatedImplementation.add,
|
||||
subtract: AnimatedImplementation.subtract,
|
||||
divide: AnimatedImplementation.divide,
|
||||
multiply: AnimatedImplementation.multiply,
|
||||
modulo: AnimatedImplementation.modulo,
|
||||
diffClamp: AnimatedImplementation.diffClamp,
|
||||
delay,
|
||||
sequence,
|
||||
parallel,
|
||||
stagger,
|
||||
loop,
|
||||
event,
|
||||
createAnimatedComponent,
|
||||
attachNativeEvent,
|
||||
forkEvent: AnimatedImplementation.forkEvent,
|
||||
unforkEvent: AnimatedImplementation.unforkEvent,
|
||||
Event: AnimatedEvent,
|
||||
__PropsOnlyForTests: AnimatedProps,
|
||||
};
|
23
node_modules/react-native/Libraries/Animated/src/AnimatedWeb.js
generated
vendored
Normal file
23
node_modules/react-native/Libraries/Animated/src/AnimatedWeb.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedImplementation = require('./AnimatedImplementation');
|
||||
|
||||
module.exports = {
|
||||
...AnimatedImplementation,
|
||||
// $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this
|
||||
div: (AnimatedImplementation.createAnimatedComponent('div'): $FlowFixMe),
|
||||
// $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this
|
||||
span: (AnimatedImplementation.createAnimatedComponent('span'): $FlowFixMe),
|
||||
// $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this
|
||||
img: (AnimatedImplementation.createAnimatedComponent('img'): $FlowFixMe),
|
||||
};
|
252
node_modules/react-native/Libraries/Animated/src/Easing.js
generated
vendored
Normal file
252
node_modules/react-native/Libraries/Animated/src/Easing.js
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let ease;
|
||||
|
||||
/**
|
||||
* The `Easing` module implements common easing functions. This module is used
|
||||
* by [Animate.timing()](docs/animate.html#timing) to convey physically
|
||||
* believable motion in animations.
|
||||
*
|
||||
* You can find a visualization of some common easing functions at
|
||||
* http://easings.net/
|
||||
*
|
||||
* ### Predefined animations
|
||||
*
|
||||
* The `Easing` module provides several predefined animations through the
|
||||
* following methods:
|
||||
*
|
||||
* - [`back`](docs/easing.html#back) provides a simple animation where the
|
||||
* object goes slightly back before moving forward
|
||||
* - [`bounce`](docs/easing.html#bounce) provides a bouncing animation
|
||||
* - [`ease`](docs/easing.html#ease) provides a simple inertial animation
|
||||
* - [`elastic`](docs/easing.html#elastic) provides a simple spring interaction
|
||||
*
|
||||
* ### Standard functions
|
||||
*
|
||||
* Three standard easing functions are provided:
|
||||
*
|
||||
* - [`linear`](docs/easing.html#linear)
|
||||
* - [`quad`](docs/easing.html#quad)
|
||||
* - [`cubic`](docs/easing.html#cubic)
|
||||
*
|
||||
* The [`poly`](docs/easing.html#poly) function can be used to implement
|
||||
* quartic, quintic, and other higher power functions.
|
||||
*
|
||||
* ### Additional functions
|
||||
*
|
||||
* Additional mathematical functions are provided by the following methods:
|
||||
*
|
||||
* - [`bezier`](docs/easing.html#bezier) provides a cubic bezier curve
|
||||
* - [`circle`](docs/easing.html#circle) provides a circular function
|
||||
* - [`sin`](docs/easing.html#sin) provides a sinusoidal function
|
||||
* - [`exp`](docs/easing.html#exp) provides an exponential function
|
||||
*
|
||||
* The following helpers are used to modify other easing functions.
|
||||
*
|
||||
* - [`in`](docs/easing.html#in) runs an easing function forwards
|
||||
* - [`inOut`](docs/easing.html#inout) makes any easing function symmetrical
|
||||
* - [`out`](docs/easing.html#out) runs an easing function backwards
|
||||
*/
|
||||
class Easing {
|
||||
/**
|
||||
* A stepping function, returns 1 for any positive value of `n`.
|
||||
*/
|
||||
static step0(n: number): number {
|
||||
return n > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A stepping function, returns 1 if `n` is greater than or equal to 1.
|
||||
*/
|
||||
static step1(n: number): number {
|
||||
return n >= 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A linear function, `f(t) = t`. Position correlates to elapsed time one to
|
||||
* one.
|
||||
*
|
||||
* http://cubic-bezier.com/#0,0,1,1
|
||||
*/
|
||||
static linear(t: number): number {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple inertial interaction, similar to an object slowly accelerating to
|
||||
* speed.
|
||||
*
|
||||
* http://cubic-bezier.com/#.42,0,1,1
|
||||
*/
|
||||
static ease(t: number): number {
|
||||
if (!ease) {
|
||||
ease = Easing.bezier(0.42, 0, 1, 1);
|
||||
}
|
||||
return ease(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* A quadratic function, `f(t) = t * t`. Position equals the square of elapsed
|
||||
* time.
|
||||
*
|
||||
* http://easings.net/#easeInQuad
|
||||
*/
|
||||
static quad(t: number): number {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
/**
|
||||
* A cubic function, `f(t) = t * t * t`. Position equals the cube of elapsed
|
||||
* time.
|
||||
*
|
||||
* http://easings.net/#easeInCubic
|
||||
*/
|
||||
static cubic(t: number): number {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
/**
|
||||
* A power function. Position is equal to the Nth power of elapsed time.
|
||||
*
|
||||
* n = 4: http://easings.net/#easeInQuart
|
||||
* n = 5: http://easings.net/#easeInQuint
|
||||
*/
|
||||
static poly(n: number): (t: number) => number {
|
||||
return (t: number) => Math.pow(t, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sinusoidal function.
|
||||
*
|
||||
* http://easings.net/#easeInSine
|
||||
*/
|
||||
static sin(t: number): number {
|
||||
return 1 - Math.cos((t * Math.PI) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* A circular function.
|
||||
*
|
||||
* http://easings.net/#easeInCirc
|
||||
*/
|
||||
static circle(t: number): number {
|
||||
return 1 - Math.sqrt(1 - t * t);
|
||||
}
|
||||
|
||||
/**
|
||||
* An exponential function.
|
||||
*
|
||||
* http://easings.net/#easeInExpo
|
||||
*/
|
||||
static exp(t: number): number {
|
||||
return Math.pow(2, 10 * (t - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple elastic interaction, similar to a spring oscillating back and
|
||||
* forth.
|
||||
*
|
||||
* Default bounciness is 1, which overshoots a little bit once. 0 bounciness
|
||||
* doesn't overshoot at all, and bounciness of N > 1 will overshoot about N
|
||||
* times.
|
||||
*
|
||||
* http://easings.net/#easeInElastic
|
||||
*/
|
||||
static elastic(bounciness: number = 1): (t: number) => number {
|
||||
const p = bounciness * Math.PI;
|
||||
return t => 1 - Math.pow(Math.cos((t * Math.PI) / 2), 3) * Math.cos(t * p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use with `Animated.parallel()` to create a simple effect where the object
|
||||
* animates back slightly as the animation starts.
|
||||
*
|
||||
* Wolfram Plot:
|
||||
*
|
||||
* - http://tiny.cc/back_default (s = 1.70158, default)
|
||||
*/
|
||||
static back(s: number = 1.70158): (t: number) => number {
|
||||
return t => t * t * ((s + 1) * t - s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple bouncing effect.
|
||||
*
|
||||
* http://easings.net/#easeInBounce
|
||||
*/
|
||||
static bounce(t: number): number {
|
||||
if (t < 1 / 2.75) {
|
||||
return 7.5625 * t * t;
|
||||
}
|
||||
|
||||
if (t < 2 / 2.75) {
|
||||
const t2 = t - 1.5 / 2.75;
|
||||
return 7.5625 * t2 * t2 + 0.75;
|
||||
}
|
||||
|
||||
if (t < 2.5 / 2.75) {
|
||||
const t2 = t - 2.25 / 2.75;
|
||||
return 7.5625 * t2 * t2 + 0.9375;
|
||||
}
|
||||
|
||||
const t2 = t - 2.625 / 2.75;
|
||||
return 7.5625 * t2 * t2 + 0.984375;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a cubic bezier curve, equivalent to CSS Transitions'
|
||||
* `transition-timing-function`.
|
||||
*
|
||||
* A useful tool to visualize cubic bezier curves can be found at
|
||||
* http://cubic-bezier.com/
|
||||
*/
|
||||
static bezier(
|
||||
x1: number,
|
||||
y1: number,
|
||||
x2: number,
|
||||
y2: number,
|
||||
): (t: number) => number {
|
||||
const _bezier = require('./bezier');
|
||||
return _bezier(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an easing function forwards.
|
||||
*/
|
||||
static in(easing: (t: number) => number): (t: number) => number {
|
||||
return easing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an easing function backwards.
|
||||
*/
|
||||
static out(easing: (t: number) => number): (t: number) => number {
|
||||
return t => 1 - easing(1 - t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes any easing function symmetrical. The easing function will run
|
||||
* forwards for half of the duration, then backwards for the rest of the
|
||||
* duration.
|
||||
*/
|
||||
static inOut(easing: (t: number) => number): (t: number) => number {
|
||||
return t => {
|
||||
if (t < 0.5) {
|
||||
return easing(t * 2) / 2;
|
||||
}
|
||||
return 1 - easing((1 - t) * 2) / 2;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Easing;
|
342
node_modules/react-native/Libraries/Animated/src/NativeAnimatedHelper.js
generated
vendored
Normal file
342
node_modules/react-native/Libraries/Animated/src/NativeAnimatedHelper.js
generated
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter';
|
||||
import type {EventConfig} from './AnimatedEvent';
|
||||
import NativeAnimatedModule from './NativeAnimatedModule';
|
||||
import type {
|
||||
EventMapping,
|
||||
AnimatedNodeConfig,
|
||||
AnimatingNodeConfig,
|
||||
} from './NativeAnimatedModule';
|
||||
import type {AnimationConfig, EndCallback} from './animations/Animation';
|
||||
import type {InterpolationConfigType} from './nodes/AnimatedInterpolation';
|
||||
import invariant from 'invariant';
|
||||
|
||||
let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
|
||||
let __nativeAnimationIdCount = 1; /* used for started animations */
|
||||
|
||||
let nativeEventEmitter;
|
||||
|
||||
let queueConnections = false;
|
||||
let queue = [];
|
||||
|
||||
/**
|
||||
* Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
|
||||
* the native module methods
|
||||
*/
|
||||
const API = {
|
||||
enableQueue: function(): void {
|
||||
queueConnections = true;
|
||||
},
|
||||
disableQueue: function(): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
queueConnections = false;
|
||||
for (let q = 0, l = queue.length; q < l; q++) {
|
||||
const args = queue[q];
|
||||
NativeAnimatedModule.connectAnimatedNodes(args[0], args[1]);
|
||||
}
|
||||
queue.length = 0;
|
||||
},
|
||||
createAnimatedNode: function(tag: number, config: AnimatedNodeConfig): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.createAnimatedNode(tag, config);
|
||||
},
|
||||
startListeningToAnimatedNodeValue: function(tag: number) {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
|
||||
},
|
||||
stopListeningToAnimatedNodeValue: function(tag: number) {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
|
||||
},
|
||||
connectAnimatedNodes: function(parentTag: number, childTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
if (queueConnections) {
|
||||
queue.push([parentTag, childTag]);
|
||||
return;
|
||||
}
|
||||
NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
|
||||
},
|
||||
disconnectAnimatedNodes: function(parentTag: number, childTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
|
||||
},
|
||||
startAnimatingNode: function(
|
||||
animationId: number,
|
||||
nodeTag: number,
|
||||
config: AnimatingNodeConfig,
|
||||
endCallback: EndCallback,
|
||||
): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.startAnimatingNode(
|
||||
animationId,
|
||||
nodeTag,
|
||||
config,
|
||||
endCallback,
|
||||
);
|
||||
},
|
||||
stopAnimation: function(animationId: number) {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.stopAnimation(animationId);
|
||||
},
|
||||
setAnimatedNodeValue: function(nodeTag: number, value: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
|
||||
},
|
||||
setAnimatedNodeOffset: function(nodeTag: number, offset: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
|
||||
},
|
||||
flattenAnimatedNodeOffset: function(nodeTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
|
||||
},
|
||||
extractAnimatedNodeOffset: function(nodeTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
|
||||
},
|
||||
connectAnimatedNodeToView: function(nodeTag: number, viewTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
|
||||
},
|
||||
disconnectAnimatedNodeFromView: function(
|
||||
nodeTag: number,
|
||||
viewTag: number,
|
||||
): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
|
||||
},
|
||||
restoreDefaultValues: function(nodeTag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
// Backwards compat with older native runtimes, can be removed later.
|
||||
if (NativeAnimatedModule.restoreDefaultValues != null) {
|
||||
NativeAnimatedModule.restoreDefaultValues(nodeTag);
|
||||
}
|
||||
},
|
||||
dropAnimatedNode: function(tag: number): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.dropAnimatedNode(tag);
|
||||
},
|
||||
addAnimatedEventToView: function(
|
||||
viewTag: number,
|
||||
eventName: string,
|
||||
eventMapping: EventMapping,
|
||||
) {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.addAnimatedEventToView(
|
||||
viewTag,
|
||||
eventName,
|
||||
eventMapping,
|
||||
);
|
||||
},
|
||||
removeAnimatedEventFromView(
|
||||
viewTag: number,
|
||||
eventName: string,
|
||||
animatedNodeTag: number,
|
||||
) {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
NativeAnimatedModule.removeAnimatedEventFromView(
|
||||
viewTag,
|
||||
eventName,
|
||||
animatedNodeTag,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Styles allowed by the native animated implementation.
|
||||
*
|
||||
* In general native animated implementation should support any numeric property that doesn't need
|
||||
* to be updated through the shadow view hierarchy (all non-layout properties).
|
||||
*/
|
||||
const STYLES_WHITELIST = {
|
||||
opacity: true,
|
||||
transform: true,
|
||||
borderRadius: true,
|
||||
borderBottomEndRadius: true,
|
||||
borderBottomLeftRadius: true,
|
||||
borderBottomRightRadius: true,
|
||||
borderBottomStartRadius: true,
|
||||
borderTopEndRadius: true,
|
||||
borderTopLeftRadius: true,
|
||||
borderTopRightRadius: true,
|
||||
borderTopStartRadius: true,
|
||||
elevation: true,
|
||||
zIndex: true,
|
||||
/* ios styles */
|
||||
shadowOpacity: true,
|
||||
shadowRadius: true,
|
||||
/* legacy android transform properties */
|
||||
scaleX: true,
|
||||
scaleY: true,
|
||||
translateX: true,
|
||||
translateY: true,
|
||||
};
|
||||
|
||||
const TRANSFORM_WHITELIST = {
|
||||
translateX: true,
|
||||
translateY: true,
|
||||
scale: true,
|
||||
scaleX: true,
|
||||
scaleY: true,
|
||||
rotate: true,
|
||||
rotateX: true,
|
||||
rotateY: true,
|
||||
rotateZ: true,
|
||||
perspective: true,
|
||||
};
|
||||
|
||||
const SUPPORTED_INTERPOLATION_PARAMS = {
|
||||
inputRange: true,
|
||||
outputRange: true,
|
||||
extrapolate: true,
|
||||
extrapolateRight: true,
|
||||
extrapolateLeft: true,
|
||||
};
|
||||
|
||||
function addWhitelistedStyleProp(prop: string): void {
|
||||
STYLES_WHITELIST[prop] = true;
|
||||
}
|
||||
|
||||
function addWhitelistedTransformProp(prop: string): void {
|
||||
TRANSFORM_WHITELIST[prop] = true;
|
||||
}
|
||||
|
||||
function addWhitelistedInterpolationParam(param: string): void {
|
||||
SUPPORTED_INTERPOLATION_PARAMS[param] = true;
|
||||
}
|
||||
|
||||
function validateTransform(
|
||||
configs: Array<
|
||||
| {
|
||||
type: 'animated',
|
||||
property: string,
|
||||
nodeTag: ?number,
|
||||
...
|
||||
}
|
||||
| {
|
||||
type: 'static',
|
||||
property: string,
|
||||
value: number | string,
|
||||
...
|
||||
},
|
||||
>,
|
||||
): void {
|
||||
configs.forEach(config => {
|
||||
if (!TRANSFORM_WHITELIST.hasOwnProperty(config.property)) {
|
||||
throw new Error(
|
||||
`Property '${
|
||||
config.property
|
||||
}' is not supported by native animated module`,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function validateStyles(styles: {[key: string]: ?number, ...}): void {
|
||||
for (const key in styles) {
|
||||
if (!STYLES_WHITELIST.hasOwnProperty(key)) {
|
||||
throw new Error(
|
||||
`Style property '${key}' is not supported by native animated module`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateInterpolation(config: InterpolationConfigType): void {
|
||||
for (const key in config) {
|
||||
if (!SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(key)) {
|
||||
throw new Error(
|
||||
`Interpolation property '${key}' is not supported by native animated module`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateNewNodeTag(): number {
|
||||
return __nativeAnimatedNodeTagCount++;
|
||||
}
|
||||
|
||||
function generateNewAnimationId(): number {
|
||||
return __nativeAnimationIdCount++;
|
||||
}
|
||||
|
||||
function assertNativeAnimatedModule(): void {
|
||||
invariant(NativeAnimatedModule, 'Native animated module is not available');
|
||||
}
|
||||
|
||||
let _warnedMissingNativeAnimated = false;
|
||||
|
||||
function shouldUseNativeDriver(
|
||||
config: {...AnimationConfig, ...} | EventConfig,
|
||||
): boolean {
|
||||
if (config.useNativeDriver == null) {
|
||||
console.warn(
|
||||
'Animated: `useNativeDriver` was not specified. This is a required ' +
|
||||
'option and must be explicitly set to `true` or `false`',
|
||||
);
|
||||
}
|
||||
|
||||
if (config.useNativeDriver === true && !NativeAnimatedModule) {
|
||||
if (!_warnedMissingNativeAnimated) {
|
||||
console.warn(
|
||||
'Animated: `useNativeDriver` is not supported because the native ' +
|
||||
'animated module is missing. Falling back to JS-based animation. To ' +
|
||||
'resolve this, add `RCTAnimation` module to this app, or remove ' +
|
||||
'`useNativeDriver`. ' +
|
||||
'Make sure to run `pod install` first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md',
|
||||
);
|
||||
_warnedMissingNativeAnimated = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return config.useNativeDriver || false;
|
||||
}
|
||||
|
||||
function transformDataType(value: number | string): number | string {
|
||||
// Change the string type to number type so we can reuse the same logic in
|
||||
// iOS and Android platform
|
||||
if (typeof value !== 'string') {
|
||||
return value;
|
||||
}
|
||||
if (/deg$/.test(value)) {
|
||||
const degrees = parseFloat(value) || 0;
|
||||
const radians = (degrees * Math.PI) / 180.0;
|
||||
return radians;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
API,
|
||||
addWhitelistedStyleProp,
|
||||
addWhitelistedTransformProp,
|
||||
addWhitelistedInterpolationParam,
|
||||
validateStyles,
|
||||
validateTransform,
|
||||
validateInterpolation,
|
||||
generateNewNodeTag,
|
||||
generateNewAnimationId,
|
||||
assertNativeAnimatedModule,
|
||||
shouldUseNativeDriver,
|
||||
transformDataType,
|
||||
// $FlowExpectedError - unsafe getter lint suppresion
|
||||
get nativeEventEmitter(): NativeEventEmitter {
|
||||
if (!nativeEventEmitter) {
|
||||
nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);
|
||||
}
|
||||
return nativeEventEmitter;
|
||||
},
|
||||
};
|
66
node_modules/react-native/Libraries/Animated/src/NativeAnimatedModule.js
generated
vendored
Normal file
66
node_modules/react-native/Libraries/Animated/src/NativeAnimatedModule.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {TurboModule} from '../../TurboModule/RCTExport';
|
||||
import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry';
|
||||
|
||||
type EndResult = {finished: boolean, ...};
|
||||
type EndCallback = (result: EndResult) => void;
|
||||
|
||||
export type EventMapping = {|
|
||||
nativeEventPath: Array<string>,
|
||||
animatedValueTag: ?number,
|
||||
|};
|
||||
|
||||
// The config has different keys depending on the type of the Node
|
||||
// TODO(T54896888): Make these types strict
|
||||
export type AnimatedNodeConfig = Object;
|
||||
export type AnimatingNodeConfig = Object;
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+createAnimatedNode: (tag: number, config: AnimatedNodeConfig) => void;
|
||||
+startListeningToAnimatedNodeValue: (tag: number) => void;
|
||||
+stopListeningToAnimatedNodeValue: (tag: number) => void;
|
||||
+connectAnimatedNodes: (parentTag: number, childTag: number) => void;
|
||||
+disconnectAnimatedNodes: (parentTag: number, childTag: number) => void;
|
||||
+startAnimatingNode: (
|
||||
animationId: number,
|
||||
nodeTag: number,
|
||||
config: AnimatingNodeConfig,
|
||||
endCallback: EndCallback,
|
||||
) => void;
|
||||
+stopAnimation: (animationId: number) => void;
|
||||
+setAnimatedNodeValue: (nodeTag: number, value: number) => void;
|
||||
+setAnimatedNodeOffset: (nodeTag: number, offset: number) => void;
|
||||
+flattenAnimatedNodeOffset: (nodeTag: number) => void;
|
||||
+extractAnimatedNodeOffset: (nodeTag: number) => void;
|
||||
+connectAnimatedNodeToView: (nodeTag: number, viewTag: number) => void;
|
||||
+disconnectAnimatedNodeFromView: (nodeTag: number, viewTag: number) => void;
|
||||
+restoreDefaultValues: (nodeTag: number) => void;
|
||||
+dropAnimatedNode: (tag: number) => void;
|
||||
+addAnimatedEventToView: (
|
||||
viewTag: number,
|
||||
eventName: string,
|
||||
eventMapping: EventMapping,
|
||||
) => void;
|
||||
+removeAnimatedEventFromView: (
|
||||
viewTag: number,
|
||||
eventName: string,
|
||||
animatedNodeTag: number,
|
||||
) => void;
|
||||
|
||||
// Events
|
||||
+addListener: (eventName: string) => void;
|
||||
+removeListeners: (count: number) => void;
|
||||
}
|
||||
|
||||
export default (TurboModuleRegistry.get<Spec>('NativeAnimatedModule'): ?Spec);
|
103
node_modules/react-native/Libraries/Animated/src/SpringConfig.js
generated
vendored
Normal file
103
node_modules/react-native/Libraries/Animated/src/SpringConfig.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
type SpringConfigType = {
|
||||
stiffness: number,
|
||||
damping: number,
|
||||
...
|
||||
};
|
||||
|
||||
function stiffnessFromOrigamiValue(oValue) {
|
||||
return (oValue - 30) * 3.62 + 194;
|
||||
}
|
||||
|
||||
function dampingFromOrigamiValue(oValue) {
|
||||
return (oValue - 8) * 3 + 25;
|
||||
}
|
||||
|
||||
function fromOrigamiTensionAndFriction(
|
||||
tension: number,
|
||||
friction: number,
|
||||
): SpringConfigType {
|
||||
return {
|
||||
stiffness: stiffnessFromOrigamiValue(tension),
|
||||
damping: dampingFromOrigamiValue(friction),
|
||||
};
|
||||
}
|
||||
|
||||
function fromBouncinessAndSpeed(
|
||||
bounciness: number,
|
||||
speed: number,
|
||||
): SpringConfigType {
|
||||
function normalize(value, startValue, endValue) {
|
||||
return (value - startValue) / (endValue - startValue);
|
||||
}
|
||||
|
||||
function projectNormal(n, start, end) {
|
||||
return start + n * (end - start);
|
||||
}
|
||||
|
||||
function linearInterpolation(t, start, end) {
|
||||
return t * end + (1 - t) * start;
|
||||
}
|
||||
|
||||
function quadraticOutInterpolation(t, start, end) {
|
||||
return linearInterpolation(2 * t - t * t, start, end);
|
||||
}
|
||||
|
||||
function b3Friction1(x) {
|
||||
return 0.0007 * Math.pow(x, 3) - 0.031 * Math.pow(x, 2) + 0.64 * x + 1.28;
|
||||
}
|
||||
|
||||
function b3Friction2(x) {
|
||||
return 0.000044 * Math.pow(x, 3) - 0.006 * Math.pow(x, 2) + 0.36 * x + 2;
|
||||
}
|
||||
|
||||
function b3Friction3(x) {
|
||||
return (
|
||||
0.00000045 * Math.pow(x, 3) -
|
||||
0.000332 * Math.pow(x, 2) +
|
||||
0.1078 * x +
|
||||
5.84
|
||||
);
|
||||
}
|
||||
|
||||
function b3Nobounce(tension) {
|
||||
if (tension <= 18) {
|
||||
return b3Friction1(tension);
|
||||
} else if (tension > 18 && tension <= 44) {
|
||||
return b3Friction2(tension);
|
||||
} else {
|
||||
return b3Friction3(tension);
|
||||
}
|
||||
}
|
||||
|
||||
let b = normalize(bounciness / 1.7, 0, 20);
|
||||
b = projectNormal(b, 0, 0.8);
|
||||
const s = normalize(speed / 1.7, 0, 20);
|
||||
const bouncyTension = projectNormal(s, 0.5, 200);
|
||||
const bouncyFriction = quadraticOutInterpolation(
|
||||
b,
|
||||
b3Nobounce(bouncyTension),
|
||||
0.01,
|
||||
);
|
||||
|
||||
return {
|
||||
stiffness: stiffnessFromOrigamiValue(bouncyTension),
|
||||
damping: dampingFromOrigamiValue(bouncyFriction),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fromOrigamiTensionAndFriction,
|
||||
fromBouncinessAndSpeed,
|
||||
};
|
73
node_modules/react-native/Libraries/Animated/src/animations/Animation.js
generated
vendored
Normal file
73
node_modules/react-native/Libraries/Animated/src/animations/Animation.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
import type AnimatedValue from '../nodes/AnimatedValue';
|
||||
|
||||
export type EndResult = {finished: boolean, ...};
|
||||
export type EndCallback = (result: EndResult) => void;
|
||||
|
||||
export type AnimationConfig = {
|
||||
isInteraction?: boolean,
|
||||
useNativeDriver: boolean,
|
||||
onComplete?: ?EndCallback,
|
||||
iterations?: number,
|
||||
};
|
||||
|
||||
// Important note: start() and stop() will only be called at most once.
|
||||
// Once an animation has been stopped or finished its course, it will
|
||||
// not be reused.
|
||||
class Animation {
|
||||
__active: boolean;
|
||||
__isInteraction: boolean;
|
||||
__nativeId: number;
|
||||
__onEnd: ?EndCallback;
|
||||
__iterations: number;
|
||||
start(
|
||||
fromValue: number,
|
||||
onUpdate: (value: number) => void,
|
||||
onEnd: ?EndCallback,
|
||||
previousAnimation: ?Animation,
|
||||
animatedValue: AnimatedValue,
|
||||
): void {}
|
||||
stop(): void {
|
||||
if (this.__nativeId) {
|
||||
NativeAnimatedHelper.API.stopAnimation(this.__nativeId);
|
||||
}
|
||||
}
|
||||
__getNativeAnimationConfig(): any {
|
||||
// Subclasses that have corresponding animation implementation done in native
|
||||
// should override this method
|
||||
throw new Error('This animation type cannot be offloaded to native');
|
||||
}
|
||||
// Helper function for subclasses to make sure onEnd is only called once.
|
||||
__debouncedOnEnd(result: EndResult): void {
|
||||
const onEnd = this.__onEnd;
|
||||
this.__onEnd = null;
|
||||
onEnd && onEnd(result);
|
||||
}
|
||||
__startNativeAnimation(animatedValue: AnimatedValue): void {
|
||||
NativeAnimatedHelper.API.enableQueue();
|
||||
animatedValue.__makeNative();
|
||||
NativeAnimatedHelper.API.disableQueue();
|
||||
this.__nativeId = NativeAnimatedHelper.generateNewAnimationId();
|
||||
NativeAnimatedHelper.API.startAnimatingNode(
|
||||
this.__nativeId,
|
||||
animatedValue.__getNativeTag(),
|
||||
this.__getNativeAnimationConfig(),
|
||||
this.__debouncedOnEnd.bind(this),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Animation;
|
120
node_modules/react-native/Libraries/Animated/src/animations/DecayAnimation.js
generated
vendored
Normal file
120
node_modules/react-native/Libraries/Animated/src/animations/DecayAnimation.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Animation = require('./Animation');
|
||||
|
||||
const {shouldUseNativeDriver} = require('../NativeAnimatedHelper');
|
||||
|
||||
import type AnimatedValue from '../nodes/AnimatedValue';
|
||||
import type {AnimationConfig, EndCallback} from './Animation';
|
||||
|
||||
export type DecayAnimationConfig = {
|
||||
...AnimationConfig,
|
||||
velocity:
|
||||
| number
|
||||
| {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
},
|
||||
deceleration?: number,
|
||||
};
|
||||
|
||||
export type DecayAnimationConfigSingle = {
|
||||
...AnimationConfig,
|
||||
velocity: number,
|
||||
deceleration?: number,
|
||||
};
|
||||
|
||||
class DecayAnimation extends Animation {
|
||||
_startTime: number;
|
||||
_lastValue: number;
|
||||
_fromValue: number;
|
||||
_deceleration: number;
|
||||
_velocity: number;
|
||||
_onUpdate: (value: number) => void;
|
||||
_animationFrame: any;
|
||||
_useNativeDriver: boolean;
|
||||
|
||||
constructor(config: DecayAnimationConfigSingle) {
|
||||
super();
|
||||
this._deceleration = config.deceleration ?? 0.998;
|
||||
this._velocity = config.velocity;
|
||||
this._useNativeDriver = shouldUseNativeDriver(config);
|
||||
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
|
||||
this.__iterations = config.iterations ?? 1;
|
||||
}
|
||||
|
||||
__getNativeAnimationConfig(): {|
|
||||
deceleration: number,
|
||||
iterations: number,
|
||||
type: $TEMPORARY$string<'decay'>,
|
||||
velocity: number,
|
||||
|} {
|
||||
return {
|
||||
type: 'decay',
|
||||
deceleration: this._deceleration,
|
||||
velocity: this._velocity,
|
||||
iterations: this.__iterations,
|
||||
};
|
||||
}
|
||||
|
||||
start(
|
||||
fromValue: number,
|
||||
onUpdate: (value: number) => void,
|
||||
onEnd: ?EndCallback,
|
||||
previousAnimation: ?Animation,
|
||||
animatedValue: AnimatedValue,
|
||||
): void {
|
||||
this.__active = true;
|
||||
this._lastValue = fromValue;
|
||||
this._fromValue = fromValue;
|
||||
this._onUpdate = onUpdate;
|
||||
this.__onEnd = onEnd;
|
||||
this._startTime = Date.now();
|
||||
if (this._useNativeDriver) {
|
||||
this.__startNativeAnimation(animatedValue);
|
||||
} else {
|
||||
this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
onUpdate(): void {
|
||||
const now = Date.now();
|
||||
|
||||
const value =
|
||||
this._fromValue +
|
||||
(this._velocity / (1 - this._deceleration)) *
|
||||
(1 - Math.exp(-(1 - this._deceleration) * (now - this._startTime)));
|
||||
|
||||
this._onUpdate(value);
|
||||
|
||||
if (Math.abs(this._lastValue - value) < 0.1) {
|
||||
this.__debouncedOnEnd({finished: true});
|
||||
return;
|
||||
}
|
||||
|
||||
this._lastValue = value;
|
||||
if (this.__active) {
|
||||
this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
super.stop();
|
||||
this.__active = false;
|
||||
global.cancelAnimationFrame(this._animationFrame);
|
||||
this.__debouncedOnEnd({finished: false});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DecayAnimation;
|
359
node_modules/react-native/Libraries/Animated/src/animations/SpringAnimation.js
generated
vendored
Normal file
359
node_modules/react-native/Libraries/Animated/src/animations/SpringAnimation.js
generated
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('../nodes/AnimatedValue');
|
||||
const AnimatedValueXY = require('../nodes/AnimatedValueXY');
|
||||
const AnimatedInterpolation = require('../nodes/AnimatedInterpolation');
|
||||
const Animation = require('./Animation');
|
||||
const SpringConfig = require('../SpringConfig');
|
||||
|
||||
const invariant = require('invariant');
|
||||
|
||||
const {shouldUseNativeDriver} = require('../NativeAnimatedHelper');
|
||||
|
||||
import type {AnimationConfig, EndCallback} from './Animation';
|
||||
|
||||
export type SpringAnimationConfig = {
|
||||
...AnimationConfig,
|
||||
toValue:
|
||||
| number
|
||||
| AnimatedValue
|
||||
| {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
}
|
||||
| AnimatedValueXY
|
||||
| AnimatedInterpolation,
|
||||
overshootClamping?: boolean,
|
||||
restDisplacementThreshold?: number,
|
||||
restSpeedThreshold?: number,
|
||||
velocity?:
|
||||
| number
|
||||
| {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
},
|
||||
bounciness?: number,
|
||||
speed?: number,
|
||||
tension?: number,
|
||||
friction?: number,
|
||||
stiffness?: number,
|
||||
damping?: number,
|
||||
mass?: number,
|
||||
delay?: number,
|
||||
};
|
||||
|
||||
export type SpringAnimationConfigSingle = {
|
||||
...AnimationConfig,
|
||||
toValue: number | AnimatedValue | AnimatedInterpolation,
|
||||
overshootClamping?: boolean,
|
||||
restDisplacementThreshold?: number,
|
||||
restSpeedThreshold?: number,
|
||||
velocity?: number,
|
||||
bounciness?: number,
|
||||
speed?: number,
|
||||
tension?: number,
|
||||
friction?: number,
|
||||
stiffness?: number,
|
||||
damping?: number,
|
||||
mass?: number,
|
||||
delay?: number,
|
||||
};
|
||||
|
||||
class SpringAnimation extends Animation {
|
||||
_overshootClamping: boolean;
|
||||
_restDisplacementThreshold: number;
|
||||
_restSpeedThreshold: number;
|
||||
_lastVelocity: number;
|
||||
_startPosition: number;
|
||||
_lastPosition: number;
|
||||
_fromValue: number;
|
||||
_toValue: any;
|
||||
_stiffness: number;
|
||||
_damping: number;
|
||||
_mass: number;
|
||||
_initialVelocity: number;
|
||||
_delay: number;
|
||||
_timeout: any;
|
||||
_startTime: number;
|
||||
_lastTime: number;
|
||||
_frameTime: number;
|
||||
_onUpdate: (value: number) => void;
|
||||
_animationFrame: any;
|
||||
_useNativeDriver: boolean;
|
||||
|
||||
constructor(config: SpringAnimationConfigSingle) {
|
||||
super();
|
||||
|
||||
this._overshootClamping = config.overshootClamping ?? false;
|
||||
this._restDisplacementThreshold = config.restDisplacementThreshold ?? 0.001;
|
||||
this._restSpeedThreshold = config.restSpeedThreshold ?? 0.001;
|
||||
this._initialVelocity = config.velocity ?? 0;
|
||||
this._lastVelocity = config.velocity ?? 0;
|
||||
this._toValue = config.toValue;
|
||||
this._delay = config.delay ?? 0;
|
||||
this._useNativeDriver = shouldUseNativeDriver(config);
|
||||
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
|
||||
this.__iterations = config.iterations ?? 1;
|
||||
|
||||
if (
|
||||
config.stiffness !== undefined ||
|
||||
config.damping !== undefined ||
|
||||
config.mass !== undefined
|
||||
) {
|
||||
invariant(
|
||||
config.bounciness === undefined &&
|
||||
config.speed === undefined &&
|
||||
config.tension === undefined &&
|
||||
config.friction === undefined,
|
||||
'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one',
|
||||
);
|
||||
this._stiffness = config.stiffness ?? 100;
|
||||
this._damping = config.damping ?? 10;
|
||||
this._mass = config.mass ?? 1;
|
||||
} else if (config.bounciness !== undefined || config.speed !== undefined) {
|
||||
// Convert the origami bounciness/speed values to stiffness/damping
|
||||
// We assume mass is 1.
|
||||
invariant(
|
||||
config.tension === undefined &&
|
||||
config.friction === undefined &&
|
||||
config.stiffness === undefined &&
|
||||
config.damping === undefined &&
|
||||
config.mass === undefined,
|
||||
'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one',
|
||||
);
|
||||
const springConfig = SpringConfig.fromBouncinessAndSpeed(
|
||||
config.bounciness ?? 8,
|
||||
config.speed ?? 12,
|
||||
);
|
||||
this._stiffness = springConfig.stiffness;
|
||||
this._damping = springConfig.damping;
|
||||
this._mass = 1;
|
||||
} else {
|
||||
// Convert the origami tension/friction values to stiffness/damping
|
||||
// We assume mass is 1.
|
||||
const springConfig = SpringConfig.fromOrigamiTensionAndFriction(
|
||||
config.tension ?? 40,
|
||||
config.friction ?? 7,
|
||||
);
|
||||
this._stiffness = springConfig.stiffness;
|
||||
this._damping = springConfig.damping;
|
||||
this._mass = 1;
|
||||
}
|
||||
|
||||
invariant(this._stiffness > 0, 'Stiffness value must be greater than 0');
|
||||
invariant(this._damping > 0, 'Damping value must be greater than 0');
|
||||
invariant(this._mass > 0, 'Mass value must be greater than 0');
|
||||
}
|
||||
|
||||
__getNativeAnimationConfig(): {|
|
||||
damping: number,
|
||||
initialVelocity: number,
|
||||
iterations: number,
|
||||
mass: number,
|
||||
overshootClamping: boolean,
|
||||
restDisplacementThreshold: number,
|
||||
restSpeedThreshold: number,
|
||||
stiffness: number,
|
||||
toValue: any,
|
||||
type: $TEMPORARY$string<'spring'>,
|
||||
|} {
|
||||
return {
|
||||
type: 'spring',
|
||||
overshootClamping: this._overshootClamping,
|
||||
restDisplacementThreshold: this._restDisplacementThreshold,
|
||||
restSpeedThreshold: this._restSpeedThreshold,
|
||||
stiffness: this._stiffness,
|
||||
damping: this._damping,
|
||||
mass: this._mass,
|
||||
initialVelocity: this._initialVelocity ?? this._lastVelocity,
|
||||
toValue: this._toValue,
|
||||
iterations: this.__iterations,
|
||||
};
|
||||
}
|
||||
|
||||
start(
|
||||
fromValue: number,
|
||||
onUpdate: (value: number) => void,
|
||||
onEnd: ?EndCallback,
|
||||
previousAnimation: ?Animation,
|
||||
animatedValue: AnimatedValue,
|
||||
): void {
|
||||
this.__active = true;
|
||||
this._startPosition = fromValue;
|
||||
this._lastPosition = this._startPosition;
|
||||
|
||||
this._onUpdate = onUpdate;
|
||||
this.__onEnd = onEnd;
|
||||
this._lastTime = Date.now();
|
||||
this._frameTime = 0.0;
|
||||
|
||||
if (previousAnimation instanceof SpringAnimation) {
|
||||
const internalState = previousAnimation.getInternalState();
|
||||
this._lastPosition = internalState.lastPosition;
|
||||
this._lastVelocity = internalState.lastVelocity;
|
||||
// Set the initial velocity to the last velocity
|
||||
this._initialVelocity = this._lastVelocity;
|
||||
this._lastTime = internalState.lastTime;
|
||||
}
|
||||
|
||||
const start = () => {
|
||||
if (this._useNativeDriver) {
|
||||
this.__startNativeAnimation(animatedValue);
|
||||
} else {
|
||||
this.onUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// If this._delay is more than 0, we start after the timeout.
|
||||
if (this._delay) {
|
||||
this._timeout = setTimeout(start, this._delay);
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
getInternalState(): Object {
|
||||
return {
|
||||
lastPosition: this._lastPosition,
|
||||
lastVelocity: this._lastVelocity,
|
||||
lastTime: this._lastTime,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This spring model is based off of a damped harmonic oscillator
|
||||
* (https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator).
|
||||
*
|
||||
* We use the closed form of the second order differential equation:
|
||||
*
|
||||
* x'' + (2ζ⍵_0)x' + ⍵^2x = 0
|
||||
*
|
||||
* where
|
||||
* ⍵_0 = √(k / m) (undamped angular frequency of the oscillator),
|
||||
* ζ = c / 2√mk (damping ratio),
|
||||
* c = damping constant
|
||||
* k = stiffness
|
||||
* m = mass
|
||||
*
|
||||
* The derivation of the closed form is described in detail here:
|
||||
* http://planetmath.org/sites/default/files/texpdf/39745.pdf
|
||||
*
|
||||
* This algorithm happens to match the algorithm used by CASpringAnimation,
|
||||
* a QuartzCore (iOS) API that creates spring animations.
|
||||
*/
|
||||
onUpdate(): void {
|
||||
// If for some reason we lost a lot of frames (e.g. process large payload or
|
||||
// stopped in the debugger), we only advance by 4 frames worth of
|
||||
// computation and will continue on the next frame. It's better to have it
|
||||
// running at faster speed than jumping to the end.
|
||||
const MAX_STEPS = 64;
|
||||
let now = Date.now();
|
||||
if (now > this._lastTime + MAX_STEPS) {
|
||||
now = this._lastTime + MAX_STEPS;
|
||||
}
|
||||
|
||||
const deltaTime = (now - this._lastTime) / 1000;
|
||||
this._frameTime += deltaTime;
|
||||
|
||||
const c: number = this._damping;
|
||||
const m: number = this._mass;
|
||||
const k: number = this._stiffness;
|
||||
const v0: number = -this._initialVelocity;
|
||||
|
||||
const zeta = c / (2 * Math.sqrt(k * m)); // damping ratio
|
||||
const omega0 = Math.sqrt(k / m); // undamped angular frequency of the oscillator (rad/ms)
|
||||
const omega1 = omega0 * Math.sqrt(1.0 - zeta * zeta); // exponential decay
|
||||
const x0 = this._toValue - this._startPosition; // calculate the oscillation from x0 = 1 to x = 0
|
||||
|
||||
let position = 0.0;
|
||||
let velocity = 0.0;
|
||||
const t = this._frameTime;
|
||||
if (zeta < 1) {
|
||||
// Under damped
|
||||
const envelope = Math.exp(-zeta * omega0 * t);
|
||||
position =
|
||||
this._toValue -
|
||||
envelope *
|
||||
(((v0 + zeta * omega0 * x0) / omega1) * Math.sin(omega1 * t) +
|
||||
x0 * Math.cos(omega1 * t));
|
||||
// This looks crazy -- it's actually just the derivative of the
|
||||
// oscillation function
|
||||
velocity =
|
||||
zeta *
|
||||
omega0 *
|
||||
envelope *
|
||||
((Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0)) / omega1 +
|
||||
x0 * Math.cos(omega1 * t)) -
|
||||
envelope *
|
||||
(Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0) -
|
||||
omega1 * x0 * Math.sin(omega1 * t));
|
||||
} else {
|
||||
// Critically damped
|
||||
const envelope = Math.exp(-omega0 * t);
|
||||
position = this._toValue - envelope * (x0 + (v0 + omega0 * x0) * t);
|
||||
velocity =
|
||||
envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0));
|
||||
}
|
||||
|
||||
this._lastTime = now;
|
||||
this._lastPosition = position;
|
||||
this._lastVelocity = velocity;
|
||||
|
||||
this._onUpdate(position);
|
||||
if (!this.__active) {
|
||||
// a listener might have stopped us in _onUpdate
|
||||
return;
|
||||
}
|
||||
|
||||
// Conditions for stopping the spring animation
|
||||
let isOvershooting = false;
|
||||
if (this._overshootClamping && this._stiffness !== 0) {
|
||||
if (this._startPosition < this._toValue) {
|
||||
isOvershooting = position > this._toValue;
|
||||
} else {
|
||||
isOvershooting = position < this._toValue;
|
||||
}
|
||||
}
|
||||
const isVelocity = Math.abs(velocity) <= this._restSpeedThreshold;
|
||||
let isDisplacement = true;
|
||||
if (this._stiffness !== 0) {
|
||||
isDisplacement =
|
||||
Math.abs(this._toValue - position) <= this._restDisplacementThreshold;
|
||||
}
|
||||
|
||||
if (isOvershooting || (isVelocity && isDisplacement)) {
|
||||
if (this._stiffness !== 0) {
|
||||
// Ensure that we end up with a round value
|
||||
this._lastPosition = this._toValue;
|
||||
this._lastVelocity = 0;
|
||||
this._onUpdate(this._toValue);
|
||||
}
|
||||
|
||||
this.__debouncedOnEnd({finished: true});
|
||||
return;
|
||||
}
|
||||
this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
super.stop();
|
||||
this.__active = false;
|
||||
clearTimeout(this._timeout);
|
||||
global.cancelAnimationFrame(this._animationFrame);
|
||||
this.__debouncedOnEnd({finished: false});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SpringAnimation;
|
165
node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js
generated
vendored
Normal file
165
node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('../nodes/AnimatedValue');
|
||||
const AnimatedValueXY = require('../nodes/AnimatedValueXY');
|
||||
const AnimatedInterpolation = require('../nodes/AnimatedInterpolation');
|
||||
const Animation = require('./Animation');
|
||||
|
||||
const {shouldUseNativeDriver} = require('../NativeAnimatedHelper');
|
||||
|
||||
import type {AnimationConfig, EndCallback} from './Animation';
|
||||
|
||||
export type TimingAnimationConfig = {
|
||||
...AnimationConfig,
|
||||
toValue:
|
||||
| number
|
||||
| AnimatedValue
|
||||
| {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
}
|
||||
| AnimatedValueXY
|
||||
| AnimatedInterpolation,
|
||||
easing?: (value: number) => number,
|
||||
duration?: number,
|
||||
delay?: number,
|
||||
};
|
||||
|
||||
export type TimingAnimationConfigSingle = {
|
||||
...AnimationConfig,
|
||||
toValue: number | AnimatedValue | AnimatedInterpolation,
|
||||
easing?: (value: number) => number,
|
||||
duration?: number,
|
||||
delay?: number,
|
||||
};
|
||||
|
||||
let _easeInOut;
|
||||
function easeInOut() {
|
||||
if (!_easeInOut) {
|
||||
const Easing = require('../Easing');
|
||||
_easeInOut = Easing.inOut(Easing.ease);
|
||||
}
|
||||
return _easeInOut;
|
||||
}
|
||||
|
||||
class TimingAnimation extends Animation {
|
||||
_startTime: number;
|
||||
_fromValue: number;
|
||||
_toValue: any;
|
||||
_duration: number;
|
||||
_delay: number;
|
||||
_easing: (value: number) => number;
|
||||
_onUpdate: (value: number) => void;
|
||||
_animationFrame: any;
|
||||
_timeout: any;
|
||||
_useNativeDriver: boolean;
|
||||
|
||||
constructor(config: TimingAnimationConfigSingle) {
|
||||
super();
|
||||
this._toValue = config.toValue;
|
||||
this._easing = config.easing ?? easeInOut();
|
||||
this._duration = config.duration ?? 500;
|
||||
this._delay = config.delay ?? 0;
|
||||
this.__iterations = config.iterations ?? 1;
|
||||
this._useNativeDriver = shouldUseNativeDriver(config);
|
||||
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
|
||||
}
|
||||
|
||||
__getNativeAnimationConfig(): any {
|
||||
const frameDuration = 1000.0 / 60.0;
|
||||
const frames = [];
|
||||
const numFrames = Math.round(this._duration / frameDuration);
|
||||
for (let frame = 0; frame < numFrames; frame++) {
|
||||
frames.push(this._easing(frame / numFrames));
|
||||
}
|
||||
frames.push(this._easing(1));
|
||||
return {
|
||||
type: 'frames',
|
||||
frames,
|
||||
toValue: this._toValue,
|
||||
iterations: this.__iterations,
|
||||
};
|
||||
}
|
||||
|
||||
start(
|
||||
fromValue: number,
|
||||
onUpdate: (value: number) => void,
|
||||
onEnd: ?EndCallback,
|
||||
previousAnimation: ?Animation,
|
||||
animatedValue: AnimatedValue,
|
||||
): void {
|
||||
this.__active = true;
|
||||
this._fromValue = fromValue;
|
||||
this._onUpdate = onUpdate;
|
||||
this.__onEnd = onEnd;
|
||||
|
||||
const start = () => {
|
||||
// Animations that sometimes have 0 duration and sometimes do not
|
||||
// still need to use the native driver when duration is 0 so as to
|
||||
// not cause intermixed JS and native animations.
|
||||
if (this._duration === 0 && !this._useNativeDriver) {
|
||||
this._onUpdate(this._toValue);
|
||||
this.__debouncedOnEnd({finished: true});
|
||||
} else {
|
||||
this._startTime = Date.now();
|
||||
if (this._useNativeDriver) {
|
||||
this.__startNativeAnimation(animatedValue);
|
||||
} else {
|
||||
this._animationFrame = requestAnimationFrame(
|
||||
this.onUpdate.bind(this),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this._delay) {
|
||||
this._timeout = setTimeout(start, this._delay);
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
onUpdate(): void {
|
||||
const now = Date.now();
|
||||
if (now >= this._startTime + this._duration) {
|
||||
if (this._duration === 0) {
|
||||
this._onUpdate(this._toValue);
|
||||
} else {
|
||||
this._onUpdate(
|
||||
this._fromValue + this._easing(1) * (this._toValue - this._fromValue),
|
||||
);
|
||||
}
|
||||
this.__debouncedOnEnd({finished: true});
|
||||
return;
|
||||
}
|
||||
|
||||
this._onUpdate(
|
||||
this._fromValue +
|
||||
this._easing((now - this._startTime) / this._duration) *
|
||||
(this._toValue - this._fromValue),
|
||||
);
|
||||
if (this.__active) {
|
||||
this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
super.stop();
|
||||
this.__active = false;
|
||||
clearTimeout(this._timeout);
|
||||
global.cancelAnimationFrame(this._animationFrame);
|
||||
this.__debouncedOnEnd({finished: false});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TimingAnimation;
|
153
node_modules/react-native/Libraries/Animated/src/bezier.js
generated
vendored
Normal file
153
node_modules/react-native/Libraries/Animated/src/bezier.js
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Portions Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
/**
|
||||
* BezierEasing - use bezier curve for transition easing function
|
||||
* https://github.com/gre/bezier-easing
|
||||
* @copyright 2014-2015 Gaëtan Renaudeau. MIT License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// These values are established by empiricism with tests (tradeoff: performance VS precision)
|
||||
const NEWTON_ITERATIONS = 4;
|
||||
const NEWTON_MIN_SLOPE = 0.001;
|
||||
const SUBDIVISION_PRECISION = 0.0000001;
|
||||
const SUBDIVISION_MAX_ITERATIONS = 10;
|
||||
|
||||
const kSplineTableSize = 11;
|
||||
const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
||||
|
||||
const float32ArraySupported = typeof Float32Array === 'function';
|
||||
|
||||
function A(aA1, aA2) {
|
||||
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
|
||||
}
|
||||
function B(aA1, aA2) {
|
||||
return 3.0 * aA2 - 6.0 * aA1;
|
||||
}
|
||||
function C(aA1) {
|
||||
return 3.0 * aA1;
|
||||
}
|
||||
|
||||
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
||||
function calcBezier(aT, aA1, aA2) {
|
||||
return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
|
||||
}
|
||||
|
||||
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
||||
function getSlope(aT, aA1, aA2) {
|
||||
return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
|
||||
}
|
||||
|
||||
function binarySubdivide(aX, _aA, _aB, mX1, mX2) {
|
||||
let currentX,
|
||||
currentT,
|
||||
i = 0,
|
||||
aA = _aA,
|
||||
aB = _aB;
|
||||
do {
|
||||
currentT = aA + (aB - aA) / 2.0;
|
||||
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
||||
if (currentX > 0.0) {
|
||||
aB = currentT;
|
||||
} else {
|
||||
aA = currentT;
|
||||
}
|
||||
} while (
|
||||
Math.abs(currentX) > SUBDIVISION_PRECISION &&
|
||||
++i < SUBDIVISION_MAX_ITERATIONS
|
||||
);
|
||||
return currentT;
|
||||
}
|
||||
|
||||
function newtonRaphsonIterate(aX, _aGuessT, mX1, mX2) {
|
||||
let aGuessT = _aGuessT;
|
||||
for (let i = 0; i < NEWTON_ITERATIONS; ++i) {
|
||||
const currentSlope = getSlope(aGuessT, mX1, mX2);
|
||||
if (currentSlope === 0.0) {
|
||||
return aGuessT;
|
||||
}
|
||||
const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
|
||||
aGuessT -= currentX / currentSlope;
|
||||
}
|
||||
return aGuessT;
|
||||
}
|
||||
|
||||
module.exports = function bezier(
|
||||
mX1: number,
|
||||
mY1: number,
|
||||
mX2: number,
|
||||
mY2: number,
|
||||
): (x: number) => number {
|
||||
if (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {
|
||||
throw new Error('bezier x values must be in [0, 1] range');
|
||||
}
|
||||
|
||||
// Precompute samples table
|
||||
const sampleValues = float32ArraySupported
|
||||
? new Float32Array(kSplineTableSize)
|
||||
: new Array(kSplineTableSize);
|
||||
if (mX1 !== mY1 || mX2 !== mY2) {
|
||||
for (let i = 0; i < kSplineTableSize; ++i) {
|
||||
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
||||
}
|
||||
}
|
||||
|
||||
function getTForX(aX) {
|
||||
let intervalStart = 0.0;
|
||||
let currentSample = 1;
|
||||
const lastSample = kSplineTableSize - 1;
|
||||
|
||||
for (
|
||||
;
|
||||
currentSample !== lastSample && sampleValues[currentSample] <= aX;
|
||||
++currentSample
|
||||
) {
|
||||
intervalStart += kSampleStepSize;
|
||||
}
|
||||
--currentSample;
|
||||
|
||||
// Interpolate to provide an initial guess for t
|
||||
const dist =
|
||||
(aX - sampleValues[currentSample]) /
|
||||
(sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
||||
const guessForT = intervalStart + dist * kSampleStepSize;
|
||||
|
||||
const initialSlope = getSlope(guessForT, mX1, mX2);
|
||||
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
||||
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
||||
} else if (initialSlope === 0.0) {
|
||||
return guessForT;
|
||||
} else {
|
||||
return binarySubdivide(
|
||||
aX,
|
||||
intervalStart,
|
||||
intervalStart + kSampleStepSize,
|
||||
mX1,
|
||||
mX2,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return function BezierEasing(x: number): number {
|
||||
if (mX1 === mY1 && mX2 === mY2) {
|
||||
return x; // linear
|
||||
}
|
||||
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
||||
if (x === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (x === 1) {
|
||||
return 1;
|
||||
}
|
||||
return calcBezier(getTForX(x), mY1, mY2);
|
||||
};
|
||||
};
|
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedFlatList.js
generated
vendored
Normal file
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedFlatList.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const FlatList = require('../../../Lists/FlatList');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
/**
|
||||
* @see https://github.com/facebook/react-native/commit/b8c8562
|
||||
*/
|
||||
const FlatListWithEventThrottle = React.forwardRef((props, ref) => (
|
||||
<FlatList scrollEventThrottle={0.0001} {...props} ref={ref} />
|
||||
));
|
||||
|
||||
module.exports = (createAnimatedComponent(
|
||||
FlatListWithEventThrottle,
|
||||
): AnimatedComponentType<
|
||||
React.ElementConfig<typeof FlatList>,
|
||||
React.ElementRef<typeof FlatList>,
|
||||
>);
|
25
node_modules/react-native/Libraries/Animated/src/components/AnimatedImage.js
generated
vendored
Normal file
25
node_modules/react-native/Libraries/Animated/src/components/AnimatedImage.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const Image = require('../../../Image/Image');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
module.exports = (createAnimatedComponent(
|
||||
(Image: $FlowFixMe),
|
||||
): AnimatedComponentType<
|
||||
React.ElementConfig<typeof Image>,
|
||||
React.ElementRef<typeof Image>,
|
||||
>);
|
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedScrollView.js
generated
vendored
Normal file
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedScrollView.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const ScrollView = require('../../../Components/ScrollView/ScrollView');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
/**
|
||||
* @see https://github.com/facebook/react-native/commit/b8c8562
|
||||
*/
|
||||
const ScrollViewWithEventThrottle = React.forwardRef((props, ref) => (
|
||||
<ScrollView scrollEventThrottle={0.0001} {...props} ref={ref} />
|
||||
));
|
||||
|
||||
module.exports = (createAnimatedComponent(
|
||||
ScrollViewWithEventThrottle,
|
||||
): AnimatedComponentType<
|
||||
React.ElementConfig<typeof ScrollView>,
|
||||
React.ElementRef<typeof ScrollView>,
|
||||
>);
|
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedSectionList.js
generated
vendored
Normal file
32
node_modules/react-native/Libraries/Animated/src/components/AnimatedSectionList.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const SectionList = require('../../../Lists/SectionList');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
/**
|
||||
* @see https://github.com/facebook/react-native/commit/b8c8562
|
||||
*/
|
||||
const SectionListWithEventThrottle = React.forwardRef((props, ref) => (
|
||||
<SectionList scrollEventThrottle={0.0001} {...props} ref={ref} />
|
||||
));
|
||||
|
||||
module.exports = (createAnimatedComponent(
|
||||
SectionListWithEventThrottle,
|
||||
): AnimatedComponentType<
|
||||
React.ElementConfig<typeof SectionList>,
|
||||
React.ElementRef<typeof SectionList>,
|
||||
>);
|
25
node_modules/react-native/Libraries/Animated/src/components/AnimatedText.js
generated
vendored
Normal file
25
node_modules/react-native/Libraries/Animated/src/components/AnimatedText.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const Text = require('../../../Text/Text');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
module.exports = (createAnimatedComponent(
|
||||
(Text: $FlowFixMe),
|
||||
): AnimatedComponentType<
|
||||
React.ElementConfig<typeof Text>,
|
||||
React.ElementRef<typeof Text>,
|
||||
>);
|
23
node_modules/react-native/Libraries/Animated/src/components/AnimatedView.js
generated
vendored
Normal file
23
node_modules/react-native/Libraries/Animated/src/components/AnimatedView.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const View = require('../../../Components/View/View');
|
||||
const createAnimatedComponent = require('../createAnimatedComponent');
|
||||
|
||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||
|
||||
module.exports = (createAnimatedComponent(View): AnimatedComponentType<
|
||||
React.ElementConfig<typeof View>,
|
||||
React.ElementRef<typeof View>,
|
||||
>);
|
223
node_modules/react-native/Libraries/Animated/src/createAnimatedComponent.js
generated
vendored
Normal file
223
node_modules/react-native/Libraries/Animated/src/createAnimatedComponent.js
generated
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {AnimatedEvent} = require('./AnimatedEvent');
|
||||
const AnimatedProps = require('./nodes/AnimatedProps');
|
||||
const React = require('react');
|
||||
|
||||
const invariant = require('invariant');
|
||||
const setAndForwardRef = require('../../Utilities/setAndForwardRef');
|
||||
|
||||
export type AnimatedComponentType<
|
||||
Props: {+[string]: mixed, ...},
|
||||
Instance,
|
||||
> = React.AbstractComponent<$ObjMap<Props, () => any>, Instance>;
|
||||
|
||||
function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
|
||||
Component: React.AbstractComponent<Props, Instance>,
|
||||
): AnimatedComponentType<Props, Instance> {
|
||||
invariant(
|
||||
typeof Component !== 'function' ||
|
||||
(Component.prototype && Component.prototype.isReactComponent),
|
||||
'`createAnimatedComponent` does not support stateless functional components; ' +
|
||||
'use a class component instead.',
|
||||
);
|
||||
|
||||
class AnimatedComponent extends React.Component<Object> {
|
||||
_component: any; // TODO T53738161: flow type this, and the whole file
|
||||
_invokeAnimatedPropsCallbackOnMount: boolean = false;
|
||||
_prevComponent: any;
|
||||
_propsAnimated: AnimatedProps;
|
||||
_eventDetachers: Array<Function> = [];
|
||||
|
||||
_attachNativeEvents() {
|
||||
// Make sure to get the scrollable node for components that implement
|
||||
// `ScrollResponder.Mixin`.
|
||||
const scrollableNode = this._component?.getScrollableNode
|
||||
? this._component.getScrollableNode()
|
||||
: this._component;
|
||||
|
||||
for (const key in this.props) {
|
||||
const prop = this.props[key];
|
||||
if (prop instanceof AnimatedEvent && prop.__isNative) {
|
||||
prop.__attach(scrollableNode, key);
|
||||
this._eventDetachers.push(() => prop.__detach(scrollableNode, key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_detachNativeEvents() {
|
||||
this._eventDetachers.forEach(remove => remove());
|
||||
this._eventDetachers = [];
|
||||
}
|
||||
|
||||
// The system is best designed when setNativeProps is implemented. It is
|
||||
// able to avoid re-rendering and directly set the attributes that changed.
|
||||
// However, setNativeProps can only be implemented on leaf native
|
||||
// components. If you want to animate a composite component, you need to
|
||||
// re-render it. In this case, we have a fallback that uses forceUpdate.
|
||||
_animatedPropsCallback = () => {
|
||||
if (this._component == null) {
|
||||
// AnimatedProps is created in will-mount because it's used in render.
|
||||
// But this callback may be invoked before mount in async mode,
|
||||
// In which case we should defer the setNativeProps() call.
|
||||
// React may throw away uncommitted work in async mode,
|
||||
// So a deferred call won't always be invoked.
|
||||
this._invokeAnimatedPropsCallbackOnMount = true;
|
||||
} else if (
|
||||
process.env.NODE_ENV === 'test' ||
|
||||
// For animating properties of non-leaf/non-native components
|
||||
typeof this._component.setNativeProps !== 'function' ||
|
||||
// In Fabric, force animations to go through forceUpdate and skip setNativeProps
|
||||
// eslint-disable-next-line dot-notation
|
||||
this._component['_internalInstanceHandle']?.stateNode?.canonical !=
|
||||
null ||
|
||||
// Some components have a setNativeProps function but aren't a host component
|
||||
// such as lists like FlatList and SectionList. These should also use
|
||||
// forceUpdate in Fabric since setNativeProps doesn't exist on the underlying
|
||||
// host component. This crazy hack is essentially special casing those lists and
|
||||
// ScrollView itself to use forceUpdate in Fabric.
|
||||
// If these components end up using forwardRef then these hacks can go away
|
||||
// as this._component would actually be the underlying host component and the above check
|
||||
// would be sufficient.
|
||||
(this._component.getNativeScrollRef != null &&
|
||||
this._component.getNativeScrollRef() != null &&
|
||||
// eslint-disable-next-line dot-notation
|
||||
this._component.getNativeScrollRef()['_internalInstanceHandle']
|
||||
?.stateNode?.canonical != null) ||
|
||||
(this._component.getScrollResponder != null &&
|
||||
this._component.getScrollResponder().getNativeScrollRef != null &&
|
||||
this._component.getScrollResponder().getNativeScrollRef() != null &&
|
||||
this._component.getScrollResponder().getNativeScrollRef()[
|
||||
// eslint-disable-next-line dot-notation
|
||||
'_internalInstanceHandle'
|
||||
]?.stateNode?.canonical != null)
|
||||
) {
|
||||
this.forceUpdate();
|
||||
} else if (!this._propsAnimated.__isNative) {
|
||||
this._component.setNativeProps(
|
||||
this._propsAnimated.__getAnimatedValue(),
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
'Attempting to run JS driven animation on animated ' +
|
||||
'node that has been moved to "native" earlier by starting an ' +
|
||||
'animation with `useNativeDriver: true`',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_attachProps(nextProps) {
|
||||
const oldPropsAnimated = this._propsAnimated;
|
||||
|
||||
this._propsAnimated = new AnimatedProps(
|
||||
nextProps,
|
||||
this._animatedPropsCallback,
|
||||
);
|
||||
|
||||
// When you call detach, it removes the element from the parent list
|
||||
// of children. If it goes to 0, then the parent also detaches itself
|
||||
// and so on.
|
||||
// An optimization is to attach the new elements and THEN detach the old
|
||||
// ones instead of detaching and THEN attaching.
|
||||
// This way the intermediate state isn't to go to 0 and trigger
|
||||
// this expensive recursive detaching to then re-attach everything on
|
||||
// the very next operation.
|
||||
if (oldPropsAnimated) {
|
||||
oldPropsAnimated.__restoreDefaultValues();
|
||||
oldPropsAnimated.__detach();
|
||||
}
|
||||
}
|
||||
|
||||
_setComponentRef = setAndForwardRef({
|
||||
getForwardedRef: () => this.props.forwardedRef,
|
||||
setLocalRef: ref => {
|
||||
this._prevComponent = this._component;
|
||||
this._component = ref;
|
||||
|
||||
// TODO: Delete this in a future release.
|
||||
if (ref != null && ref.getNode == null) {
|
||||
ref.getNode = () => {
|
||||
console.warn(
|
||||
'%s: Calling `getNode()` on the ref of an Animated component ' +
|
||||
'is no longer necessary. You can now directly use the ref ' +
|
||||
'instead. This method will be removed in a future release.',
|
||||
ref.constructor.name ?? '<<anonymous>>',
|
||||
);
|
||||
return ref;
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
render() {
|
||||
const props = this._propsAnimated.__getValue();
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
ref={this._setComponentRef}
|
||||
// The native driver updates views directly through the UI thread so we
|
||||
// have to make sure the view doesn't get optimized away because it cannot
|
||||
// go through the NativeViewHierarchyManager since it operates on the shadow
|
||||
// thread.
|
||||
collapsable={
|
||||
this._propsAnimated.__isNative ? false : props.collapsable
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this._attachProps(this.props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this._invokeAnimatedPropsCallbackOnMount) {
|
||||
this._invokeAnimatedPropsCallbackOnMount = false;
|
||||
this._animatedPropsCallback();
|
||||
}
|
||||
|
||||
this._propsAnimated.setNativeView(this._component);
|
||||
this._attachNativeEvents();
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
this._attachProps(newProps);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this._component !== this._prevComponent) {
|
||||
this._propsAnimated.setNativeView(this._component);
|
||||
}
|
||||
if (this._component !== this._prevComponent || prevProps !== this.props) {
|
||||
this._detachNativeEvents();
|
||||
this._attachNativeEvents();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._propsAnimated && this._propsAnimated.__detach();
|
||||
this._detachNativeEvents();
|
||||
}
|
||||
}
|
||||
|
||||
return React.forwardRef(function AnimatedComponentWrapper(props, ref) {
|
||||
return (
|
||||
<AnimatedComponent
|
||||
{...props}
|
||||
{...(ref == null ? null : {forwardedRef: ref})}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = createAnimatedComponent;
|
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedAddition.js
generated
vendored
Normal file
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedAddition.js
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedAddition extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_b: AnimatedNode;
|
||||
|
||||
constructor(a: AnimatedNode | number, b: AnimatedNode | number) {
|
||||
super();
|
||||
this._a = typeof a === 'number' ? new AnimatedValue(a) : a;
|
||||
this._b = typeof b === 'number' ? new AnimatedValue(b) : b;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
this._b.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return this._a.__getValue() + this._b.__getValue();
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
this._b.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
this._b.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'addition',
|
||||
input: [this._a.__getNativeTag(), this._b.__getNativeTag()],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedAddition;
|
71
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedDiffClamp.js
generated
vendored
Normal file
71
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedDiffClamp.js
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedDiffClamp extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_min: number;
|
||||
_max: number;
|
||||
_value: number;
|
||||
_lastValue: number;
|
||||
|
||||
constructor(a: AnimatedNode, min: number, max: number) {
|
||||
super();
|
||||
|
||||
this._a = a;
|
||||
this._min = min;
|
||||
this._max = max;
|
||||
this._value = this._lastValue = this._a.__getValue();
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
const value = this._a.__getValue();
|
||||
const diff = value - this._lastValue;
|
||||
this._lastValue = value;
|
||||
this._value = Math.min(Math.max(this._value + diff, this._min), this._max);
|
||||
return this._value;
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'diffclamp',
|
||||
input: this._a.__getNativeTag(),
|
||||
min: this._min,
|
||||
max: this._max,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedDiffClamp;
|
68
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedDivision.js
generated
vendored
Normal file
68
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedDivision.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedDivision extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_b: AnimatedNode;
|
||||
|
||||
constructor(a: AnimatedNode | number, b: AnimatedNode | number) {
|
||||
super();
|
||||
this._a = typeof a === 'number' ? new AnimatedValue(a) : a;
|
||||
this._b = typeof b === 'number' ? new AnimatedValue(b) : b;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
this._b.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
const a = this._a.__getValue();
|
||||
const b = this._b.__getValue();
|
||||
if (b === 0) {
|
||||
console.error('Detected division by zero in AnimatedDivision');
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
this._b.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
this._b.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'division',
|
||||
input: [this._a.__getNativeTag(), this._b.__getNativeTag()],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedDivision;
|
373
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js
generated
vendored
Normal file
373
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js
generated
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* eslint no-bitwise: 0 */
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
const invariant = require('invariant');
|
||||
const normalizeColor = require('../../../StyleSheet/normalizeColor');
|
||||
|
||||
type ExtrapolateType = 'extend' | 'identity' | 'clamp';
|
||||
|
||||
export type InterpolationConfigType = {
|
||||
inputRange: $ReadOnlyArray<number>,
|
||||
outputRange: $ReadOnlyArray<number> | $ReadOnlyArray<string>,
|
||||
easing?: (input: number) => number,
|
||||
extrapolate?: ExtrapolateType,
|
||||
extrapolateLeft?: ExtrapolateType,
|
||||
extrapolateRight?: ExtrapolateType,
|
||||
};
|
||||
|
||||
const linear = t => t;
|
||||
|
||||
/**
|
||||
* Very handy helper to map input ranges to output ranges with an easing
|
||||
* function and custom behavior outside of the ranges.
|
||||
*/
|
||||
function createInterpolation(
|
||||
config: InterpolationConfigType,
|
||||
): (input: number) => number | string {
|
||||
if (config.outputRange && typeof config.outputRange[0] === 'string') {
|
||||
return createInterpolationFromStringOutputRange(config);
|
||||
}
|
||||
|
||||
const outputRange: Array<number> = (config.outputRange: any);
|
||||
checkInfiniteRange('outputRange', outputRange);
|
||||
|
||||
const inputRange = config.inputRange;
|
||||
checkInfiniteRange('inputRange', inputRange);
|
||||
checkValidInputRange(inputRange);
|
||||
|
||||
invariant(
|
||||
inputRange.length === outputRange.length,
|
||||
'inputRange (' +
|
||||
inputRange.length +
|
||||
') and outputRange (' +
|
||||
outputRange.length +
|
||||
') must have the same length',
|
||||
);
|
||||
|
||||
const easing = config.easing || linear;
|
||||
|
||||
let extrapolateLeft: ExtrapolateType = 'extend';
|
||||
if (config.extrapolateLeft !== undefined) {
|
||||
extrapolateLeft = config.extrapolateLeft;
|
||||
} else if (config.extrapolate !== undefined) {
|
||||
extrapolateLeft = config.extrapolate;
|
||||
}
|
||||
|
||||
let extrapolateRight: ExtrapolateType = 'extend';
|
||||
if (config.extrapolateRight !== undefined) {
|
||||
extrapolateRight = config.extrapolateRight;
|
||||
} else if (config.extrapolate !== undefined) {
|
||||
extrapolateRight = config.extrapolate;
|
||||
}
|
||||
|
||||
return input => {
|
||||
invariant(
|
||||
typeof input === 'number',
|
||||
'Cannot interpolation an input which is not a number',
|
||||
);
|
||||
|
||||
const range = findRange(input, inputRange);
|
||||
return interpolate(
|
||||
input,
|
||||
inputRange[range],
|
||||
inputRange[range + 1],
|
||||
outputRange[range],
|
||||
outputRange[range + 1],
|
||||
easing,
|
||||
extrapolateLeft,
|
||||
extrapolateRight,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function interpolate(
|
||||
input: number,
|
||||
inputMin: number,
|
||||
inputMax: number,
|
||||
outputMin: number,
|
||||
outputMax: number,
|
||||
easing: (input: number) => number,
|
||||
extrapolateLeft: ExtrapolateType,
|
||||
extrapolateRight: ExtrapolateType,
|
||||
) {
|
||||
let result = input;
|
||||
|
||||
// Extrapolate
|
||||
if (result < inputMin) {
|
||||
if (extrapolateLeft === 'identity') {
|
||||
return result;
|
||||
} else if (extrapolateLeft === 'clamp') {
|
||||
result = inputMin;
|
||||
} else if (extrapolateLeft === 'extend') {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (result > inputMax) {
|
||||
if (extrapolateRight === 'identity') {
|
||||
return result;
|
||||
} else if (extrapolateRight === 'clamp') {
|
||||
result = inputMax;
|
||||
} else if (extrapolateRight === 'extend') {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (outputMin === outputMax) {
|
||||
return outputMin;
|
||||
}
|
||||
|
||||
if (inputMin === inputMax) {
|
||||
if (input <= inputMin) {
|
||||
return outputMin;
|
||||
}
|
||||
return outputMax;
|
||||
}
|
||||
|
||||
// Input Range
|
||||
if (inputMin === -Infinity) {
|
||||
result = -result;
|
||||
} else if (inputMax === Infinity) {
|
||||
result = result - inputMin;
|
||||
} else {
|
||||
result = (result - inputMin) / (inputMax - inputMin);
|
||||
}
|
||||
|
||||
// Easing
|
||||
result = easing(result);
|
||||
|
||||
// Output Range
|
||||
if (outputMin === -Infinity) {
|
||||
result = -result;
|
||||
} else if (outputMax === Infinity) {
|
||||
result = result + outputMin;
|
||||
} else {
|
||||
result = result * (outputMax - outputMin) + outputMin;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function colorToRgba(input: string): string {
|
||||
let normalizedColor = normalizeColor(input);
|
||||
if (normalizedColor === null || typeof normalizedColor !== 'number') {
|
||||
return input;
|
||||
}
|
||||
|
||||
normalizedColor = normalizedColor || 0;
|
||||
|
||||
const r = (normalizedColor & 0xff000000) >>> 24;
|
||||
const g = (normalizedColor & 0x00ff0000) >>> 16;
|
||||
const b = (normalizedColor & 0x0000ff00) >>> 8;
|
||||
const a = (normalizedColor & 0x000000ff) / 255;
|
||||
|
||||
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
||||
}
|
||||
|
||||
const stringShapeRegex = /[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/g;
|
||||
|
||||
/**
|
||||
* Supports string shapes by extracting numbers so new values can be computed,
|
||||
* and recombines those values into new strings of the same shape. Supports
|
||||
* things like:
|
||||
*
|
||||
* rgba(123, 42, 99, 0.36) // colors
|
||||
* -45deg // values with units
|
||||
*/
|
||||
function createInterpolationFromStringOutputRange(
|
||||
config: InterpolationConfigType,
|
||||
): (input: number) => string {
|
||||
let outputRange: Array<string> = (config.outputRange: any);
|
||||
invariant(outputRange.length >= 2, 'Bad output range');
|
||||
outputRange = outputRange.map(colorToRgba);
|
||||
checkPattern(outputRange);
|
||||
|
||||
// ['rgba(0, 100, 200, 0)', 'rgba(50, 150, 250, 0.5)']
|
||||
// ->
|
||||
// [
|
||||
// [0, 50],
|
||||
// [100, 150],
|
||||
// [200, 250],
|
||||
// [0, 0.5],
|
||||
// ]
|
||||
/* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need to
|
||||
* guard against this possibility.
|
||||
*/
|
||||
const outputRanges = outputRange[0].match(stringShapeRegex).map(() => []);
|
||||
outputRange.forEach(value => {
|
||||
/* $FlowFixMe(>=0.18.0): `value.match()` can return `null`. Need to guard
|
||||
* against this possibility.
|
||||
*/
|
||||
value.match(stringShapeRegex).forEach((number, i) => {
|
||||
outputRanges[i].push(+number);
|
||||
});
|
||||
});
|
||||
|
||||
const interpolations = outputRange[0]
|
||||
.match(stringShapeRegex)
|
||||
/* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need
|
||||
* to guard against this possibility. */
|
||||
.map((value, i) => {
|
||||
return createInterpolation({
|
||||
...config,
|
||||
outputRange: outputRanges[i],
|
||||
});
|
||||
});
|
||||
|
||||
// rgba requires that the r,g,b are integers.... so we want to round them, but we *dont* want to
|
||||
// round the opacity (4th column).
|
||||
const shouldRound = isRgbOrRgba(outputRange[0]);
|
||||
|
||||
return input => {
|
||||
let i = 0;
|
||||
// 'rgba(0, 100, 200, 0)'
|
||||
// ->
|
||||
// 'rgba(${interpolations[0](input)}, ${interpolations[1](input)}, ...'
|
||||
return outputRange[0].replace(stringShapeRegex, () => {
|
||||
let val = +interpolations[i++](input);
|
||||
if (shouldRound) {
|
||||
val = i < 4 ? Math.round(val) : Math.round(val * 1000) / 1000;
|
||||
}
|
||||
return String(val);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function isRgbOrRgba(range) {
|
||||
return typeof range === 'string' && range.startsWith('rgb');
|
||||
}
|
||||
|
||||
function checkPattern(arr: $ReadOnlyArray<string>) {
|
||||
const pattern = arr[0].replace(stringShapeRegex, '');
|
||||
for (let i = 1; i < arr.length; ++i) {
|
||||
invariant(
|
||||
pattern === arr[i].replace(stringShapeRegex, ''),
|
||||
'invalid pattern ' + arr[0] + ' and ' + arr[i],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function findRange(input: number, inputRange: $ReadOnlyArray<number>) {
|
||||
let i;
|
||||
for (i = 1; i < inputRange.length - 1; ++i) {
|
||||
if (inputRange[i] >= input) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
function checkValidInputRange(arr: $ReadOnlyArray<number>) {
|
||||
invariant(arr.length >= 2, 'inputRange must have at least 2 elements');
|
||||
for (let i = 1; i < arr.length; ++i) {
|
||||
invariant(
|
||||
arr[i] >= arr[i - 1],
|
||||
/* $FlowFixMe(>=0.13.0) - In the addition expression below this comment,
|
||||
* one or both of the operands may be something that doesn't cleanly
|
||||
* convert to a string, like undefined, null, and object, etc. If you really
|
||||
* mean this implicit string conversion, you can do something like
|
||||
* String(myThing)
|
||||
*/
|
||||
'inputRange must be monotonically non-decreasing ' + arr,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function checkInfiniteRange(name: string, arr: $ReadOnlyArray<number>) {
|
||||
invariant(arr.length >= 2, name + ' must have at least 2 elements');
|
||||
invariant(
|
||||
arr.length !== 2 || arr[0] !== -Infinity || arr[1] !== Infinity,
|
||||
/* $FlowFixMe(>=0.13.0) - In the addition expression below this comment,
|
||||
* one or both of the operands may be something that doesn't cleanly convert
|
||||
* to a string, like undefined, null, and object, etc. If you really mean
|
||||
* this implicit string conversion, you can do something like
|
||||
* String(myThing)
|
||||
*/
|
||||
name + 'cannot be ]-infinity;+infinity[ ' + arr,
|
||||
);
|
||||
}
|
||||
|
||||
class AnimatedInterpolation extends AnimatedWithChildren {
|
||||
// Export for testing.
|
||||
static __createInterpolation: (
|
||||
config: InterpolationConfigType,
|
||||
) => (input: number) => number | string = createInterpolation;
|
||||
|
||||
_parent: AnimatedNode;
|
||||
_config: InterpolationConfigType;
|
||||
_interpolation: (input: number) => number | string;
|
||||
|
||||
constructor(parent: AnimatedNode, config: InterpolationConfigType) {
|
||||
super();
|
||||
this._parent = parent;
|
||||
this._config = config;
|
||||
this._interpolation = createInterpolation(config);
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._parent.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number | string {
|
||||
const parentValue: number = this._parent.__getValue();
|
||||
invariant(
|
||||
typeof parentValue === 'number',
|
||||
'Cannot interpolate an input which is not a number.',
|
||||
);
|
||||
return this._interpolation(parentValue);
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._parent.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._parent.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__transformDataType(range: Array<any>): Array<any> {
|
||||
return range.map(NativeAnimatedHelper.transformDataType);
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
if (__DEV__) {
|
||||
NativeAnimatedHelper.validateInterpolation(this._config);
|
||||
}
|
||||
|
||||
return {
|
||||
inputRange: this._config.inputRange,
|
||||
// Only the `outputRange` can contain strings so we don't need to transform `inputRange` here
|
||||
/* $FlowFixMe(>=0.38.0) - Flow error detected during the deployment of
|
||||
* v0.38.0. To see the error, remove this comment and run flow */
|
||||
outputRange: this.__transformDataType(this._config.outputRange),
|
||||
extrapolateLeft:
|
||||
this._config.extrapolateLeft || this._config.extrapolate || 'extend',
|
||||
extrapolateRight:
|
||||
this._config.extrapolateRight || this._config.extrapolate || 'extend',
|
||||
type: 'interpolation',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedInterpolation;
|
62
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedModulo.js
generated
vendored
Normal file
62
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedModulo.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedModulo extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_modulus: number;
|
||||
|
||||
constructor(a: AnimatedNode, modulus: number) {
|
||||
super();
|
||||
this._a = a;
|
||||
this._modulus = modulus;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return (
|
||||
((this._a.__getValue() % this._modulus) + this._modulus) % this._modulus
|
||||
);
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'modulus',
|
||||
input: this._a.__getNativeTag(),
|
||||
modulus: this._modulus,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedModulo;
|
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedMultiplication.js
generated
vendored
Normal file
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedMultiplication.js
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedMultiplication extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_b: AnimatedNode;
|
||||
|
||||
constructor(a: AnimatedNode | number, b: AnimatedNode | number) {
|
||||
super();
|
||||
this._a = typeof a === 'number' ? new AnimatedValue(a) : a;
|
||||
this._b = typeof b === 'number' ? new AnimatedValue(b) : b;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
this._b.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return this._a.__getValue() * this._b.__getValue();
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
this._b.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
this._b.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'multiplication',
|
||||
input: [this._a.__getNativeTag(), this._b.__getNativeTag()],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedMultiplication;
|
184
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedNode.js
generated
vendored
Normal file
184
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedNode.js
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
const NativeAnimatedAPI = NativeAnimatedHelper.API;
|
||||
const invariant = require('invariant');
|
||||
|
||||
type ValueListenerCallback = (state: {value: number, ...}) => mixed;
|
||||
|
||||
let _uniqueId = 1;
|
||||
|
||||
// Note(vjeux): this would be better as an interface but flow doesn't
|
||||
// support them yet
|
||||
class AnimatedNode {
|
||||
_listeners: {[key: string]: ValueListenerCallback, ...};
|
||||
__nativeAnimatedValueListener: ?any;
|
||||
__attach(): void {}
|
||||
__detach(): void {
|
||||
if (this.__isNative && this.__nativeTag != null) {
|
||||
NativeAnimatedHelper.API.dropAnimatedNode(this.__nativeTag);
|
||||
this.__nativeTag = undefined;
|
||||
}
|
||||
}
|
||||
__getValue(): any {}
|
||||
__getAnimatedValue(): any {
|
||||
return this.__getValue();
|
||||
}
|
||||
__addChild(child: AnimatedNode) {}
|
||||
__removeChild(child: AnimatedNode) {}
|
||||
__getChildren(): Array<AnimatedNode> {
|
||||
return [];
|
||||
}
|
||||
|
||||
/* Methods and props used by native Animated impl */
|
||||
__isNative: boolean;
|
||||
__nativeTag: ?number;
|
||||
__shouldUpdateListenersForNewNativeTag: boolean;
|
||||
|
||||
constructor() {
|
||||
this._listeners = {};
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
if (!this.__isNative) {
|
||||
throw new Error('This node cannot be made a "native" animated node');
|
||||
}
|
||||
|
||||
if (this.hasListeners()) {
|
||||
this._startListeningToNativeValueUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an asynchronous listener to the value so you can observe updates from
|
||||
* animations. This is useful because there is no way to
|
||||
* synchronously read the value because it might be driven natively.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#addlistener
|
||||
*/
|
||||
addListener(callback: (value: any) => mixed): string {
|
||||
const id = String(_uniqueId++);
|
||||
this._listeners[id] = callback;
|
||||
if (this.__isNative) {
|
||||
this._startListeningToNativeValueUpdates();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a listener. The `id` param shall match the identifier
|
||||
* previously returned by `addListener()`.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#removelistener
|
||||
*/
|
||||
removeListener(id: string): void {
|
||||
delete this._listeners[id];
|
||||
if (this.__isNative && !this.hasListeners()) {
|
||||
this._stopListeningForNativeValueUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all registered listeners.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#removealllisteners
|
||||
*/
|
||||
removeAllListeners(): void {
|
||||
this._listeners = {};
|
||||
if (this.__isNative) {
|
||||
this._stopListeningForNativeValueUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
hasListeners(): boolean {
|
||||
return !!Object.keys(this._listeners).length;
|
||||
}
|
||||
|
||||
_startListeningToNativeValueUpdates() {
|
||||
if (
|
||||
this.__nativeAnimatedValueListener &&
|
||||
!this.__shouldUpdateListenersForNewNativeTag
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.__shouldUpdateListenersForNewNativeTag) {
|
||||
this.__shouldUpdateListenersForNewNativeTag = false;
|
||||
this._stopListeningForNativeValueUpdates();
|
||||
}
|
||||
|
||||
NativeAnimatedAPI.startListeningToAnimatedNodeValue(this.__getNativeTag());
|
||||
this.__nativeAnimatedValueListener = NativeAnimatedHelper.nativeEventEmitter.addListener(
|
||||
'onAnimatedValueUpdate',
|
||||
data => {
|
||||
if (data.tag !== this.__getNativeTag()) {
|
||||
return;
|
||||
}
|
||||
this._onAnimatedValueUpdateReceived(data.value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_onAnimatedValueUpdateReceived(value: number) {
|
||||
this.__callListeners(value);
|
||||
}
|
||||
|
||||
__callListeners(value: number): void {
|
||||
for (const key in this._listeners) {
|
||||
this._listeners[key]({value});
|
||||
}
|
||||
}
|
||||
|
||||
_stopListeningForNativeValueUpdates() {
|
||||
if (!this.__nativeAnimatedValueListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.__nativeAnimatedValueListener.remove();
|
||||
this.__nativeAnimatedValueListener = null;
|
||||
NativeAnimatedAPI.stopListeningToAnimatedNodeValue(this.__getNativeTag());
|
||||
}
|
||||
|
||||
__getNativeTag(): number {
|
||||
NativeAnimatedHelper.assertNativeAnimatedModule();
|
||||
invariant(
|
||||
this.__isNative,
|
||||
'Attempt to get native tag from node not marked as "native"',
|
||||
);
|
||||
|
||||
const nativeTag =
|
||||
this.__nativeTag ?? NativeAnimatedHelper.generateNewNodeTag();
|
||||
|
||||
if (this.__nativeTag == null) {
|
||||
this.__nativeTag = nativeTag;
|
||||
NativeAnimatedHelper.API.createAnimatedNode(
|
||||
nativeTag,
|
||||
this.__getNativeConfig(),
|
||||
);
|
||||
this.__shouldUpdateListenersForNewNativeTag = true;
|
||||
}
|
||||
|
||||
return nativeTag;
|
||||
}
|
||||
__getNativeConfig(): Object {
|
||||
throw new Error(
|
||||
'This JS animated node type cannot be used as native animated node',
|
||||
);
|
||||
}
|
||||
toJSON(): any {
|
||||
return this.__getValue();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedNode;
|
176
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedProps.js
generated
vendored
Normal file
176
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedProps.js
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {AnimatedEvent} = require('../AnimatedEvent');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedStyle = require('./AnimatedStyle');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
const ReactNative = require('../../../Renderer/shims/ReactNative');
|
||||
|
||||
const invariant = require('invariant');
|
||||
|
||||
class AnimatedProps extends AnimatedNode {
|
||||
_props: Object;
|
||||
_animatedView: any;
|
||||
_callback: () => void;
|
||||
|
||||
constructor(props: Object, callback: () => void) {
|
||||
super();
|
||||
if (props.style) {
|
||||
props = {
|
||||
...props,
|
||||
style: new AnimatedStyle(props.style),
|
||||
};
|
||||
}
|
||||
this._props = props;
|
||||
this._callback = callback;
|
||||
this.__attach();
|
||||
}
|
||||
|
||||
__getValue(): Object {
|
||||
const props = {};
|
||||
for (const key in this._props) {
|
||||
const value = this._props[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
if (!value.__isNative || value instanceof AnimatedStyle) {
|
||||
// We cannot use value of natively driven nodes this way as the value we have access from
|
||||
// JS may not be up to date.
|
||||
props[key] = value.__getValue();
|
||||
}
|
||||
} else if (value instanceof AnimatedEvent) {
|
||||
props[key] = value.__getHandler();
|
||||
} else {
|
||||
props[key] = value;
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
__getAnimatedValue(): Object {
|
||||
const props = {};
|
||||
for (const key in this._props) {
|
||||
const value = this._props[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
props[key] = value.__getAnimatedValue();
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
for (const key in this._props) {
|
||||
const value = this._props[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__addChild(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
if (this.__isNative && this._animatedView) {
|
||||
this.__disconnectAnimatedView();
|
||||
}
|
||||
for (const key in this._props) {
|
||||
const value = this._props[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__removeChild(this);
|
||||
}
|
||||
}
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
update(): void {
|
||||
this._callback();
|
||||
}
|
||||
|
||||
__makeNative(): void {
|
||||
if (!this.__isNative) {
|
||||
this.__isNative = true;
|
||||
for (const key in this._props) {
|
||||
const value = this._props[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__makeNative();
|
||||
}
|
||||
}
|
||||
if (this._animatedView) {
|
||||
this.__connectAnimatedView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setNativeView(animatedView: any): void {
|
||||
if (this._animatedView === animatedView) {
|
||||
return;
|
||||
}
|
||||
this._animatedView = animatedView;
|
||||
if (this.__isNative) {
|
||||
this.__connectAnimatedView();
|
||||
}
|
||||
}
|
||||
|
||||
__connectAnimatedView(): void {
|
||||
invariant(this.__isNative, 'Expected node to be marked as "native"');
|
||||
const nativeViewTag: ?number = ReactNative.findNodeHandle(
|
||||
this._animatedView,
|
||||
);
|
||||
invariant(
|
||||
nativeViewTag != null,
|
||||
'Unable to locate attached view in the native tree',
|
||||
);
|
||||
NativeAnimatedHelper.API.connectAnimatedNodeToView(
|
||||
this.__getNativeTag(),
|
||||
nativeViewTag,
|
||||
);
|
||||
}
|
||||
|
||||
__disconnectAnimatedView(): void {
|
||||
invariant(this.__isNative, 'Expected node to be marked as "native"');
|
||||
const nativeViewTag: ?number = ReactNative.findNodeHandle(
|
||||
this._animatedView,
|
||||
);
|
||||
invariant(
|
||||
nativeViewTag != null,
|
||||
'Unable to locate attached view in the native tree',
|
||||
);
|
||||
NativeAnimatedHelper.API.disconnectAnimatedNodeFromView(
|
||||
this.__getNativeTag(),
|
||||
nativeViewTag,
|
||||
);
|
||||
}
|
||||
|
||||
__restoreDefaultValues(): void {
|
||||
// When using the native driver, view properties need to be restored to
|
||||
// their default values manually since react no longer tracks them. This
|
||||
// is needed to handle cases where a prop driven by native animated is removed
|
||||
// after having been changed natively by an animation.
|
||||
if (this.__isNative) {
|
||||
NativeAnimatedHelper.API.restoreDefaultValues(this.__getNativeTag());
|
||||
}
|
||||
}
|
||||
|
||||
__getNativeConfig(): Object {
|
||||
const propsConfig = {};
|
||||
for (const propKey in this._props) {
|
||||
const value = this._props[propKey];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__makeNative();
|
||||
propsConfig[propKey] = value.__getNativeTag();
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'props',
|
||||
props: propsConfig,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedProps;
|
127
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedStyle.js
generated
vendored
Normal file
127
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedStyle.js
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedTransform = require('./AnimatedTransform');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
const flattenStyle = require('../../../StyleSheet/flattenStyle');
|
||||
|
||||
class AnimatedStyle extends AnimatedWithChildren {
|
||||
_style: Object;
|
||||
|
||||
constructor(style: any) {
|
||||
super();
|
||||
style = flattenStyle(style) || {};
|
||||
if (style.transform) {
|
||||
style = {
|
||||
...style,
|
||||
transform: new AnimatedTransform(style.transform),
|
||||
};
|
||||
}
|
||||
this._style = style;
|
||||
}
|
||||
|
||||
// Recursively get values for nested styles (like iOS's shadowOffset)
|
||||
_walkStyleAndGetValues(style) {
|
||||
const updatedStyle = {};
|
||||
for (const key in style) {
|
||||
const value = style[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
if (!value.__isNative) {
|
||||
// We cannot use value of natively driven nodes this way as the value we have access from
|
||||
// JS may not be up to date.
|
||||
updatedStyle[key] = value.__getValue();
|
||||
}
|
||||
} else if (value && !Array.isArray(value) && typeof value === 'object') {
|
||||
// Support animating nested values (for example: shadowOffset.height)
|
||||
updatedStyle[key] = this._walkStyleAndGetValues(value);
|
||||
} else {
|
||||
updatedStyle[key] = value;
|
||||
}
|
||||
}
|
||||
return updatedStyle;
|
||||
}
|
||||
|
||||
__getValue(): Object {
|
||||
return this._walkStyleAndGetValues(this._style);
|
||||
}
|
||||
|
||||
// Recursively get animated values for nested styles (like iOS's shadowOffset)
|
||||
_walkStyleAndGetAnimatedValues(style) {
|
||||
const updatedStyle = {};
|
||||
for (const key in style) {
|
||||
const value = style[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
updatedStyle[key] = value.__getAnimatedValue();
|
||||
} else if (value && !Array.isArray(value) && typeof value === 'object') {
|
||||
// Support animating nested values (for example: shadowOffset.height)
|
||||
updatedStyle[key] = this._walkStyleAndGetAnimatedValues(value);
|
||||
}
|
||||
}
|
||||
return updatedStyle;
|
||||
}
|
||||
|
||||
__getAnimatedValue(): Object {
|
||||
return this._walkStyleAndGetAnimatedValues(this._style);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
for (const key in this._style) {
|
||||
const value = this._style[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__addChild(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
for (const key in this._style) {
|
||||
const value = this._style[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__removeChild(this);
|
||||
}
|
||||
}
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
for (const key in this._style) {
|
||||
const value = this._style[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__makeNative();
|
||||
}
|
||||
}
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getNativeConfig(): Object {
|
||||
const styleConfig = {};
|
||||
for (const styleKey in this._style) {
|
||||
if (this._style[styleKey] instanceof AnimatedNode) {
|
||||
const style = this._style[styleKey];
|
||||
style.__makeNative();
|
||||
styleConfig[styleKey] = style.__getNativeTag();
|
||||
}
|
||||
// Non-animated styles are set using `setNativeProps`, no need
|
||||
// to pass those as a part of the node config
|
||||
}
|
||||
NativeAnimatedHelper.validateStyles(styleConfig);
|
||||
return {
|
||||
type: 'style',
|
||||
style: styleConfig,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedStyle;
|
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedSubtraction.js
generated
vendored
Normal file
63
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedSubtraction.js
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
|
||||
class AnimatedSubtraction extends AnimatedWithChildren {
|
||||
_a: AnimatedNode;
|
||||
_b: AnimatedNode;
|
||||
|
||||
constructor(a: AnimatedNode | number, b: AnimatedNode | number) {
|
||||
super();
|
||||
this._a = typeof a === 'number' ? new AnimatedValue(a) : a;
|
||||
this._b = typeof b === 'number' ? new AnimatedValue(b) : b;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._a.__makeNative();
|
||||
this._b.__makeNative();
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return this._a.__getValue() - this._b.__getValue();
|
||||
}
|
||||
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._a.__addChild(this);
|
||||
this._b.__addChild(this);
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._a.__removeChild(this);
|
||||
this._b.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
return {
|
||||
type: 'subtraction',
|
||||
input: [this._a.__getNativeTag(), this._b.__getNativeTag()],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedSubtraction;
|
102
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedTracking.js
generated
vendored
Normal file
102
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedTracking.js
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const {
|
||||
generateNewAnimationId,
|
||||
shouldUseNativeDriver,
|
||||
} = require('../NativeAnimatedHelper');
|
||||
|
||||
import type {EndCallback} from '../animations/Animation';
|
||||
|
||||
class AnimatedTracking extends AnimatedNode {
|
||||
_value: AnimatedValue;
|
||||
_parent: AnimatedNode;
|
||||
_callback: ?EndCallback;
|
||||
_animationConfig: Object;
|
||||
_animationClass: any;
|
||||
_useNativeDriver: boolean;
|
||||
|
||||
constructor(
|
||||
value: AnimatedValue,
|
||||
parent: AnimatedNode,
|
||||
animationClass: any,
|
||||
animationConfig: Object,
|
||||
callback?: ?EndCallback,
|
||||
) {
|
||||
super();
|
||||
this._value = value;
|
||||
this._parent = parent;
|
||||
this._animationClass = animationClass;
|
||||
this._animationConfig = animationConfig;
|
||||
this._useNativeDriver = shouldUseNativeDriver(animationConfig);
|
||||
this._callback = callback;
|
||||
this.__attach();
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this.__isNative = true;
|
||||
this._parent.__makeNative();
|
||||
super.__makeNative();
|
||||
this._value.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): Object {
|
||||
return this._parent.__getValue();
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._parent.__addChild(this);
|
||||
if (this._useNativeDriver) {
|
||||
// when the tracking starts we need to convert this node to a "native node"
|
||||
// so that the parent node will be made "native" too. This is necessary as
|
||||
// if we don't do this `update` method will get called. At that point it
|
||||
// may be too late as it would mean the JS driver has already started
|
||||
// updating node values
|
||||
this.__makeNative();
|
||||
}
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._parent.__removeChild(this);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
update(): void {
|
||||
this._value.animate(
|
||||
new this._animationClass({
|
||||
...this._animationConfig,
|
||||
toValue: (this._animationConfig.toValue: any).__getValue(),
|
||||
}),
|
||||
this._callback,
|
||||
);
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
const animation = new this._animationClass({
|
||||
...this._animationConfig,
|
||||
// remove toValue from the config as it's a ref to Animated.Value
|
||||
toValue: undefined,
|
||||
});
|
||||
const animationConfig = animation.__getNativeAnimationConfig();
|
||||
return {
|
||||
type: 'tracking',
|
||||
animationId: generateNewAnimationId(),
|
||||
animationConfig,
|
||||
toValue: this._parent.__getNativeTag(),
|
||||
value: this._value.__getNativeTag(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedTracking;
|
121
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedTransform.js
generated
vendored
Normal file
121
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedTransform.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
class AnimatedTransform extends AnimatedWithChildren {
|
||||
_transforms: $ReadOnlyArray<Object>;
|
||||
|
||||
constructor(transforms: $ReadOnlyArray<Object>) {
|
||||
super();
|
||||
this._transforms = transforms;
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
this._transforms.forEach(transform => {
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__makeNative();
|
||||
}
|
||||
}
|
||||
});
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__getValue(): $ReadOnlyArray<Object> {
|
||||
return this._transforms.map(transform => {
|
||||
const result = {};
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
result[key] = value.__getValue();
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
__getAnimatedValue(): $ReadOnlyArray<Object> {
|
||||
return this._transforms.map(transform => {
|
||||
const result = {};
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
result[key] = value.__getAnimatedValue();
|
||||
} else {
|
||||
// All transform components needed to recompose matrix
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
this._transforms.forEach(transform => {
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__addChild(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
this._transforms.forEach(transform => {
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
value.__removeChild(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getNativeConfig(): any {
|
||||
const transConfigs = [];
|
||||
|
||||
this._transforms.forEach(transform => {
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
if (value instanceof AnimatedNode) {
|
||||
transConfigs.push({
|
||||
type: 'animated',
|
||||
property: key,
|
||||
nodeTag: value.__getNativeTag(),
|
||||
});
|
||||
} else {
|
||||
transConfigs.push({
|
||||
type: 'static',
|
||||
property: key,
|
||||
value: NativeAnimatedHelper.transformDataType(value),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
NativeAnimatedHelper.validateTransform(transConfigs);
|
||||
return {
|
||||
type: 'transform',
|
||||
transforms: transConfigs,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedTransform;
|
265
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedValue.js
generated
vendored
Normal file
265
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedValue.js
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedInterpolation = require('./AnimatedInterpolation');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
const InteractionManager = require('../../../Interaction/InteractionManager');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
import type Animation, {EndCallback} from '../animations/Animation';
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
import type AnimatedTracking from './AnimatedTracking';
|
||||
|
||||
const NativeAnimatedAPI = NativeAnimatedHelper.API;
|
||||
|
||||
/**
|
||||
* Animated works by building a directed acyclic graph of dependencies
|
||||
* transparently when you render your Animated components.
|
||||
*
|
||||
* new Animated.Value(0)
|
||||
* .interpolate() .interpolate() new Animated.Value(1)
|
||||
* opacity translateY scale
|
||||
* style transform
|
||||
* View#234 style
|
||||
* View#123
|
||||
*
|
||||
* A) Top Down phase
|
||||
* When an Animated.Value is updated, we recursively go down through this
|
||||
* graph in order to find leaf nodes: the views that we flag as needing
|
||||
* an update.
|
||||
*
|
||||
* B) Bottom Up phase
|
||||
* When a view is flagged as needing an update, we recursively go back up
|
||||
* in order to build the new value that it needs. The reason why we need
|
||||
* this two-phases process is to deal with composite props such as
|
||||
* transform which can receive values from multiple parents.
|
||||
*/
|
||||
function _flush(rootNode: AnimatedValue): void {
|
||||
const animatedStyles = new Set();
|
||||
function findAnimatedStyles(node) {
|
||||
/* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.68 was deployed. To see the error delete this
|
||||
* comment and run Flow. */
|
||||
if (typeof node.update === 'function') {
|
||||
animatedStyles.add(node);
|
||||
} else {
|
||||
node.__getChildren().forEach(findAnimatedStyles);
|
||||
}
|
||||
}
|
||||
findAnimatedStyles(rootNode);
|
||||
/* $FlowFixMe */
|
||||
animatedStyles.forEach(animatedStyle => animatedStyle.update());
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard value for driving animations. One `Animated.Value` can drive
|
||||
* multiple properties in a synchronized fashion, but can only be driven by one
|
||||
* mechanism at a time. Using a new mechanism (e.g. starting a new animation,
|
||||
* or calling `setValue`) will stop any previous ones.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html
|
||||
*/
|
||||
class AnimatedValue extends AnimatedWithChildren {
|
||||
_value: number;
|
||||
_startingValue: number;
|
||||
_offset: number;
|
||||
_animation: ?Animation;
|
||||
_tracking: ?AnimatedTracking;
|
||||
|
||||
constructor(value: number) {
|
||||
super();
|
||||
if (typeof value !== 'number') {
|
||||
throw new Error('AnimatedValue: Attempting to set value to undefined');
|
||||
}
|
||||
this._startingValue = this._value = value;
|
||||
this._offset = 0;
|
||||
this._animation = null;
|
||||
}
|
||||
|
||||
__detach() {
|
||||
this.stopAnimation();
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return this._value + this._offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly set the value. This will stop any animations running on the value
|
||||
* and update all the bound properties.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#setvalue
|
||||
*/
|
||||
setValue(value: number): void {
|
||||
if (this._animation) {
|
||||
this._animation.stop();
|
||||
this._animation = null;
|
||||
}
|
||||
this._updateValue(
|
||||
value,
|
||||
!this.__isNative /* don't perform a flush for natively driven values */,
|
||||
);
|
||||
if (this.__isNative) {
|
||||
NativeAnimatedAPI.setAnimatedNodeValue(this.__getNativeTag(), value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an offset that is applied on top of whatever value is set, whether via
|
||||
* `setValue`, an animation, or `Animated.event`. Useful for compensating
|
||||
* things like the start of a pan gesture.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#setoffset
|
||||
*/
|
||||
setOffset(offset: number): void {
|
||||
this._offset = offset;
|
||||
if (this.__isNative) {
|
||||
NativeAnimatedAPI.setAnimatedNodeOffset(this.__getNativeTag(), offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the offset value into the base value and resets the offset to zero.
|
||||
* The final output of the value is unchanged.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#flattenoffset
|
||||
*/
|
||||
flattenOffset(): void {
|
||||
this._value += this._offset;
|
||||
this._offset = 0;
|
||||
if (this.__isNative) {
|
||||
NativeAnimatedAPI.flattenAnimatedNodeOffset(this.__getNativeTag());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset value to the base value, and resets the base value to zero.
|
||||
* The final output of the value is unchanged.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#extractoffset
|
||||
*/
|
||||
extractOffset(): void {
|
||||
this._offset += this._value;
|
||||
this._value = 0;
|
||||
if (this.__isNative) {
|
||||
NativeAnimatedAPI.extractAnimatedNodeOffset(this.__getNativeTag());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any running animation or tracking. `callback` is invoked with the
|
||||
* final value after stopping the animation, which is useful for updating
|
||||
* state to match the animation position with layout.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#stopanimation
|
||||
*/
|
||||
stopAnimation(callback?: ?(value: number) => void): void {
|
||||
this.stopTracking();
|
||||
this._animation && this._animation.stop();
|
||||
this._animation = null;
|
||||
callback && callback(this.__getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any animation and resets the value to its original.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#resetanimation
|
||||
*/
|
||||
resetAnimation(callback?: ?(value: number) => void): void {
|
||||
this.stopAnimation(callback);
|
||||
this._value = this._startingValue;
|
||||
}
|
||||
|
||||
_onAnimatedValueUpdateReceived(value: number): void {
|
||||
this._updateValue(value, false /*flush*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates the value before updating the property, e.g. mapping 0-1 to
|
||||
* 0-10.
|
||||
*/
|
||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||
return new AnimatedInterpolation(this, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically only used internally, but could be used by a custom Animation
|
||||
* class.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvalue.html#animate
|
||||
*/
|
||||
animate(animation: Animation, callback: ?EndCallback): void {
|
||||
let handle = null;
|
||||
if (animation.__isInteraction) {
|
||||
handle = InteractionManager.createInteractionHandle();
|
||||
}
|
||||
const previousAnimation = this._animation;
|
||||
this._animation && this._animation.stop();
|
||||
this._animation = animation;
|
||||
animation.start(
|
||||
this._value,
|
||||
value => {
|
||||
// Natively driven animations will never call into that callback, therefore we can always
|
||||
// pass flush = true to allow the updated value to propagate to native with setNativeProps
|
||||
this._updateValue(value, true /* flush */);
|
||||
},
|
||||
result => {
|
||||
this._animation = null;
|
||||
if (handle !== null) {
|
||||
InteractionManager.clearInteractionHandle(handle);
|
||||
}
|
||||
callback && callback(result);
|
||||
},
|
||||
previousAnimation,
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically only used internally.
|
||||
*/
|
||||
stopTracking(): void {
|
||||
this._tracking && this._tracking.__detach();
|
||||
this._tracking = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically only used internally.
|
||||
*/
|
||||
track(tracking: AnimatedTracking): void {
|
||||
this.stopTracking();
|
||||
this._tracking = tracking;
|
||||
}
|
||||
|
||||
_updateValue(value: number, flush: boolean): void {
|
||||
if (value === undefined) {
|
||||
throw new Error('AnimatedValue: Attempting to set value to undefined');
|
||||
}
|
||||
|
||||
this._value = value;
|
||||
if (flush) {
|
||||
_flush(this);
|
||||
}
|
||||
super.__callListeners(this.__getValue());
|
||||
}
|
||||
|
||||
__getNativeConfig(): Object {
|
||||
return {
|
||||
type: 'value',
|
||||
value: this._value,
|
||||
offset: this._offset,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedValue;
|
226
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedValueXY.js
generated
vendored
Normal file
226
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedValueXY.js
generated
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('./AnimatedValue');
|
||||
const AnimatedWithChildren = require('./AnimatedWithChildren');
|
||||
|
||||
const invariant = require('invariant');
|
||||
|
||||
type ValueXYListenerCallback = (value: {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
}) => mixed;
|
||||
|
||||
let _uniqueId = 1;
|
||||
|
||||
/**
|
||||
* 2D Value for driving 2D animations, such as pan gestures. Almost identical
|
||||
* API to normal `Animated.Value`, but multiplexed.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html
|
||||
*/
|
||||
class AnimatedValueXY extends AnimatedWithChildren {
|
||||
x: AnimatedValue;
|
||||
y: AnimatedValue;
|
||||
_listeners: {
|
||||
[key: string]: {
|
||||
x: string,
|
||||
y: string,
|
||||
...
|
||||
},
|
||||
...,
|
||||
};
|
||||
|
||||
constructor(
|
||||
valueIn?: ?{
|
||||
+x: number | AnimatedValue,
|
||||
+y: number | AnimatedValue,
|
||||
...
|
||||
},
|
||||
) {
|
||||
super();
|
||||
const value: any = valueIn || {x: 0, y: 0}; // @flowfixme: shouldn't need `: any`
|
||||
if (typeof value.x === 'number' && typeof value.y === 'number') {
|
||||
this.x = new AnimatedValue(value.x);
|
||||
this.y = new AnimatedValue(value.y);
|
||||
} else {
|
||||
invariant(
|
||||
value.x instanceof AnimatedValue && value.y instanceof AnimatedValue,
|
||||
'AnimatedValueXY must be initialized with an object of numbers or ' +
|
||||
'AnimatedValues.',
|
||||
);
|
||||
this.x = value.x;
|
||||
this.y = value.y;
|
||||
}
|
||||
this._listeners = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly set the value. This will stop any animations running on the value
|
||||
* and update all the bound properties.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#setvalue
|
||||
*/
|
||||
setValue(value: {x: number, y: number, ...}) {
|
||||
this.x.setValue(value.x);
|
||||
this.y.setValue(value.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an offset that is applied on top of whatever value is set, whether
|
||||
* via `setValue`, an animation, or `Animated.event`. Useful for compensating
|
||||
* things like the start of a pan gesture.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#setoffset
|
||||
*/
|
||||
setOffset(offset: {x: number, y: number, ...}) {
|
||||
this.x.setOffset(offset.x);
|
||||
this.y.setOffset(offset.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the offset value into the base value and resets the offset to zero.
|
||||
* The final output of the value is unchanged.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#flattenoffset
|
||||
*/
|
||||
flattenOffset(): void {
|
||||
this.x.flattenOffset();
|
||||
this.y.flattenOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset value to the base value, and resets the base value to
|
||||
* zero. The final output of the value is unchanged.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#extractoffset
|
||||
*/
|
||||
extractOffset(): void {
|
||||
this.x.extractOffset();
|
||||
this.y.extractOffset();
|
||||
}
|
||||
|
||||
__getValue(): {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
} {
|
||||
return {
|
||||
x: this.x.__getValue(),
|
||||
y: this.y.__getValue(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any animation and resets the value to its original.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#resetanimation
|
||||
*/
|
||||
resetAnimation(
|
||||
callback?: (value: {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
}) => void,
|
||||
): void {
|
||||
this.x.resetAnimation();
|
||||
this.y.resetAnimation();
|
||||
callback && callback(this.__getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any running animation or tracking. `callback` is invoked with the
|
||||
* final value after stopping the animation, which is useful for updating
|
||||
* state to match the animation position with layout.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#stopanimation
|
||||
*/
|
||||
stopAnimation(
|
||||
callback?: (value: {
|
||||
x: number,
|
||||
y: number,
|
||||
...
|
||||
}) => void,
|
||||
): void {
|
||||
this.x.stopAnimation();
|
||||
this.y.stopAnimation();
|
||||
callback && callback(this.__getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an asynchronous listener to the value so you can observe updates from
|
||||
* animations. This is useful because there is no way to synchronously read
|
||||
* the value because it might be driven natively.
|
||||
*
|
||||
* Returns a string that serves as an identifier for the listener.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#addlistener
|
||||
*/
|
||||
addListener(callback: ValueXYListenerCallback): string {
|
||||
const id = String(_uniqueId++);
|
||||
const jointCallback = ({value: number}) => {
|
||||
callback(this.__getValue());
|
||||
};
|
||||
this._listeners[id] = {
|
||||
x: this.x.addListener(jointCallback),
|
||||
y: this.y.addListener(jointCallback),
|
||||
};
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a listener. The `id` param shall match the identifier
|
||||
* previously returned by `addListener()`.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#removelistener
|
||||
*/
|
||||
removeListener(id: string): void {
|
||||
this.x.removeListener(this._listeners[id].x);
|
||||
this.y.removeListener(this._listeners[id].y);
|
||||
delete this._listeners[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all registered listeners.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#removealllisteners
|
||||
*/
|
||||
removeAllListeners(): void {
|
||||
this.x.removeAllListeners();
|
||||
this.y.removeAllListeners();
|
||||
this._listeners = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `{x, y}` into `{left, top}` for use in style.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#getlayout
|
||||
*/
|
||||
getLayout(): {[key: string]: AnimatedValue, ...} {
|
||||
return {
|
||||
left: this.x,
|
||||
top: this.y,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `{x, y}` into a useable translation transform.
|
||||
*
|
||||
* See https://reactnative.dev/docs/animatedvaluexy.html#gettranslatetransform
|
||||
*/
|
||||
getTranslateTransform(): Array<{[key: string]: AnimatedValue, ...}> {
|
||||
return [{translateX: this.x}, {translateY: this.y}];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedValueXY;
|
87
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedWithChildren.js
generated
vendored
Normal file
87
node_modules/react-native/Libraries/Animated/src/nodes/AnimatedWithChildren.js
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const AnimatedNode = require('./AnimatedNode');
|
||||
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
|
||||
|
||||
class AnimatedWithChildren extends AnimatedNode {
|
||||
_children: Array<AnimatedNode>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._children = [];
|
||||
}
|
||||
|
||||
__makeNative() {
|
||||
if (!this.__isNative) {
|
||||
this.__isNative = true;
|
||||
for (const child of this._children) {
|
||||
child.__makeNative();
|
||||
NativeAnimatedHelper.API.connectAnimatedNodes(
|
||||
this.__getNativeTag(),
|
||||
child.__getNativeTag(),
|
||||
);
|
||||
}
|
||||
}
|
||||
super.__makeNative();
|
||||
}
|
||||
|
||||
__addChild(child: AnimatedNode): void {
|
||||
if (this._children.length === 0) {
|
||||
this.__attach();
|
||||
}
|
||||
this._children.push(child);
|
||||
if (this.__isNative) {
|
||||
// Only accept "native" animated nodes as children
|
||||
child.__makeNative();
|
||||
NativeAnimatedHelper.API.connectAnimatedNodes(
|
||||
this.__getNativeTag(),
|
||||
child.__getNativeTag(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
__removeChild(child: AnimatedNode): void {
|
||||
const index = this._children.indexOf(child);
|
||||
if (index === -1) {
|
||||
console.warn("Trying to remove a child that doesn't exist");
|
||||
return;
|
||||
}
|
||||
if (this.__isNative && child.__isNative) {
|
||||
NativeAnimatedHelper.API.disconnectAnimatedNodes(
|
||||
this.__getNativeTag(),
|
||||
child.__getNativeTag(),
|
||||
);
|
||||
}
|
||||
this._children.splice(index, 1);
|
||||
if (this._children.length === 0) {
|
||||
this.__detach();
|
||||
}
|
||||
}
|
||||
|
||||
__getChildren(): Array<AnimatedNode> {
|
||||
return this._children;
|
||||
}
|
||||
|
||||
__callListeners(value: number): void {
|
||||
super.__callListeners(value);
|
||||
if (!this.__isNative) {
|
||||
for (const child of this._children) {
|
||||
if (child.__getValue) {
|
||||
child.__callListeners(child.__getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnimatedWithChildren;
|
15
node_modules/react-native/Libraries/Animated/src/polyfills/InteractionManager.js
generated
vendored
Normal file
15
node_modules/react-native/Libraries/Animated/src/polyfills/InteractionManager.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
createInteractionHandle: function() {},
|
||||
clearInteractionHandle: function() {},
|
||||
};
|
26
node_modules/react-native/Libraries/Animated/src/polyfills/Set.js
generated
vendored
Normal file
26
node_modules/react-native/Libraries/Animated/src/polyfills/Set.js
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function SetPolyfill() {
|
||||
this._cache = [];
|
||||
}
|
||||
|
||||
SetPolyfill.prototype.add = function(e) {
|
||||
if (this._cache.indexOf(e) === -1) {
|
||||
this._cache.push(e);
|
||||
}
|
||||
};
|
||||
|
||||
SetPolyfill.prototype.forEach = function(cb) {
|
||||
this._cache.forEach(cb);
|
||||
};
|
||||
|
||||
module.exports = SetPolyfill;
|
13
node_modules/react-native/Libraries/Animated/src/polyfills/flattenStyle.js
generated
vendored
Normal file
13
node_modules/react-native/Libraries/Animated/src/polyfills/flattenStyle.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
module.exports = function(style) {
|
||||
return style;
|
||||
};
|
Reference in New Issue
Block a user