UNPKG

react-spring

Version:
1,697 lines (1,384 loc) 56.5 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _extends = _interopDefault(require('@babel/runtime/helpers/builtin/extends')); var _inheritsLoose = _interopDefault(require('@babel/runtime/helpers/builtin/inheritsLoose')); var React = _interopDefault(require('react')); var _objectWithoutProperties = _interopDefault(require('@babel/runtime/helpers/builtin/objectWithoutProperties')); var bugfixes = undefined; var applyAnimatedValues = undefined; var colorNames = []; var requestFrame = function requestFrame(cb) { return global.requestAnimationFrame(cb); }; var cancelFrame = function cancelFrame(cb) { return global.cancelAnimationFrame(cb); }; var interpolation = undefined; var injectApplyAnimatedValues = function injectApplyAnimatedValues(fn, transform) { return applyAnimatedValues = { fn: fn, transform: transform }; }; var injectColorNames = function injectColorNames(names) { return colorNames = names; }; var injectBugfixes = function injectBugfixes(fn) { return bugfixes = fn; }; var injectInterpolation = function injectInterpolation(cls) { return interpolation = cls; }; var injectFrame = function injectFrame(raf, caf) { var _ref; return _ref = [raf, caf], requestFrame = _ref[0], cancelFrame = _ref[1], _ref; }; var Globals = /*#__PURE__*/Object.freeze({ get bugfixes () { return bugfixes; }, get applyAnimatedValues () { return applyAnimatedValues; }, get colorNames () { return colorNames; }, get requestFrame () { return requestFrame; }, get cancelFrame () { return cancelFrame; }, get interpolation () { return interpolation; }, injectApplyAnimatedValues: injectApplyAnimatedValues, injectColorNames: injectColorNames, injectBugfixes: injectBugfixes, injectInterpolation: injectInterpolation, injectFrame: injectFrame }); // Important note: start() and stop() will only be called at most once. // Once an animation has been stopped or finished its course, it will // not be reused. var Animation = /*#__PURE__*/ function () { function Animation() {} var _proto = Animation.prototype; _proto.start = function start(fromValue, onUpdate, onEnd, previousAnimation) {}; _proto.stop = function stop() {}; // Helper function for subclasses to make sure onEnd is only called once. _proto.__debouncedOnEnd = function __debouncedOnEnd(result) { var onEnd = this.__onEnd; this.__onEnd = null; onEnd && onEnd(result); }; return Animation; }(); var Animated = /*#__PURE__*/ function () { function Animated() {} var _proto = Animated.prototype; _proto.__attach = function __attach() {}; _proto.__detach = function __detach() {}; _proto.__getValue = function __getValue() {}; _proto.__getAnimatedValue = function __getAnimatedValue() { return this.__getValue(); }; _proto.__addChild = function __addChild(child) {}; _proto.__removeChild = function __removeChild(child) {}; _proto.__getChildren = function __getChildren() { return []; }; return Animated; }(); var AnimatedTracking = /*#__PURE__*/ function (_Animated) { _inheritsLoose(AnimatedTracking, _Animated); function AnimatedTracking(value, parent, animationClass, animationConfig, callback) { var _this; _this = _Animated.call(this) || this; _this.update = throttle(function () { _this._value.animate(new _this._animationClass(_extends({}, _this._animationConfig, { to: _this._animationConfig.to.__getValue() })), _this._callback); }, 1000 / 30); _this._value = value; _this._parent = parent; _this._animationClass = animationClass; _this._animationConfig = animationConfig; _this._callback = callback; _this.__attach(); return _this; } var _proto = AnimatedTracking.prototype; _proto.__getValue = function __getValue() { return this._parent.__getValue(); }; _proto.__attach = function __attach() { this._parent.__addChild(this); }; _proto.__detach = function __detach() { this._parent.__removeChild(this); }; return AnimatedTracking; }(Animated); function throttle(callback, limit) { var wait = false; return function () { if (!wait) { callback.call(); wait = true; setTimeout(function () { return wait = false; }, limit); } }; } var AnimatedWithChildren = /*#__PURE__*/ function (_Animated) { _inheritsLoose(AnimatedWithChildren, _Animated); function AnimatedWithChildren() { var _this; _this = _Animated.call(this) || this; _this._children = []; return _this; } var _proto = AnimatedWithChildren.prototype; _proto.__addChild = function __addChild(child) { if (this._children.length === 0) this.__attach(); this._children.push(child); }; _proto.__removeChild = function __removeChild(child) { var index = this._children.indexOf(child); if (index === -1) { console.warn("Trying to remove a child that doesn't exist"); return; } this._children.splice(index, 1); if (this._children.length === 0) this.__detach(); }; _proto.__getChildren = function __getChildren() { return this._children; }; return AnimatedWithChildren; }(Animated); var linear = function linear(t) { return t; }; var Interpolation = /*#__PURE__*/ function () { function Interpolation() {} Interpolation.create = function create(config) { if (typeof config === 'function') return config; if (interpolation && config.output && typeof config.output[0] === 'string') return interpolation(config); var outputRange = config.output; var inputRange = config.range; var easing = config.easing || linear; var extrapolateLeft = 'extend'; var map = config.map; if (config.extrapolateLeft !== undefined) { extrapolateLeft = config.extrapolateLeft; } else if (config.extrapolate !== undefined) { extrapolateLeft = config.extrapolate; } var extrapolateRight = 'extend'; if (config.extrapolateRight !== undefined) { extrapolateRight = config.extrapolateRight; } else if (config.extrapolate !== undefined) { extrapolateRight = config.extrapolate; } return function (input) { var range = findRange(input, inputRange); return interpolate(input, inputRange[range], inputRange[range + 1], outputRange[range], outputRange[range + 1], easing, extrapolateLeft, extrapolateRight, map); }; }; return Interpolation; }(); function interpolate(input, inputMin, inputMax, outputMin, outputMax, easing, extrapolateLeft, extrapolateRight, map) { var result = map ? map(input) : input; // Extrapolate if (result < inputMin) { if (extrapolateLeft === 'identity') { return result; } else if (extrapolateLeft === 'clamp') { result = inputMin; } } if (result > inputMax) { if (extrapolateRight === 'identity') { return result; } else if (extrapolateRight === 'clamp') { result = inputMax; } } if (outputMin === outputMax) return outputMin; if (inputMin === inputMax) { if (input <= inputMin) return outputMin; return outputMax; } // Input Range if (inputMin === -Infinity) { result = -result; } else if (inputMax === Infinity) { result = result - inputMin; } else { result = (result - inputMin) / (inputMax - inputMin); } // Easing result = easing(result); // Output Range if (outputMin === -Infinity) { result = -result; } else if (outputMax === Infinity) { result = result + outputMin; } else { result = result * (outputMax - outputMin) + outputMin; } return result; } function findRange(input, inputRange) { for (var i = 1; i < inputRange.length - 1; ++i) { if (inputRange[i] >= input) break; } return i - 1; } var AnimatedInterpolation = /*#__PURE__*/ function (_AnimatedWithChildren) { _inheritsLoose(AnimatedInterpolation, _AnimatedWithChildren); function AnimatedInterpolation(parents, config) { var _this; _this = _AnimatedWithChildren.call(this) || this; _this._parents = Array.isArray(parents) ? parents : [parents]; _this._interpolation = Interpolation.create(config); return _this; } var _proto = AnimatedInterpolation.prototype; _proto.__getValue = function __getValue() { return this._interpolation.apply(this, this._parents.map(function (value) { return value.__getValue(); })); }; _proto.__attach = function __attach() { for (var i = 0; i < this._parents.length; ++i) { if (this._parents[i] instanceof Animated) this._parents[i].__addChild(this); } }; _proto.__detach = function __detach() { for (var i = 0; i < this._parents.length; ++i) { if (this._parents[i] instanceof Animated) this._parents[i].__removeChild(this); } }; _proto.__update = function __update(config) { this._interpolation = Interpolation.create(config); return this; }; _proto.interpolate = function interpolate(config) { return new AnimatedInterpolation(this, config); }; return AnimatedInterpolation; }(AnimatedWithChildren); var _uniqueId = 0; /** * Animated works by building a directed acyclic graph of dependencies * transparently when you render your Animated components. * * new Animated.Value(0) * .interpolate() .interpolate() new Animated.Value(1) * opacity translateY scale * style transform * View#234 style * View#123 * * A) Top Down phase * When an Animated.Value is updated, we recursively go down through this * graph in order to find leaf nodes: the views that we flag as needing * an update. * * B) Bottom Up phase * When a view is flagged as needing an update, we recursively go back up * in order to build the new value that it needs. The reason why we need * this two-phases process is to deal with composite props such as * transform which can receive values from multiple parents. */ function findAnimatedStyles(node, styles) { if (typeof node.update === 'function') styles.add(node);else node.__getChildren().forEach(function (child) { return findAnimatedStyles(child, styles); }); } /** * Standard value for driving animations. One `Animated.Value` can drive * multiple properties in a synchronized fashion, but can only be driven by one * mechanism at a time. Using a new mechanism (e.g. starting a new animation, * or calling `setValue`) will stop any previous ones. */ var AnimatedValue = /*#__PURE__*/ function (_AnimatedWithChildren) { _inheritsLoose(AnimatedValue, _AnimatedWithChildren); function AnimatedValue(value) { var _this; _this = _AnimatedWithChildren.call(this) || this; _this._value = value; _this._animation = null; _this._animatedStyles = new Set(); _this._listeners = {}; return _this; } var _proto = AnimatedValue.prototype; _proto.__detach = function __detach() { this.stopAnimation(); }; _proto.__getValue = function __getValue() { return this._value; }; _proto._update = function _update() { findAnimatedStyles(this, this._animatedStyles); }; _proto._flush = function _flush() { if (this._animatedStyles.size === 0) this._update(); this._animatedStyles.forEach(function (animatedStyle) { return animatedStyle.update(); }); }; _proto._updateValue = function _updateValue(value) { this._value = value; this._flush(); for (var key in this._listeners) { this._listeners[key]({ value: this.__getValue() }); } }; /** * Directly set the value. This will stop any animations running on the value * and update all the bound properties. */ _proto.setValue = function setValue(value) { if (this._animation) { this._animation.stop(); this._animation = null; } this._animatedStyles.clear(); this._updateValue(value); }; /** * Stops any running animation or tracking. `callback` is invoked with the * final value after stopping the animation, which is useful for updating * state to match the animation position with layout. */ _proto.stopAnimation = function stopAnimation(callback) { this.stopTracking(); this._animation && this._animation.stop(); this._animation = null; callback && callback(this.__getValue()); }; /** * Interpolates the value before updating the property, e.g. mapping 0-1 to * 0-10. */ _proto.interpolate = function interpolate(config) { return new AnimatedInterpolation(this, config); }; /** * Typically only used internally, but could be used by a custom Animation * class. */ _proto.animate = function animate(animation, callback) { var _this2 = this; var previousAnimation = this._animation; this._animation && this._animation.stop(); this._animation = animation; this._animatedStyles.clear(); animation.start(this._value, function (value) { return _this2._updateValue(value); }, function (result) { _this2._animation = null; callback && callback(result); }, previousAnimation); }; /** * Adds an asynchronous listener to the value so you can observe updates from * animations. This is useful because there is no way to * synchronously read the value because it might be driven natively. */ _proto.addListener = function addListener(callback) { var id = String(_uniqueId++); this._listeners[id] = callback; return id; }; _proto.removeListener = function removeListener(id) { delete this._listeners[id]; }; _proto.removeAllListeners = function removeAllListeners() { this._listeners = {}; }; /** * Typically only used internally. */ _proto.stopTracking = function stopTracking() { this._tracking && this._tracking.__detach(); this._tracking = null; }; /** * Typically only used internally. */ _proto.track = function track(tracking) { this.stopTracking(); this._tracking = tracking; }; return AnimatedValue; }(AnimatedWithChildren); var withDefault = function withDefault(value, defaultValue) { return value === undefined || value === null ? defaultValue : value; }; var tensionFromOrigamiValue = function tensionFromOrigamiValue(oValue) { return (oValue - 30) * 3.62 + 194; }; var frictionFromOrigamiValue = function frictionFromOrigamiValue(oValue) { return (oValue - 8) * 3 + 25; }; var fromOrigamiTensionAndFriction = function fromOrigamiTensionAndFriction(tension, friction) { return { tension: tensionFromOrigamiValue(tension), friction: frictionFromOrigamiValue(friction) }; }; var SpringAnimation = /*#__PURE__*/ function (_Animation) { _inheritsLoose(SpringAnimation, _Animation); function SpringAnimation(config) { var _this; _this = _Animation.call(this) || this; _this.onUpdate = function () { var position = _this._lastPosition; var velocity = _this._lastVelocity; var tempPosition = _this._lastPosition; var tempVelocity = _this._lastVelocity; // If for some reason we lost a lot of frames (e.g. process large payload or // stopped in the debugger), we only advance by 4 frames worth of // computation and will continue on the next frame. It's better to have it // running at faster speed than jumping to the end. var MAX_STEPS = 64; var now = Date.now(); if (now > _this._lastTime + MAX_STEPS) now = _this._lastTime + MAX_STEPS; // We are using a fixed time step and a maximum number of iterations. // The following post provides a lot of thoughts into how to build this // loop: http://gafferongames.com/game-physics/fix-your-timestep/ var TIMESTEP_MSEC = 1; var numSteps = Math.floor((now - _this._lastTime) / TIMESTEP_MSEC); for (var i = 0; i < numSteps; ++i) { // Velocity is based on seconds instead of milliseconds var step = TIMESTEP_MSEC / 1000; // This is using RK4. A good blog post to understand how it works: // http://gafferongames.com/game-physics/integration-basics/ var aVelocity = velocity; var aAcceleration = _this._tension * (_this._to - tempPosition) - _this._friction * tempVelocity; var tempPosition = position + aVelocity * step / 2; var tempVelocity = velocity + aAcceleration * step / 2; var bVelocity = tempVelocity; var bAcceleration = _this._tension * (_this._to - tempPosition) - _this._friction * tempVelocity; tempPosition = position + bVelocity * step / 2; tempVelocity = velocity + bAcceleration * step / 2; var cVelocity = tempVelocity; var cAcceleration = _this._tension * (_this._to - tempPosition) - _this._friction * tempVelocity; tempPosition = position + cVelocity * step / 2; tempVelocity = velocity + cAcceleration * step / 2; var dVelocity = tempVelocity; var dAcceleration = _this._tension * (_this._to - tempPosition) - _this._friction * tempVelocity; tempPosition = position + cVelocity * step / 2; tempVelocity = velocity + cAcceleration * step / 2; var dxdt = (aVelocity + 2 * (bVelocity + cVelocity) + dVelocity) / 6; var dvdt = (aAcceleration + 2 * (bAcceleration + cAcceleration) + dAcceleration) / 6; position += dxdt * step; velocity += dvdt * step; } _this._lastTime = now; _this._lastPosition = position; _this._lastVelocity = velocity; _this._onUpdate(position); // a listener might have stopped us in _onUpdate if (!_this.__active) return; // Conditions for stopping the spring animation var isOvershooting = false; if (_this._overshootClamping && _this._tension !== 0) { if (_this._startPosition < _this._to) { isOvershooting = position > _this._to; } else { isOvershooting = position < _this._to; } } var isVelocity = Math.abs(velocity) <= _this._restSpeedThreshold; var isDisplacement = true; if (_this._tension !== 0) isDisplacement = Math.abs(_this._to - position) <= _this._restDisplacementThreshold; if (isOvershooting || isVelocity && isDisplacement) { // Ensure that we end up with a round value if (_this._tension !== 0) _this._onUpdate(_this._to); return _this.__debouncedOnEnd({ finished: true }); } _this._animationFrame = requestFrame(_this.onUpdate); }; _this._overshootClamping = withDefault(config.overshootClamping, false); _this._restDisplacementThreshold = withDefault(config.restDisplacementThreshold, 0.0001); _this._restSpeedThreshold = withDefault(config.restSpeedThreshold, 0.0001); _this._initialVelocity = config.velocity; _this._lastVelocity = withDefault(config.velocity, 0); _this._to = config.to; var springConfig = fromOrigamiTensionAndFriction(withDefault(config.tension, 40), withDefault(config.friction, 7)); _this._tension = springConfig.tension; _this._friction = springConfig.friction; return _this; } var _proto = SpringAnimation.prototype; _proto.start = function start(fromValue, onUpdate, onEnd, previousAnimation) { this.__active = true; this._startPosition = fromValue; this._lastPosition = this._startPosition; this._onUpdate = onUpdate; this.__onEnd = onEnd; this._lastTime = Date.now(); if (previousAnimation instanceof SpringAnimation) { var internalState = previousAnimation.getInternalState(); this._lastPosition = internalState.lastPosition; this._lastVelocity = internalState.lastVelocity; this._lastTime = internalState.lastTime; } if (typeof fromValue === 'string') { this._onUpdate(fromValue); return this.__debouncedOnEnd({ finished: true }); } if (this._initialVelocity !== undefined && this._initialVelocity !== null) this._lastVelocity = this._initialVelocity; this.onUpdate(); }; _proto.getInternalState = function getInternalState() { return { lastPosition: this._lastPosition, lastVelocity: this._lastVelocity, lastTime: this._lastTime }; }; _proto.stop = function stop() { this.__active = false; clearTimeout(this._timeout); cancelFrame(this._animationFrame); this.__debouncedOnEnd({ finished: false }); }; return SpringAnimation; }(Animation); var AnimatedArray = /*#__PURE__*/ function (_AnimatedWithChildren) { _inheritsLoose(AnimatedArray, _AnimatedWithChildren); function AnimatedArray(array) { var _this; _this = _AnimatedWithChildren.call(this) || this; _this._values = array.map(function (n) { return new AnimatedValue(n); }); return _this; } var _proto = AnimatedArray.prototype; _proto.setValue = function setValue(values) { var _this2 = this; values.forEach(function (n, i) { return _this2._values[i].setValue(n); }); }; _proto.__getValue = function __getValue() { return this._values.map(function (v) { return v.__getValue(); }); }; _proto.stopAnimation = function stopAnimation(callback) { this._values.forEach(function (v) { return v.stopAnimation(); }); callback && callback(this.__getValue()); }; _proto.__attach = function __attach() { for (var i = 0; i < this._values.length; ++i) { if (this._values[i] instanceof Animated) this._values[i].__addChild(this); } }; _proto.__detach = function __detach() { for (var i = 0; i < this._values.length; ++i) { if (this._values[i] instanceof Animated) this._values[i].__removeChild(this); } }; return AnimatedArray; }(AnimatedWithChildren); function maybeVectorAnim(array, _ref, anim, impl) { var tension = _ref.tension, friction = _ref.friction, to = _ref.to; // { tension, friction, to: [...]} if (array instanceof AnimatedArray) return parallel(array._values.map(function (v, i) { return anim(v, { tension: tension, friction: friction, to: to[i] }, impl); }), { stopTogether: false }); return null; } function parallel(animations, config) { var doneCount = 0; var hasEnded = {}; var stopTogether = !(config && config.stopTogether === false); var result = { start: function start(callback) { if (doneCount === animations.length) return callback && callback({ finished: true }); animations.forEach(function (animation, idx) { var cb = function cb(endResult) { hasEnded[idx] = true; doneCount++; if (doneCount === animations.length) { doneCount = 0; return callback && callback(endResult); } if (!endResult.finished && stopTogether) result.stop(); }; if (!animation) cb({ finished: true });else animation.start(cb); }); }, stop: function stop() { animations.forEach(function (animation, idx) { !hasEnded[idx] && animation.stop(); hasEnded[idx] = true; }); } }; return result; } function controller(value, config, impl) { if (impl === void 0) { impl = SpringAnimation; } return maybeVectorAnim(value, config, controller, impl) || { start: function start(callback) { var singleValue = value; var singleConfig = config; singleValue.stopTracking(); if (config.to instanceof Animated) singleValue.track(new AnimatedTracking(singleValue, config.to, impl, singleConfig, callback));else singleValue.animate(new impl(singleConfig), callback); }, stop: function stop() { value.stopAnimation(); } }; } var AnimatedStyle = /*#__PURE__*/ function (_AnimatedWithChildren) { _inheritsLoose(AnimatedStyle, _AnimatedWithChildren); function AnimatedStyle(style) { var _this; _this = _AnimatedWithChildren.call(this) || this; style = style || {}; if (style.transform && !(style.transform instanceof Animated)) style = applyAnimatedValues.transform(style); _this._style = style; return _this; } var _proto = AnimatedStyle.prototype; _proto.__getValue = function __getValue() { var style = {}; for (var key in this._style) { var value = this._style[key]; style[key] = value instanceof Animated ? value.__getValue() : value; } return style; }; _proto.__getAnimatedValue = function __getAnimatedValue() { var style = {}; for (var key in this._style) { var value = this._style[key]; if (value instanceof Animated) style[key] = value.__getAnimatedValue(); } return style; }; _proto.__attach = function __attach() { for (var key in this._style) { var value = this._style[key]; if (value instanceof Animated) value.__addChild(this); } }; _proto.__detach = function __detach() { for (var key in this._style) { var value = this._style[key]; if (value instanceof Animated) value.__removeChild(this); } }; return AnimatedStyle; }(AnimatedWithChildren); var AnimatedProps = /*#__PURE__*/ function (_Animated) { _inheritsLoose(AnimatedProps, _Animated); function AnimatedProps(props, callback) { var _this; _this = _Animated.call(this) || this; if (props.style) { props = _extends({}, props, { style: new AnimatedStyle(props.style) }); } _this._props = props; _this._callback = callback; _this.__attach(); return _this; } var _proto = AnimatedProps.prototype; _proto.__getValue = function __getValue() { var props = {}; for (var key in this._props) { var value = this._props[key]; if (value instanceof Animated) props[key] = value.__getValue();else props[key] = value; } return props; }; _proto.__getAnimatedValue = function __getAnimatedValue() { var props = {}; for (var key in this._props) { var value = this._props[key]; if (value instanceof Animated) props[key] = value.__getAnimatedValue(); } return props; }; _proto.__attach = function __attach() { for (var key in this._props) { var value = this._props[key]; if (value instanceof Animated) value.__addChild(this); } }; _proto.__detach = function __detach() { for (var key in this._props) { var value = this._props[key]; if (value instanceof Animated) value.__removeChild(this); } }; _proto.update = function update() { this._callback(); }; return AnimatedProps; }(Animated); function createAnimatedComponent(Component) { return ( /*#__PURE__*/ function (_React$Component) { _inheritsLoose(AnimatedComponent, _React$Component); function AnimatedComponent() { return _React$Component.apply(this, arguments) || this; } var _proto = AnimatedComponent.prototype; _proto.componentWillUnmount = function componentWillUnmount() { this._propsAnimated && this._propsAnimated.__detach(); }; _proto.setNativeProps = function setNativeProps(props) { var didUpdate = applyAnimatedValues.fn(this.node, props, this); if (didUpdate === false) this.forceUpdate(); }; _proto.componentWillMount = function componentWillMount() { this.attachProps(this.props); }; _proto.attachProps = function attachProps(nextProps) { var _this = this; var oldPropsAnimated = this._propsAnimated; // The system is best designed when setNativeProps is implemented. It is // able to avoid re-rendering and directly set the attributes that // changed. However, setNativeProps can only be implemented on leaf // native components. If you want to animate a composite component, you // need to re-render it. In this case, we have a fallback that uses // forceUpdate. var callback = function callback() { if (_this.node) { var didUpdate = applyAnimatedValues.fn(_this.node, _this._propsAnimated.__getAnimatedValue(), _this); if (didUpdate === false) _this.forceUpdate(); } }; this._propsAnimated = new AnimatedProps(nextProps, callback); // When you call detach, it removes the element from the parent list // of children. If it goes to 0, then the parent also detaches itself // and so on. // An optimization is to attach the new elements and THEN detach the old // ones instead of detaching and THEN attaching. // This way the intermediate state isn't to go to 0 and trigger // this expensive recursive detaching to then re-attach everything on // the very next operation. oldPropsAnimated && oldPropsAnimated.__detach(); }; _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { this.attachProps(nextProps); }; _proto.render = function render() { var _this2 = this; var props = this._propsAnimated.__getValue(); return React.createElement(Component, _extends({}, props, { ref: function ref(node) { return _this2.node = node; } })); }; return AnimatedComponent; }(React.Component) ); } var config = { default: { tension: 170, friction: 26 }, gentle: { tension: 120, friction: 14 }, wobbly: { tension: 180, friction: 12 }, stiff: { tension: 210, friction: 20 }, slow: { tension: 280, friction: 60 } }; function shallowEqual(a, b) { for (var i in a) { if (!(i in b)) return false; } for (var _i in b) { if (a[_i] !== b[_i]) return false; } return true; } function callProp(arg, state) { return typeof arg === 'function' ? arg(state) : arg; } function getValues(object) { return Object.keys(object).map(function (k) { return object[k]; }); } function getForwardProps(props) { var to = props.to, from = props.from, config = props.config, native = props.native, onRest = props.onRest, onFrame = props.onFrame, children = props.children, render = props.render, reset = props.reset, force = props.force, immediate = props.immediate, impl = props.impl, inject = props.inject, delay = props.delay, attach = props.attach, forward = _objectWithoutProperties(props, ["to", "from", "config", "native", "onRest", "onFrame", "children", "render", "reset", "force", "immediate", "impl", "inject", "delay", "attach"]); return forward; } function renderChildren(props, componentProps) { var forward = _extends({}, componentProps, getForwardProps(props)); return props.render ? props.render(_extends({}, forward, { children: props.children })) : props.children(forward); } function convertToAnimatedValue(acc, _ref) { var _extends2; var name = _ref[0], value = _ref[1]; return _extends({}, acc, (_extends2 = {}, _extends2[name] = new AnimatedValue(value), _extends2)); } function convertValues(props) { var from = props.from, to = props.to, native = props.native; var allProps = Object.entries(_extends({}, from, to)); return native ? allProps.reduce(convertToAnimatedValue, {}) : _extends({}, from, to); } var Spring = /*#__PURE__*/ function (_React$Component) { _inheritsLoose(Spring, _React$Component); function Spring() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this; _this.state = { lastProps: { from: {}, to: {} }, changed: false, dry: false }; _this.didUpdate = false; _this.didInject = false; _this.animations = {}; _this.interpolators = {}; _this.start = function () { var _this$props = _this.props, config$$1 = _this$props.config, impl = _this$props.impl; if (_this.props.onStart) _this.props.onStart(); Object.keys(_this.animations).forEach(function (name) { var _this$animations$name = _this.animations[name], animation = _this$animations$name.animation, to = _this$animations$name.toValue; // TODO: figure out why this is needed ... if (!to.__getValue && animation.__getValue() === to) return _this.finishAnimation(name); controller(animation, _extends({ to: to }, callProp(config$$1, name)), impl).start(!to.__getValue && function (props) { return props.finished && _this.finishAnimation(name); }); }); }; _this.stop = function () { return getValues(_this.animations).forEach(function (_ref) { var animation = _ref.animation; return animation.stopAnimation(); }); }; _this.finishAnimation = function (name) { if (!_this.mounted) return; var _this$animations$name2 = _this.animations[name], animation = _this$animations$name2.animation, to = _this$animations$name2.toValue; _this.animations[name].stopped = true; if (getValues(_this.animations).every(function (a) { return a.stopped; })) { var current = _extends({}, _this.props.from, _this.props.to); if (_this.props.onRest) _this.props.onRest(current); // Restore end-state if (_this.didInject) { _this.afterInject = convertValues(_this.props); _this.didInject = false; _this.setState({ dry: true }); } } }; return _this; } var _proto = Spring.prototype; _proto.componentDidMount = function componentDidMount() { // componentDidUpdate isn't called on mount, we call it here to start animating this.componentDidUpdate(); this.mounted = true; }; _proto.componentWillUnmount = function componentWillUnmount() { // Stop all ongoing animtions this.mounted = false; this.stop(); }; Spring.getDerivedStateFromProps = function getDerivedStateFromProps(props, _ref2) { var changed = _ref2.changed, dry = _ref2.dry, lastProps = _ref2.lastProps; // The following is a test against props that could alter the animation var from = props.from, to = props.to, reset = props.reset, force = props.force; changed = !shallowEqual(to, lastProps.to) || !shallowEqual(from, lastProps.from) || reset || force && !dry; return { changed: changed, lastProps: props, dry: false }; }; _proto.render = function render() { var _this2 = this; var propsChanged = this.state.changed; // Handle injected frames, for instance targets/web/fix-auto // An inject will return an intermediary React node which measures itself out // .. and returns a callback when the values sought after are ready, usually "auto". if (this.props.inject && propsChanged && !this.injectProps) { var frame = this.props.inject(this.props, function (injectProps) { // The inject frame has rendered, now let's update animations... _this2.injectProps = injectProps; _this2.setState({ dry: true }); }); // Render out injected frame if (frame) return frame; } // Update animations, this turns from/to props into AnimatedValues // An update can occur on injected props, or when own-props have changed. if (this.injectProps) { this.updateAnimations(this.injectProps); this.injectProps = undefined; // didInject is needed, because there will be a 3rd stage, where the original values // .. will be restored after the animation is finished. When someone animates towards // .. "auto", the end-result should be "auto", not "1999px", which would block nested // .. height/width changes. this.didInject = true; } else if (propsChanged) this.updateAnimations(this.props); // Render out raw values or AnimatedValues depending on "native" var values = this.getAnimatedValues(); return values && Object.keys(values).length ? renderChildren(this.props, _extends({}, values, this.afterInject)) : null; }; _proto.componentDidUpdate = function componentDidUpdate() { // The animation has to start *after* render, since at that point the scene // .. graph should be established, so we do it here. Unfortunatelly, non-native // .. animations as well as "auto" injects call forceUpdate, so it's causing a loop. // .. didUpdate prevents that as it gets set only on prop changes. if (this.didUpdate) { if (this.props.delay) { if (this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(this.start, this.props.delay); } else this.start(); } this.didUpdate = false; }; _proto.updateAnimations = function updateAnimations(_ref3) { var _this3 = this; var from = _ref3.from, to = _ref3.to, attach = _ref3.attach, reset = _ref3.reset, immediate = _ref3.immediate, onFrame = _ref3.onFrame, native = _ref3.native; // This function will turn own-props into AnimatedValues, it tries to re-use // .. exsting animations as best as it can by detecting the changes made // Attachment handling, trailed springs can "attach" themselves to a previous spring var target = attach && attach(this); var animationsChanged = false; var allProps = Object.entries(_extends({}, from, to)); this.animations = allProps.reduce(function (acc, _ref4, i) { var _extends2, _extends3; var name = _ref4[0], value = _ref4[1]; var entry = reset === false && acc[name] || { stopped: true }; var isNumber = typeof value === 'number'; var isString = typeof value === 'string' && !value.startsWith('#') && !/\d/.test(value) && !colorNames[value]; var isArray = !isNumber && !isString && Array.isArray(value); var fromValue = from[name] !== undefined ? from[name] : value; var fromAnimated = fromValue instanceof AnimatedValue; var toValue = isNumber || isArray ? value : 1; if (target) { // Attach value to target animation var attachedAnimation = target.animations[name]; if (attachedAnimation) toValue = attachedAnimation.animation; } var old = entry.animation; var animation, interpolation$$1; if (fromAnimated) { // Use provided animated value animation = interpolation$$1 = fromValue; } else if (isNumber || isString) { // Create animated value animation = interpolation$$1 = entry.animation || new AnimatedValue(fromValue); } else if (isArray) { // Create animated array animation = interpolation$$1 = entry.animation || new AnimatedArray(fromValue); } else { // Deal with interpolations var previous = entry.interpolation && entry.interpolation._interpolation(entry.animation._value); if (entry.animation) { animation = entry.animation; animation.setValue(0); } else animation = new AnimatedValue(0); var _config = { range: [0, 1], output: [previous !== undefined ? previous : fromValue, value] }; if (entry.interpolation) interpolation$$1 = entry.interpolation.__update(_config);else interpolation$$1 = animation.interpolate(_config); } if (old !== animation) animationsChanged = true; // Set immediate values if (callProp(immediate, name)) animation.setValue(toValue); // Save interpolators _this3.interpolators = _extends({}, _this3.interpolators, (_extends2 = {}, _extends2[name] = interpolation$$1, _extends2)); return _extends({}, acc, (_extends3 = {}, _extends3[name] = _extends({}, entry, { name: name, animation: animation, interpolation: interpolation$$1, toValue: toValue, stopped: false }), _extends3)); }, this.animations); // Update animated props (which from now on will take care of the animation) if (animationsChanged) { var oldAnimatedProps = this.animatedProps; this.animatedProps = new AnimatedProps(this.interpolators, function () { // This gets called on every animation frame ... if (onFrame) onFrame(_this3.animatedProps.__getValue()); if (!native) _this3.setState({ dry: true }); }); oldAnimatedProps && oldAnimatedProps.__detach(); } // Flag an update that occured, componentDidUpdate will start the animation later on this.didUpdate = true; this.afterInject = undefined; this.didInject = false; }; _proto.flush = function flush() { getValues(this.animations).forEach(function (_ref5) { var animation = _ref5.animation; return animation._update && animation._update(); }); }; _proto.getValues = function getValues$$1() { return this.animatedProps ? this.animatedProps.__getValue() : {}; }; _proto.getAnimatedValues = function getAnimatedValues() { return this.props.native ? this.interpolators : this.getValues(); }; return Spring; }(React.Component); Spring.defaultProps = { from: {}, to: {}, config: config.default, native: false, immediate: false, reset: false, force: false, impl: SpringAnimation, inject: bugfixes }; var empty = function empty() { return null; }; var ref = function ref(object, key, defaultValue) { return typeof object === 'function' ? object(key) : object || defaultValue; }; var get = function get(props) { var keys = props.keys, children = props.children, render = props.render, items = props.items, rest = _objectWithoutProperties(props, ["keys", "children", "render", "items"]); children = render || children || empty; keys = typeof keys === 'function' ? items.map(keys) : keys; if (!Array.isArray(children)) { children = [children]; keys = keys !== void 0 ? [keys] : children.map(function (c) { return c.toString(); }); } // Make sure numeric keys are interpreted as Strings (5 !== "5") keys = keys.map(function (k) { return String(k); }); return _extends({ keys: keys, children: children, items: items }, rest); }; var guid = 0; var Transition = /*#__PURE__*/ function (_React$PureComponent) { _inheritsLoose(Transition, _React$PureComponent); function Transition(prevProps) { var _this; _this = _React$PureComponent.call(this, prevProps) || this; _this.springs = []; _this.state = { transitions: [], current: {}, deleted: [], prevProps: prevProps }; return _this; } Transition.getDerivedStateFromProps = function getDerivedStateFromProps(props, _ref) { var prevProps = _ref.prevProps, state = _objectWithoutProperties(_ref, ["prevProps"]); var _get = get(props), keys = _get.keys, children = _get.children, items = _get.items, from = _get.from, enter = _get.enter, leave = _get.leave, update = _get.update; var _get2 = get(prevProps), _keys = _get2.keys, _items = _get2.items; var current = _extends({}, state.current); var deleted = state.deleted.concat(); // Compare next keys with current keys var currentKeys = Object.keys(current); var currentSet = new Set(currentKeys); var nextSet = new Set(keys); var added = keys.filter(function (item) { return !currentSet.has(item); }); var removed = currentKeys.filter(function (item) { return !nextSet.has(item); }); var updated = keys.filter(function (item) { return currentSet.has(item); }); added.forEach(function (key) { var keyIndex = keys.indexOf(key); var item = items ? items[keyIndex] : key; current[key] = { children: children[keyIndex], key: guid++, item: item, to: ref(enter, item), from: ref(from, item) }; }); removed.forEach(function (key) { var keyIndex = _keys.indexOf(key); deleted.push(_extends({ destroyed: true, lastIndex: keyIndex }, current[key], { to: ref(leave, _items ? _items[keyIndex] : key) })); delete current[key]; }); updated.forEach(function (key) { var keyIndex = keys.indexOf(key); var item = items ? items[keyIndex] : key; current[key] = _extends({}, current[key], { children: children[keyIndex], to: ref(update, item, current[key].to) }); }); var transitions = keys.map(function (key) { return current[key]; }); deleted.forEach(function (_ref2) { var i = _ref2.lastIndex, t = _objectWithoutProperties(_ref2, ["lastIndex"]); return transitions = transitions.slice(0, i).concat([t], transitions.slice(i)); }); return { transitions: transitions, current: current, deleted: deleted, prevProps: props }; }; var _proto = Transition.prototype; _proto.getValues = function getValues() { return undefined; }; _proto.render = function render() { var _this2 = this; var _this$props = this.props, render = _this$props.render, _this$props$from = _this$props.from, _this$props$enter = _this$props.enter, _this$props$leave = _this$props.leave, _this$props$native = _this$props.native, native = _this$props$native === void 0 ? false : _this$props$native, keys = _this$props.keys, items = _this$props.items, onFrame = _this$props.onFrame, onRest = _this$props.onRest, extra = _objectWithoutProperties(_this$props, ["render", "from", "enter", "leave", "native", "keys", "items", "onFrame", "onRest"]); var props = _extends({ native: native }, extra); return this.state.transitions.map(function (transition, i) { var key = transition.key, item = transition.item, children = transition.children, from = transition.from, rest = _objectWithoutProperties(transition, ["key", "item", "children", "from"]); return React.createElement(Spring, _extends({ ref: function ref(r) { return r && (_this2.springs[key] = r.getValues()); }, key: key, onRest: rest.destroyed ? function () { return _this2.setState(function (_ref3) { var deleted = _ref3.deleted; return { deleted: deleted.filter(function (t) { return t.key !== key; }) }; }, function () { return delete _this2.springs[key]; }); } : onRest && function (values) { return onRest(item, values); }, onFrame: onFrame && function (values) { return onFrame(item, values); } }, rest, props, { from: rest.destroyed ? _this2.springs[key] || from : from, render: render && children, children: render ? _this2.props.children : children })); }); }; return Transition; }(React.PureComponent); var Trail = /*#__PURE__*/ function (_React$PureComponent) { _inheritsLoose(Trail, _React$PureComponent); function Trail() { return _React$PureComponent.apply(this, arguments) || this; } var _proto = Trail.prototype; _proto.getValues = function getValues() { return this.instance && this.instance.getValues(); }; _proto.componentDidMount = function componentDidMount() { this.instance && this.instance.flush(); }; _proto.componentDidUpdate = function componentDidUpdate() { this.instance && this.instance.flush(); }; _proto.render = function render() { var _this = this; var _this$props = this.props, children = _this$props.children, render = _this$props.render, _this$props$from = _this$props.from, from = _this$props$from === void 0 ? {} : _this$props$from, _this$props$to = _this$props.to, to = _this$props$to === void 0 ? {} : _this$props$to, _this$props$native = _this$props.native, native = _this$props$native === void 0 ? false : _this$props$native, keys = _this$props.keys, delay = _this$props.delay, onRest = _this$props.onRest, extra = _objectWithoutProperties(_this$props, ["children", "render", "from", "to", "native", "keys", "delay", "onRest"]); var animations = new Set(); var hook = function hook(index, animation) { animations.add(animation); if (index === 0) return undefined;else return Array.from(animations)[index - 1]; }; var props = _extends({}, extra, { native: native, from: from, to: to }); var target = render || children; return target.map(function (child, i) { var attachedHook = function attachedHook(animation) { return hook(i, animation); }; var firstDelay = i === 0 && delay; return React.createElement(Spring, _extends({ ref: function ref(_ref) { return i === 0 && (_this.instance = _ref); }, onRest: i === 0 ? onRest : null, key: keys[i] }, props, { delay: firstDelay || undefined, attach: attachedHook, render: render && child, children: render ? children : child })); }); }; return Trail; }(React.PureComponent); var DEFAULT = '__default'; var Keyframes = /*#__PURE__*/ function (_React$PureComponent) { _inheritsLoose(Keyframes, _React$PureComponent); function Keyframes