Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-motion

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-motion - npm Package Compare versions

Comparing version 0.2.2 to 0.2.3

lib/compareTrees.js

7

HISTORY.md

@@ -7,2 +7,9 @@ Legend:

### 0.2.3 (July 29th 2015)
- [I] React-native support!
- [I] Allow returning `null` from children function. #101
- [I] `defaultValue` for specifying a... default value, upon mounting.
- [I] `TransitionSpring`'s `willLeave` API got simplified and now asks for an object as a return value instead of `null`. `null` is still supported, but is deprecated and will be removed in the next version. See the new docs on it [here](https://github.com/chenglou/react-motion/blob/24d6a7284ef61268c0ead67fe43d7e40bf45d381/README.md#transitionspring-).
- [I] Exposed a few tasteful default spring constants under the new exported `constants`.
### 0.2.2 (July 24th 2015)

@@ -9,0 +16,0 @@ - [F] Import some internal modules correctly for Ubuntu/Linux node (case-sensitive for them).

193

lib/animationLoop.js
'use strict';
exports.__esModule = true;
exports['default'] = createAnimationLoop;
exports['default'] = configAnimation;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _filter = require('./filter');
var _filter2 = _interopRequireDefault(_filter);
var _performanceNow = require('performance-now');

@@ -20,115 +16,130 @@

function renderSubscriber(alpha, subscriber) {
// subscriber.render: this.animationRender
subscriber.render(alpha, subscriber.value, subscriber.prevValue);
return subscriber.active;
}
function configAnimation() {
var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var _config$timeStep = config.timeStep;
var timeStep = _config$timeStep === undefined ? 1 / 60 * 1000 : _config$timeStep;
var _config$timeScale = config.timeScale;
var timeScale = _config$timeScale === undefined ? 1 : _config$timeScale;
var _config$maxSteps = config.maxSteps;
var maxSteps = _config$maxSteps === undefined ? 10 : _config$maxSteps;
var _config$raf = config.raf;
var raf = _config$raf === undefined ? _raf2['default'] : _config$raf;
var _config$now = config.now;
var now = _config$now === undefined ? _performanceNow2['default'] : _config$now;
var prototype = {
running: false,
shouldStop: false,
lastTime: 0,
accumulatedTime: 0,
var animRunning = [];
var running = false;
var prevTime = 0;
var accumulatedTime = 0;
// step: this.animationStep
// render: this.animationRender
// value: state
subscribe: function subscribe(step, render, value) {
var subscriber = {
value: value,
prevValue: value,
step: step,
render: render,
active: true
};
function loop() {
var currentTime = now();
var frameTime = currentTime - prevTime; // delta
this.subscribers.push(subscriber);
prevTime = currentTime;
accumulatedTime += frameTime * timeScale;
return function unsubscribe() {
subscriber.active = false;
};
},
loop: function loop() {
var currentTime = _performanceNow2['default']();
if (this.shouldStop) {
this.running = this.shouldStop = false;
return;
if (accumulatedTime > timeStep * maxSteps) {
accumulatedTime = 0;
}
var timeStep = this.timeStep;
// delta
var frameTime = currentTime - this.lastTime;
var frameNumber = Math.ceil(accumulatedTime / timeStep);
for (var i = 0; i < animRunning.length; i++) {
var _animRunning$i = animRunning[i];
var active = _animRunning$i.active;
var step = _animRunning$i.step;
var prevPrevState = _animRunning$i.prevState;
var prevNextState = _animRunning$i.nextState;
this.lastTime = currentTime;
this.accumulatedTime += frameTime * this.timeScale;
if (!active) {
continue;
}
if (this.accumulatedTime > timeStep * this.maxSteps) {
this.accumulatedTime = 0;
// Seems like because the TS sets destVals as enterVals for the first
// tick, we might render that value twice. We render it once, currValue is
// enterVal and destVal is enterVal. The next tick is faster than 16ms,
// so accumulatedTime (which would be about -16ms from the previous tick)
// is negative (-16ms + any number less than 16ms < 0). So we just render
// part ways towards the nextState, but that's enterVal still. We render
// say 75% between currValue (=== enterVal) and destValue (=== enterVal).
// So we render the same value a second time.
// The solution bellow is to recalculate the destination state even when
// you're moving partially towards it.
if (accumulatedTime <= 0) {
animRunning[i].nextState = step(timeStep / 1000, prevPrevState);
} else {
for (var j = 0; j < frameNumber; j++) {
animRunning[i].nextState = step(timeStep / 1000, prevNextState);
animRunning[i].prevState = prevNextState;
}
}
}
while (this.accumulatedTime > 0) {
this.subscribers.forEach(this.step); // animationLoop.step
this.accumulatedTime -= timeStep;
}
accumulatedTime = accumulatedTime - frameNumber * timeStep;
// Render and filter in one iteration.
this.subscribers = _filter2['default'](this.subscribers, renderSubscriber, 1 + this.accumulatedTime / timeStep);
var newAnimRunning = [];
var alpha = 1 + accumulatedTime / timeStep;
for (var i = 0; i < animRunning.length; i++) {
var _animRunning$i2 = animRunning[i];
if (this.subscribers.length === 0) {
this.shouldStop = true;
// Might mutate animRunning........
var render = _animRunning$i2.render;
var active = _animRunning$i2.active;
var nextState = _animRunning$i2.nextState;
var prevState = _animRunning$i2.prevState;
render(alpha, nextState, prevState);
if (active) {
newAnimRunning.push(animRunning[i]);
}
}
_raf2['default'](this.loop);
},
animRunning = newAnimRunning;
start: function start() {
if (this.subscribers.length) {
if (this.shouldStop) {
this.shouldStop = false;
} else if (!this.running) {
this.running = true;
this.lastTime = _performanceNow2['default']();
this.accumulatedTime = 0;
_raf2['default'](this.loop);
}
if (animRunning.length === 0) {
running = false;
} else {
raf(loop);
}
}
};
function start() {
if (!running) {
running = true;
prevTime = now();
accumulatedTime = 0;
raf(loop);
}
}
// stop() {
// this.shouldStop = true;
return function startAnimation(state, step, render) {
for (var i = 0; i < animRunning.length; i++) {
var val = animRunning[i];
if (val.step === step) {
val.active = true;
val.prevState = state;
start();
return val.stop;
}
}
// return this;
// },
var newAnim = {
step: step,
render: render,
prevState: state,
nextState: state,
active: true
};
function createAnimationLoop(_ref) {
var timeStep = _ref.timeStep;
var timeScale = _ref.timeScale;
var maxSteps = _ref.maxSteps;
newAnim.stop = function () {
return newAnim.active = false;
};
animRunning.push(newAnim);
var animationLoop = Object.create(prototype);
start();
animationLoop.loop = animationLoop.loop.bind(animationLoop);
animationLoop.subscribers = [];
// timeStep is in milliseconds
animationLoop.timeStep = timeStep * 1000; // seconds
animationLoop.timeScale = timeScale;
animationLoop.maxSteps = maxSteps;
animationLoop.step = function (subscriber) {
if (subscriber.active) {
var value = subscriber.value; // value = this.state
subscriber.prevValue = value;
subscriber.value = subscriber.step(timeStep, value); // animationStep
}
return newAnim.stop;
};
return animationLoop;
}
module.exports = exports['default'];

@@ -7,3 +7,3 @@ // this function is allocation-less thanks to babel, which transforms the tail

exports["default"] = mergeDiff;
function mergeDiffArr2(_x, _x2, _x3, _x4, _x5, _x6, _x7) {
function mergeDiffArr(_x, _x2, _x3, _x4, _x5, _x6, _x7) {
var _again = true;

@@ -106,3 +106,3 @@

// give you a medal
mergeDiffArr2(Object.keys(a), Object.keys(b), b, 0, 0, onRemove, ret);
mergeDiffArr(Object.keys(a), Object.keys(b), b, 0, 0, onRemove, ret);
return ret;

@@ -109,0 +109,0 @@ }

@@ -15,2 +15,8 @@ 'use strict';

exports.TransitionSpring = _Spring.TransitionSpring;
var _constants2 = require('./constants');
var _constants3 = _interopRequireDefault(_constants2);
exports.constants = _constants3['default'];
var utils = {

@@ -17,0 +23,0 @@ reorderKeys: _reorderKeys2['default']

'use strict';
exports.__esModule = true;
exports.updateCurrValue = updateCurrValue;
exports.updateCurrVelocity = updateCurrVelocity;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _mapTree = require('./mapTree');

@@ -17,14 +11,10 @@

var _lodashIsplainobject = require('lodash.isplainobject');
var _noVelocity = require('./noVelocity');
var _lodashIsplainobject2 = _interopRequireDefault(_lodashIsplainobject);
var _noVelocity2 = _interopRequireDefault(_noVelocity);
var _stepper = require('./stepper');
var _compareTrees = require('./compareTrees');
var _stepper2 = _interopRequireDefault(_stepper);
var _compareTrees2 = _interopRequireDefault(_compareTrees);
var _noVelocity = require('./noVelocity');
var _noVelocity2 = _interopRequireDefault(_noVelocity);
var _mergeDiff = require('./mergeDiff');

@@ -38,157 +28,108 @@

var animationLoop = _animationLoop2['default']({
// Fixed time step in seconds.
timeStep: 1 / 60,
// Slow-mo anyone? Give 0.1 a try.
timeScale: 1,
// Pause if we have more than this many steps worth of accumulated time.
maxSteps: 10
});
var _zero = require('./zero');
function zero() {
return 0;
}
var _zero2 = _interopRequireDefault(_zero);
// TODO: refactor common logic with updateCurrValue and updateCurrVelocity
function interpolateValue(alpha, nextValue, prevValue) {
if (nextValue === null) {
return null;
}
if (prevValue == null) {
return nextValue;
}
if (typeof nextValue === 'number') {
// https://github.com/chenglou/react-motion/pull/57#issuecomment-121924628
return nextValue * alpha + prevValue * (1 - alpha);
}
if (nextValue.val != null && nextValue.config && nextValue.config.length === 0) {
return nextValue;
}
if (nextValue.val != null) {
var ret = {
val: interpolateValue(alpha, nextValue.val, prevValue.val)
};
if (nextValue.config) {
ret.config = nextValue.config;
}
return ret;
}
if (Array.isArray(nextValue)) {
return nextValue.map(function (_, i) {
return interpolateValue(alpha, nextValue[i], prevValue[i]);
});
}
if (_lodashIsplainobject2['default'](nextValue)) {
return Object.keys(nextValue).reduce(function (ret, key) {
ret[key] = interpolateValue(alpha, nextValue[key], prevValue[key]);
return ret;
}, {});
}
return nextValue;
var _updateTree = require('./updateTree');
var React = undefined;
try {
React = require('react-native');
} catch (e) {
React = require('react');
}
// TODO: refactor common logic with updateCurrVelocity
var _React = React;
var PropTypes = _React.PropTypes;
function updateCurrValue(frameRate, currValue, currVelocity, endValue, k, b) {
if (endValue === null) {
return null;
var startAnimation = _animationLoop2['default']();
function animationStep(shouldMerge, stopAnimation, getProps, timestep, state) {
var currValue = state.currValue;
var currVelocity = state.currVelocity;
var _getProps = getProps();
var willEnter = _getProps.willEnter;
var willLeave = _getProps.willLeave;
var endValue = _getProps.endValue;
if (typeof endValue === 'function') {
endValue = endValue(currValue);
}
if (typeof endValue === 'number') {
if (k == null || b == null) {
return endValue;
}
// TODO: do something to stepper to make this not allocate (2 steppers?)
return _stepper2['default'](frameRate, currValue, currVelocity, endValue, k, b)[0];
}
if (endValue.val != null && endValue.config && endValue.config.length === 0) {
return endValue;
}
if (endValue.val != null) {
var _ref = endValue.config || [170, 26];
var _k = _ref[0];
var _b = _ref[1];
var mergedValue = endValue; // set mergedValue to endValue as the default
var hasNewKey = false;
var ret = {
val: updateCurrValue(frameRate, currValue.val, currVelocity.val, endValue.val, _k, _b)
};
if (endValue.config) {
ret.config = endValue.config;
}
return ret;
}
if (Array.isArray(endValue)) {
return endValue.map(function (_, i) {
return updateCurrValue(frameRate, currValue[i], currVelocity[i], endValue[i], k, b);
if (shouldMerge) {
mergedValue = _mergeDiff2['default'](currValue, endValue,
// TODO: stop allocating like crazy in this whole code path
function (key) {
var res = willLeave(key, currValue[key], endValue, currValue, currVelocity);
if (res == null) {
// For legacy reason. We won't allow returning null soon
// TODO: remove, after next release
return null;
}
if (_noVelocity2['default'](currVelocity[key]) && _compareTrees2['default'](currValue[key], res)) {
return null;
}
return res;
});
}
if (_lodashIsplainobject2['default'](endValue)) {
return Object.keys(endValue).reduce(function (ret, key) {
ret[key] = updateCurrValue(frameRate, currValue[key], currVelocity[key], endValue[key], k, b);
return ret;
}, {});
}
return endValue;
}
function updateCurrVelocity(frameRate, currValue, currVelocity, endValue, k, b) {
if (endValue === null) {
return null;
Object.keys(mergedValue).filter(function (key) {
return !currValue.hasOwnProperty(key);
}).forEach(function (key) {
hasNewKey = true;
var enterValue = willEnter(key, mergedValue[key], endValue, currValue, currVelocity);
currValue[key] = enterValue;
mergedValue[key] = enterValue;
currVelocity[key] = _mapTree2['default'](_zero2['default'], currValue[key]);
});
}
if (typeof endValue === 'number') {
if (k == null || b == null) {
return _mapTree2['default'](zero, currVelocity);
}
// TODO: do something to stepper to make this not allocate (2 steppers?)
return _stepper2['default'](frameRate, currValue, currVelocity, endValue, k, b)[1];
}
if (endValue.val != null && endValue.config && endValue.config.length === 0) {
return _mapTree2['default'](zero, currVelocity);
}
if (endValue.val != null) {
var _ref2 = endValue.config || [170, 26];
var _k = _ref2[0];
var _b = _ref2[1];
var newCurrValue = _updateTree.updateCurrValue(timestep, currValue, currVelocity, mergedValue);
var newCurrVelocity = _updateTree.updateCurrVelocity(timestep, currValue, currVelocity, mergedValue);
var ret = {
val: updateCurrVelocity(frameRate, currValue.val, currVelocity.val, endValue.val, _k, _b)
};
if (endValue.config) {
ret.config = endValue.config;
}
return ret;
if (!hasNewKey && _noVelocity2['default'](currVelocity) && _noVelocity2['default'](newCurrVelocity)) {
// check explanation in `Spring.animationRender`
stopAnimation(); // Nasty side effects....
}
if (Array.isArray(endValue)) {
return endValue.map(function (_, i) {
return updateCurrVelocity(frameRate, currValue[i], currVelocity[i], endValue[i], k, b);
});
}
if (_lodashIsplainobject2['default'](endValue)) {
return Object.keys(endValue).reduce(function (ret, key) {
ret[key] = updateCurrVelocity(frameRate, currValue[key], currVelocity[key], endValue[key], k, b);
return ret;
}, {});
}
return _mapTree2['default'](zero, currVelocity);
return {
currValue: newCurrValue,
currVelocity: newCurrVelocity
};
}
var Spring = _react2['default'].createClass({
var Spring = React.createClass({
displayName: 'Spring',
propTypes: {
endValue: _react.PropTypes.oneOfType([_react.PropTypes.func, _react.PropTypes.object, _react.PropTypes.array]).isRequired,
children: _react.PropTypes.func.isRequired
defaultValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
endValue: PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.array]).isRequired,
children: PropTypes.func.isRequired
},
getInitialState: function getInitialState() {
var endValue = this.props.endValue;
var _props = this.props;
var endValue = _props.endValue;
var defaultValue = _props.defaultValue;
if (typeof endValue === 'function') {
// TODO: provide warning for failing to provide base case
endValue = endValue();
var currValue = undefined;
if (defaultValue == null) {
if (typeof endValue === 'function') {
// TODO: provide perf tip here when endValue argument count is 0
// (meaning you could have passed an obj)
currValue = endValue();
} else {
currValue = endValue;
}
} else {
currValue = defaultValue;
}
return {
currValue: endValue,
currVelocity: _mapTree2['default'](zero, endValue)
currValue: currValue,
currVelocity: _mapTree2['default'](_zero2['default'], currValue)
};

@@ -198,2 +139,9 @@ },

componentDidMount: function componentDidMount() {
var _this = this;
this.animationStep = animationStep.bind(null, false, function () {
return _this.stopAnimation();
}, function () {
return _this.props;
});
this.startAnimating();

@@ -206,3 +154,3 @@ },

unsubscribeAnimation: null,
stopAnimation: null,

@@ -212,7 +160,6 @@ // used in animationRender

animationStep: null,
componentWillUnmount: function componentWillUnmount() {
if (this.unsubscribeAnimation) {
this.unsubscribeAnimation();
this.unsubscribeAnimation = null;
}
this.stopAnimation();
this.hasUnmounted = true;

@@ -222,35 +169,6 @@ },

startAnimating: function startAnimating() {
if (!this.unsubscribeAnimation) {
// means we're not animating
this.unsubscribeAnimation = animationLoop.subscribe(this.animationStep, this.animationRender, this.state);
animationLoop.start();
}
// Is smart enough to not start it twice
this.stopAnimation = startAnimation(this.state, this.animationStep, this.animationRender);
},
animationStep: function animationStep(timeStep, state) {
var currValue = state.currValue;
var currVelocity = state.currVelocity;
var endValue = this.props.endValue;
if (typeof endValue === 'function') {
endValue = endValue(currValue);
}
var newCurrValue = updateCurrValue(timeStep, currValue, currVelocity, endValue);
var newCurrVelocity = updateCurrVelocity(timeStep, currValue, currVelocity, endValue);
if (_noVelocity2['default'](currVelocity) && _noVelocity2['default'](newCurrVelocity)) {
// check explanation in `animationRender`
if (!this.hasUnmounted) {
this.unsubscribeAnimation();
this.unsubscribeAnimation = null;
}
}
return {
currValue: newCurrValue,
currVelocity: newCurrVelocity
};
},
animationRender: function animationRender(alpha, nextState, prevState) {

@@ -263,3 +181,3 @@ // `this.hasUnmounted` might be true in the following condition:

this.setState({
currValue: interpolateValue(alpha, nextState.currValue, prevState.currValue),
currValue: _updateTree.interpolateValue(alpha, nextState.currValue, prevState.currValue),
currVelocity: nextState.currVelocity

@@ -271,5 +189,4 @@ });

render: function render() {
var currValue = this.state.currValue;
return _react2['default'].Children.only(this.props.children(currValue));
var renderedChildren = this.props.children(this.state.currValue);
return renderedChildren && React.Children.only(renderedChildren);
}

@@ -279,10 +196,8 @@ });

exports.Spring = Spring;
var TransitionSpring = _react2['default'].createClass({
var TransitionSpring = React.createClass({
displayName: 'TransitionSpring',
propTypes: {
endValue: _react.PropTypes.oneOfType([_react.PropTypes.func, _react.PropTypes.objectOf({
key: _react.PropTypes.any.isRequired
})]).
// coming soon
defaultValue: PropTypes.objectOf(PropTypes.any),
endValue: PropTypes.oneOfType([PropTypes.func, PropTypes.objectOf(PropTypes.any.isRequired)]).
// PropTypes.arrayOf(PropTypes.shape({

@@ -293,12 +208,11 @@ // key: PropTypes.any.isRequired,

isRequired,
willLeave: _react.PropTypes.oneOfType([_react.PropTypes.func]),
willLeave: PropTypes.oneOfType([PropTypes.func]),
// PropTypes.object,
// PropTypes.array,
// TODO: numbers? strings?
willEnter: _react.PropTypes.oneOfType([_react.PropTypes.func]),
willEnter: PropTypes.oneOfType([PropTypes.func]),
// PropTypes.object,
// PropTypes.array,
children: _react.PropTypes.func.isRequired
children: PropTypes.func.isRequired
},

@@ -318,10 +232,19 @@

getInitialState: function getInitialState() {
var endValue = this.props.endValue;
var _props2 = this.props;
var endValue = _props2.endValue;
var defaultValue = _props2.defaultValue;
if (typeof endValue === 'function') {
endValue = endValue();
var currValue = undefined;
if (defaultValue == null) {
if (typeof endValue === 'function') {
currValue = endValue();
} else {
currValue = endValue;
}
} else {
currValue = defaultValue;
}
return {
currValue: endValue,
currVelocity: _mapTree2['default'](zero, endValue)
currValue: currValue,
currVelocity: _mapTree2['default'](_zero2['default'], currValue)
};

@@ -331,2 +254,9 @@ },

componentDidMount: function componentDidMount() {
var _this2 = this;
this.animationStep = animationStep.bind(null, true, function () {
return _this2.stopAnimation();
}, function () {
return _this2.props;
});
this.startAnimating();

@@ -339,3 +269,3 @@ },

unsubscribeAnimation: null,
stopAnimation: null,

@@ -345,64 +275,12 @@ // used in animationRender

animationStep: null,
componentWillUnmount: function componentWillUnmount() {
if (this.unsubscribeAnimation) {
this.unsubscribeAnimation();
this.unsubscribeAnimation = undefined;
}
this.stopAnimation();
},
startAnimating: function startAnimating() {
if (!this.unsubscribeAnimation) {
this.unsubscribeAnimation = animationLoop.subscribe(this.animationStep, this.animationRender, this.state);
animationLoop.start();
}
this.stopAnimation = startAnimation(this.state, this.animationStep, this.animationRender);
},
animationStep: function animationStep(timeStep, state) {
var currValue = state.currValue;
var currVelocity = state.currVelocity;
var endValue = this.props.endValue;
var _props = this.props;
var willEnter = _props.willEnter;
var willLeave = _props.willLeave;
if (typeof endValue === 'function') {
endValue = endValue(currValue);
}
var mergedValue = undefined;
// only other option is obj
mergedValue = _mergeDiff2['default'](currValue, endValue,
// TODO: stop allocating like crazy in this whole code path
function (key) {
return willLeave(key, currValue[key], endValue, currValue, currVelocity);
});
var hasNewKey = false;
Object.keys(mergedValue).filter(function (key) {
return !currValue.hasOwnProperty(key);
}).forEach(function (key) {
hasNewKey = true;
var enterValue = willEnter(key, mergedValue[key], endValue, currValue, currVelocity);
currValue[key] = enterValue;
mergedValue[key] = enterValue;
currVelocity[key] = _mapTree2['default'](zero, currValue[key]);
});
var newCurrValue = updateCurrValue(timeStep, currValue, currVelocity, mergedValue);
var newCurrVelocity = updateCurrVelocity(timeStep, currValue, currVelocity, mergedValue);
if (_noVelocity2['default'](currVelocity) && _noVelocity2['default'](newCurrVelocity) && !hasNewKey) {
// check explanation in `Spring.animationRender`
if (!this.hasUnmounted) {
this.unsubscribeAnimation();
this.unsubscribeAnimation = undefined;
}
}
return {
currValue: newCurrValue,
currVelocity: newCurrVelocity
};
},
animationRender: function animationRender(alpha, nextState, prevState) {

@@ -412,3 +290,3 @@ // See comment in Spring.

this.setState({
currValue: interpolateValue(alpha, nextState.currValue, prevState.currValue),
currValue: _updateTree.interpolateValue(alpha, nextState.currValue, prevState.currValue),
currVelocity: nextState.currVelocity

@@ -420,7 +298,6 @@ });

render: function render() {
var currValue = this.state.currValue;
return _react2['default'].Children.only(this.props.children(currValue));
var renderedChildren = this.props.children(this.state.currValue);
return renderedChildren && React.Children.only(renderedChildren);
}
});
exports.TransitionSpring = TransitionSpring;
{
"name": "react-motion",
"version": "0.2.2",
"version": "0.2.3",
"description": "A spring that solves your animation problems.",

@@ -18,3 +18,3 @@ "main": "lib/react-motion.js",

"eslint-plugin-react": "^2.7.0",
"inject-loader": "^2.0.0",
"inject-loader": "plasticine/inject-loader#master",
"isparta-loader": "^0.2.0",

@@ -21,0 +21,0 @@ "karma": "^0.12.37",

@@ -13,3 +13,3 @@ # React-Motion

Animate a counter to `10`, from whatever value it currently is. For more advanced usage, see below.
Animate a counter to `10`, from whatever value it currently is. For more advanced usage, see [below](#constants).

@@ -26,4 +26,6 @@ Npm:

[Check](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo0/index.html) [Out](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo1/index.html) [The](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo2/index.html) [Cool](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo3/index.html) [Demos](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo4/index.html).
Or build it yourself from the repo: `git clone https://github.com/chenglou/react-motion.git && npm i && npm run prerelease`
[Check](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo0/index.html) [Out](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo1/index.html) [The](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo2/index.html) [Cool](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo3/index.html) [Demos](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo4/index.html) [Here](https://cdn.rawgit.com/chenglou/react-motion/2a5f89bee700c6bbb0560eee0c8f9ad66d111bdd/demos/demo5/index.html).
## What does this library try to solve?

@@ -55,3 +57,3 @@

<button onMouseDown={this.handleMouseDown}>Toggle</button>
<Spring endValue={{val: this.state.open ? 400 : 0}}>
<Spring defaultValue={{val: 0}} endValue={{val: this.state.open ? 400 : 0}}>
{interpolated =>

@@ -69,10 +71,17 @@ <div className="demo0-block" style={{

The library exports a `Spring`, a `TransitionSpring` and `utils`.
The library exports a `Spring`, a `TransitionSpring`, `constants` `utils`.
### &lt;Spring />
Exposes a single prop, `endValue`, which takes either an object, an array or a function that returns an object or an array.
Type: `endValue: object | array | object -> (object | array)`.
Exposes the props `defaultValue` (object or array) and `endValue` (object, array or a function that returns an object or an array).
`endValue` can be of an arbitrary shape (**but must stay the same shape from one render to the next**). There are however 2 reserved keys: `val` and `config`. Say your initial data structure looks so:
Types:
- `defaultValue: object | array`.
- `endValue: object | array | object -> (object | array)`.
Both values can be of an arbitrary shape (**but must have the same shape. `endValue` must stay the same shape from one render to the next**).
`defaultValue` is used as the first value upon mounting. Usually your `endValue` would differ from it, as to give the mounting animation effect.
`endValue` is the value you want to reach. There are 2 reserved keys for it: `val` and `config`. Say your initial data structure looks so:
```js

@@ -113,3 +122,3 @@ {size: 10, top: 20}

A stiffness of `120` and damping of `17` gives the spring a slight bounce effect. The default configuration, if you don't pass `config` alongside `val`, is `[170, 26]`.
A stiffness of `120` and damping of `17` gives the spring a slight bounce effect. The library exports a `constants` object that contains the commonly used stiffness and damping. See the `constants` section below.

@@ -170,16 +179,10 @@ You can nest `val` wrappers; the innermost takes priority:

Sometime, you want to rely on the currently interpolated value to calculate `endValue`. E.g. (demo 1) a chat head's final position is the current position of the leading chat head. `endValue` can also accept a function `(currentPositions) => yourEndValue`, where `currentPositions` is the same data structure you'd receive from the children callback.
Sometime, you want to rely on the currently interpolated value to calculate `endValue`. E.g. (demo 1) a chat head's final position is the current position of the leading chat head. `endValue` can also accept a function `(prevValue) => yourEndValue`, where `prevValue` is the data you returned from the previous tick of `getEndValue`.
```jsx
// ...Somewhere in your React class
getEndValues: function(currentPositions) {
// currentPositions of `null` means it's the first render for Spring.
if (currentPositions == null) {
return {val: utils.range(6).map(() => [0, 0])};
}
// This is really the previous tick of currentPositions. In practice, it
// doesn't make much difference.
let endValue = currentPositions.val.map((_, i) => {
getEndValue: function(prevValue) {
let endValue = prevValue.val.map((_, i) => {
// First one follows the mouse
return i === 0 ? this.state.mousePosition : currentPositions.val[i - 1];
return i === 0 ? this.state.mousePosition : prevValue.val[i - 1];
});

@@ -190,2 +193,3 @@ // Have fun adjusting config to make the chat heads bounce a little more!

// in render: <Spring endValue={this.getEndValue}></Spring>
```

@@ -196,2 +200,4 @@

`defaultValue`: see `endValue` just below.
`endValue`: now constrained to an object (or a callback `currentValue -> object`) of the shape `{key => yourStuff}` (the data is constrained to this shape, but that doesn't mean the way you use your interpolated value has to be). When `endValue` differs from the current interpolated value by an added/removed key:

@@ -201,3 +207,3 @@

`willLeave`: a callback that's called **many** times and is passed `(keyThatLeaves, correspondingValueOfKeyThatJustLeft, endValueYouJustSpecified, currentInterpolatedValue, currentSpeed)`. Return an object/array configuration (which will serve as the new `endValue[keyThatLeaves]` and merged into `endValue`) to indicate you still want to keep the item around. Otherwise, return `null`.
`willLeave`: a callback that's called **many** times and is passed `(keyThatLeaves, correspondingValueOfKeyThatJustLeft, endValueYouJustSpecified, currentInterpolatedValue, currentSpeed)`. Return an object/array configuration (which will serve as the new `endValue[keyThatLeaves]` and merged into `endValue`). When that value is reached through the spring interpolation, the key will be actually unmounted.

@@ -260,3 +266,3 @@ #### Sample Usage

<TransitionSpring
endValue={this.getEndValue}
endValue={this.getEndValue()}
willEnter={this.willEnter}

@@ -285,2 +291,5 @@ willLeave={this.willLeave}>

### `constants`
Some tasteful, commonly used spring constants you can plug into your `endValue` like so: `{val: 10, config: constants.wobbly}`. [See here](https://github.com/chenglou/react-motion/blob/372446fc8679dcdbf4de2e983d53709ab40ce88c/src/constants.js).
### Little Extras

@@ -296,1 +305,28 @@ _(You might not need this until later on.)_

`newKeysFunction` will receive, as arguments, the array of keys in `object` and should return a new array of keys (with e.g. order changed and/or keys missing). `reorderKeys` will then return a new object similar to `object`, but with the keys in the order `newKeysFunction` dictated.
## FAQ
- How do I do staggering/chained animation where items animate in one after another?
In most cases, what you want to express here is a relationship between animations, e.g. item 2 appears after item 1. Staggering/chained animation have hard-coded values and go against the spirit of a physics system. Check out [demo 1](https://cdn.rawgit.com/chenglou/react-motion/3b5be548cd08630a836562a053576ff91f94b93f/demo1/index.html); each ball follows the one in front of it, creating a natural staggering animation. The code in `endValue` looks roughly so:
```jsx
<Spring endValue={prevValue => {
const endValue = prevValue.val.map(
(_, i) => i === 0 ? someMousePosition : prevValue.val[i - 1]
);
return {val: endValue};
}}>
...
```
First ball's destination is the mouse position. The subsequent ones' destination is the current position of the ball in front of them (technically, the previous tick's position; Doesn't matter much). The values depend on each other. No hard-coded duration/timeout here!
- My `ref` doesn't work in the children function.
React string refs won't work:
```jsx
<Spring endValue={...}>
{currentValue => <div ref="stuff" />}
</Spring>
```
This is how React works. Here's the [callback ref solution](https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute).

@@ -34,3 +34,4 @@ var webpack = require('webpack');

amd: 'react'
}
},
'react-native': true,
},

@@ -37,0 +38,0 @@ };

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc