diff --git a/packages/animations/browser/src/dsl/animation.ts b/packages/animations/browser/src/dsl/animation.ts index f0948a1c4d..f03f9c697c 100644 --- a/packages/animations/browser/src/dsl/animation.ts +++ b/packages/animations/browser/src/dsl/animation.ts @@ -5,7 +5,7 @@ * 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 */ -import {AnimationMetadata, AnimationMetadataType, AnimationOptions, ɵStyleData} from '@angular/animations'; +import {AnimationMetadata, AnimationOptions, ɵStyleData} from '@angular/animations'; import {AnimationDriver} from '../render/animation_driver'; import {normalizeStyles} from '../util'; @@ -17,7 +17,7 @@ import {AnimationTimelineInstruction} from './animation_timeline_instruction'; import {ElementInstructionMap} from './element_instruction_map'; export class Animation { - private _animationAst: Ast; + private _animationAst: Ast; constructor(private _driver: AnimationDriver, input: AnimationMetadata|AnimationMetadata[]) { const errors: any[] = []; const ast = buildAnimationAst(_driver, input, errors); diff --git a/packages/animations/browser/src/dsl/animation_ast.ts b/packages/animations/browser/src/dsl/animation_ast.ts index 7055b59542..0a8b1309cd 100644 --- a/packages/animations/browser/src/dsl/animation_ast.ts +++ b/packages/animations/browser/src/dsl/animation_ast.ts @@ -5,7 +5,7 @@ * 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 */ -import {AnimateTimings, AnimationMetadataType, AnimationOptions, ɵStyleData} from '@angular/animations'; +import {AnimateTimings, AnimationOptions, ɵStyleData} from '@angular/animations'; const EMPTY_ANIMATION_OPTIONS: AnimationOptions = {}; @@ -23,90 +23,129 @@ export interface AstVisitor { visitAnimateRef(ast: AnimateRefAst, context: any): any; visitQuery(ast: QueryAst, context: any): any; visitStagger(ast: StaggerAst, context: any): any; + visitTiming(ast: TimingAst, context: any): any; } -export interface Ast { - type: T; - options: AnimationOptions|null; +export abstract class Ast { + abstract visit(ast: AstVisitor, context: any): any; + public options: AnimationOptions = EMPTY_ANIMATION_OPTIONS; + + get params(): {[name: string]: any}|null { return this.options['params'] || null; } } -export interface TriggerAst extends Ast { - type: AnimationMetadataType.Trigger; - name: string; - states: StateAst[]; - transitions: TransitionAst[]; - queryCount: number; - depCount: number; +export class TriggerAst extends Ast { + public queryCount: number = 0; + public depCount: number = 0; + + constructor(public name: string, public states: StateAst[], public transitions: TransitionAst[]) { + super(); + } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitTrigger(this, context); } } -export interface StateAst extends Ast { - type: AnimationMetadataType.State; - name: string; - style: StyleAst; +export class StateAst extends Ast { + constructor(public name: string, public style: StyleAst) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitState(this, context); } } -export interface TransitionAst extends Ast { - matchers: ((fromState: string, toState: string) => boolean)[]; - animation: Ast; - queryCount: number; - depCount: number; +export class TransitionAst extends Ast { + public queryCount: number = 0; + public depCount: number = 0; + + constructor( + public matchers: ((fromState: string, toState: string) => boolean)[], public animation: Ast) { + super(); + } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitTransition(this, context); } } -export interface SequenceAst extends Ast { - steps: Ast[]; +export class SequenceAst extends Ast { + constructor(public steps: Ast[]) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitSequence(this, context); } } -export interface GroupAst extends Ast { - steps: Ast[]; +export class GroupAst extends Ast { + constructor(public steps: Ast[]) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitGroup(this, context); } } -export interface AnimateAst extends Ast { - timings: TimingAst; - style: StyleAst|KeyframesAst; +export class AnimateAst extends Ast { + constructor(public timings: TimingAst, public style: StyleAst|KeyframesAst) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitAnimate(this, context); } } -export interface StyleAst extends Ast { - styles: (ɵStyleData|string)[]; - easing: string|null; - offset: number|null; - containsDynamicStyles: boolean; - isEmptyStep?: boolean; +export class StyleAst extends Ast { + public isEmptyStep = false; + public containsDynamicStyles = false; + + constructor( + public styles: (ɵStyleData|string)[], public easing: string|null, + public offset: number|null) { + super(); + } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitStyle(this, context); } } -export interface KeyframesAst extends Ast { styles: StyleAst[]; } +export class KeyframesAst extends Ast { + constructor(public styles: StyleAst[]) { super(); } -export interface ReferenceAst extends Ast { - animation: Ast; + visit(visitor: AstVisitor, context: any): any { return visitor.visitKeyframes(this, context); } } -export interface AnimateChildAst extends Ast {} +export class ReferenceAst extends Ast { + constructor(public animation: Ast) { super(); } -export interface AnimateRefAst extends Ast { - animation: ReferenceAst; + visit(visitor: AstVisitor, context: any): any { return visitor.visitReference(this, context); } } -export interface QueryAst extends Ast { - selector: string; - limit: number; - optional: boolean; - includeSelf: boolean; - animation: Ast; - originalSelector: string; +export class AnimateChildAst extends Ast { + constructor() { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitAnimateChild(this, context); } } -export interface StaggerAst extends Ast { - timings: AnimateTimings; - animation: Ast; +export class AnimateRefAst extends Ast { + constructor(public animation: ReferenceAst) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitAnimateRef(this, context); } } -export interface TimingAst { - duration: number; - delay: number; - easing: string|null; - dynamic?: boolean; +export class QueryAst extends Ast { + public originalSelector: string; + + constructor( + public selector: string, public limit: number, public optional: boolean, + public includeSelf: boolean, public animation: Ast) { + super(); + } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitQuery(this, context); } } -export interface DynamicTimingAst extends TimingAst { - strValue: string; - dynamic: true; +export class StaggerAst extends Ast { + constructor(public timings: AnimateTimings, public animation: Ast) { super(); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitStagger(this, context); } +} + +export class TimingAst extends Ast { + constructor( + public duration: number, public delay: number = 0, public easing: string|null = null) { + super(); + } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitTiming(this, context); } +} + +export class DynamicTimingAst extends TimingAst { + constructor(public value: string) { super(0, 0, ''); } + + visit(visitor: AstVisitor, context: any): any { return visitor.visitTiming(this, context); } } diff --git a/packages/animations/browser/src/dsl/animation_ast_builder.ts b/packages/animations/browser/src/dsl/animation_ast_builder.ts index 958232d88c..0a6fd2fd6e 100644 --- a/packages/animations/browser/src/dsl/animation_ast_builder.ts +++ b/packages/animations/browser/src/dsl/animation_ast_builder.ts @@ -9,10 +9,10 @@ import {AUTO_STYLE, AnimateTimings, AnimationAnimateChildMetadata, AnimationAnim import {AnimationDriver} from '../render/animation_driver'; import {getOrSetAsInMap} from '../render/shared'; -import {ENTER_SELECTOR, LEAVE_SELECTOR, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, SUBSTITUTION_EXPR_START, copyObj, extractStyleParams, iteratorToArray, normalizeAnimationEntry, resolveTiming, validateStyleParams, visitDslNode} from '../util'; +import {ENTER_SELECTOR, LEAVE_SELECTOR, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, SUBSTITUTION_EXPR_START, copyObj, extractStyleParams, iteratorToArray, normalizeAnimationEntry, resolveTiming, validateStyleParams} from '../util'; import {AnimateAst, AnimateChildAst, AnimateRefAst, Ast, DynamicTimingAst, GroupAst, KeyframesAst, QueryAst, ReferenceAst, SequenceAst, StaggerAst, StateAst, StyleAst, TimingAst, TransitionAst, TriggerAst} from './animation_ast'; -import {AnimationDslVisitor} from './animation_dsl_visitor'; +import {AnimationDslVisitor, visitAnimationNode} from './animation_dsl_visitor'; import {parseTransitionExpr} from './animation_transition_expr'; const SELF_TOKEN = ':self'; @@ -56,7 +56,7 @@ const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g'); */ export function buildAnimationAst( driver: AnimationDriver, metadata: AnimationMetadata | AnimationMetadata[], - errors: any[]): Ast { + errors: any[]): Ast { return new AnimationAstBuilderVisitor(driver).build(metadata, errors); } @@ -69,12 +69,10 @@ const ROOT_SELECTOR = ''; export class AnimationAstBuilderVisitor implements AnimationDslVisitor { constructor(private _driver: AnimationDriver) {} - build(metadata: AnimationMetadata|AnimationMetadata[], errors: any[]): - Ast { + build(metadata: AnimationMetadata|AnimationMetadata[], errors: any[]): Ast { const context = new AnimationAstBuilderContext(errors); this._resetContextStyleTimingState(context); - return >visitDslNode( - this, normalizeAnimationEntry(metadata), context); + return visitAnimationNode(this, normalizeAnimationEntry(metadata), context) as Ast; } private _resetContextStyleTimingState(context: AnimationAstBuilderContext) { @@ -110,12 +108,11 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { 'only state() and transition() definitions can sit inside of a trigger()'); } }); - - return { - type: AnimationMetadataType.Trigger, - name: metadata.name, states, transitions, queryCount, depCount, - options: null - }; + const ast = new TriggerAst(metadata.name, states, transitions); + ast.options = normalizeAnimationOptions(metadata.options); + ast.queryCount = queryCount; + ast.depCount = depCount; + return ast; } visitState(metadata: AnimationStateMetadata, context: AnimationAstBuilderContext): StateAst { @@ -143,38 +140,31 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { } } - return { - type: AnimationMetadataType.State, - name: metadata.name, - style: styleAst, - options: astParams ? {params: astParams} : null - }; + const stateAst = new StateAst(metadata.name, styleAst); + if (astParams) { + stateAst.options = {params: astParams}; + } + return stateAst; } visitTransition(metadata: AnimationTransitionMetadata, context: AnimationAstBuilderContext): TransitionAst { context.queryCount = 0; context.depCount = 0; - const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); + const entry = visitAnimationNode(this, normalizeAnimationEntry(metadata.animation), context); const matchers = parseTransitionExpr(metadata.expr, context.errors); - - return { - type: AnimationMetadataType.Transition, - matchers, - animation, - queryCount: context.queryCount, - depCount: context.depCount, - options: normalizeAnimationOptions(metadata.options) - }; + const ast = new TransitionAst(matchers, entry); + ast.options = normalizeAnimationOptions(metadata.options); + ast.queryCount = context.queryCount; + ast.depCount = context.depCount; + return ast; } visitSequence(metadata: AnimationSequenceMetadata, context: AnimationAstBuilderContext): SequenceAst { - return { - type: AnimationMetadataType.Sequence, - steps: metadata.steps.map(s => visitDslNode(this, s, context)), - options: normalizeAnimationOptions(metadata.options) - }; + const ast = new SequenceAst(metadata.steps.map(s => visitAnimationNode(this, s, context))); + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitGroup(metadata: AnimationGroupMetadata, context: AnimationAstBuilderContext): GroupAst { @@ -182,17 +172,15 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { let furthestTime = 0; const steps = metadata.steps.map(step => { context.currentTime = currentTime; - const innerAst = visitDslNode(this, step, context); + const innerAst = visitAnimationNode(this, step, context); furthestTime = Math.max(furthestTime, context.currentTime); return innerAst; }); context.currentTime = furthestTime; - return { - type: AnimationMetadataType.Group, - steps, - options: normalizeAnimationOptions(metadata.options) - }; + const ast = new GroupAst(steps); + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitAnimate(metadata: AnimationAnimateMetadata, context: AnimationAstBuilderContext): @@ -200,10 +188,10 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { const timingAst = constructTimingAst(metadata.timings, context.errors); context.currentAnimateTimings = timingAst; - let styleAst: StyleAst|KeyframesAst; + let styles: StyleAst|KeyframesAst; let styleMetadata: AnimationMetadata = metadata.styles ? metadata.styles : style({}); if (styleMetadata.type == AnimationMetadataType.Keyframes) { - styleAst = this.visitKeyframes(styleMetadata as AnimationKeyframesSequenceMetadata, context); + styles = this.visitKeyframes(styleMetadata as AnimationKeyframesSequenceMetadata, context); } else { let styleMetadata = metadata.styles as AnimationStyleMetadata; let isEmpty = false; @@ -216,18 +204,13 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { styleMetadata = style(newStyleData); } context.currentTime += timingAst.duration + timingAst.delay; - const _styleAst = this.visitStyle(styleMetadata, context); - _styleAst.isEmptyStep = isEmpty; - styleAst = _styleAst; + const styleAst = this.visitStyle(styleMetadata, context); + styleAst.isEmptyStep = isEmpty; + styles = styleAst; } context.currentAnimateTimings = null; - return { - type: AnimationMetadataType.Animate, - timings: timingAst, - style: styleAst, - options: null - }; + return new AnimateAst(timingAst, styles); } visitStyle(metadata: AnimationStyleMetadata, context: AnimationAstBuilderContext): StyleAst { @@ -277,13 +260,9 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { } }); - return { - type: AnimationMetadataType.Style, - styles, - easing: collectedEasing, - offset: metadata.offset, containsDynamicStyles, - options: null - }; + const ast = new StyleAst(styles, collectedEasing, metadata.offset); + ast.containsDynamicStyles = containsDynamicStyles; + return ast; } private _validateStyleAst(ast: StyleAst, context: AnimationAstBuilderContext): void { @@ -334,10 +313,9 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { visitKeyframes(metadata: AnimationKeyframesSequenceMetadata, context: AnimationAstBuilderContext): KeyframesAst { - const ast: KeyframesAst = {type: AnimationMetadataType.Keyframes, styles: [], options: null}; if (!context.currentAnimateTimings) { context.errors.push(`keyframes() must be placed inside of a call to animate()`); - return ast; + return new KeyframesAst([]); } const MAX_KEYFRAME_OFFSET = 1; @@ -391,38 +369,33 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { currentAnimateTimings.duration = durationUpToThisFrame; this._validateStyleAst(kf, context); kf.offset = offset; - - ast.styles.push(kf); }); - return ast; + return new KeyframesAst(keyframes); } visitReference(metadata: AnimationReferenceMetadata, context: AnimationAstBuilderContext): ReferenceAst { - return { - type: AnimationMetadataType.Reference, - animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), - options: normalizeAnimationOptions(metadata.options) - }; + const entry = visitAnimationNode(this, normalizeAnimationEntry(metadata.animation), context); + const ast = new ReferenceAst(entry); + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitAnimateChild(metadata: AnimationAnimateChildMetadata, context: AnimationAstBuilderContext): AnimateChildAst { context.depCount++; - return { - type: AnimationMetadataType.AnimateChild, - options: normalizeAnimationOptions(metadata.options) - }; + const ast = new AnimateChildAst(); + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitAnimateRef(metadata: AnimationAnimateRefMetadata, context: AnimationAstBuilderContext): AnimateRefAst { - return { - type: AnimationMetadataType.AnimateRef, - animation: this.visitReference(metadata.animation, context), - options: normalizeAnimationOptions(metadata.options) - }; + const animation = this.visitReference(metadata.animation, context); + const ast = new AnimateRefAst(animation); + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitQuery(metadata: AnimationQueryMetadata, context: AnimationAstBuilderContext): QueryAst { @@ -436,18 +409,14 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { parentSelector.length ? (parentSelector + ' ' + selector) : selector; getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {}); - const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); + const entry = visitAnimationNode(this, normalizeAnimationEntry(metadata.animation), context); context.currentQuery = null; context.currentQuerySelector = parentSelector; - return { - type: AnimationMetadataType.Query, - selector, - limit: options.limit || 0, - optional: !!options.optional, includeSelf, animation, - originalSelector: metadata.selector, - options: normalizeAnimationOptions(metadata.options) - }; + const ast = new QueryAst(selector, options.limit || 0, !!options.optional, includeSelf, entry); + ast.originalSelector = metadata.selector; + ast.options = normalizeAnimationOptions(metadata.options); + return ast; } visitStagger(metadata: AnimationStaggerMetadata, context: AnimationAstBuilderContext): @@ -458,12 +427,9 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor { const timings = metadata.timings === 'full' ? {duration: 0, delay: 0, easing: 'full'} : resolveTiming(metadata.timings, context.errors, true); - - return { - type: AnimationMetadataType.Stagger, - animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), timings, - options: null - }; + const animation = + visitAnimationNode(this, normalizeAnimationEntry(metadata.animation), context); + return new StaggerAst(timings, animation); } } @@ -535,20 +501,17 @@ function constructTimingAst(value: string | number | AnimateTimings, errors: any timings = value as AnimateTimings; } else if (typeof value == 'number') { const duration = resolveTiming(value as number, errors).duration; - return makeTimingAst(duration as number, 0, ''); + return new TimingAst(value as number, 0, ''); } const strValue = value as string; const isDynamic = strValue.split(/\s+/).some(v => v.charAt(0) == '{' && v.charAt(1) == '{'); if (isDynamic) { - const ast = makeTimingAst(0, 0, '') as any; - ast.dynamic = true; - ast.strValue = strValue; - return ast as DynamicTimingAst; + return new DynamicTimingAst(strValue); } timings = timings || resolveTiming(strValue, errors); - return makeTimingAst(timings.duration, timings.delay, timings.easing); + return new TimingAst(timings.duration, timings.delay, timings.easing); } function normalizeAnimationOptions(options: AnimationOptions | null): AnimationOptions { @@ -562,7 +525,3 @@ function normalizeAnimationOptions(options: AnimationOptions | null): AnimationO } return options; } - -function makeTimingAst(duration: number, delay: number, easing: string | null): TimingAst { - return {duration, delay, easing}; -} diff --git a/packages/animations/browser/src/dsl/animation_dsl_visitor.ts b/packages/animations/browser/src/dsl/animation_dsl_visitor.ts index e77f9db90e..6b2176d0ab 100644 --- a/packages/animations/browser/src/dsl/animation_dsl_visitor.ts +++ b/packages/animations/browser/src/dsl/animation_dsl_visitor.ts @@ -5,20 +5,54 @@ * 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 */ -import {AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationQueryMetadata, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata} from '@angular/animations'; +import {AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationMetadataType, AnimationQueryMetadata, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata} from '@angular/animations'; export interface AnimationDslVisitor { - visitTrigger(node: AnimationTriggerMetadata, context: any): any; - visitState(node: AnimationStateMetadata, context: any): any; - visitTransition(node: AnimationTransitionMetadata, context: any): any; - visitSequence(node: AnimationSequenceMetadata, context: any): any; - visitGroup(node: AnimationGroupMetadata, context: any): any; - visitAnimate(node: AnimationAnimateMetadata, context: any): any; - visitStyle(node: AnimationStyleMetadata, context: any): any; - visitKeyframes(node: AnimationKeyframesSequenceMetadata, context: any): any; - visitReference(node: AnimationReferenceMetadata, context: any): any; - visitAnimateChild(node: AnimationAnimateChildMetadata, context: any): any; - visitAnimateRef(node: AnimationAnimateRefMetadata, context: any): any; - visitQuery(node: AnimationQueryMetadata, context: any): any; - visitStagger(node: AnimationStaggerMetadata, context: any): any; + visitTrigger(ast: AnimationTriggerMetadata, context: any): any; + visitState(ast: AnimationStateMetadata, context: any): any; + visitTransition(ast: AnimationTransitionMetadata, context: any): any; + visitSequence(ast: AnimationSequenceMetadata, context: any): any; + visitGroup(ast: AnimationGroupMetadata, context: any): any; + visitAnimate(ast: AnimationAnimateMetadata, context: any): any; + visitStyle(ast: AnimationStyleMetadata, context: any): any; + visitKeyframes(ast: AnimationKeyframesSequenceMetadata, context: any): any; + visitReference(ast: AnimationReferenceMetadata, context: any): any; + visitAnimateChild(ast: AnimationAnimateChildMetadata, context: any): any; + visitAnimateRef(ast: AnimationAnimateRefMetadata, context: any): any; + visitQuery(ast: AnimationQueryMetadata, context: any): any; + visitStagger(ast: AnimationStaggerMetadata, context: any): any; +} + +export function visitAnimationNode( + visitor: AnimationDslVisitor, node: AnimationMetadata, context: any) { + switch (node.type) { + case AnimationMetadataType.Trigger: + return visitor.visitTrigger(node as AnimationTriggerMetadata, context); + case AnimationMetadataType.State: + return visitor.visitState(node as AnimationStateMetadata, context); + case AnimationMetadataType.Transition: + return visitor.visitTransition(node as AnimationTransitionMetadata, context); + case AnimationMetadataType.Sequence: + return visitor.visitSequence(node as AnimationSequenceMetadata, context); + case AnimationMetadataType.Group: + return visitor.visitGroup(node as AnimationGroupMetadata, context); + case AnimationMetadataType.Animate: + return visitor.visitAnimate(node as AnimationAnimateMetadata, context); + case AnimationMetadataType.Keyframes: + return visitor.visitKeyframes(node as AnimationKeyframesSequenceMetadata, context); + case AnimationMetadataType.Style: + return visitor.visitStyle(node as AnimationStyleMetadata, context); + case AnimationMetadataType.Reference: + return visitor.visitReference(node as AnimationReferenceMetadata, context); + case AnimationMetadataType.AnimateChild: + return visitor.visitAnimateChild(node as AnimationAnimateChildMetadata, context); + case AnimationMetadataType.AnimateRef: + return visitor.visitAnimateRef(node as AnimationAnimateRefMetadata, context); + case AnimationMetadataType.Query: + return visitor.visitQuery(node as AnimationQueryMetadata, context); + case AnimationMetadataType.Stagger: + return visitor.visitStagger(node as AnimationStaggerMetadata, context); + default: + throw new Error(`Unable to resolve animation metadata node #${node.type}`); + } } diff --git a/packages/animations/browser/src/dsl/animation_timeline_builder.ts b/packages/animations/browser/src/dsl/animation_timeline_builder.ts index 5bfedae0f5..51cd604c22 100644 --- a/packages/animations/browser/src/dsl/animation_timeline_builder.ts +++ b/packages/animations/browser/src/dsl/animation_timeline_builder.ts @@ -5,10 +5,10 @@ * 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 */ -import {AUTO_STYLE, AnimateChildOptions, AnimateTimings, AnimationMetadataType, AnimationOptions, AnimationQueryOptions, ɵPRE_STYLE as PRE_STYLE, ɵStyleData} from '@angular/animations'; +import {AUTO_STYLE, AnimateChildOptions, AnimateTimings, AnimationOptions, AnimationQueryOptions, ɵPRE_STYLE as PRE_STYLE, ɵStyleData} from '@angular/animations'; import {AnimationDriver} from '../render/animation_driver'; -import {copyObj, copyStyles, interpolateParams, iteratorToArray, resolveTiming, resolveTimingValue, visitDslNode} from '../util'; +import {copyObj, copyStyles, interpolateParams, iteratorToArray, resolveTiming, resolveTimingValue} from '../util'; import {AnimateAst, AnimateChildAst, AnimateRefAst, Ast, AstVisitor, DynamicTimingAst, GroupAst, KeyframesAst, QueryAst, ReferenceAst, SequenceAst, StaggerAst, StateAst, StyleAst, TimingAst, TransitionAst, TriggerAst} from './animation_ast'; import {AnimationTimelineInstruction, createTimelineInstruction} from './animation_timeline_instruction'; @@ -101,8 +101,8 @@ const ONE_FRAME_IN_MILLISECONDS = 1; * the `AnimationValidatorVisitor` code. */ export function buildAnimationTimelines( - driver: AnimationDriver, rootElement: any, ast: Ast, - startingStyles: ɵStyleData = {}, finalStyles: ɵStyleData = {}, options: AnimationOptions, + driver: AnimationDriver, rootElement: any, ast: Ast, startingStyles: ɵStyleData = {}, + finalStyles: ɵStyleData = {}, options: AnimationOptions, subInstructions?: ElementInstructionMap, errors: any[] = []): AnimationTimelineInstruction[] { return new AnimationTimelineBuilderVisitor().buildKeyframes( driver, rootElement, ast, startingStyles, finalStyles, options, subInstructions, errors); @@ -110,15 +110,15 @@ export function buildAnimationTimelines( export class AnimationTimelineBuilderVisitor implements AstVisitor { buildKeyframes( - driver: AnimationDriver, rootElement: any, ast: Ast, - startingStyles: ɵStyleData, finalStyles: ɵStyleData, options: AnimationOptions, - subInstructions?: ElementInstructionMap, errors: any[] = []): AnimationTimelineInstruction[] { + driver: AnimationDriver, rootElement: any, ast: Ast, startingStyles: ɵStyleData, + finalStyles: ɵStyleData, options: AnimationOptions, subInstructions?: ElementInstructionMap, + errors: any[] = []): AnimationTimelineInstruction[] { subInstructions = subInstructions || new ElementInstructionMap(); const context = new AnimationTimelineContext(driver, rootElement, subInstructions, errors, []); context.options = options; context.currentTimeline.setStyles([startingStyles], null, context.errors, options); - visitDslNode(this, ast, context); + ast.visit(this, context); // this checks to see if an actual animation happened const timelines = context.timelines.filter(timeline => timeline.containsAnimation()); @@ -193,7 +193,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { visitReference(ast: ReferenceAst, context: AnimationTimelineContext) { context.updateOptions(ast.options, true); - visitDslNode(this, ast.animation, context); + ast.animation.visit(this, context); context.previousNode = ast; } @@ -207,7 +207,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { ctx.transformIntoNewTimeline(); if (options.delay != null) { - if (ctx.previousNode.type == AnimationMetadataType.Style) { + if (ctx.previousNode instanceof StyleAst) { ctx.currentTimeline.snapshotCurrentStyles(); ctx.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; } @@ -218,7 +218,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { } if (ast.steps.length) { - ast.steps.forEach(s => visitDslNode(this, s, ctx)); + ast.steps.forEach(s => s.visit(this, ctx)); // this is here just incase the inner steps only contain or end with a style() call ctx.currentTimeline.applyStylesToKeyframe(); @@ -245,7 +245,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { innerContext.delayNextStep(delay); } - visitDslNode(this, s, innerContext); + s.visit(this, innerContext); furthestTime = Math.max(furthestTime, innerContext.currentTimeline.currentTime); innerTimelines.push(innerContext.currentTimeline); }); @@ -259,19 +259,19 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { context.previousNode = ast; } - private _visitTiming(ast: TimingAst, context: AnimationTimelineContext): AnimateTimings { - if ((ast as DynamicTimingAst).dynamic) { - const strValue = (ast as DynamicTimingAst).strValue; - const timingValue = - context.params ? interpolateParams(strValue, context.params, context.errors) : strValue; - return resolveTiming(timingValue, context.errors); + visitTiming(ast: TimingAst, context: AnimationTimelineContext): AnimateTimings { + if (ast instanceof DynamicTimingAst) { + const strValue = context.params ? + interpolateParams(ast.value, context.params, context.errors) : + ast.value.toString(); + return resolveTiming(strValue, context.errors); } else { return {duration: ast.duration, delay: ast.delay, easing: ast.easing}; } } visitAnimate(ast: AnimateAst, context: AnimationTimelineContext) { - const timings = context.currentAnimateTimings = this._visitTiming(ast.timings, context); + const timings = context.currentAnimateTimings = this.visitTiming(ast.timings, context); const timeline = context.currentTimeline; if (timings.delay) { context.incrementTime(timings.delay); @@ -279,7 +279,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { } const style = ast.style; - if (style.type == AnimationMetadataType.Keyframes) { + if (style instanceof KeyframesAst) { this.visitKeyframes(style, context); } else { context.incrementTime(timings.duration); @@ -343,7 +343,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { const options = (ast.options || {}) as AnimationQueryOptions; const delay = options.delay ? resolveTimingValue(options.delay) : 0; - if (delay && (context.previousNode.type === AnimationMetadataType.Style || + if (delay && (context.previousNode instanceof StyleAst || (startTime == 0 && context.currentTimeline.getCurrentStyleProperties().length))) { context.currentTimeline.snapshotCurrentStyles(); context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; @@ -368,7 +368,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { sameElementTimeline = innerContext.currentTimeline; } - visitDslNode(this, ast.animation, innerContext); + ast.animation.visit(this, innerContext); // this is here just incase the inner steps only contain or end // with a style() call (which is here to signal that this is a preparatory @@ -415,7 +415,7 @@ export class AnimationTimelineBuilderVisitor implements AstVisitor { } const startingTime = timeline.currentTime; - visitDslNode(this, ast.animation, context); + ast.animation.visit(this, context); context.previousNode = ast; // time = duration + delay @@ -431,12 +431,12 @@ export declare type StyleAtTime = { time: number; value: string | number; }; -const DEFAULT_NOOP_PREVIOUS_NODE = >{}; +const DEFAULT_NOOP_PREVIOUS_NODE = {}; export class AnimationTimelineContext { public parentContext: AnimationTimelineContext|null = null; public currentTimeline: TimelineBuilder; public currentAnimateTimings: AnimateTimings|null = null; - public previousNode: Ast = DEFAULT_NOOP_PREVIOUS_NODE; + public previousNode: Ast = DEFAULT_NOOP_PREVIOUS_NODE; public subContextCount = 0; public options: AnimationOptions = {}; public currentQueryIndex: number = 0; @@ -489,7 +489,7 @@ export class AnimationTimelineContext { const oldParams = this.options.params; if (oldParams) { const params: {[name: string]: any} = options['params'] = {}; - Object.keys(oldParams).forEach(name => { params[name] = oldParams[name]; }); + Object.keys(this.options.params).forEach(name => { params[name] = oldParams[name]; }); } } return options; diff --git a/packages/animations/browser/src/dsl/animation_trigger.ts b/packages/animations/browser/src/dsl/animation_trigger.ts index b52ff0b5dc..9d820e25c2 100644 --- a/packages/animations/browser/src/dsl/animation_trigger.ts +++ b/packages/animations/browser/src/dsl/animation_trigger.ts @@ -5,7 +5,7 @@ * 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 */ -import {AnimationMetadataType, ɵStyleData} from '@angular/animations'; +import {ɵStyleData} from '@angular/animations'; import {copyStyles, interpolateParams} from '../util'; @@ -13,7 +13,6 @@ import {SequenceAst, StyleAst, TransitionAst, TriggerAst} from './animation_ast' import {AnimationStateStyles, AnimationTransitionFactory} from './animation_transition_factory'; - /** * @experimental Animation support is experimental. */ @@ -61,15 +60,8 @@ function createFallbackTransition( triggerName: string, states: {[stateName: string]: AnimationStateStyles}): AnimationTransitionFactory { const matchers = [(fromState: any, toState: any) => true]; - const animation: SequenceAst = {type: AnimationMetadataType.Sequence, steps: [], options: null}; - const transition: TransitionAst = { - type: AnimationMetadataType.Transition, - animation, - matchers, - options: null, - queryCount: 0, - depCount: 0 - }; + const animation = new SequenceAst([]); + const transition = new TransitionAst(matchers, animation); return new AnimationTransitionFactory(triggerName, transition, states); } diff --git a/packages/animations/browser/src/render/timeline_animation_engine.ts b/packages/animations/browser/src/render/timeline_animation_engine.ts index 49fa5bc39c..b217b9f1cf 100644 --- a/packages/animations/browser/src/render/timeline_animation_engine.ts +++ b/packages/animations/browser/src/render/timeline_animation_engine.ts @@ -5,7 +5,7 @@ * 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 */ -import {AUTO_STYLE, AnimationMetadata, AnimationMetadataType, AnimationOptions, AnimationPlayer, ɵStyleData} from '@angular/animations'; +import {AUTO_STYLE, AnimationMetadata, AnimationOptions, AnimationPlayer, ɵStyleData} from '@angular/animations'; import {Ast} from '../dsl/animation_ast'; import {buildAnimationAst} from '../dsl/animation_ast_builder'; @@ -20,7 +20,7 @@ import {getOrSetAsInMap, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, const EMPTY_INSTRUCTION_MAP = new ElementInstructionMap(); export class TimelineAnimationEngine { - private _animations: {[id: string]: Ast} = {}; + private _animations: {[id: string]: Ast} = {}; private _playersById: {[id: string]: AnimationPlayer} = {}; public players: AnimationPlayer[] = []; diff --git a/packages/animations/browser/src/util.ts b/packages/animations/browser/src/util.ts index 20fd973191..dbdfa4f213 100644 --- a/packages/animations/browser/src/util.ts +++ b/packages/animations/browser/src/util.ts @@ -5,9 +5,7 @@ * 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 */ -import {AnimateTimings, AnimationMetadata, AnimationMetadataType, AnimationOptions, sequence, ɵStyleData} from '@angular/animations'; -import {Ast as AnimationAst, AstVisitor as AnimationAstVisitor} from './dsl/animation_ast'; -import {AnimationDslVisitor} from './dsl/animation_dsl_visitor'; +import {AnimateTimings, AnimationMetadata, AnimationOptions, sequence, ɵStyleData} from '@angular/animations'; export const ONE_SECOND = 1000; @@ -234,40 +232,3 @@ export function dashCaseToCamelCase(input: string): string { export function allowPreviousPlayerStylesMerge(duration: number, delay: number) { return duration === 0 || delay === 0; } - -export function visitDslNode( - visitor: AnimationDslVisitor, node: AnimationMetadata, context: any): any; -export function visitDslNode( - visitor: AnimationAstVisitor, node: AnimationAst, context: any): any; -export function visitDslNode(visitor: any, node: any, context: any): any { - switch (node.type) { - case AnimationMetadataType.Trigger: - return visitor.visitTrigger(node, context); - case AnimationMetadataType.State: - return visitor.visitState(node, context); - case AnimationMetadataType.Transition: - return visitor.visitTransition(node, context); - case AnimationMetadataType.Sequence: - return visitor.visitSequence(node, context); - case AnimationMetadataType.Group: - return visitor.visitGroup(node, context); - case AnimationMetadataType.Animate: - return visitor.visitAnimate(node, context); - case AnimationMetadataType.Keyframes: - return visitor.visitKeyframes(node, context); - case AnimationMetadataType.Style: - return visitor.visitStyle(node, context); - case AnimationMetadataType.Reference: - return visitor.visitReference(node, context); - case AnimationMetadataType.AnimateChild: - return visitor.visitAnimateChild(node, context); - case AnimationMetadataType.AnimateRef: - return visitor.visitAnimateRef(node, context); - case AnimationMetadataType.Query: - return visitor.visitQuery(node, context); - case AnimationMetadataType.Stagger: - return visitor.visitStagger(node, context); - default: - throw new Error(`Unable to resolve animation metadata node #${node.type}`); - } -}