/*! Shifty 2.14.2 - https://github.com/jeremyckahn/shifty */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("shifty", [], factory);
else if(typeof exports === 'object')
exports["shifty"] = factory();
else
root["shifty"] = factory();
})(global, function() {
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] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = 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;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, "processTweens", function() { return /* reexport */ processTweens; });
__webpack_require__.d(__webpack_exports__, "Tweenable", function() { return /* reexport */ Tweenable; });
__webpack_require__.d(__webpack_exports__, "tween", function() { return /* reexport */ tween; });
__webpack_require__.d(__webpack_exports__, "interpolate", function() { return /* reexport */ interpolate_interpolate; });
__webpack_require__.d(__webpack_exports__, "Scene", function() { return /* reexport */ Scene; });
__webpack_require__.d(__webpack_exports__, "setBezierFunction", function() { return /* reexport */ bezier_setBezierFunction; });
__webpack_require__.d(__webpack_exports__, "unsetBezierFunction", function() { return /* reexport */ bezier_unsetBezierFunction; });
// NAMESPACE OBJECT: ./src/easing-functions.js
var easing_functions_namespaceObject = {};
__webpack_require__.r(easing_functions_namespaceObject);
__webpack_require__.d(easing_functions_namespaceObject, "linear", function() { return linear; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuad", function() { return easeInQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuad", function() { return easeOutQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuad", function() { return easeInOutQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInCubic", function() { return easeInCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutCubic", function() { return easeOutCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutCubic", function() { return easeInOutCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuart", function() { return easeInQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuart", function() { return easeOutQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuart", function() { return easeInOutQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuint", function() { return easeInQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuint", function() { return easeOutQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuint", function() { return easeInOutQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInSine", function() { return easeInSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutSine", function() { return easeOutSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutSine", function() { return easeInOutSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInExpo", function() { return easeInExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutExpo", function() { return easeOutExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutExpo", function() { return easeInOutExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInCirc", function() { return easeInCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutCirc", function() { return easeOutCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutCirc", function() { return easeInOutCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutBounce", function() { return easeOutBounce; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInBack", function() { return easeInBack; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutBack", function() { return easeOutBack; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutBack", function() { return easeInOutBack; });
__webpack_require__.d(easing_functions_namespaceObject, "elastic", function() { return elastic; });
__webpack_require__.d(easing_functions_namespaceObject, "swingFromTo", function() { return swingFromTo; });
__webpack_require__.d(easing_functions_namespaceObject, "swingFrom", function() { return swingFrom; });
__webpack_require__.d(easing_functions_namespaceObject, "swingTo", function() { return swingTo; });
__webpack_require__.d(easing_functions_namespaceObject, "bounce", function() { return bounce; });
__webpack_require__.d(easing_functions_namespaceObject, "bouncePast", function() { return bouncePast; });
__webpack_require__.d(easing_functions_namespaceObject, "easeFromTo", function() { return easeFromTo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeFrom", function() { return easeFrom; });
__webpack_require__.d(easing_functions_namespaceObject, "easeTo", function() { return easeTo; });
// NAMESPACE OBJECT: ./src/token.js
var token_namespaceObject = {};
__webpack_require__.r(token_namespaceObject);
__webpack_require__.d(token_namespaceObject, "doesApply", function() { return doesApply; });
__webpack_require__.d(token_namespaceObject, "tweenCreated", function() { return tweenCreated; });
__webpack_require__.d(token_namespaceObject, "beforeTween", function() { return beforeTween; });
__webpack_require__.d(token_namespaceObject, "afterTween", function() { return afterTween; });
// CONCATENATED MODULE: ./src/easing-functions.js
/*!
* All equations are adapted from Thomas Fuchs'
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js).
*
* Based on Easing Equations (c) 2003 [Robert
* Penner](http://www.robertpenner.com/), all rights reserved. This work is
* [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html).
*/
/*!
* TERMS OF USE - EASING EQUATIONS
* Open source under the BSD License.
* Easing Equations (c) 2003 Robert Penner, all rights reserved.
*/
/**
* @member shifty.Tweenable.formulas
* @description A static Object of {@link shifty.easingFunction}s that can by
* used by Shifty. The default values are defined in
* [`easing-functions.js`](easing-functions.js.html), but you can add your own
* {@link shifty.easingFunction}s by defining them as keys to this Object.
*
* Shifty ships with an implementation of [Robert Penner's easing
* equations](http://robertpenner.com/easing/), as adapted from
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js)'s
* implementation.
*
See the Pen Shifty - Easing formula
* names by Jeremy Kahn (@jeremyckahn) on CodePen.
*
* @type {Object.}
* @static
*/
var linear = function linear(pos) {
return pos;
};
var easeInQuad = function easeInQuad(pos) {
return Math.pow(pos, 2);
};
var easeOutQuad = function easeOutQuad(pos) {
return -(Math.pow(pos - 1, 2) - 1);
};
var easeInOutQuad = function easeInOutQuad(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 2) : -0.5 * ((pos -= 2) * pos - 2);
};
var easeInCubic = function easeInCubic(pos) {
return Math.pow(pos, 3);
};
var easeOutCubic = function easeOutCubic(pos) {
return Math.pow(pos - 1, 3) + 1;
};
var easeInOutCubic = function easeInOutCubic(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 3) : 0.5 * (Math.pow(pos - 2, 3) + 2);
};
var easeInQuart = function easeInQuart(pos) {
return Math.pow(pos, 4);
};
var easeOutQuart = function easeOutQuart(pos) {
return -(Math.pow(pos - 1, 4) - 1);
};
var easeInOutQuart = function easeInOutQuart(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 4) : -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
};
var easeInQuint = function easeInQuint(pos) {
return Math.pow(pos, 5);
};
var easeOutQuint = function easeOutQuint(pos) {
return Math.pow(pos - 1, 5) + 1;
};
var easeInOutQuint = function easeInOutQuint(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 5) : 0.5 * (Math.pow(pos - 2, 5) + 2);
};
var easeInSine = function easeInSine(pos) {
return -Math.cos(pos * (Math.PI / 2)) + 1;
};
var easeOutSine = function easeOutSine(pos) {
return Math.sin(pos * (Math.PI / 2));
};
var easeInOutSine = function easeInOutSine(pos) {
return -0.5 * (Math.cos(Math.PI * pos) - 1);
};
var easeInExpo = function easeInExpo(pos) {
return pos === 0 ? 0 : Math.pow(2, 10 * (pos - 1));
};
var easeOutExpo = function easeOutExpo(pos) {
return pos === 1 ? 1 : -Math.pow(2, -10 * pos) + 1;
};
var easeInOutExpo = function easeInOutExpo(pos) {
if (pos === 0) {
return 0;
}
if (pos === 1) {
return 1;
}
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(2, 10 * (pos - 1));
}
return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
};
var easeInCirc = function easeInCirc(pos) {
return -(Math.sqrt(1 - pos * pos) - 1);
};
var easeOutCirc = function easeOutCirc(pos) {
return Math.sqrt(1 - Math.pow(pos - 1, 2));
};
var easeInOutCirc = function easeInOutCirc(pos) {
return (pos /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - pos * pos) - 1) : 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);
};
var easeOutBounce = function easeOutBounce(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75;
} else if (pos < 2.5 / 2.75) {
return 7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375;
} else {
return 7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375;
}
};
var easeInBack = function easeInBack(pos) {
var s = 1.70158;
return pos * pos * ((s + 1) * pos - s);
};
var easeOutBack = function easeOutBack(pos) {
var s = 1.70158;
return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;
};
var easeInOutBack = function easeInOutBack(pos) {
var s = 1.70158;
if ((pos /= 0.5) < 1) {
return 0.5 * (pos * pos * (((s *= 1.525) + 1) * pos - s));
}
return 0.5 * ((pos -= 2) * pos * (((s *= 1.525) + 1) * pos + s) + 2);
};
var elastic = function elastic(pos) {
return -1 * Math.pow(4, -8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;
};
var swingFromTo = function swingFromTo(pos) {
var s = 1.70158;
return (pos /= 0.5) < 1 ? 0.5 * (pos * pos * (((s *= 1.525) + 1) * pos - s)) : 0.5 * ((pos -= 2) * pos * (((s *= 1.525) + 1) * pos + s) + 2);
};
var swingFrom = function swingFrom(pos) {
var s = 1.70158;
return pos * pos * ((s + 1) * pos - s);
};
var swingTo = function swingTo(pos) {
var s = 1.70158;
return (pos -= 1) * pos * ((s + 1) * pos + s) + 1;
};
var bounce = function bounce(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75;
} else if (pos < 2.5 / 2.75) {
return 7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375;
} else {
return 7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375;
}
};
var bouncePast = function bouncePast(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 2 - (7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75);
} else if (pos < 2.5 / 2.75) {
return 2 - (7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375);
} else {
return 2 - (7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375);
}
};
var easeFromTo = function easeFromTo(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 4) : -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
};
var easeFrom = function easeFrom(pos) {
return Math.pow(pos, 4);
};
var easeTo = function easeTo(pos) {
return Math.pow(pos, 0.25);
};
// CONCATENATED MODULE: ./src/tweenable.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// CONSTANTS
var DEFAULT_EASING = 'linear';
var DEFAULT_DURATION = 500;
var UPDATE_TIME = 1000 / 60;
var root = typeof window !== 'undefined' ? window : global;
var AFTER_TWEEN = 'afterTween';
var AFTER_TWEEN_END = 'afterTweenEnd';
var BEFORE_TWEEN = 'beforeTween';
var TWEEN_CREATED = 'tweenCreated';
var TYPE_FUNCTION = 'function';
var TYPE_STRING = 'string'; // requestAnimationFrame() shim by Paul Irish (modified for Shifty)
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
var scheduleFunction = root.requestAnimationFrame || root.webkitRequestAnimationFrame || root.oRequestAnimationFrame || root.msRequestAnimationFrame || root.mozCancelRequestAnimationFrame && root.mozRequestAnimationFrame || setTimeout;
var noop = function noop() {};
var listHead = null;
var listTail = null; // Strictly used for testing
var resetList = function resetList() {
return listHead = listTail = null;
};
var getListHead = function getListHead() {
return listHead;
};
var getListTail = function getListTail() {
return listTail;
};
var formulas = _objectSpread({}, easing_functions_namespaceObject);
/**
* Calculates the interpolated tween values of an Object for a given
* timestamp.
* @param {number} forPosition The position to compute the state for.
* @param {Object} currentState Current state properties.
* @param {Object} originalState: The original state properties the Object is
* tweening from.
* @param {Object} targetState: The destination state properties the Object
* is tweening to.
* @param {number} duration: The length of the tween in milliseconds.
* @param {number} timestamp: The UNIX epoch time at which the tween began.
* @param {Object} easing: This Object's keys must correspond
* to the keys in targetState.
* @returns {Object}
* @private
*/
var tweenProps = function tweenProps(forPosition, currentState, originalState, targetState, duration, timestamp, easing) {
var easedPosition;
var easingObjectProp;
var start;
var normalizedPosition = forPosition < timestamp ? 0 : (forPosition - timestamp) / duration;
var easingFn = null;
var hasOneEase = false;
if (easing && easing.call) {
hasOneEase = true;
easedPosition = easing(normalizedPosition);
}
for (var key in currentState) {
if (!hasOneEase) {
easingObjectProp = easing[key];
easingFn = easingObjectProp.call ? easingObjectProp : formulas[easingObjectProp];
easedPosition = easingFn(normalizedPosition);
}
start = originalState[key];
currentState[key] = start + (targetState[key] - start) * easedPosition;
}
return currentState;
};
var processTween = function processTween(tween, currentTime) {
var timestamp = tween._timestamp;
var currentState = tween._currentState;
var delay = tween._delay;
if (currentTime < timestamp + delay) {
return;
}
var duration = tween._duration;
var targetState = tween._targetState;
var endTime = timestamp + delay + duration;
var timeToCompute = currentTime > endTime ? endTime : currentTime;
var hasEnded = timeToCompute >= endTime;
var offset = duration - (endTime - timeToCompute);
var hasFilters = tween._filters.length > 0;
if (hasEnded) {
tween._render(targetState, tween._data, offset);
return tween.stop(true);
}
if (hasFilters) {
tween._applyFilter(BEFORE_TWEEN);
} // If the animation has not yet reached the start point (e.g., there was
// delay that has not yet completed), just interpolate the starting
// position of the tween.
if (timeToCompute < timestamp + delay) {
timestamp = duration = timeToCompute = 1;
} else {
timestamp += delay;
}
tweenProps(timeToCompute, currentState, tween._originalState, targetState, duration, timestamp, tween._easing);
if (hasFilters) {
tween._applyFilter(AFTER_TWEEN);
}
tween._render(currentState, tween._data, offset);
};
/**
* Process all tweens currently managed by Shifty for the current tick. This
* does not perform any timing or update scheduling; it is the logic that is
* run *by* the scheduling functionality. Specifically, it computes the state
* and calls all of the relevant {@link shifty.tweenConfig} functions supplied
* to each of the tweens for the current point in time (as determined by {@link
* shifty.Tweenable.now}.
*
* This is a low-level API that won't be needed in the majority of situations.
* It is primarily useful as a hook for higher-level animation systems that are
* built on top of Shifty. If you need this function, it is likely you need to
* pass something like `() => {}` to {@link
* shifty.Tweenable.setScheduleFunction}, override {@link shifty.Tweenable.now}
* and manage the scheduling logic yourself.
*
* @method shifty.processTweens
* @see https://github.com/jeremyckahn/shifty/issues/109
*/
var processTweens = function processTweens() {
var nextTweenToProcess;
var currentTime = Tweenable.now();
var currentTween = listHead;
while (currentTween) {
nextTweenToProcess = currentTween._next;
processTween(currentTween, currentTime);
currentTween = nextTweenToProcess;
}
};
var getCurrentTime = Date.now || function () {
return +new Date();
};
var now;
/**
* Handles the update logic for one tick of a tween.
* @param {number} [currentTimeOverride] Needed for accurate timestamp in
* shifty.Tweenable#seek.
* @private
*/
var scheduleUpdate = function scheduleUpdate() {
now = getCurrentTime();
scheduleFunction.call(root, scheduleUpdate, UPDATE_TIME);
processTweens();
};
/**
* Creates a usable easing Object from a string, a function or another easing
* Object. If `easing` is an Object, then this function clones it and fills
* in the missing properties with `"linear"`.
*
* If the tween has only one easing across all properties, that function is
* returned directly.
* @param {Object.} fromTweenParams
* @param {Object|string|Function} [easing]
* @param {Object} [composedEasing] Reused composedEasing object (used internally)
* @return {Object.|Function}
* @private
*/
var composeEasingObject = function composeEasingObject(fromTweenParams) {
var easing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_EASING;
var composedEasing = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var typeofEasing = _typeof(easing);
if (formulas[easing]) {
return formulas[easing];
}
if (typeofEasing === TYPE_STRING || typeofEasing === TYPE_FUNCTION) {
for (var prop in fromTweenParams) {
composedEasing[prop] = easing;
}
} else {
for (var _prop in fromTweenParams) {
composedEasing[_prop] = easing[_prop] || DEFAULT_EASING;
}
}
return composedEasing;
}; // Private declarations used below
var remove = function (previousTween, nextTween) {
return function (tween) {
// Adapted from:
// https://github.com/trekhleb/javascript-algorithms/blob/7c9601df3e8ca4206d419ce50b88bd13ff39deb6/src/data-structures/doubly-linked-list/DoublyLinkedList.js#L73-L121
if (tween === listHead) {
listHead = tween._next;
if (listHead) {
listHead._previous = null;
} else {
listTail = null;
}
} else if (tween === listTail) {
listTail = tween._previous;
if (listTail) {
listTail._next = null;
} else {
listHead = null;
}
} else {
previousTween = tween._previous;
nextTween = tween._next;
previousTween._next = nextTween;
nextTween._previous = previousTween;
} // Clean up any references in case the tween is restarted later.
tween._previous = tween._next = null;
};
}();
var defaultPromiseCtor = typeof Promise === 'function' ? Promise : null;
var Tweenable = /*#__PURE__*/function () {
/**
* @method shifty.Tweenable.now
* @static
* @returns {number} The current timestamp.
*/
/**
* @param {Object} [initialState={}] The values that the initial tween should
* start at if a `from` value is not provided to {@link
* shifty.Tweenable#tween} or {@link shifty.Tweenable#setConfig}.
* @param {shifty.tweenConfig} [config] Configuration object to be passed to
* {@link shifty.Tweenable#setConfig}.
* @constructs shifty.Tweenable
*/
function Tweenable() {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
_classCallCheck(this, Tweenable);
this._config = {};
this._data = {};
this._delay = 0;
this._filters = [];
this._next = null;
this._previous = null;
this._timestamp = null;
this._resolve = null;
this._reject = null;
this._currentState = initialState || {};
this._originalState = {};
this._targetState = {};
this._start = noop;
this._render = noop;
this._promiseCtor = defaultPromiseCtor; // To prevent unnecessary calls to setConfig do not set default
// configuration here. Only set default configuration immediately before
// tweening if none has been set.
if (config) {
this.setConfig(config);
}
}
/**
* Applies a filter to Tweenable instance.
* @param {string} filterName The name of the filter to apply.
* @private
*/
_createClass(Tweenable, [{
key: "_applyFilter",
value: function _applyFilter(filterName) {
for (var i = this._filters.length; i > 0; i--) {
var filterType = this._filters[i - i];
var filter = filterType[filterName];
if (filter) {
filter(this);
}
}
}
/**
* Configure and start a tween. If this {@link shifty.Tweenable}'s instance
* is already running, then it will stop playing the old tween and
* immediately play the new one.
* @method shifty.Tweenable#tween
* @param {shifty.tweenConfig} [config] Gets passed to {@link
* shifty.Tweenable#setConfig}.
* @return {shifty.Tweenable}
*/
}, {
key: "tween",
value: function tween() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
if (this._isPlaying) {
this.stop();
}
if (config || !this._config) {
this.setConfig(config);
}
this._pausedAtTime = null;
this._timestamp = Tweenable.now();
this._start(this.get(), this._data);
if (this._delay) {
this._render(this._currentState, this._data, 0);
}
return this._resume(this._timestamp);
}
/**
* Configure a tween that will start at some point in the future. Aside from
* `delay`, `from`, and `to`, each configuration option will automatically
* default to the same option used in the preceding tween of this {@link
* shifty.Tweenable} instance.
* @method shifty.Tweenable#setConfig
* @param {shifty.tweenConfig} [config={}]
* @return {shifty.Tweenable}
*/
}, {
key: "setConfig",
value: function setConfig() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _config = this._config;
for (var key in config) {
_config[key] = config[key];
} // Configuration options to reuse from previous tweens
var _config$promise = _config.promise,
promise = _config$promise === void 0 ? this._promiseCtor : _config$promise,
_config$start = _config.start,
start = _config$start === void 0 ? noop : _config$start,
finish = _config.finish,
_config$render = _config.render,
render = _config$render === void 0 ? this._config.step || noop : _config$render,
_config$step = _config.step,
step = _config$step === void 0 ? noop : _config$step; // Attach something to this Tweenable instance (e.g.: a DOM element, an
// object, a string, etc.);
this._data = _config.data || _config.attachment || this._data; // Init the internal state
this._isPlaying = false;
this._pausedAtTime = null;
this._scheduleId = null;
this._delay = config.delay || 0;
this._start = start;
this._render = render || step;
this._duration = _config.duration || DEFAULT_DURATION;
this._promiseCtor = promise;
if (finish) {
this._resolve = finish;
}
var from = config.from,
_config$to = config.to,
to = _config$to === void 0 ? {} : _config$to;
var _currentState = this._currentState,
_originalState = this._originalState,
_targetState = this._targetState;
for (var _key in from) {
_currentState[_key] = from[_key];
}
var anyPropsAreStrings = false;
for (var _key2 in _currentState) {
var currentProp = _currentState[_key2];
if (!anyPropsAreStrings && _typeof(currentProp) === TYPE_STRING) {
anyPropsAreStrings = true;
}
_originalState[_key2] = currentProp; // Ensure that there is always something to tween to.
_targetState[_key2] = to.hasOwnProperty(_key2) ? to[_key2] : currentProp;
}
this._easing = composeEasingObject(this._currentState, _config.easing, this._easing);
this._filters.length = 0;
if (anyPropsAreStrings) {
for (var _key3 in Tweenable.filters) {
if (Tweenable.filters[_key3].doesApply(this)) {
this._filters.push(Tweenable.filters[_key3]);
}
}
this._applyFilter(TWEEN_CREATED);
}
return this;
}
/**
* Overrides any `finish` function passed via a {@link shifty.tweenConfig}.
* @method shifty.Tweenable#then
* @param {function} onFulfilled Receives {@link shifty.promisedData} as the
* first parameter.
* @param {function} onRejected Receives {@link shifty.promisedData} as the
* first parameter.
* @return {external:Promise}
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
*/
}, {
key: "then",
value: function then(onFulfilled, onRejected) {
var _this = this;
this._promise = new this._promiseCtor(function (resolve, reject) {
_this._resolve = resolve;
_this._reject = reject;
});
return this._promise.then(onFulfilled, onRejected);
}
/**
* @method shifty.Tweenable#catch
* @param {function} onRejected Receives {@link shifty.promisedData} as the
* first parameter.
* @return {external:Promise}
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
*/
}, {
key: "catch",
value: function _catch(onRejected) {
return this.then()["catch"](onRejected);
}
/**
* @method shifty.Tweenable#get
* @return {Object} The current state.
*/
}, {
key: "get",
value: function get() {
return _objectSpread({}, this._currentState);
}
/**
* Set the current state.
* @method shifty.Tweenable#set
* @param {Object} state The state to set.
*/
}, {
key: "set",
value: function set(state) {
this._currentState = state;
}
/**
* Pause a tween. Paused tweens can be resumed from the point at which they
* were paused. If a tween is not running, this is a no-op.
* @method shifty.Tweenable#pause
* @return {shifty.Tweenable}
*/
}, {
key: "pause",
value: function pause() {
if (!this._isPlaying) {
return;
}
this._pausedAtTime = Tweenable.now();
this._isPlaying = false;
remove(this);
return this;
}
/**
* Resume a paused tween.
* @method shifty.Tweenable#resume
* @return {shifty.Tweenable}
*/
}, {
key: "resume",
value: function resume() {
return this._resume();
}
}, {
key: "_resume",
value: function _resume() {
var currentTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Tweenable.now();
if (this._timestamp === null) {
return this.tween();
}
if (this._isPlaying) {
return this._promise;
}
if (this._pausedAtTime) {
this._timestamp += currentTime - this._pausedAtTime;
this._pausedAtTime = null;
}
this._isPlaying = true;
if (listHead === null) {
listHead = this;
listTail = this;
} else {
this._previous = listTail;
listTail._next = this;
listTail = this;
}
return this;
}
/**
* Move the state of the animation to a specific point in the tween's
* timeline. If the animation is not running, this will cause {@link
* shifty.renderFunction} handlers to be called.
* @method shifty.Tweenable#seek
* @param {millisecond} millisecond The millisecond of the animation to seek
* to. This must not be less than `0`.
* @return {shifty.Tweenable}
*/
}, {
key: "seek",
value: function seek(millisecond) {
millisecond = Math.max(millisecond, 0);
var currentTime = Tweenable.now();
if (this._timestamp + millisecond === 0) {
return this;
}
this._timestamp = currentTime - millisecond; // Make sure that any render handlers are run.
processTween(this, currentTime);
return this;
}
/**
* Stops a tween. If a tween is not running, this is a no-op. This method
* does not cancel the tween {@link external:Promise}. For that, use {@link
* shifty.Tweenable#cancel}.
* @param {boolean} [gotoEnd] If `false`, the tween just stops at its current
* state. If `true`, the tweened object's values are instantly set to the
* target values.
* @method shifty.Tweenable#stop
* @return {shifty.Tweenable}
*/
}, {
key: "stop",
value: function stop() {
var gotoEnd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
if (!this._isPlaying) {
return this;
}
this._isPlaying = false;
remove(this);
var hasFilters = this._filters.length > 0;
if (gotoEnd) {
if (hasFilters) {
this._applyFilter(BEFORE_TWEEN);
}
tweenProps(1, this._currentState, this._originalState, this._targetState, 1, 0, this._easing);
if (hasFilters) {
this._applyFilter(AFTER_TWEEN);
this._applyFilter(AFTER_TWEEN_END);
}
}
if (this._resolve) {
this._resolve({
data: this._data,
state: this._currentState,
tweenable: this
});
}
this._resolve = null;
this._reject = null;
var _currentState = this._currentState,
_originalState = this._originalState,
_targetState = this._targetState;
for (var key in _currentState) {
_originalState[key] = _targetState[key] = _currentState[key];
}
return this;
}
/**
* {@link shifty.Tweenable#stop}s a tween and also `reject`s its {@link
* external:Promise}. If a tween is not running, this is a no-op. Prevents
* calling any provided `finish` function.
* @param {boolean} [gotoEnd] Is propagated to {@link shifty.Tweenable#stop}.
* @method shifty.Tweenable#cancel
* @return {shifty.Tweenable}
* @see https://github.com/jeremyckahn/shifty/issues/122
*/
}, {
key: "cancel",
value: function cancel() {
var gotoEnd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var _currentState = this._currentState,
_data = this._data,
_isPlaying = this._isPlaying;
if (!_isPlaying) {
return this;
}
if (this._reject) {
this._reject({
data: _data,
state: _currentState,
tweenable: this
});
}
this._resolve = null;
this._reject = null;
return this.stop(gotoEnd);
}
/**
* Whether or not a tween is running.
* @method shifty.Tweenable#isPlaying
* @return {boolean}
*/
}, {
key: "isPlaying",
value: function isPlaying() {
return this._isPlaying;
}
/**
* @method shifty.Tweenable#setScheduleFunction
* @param {shifty.scheduleFunction} scheduleFunction
* @deprecated Will be removed in favor of {@link shifty.Tweenable.setScheduleFunction} in 3.0.
*/
}, {
key: "setScheduleFunction",
value: function setScheduleFunction(scheduleFunction) {
Tweenable.setScheduleFunction(scheduleFunction);
}
/**
* Get and optionally set the data that gets passed as `data` to {@link
* shifty.promisedData}, {@link shifty.startFunction} and {@link
* shifty.renderFunction}.
* @param {Object} [data]
* @method shifty.Tweenable#data
* @return {Object} The internally stored `data`.
*/
}, {
key: "data",
value: function data() {
var _data2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (_data2) {
this._data = _objectSpread({}, _data2);
}
return this._data;
}
/**
* `delete` all "own" properties. Call this when the {@link
* shifty.Tweenable} instance is no longer needed to free memory.
* @method shifty.Tweenable#dispose
*/
}, {
key: "dispose",
value: function dispose() {
for (var prop in this) {
delete this[prop];
}
}
}]);
return Tweenable;
}(); // TODO: Make these proper static methods.
/**
* Set a custom schedule function.
*
* By default,
* [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame)
* is used if available, otherwise
* [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)
* is used.
* @method shifty.Tweenable.setScheduleFunction
* @param {shifty.scheduleFunction} fn The function to be
* used to schedule the next frame to be rendered.
* @return {shifty.scheduleFunction} The function that was set.
*/
_defineProperty(Tweenable, "now", function () {
return now;
});
Tweenable.setScheduleFunction = function (fn) {
return scheduleFunction = fn;
};
Tweenable.formulas = formulas;
/**
* The {@link shifty.filter}s available for use. These filters are
* automatically applied at tween-time by Shifty. You can define your own
* {@link shifty.filter}s and attach them to this object.
* @member shifty.Tweenable.filters
* @type {Object.}
*/
Tweenable.filters = {};
/**
* @method shifty.tween
* @param {shifty.tweenConfig} [config={}]
* @description Standalone convenience method that functions identically to
* {@link shifty.Tweenable#tween}. You can use this to create tweens without
* needing to set up a {@link shifty.Tweenable} instance.
*
* ```
* import { tween } from 'shifty';
*
* tween({ from: { x: 0 }, to: { x: 10 } }).then(
* () => console.log('All done!')
* );
* ```
*
* @returns {shifty.Tweenable} A new {@link shifty.Tweenable} instance.
*/
function tween() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var tweenable = new Tweenable();
tweenable.tween(config); // This is strictly a legacy shim from when this function returned a Promise.
// REMOVE THIS LINE IN THE NEXT MAJOR VERSION
tweenable.tweenable = tweenable;
return tweenable;
}
scheduleUpdate();
// CONCATENATED MODULE: ./src/token.js
var R_NUMBER_COMPONENT = /(\d|-|\.)/;
var R_FORMAT_CHUNKS = /([^\-0-9.]+)/g;
var R_UNFORMATTED_VALUES = /[0-9.-]+/g;
var R_RGB = function () {
var number = R_UNFORMATTED_VALUES.source;
var comma = /,\s*/.source;
return new RegExp("rgb\\(".concat(number).concat(comma).concat(number).concat(comma).concat(number, "\\)"), 'g');
}();
var R_RGB_PREFIX = /^.*\(/;
var R_HEX = /#([0-9]|[a-f]){3,6}/gi;
var VALUE_PLACEHOLDER = 'VAL'; // HELPERS
/**
* @param {Array.number} rawValues
* @param {string} prefix
*
* @return {Array.}
* @private
*/
var getFormatChunksFrom = function getFormatChunksFrom(rawValues, prefix) {
return rawValues.map(function (val, i) {
return "_".concat(prefix, "_").concat(i);
});
};
/**
* @param {string} formattedString
*
* @return {string}
* @private
*/
var getFormatStringFrom = function getFormatStringFrom(formattedString) {
var chunks = formattedString.match(R_FORMAT_CHUNKS);
if (!chunks) {
// chunks will be null if there were no tokens to parse in
// formattedString (for example, if formattedString is '2'). Coerce
// chunks to be useful here.
chunks = ['', '']; // If there is only one chunk, assume that the string is a number
// followed by a token...
// NOTE: This may be an unwise assumption.
} else if (chunks.length === 1 || // ...or if the string starts with a number component (".", "-", or a
// digit)...
formattedString.charAt(0).match(R_NUMBER_COMPONENT)) {
// ...prepend an empty string here to make sure that the formatted number
// is properly replaced by VALUE_PLACEHOLDER
chunks.unshift('');
}
return chunks.join(VALUE_PLACEHOLDER);
};
/**
* Convert a base-16 number to base-10.
*
* @param {number|string} hex The value to convert.
*
* @returns {number} The base-10 equivalent of `hex`.
* @private
*/
function hexToDec(hex) {
return parseInt(hex, 16);
}
/**
* Convert a hexadecimal string to an array with three items, one each for
* the red, blue, and green decimal values.
*
* @param {string} hex A hexadecimal string.
*
* @returns {Array.} The converted Array of RGB values if `hex` is a
* valid string, or an Array of three 0's.
* @private
*/
var hexToRGBArray = function hexToRGBArray(hex) {
hex = hex.replace(/#/, ''); // If the string is a shorthand three digit hex notation, normalize it to
// the standard six digit notation
if (hex.length === 3) {
hex = hex.split('');
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
return [hexToDec(hex.substr(0, 2)), hexToDec(hex.substr(2, 2)), hexToDec(hex.substr(4, 2))];
};
/**
* @param {string} hexString
*
* @return {string}
* @private
*/
var convertHexToRGB = function convertHexToRGB(hexString) {
return "rgb(".concat(hexToRGBArray(hexString).join(','), ")");
};
/**
* TODO: Can this be rewritten to leverage String#replace more efficiently?
* Runs a filter operation on all chunks of a string that match a RegExp.
*
* @param {RegExp} pattern
* @param {string} unfilteredString
* @param {function(string)} filter
*
* @return {string}
* @private
*/
var filterStringChunks = function filterStringChunks(pattern, unfilteredString, filter) {
var patternMatches = unfilteredString.match(pattern);
var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER);
if (patternMatches) {
patternMatches.forEach(function (match) {
return filteredString = filteredString.replace(VALUE_PLACEHOLDER, filter(match));
});
}
return filteredString;
};
/**
* @param {string} str
*
* @return {string}
* @private
*/
var sanitizeHexChunksToRGB = function sanitizeHexChunksToRGB(str) {
return filterStringChunks(R_HEX, str, convertHexToRGB);
};
/**
* Convert all hex color values within a string to an rgb string.
*
* @param {Object} stateObject
* @private
*/
var sanitizeObjectForHexProps = function sanitizeObjectForHexProps(stateObject) {
for (var prop in stateObject) {
var currentProp = stateObject[prop];
if (typeof currentProp === 'string' && currentProp.match(R_HEX)) {
stateObject[prop] = sanitizeHexChunksToRGB(currentProp);
}
}
};
/**
* @param {string} rgbChunk
*
* @return {string}
* @private
*/
var sanitizeRGBChunk = function sanitizeRGBChunk(rgbChunk) {
var numbers = rgbChunk.match(R_UNFORMATTED_VALUES).map(Math.floor);
var prefix = rgbChunk.match(R_RGB_PREFIX)[0];
return "".concat(prefix).concat(numbers.join(','), ")");
};
/**
* Check for floating point values within rgb strings and round them.
*
* @param {string} formattedString
*
* @return {string}
* @private
*/
var sanitizeRGBChunks = function sanitizeRGBChunks(formattedString) {
return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk);
};
/**
* Note: It's the duty of the caller to convert the Array elements of the
* return value into numbers. This is a performance optimization.
*
* @param {string} formattedString
*
* @return {Array.|null}
* @private
*/
var getValuesFrom = function getValuesFrom(formattedString) {
return formattedString.match(R_UNFORMATTED_VALUES);
};
/**
* @param {Object} stateObject
*
* @return {Object} An Object of formatSignatures that correspond to
* the string properties of stateObject.
* @private
*/
var getFormatSignatures = function getFormatSignatures(stateObject) {
var signatures = {};
for (var propertyName in stateObject) {
var property = stateObject[propertyName];
if (typeof property === 'string') {
signatures[propertyName] = {
formatString: getFormatStringFrom(property),
chunkNames: getFormatChunksFrom(getValuesFrom(property), propertyName)
};
}
}
return signatures;
};
/**
* @param {Object} stateObject
* @param {Object} formatSignatures
* @private
*/
var expandFormattedProperties = function expandFormattedProperties(stateObject, formatSignatures) {
var _loop = function _loop(propertyName) {
getValuesFrom(stateObject[propertyName]).forEach(function (number, i) {
return stateObject[formatSignatures[propertyName].chunkNames[i]] = +number;
});
delete stateObject[propertyName];
};
for (var propertyName in formatSignatures) {
_loop(propertyName);
}
};
/**
* @param {Object} stateObject
* @param {Array.} chunkNames
*
* @return {Object} The extracted value chunks.
* @private
*/
var extractPropertyChunks = function extractPropertyChunks(stateObject, chunkNames) {
var extractedValues = {};
chunkNames.forEach(function (chunkName) {
extractedValues[chunkName] = stateObject[chunkName];
delete stateObject[chunkName];
});
return extractedValues;
};
/**
* @param {Object} stateObject
* @param {Array.} chunkNames
*
* @return {Array.}
* @private
*/
var getValuesList = function getValuesList(stateObject, chunkNames) {
return chunkNames.map(function (chunkName) {
return stateObject[chunkName];
});
};
/**
* @param {string} formatString
* @param {Array.} rawValues
*
* @return {string}
* @private
*/
var getFormattedValues = function getFormattedValues(formatString, rawValues) {
rawValues.forEach(function (rawValue) {
return formatString = formatString.replace(VALUE_PLACEHOLDER, +rawValue.toFixed(4));
});
return formatString;
};
/**
* @param {Object} stateObject
* @param {Object} formatSignatures
* @private
*/
var collapseFormattedProperties = function collapseFormattedProperties(stateObject, formatSignatures) {
for (var prop in formatSignatures) {
var _formatSignatures$pro = formatSignatures[prop],
chunkNames = _formatSignatures$pro.chunkNames,
formatString = _formatSignatures$pro.formatString;
var currentProp = getFormattedValues(formatString, getValuesList(extractPropertyChunks(stateObject, chunkNames), chunkNames));
stateObject[prop] = sanitizeRGBChunks(currentProp);
}
};
/**
* @param {Object} easingObject
* @param {Object} tokenData
* @private
*/
var expandEasingObject = function expandEasingObject(easingObject, tokenData) {
var _loop2 = function _loop2(prop) {
var chunkNames = tokenData[prop].chunkNames;
var easing = easingObject[prop];
if (typeof easing === 'string') {
var easingNames = easing.split(' ');
var defaultEasing = easingNames[easingNames.length - 1];
chunkNames.forEach(function (chunkName, i) {
return easingObject[chunkName] = easingNames[i] || defaultEasing;
});
} else {
// easing is a function
chunkNames.forEach(function (chunkName) {
return easingObject[chunkName] = easing;
});
}
delete easingObject[prop];
};
for (var prop in tokenData) {
_loop2(prop);
}
};
/**
* @param {Object} easingObject
* @param {Object} tokenData
* @private
*/
var collapseEasingObject = function collapseEasingObject(easingObject, tokenData) {
for (var prop in tokenData) {
var chunkNames = tokenData[prop].chunkNames;
var firstEasing = easingObject[chunkNames[0]];
if (typeof firstEasing === 'string') {
easingObject[prop] = chunkNames.map(function (chunkName) {
var easingName = easingObject[chunkName];
delete easingObject[chunkName];
return easingName;
}).join(' ');
} else {
// firstEasing is a function
easingObject[prop] = firstEasing;
}
}
};
var doesApply = function doesApply(tweenable) {
for (var key in tweenable._currentState) {
if (typeof tweenable._currentState[key] === 'string') {
return true;
}
}
return false;
};
function tweenCreated(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState;
[_currentState, _originalState, _targetState].forEach(sanitizeObjectForHexProps);
tweenable._tokenData = getFormatSignatures(_currentState);
}
function beforeTween(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState,
_easing = tweenable._easing,
_tokenData = tweenable._tokenData;
expandEasingObject(_easing, _tokenData);
[_currentState, _originalState, _targetState].forEach(function (state) {
return expandFormattedProperties(state, _tokenData);
});
}
function afterTween(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState,
_easing = tweenable._easing,
_tokenData = tweenable._tokenData;
[_currentState, _originalState, _targetState].forEach(function (state) {
return collapseFormattedProperties(state, _tokenData);
});
collapseEasingObject(_easing, _tokenData);
}
// CONCATENATED MODULE: ./src/interpolate.js
function interpolate_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function interpolate_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { interpolate_ownKeys(Object(source), true).forEach(function (key) { interpolate_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { interpolate_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function interpolate_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// Fake a Tweenable and patch some internals. This approach allows us to
// skip uneccessary processing and object recreation, cutting down on garbage
// collection pauses.
var mockTweenable = new Tweenable();
var filters = Tweenable.filters;
/**
* Compute the midpoint of two Objects. This method effectively calculates a
* specific frame of animation that {@link shifty.Tweenable#tween} does many times
* over the course of a full tween.
*
* ```
* import { interpolate } from 'shifty';
*
* const interpolatedValues = interpolate({
* width: '100px',
* opacity: 0,
* color: '#fff'
* }, {
* width: '200px',
* opacity: 1,
* color: '#000'
* },
* 0.5
* );
*
* console.log(interpolatedValues); // Logs: {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"}
* ```
*
* @method shifty.interpolate
* @param {Object} from The starting values to tween from.
* @param {Object} to The ending values to tween to.
* @param {number} position The normalized position value (between `0.0` and
* `1.0`) to interpolate the values between `from` and `to` for. `from`
* represents `0` and `to` represents `1`.
* @param {Object.|string|shifty.easingFunction}
* easing The easing curve(s) to calculate the midpoint against. You can
* reference any easing function attached to {@link shifty.Tweenable.formulas},
* or provide the {@link shifty.easingFunction}(s) directly. If omitted, this
* defaults to "linear".
* @param {number} [delay=0] Optional delay to pad the beginning of the
* interpolated tween with. This increases the range of `position` from (`0`
* through `1`) to (`0` through `1 + delay`). So, a delay of `0.5` would
* increase all valid values of `position` to numbers between `0` and `1.5`.
* @return {Object}
*/
var interpolate_interpolate = function interpolate(from, to, position, easing) {
var delay = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
var current = interpolate_objectSpread({}, from);
var easingObject = composeEasingObject(from, easing);
mockTweenable._filters.length = 0;
mockTweenable.set({});
mockTweenable._currentState = current;
mockTweenable._originalState = from;
mockTweenable._targetState = to;
mockTweenable._easing = easingObject;
for (var name in filters) {
if (filters[name].doesApply(mockTweenable)) {
mockTweenable._filters.push(filters[name]);
}
} // Any defined value transformation must be applied
mockTweenable._applyFilter('tweenCreated');
mockTweenable._applyFilter('beforeTween');
var interpolatedValues = tweenProps(position, current, from, to, 1, delay, easingObject); // Transform data in interpolatedValues back into its original format
mockTweenable._applyFilter('afterTween');
return interpolatedValues;
};
// CONCATENATED MODULE: ./src/scene.js
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function scene_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function scene_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function scene_createClass(Constructor, protoProps, staticProps) { if (protoProps) scene_defineProperties(Constructor.prototype, protoProps); if (staticProps) scene_defineProperties(Constructor, staticProps); return Constructor; }
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
var _tweenables = new WeakMap();
var Scene = /*#__PURE__*/function () {
/**
* The {@link shifty.Scene} class provides a way to control groups of {@link
* shifty.Tweenable}s. It is lightweight, minimalistic, and meant to provide
* performant {@link shifty.Tweenable} batch control that users of Shifty
* might otherwise have to implement themselves. It is **not** a robust
* timeline solution, and it does **not** provide utilities for sophisticated
* animation sequencing or orchestration. If that is what you need for your
* project, consider using a more robust tool such as
* [Rekapi](http://jeremyckahn.github.io/rekapi/doc/) (a timeline layer built
* on top of Shifty).
*
* Please be aware that {@link shifty.Scene} does **not** perform any
* automatic cleanup. If you want to remove a {@link shifty.Tweenable} from a
* {@link shifty.Scene}, you must do so explicitly with either {@link
* shifty.Scene#remove} or {@link shifty.Scene#empty}.
*
*
* See the Pen
* Shifty Scene Demo by Jeremy Kahn (@jeremyckahn)
* on CodePen.
*
*
* @param {...shifty.Tweenable} tweenables
* @see https://codepen.io/jeremyckahn/pen/qvZKbe
* @constructs shifty.Scene
*/
function Scene() {
scene_classCallCheck(this, Scene);
_tweenables.set(this, {
writable: true,
value: []
});
for (var _len = arguments.length, tweenables = new Array(_len), _key = 0; _key < _len; _key++) {
tweenables[_key] = arguments[_key];
}
tweenables.forEach(this.add.bind(this));
}
/**
* A copy of the internal {@link shifty.Tweenable}s array.
* @member shifty.Scene#tweenables
* @type {Array.}
* @readonly
*/
scene_createClass(Scene, [{
key: "add",
/**
* Add a {@link shifty.Tweenable} to be controlled by this {@link
* shifty.Scene}.
* @method shifty.Scene#add
* @param {shifty.Tweenable} tweenable
* @return {shifty.Tweenable} The {@link shifty.Tweenable} that was added.
*/
value: function add(tweenable) {
_classPrivateFieldGet(this, _tweenables).push(tweenable);
return tweenable;
}
/**
* Remove a {@link shifty.Tweenable} that is controlled by this {@link
* shifty.Scene}.
* @method shifty.Scene#remove
* @param {shifty.Tweenable} tweenable
* @return {shifty.Tweenable} The {@link shifty.Tweenable} that was removed.
*/
}, {
key: "remove",
value: function remove(tweenable) {
var index = _classPrivateFieldGet(this, _tweenables).indexOf(tweenable);
if (~index) {
_classPrivateFieldGet(this, _tweenables).splice(index, 1);
}
return tweenable;
}
/**
* [Remove]{@link shifty.Scene#remove} all {@link shifty.Tweenable}s in this {@link
* shifty.Scene}.
* @method shifty.Scene#empty
* @return {Array.} The {@link shifty.Tweenable}s that were
* removed.
*/
}, {
key: "empty",
value: function empty() {
// Deliberate of the tweenables getter here to create a temporary array
return this.tweenables.map(this.remove.bind(this));
}
/**
* Is `true` if any {@link shifty.Tweenable} in this {@link shifty.Scene} is
* playing.
* @method shifty.Scene#isPlaying
* @return {boolean}
*/
}, {
key: "isPlaying",
value: function isPlaying() {
return _classPrivateFieldGet(this, _tweenables).some(function (tweenable) {
return tweenable.isPlaying();
});
}
/**
* Play all {@link shifty.Tweenable}s from their beginning.
* @method shifty.Scene#play
* @return {shifty.Scene}
*/
}, {
key: "play",
value: function play() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.tween();
});
return this;
}
/**
* {@link shifty.Tweenable#pause} all {@link shifty.Tweenable}s in this
* {@link shifty.Scene}.
* @method shifty.Scene#pause
* @return {shifty.Scene}
*/
}, {
key: "pause",
value: function pause() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.pause();
});
return this;
}
/**
* {@link shifty.Tweenable#resume} all paused {@link shifty.Tweenable}s.
* @method shifty.Scene#resume
* @return {shifty.Scene}
*/
}, {
key: "resume",
value: function resume() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.resume();
});
return this;
}
/**
* {@link shifty.Tweenable#stop} all {@link shifty.Tweenable}s in this {@link
* shifty.Scene}.
* @method shifty.Scene#stop
* @param {boolean} [gotoEnd]
* @return {shifty.Scene}
*/
}, {
key: "stop",
value: function stop(gotoEnd) {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.stop(gotoEnd);
});
return this;
}
}, {
key: "tweenables",
get: function get() {
return _toConsumableArray(_classPrivateFieldGet(this, _tweenables));
}
/**
* The {@link external:Promise}s for all {@link shifty.Tweenable}s in this
* {@link shifty.Scene} that have been configured with {@link
* shifty.Tweenable#setConfig}. Note that each call of {@link
* shifty.Scene#play} or {@link shifty.Scene#pause} creates new {@link
* external:Promise}s:
*
* const scene = new Scene(new Tweenable());
* scene.play();
*
* Promise.all(scene.promises).then(() =>
* // Plays the scene again upon completion, but a new promise is
* // created so this line only runs once.
* scene.play()
* );
*
* @member shifty.Scene#promises
* @type {Array.}
* @readonly
*/
}, {
key: "promises",
get: function get() {
return _classPrivateFieldGet(this, _tweenables).map(function (tweenable) {
return tweenable.then();
});
}
}]);
return Scene;
}();
// CONCATENATED MODULE: ./src/bezier.js
/**
* The Bezier magic in this file is adapted/copied almost wholesale from
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js),
* which was adapted from Apple code (which probably came from
* [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)).
* Special thanks to Apple and Thomas Fuchs for much of this code.
*/
/**
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder(s) nor the names of any
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
// port of webkit cubic bezier handling by http://www.netzgesta.de/dev/
/**
* @param {number} t
* @param {number} p1x
* @param {number} p1y
* @param {number} p2x
* @param {number} p2y
* @param {number} duration
* @returns {Function}
* @private
*/
function cubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
var ax = 0,
bx = 0,
cx = 0,
ay = 0,
by = 0,
cy = 0;
var sampleCurveX = function sampleCurveX(t) {
return ((ax * t + bx) * t + cx) * t;
};
var sampleCurveY = function sampleCurveY(t) {
return ((ay * t + by) * t + cy) * t;
};
var sampleCurveDerivativeX = function sampleCurveDerivativeX(t) {
return (3 * ax * t + 2 * bx) * t + cx;
};
var solveEpsilon = function solveEpsilon(duration) {
return 1 / (200 * duration);
};
var fabs = function fabs(n) {
return n >= 0 ? n : 0 - n;
};
var solveCurveX = function solveCurveX(x, epsilon) {
var t0, t1, t2, x2, d2, i;
for (t2 = x, i = 0; i < 8; i++) {
x2 = sampleCurveX(t2) - x;
if (fabs(x2) < epsilon) {
return t2;
}
d2 = sampleCurveDerivativeX(t2);
if (fabs(d2) < 1e-6) {
break;
}
t2 = t2 - x2 / d2;
}
t0 = 0;
t1 = 1;
t2 = x;
if (t2 < t0) {
return t0;
}
if (t2 > t1) {
return t1;
}
while (t0 < t1) {
x2 = sampleCurveX(t2);
if (fabs(x2 - x) < epsilon) {
return t2;
}
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
return t2; // Failure.
};
var solve = function solve(x, epsilon) {
return sampleCurveY(solveCurveX(x, epsilon));
};
cx = 3 * p1x;
bx = 3 * (p2x - p1x) - cx;
ax = 1 - cx - bx;
cy = 3 * p1y;
by = 3 * (p2y - p1y) - cy;
ay = 1 - cy - by;
return solve(t, solveEpsilon(duration));
} // End ported code
/**
* GetCubicBezierTransition(x1, y1, x2, y2) -> Function.
*
* Generates a transition easing function that is compatible
* with WebKit's CSS transitions `-webkit-transition-timing-function`
* CSS property.
*
* The W3C has more information about CSS3 transition timing functions:
* http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {Function}
* @private
*/
var getCubicBezierTransition = function getCubicBezierTransition(x1, y1, x2, y2) {
return function (pos) {
return cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
};
};
/**
* Create a Bezier easing function and attach it to {@link
* shifty.Tweenable.formulas}. This function gives you total control over the
* easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a
* useful tool for visualizing the curves you can make with this function.
* @method shifty.setBezierFunction
* @param {string} name The name of the easing curve. Overwrites the old
* easing function on {@link shifty.Tweenable.formulas} if it exists.
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {shifty.easingFunction} The {@link shifty.easingFunction} that was
* attached to {@link shifty.Tweenable.formulas}.
*/
var bezier_setBezierFunction = function setBezierFunction(name, x1, y1, x2, y2) {
var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2);
cubicBezierTransition.displayName = name;
cubicBezierTransition.x1 = x1;
cubicBezierTransition.y1 = y1;
cubicBezierTransition.x2 = x2;
cubicBezierTransition.y2 = y2;
return Tweenable.formulas[name] = cubicBezierTransition;
};
/**
* `delete` an easing function from {@link shifty.Tweenable.formulas}. Be
* careful with this method, as it `delete`s whatever easing formula matches
* `name` (which means you can delete standard Shifty easing functions).
* @method shifty.unsetBezierFunction
* @param {string} name The name of the easing function to delete.
* @return {boolean} Whether or not the functions was `delete`d.
*/
var bezier_unsetBezierFunction = function unsetBezierFunction(name) {
return delete Tweenable.formulas[name];
};
// CONCATENATED MODULE: ./src/index.js
/**
* @namespace shifty
*/
Tweenable.filters.token = token_namespaceObject;
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise}
*/
/**
* @external thenable
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then}
*/
/**
* @callback {Function} shifty.easingFunction
* @param {number} position The normalized (0-1) position of the tween.
* @return {number} The curve-adjusted value.
*/
/**
* @callback {Function} shifty.startFunction
* @param {Object} state The current state of the tween.
* @param {Object|undefined} [data] User-defined data provided via a {@link
* shifty.tweenConfig}.
*/
/**
* @callback {Function} shifty.finishFunction
* @param {shifty.promisedData} promisedData
*/
/**
* Gets called for every tick of the tween. This function is not called on the
* final tick of the animation.
* @callback {Function} shifty.renderFunction
* @param {Object} state The current state of the tween.
* @param {Object|undefined} [data] User-defined data provided via a {@link
* shifty.tweenConfig}.
* @param {number} timeElapsed The time elapsed since the start of the tween.
*/
/**
* @callback shifty.scheduleFunction
* @param {Function} callback
* @param {number} timeout
*/
/**
* @typedef {Object} shifty.tweenConfig
* @property {Object} [from] Starting position. If omitted, {@link
* shifty.Tweenable#get} is used.
* @property {Object} [to] Ending position. The keys of this Object should
* match those of `to`.
* @property {number} [duration] How many milliseconds to animate for.
* @property {number} [delay] How many milliseconds to wait before starting the
* tween.
* @property {shifty.startFunction} [start] Executes when the tween begins.
* @property {shifty.finishFunction} [finish] Executes when the tween
* completes. This will get overridden by {@link shifty.Tweenable#then} if that
* is called, and it will not fire if {@link shifty.Tweenable#cancel} is
* called.
* @property {shifty.renderFunction} [render] Executes on every tick. Shifty
* assumes a [retained mode](https://en.wikipedia.org/wiki/Retained_mode)
* rendering environment, which in practice means that `render` only gets
* called when the tween state changes. Importantly, this means that `render`
* is _not_ called when a tween is not animating (for instance, when it is
* paused or waiting to start via the `delay` option). This works naturally
* with DOM environments, but you may need to account for this design in more
* custom environments such as `