diff --git a/jest/Animated/AnimatedImplementation.js b/jest/Animated/AnimatedImplementation.js deleted file mode 100755 index 9d7b3b4e5cfa41..00000000000000 --- a/jest/Animated/AnimatedImplementation.js +++ /dev/null @@ -1,1191 +0,0 @@ -import invariant from 'invariant'; -import Interpolation from './Interpolation'; -import Easing from './Easing'; -import InteractionManager from '../InteractionManager'; -import SpringConfig from './SpringConfig'; -import requestAnimationFrame from 'raf'; - -function flattenStyle(style) { - if (!style) { - return undefined; - } - if (!Array.isArray(style)) { - return style; - } - return Object.assign({}, ...style); -} - -class Animated { - __attach() {} - __detach() {} - __getValue() {} - __getAnimatedValue() { return this.__getValue(); } - __addChild(child) {} - __removeChild(child) {} - __getChildren() { return []; } -} - -class Animation { - start(fromValue, onUpdate, onEnd, previousAnimation) {} - stop() {} - __debouncedOnEnd(result) { - const onEnd = this.__onEnd; - this.__onEnd = null; - if (onEnd) { - onEnd(result); - } - } -} - -class AnimatedWithChildren extends Animated { - constructor() { - super(); - this._children = []; - } - - __addChild(child) { - if (this._children.length === 0) { - this.__attach(); - } - this._children.push(child); - } - - __removeChild(child) { - const 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(); - } - } - - __getChildren() { - return this._children; - } -} - -/** - * Animated works by building a directed acyclic graph of dependencies - * transparently when you render your Animated components. - * - * new Animated.Value(0) - * .interpolate() .interpolate() new Animated.Value(1) - * opacity translateY scale - * style transform - * View#234 style - * View#123 - * - * A) Top Down phase - * When an Animated.Value is updated, we recursively go down through this - * graph in order to find leaf nodes: the views that we flag as needing - * an update. - * - * B) Bottom Up phase - * When a view is flagged as needing an update, we recursively go back up - * in order to build the new value that it needs. The reason why we need - * this two-phases process is to deal with composite props such as - * transform which can receive values from multiple parents. - */ -function _flush(rootNode) { - const animatedStyles = new Set(); - function findAnimatedStyles(node) { - if (typeof node.update === 'function') { - animatedStyles.add(node); - } else { - node.__getChildren().forEach(findAnimatedStyles); - } - } - findAnimatedStyles(rootNode); - animatedStyles.forEach(animatedStyle => animatedStyle.update()); -} - -const easeInOut = Easing.inOut(Easing.ease); - -class TimingAnimation extends Animation { - constructor(config) { - super(); - this._toValue = config.toValue; - this._easing = config.easing || easeInOut; - this._duration = config.duration !== undefined ? config.duration : 500; - this._delay = config.delay || 0; - this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; - } - - start(fromValue, onUpdate, onEnd) { - this.__active = true; - this._fromValue = fromValue; - this._onUpdate = onUpdate; - this.__onEnd = onEnd; - - const start = () => { - if (this._duration === 0) { - this._onUpdate(this._toValue); - this.__debouncedOnEnd({ finished: true }); - } else { - this._startTime = Date.now(); - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - }; - if (this._delay) { - this._timeout = setTimeout(start, this._delay); - } else { - start(); - } - } - - onUpdate() { - const now = Date.now(); - if (now >= this._startTime + this._duration) { - if (this._duration === 0) { - this._onUpdate(this._toValue); - } else { - this._onUpdate( - this._fromValue + this._easing(1) * (this._toValue - this._fromValue) - ); - } - this.__debouncedOnEnd({ finished: true }); - return; - } - - this._onUpdate( - this._fromValue + - this._easing((now - this._startTime) / this._duration) * - (this._toValue - this._fromValue) - ); - if (this.__active) { - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - } - - stop() { - this.__active = false; - clearTimeout(this._timeout); - if (global && global.cancelAnimationFrame) { - global.cancelAnimationFrame(this._animationFrame); - } - this.__debouncedOnEnd({ finished: false }); - } -} - -class DecayAnimation extends Animation { - constructor(config) { - super(); - this._deceleration = config.deceleration || 0.998; - this._velocity = config.velocity; - this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; - } - - start(fromValue, onUpdate, onEnd) { - this.__active = true; - this._lastValue = fromValue; - this._fromValue = fromValue; - this._onUpdate = onUpdate; - this.__onEnd = onEnd; - this._startTime = Date.now(); - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - - onUpdate() { - const now = Date.now(); - - const value = this._fromValue + - (this._velocity / (1 - this._deceleration)) * - (1 - Math.exp(-(1 - this._deceleration) * (now - this._startTime))); - - this._onUpdate(value); - - if (Math.abs(this._lastValue - value) < 0.1) { - this.__debouncedOnEnd({ finished: true }); - return; - } - - this._lastValue = value; - if (this.__active) { - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - } - - stop() { - this.__active = false; - if (global && global.cancelAnimationFrame) { - global.cancelAnimationFrame(this._animationFrame); - } - this.__debouncedOnEnd({ finished: false }); - } -} - -function withDefault(value, defaultValue) { - if (value === undefined || value === null) { - return defaultValue; - } - return value; -} - -class SpringAnimation extends Animation { - constructor(config) { - super(); - - this._overshootClamping = withDefault(config.overshootClamping, false); - this._restDisplacementThreshold = withDefault(config.restDisplacementThreshold, 0.001); - this._restSpeedThreshold = withDefault(config.restSpeedThreshold, 0.001); - this._initialVelocity = config.velocity; - this._lastVelocity = withDefault(config.velocity, 0); - this._toValue = config.toValue; - this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; - - let springConfig; - if (config.bounciness !== undefined || config.speed !== undefined) { - invariant( - config.tension === undefined && config.friction === undefined, - 'You can only define bounciness/speed or tension/friction but not both' - ); - springConfig = SpringConfig.fromBouncinessAndSpeed( - withDefault(config.bounciness, 8), - withDefault(config.speed, 12), - ); - } else { - springConfig = SpringConfig.fromOrigamiTensionAndFriction( - withDefault(config.tension, 40), - withDefault(config.friction, 7), - ); - } - this._tension = springConfig.tension; - this._friction = springConfig.friction; - } - - 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) { - const internalState = previousAnimation.getInternalState(); - this._lastPosition = internalState.lastPosition; - this._lastVelocity = internalState.lastVelocity; - this._lastTime = internalState.lastTime; - } - if (this._initialVelocity !== undefined && this._initialVelocity !== null) { - this._lastVelocity = this._initialVelocity; - } - this.onUpdate(); - } - - getInternalState() { - return { - lastPosition: this._lastPosition, - lastVelocity: this._lastVelocity, - lastTime: this._lastTime, - }; - } - - onUpdate() { - let position = this._lastPosition; - let velocity = this._lastVelocity; - - let tempPosition = this._lastPosition; - let 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. - const MAX_STEPS = 64; - let 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/ - const TIMESTEP_MSEC = 1; - const numSteps = Math.floor((now - this._lastTime) / TIMESTEP_MSEC); - - for (let i = 0; i < numSteps; ++i) { - // Velocity is based on seconds instead of milliseconds - const step = TIMESTEP_MSEC / 1000; - - // This is using RK4. A good blog post to understand how it works: - // http://gafferongames.com/game-physics/integration-basics/ - const aVelocity = velocity; - const aAcceleration = - this._tension * (this._toValue - tempPosition) - this._friction * tempVelocity; - tempPosition = position + aVelocity * step / 2; - tempVelocity = velocity + aAcceleration * step / 2; - - const bVelocity = tempVelocity; - const bAcceleration = - this._tension * (this._toValue - tempPosition) - this._friction * tempVelocity; - tempPosition = position + bVelocity * step / 2; - tempVelocity = velocity + bAcceleration * step / 2; - - const cVelocity = tempVelocity; - const cAcceleration = - this._tension * (this._toValue - tempPosition) - this._friction * tempVelocity; - tempPosition = position + cVelocity * step / 2; - tempVelocity = velocity + cAcceleration * step / 2; - - const dVelocity = tempVelocity; - const dAcceleration = - this._tension * (this._toValue - tempPosition) - this._friction * tempVelocity; - tempPosition = position + cVelocity * step / 2; - tempVelocity = velocity + cAcceleration * step / 2; - - const dxdt = (aVelocity + 2 * (bVelocity + cVelocity) + dVelocity) / 6; - const 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); - if (!this.__active) { // a listener might have stopped us in _onUpdate - return; - } - - // Conditions for stopping the spring animation - let isOvershooting = false; - if (this._overshootClamping && this._tension !== 0) { - if (this._startPosition < this._toValue) { - isOvershooting = position > this._toValue; - } else { - isOvershooting = position < this._toValue; - } - } - - const isVelocity = Math.abs(velocity) <= this._restSpeedThreshold; - let isDisplacement = true; - if (this._tension !== 0) { - isDisplacement = Math.abs(this._toValue - position) <= this._restDisplacementThreshold; - } - - if (isOvershooting || (isVelocity && isDisplacement)) { - if (this._tension !== 0) { - // Ensure that we end up with a round value - this._onUpdate(this._toValue); - } - - this.__debouncedOnEnd({ finished: true }); - return; - } - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - - stop() { - this.__active = false; - window.cancelAnimationFrame(this._animationFrame); - this.__debouncedOnEnd({ finished: false }); - } -} - -let _uniqueId = 1; - -class AnimatedInterpolation extends AnimatedWithChildren { - constructor(parent, interpolation) { - super(); - this._parent = parent; - this._interpolation = interpolation; - } - - __getValue() { - const parentValue = this._parent.__getValue(); - invariant( - typeof parentValue === 'number', - 'Cannot interpolate an input which is not a number.' - ); - return this._interpolation(parentValue); - } - - interpolate(config) { - return new AnimatedInterpolation(this, Interpolation.create(config)); - } - - __attach() { - this._parent.__addChild(this); - } - - __detach() { - this._parent.__removeChild(this); - } -} - - -class AnimatedValue extends AnimatedWithChildren { - constructor(value) { - super(); - this._value = value; - this._offset = 0; - this._animation = null; - this._listeners = {}; - } - - __detach() { - this.stopAnimation(); - } - - __getValue() { - return this._value + this._offset; - } - - /** - * Directly set the value. This will stop any animations running on the value - * and update all the bound properties. - */ - setValue(value) { - if (this._animation) { - this._animation.stop(); - this._animation = null; - } - this._updateValue(value); - } - - /** - * Sets an offset that is applied on top of whatever value is set, whether via - * `setValue`, an animation, or `Animated.event`. Useful for compensating - * things like the start of a pan gesture. - */ - setOffset(offset) { - this._offset = offset; - } - - /** - * Merges the offset value into the base value and resets the offset to zero. - * The final output of the value is unchanged. - */ - flattenOffset() { - this._value += this._offset; - this._offset = 0; - } - - /** - * 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. - */ - addListener(callback) { - const id = String(_uniqueId++); - this._listeners[id] = callback; - return id; - } - - removeListener(id) { - delete this._listeners[id]; - } - - removeAllListeners() { - this._listeners = {}; - } - - /** - * 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. - */ - stopAnimation(callback) { - this.stopTracking(); - if (this._animation) { - this._animation.stop(); - } - this._animation = null; - if (callback) { - callback(this.__getValue()); - } - } - - /** - * Interpolates the value before updating the property, e.g. mapping 0-1 to - * 0-10. - */ - interpolate(config) { - return new AnimatedInterpolation(this, Interpolation.create(config)); - } - - /** - * Typically only used internally, but could be used by a custom Animation - * class. - */ - animate(animation, callback) { - let handle = null; - if (animation.__isInteraction) { - handle = InteractionManager.createInteractionHandle(); - } - const previousAnimation = this._animation; - if (this._animation) { - this._animation.stop(); - } - this._animation = animation; - animation.start( - this._value, - (value) => { - this._updateValue(value); - }, - (result) => { - this._animation = null; - if (handle !== null) { - InteractionManager.clearInteractionHandle(handle); - } - if (callback) { - callback(result); - } - }, - previousAnimation - ); - } - - /** - * Typically only used internally. - */ - stopTracking() { - if (this._tracking) { - this._tracking.__detach(); - } - this._tracking = null; - } - - /** - * Typically only used internally. - */ - track(tracking) { - this.stopTracking(); - this._tracking = tracking; - } - - _updateValue(value) { - this._value = value; - _flush(this); - for (const key in this._listeners) { - this._listeners[key]({ value: this.__getValue() }); - } - } -} - - -class AnimatedValueXY extends AnimatedWithChildren { - constructor(valueIn) { - super(); - const value = valueIn || { x: 0, y: 0 }; // @flowfixme: shouldn't need `: any` - if (typeof value.x === 'number' && typeof value.y === 'number') { - this.x = new AnimatedValue(value.x); - this.y = new AnimatedValue(value.y); - } else { - invariant( - value.x instanceof AnimatedValue && - value.y instanceof AnimatedValue, - 'AnimatedValueXY must be initalized with an object of numbers or ' + - 'AnimatedValues.' - ); - this.x = value.x; - this.y = value.y; - } - this._listeners = {}; - } - - setValue(value) { - this.x.setValue(value.x); - this.y.setValue(value.y); - } - - setOffset(offset) { - this.x.setOffset(offset.x); - this.y.setOffset(offset.y); - } - - flattenOffset() { - this.x.flattenOffset(); - this.y.flattenOffset(); - } - - __getValue() { - return { - x: this.x.__getValue(), - y: this.y.__getValue(), - }; - } - - stopAnimation(callback) { - this.x.stopAnimation(); - this.y.stopAnimation(); - if (callback) { - callback(this.__getValue()); - } - } - - addListener(callback) { - const id = String(_uniqueId++); - const jointCallback = ({ value }) => { - callback(this.__getValue()); - }; - this._listeners[id] = { - x: this.x.addListener(jointCallback), - y: this.y.addListener(jointCallback), - }; - return id; - } - - removeListener(id) { - this.x.removeListener(this._listeners[id].x); - this.y.removeListener(this._listeners[id].y); - delete this._listeners[id]; - } - - /** - * Converts `{x, y}` into `{left, top}` for use in style, e.g. - * - *```javascript - * style={this.state.anim.getLayout()} - *``` - */ - getLayout() { - return { - left: this.x, - top: this.y, - }; - } - - /** - * Converts `{x, y}` into a useable translation transform, e.g. - * - *```javascript - * style={{ - * transform: this.state.anim.getTranslateTransform() - * }} - *``` - */ - getTranslateTransform() { - return [ - { translateX: this.x }, - { translateY: this.y } - ]; - } -} - - -class AnimatedAddition extends AnimatedWithChildren { - constructor(a, b) { - super(); - this._a = a; - this._b = b; - } - - __getValue() { - return this._a.__getValue() + this._b.__getValue(); - } - - interpolate(config) { - return new AnimatedInterpolation(this, Interpolation.create(config)); - } - - __attach() { - this._a.__addChild(this); - this._b.__addChild(this); - } - - __detach() { - this._a.__removeChild(this); - this._b.__removeChild(this); - } -} - -class AnimatedMultiplication extends AnimatedWithChildren { - constructor(a, b) { - super(); - this._a = a; - this._b = b; - } - - __getValue() { - return this._a.__getValue() * this._b.__getValue(); - } - - interpolate(config) { - return new AnimatedInterpolation(this, Interpolation.create(config)); - } - - __attach() { - this._a.__addChild(this); - this._b.__addChild(this); - } - - __detach() { - this._a.__removeChild(this); - this._b.__removeChild(this); - } -} - -class AnimatedTransform extends AnimatedWithChildren { - constructor(transforms) { - super(); - this._transforms = transforms; - } - - __getValue() { - return this._transforms.map(transform => { - const result = {}; - for (const key in transform) { - const value = transform[key]; - if (value instanceof Animated) { - result[key] = value.__getValue(); - } else { - result[key] = value; - } - } - return result; - }); - } - - __getAnimatedValue() { - return this._transforms.map(transform => { - const result = {}; - for (const key in transform) { - const value = transform[key]; - if (value instanceof Animated) { - result[key] = value.__getAnimatedValue(); - } else { - // All transform components needed to recompose matrix - result[key] = value; - } - } - return result; - }); - } - - __attach() { - this._transforms.forEach(transform => { - for (const key in transform) { - const value = transform[key]; - if (value instanceof Animated) { - value.__addChild(this); - } - } - }); - } - - __detach() { - this._transforms.forEach(transform => { - for (const key in transform) { - const value = transform[key]; - if (value instanceof Animated) { - value.__removeChild(this); - } - } - }); - } -} - -class AnimatedStyle extends AnimatedWithChildren { - constructor(style) { - super(); - let newStyle; - newStyle = flattenStyle(style) || {}; - if (newStyle.transform) { - newStyle = { - ...newStyle, - transform: new AnimatedTransform(newStyle.transform), - }; - } - this._style = newStyle; - } - - __getValue() { - const style = {}; - for (const key in this._style) { - const value = this._style[key]; - if (value instanceof Animated) { - style[key] = value.__getValue(); - } else { - style[key] = value; - } - } - return style; - } - - __getAnimatedValue() { - const style = {}; - for (const key in this._style) { - const value = this._style[key]; - if (value instanceof Animated) { - style[key] = value.__getAnimatedValue(); - } - } - return style; - } - - __attach() { - for (const key in this._style) { - const value = this._style[key]; - if (value instanceof Animated) { - value.__addChild(this); - } - } - } - - __detach() { - for (const key in this._style) { - const value = this._style[key]; - if (value instanceof Animated) { - value.__removeChild(this); - } - } - } -} - -class AnimatedProps extends Animated { - constructor(props, callback) { - super(); - this._props = props; - if (this._props.style) { - this._props = { - ...this._props, - style: new AnimatedStyle(this._props.style), - }; - } - this._callback = callback; - this.__attach(); - } - - __getValue() { - const props = {}; - for (const key in this._props) { - const value = this._props[key]; - if (value instanceof Animated) { - props[key] = value.__getValue(); - } else { - props[key] = value; - } - } - return props; - } - - __getAnimatedValue() { - const props = {}; - for (const key in this._props) { - const value = this._props[key]; - if (value instanceof Animated) { - props[key] = value.__getAnimatedValue(); - } - } - return props; - } - - __attach() { - for (const key in this._props) { - const value = this._props[key]; - if (value instanceof Animated) { - value.__addChild(this); - } - } - } - - __detach() { - for (const key in this._props) { - const value = this._props[key]; - if (value instanceof Animated) { - value.__removeChild(this); - } - } - } - - update() { - this._callback(); - } -} - -class AnimatedTracking extends Animated { - constructor(value, parent, animationClass, animationConfig, callback) { - super(); - this._value = value; - this._parent = parent; - this._animationClass = animationClass; - this._animationConfig = animationConfig; - this._callback = callback; - this.__attach(); - } - - __getValue() { - return this._parent.__getValue(); - } - - __attach() { - this._parent.__addChild(this); - } - - __detach() { - this._parent.__removeChild(this); - } - - update() { - this._value.animate(new this._animationClass({ - ...this._animationConfig, - toValue: this._animationConfig.toValue.__getValue(), - }), this._callback); - } -} - -function add(a, b) { - return new AnimatedAddition(a, b); -} - -function multiply(a, b) { - return new AnimatedMultiplication(a, b); -} - -function parallel(animations, config) { - let doneCount = 0; - // Make sure we only call stop() at most once for each animation - const hasEnded = {}; - const stopTogether = !(config && config.stopTogether === false); - - const result = { - start(callback) { - if (doneCount === animations.length) { - if (callback) { - callback({ finished: true }); - } - return; - } - - animations.forEach((animation, idx) => { - const cb = function (endResult) { - hasEnded[idx] = true; - doneCount++; - if (doneCount === animations.length) { - doneCount = 0; - if (callback) { - callback(endResult); - } - return; - } - - if (!endResult.finished && stopTogether) { - result.stop(); - } - }; - - if (!animation) { - cb({ finished: true }); - } else { - animation.start(cb); - } - }); - }, - - stop() { - animations.forEach((animation, idx) => { - if (!hasEnded[idx]) { - animation.stop(); - } - hasEnded[idx] = true; - }); - } - }; - - return result; -} - -function maybeVectorAnim(value, config, anim) { - if (value instanceof AnimatedValueXY) { - const configX = { ...config }; - const configY = { ...config }; - for (const key in config) { - const { x, y } = config[key]; - if (x !== undefined && y !== undefined) { - configX[key] = x; - configY[key] = y; - } - } - const aX = anim(value.x, configX); - const aY = anim(value.y, configY); - // We use `stopTogether: false` here because otherwise tracking will break - // because the second animation will get stopped before it can update. - return parallel([aX, aY], { stopTogether: false }); - } - return null; -} - -function spring(value, config) { - return maybeVectorAnim(value, config, spring) || { - start(callback) { - const singleValue = value; - const singleConfig = config; - singleValue.stopTracking(); - if (config.toValue instanceof Animated) { - singleValue.track(new AnimatedTracking( - singleValue, - config.toValue, - SpringAnimation, - singleConfig, - callback - )); - } else { - singleValue.animate(new SpringAnimation(singleConfig), callback); - } - }, - - stop() { - value.stopAnimation(); - }, - }; -} - -function timing(value, config) { - return maybeVectorAnim(value, config, timing) || { - start(callback) { - const singleValue = value; - const singleConfig = config; - singleValue.stopTracking(); - if (config.toValue instanceof Animated) { - singleValue.track(new AnimatedTracking( - singleValue, - config.toValue, - TimingAnimation, - singleConfig, - callback - )); - } else { - singleValue.animate(new TimingAnimation(singleConfig), callback); - } - }, - - stop() { - value.stopAnimation(); - }, - }; -} - -function decay(value, config) { - return maybeVectorAnim(value, config, decay) || { - start(callback) { - const singleValue = value; - const singleConfig = config; - singleValue.stopTracking(); - singleValue.animate(new DecayAnimation(singleConfig), callback); - }, - - stop() { - value.stopAnimation(); - }, - }; -} - -function sequence(animations) { - let current = 0; - return { - start(callback) { - const onComplete = function (result) { - if (!result.finished) { - if (callback) { - callback(result); - } - return; - } - - current++; - - if (current === animations.length) { - if (callback) { - callback(result); - } - return; - } - - animations[current].start(onComplete); - }; - - if (animations.length === 0) { - if (callback) { - callback({ finished: true }); - } - } else { - animations[current].start(onComplete); - } - }, - - stop() { - if (current < animations.length) { - animations[current].stop(); - } - } - }; -} - -function delay(time) { - // Would be nice to make a specialized implementation - return timing(new AnimatedValue(0), { toValue: 0, delay: time, duration: 0 }); -} - -function stagger(time, animations) { - return parallel(animations.map(function (animation, i) { - return sequence([ - delay(time * i), - animation, - ]); - })); -} - -function event(argMapping, config) { - return function (...args) { - const traverse = function (recMapping, recEvt, key) { - if (typeof recEvt === 'number') { - invariant( - recMapping instanceof AnimatedValue, - 'Bad mapping of type ' + typeof recMapping + ' for key ' + key + - ', event value must map to AnimatedValue' - ); - recMapping.setValue(recEvt); - return; - } - invariant( - typeof recMapping === 'object', - 'Bad mapping of type ' + typeof recMapping + ' for key ' + key - ); - invariant( - typeof recEvt === 'object', - 'Bad event of type ' + typeof recEvt + ' for key ' + key - ); - for (const i in recMapping) { - traverse(recMapping[i], recEvt[i], i); - } - }; - argMapping.forEach((mapping, idx) => { - traverse(mapping, args[idx], 'arg' + idx); - }); - if (config && config.listener) { - config.listener.apply(null, args); - } - }; -} - -const AnimatedImplementation = { - Value: AnimatedValue, - ValueXY: AnimatedValueXY, - decay, - timing, - spring, - add, - multiply, - sequence, - parallel, - stagger, - event, - - __PropsOnlyForTests: AnimatedProps, - __Animated: Animated, - __Animation: Animation, - __AnimatedWithChildren: AnimatedWithChildren, - __AnimatedStyle: AnimatedStyle, -}; - -module.exports = AnimatedImplementation; diff --git a/jest/Animated/Easing.js b/jest/Animated/Easing.js deleted file mode 100755 index 03c40917597baa..00000000000000 --- a/jest/Animated/Easing.js +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Easing - * @flow - */ -'use strict'; - -let ease; - -/** - * The `Easing` module implements common easing functions. This module is used - * by [Animate.timing()](docs/animate.html#timing) to convey physically - * believable motion in animations. - * - * You can find a visualization of some common easing functions at - * http://easings.net/ - * - * ### Predefined animations - * - * The `Easing` module provides several predefined animations through the - * following methods: - * - * - [`back`](docs/easing.html#back) provides a simple animation where the - * object goes slightly back before moving forward - * - [`bounce`](docs/easing.html#bounce) provides a bouncing animation - * - [`ease`](docs/easing.html#ease) provides a simple inertial animation - * - [`elastic`](docs/easing.html#elastic) provides a simple spring interaction - * - * ### Standard functions - * - * Three standard easing functions are provided: - * - * - [`linear`](docs/easing.html#linear) - * - [`quad`](docs/easing.html#quad) - * - [`cubic`](docs/easing.html#cubic) - * - * The [`poly`](docs/easing.html#poly) function can be used to implement - * quartic, quintic, and other higher power functions. - * - * ### Additional functions - * - * Additional mathematical functions are provided by the following methods: - * - * - [`bezier`](docs/easing.html#bezier) provides a cubic bezier curve - * - [`circle`](docs/easing.html#circle) provides a circular function - * - [`sin`](docs/easing.html#sin) provides a sinusoidal function - * - [`exp`](docs/easing.html#exp) provides an exponential function - * - * The following helpers are used to modify other easing functions. - * - * - [`in`](docs/easing.html#in) runs an easing function forwards - * - [`inOut`](docs/easing.html#inout) makes any easing function symmetrical - * - [`out`](docs/easing.html#out) runs an easing function backwards - */ -class Easing { - /** - * A stepping function, returns 1 for any positive value of `n`. - */ - static step0(n) { - return n > 0 ? 1 : 0; - } - - /** - * A stepping function, returns 1 if `n` is greater than or equal to 1. - */ - static step1(n) { - return n >= 1 ? 1 : 0; - } - - /** - * A linear function, `f(t) = t`. Position correlates to elapsed time one to - * one. - * - * http://cubic-bezier.com/#0,0,1,1 - */ - static linear(t) { - return t; - } - - /** - * A simple inertial interaction, similar to an object slowly accelerating to - * speed. - * - * http://cubic-bezier.com/#.42,0,1,1 - */ - static ease(t: number): number { - if (!ease) { - ease = Easing.bezier(0.42, 0, 1, 1); - } - return ease(t); - } - - /** - * A quadratic function, `f(t) = t * t`. Position equals the square of elapsed - * time. - * - * http://easings.net/#easeInQuad - */ - static quad(t) { - return t * t; - } - - /** - * A cubic function, `f(t) = t * t * t`. Position equals the cube of elapsed - * time. - * - * http://easings.net/#easeInCubic - */ - static cubic(t) { - return t * t * t; - } - - /** - * A power function. Position is equal to the Nth power of elapsed time. - * - * n = 4: http://easings.net/#easeInQuart - * n = 5: http://easings.net/#easeInQuint - */ - static poly(n) { - return (t) => Math.pow(t, n); - } - - /** - * A sinusoidal function. - * - * http://easings.net/#easeInSine - */ - static sin(t) { - return 1 - Math.cos(t * Math.PI / 2); - } - - /** - * A circular function. - * - * http://easings.net/#easeInCirc - */ - static circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - - /** - * An exponential function. - * - * http://easings.net/#easeInExpo - */ - static exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - - /** - * A simple elastic interaction, similar to a spring oscillating back and - * forth. - * - * Default bounciness is 1, which overshoots a little bit once. 0 bounciness - * doesn't overshoot at all, and bounciness of N > 1 will overshoot about N - * times. - * - * http://easings.net/#easeInElastic - * - * Wolfram Plots: - * - * - http://tiny.cc/elastic_b_1 (bounciness = 1, default) - * - http://tiny.cc/elastic_b_3 (bounciness = 3) - */ - static elastic(bounciness: number = 1): (t: number) => number { - const p = bounciness * Math.PI; - return (t) => 1 - Math.pow(Math.cos(t * Math.PI / 2), 3) * Math.cos(t * p); - } - - /** - * Use with `Animated.parallel()` to create a simple effect where the object - * animates back slightly as the animation starts. - * - * Wolfram Plot: - * - * - http://tiny.cc/back_default (s = 1.70158, default) - */ - static back(s: number): (t: number) => number { - if (s === undefined) { - s = 1.70158; - } - return (t) => t * t * ((s + 1) * t - s); - } - - /** - * Provides a simple bouncing effect. - * - * http://easings.net/#easeInBounce - */ - static bounce(t: number): number { - if (t < 1 / 2.75) { - return 7.5625 * t * t; - } - - if (t < 2 / 2.75) { - t -= 1.5 / 2.75; - return 7.5625 * t * t + 0.75; - } - - if (t < 2.5 / 2.75) { - t -= 2.25 / 2.75; - return 7.5625 * t * t + 0.9375; - } - - t -= 2.625 / 2.75; - return 7.5625 * t * t + 0.984375; - } - - /** - * Provides a cubic bezier curve, equivalent to CSS Transitions' - * `transition-timing-function`. - * - * A useful tool to visualize cubic bezier curves can be found at - * http://cubic-bezier.com/ - */ - static bezier( - x1: number, - y1: number, - x2: number, - y2: number - ): (t: number) => number { - const _bezier = require('bezier'); - return _bezier(x1, y1, x2, y2); - } - - /** - * Runs an easing function forwards. - */ - static in( - easing: (t: number) => number, - ): (t: number) => number { - return easing; - } - - /** - * Runs an easing function backwards. - */ - static out( - easing: (t: number) => number, - ): (t: number) => number { - return (t) => 1 - easing(1 - t); - } - - /** - * Makes any easing function symmetrical. The easing function will run - * forwards for half of the duration, then backwards for the rest of the - * duration. - */ - static inOut( - easing: (t: number) => number, - ): (t: number) => number { - return (t) => { - if (t < 0.5) { - return easing(t * 2) / 2; - } - return 1 - easing((1 - t) * 2) / 2; - }; - } -} - -module.exports = Easing; diff --git a/jest/Animated/Interpolation.js b/jest/Animated/Interpolation.js deleted file mode 100755 index aa38a490e8b9f1..00000000000000 --- a/jest/Animated/Interpolation.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * https://github.com/facebook/react-native/blob/master/Libraries/Animated/src/Interpolation.js - */ -class Interpolation { - static create(config) { - // TODO(lmr): - } -} - -module.exports = Interpolation; diff --git a/jest/Animated/SpringConfig.js b/jest/Animated/SpringConfig.js deleted file mode 100755 index 0488523a01f5a8..00000000000000 --- a/jest/Animated/SpringConfig.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * https://github.com/facebook/react-native/blob/master/Libraries/Animated/src/SpringConfig.js - */ - -function tensionFromOrigamiValue(oValue) { - return (oValue - 30) * 3.62 + 194; -} - -function frictionFromOrigamiValue(oValue) { - return (oValue - 8) * 3 + 25; -} - -function fromOrigamiTensionAndFriction(tension, friction) { - return { - tension: tensionFromOrigamiValue(tension), - friction: frictionFromOrigamiValue(friction) - }; -} - -function fromBouncinessAndSpeed(bounciness, speed) { - function normalize(value, startValue, endValue) { - return (value - startValue) / (endValue - startValue); - } - - function projectNormal(n, start, end) { - return start + (n * (end - start)); - } - - function linearInterpolation(t, start, end) { - return t * end + (1 - t) * start; - } - - function quadraticOutInterpolation(t, start, end) { - return linearInterpolation(2 * t - t * t, start, end); - } - - function b3Friction1(x) { - return (0.0007 * Math.pow(x, 3)) - - (0.031 * Math.pow(x, 2)) + 0.64 * x + 1.28; - } - - function b3Friction2(x) { - return (0.000044 * Math.pow(x, 3)) - - (0.006 * Math.pow(x, 2)) + 0.36 * x + 2; - } - - function b3Friction3(x) { - return (0.00000045 * Math.pow(x, 3)) - - (0.000332 * Math.pow(x, 2)) + 0.1078 * x + 5.84; - } - - function b3Nobounce(tension) { - if (tension <= 18) { - return b3Friction1(tension); - } else if (tension > 18 && tension <= 44) { - return b3Friction2(tension); - } - return b3Friction3(tension); - } - - let b = normalize(bounciness / 1.7, 0, 20); - b = projectNormal(b, 0, 0.8); - const s = normalize(speed / 1.7, 0, 20); - const bouncyTension = projectNormal(s, 0.5, 200); - const bouncyFriction = quadraticOutInterpolation( - b, - b3Nobounce(bouncyTension), - 0.01 - ); - - return { - tension: tensionFromOrigamiValue(bouncyTension), - friction: frictionFromOrigamiValue(bouncyFriction) - }; -} - -module.exports = { - fromOrigamiTensionAndFriction, - fromBouncinessAndSpeed, -}; diff --git a/jest/Animated/createAnimatedComponent.js b/jest/Animated/createAnimatedComponent.js deleted file mode 100755 index 6e9cba5ec3ceb8..00000000000000 --- a/jest/Animated/createAnimatedComponent.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -function createAnimatedComponent(Component) { - const refName = 'node'; - - class AnimatedComponent extends React.Component { - render() { - return ( - - ); - } - } - - return AnimatedComponent; -} - -module.exports = createAnimatedComponent; diff --git a/jest/Animated/index.js b/jest/Animated/index.js deleted file mode 100755 index faa10a38ed6c05..00000000000000 --- a/jest/Animated/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import createAnimatedComponent from './createAnimatedComponent'; -import AnimatedImplementation from './AnimatedImplementation'; - -const mockAnimatedComponent = require.requireActual('./mockAnimatedComponent'); - -module.exports = { - ...AnimatedImplementation, - createAnimatedComponent, - View: mockAnimatedComponent('Animated.View'), - Text: mockAnimatedComponent('Animated.Text'), - Image: mockAnimatedComponent('IAnimated.mage'), -}; diff --git a/jest/Animated/mockAnimatedComponent.js b/jest/Animated/mockAnimatedComponent.js deleted file mode 100644 index ba9ca2ab3558d4..00000000000000 --- a/jest/Animated/mockAnimatedComponent.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -var ViewStylePropTypes = require('ViewStylePropTypes'); - -module.exports = name => { - const React = require('react'); - - const AnimatedComponent = class extends React.Component { - render() { - if (global.__JSDOM_MOUNTABLE__) { - return React.createElement( - name.replace(/^(RCT|RK)/,''), - { children: this.props.children }, - ); - } - - return React.createElement( - name.replace(/^(RCT|RK)/,''), - this.props, - this.props.children, - ); - } - }; - // from Animated/AnimatedImplemenatation - AnimatedComponent.propTypes = { - style: function(props, propName, componentName) { - if (!propTypes) { - return; - } - - for (var key in ViewStylePropTypes) { - if (!propTypes[key] && props[key] !== undefined) { - console.warn( - 'You are setting the style `{ ' + key + ': ... }` as a prop. You ' + - 'should nest it in a style object. ' + - 'E.g. `{ style: { ' + key + ': ... } }`' - ); - } - } - }, - }; - return AnimatedComponent; -}; diff --git a/jest/InteractionManager.js b/jest/InteractionManager.js deleted file mode 100644 index 21c2371f21202e..00000000000000 --- a/jest/InteractionManager.js +++ /dev/null @@ -1,69 +0,0 @@ -import keyMirror from 'keymirror'; -import invariant from 'invariant'; - -const { EventEmitter } = require('events'); - -const _emitter = new EventEmitter(); - -let _inc = 0; -let _deadline = -1; // eslint-disable-line no-unused-vars - -const InteractionManager = { - Events: keyMirror({ - interactionStart: true, - interactionComplete: true, - }), - - /** - * Schedule a function to run after all interactions have completed. - */ - runAfterInteractions(task) { - return new Promise(resolve => { - // TODO(lmr): - // _scheduleUpdate(); - // if (task) { - // _taskQueue.enqueue(task); - // } - // const name = task && task.name || '?'; - // _taskQueue.enqueue({ run: resolve, name: 'resolve ' + name }); - }); - }, - - /** - * Notify manager that an interaction has started. - */ - createInteractionHandle() { - // TODO(lmr): - // _scheduleUpdate(); - const handle = ++_inc; - // _addInteractionSet.add(handle); - return handle; - }, - - /** - * Notify manager that an interaction has completed. - */ - clearInteractionHandle(handle) { - invariant( - !!handle, - 'Must provide a handle to clear.' - ); - // TODO(lmr): - // _scheduleUpdate(); - // _addInteractionSet.delete(handle); - // _deleteInteractionSet.add(handle); - }, - - addListener: _emitter.addListener.bind(_emitter), - - /** - * A positive number will use setTimeout to schedule any tasks after the - * eventLoopRunningTime hits the deadline value, otherwise all tasks will be - * executed in one setImmediate batch (default). - */ - setDeadline(deadline) { - _deadline = deadline; - }, -}; - -module.exports = InteractionManager; diff --git a/jest/setup.js b/jest/setup.js index e48b461d948d59..bf2084d3096910 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -41,7 +41,6 @@ jest .mock('Modal', () => mockComponent('Modal')) .mock('View', () => mockComponent('View')) .mock('RefreshControl', () => require.requireMock('RefreshControlMock')) - .mock('Animated', () => require.requireActual('./Animated')) .mock('ScrollView', () => require.requireMock('ScrollViewMock')) .mock( 'ActivityIndicator',