refactor(animations): deport TCB away from animation-land forever (#10892)

* feat(animations): support animation trigger template callbacks

* refactor(animations): deport TCB away from animation-land forever
This commit is contained in:
Matias Niemelä
2016-08-22 17:18:25 -07:00
committed by Kara
parent ca41b4f5ff
commit 45e8e73670
15 changed files with 1598 additions and 1125 deletions

View File

@ -9,6 +9,7 @@
import {ANY_STATE as ANY_STATE_, DEFAULT_STATE as DEFAULT_STATE_, EMPTY_STATE as EMPTY_STATE_, FILL_STYLE_FLAG as FILL_STYLE_FLAG_} from './src/animation/animation_constants';
import {AnimationGroupPlayer as AnimationGroupPlayer_} from './src/animation/animation_group_player';
import {AnimationKeyframe as AnimationKeyframe_} from './src/animation/animation_keyframe';
import {AnimationOutput as AnimationOutput_} from './src/animation/animation_output';
import {AnimationPlayer as AnimationPlayer_, NoOpAnimationPlayer as NoOpAnimationPlayer_} from './src/animation/animation_player';
import {AnimationSequencePlayer as AnimationSequencePlayer_} from './src/animation/animation_sequence_player';
import * as animationUtils from './src/animation/animation_style_util';
@ -119,6 +120,8 @@ export declare namespace __core_private_types__ {
export var collectAndResolveStyles: typeof animationUtils.collectAndResolveStyles;
export type AnimationStyles = AnimationStyles_;
export var AnimationStyles: typeof AnimationStyles_;
export type AnimationOutput = AnimationOutput_;
export var AnimationOutput: typeof AnimationOutput_;
export var ANY_STATE: typeof ANY_STATE_;
export var DEFAULT_STATE: typeof DEFAULT_STATE_;
export var EMPTY_STATE: typeof EMPTY_STATE_;
@ -185,6 +188,7 @@ export var __core_private__ = {
renderStyles: animationUtils.renderStyles,
collectAndResolveStyles: animationUtils.collectAndResolveStyles,
AnimationStyles: AnimationStyles_,
AnimationOutput: AnimationOutput_,
ANY_STATE: ANY_STATE_,
DEFAULT_STATE: DEFAULT_STATE_,
EMPTY_STATE: EMPTY_STATE_,

View File

@ -0,0 +1,10 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export class AnimationOutput {
constructor(public name: string, public phase: string, public fullPropertyName: string) {}
}

View File

@ -7,7 +7,8 @@
*/
import {AnimationGroupPlayer} from '../animation/animation_group_player';
import {AnimationPlayer} from '../animation/animation_player';
import {AnimationOutput} from '../animation/animation_output';
import {AnimationPlayer, NoOpAnimationPlayer} from '../animation/animation_player';
import {ViewAnimationMap} from '../animation/view_animation_map';
import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/change_detection';
import {Injector} from '../di/injector';
@ -50,6 +51,8 @@ export abstract class AppView<T> {
public animationPlayers = new ViewAnimationMap();
private _animationListeners = new Map<any, _AnimationOutputWithHandler[]>();
public context: T;
constructor(
@ -77,9 +80,23 @@ export abstract class AppView<T> {
}
}
queueAnimation(element: any, animationName: string, player: AnimationPlayer): void {
queueAnimation(
element: any, animationName: string, player: AnimationPlayer, fromState: string,
toState: string): void {
var actualAnimationDetected = !(player instanceof NoOpAnimationPlayer);
var animationData = {
'fromState': fromState,
'toState': toState,
'running': actualAnimationDetected
};
this.animationPlayers.set(element, animationName, player);
player.onDone(() => { this.animationPlayers.remove(element, animationName); });
player.onDone(() => {
// TODO: make this into a datastructure for done|start
this.triggerAnimationOutput(element, animationName, 'done', animationData);
this.animationPlayers.remove(element, animationName);
});
player.onStart(
() => { this.triggerAnimationOutput(element, animationName, 'start', animationData); });
}
triggerQueuedAnimations() {
@ -90,6 +107,32 @@ export abstract class AppView<T> {
});
}
triggerAnimationOutput(
element: any, animationName: string, phase: string, animationData: {[key: string]: any}) {
var listeners = this._animationListeners.get(element);
if (isPresent(listeners) && listeners.length) {
for (let i = 0; i < listeners.length; i++) {
let listener = listeners[i];
// we check for both the name in addition to the phase in the event
// that there may be more than one @trigger on the same element
if (listener.output.name == animationName && listener.output.phase == phase) {
listener.handler(animationData);
break;
}
}
}
}
registerAnimationOutput(element: any, outputEvent: AnimationOutput, eventHandler: Function):
void {
var entry = new _AnimationOutputWithHandler(outputEvent, eventHandler);
var animations = this._animationListeners.get(element);
if (!isPresent(animations)) {
this._animationListeners.set(element, animations = []);
}
animations.push(entry);
}
create(context: T, givenProjectableNodes: Array<any|any[]>, rootSelectorOrNode: string|any):
AppElement {
this.context = context;
@ -433,3 +476,7 @@ function _findLastRenderNode(node: any): any {
}
return lastNode;
}
class _AnimationOutputWithHandler {
constructor(public output: AnimationOutput, public handler: Function) {}
}