<html>
<head>
<meta name="description" content="React.js titty shaker">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>I need a Title Please!</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="root"></div>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script src="https://fb.me/react-with-addons-0.14.7.min.js"></script>
<script src="https://fb.me/react-dom-0.14.7.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.1/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux-thunk/2.0.1/redux-thunk.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/history/1.17.0/History.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/1.0.3/ReactRouter.min.js"></script>
<script src="https://npmcdn.com/react-router-active-component@3.0.0/umd/react-router-active-component.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</body>
</html>
/*! Generated by Live LESS Theme Customizer */
@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,700|Source+Sans+Pro:400,600,600italic,400italic|Inconsolata:400,700);
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,300,700");
.navbar {
border: none;
font-size: 13px;
font-weight: 300;
}
.navbar .navbar-toggle:hover .icon-bar {
background-color: #b3b3b3;
}
.navbar-collapse {
border-top-color: rgba(0, 0, 0, 0.2);
box-shadow: none;
}
.navbar .btn {
padding-top: 6px;
padding-bottom: 6px;
}
.navbar-form {
margin-top: 7px;
margin-bottom: 5px;
}
.navbar-form .form-control {
height: auto;
padding: 4px 6px;
}
.navbar-text {
margin: 12px 15px;
line-height: 21px;
}
.navbar .dropdown-menu {
border: none;
}
.navbar .dropdown-menu > li > a,
.navbar .dropdown-menu > li > a:focus {
background-color: transparent;
font-size: 13px;
font-weight: 300;
}
.navbar .dropdown-header {
color: rgba(255, 255, 255, 0.5);
}
.navbar-default .dropdown-menu {
background-color: #333333;
}
.navbar-default .dropdown-menu > li > a,
.navbar-default .dropdown-menu > li > a:focus {
color: #ffffff;
}
.navbar-default .dropdown-menu > li > a:hover,
.navbar-default .dropdown-menu > .active > a,
.navbar-default .dropdown-menu > .active > a:hover {
background-color: #272727;
}
.navbar-inverse .dropdown-menu {
background-color: #008cba;
}
.navbar-inverse .dropdown-menu > li > a,
.navbar-inverse .dropdown-menu > li > a:focus {
color: #ffffff;
}
.navbar-inverse .dropdown-menu > li > a:hover,
.navbar-inverse .dropdown-menu > .active > a,
.navbar-inverse .dropdown-menu > .active > a:hover {
background-color: #006687;
}
.btn {
padding: 8px 12px;
}
.btn-lg {
padding: 14px 20px;
}
.btn-sm {
padding: 8px 12px;
}
.btn-xs {
padding: 4px 6px;
}
.btn-group .btn ~ .dropdown-toggle {
padding-left: 16px;
padding-right: 16px;
}
.btn-group .dropdown-menu {
border-top-width: 0;
}
.btn-group.dropup .dropdown-menu {
border-top-width: 1px;
border-bottom-width: 0;
margin-bottom: 0;
}
.btn-group .dropdown-toggle.btn-default ~ .dropdown-menu {
background-color: #e7e7e7;
border-color: #cccccc;
}
.btn-group .dropdown-toggle.btn-default ~ .dropdown-menu > li > a {
color: #333333;
}
.btn-group .dropdown-toggle.btn-default ~ .dropdown-menu > li > a:hover {
background-color: #d3d3d3;
}
.btn-group .dropdown-toggle.btn-primary ~ .dropdown-menu {
background-color: #008cba;
border-color: #0079a1;
}
.btn-group .dropdown-toggle.btn-primary ~ .dropdown-menu > li > a {
color: #ffffff;
}
.btn-group .dropdown-toggle.btn-primary ~ .dropdown-menu > li > a:hover {
background-color: #006d91;
}
.btn-group .dropdown-toggle.btn-success ~ .dropdown-menu {
background-color: #43ac6a;
border-color: #3c9a5f;
}
.btn-group .dropdown-toggle.btn-success ~ .dropdown-menu > li > a {
color: #ffffff;
}
.btn-group .dropdown-toggle.btn-success ~ .dropdown-menu > li > a:hover {
background-color: #388f58;
}
.btn-group .dropdown-toggle.btn-info ~ .dropdown-menu {
background-color: #5bc0de;
border-color: #46b8da;
}
.btn-group .dropdown-toggle.btn-info ~ .dropdown-menu > li > a {
color: #ffffff;
}
.btn-group .dropdown-toggle.btn-info ~ .dropdown-menu > li > a:hover {
background-color: #39b3d7;
}
.btn-group .dropdown-toggle.btn-warning ~ .dropdown-menu {
background-color: #e99002;
border-color: #d08002;
}
.btn-group .dropdown-toggle.btn-warning ~ .dropdown-menu > li > a {
color: #ffffff;
}
.btn-group .dropdown-toggle.btn-warning ~ .dropdown-menu > li > a:hover {
background-color: #c17702;
}
.btn-group .dropdown-toggle.btn-danger ~ .dropdown-menu {
background-color: #f04124;
border-color: #ea2f10;
}
.btn-group .dropdown-toggle.btn-danger ~ .dropdown-menu > li > a {
color: #ffffff;
}
.btn-group .dropdown-toggle.btn-danger ~ .dropdown-menu > li > a:hover {
background-color: #dc2c0f;
}
.lead {
color: #6f6f6f;
}
cite {
font-style: italic;
}
blockquote {
border-left-width: 1px;
color: #6f6f6f;
}
blockquote.pull-right {
border-right-width: 1px;
}
blockquote small {
font-size: 12px;
font-weight: 300;
}
table {
font-size: 12px;
}
label,
.control-label,
.help-block,
.checkbox,
.radio {
font-size: 12px;
font-weight: normal;
}
input[type="radio"],
input[type="checkbox"] {
margin-top: 1px;
}
.nav .open > a,
.nav .open > a:hover,
.nav .open > a:focus {
border-color: transparent;
}
.nav-tabs > li > a {
background-color: #e7e7e7;
color: #222222;
}
.nav-tabs .caret {
border-top-color: #222222;
border-bottom-color: #222222;
}
.nav-pills {
font-weight: 300;
}
.breadcrumb {
border: 1px solid #dddddd;
border-radius: 3px;
font-size: 10px;
font-weight: 300;
text-transform: uppercase;
}
.pagination {
font-size: 12px;
font-weight: 300;
color: #999999;
}
.pagination > li > a,
.pagination > li > span {
margin-left: 4px;
color: #999999;
}
.pagination > .active > a,
.pagination > .active > span {
color: #fff;
}
.pagination > li > a,
.pagination > li:first-child > a,
.pagination > li:last-child > a,
.pagination > li > span,
.pagination > li:first-child > span,
.pagination > li:last-child > span {
border-radius: 3px;
}
.pagination-lg > li > a,
.pagination-lg > li > span {
padding-left: 22px;
padding-right: 22px;
}
.pagination-sm > li > a,
.pagination-sm > li > span {
padding: 0 5px;
}
.pager {
font-size: 12px;
font-weight: 300;
color: #999999;
}
.list-group {
font-size: 12px;
font-weight: 300;
}
.close {
opacity: 0.4;
text-decoration: none;
text-shadow: none;
}
.close:hover,
.close:focus {
opacity: 1;
}
.alert {
font-size: 12px;
font-weight: 300;
}
.alert .alert-link {
font-weight: normal;
color: #fff;
text-decoration: underline;
}
.label {
padding-left: 1em;
padding-right: 1em;
border-radius: 0;
font-weight: 300;
}
.label-default {
background-color: #e7e7e7;
color: #333333;
}
.badge {
font-weight: 300;
}
.progress {
height: 22px;
padding: 2px;
background-color: #f6f6f6;
border: 1px solid #ccc;
box-shadow: none;
}
.dropdown-menu {
padding: 0;
margin-top: 0;
font-size: 12px;
}
.dropdown-menu > li > a {
padding: 12px 15px;
}
.dropdown-header {
padding-left: 15px;
padding-right: 15px;
font-size: 9px;
text-transform: uppercase;
}
.popover {
color: #fff;
font-size: 12px;
font-weight: 300;
}
.panel-heading,
.panel-footer {
border-top-right-radius: 0;
border-top-left-radius: 0;
}
.panel-default .close {
color: #222222;
}
.modal .close {
color: #222222;
}
#banner {
overflow: hidden;
width: 100%;
}
#navi {
margin: 0;
}
#navi.affix {
position: fixed;
top: 0;
width: 100%;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
height: 60px;
background-color: #f5f5f5;
}
/* Custom page CSS
-------------------------------------------------- */
/* Not required for template or sticky footer method. */
/* .container {
width: auto;
max-width: 680px;
padding: 0 15px;
} */
.container .text-muted {
margin: 20px 0;
}
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"));
else if(typeof define === 'function' && define.amd)
define(["react"], factory);
else if(typeof exports === 'object')
exports["ReactMotion"] = factory(require("react"));
else
root["ReactMotion"] = factory(root["React"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_9__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "build/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
function _interopRequire(obj) { return obj && obj.__esModule ? obj['default'] : obj; }
var _Motion = __webpack_require__(1);
exports.Motion = _interopRequire(_Motion);
var _StaggeredMotion = __webpack_require__(10);
exports.StaggeredMotion = _interopRequire(_StaggeredMotion);
var _TransitionMotion = __webpack_require__(11);
exports.TransitionMotion = _interopRequire(_TransitionMotion);
var _spring = __webpack_require__(13);
exports.spring = _interopRequire(_spring);
var _presets = __webpack_require__(14);
exports.presets = _interopRequire(_presets);
// deprecated, dummy warning function
var _reorderKeys = __webpack_require__(15);
exports.reorderKeys = _interopRequire(_reorderKeys);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _mapToZero = __webpack_require__(2);
var _mapToZero2 = _interopRequireDefault(_mapToZero);
var _stripStyle = __webpack_require__(3);
var _stripStyle2 = _interopRequireDefault(_stripStyle);
var _stepper3 = __webpack_require__(4);
var _stepper4 = _interopRequireDefault(_stepper3);
var _performanceNow = __webpack_require__(5);
var _performanceNow2 = _interopRequireDefault(_performanceNow);
var _raf = __webpack_require__(7);
var _raf2 = _interopRequireDefault(_raf);
var _shouldStopAnimation = __webpack_require__(8);
var _shouldStopAnimation2 = _interopRequireDefault(_shouldStopAnimation);
var _react = __webpack_require__(9);
var _react2 = _interopRequireDefault(_react);
var msPerFrame = 1000 / 60;
var Motion = _react2['default'].createClass({
displayName: 'Motion',
propTypes: {
// TOOD: warn against putting a config in here
defaultStyle: _react.PropTypes.objectOf(_react.PropTypes.number),
style: _react.PropTypes.objectOf(_react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.object])).isRequired,
children: _react.PropTypes.func.isRequired,
onRest: _react.PropTypes.func
},
getInitialState: function getInitialState() {
var _props = this.props;
var defaultStyle = _props.defaultStyle;
var style = _props.style;
var currentStyle = defaultStyle || _stripStyle2['default'](style);
var currentVelocity = _mapToZero2['default'](currentStyle);
return {
currentStyle: currentStyle,
currentVelocity: currentVelocity,
lastIdealStyle: currentStyle,
lastIdealVelocity: currentVelocity
};
},
wasAnimating: false,
animationID: null,
prevTime: 0,
accumulatedTime: 0,
// it's possible that currentStyle's value is stale: if props is immediately
// changed from 0 to 400 to spring(0) again, the async currentStyle is still
// at 0 (didn't have time to tick and interpolate even once). If we naively
// compare currentStyle with destVal it'll be 0 === 0 (no animation, stop).
// In reality currentStyle should be 400
unreadPropStyle: null,
// after checking for unreadPropStyle != null, we manually go set the
// non-interpolating values (those that are a number, without a spring
// config)
clearUnreadPropStyle: function clearUnreadPropStyle(destStyle) {
var dirty = false;
var _state = this.state;
var currentStyle = _state.currentStyle;
var currentVelocity = _state.currentVelocity;
var lastIdealStyle = _state.lastIdealStyle;
var lastIdealVelocity = _state.lastIdealVelocity;
for (var key in destStyle) {
if (!destStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = destStyle[key];
if (typeof styleValue === 'number') {
if (!dirty) {
dirty = true;
currentStyle = _extends({}, currentStyle);
currentVelocity = _extends({}, currentVelocity);
lastIdealStyle = _extends({}, lastIdealStyle);
lastIdealVelocity = _extends({}, lastIdealVelocity);
}
currentStyle[key] = styleValue;
currentVelocity[key] = 0;
lastIdealStyle[key] = styleValue;
lastIdealVelocity[key] = 0;
}
}
if (dirty) {
this.setState({ currentStyle: currentStyle, currentVelocity: currentVelocity, lastIdealStyle: lastIdealStyle, lastIdealVelocity: lastIdealVelocity });
}
},
startAnimationIfNecessary: function startAnimationIfNecessary() {
var _this = this;
// TODO: when config is {a: 10} and dest is {a: 10} do we raf once and
// call cb? No, otherwise accidental parent rerender causes cb trigger
this.animationID = _raf2['default'](function () {
// check if we need to animate in the first place
var propsStyle = _this.props.style;
if (_shouldStopAnimation2['default'](_this.state.currentStyle, propsStyle, _this.state.currentVelocity)) {
if (_this.wasAnimating && _this.props.onRest) {
_this.props.onRest();
}
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.wasAnimating = false;
_this.accumulatedTime = 0;
return;
}
_this.wasAnimating = true;
var currentTime = _performanceNow2['default']();
var timeDelta = currentTime - _this.prevTime;
_this.prevTime = currentTime;
_this.accumulatedTime = _this.accumulatedTime + timeDelta;
// more than 10 frames? prolly switched browser tab. Restart
if (_this.accumulatedTime > msPerFrame * 10) {
_this.accumulatedTime = 0;
}
if (_this.accumulatedTime === 0) {
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.startAnimationIfNecessary();
return;
}
var currentFrameCompletion = (_this.accumulatedTime - Math.floor(_this.accumulatedTime / msPerFrame) * msPerFrame) / msPerFrame;
var framesToCatchUp = Math.floor(_this.accumulatedTime / msPerFrame);
var newLastIdealStyle = {};
var newLastIdealVelocity = {};
var newCurrentStyle = {};
var newCurrentVelocity = {};
for (var key in propsStyle) {
if (!propsStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = propsStyle[key];
if (typeof styleValue === 'number') {
newCurrentStyle[key] = styleValue;
newCurrentVelocity[key] = 0;
newLastIdealStyle[key] = styleValue;
newLastIdealVelocity[key] = 0;
} else {
var newLastIdealStyleValue = _this.state.lastIdealStyle[key];
var newLastIdealVelocityValue = _this.state.lastIdealVelocity[key];
for (var i = 0; i < framesToCatchUp; i++) {
var _stepper = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
newLastIdealStyleValue = _stepper[0];
newLastIdealVelocityValue = _stepper[1];
}
var _stepper2 = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
var nextIdealX = _stepper2[0];
var nextIdealV = _stepper2[1];
newCurrentStyle[key] = newLastIdealStyleValue + (nextIdealX - newLastIdealStyleValue) * currentFrameCompletion;
newCurrentVelocity[key] = newLastIdealVelocityValue + (nextIdealV - newLastIdealVelocityValue) * currentFrameCompletion;
newLastIdealStyle[key] = newLastIdealStyleValue;
newLastIdealVelocity[key] = newLastIdealVelocityValue;
}
}
_this.animationID = null;
// the amount we're looped over above
_this.accumulatedTime -= framesToCatchUp * msPerFrame;
_this.setState({
currentStyle: newCurrentStyle,
currentVelocity: newCurrentVelocity,
lastIdealStyle: newLastIdealStyle,
lastIdealVelocity: newLastIdealVelocity
});
_this.unreadPropStyle = null;
_this.startAnimationIfNecessary();
});
},
componentDidMount: function componentDidMount() {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
},
componentWillReceiveProps: function componentWillReceiveProps(props) {
if (this.unreadPropStyle != null) {
// previous props haven't had the chance to be set yet; set them here
this.clearUnreadPropStyle(this.unreadPropStyle);
}
this.unreadPropStyle = props.style;
if (this.animationID == null) {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
}
},
componentWillUnmount: function componentWillUnmount() {
if (this.animationID != null) {
_raf2['default'].cancel(this.animationID);
this.animationID = null;
}
},
render: function render() {
var renderedChildren = this.props.children(this.state.currentStyle);
return renderedChildren && _react2['default'].Children.only(renderedChildren);
}
});
exports['default'] = Motion;
module.exports = exports['default'];
/***/ },
/* 2 */
/***/ function(module, exports) {
// currently used to initiate the velocity style object to 0
'use strict';
exports.__esModule = true;
exports['default'] = mapToZero;
function mapToZero(obj) {
var ret = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = 0;
}
}
return ret;
}
module.exports = exports['default'];
/***/ },
/* 3 */
/***/ function(module, exports) {
// turn {x: {val: 1, stiffness: 1, damping: 2}, y: 2} generated by
// `{x: spring(1, {stiffness: 1, damping: 2}), y: 2}` into {x: 1, y: 2}
'use strict';
exports.__esModule = true;
exports['default'] = stripStyle;
function stripStyle(style) {
var ret = {};
for (var key in style) {
if (!style.hasOwnProperty(key)) {
continue;
}
ret[key] = typeof style[key] === 'number' ? style[key] : style[key].val;
}
return ret;
}
module.exports = exports['default'];
/***/ },
/* 4 */
/***/ function(module, exports) {
// stepper is used a lot. Saves allocation to return the same array wrapper.
// This is fine and danger-free against mutations because the callsite
// immediately destructures it and gets the numbers inside without passing the
"use strict";
exports.__esModule = true;
exports["default"] = stepper;
var reusedTuple = [];
function stepper(secondPerFrame, x, v, destX, k, b, precision) {
// Spring stiffness, in kg / s^2
// for animations, destX is really spring length (spring at rest). initial
// position is considered as the stretched/compressed position of a spring
var Fspring = -k * (x - destX);
// Damping, in kg / s
var Fdamper = -b * v;
// usually we put mass here, but for animation purposes, specifying mass is a
// bit redundant. you could simply adjust k and b accordingly
// let a = (Fspring + Fdamper) / mass;
var a = Fspring + Fdamper;
var newV = v + a * secondPerFrame;
var newX = x + newV * secondPerFrame;
if (Math.abs(newV) < precision && Math.abs(newX - destX) < precision) {
reusedTuple[0] = destX;
reusedTuple[1] = 0;
return reusedTuple;
}
reusedTuple[0] = newX;
reusedTuple[1] = newV;
return reusedTuple;
}
module.exports = exports["default"];
// array reference around.
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {// Generated by CoffeeScript 1.7.1
"use strict";
(function () {
var getNanoSeconds, hrtime, loadTime;
if (typeof performance !== "undefined" && performance !== null && performance.now) {
module.exports = function () {
return performance.now();
};
} else if (typeof process !== "undefined" && process !== null && process.hrtime) {
module.exports = function () {
return (getNanoSeconds() - loadTime) / 1e6;
};
hrtime = process.hrtime;
getNanoSeconds = function () {
var hr;
hr = hrtime();
return hr[0] * 1e9 + hr[1];
};
loadTime = getNanoSeconds();
} else if (Date.now) {
module.exports = function () {
return Date.now() - loadTime;
};
loadTime = Date.now();
} else {
module.exports = function () {
return new Date().getTime() - loadTime;
};
loadTime = new Date().getTime();
}
}).call(undefined);
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)))
/***/ },
/* 6 */
/***/ function(module, exports) {
// shim for using process in browser
'use strict';
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () {
return '/';
};
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function () {
return 0;
};
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {'use strict';
var now = __webpack_require__(5),
root = typeof window === 'undefined' ? global : window,
vendors = ['moz', 'webkit'],
suffix = 'AnimationFrame',
raf = root['request' + suffix],
caf = root['cancel' + suffix] || root['cancelRequest' + suffix];
for (var i = 0; !raf && i < vendors.length; i++) {
raf = root[vendors[i] + 'Request' + suffix];
caf = root[vendors[i] + 'Cancel' + suffix] || root[vendors[i] + 'CancelRequest' + suffix];
}
// Some versions of FF have rAF but not cAF
if (!raf || !caf) {
var last = 0,
id = 0,
queue = [],
frameDuration = 1000 / 60;
raf = function (callback) {
if (queue.length === 0) {
var _now = now(),
next = Math.max(0, frameDuration - (_now - last));
last = next + _now;
setTimeout(function () {
var cp = queue.slice(0);
// Clear queue here to prevent
// callbacks from appending listeners
// to the current frame's queue
queue.length = 0;
for (var i = 0; i < cp.length; i++) {
if (!cp[i].cancelled) {
try {
cp[i].callback(last);
} catch (e) {
setTimeout(function () {
throw e;
}, 0);
}
}
}
}, Math.round(next));
}
queue.push({
handle: ++id,
callback: callback,
cancelled: false
});
return id;
};
caf = function (handle) {
for (var i = 0; i < queue.length; i++) {
if (queue[i].handle === handle) {
queue[i].cancelled = true;
}
}
};
}
module.exports = function (fn) {
// Wrap in a new function to prevent
// `cancel` potentially being assigned
// to the native rAF function
return raf.call(root, fn);
};
module.exports.cancel = function () {
caf.apply(root, arguments);
};
module.exports.polyfill = function () {
root.requestAnimationFrame = raf;
root.cancelAnimationFrame = caf;
};
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ },
/* 8 */
/***/ function(module, exports) {
// usage assumption: currentStyle values have already been rendered but it says
// nothing of whether currentStyle is stale (see unreadPropStyle)
'use strict';
exports.__esModule = true;
exports['default'] = shouldStopAnimation;
function shouldStopAnimation(currentStyle, style, currentVelocity) {
for (var key in style) {
if (!style.hasOwnProperty(key)) {
continue;
}
if (currentVelocity[key] !== 0) {
return false;
}
var styleValue = typeof style[key] === 'number' ? style[key] : style[key].val;
// stepper will have already taken care of rounding precision errors, so
// won't have such thing as 0.9999 !=== 1
if (currentStyle[key] !== styleValue) {
return false;
}
}
return true;
}
module.exports = exports['default'];
/***/ },
/* 9 */
/***/ function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_9__;
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _mapToZero = __webpack_require__(2);
var _mapToZero2 = _interopRequireDefault(_mapToZero);
var _stripStyle = __webpack_require__(3);
var _stripStyle2 = _interopRequireDefault(_stripStyle);
var _stepper3 = __webpack_require__(4);
var _stepper4 = _interopRequireDefault(_stepper3);
var _performanceNow = __webpack_require__(5);
var _performanceNow2 = _interopRequireDefault(_performanceNow);
var _raf = __webpack_require__(7);
var _raf2 = _interopRequireDefault(_raf);
var _shouldStopAnimation = __webpack_require__(8);
var _shouldStopAnimation2 = _interopRequireDefault(_shouldStopAnimation);
var _react = __webpack_require__(9);
var _react2 = _interopRequireDefault(_react);
var msPerFrame = 1000 / 60;
function shouldStopAnimationAll(currentStyles, styles, currentVelocities) {
for (var i = 0; i < currentStyles.length; i++) {
if (!_shouldStopAnimation2['default'](currentStyles[i], styles[i], currentVelocities[i])) {
return false;
}
}
return true;
}
var StaggeredMotion = _react2['default'].createClass({
displayName: 'StaggeredMotion',
propTypes: {
// TOOD: warn against putting a config in here
defaultStyles: _react.PropTypes.arrayOf(_react.PropTypes.objectOf(_react.PropTypes.number)),
styles: _react.PropTypes.func.isRequired,
children: _react.PropTypes.func.isRequired
},
getInitialState: function getInitialState() {
var _props = this.props;
var defaultStyles = _props.defaultStyles;
var styles = _props.styles;
var currentStyles = defaultStyles || styles().map(_stripStyle2['default']);
var currentVelocities = currentStyles.map(function (currentStyle) {
return _mapToZero2['default'](currentStyle);
});
return {
currentStyles: currentStyles,
currentVelocities: currentVelocities,
lastIdealStyles: currentStyles,
lastIdealVelocities: currentVelocities
};
},
animationID: null,
prevTime: 0,
accumulatedTime: 0,
// it's possible that currentStyle's value is stale: if props is immediately
// changed from 0 to 400 to spring(0) again, the async currentStyle is still
// at 0 (didn't have time to tick and interpolate even once). If we naively
// compare currentStyle with destVal it'll be 0 === 0 (no animation, stop).
// In reality currentStyle should be 400
unreadPropStyles: null,
// after checking for unreadPropStyles != null, we manually go set the
// non-interpolating values (those that are a number, without a spring
// config)
clearUnreadPropStyle: function clearUnreadPropStyle(unreadPropStyles) {
var _state = this.state;
var currentStyles = _state.currentStyles;
var currentVelocities = _state.currentVelocities;
var lastIdealStyles = _state.lastIdealStyles;
var lastIdealVelocities = _state.lastIdealVelocities;
var someDirty = false;
for (var i = 0; i < unreadPropStyles.length; i++) {
var unreadPropStyle = unreadPropStyles[i];
var dirty = false;
for (var key in unreadPropStyle) {
if (!unreadPropStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = unreadPropStyle[key];
if (typeof styleValue === 'number') {
if (!dirty) {
dirty = true;
someDirty = true;
currentStyles[i] = _extends({}, currentStyles[i]);
currentVelocities[i] = _extends({}, currentVelocities[i]);
lastIdealStyles[i] = _extends({}, lastIdealStyles[i]);
lastIdealVelocities[i] = _extends({}, lastIdealVelocities[i]);
}
currentStyles[i][key] = styleValue;
currentVelocities[i][key] = 0;
lastIdealStyles[i][key] = styleValue;
lastIdealVelocities[i][key] = 0;
}
}
}
if (someDirty) {
this.setState({ currentStyles: currentStyles, currentVelocities: currentVelocities, lastIdealStyles: lastIdealStyles, lastIdealVelocities: lastIdealVelocities });
}
},
startAnimationIfNecessary: function startAnimationIfNecessary() {
var _this = this;
// TODO: when config is {a: 10} and dest is {a: 10} do we raf once and
// call cb? No, otherwise accidental parent rerender causes cb trigger
this.animationID = _raf2['default'](function () {
var destStyles = _this.props.styles(_this.state.lastIdealStyles);
// check if we need to animate in the first place
if (shouldStopAnimationAll(_this.state.currentStyles, destStyles, _this.state.currentVelocities)) {
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.accumulatedTime = 0;
return;
}
var currentTime = _performanceNow2['default']();
var timeDelta = currentTime - _this.prevTime;
_this.prevTime = currentTime;
_this.accumulatedTime = _this.accumulatedTime + timeDelta;
// more than 10 frames? prolly switched browser tab. Restart
if (_this.accumulatedTime > msPerFrame * 10) {
_this.accumulatedTime = 0;
}
if (_this.accumulatedTime === 0) {
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.startAnimationIfNecessary();
return;
}
var currentFrameCompletion = (_this.accumulatedTime - Math.floor(_this.accumulatedTime / msPerFrame) * msPerFrame) / msPerFrame;
var framesToCatchUp = Math.floor(_this.accumulatedTime / msPerFrame);
var newLastIdealStyles = [];
var newLastIdealVelocities = [];
var newCurrentStyles = [];
var newCurrentVelocities = [];
for (var i = 0; i < destStyles.length; i++) {
var destStyle = destStyles[i];
var newCurrentStyle = {};
var newCurrentVelocity = {};
var newLastIdealStyle = {};
var newLastIdealVelocity = {};
for (var key in destStyle) {
if (!destStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = destStyle[key];
if (typeof styleValue === 'number') {
newCurrentStyle[key] = styleValue;
newCurrentVelocity[key] = 0;
newLastIdealStyle[key] = styleValue;
newLastIdealVelocity[key] = 0;
} else {
var newLastIdealStyleValue = _this.state.lastIdealStyles[i][key];
var newLastIdealVelocityValue = _this.state.lastIdealVelocities[i][key];
for (var j = 0; j < framesToCatchUp; j++) {
var _stepper = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
newLastIdealStyleValue = _stepper[0];
newLastIdealVelocityValue = _stepper[1];
}
var _stepper2 = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
var nextIdealX = _stepper2[0];
var nextIdealV = _stepper2[1];
newCurrentStyle[key] = newLastIdealStyleValue + (nextIdealX - newLastIdealStyleValue) * currentFrameCompletion;
newCurrentVelocity[key] = newLastIdealVelocityValue + (nextIdealV - newLastIdealVelocityValue) * currentFrameCompletion;
newLastIdealStyle[key] = newLastIdealStyleValue;
newLastIdealVelocity[key] = newLastIdealVelocityValue;
}
}
newCurrentStyles[i] = newCurrentStyle;
newCurrentVelocities[i] = newCurrentVelocity;
newLastIdealStyles[i] = newLastIdealStyle;
newLastIdealVelocities[i] = newLastIdealVelocity;
}
_this.animationID = null;
// the amount we're looped over above
_this.accumulatedTime -= framesToCatchUp * msPerFrame;
_this.setState({
currentStyles: newCurrentStyles,
currentVelocities: newCurrentVelocities,
lastIdealStyles: newLastIdealStyles,
lastIdealVelocities: newLastIdealVelocities
});
_this.unreadPropStyles = null;
_this.startAnimationIfNecessary();
});
},
componentDidMount: function componentDidMount() {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
},
componentWillReceiveProps: function componentWillReceiveProps(props) {
if (this.unreadPropStyles != null) {
// previous props haven't had the chance to be set yet; set them here
this.clearUnreadPropStyle(this.unreadPropStyles);
}
this.unreadPropStyles = props.styles(this.state.lastIdealStyles);
if (this.animationID == null) {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
}
},
componentWillUnmount: function componentWillUnmount() {
if (this.animationID != null) {
_raf2['default'].cancel(this.animationID);
this.animationID = null;
}
},
render: function render() {
var renderedChildren = this.props.children(this.state.currentStyles);
return renderedChildren && _react2['default'].Children.only(renderedChildren);
}
});
exports['default'] = StaggeredMotion;
module.exports = exports['default'];
/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _mapToZero = __webpack_require__(2);
var _mapToZero2 = _interopRequireDefault(_mapToZero);
var _stripStyle = __webpack_require__(3);
var _stripStyle2 = _interopRequireDefault(_stripStyle);
var _stepper3 = __webpack_require__(4);
var _stepper4 = _interopRequireDefault(_stepper3);
var _mergeDiff = __webpack_require__(12);
var _mergeDiff2 = _interopRequireDefault(_mergeDiff);
var _performanceNow = __webpack_require__(5);
var _performanceNow2 = _interopRequireDefault(_performanceNow);
var _raf = __webpack_require__(7);
var _raf2 = _interopRequireDefault(_raf);
var _shouldStopAnimation = __webpack_require__(8);
var _shouldStopAnimation2 = _interopRequireDefault(_shouldStopAnimation);
var _react = __webpack_require__(9);
var _react2 = _interopRequireDefault(_react);
var msPerFrame = 1000 / 60;
// the children function & (potential) styles function asks as param an
// Array<TransitionPlainStyle>, where each TransitionPlainStyle is of the format
// {key: string, data?: any, style: PlainStyle}. However, the way we keep
// internal states doesn't contain such a data structure (check the state and
// TransitionMotionState). So when children function and others ask for such
// data we need to generate them on the fly by combining mergedPropsStyles and
// currentStyles/lastIdealStyles
function rehydrateStyles(mergedPropsStyles, unreadPropStyles, plainStyles) {
if (unreadPropStyles == null) {
// $FlowFixMe
return mergedPropsStyles.map(function (mergedPropsStyle, i) {
return {
key: mergedPropsStyle.key,
data: mergedPropsStyle.data,
style: plainStyles[i]
};
});
}
return mergedPropsStyles.map(function (mergedPropsStyle, i) {
// $FlowFixMe
for (var j = 0; j < unreadPropStyles.length; j++) {
// $FlowFixMe
if (unreadPropStyles[j].key === mergedPropsStyle.key) {
return {
// $FlowFixMe
key: unreadPropStyles[j].key,
data: unreadPropStyles[j].data,
style: plainStyles[i]
};
}
}
// $FlowFixMe
return { key: mergedPropsStyle.key, data: mergedPropsStyle.data, style: plainStyles[i] };
});
}
function shouldStopAnimationAll(currentStyles, destStyles, currentVelocities, mergedPropsStyles) {
if (mergedPropsStyles.length !== destStyles.length) {
return false;
}
for (var i = 0; i < mergedPropsStyles.length; i++) {
if (mergedPropsStyles[i].key !== destStyles[i].key) {
return false;
}
}
// we have the invariant that mergedPropsStyles and
// currentStyles/currentVelocities/last* are synced in terms of cells, see
// mergeAndSync comment for more info
for (var i = 0; i < mergedPropsStyles.length; i++) {
if (!_shouldStopAnimation2['default'](currentStyles[i], destStyles[i].style, currentVelocities[i])) {
return false;
}
}
return true;
}
// core key merging logic
// things to do: say previously merged style is {a, b}, dest style (prop) is {b,
// c}, previous current (interpolating) style is {a, b}
// **invariant**: current[i] corresponds to merged[i] in terms of key
// steps:
// turn merged style into {a?, b, c}
// add c, value of c is destStyles.c
// maybe remove a, aka call willLeave(a), then merged is either {b, c} or {a, b, c}
// turn current (interpolating) style from {a, b} into {a?, b, c}
// maybe remove a
// certainly add c, value of c is willEnter(c)
// loop over merged and construct new current
// dest doesn't change, that's owner's
function mergeAndSync(willEnter, willLeave, oldMergedPropsStyles, destStyles, oldCurrentStyles, oldCurrentVelocities, oldLastIdealStyles, oldLastIdealVelocities) {
var newMergedPropsStyles = _mergeDiff2['default'](oldMergedPropsStyles, destStyles, function (oldIndex, oldMergedPropsStyle) {
var leavingStyle = willLeave(oldMergedPropsStyle);
if (leavingStyle == null) {
return null;
}
if (_shouldStopAnimation2['default'](oldCurrentStyles[oldIndex], leavingStyle, oldCurrentVelocities[oldIndex])) {
return null;
}
return { key: oldMergedPropsStyle.key, data: oldMergedPropsStyle.data, style: leavingStyle };
});
var newCurrentStyles = [];
var newCurrentVelocities = [];
var newLastIdealStyles = [];
var newLastIdealVelocities = [];
for (var i = 0; i < newMergedPropsStyles.length; i++) {
var newMergedPropsStyleCell = newMergedPropsStyles[i];
var foundOldIndex = null;
for (var j = 0; j < oldMergedPropsStyles.length; j++) {
if (oldMergedPropsStyles[j].key === newMergedPropsStyleCell.key) {
foundOldIndex = j;
break;
}
}
// TODO: key search code
if (foundOldIndex == null) {
var plainStyle = willEnter(newMergedPropsStyleCell);
newCurrentStyles[i] = plainStyle;
newLastIdealStyles[i] = plainStyle;
// $FlowFixMe
var velocity = _mapToZero2['default'](newMergedPropsStyleCell.style);
newCurrentVelocities[i] = velocity;
newLastIdealVelocities[i] = velocity;
} else {
newCurrentStyles[i] = oldCurrentStyles[foundOldIndex];
newLastIdealStyles[i] = oldLastIdealStyles[foundOldIndex];
newCurrentVelocities[i] = oldCurrentVelocities[foundOldIndex];
newLastIdealVelocities[i] = oldLastIdealVelocities[foundOldIndex];
}
}
return [newMergedPropsStyles, newCurrentStyles, newCurrentVelocities, newLastIdealStyles, newLastIdealVelocities];
}
var TransitionMotion = _react2['default'].createClass({
displayName: 'TransitionMotion',
propTypes: {
defaultStyles: _react.PropTypes.arrayOf(_react.PropTypes.shape({
key: _react.PropTypes.string.isRequired,
data: _react.PropTypes.any,
style: _react.PropTypes.objectOf(_react.PropTypes.number).isRequired
})),
styles: _react.PropTypes.oneOfType([_react.PropTypes.func, _react.PropTypes.arrayOf(_react.PropTypes.shape({
key: _react.PropTypes.string.isRequired,
data: _react.PropTypes.any,
style: _react.PropTypes.objectOf(_react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.object])).isRequired
}))]).isRequired,
children: _react.PropTypes.func.isRequired,
willLeave: _react.PropTypes.func,
willEnter: _react.PropTypes.func
},
getDefaultProps: function getDefaultProps() {
return {
willEnter: function willEnter(styleThatEntered) {
return _stripStyle2['default'](styleThatEntered.style);
},
// recall: returning null makes the current unmounting TransitionStyle
// disappear immediately
willLeave: function willLeave() {
return null;
}
};
},
getInitialState: function getInitialState() {
var _props = this.props;
var defaultStyles = _props.defaultStyles;
var styles = _props.styles;
var willEnter = _props.willEnter;
var willLeave = _props.willLeave;
var destStyles = typeof styles === 'function' ? styles(defaultStyles) : styles;
// this is special. for the first time around, we don't have a comparison
// between last (no last) and current merged props. we'll compute last so:
// say default is {a, b} and styles (dest style) is {b, c}, we'll
// fabricate last as {a, b}
var oldMergedPropsStyles = undefined;
if (defaultStyles == null) {
oldMergedPropsStyles = destStyles;
} else {
// $FlowFixMe
oldMergedPropsStyles = defaultStyles.map(function (defaultStyleCell) {
// TODO: key search code
for (var i = 0; i < destStyles.length; i++) {
if (destStyles[i].key === defaultStyleCell.key) {
return destStyles[i];
}
}
return defaultStyleCell;
});
}
var oldCurrentStyles = defaultStyles == null ? destStyles.map(function (s) {
return _stripStyle2['default'](s.style);
}) : defaultStyles.map(function (s) {
return _stripStyle2['default'](s.style);
});
var oldCurrentVelocities = defaultStyles == null ? destStyles.map(function (s) {
return _mapToZero2['default'](s.style);
}) : defaultStyles.map(function (s) {
return _mapToZero2['default'](s.style);
});
var _mergeAndSync = mergeAndSync(
// $FlowFixMe
willEnter,
// $FlowFixMe
willLeave, oldMergedPropsStyles, destStyles, oldCurrentStyles, oldCurrentVelocities, oldCurrentStyles, // oldLastIdealStyles really
oldCurrentVelocities);
var mergedPropsStyles = _mergeAndSync[0];
var currentStyles = _mergeAndSync[1];
var currentVelocities = _mergeAndSync[2];
var lastIdealStyles = _mergeAndSync[3];
var lastIdealVelocities = _mergeAndSync[4];
// oldLastIdealVelocities really
return {
currentStyles: currentStyles,
currentVelocities: currentVelocities,
lastIdealStyles: lastIdealStyles,
lastIdealVelocities: lastIdealVelocities,
mergedPropsStyles: mergedPropsStyles
};
},
animationID: null,
prevTime: 0,
accumulatedTime: 0,
// it's possible that currentStyle's value is stale: if props is immediately
// changed from 0 to 400 to spring(0) again, the async currentStyle is still
// at 0 (didn't have time to tick and interpolate even once). If we naively
// compare currentStyle with destVal it'll be 0 === 0 (no animation, stop).
// In reality currentStyle should be 400
unreadPropStyles: null,
// after checking for unreadPropStyles != null, we manually go set the
// non-interpolating values (those that are a number, without a spring
// config)
clearUnreadPropStyle: function clearUnreadPropStyle(unreadPropStyles) {
var _mergeAndSync2 = mergeAndSync(
// $FlowFixMe
this.props.willEnter,
// $FlowFixMe
this.props.willLeave, this.state.mergedPropsStyles, unreadPropStyles, this.state.currentStyles, this.state.currentVelocities, this.state.lastIdealStyles, this.state.lastIdealVelocities);
var mergedPropsStyles = _mergeAndSync2[0];
var currentStyles = _mergeAndSync2[1];
var currentVelocities = _mergeAndSync2[2];
var lastIdealStyles = _mergeAndSync2[3];
var lastIdealVelocities = _mergeAndSync2[4];
for (var i = 0; i < unreadPropStyles.length; i++) {
var unreadPropStyle = unreadPropStyles[i].style;
var dirty = false;
for (var key in unreadPropStyle) {
if (!unreadPropStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = unreadPropStyle[key];
if (typeof styleValue === 'number') {
if (!dirty) {
dirty = true;
currentStyles[i] = _extends({}, currentStyles[i]);
currentVelocities[i] = _extends({}, currentVelocities[i]);
lastIdealStyles[i] = _extends({}, lastIdealStyles[i]);
lastIdealVelocities[i] = _extends({}, lastIdealVelocities[i]);
mergedPropsStyles[i] = {
key: mergedPropsStyles[i].key,
data: mergedPropsStyles[i].data,
style: _extends({}, mergedPropsStyles[i].style)
};
}
currentStyles[i][key] = styleValue;
currentVelocities[i][key] = 0;
lastIdealStyles[i][key] = styleValue;
lastIdealVelocities[i][key] = 0;
mergedPropsStyles[i].style[key] = styleValue;
}
}
}
// unlike the other 2 components, we can't detect staleness and optionally
// opt out of setState here. each style object's data might contain new
// stuff we're not/cannot compare
this.setState({
currentStyles: currentStyles,
currentVelocities: currentVelocities,
mergedPropsStyles: mergedPropsStyles,
lastIdealStyles: lastIdealStyles,
lastIdealVelocities: lastIdealVelocities
});
},
startAnimationIfNecessary: function startAnimationIfNecessary() {
var _this = this;
// TODO: when config is {a: 10} and dest is {a: 10} do we raf once and
// call cb? No, otherwise accidental parent rerender causes cb trigger
this.animationID = _raf2['default'](function () {
var propStyles = _this.props.styles;
var destStyles = typeof propStyles === 'function' ? propStyles(rehydrateStyles(_this.state.mergedPropsStyles, _this.unreadPropStyles, _this.state.lastIdealStyles)) : propStyles;
// check if we need to animate in the first place
if (shouldStopAnimationAll(_this.state.currentStyles, destStyles, _this.state.currentVelocities, _this.state.mergedPropsStyles)) {
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.accumulatedTime = 0;
return;
}
var currentTime = _performanceNow2['default']();
var timeDelta = currentTime - _this.prevTime;
_this.prevTime = currentTime;
_this.accumulatedTime = _this.accumulatedTime + timeDelta;
// more than 10 frames? prolly switched browser tab. Restart
if (_this.accumulatedTime > msPerFrame * 10) {
_this.accumulatedTime = 0;
}
if (_this.accumulatedTime === 0) {
// no need to cancel animationID here; shouldn't have any in flight
_this.animationID = null;
_this.startAnimationIfNecessary();
return;
}
var currentFrameCompletion = (_this.accumulatedTime - Math.floor(_this.accumulatedTime / msPerFrame) * msPerFrame) / msPerFrame;
var framesToCatchUp = Math.floor(_this.accumulatedTime / msPerFrame);
var _mergeAndSync3 = mergeAndSync(
// $FlowFixMe
_this.props.willEnter,
// $FlowFixMe
_this.props.willLeave, _this.state.mergedPropsStyles, destStyles, _this.state.currentStyles, _this.state.currentVelocities, _this.state.lastIdealStyles, _this.state.lastIdealVelocities);
var newMergedPropsStyles = _mergeAndSync3[0];
var newCurrentStyles = _mergeAndSync3[1];
var newCurrentVelocities = _mergeAndSync3[2];
var newLastIdealStyles = _mergeAndSync3[3];
var newLastIdealVelocities = _mergeAndSync3[4];
for (var i = 0; i < newMergedPropsStyles.length; i++) {
var newMergedPropsStyle = newMergedPropsStyles[i].style;
var newCurrentStyle = {};
var newCurrentVelocity = {};
var newLastIdealStyle = {};
var newLastIdealVelocity = {};
for (var key in newMergedPropsStyle) {
if (!newMergedPropsStyle.hasOwnProperty(key)) {
continue;
}
var styleValue = newMergedPropsStyle[key];
if (typeof styleValue === 'number') {
newCurrentStyle[key] = styleValue;
newCurrentVelocity[key] = 0;
newLastIdealStyle[key] = styleValue;
newLastIdealVelocity[key] = 0;
} else {
var newLastIdealStyleValue = newLastIdealStyles[i][key];
var newLastIdealVelocityValue = newLastIdealVelocities[i][key];
for (var j = 0; j < framesToCatchUp; j++) {
var _stepper = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
newLastIdealStyleValue = _stepper[0];
newLastIdealVelocityValue = _stepper[1];
}
var _stepper2 = _stepper4['default'](msPerFrame / 1000, newLastIdealStyleValue, newLastIdealVelocityValue, styleValue.val, styleValue.stiffness, styleValue.damping, styleValue.precision);
var nextIdealX = _stepper2[0];
var nextIdealV = _stepper2[1];
newCurrentStyle[key] = newLastIdealStyleValue + (nextIdealX - newLastIdealStyleValue) * currentFrameCompletion;
newCurrentVelocity[key] = newLastIdealVelocityValue + (nextIdealV - newLastIdealVelocityValue) * currentFrameCompletion;
newLastIdealStyle[key] = newLastIdealStyleValue;
newLastIdealVelocity[key] = newLastIdealVelocityValue;
}
}
newLastIdealStyles[i] = newLastIdealStyle;
newLastIdealVelocities[i] = newLastIdealVelocity;
newCurrentStyles[i] = newCurrentStyle;
newCurrentVelocities[i] = newCurrentVelocity;
}
_this.animationID = null;
// the amount we're looped over above
_this.accumulatedTime -= framesToCatchUp * msPerFrame;
_this.setState({
currentStyles: newCurrentStyles,
currentVelocities: newCurrentVelocities,
lastIdealStyles: newLastIdealStyles,
lastIdealVelocities: newLastIdealVelocities,
mergedPropsStyles: newMergedPropsStyles
});
_this.unreadPropStyles = null;
_this.startAnimationIfNecessary();
});
},
componentDidMount: function componentDidMount() {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
},
componentWillReceiveProps: function componentWillReceiveProps(props) {
if (this.unreadPropStyles) {
// previous props haven't had the chance to be set yet; set them here
this.clearUnreadPropStyle(this.unreadPropStyles);
}
if (typeof props.styles === 'function') {
// $FlowFixMe
this.unreadPropStyles = props.styles(rehydrateStyles(this.state.mergedPropsStyles, this.unreadPropStyles, this.state.lastIdealStyles));
} else {
this.unreadPropStyles = props.styles;
}
if (this.animationID == null) {
this.prevTime = _performanceNow2['default']();
this.startAnimationIfNecessary();
}
},
componentWillUnmount: function componentWillUnmount() {
if (this.animationID != null) {
_raf2['default'].cancel(this.animationID);
this.animationID = null;
}
},
render: function render() {
var hydratedStyles = rehydrateStyles(this.state.mergedPropsStyles, this.unreadPropStyles, this.state.currentStyles);
var renderedChildren = this.props.children(hydratedStyles);
return renderedChildren && _react2['default'].Children.only(renderedChildren);
}
});
exports['default'] = TransitionMotion;
module.exports = exports['default'];
// list of styles, each containing interpolating values. Part of what's passed
// to children function. Notice that this is
// Array<ActualInterpolatingStyleObject>, without the wrapper that is {key: ...,
// data: ... style: ActualInterpolatingStyleObject}. Only mergedPropsStyles
// contains the key & data info (so that we only have a single source of truth
// for these, and to save space). Check the comment for `rehydrateStyles` to
// see how we regenerate the entirety of what's passed to children function
// the array that keeps track of currently rendered stuff! Including stuff
// that you've unmounted but that's still animating. This is where it lives
/***/ },
/* 12 */
/***/ function(module, exports) {
// core keys merging algorithm. If previous render's keys are [a, b], and the
// next render's [c, b, d], what's the final merged keys and ordering?
// - c and a must both be before b
// - b before d
// - ordering between a and c ambiguous
// this reduces to merging two partially ordered lists (e.g. lists where not
// every item has a definite ordering, like comparing a and c above). For the
// ambiguous ordering we deterministically choose to place the next render's
// item after the previous'; so c after a
// this is called a topological sorting. Except the existing algorithms don't
// work well with js bc of the amount of allocation, and isn't optimized for our
// current use-case bc the runtime is linear in terms of edges (see wiki for
// meaning), which is huge when two lists have many common elements
'use strict';
exports.__esModule = true;
exports['default'] = mergeDiff;
function mergeDiff(prev, next, onRemove) {
// bookkeeping for easier access of a key's index below. This is 2 allocations +
// potentially triggering chrome hash map mode for objs (so it might be faster
var prevKeyIndex = {};
for (var i = 0; i < prev.length; i++) {
prevKeyIndex[prev[i].key] = i;
}
var nextKeyIndex = {};
for (var i = 0; i < next.length; i++) {
nextKeyIndex[next[i].key] = i;
}
// first, an overly elaborate way of merging prev and next, eliminating
// duplicates (in terms of keys). If there's dupe, keep the item in next).
// This way of writing it saves allocations
var ret = [];
for (var i = 0; i < next.length; i++) {
ret[i] = next[i];
}
for (var i = 0; i < prev.length; i++) {
if (!nextKeyIndex.hasOwnProperty(prev[i].key)) {
// this is called my TM's `mergeAndSync`, which calls willLeave. We don't
// merge in keys that the user desires to kill
var fill = onRemove(i, prev[i]);
if (fill != null) {
ret.push(fill);
}
}
}
// now all the items all present. Core sorting logic to have the right order
return ret.sort(function (a, b) {
var nextOrderA = nextKeyIndex[a.key];
var nextOrderB = nextKeyIndex[b.key];
var prevOrderA = prevKeyIndex[a.key];
var prevOrderB = prevKeyIndex[b.key];
if (nextOrderA != null && nextOrderB != null) {
// both keys in next
return nextKeyIndex[a.key] - nextKeyIndex[b.key];
} else if (prevOrderA != null && prevOrderB != null) {
// both keys in prev
return prevKeyIndex[a.key] - prevKeyIndex[b.key];
} else if (nextOrderA != null) {
// key a in next, key b in prev
// how to determine the order between a and b? We find a "pivot" (term
// abuse), a key present in both prev and next, that is sandwiched between
// a and b. In the context of our above example, if we're comparing a and
// d, b's (the only) pivot
for (var i = 0; i < next.length; i++) {
var pivot = next[i].key;
if (!prevKeyIndex.hasOwnProperty(pivot)) {
continue;
}
if (nextOrderA < nextKeyIndex[pivot] && prevOrderB > prevKeyIndex[pivot]) {
return -1;
} else if (nextOrderA > nextKeyIndex[pivot] && prevOrderB < prevKeyIndex[pivot]) {
return 1;
}
}
// pluggable. default to: next bigger than prev
return 1;
}
// prevOrderA, nextOrderB
for (var i = 0; i < next.length; i++) {
var pivot = next[i].key;
if (!prevKeyIndex.hasOwnProperty(pivot)) {
continue;
}
if (nextOrderB < nextKeyIndex[pivot] && prevOrderA > prevKeyIndex[pivot]) {
return 1;
} else if (nextOrderB > nextKeyIndex[pivot] && prevOrderA < prevKeyIndex[pivot]) {
return -1;
}
}
// pluggable. default to: next bigger than prev
return -1;
});
}
module.exports = exports['default'];
// to loop through and find a key's index each time), but I no longer care
/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports['default'] = spring;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _presets = __webpack_require__(14);
var _presets2 = _interopRequireDefault(_presets);
var defaultConfig = _extends({}, _presets2['default'].noWobble, {
precision: 0.01
});
function spring(val, config) {
return _extends({}, defaultConfig, config, { val: val });
}
module.exports = exports['default'];
/***/ },
/* 14 */
/***/ function(module, exports) {
"use strict";
exports.__esModule = true;
exports["default"] = {
noWobble: { stiffness: 170, damping: 26 }, // the default, if nothing provided
gentle: { stiffness: 120, damping: 14 },
wobbly: { stiffness: 180, damping: 12 },
stiff: { stiffness: 210, damping: 20 }
};
module.exports = exports["default"];
/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {'use strict';
exports.__esModule = true;
exports['default'] = reorderKeys;
var hasWarned = false;
function reorderKeys() {
if (process.env.NODE_ENV === 'development') {
if (!hasWarned) {
hasWarned = true;
console.error('`reorderKeys` has been removed, since it is no longer needed for TransitionMotion\'s new styles array API.');
}
}
}
module.exports = exports['default'];
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)))
/***/ }
/******/ ])
});
;
//# sourceMappingURL=react-motion.map
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |