Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions goldens/public-api/animations/animations.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ interface AnimationEvent_2 {
totalTime: number;
triggerName: string;
}

export { AnimationEvent_2 as AnimationEvent }

// @public
Expand Down Expand Up @@ -278,7 +277,6 @@ export function trigger(name: string, definitions: AnimationMetadata[]): Animati
// @public
export function useAnimation(animation: AnimationReferenceMetadata, options?: AnimationOptions | null): AnimationAnimateRefMetadata;


// (No @packageDocumentation comment for this package)

```
4 changes: 1 addition & 3 deletions goldens/public-api/animations/browser/browser.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
// @public (undocumented)
export abstract class AnimationDriver {
// (undocumented)
abstract animate(element: any, keyframes: {
[key: string]: string | number;
}[], duration: number, delay: number, easing?: string | null, previousPlayers?: any[], scrubberAccessRequested?: boolean): any;
abstract animate(element: any, keyframes: Array<Map<string, string | number>>, duration: number, delay: number, easing?: string | null, previousPlayers?: any[], scrubberAccessRequested?: boolean): any;
// (undocumented)
abstract computeStyle(element: any, prop: string, defaultValue?: string): string;
// (undocumented)
Expand Down
20 changes: 6 additions & 14 deletions goldens/public-api/animations/browser/testing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
import { AnimationDriver } from '@angular/animations/browser';
import { AnimationPlayer } from '@angular/animations';
import { NoopAnimationPlayer } from '@angular/animations';
import { ɵStyleData } from '@angular/animations';
import { ɵStyleDataMap } from '@angular/animations';

// @public (undocumented)
export class MockAnimationDriver implements AnimationDriver {
// (undocumented)
animate(element: any, keyframes: {
[key: string]: string | number;
}[], duration: number, delay: number, easing: string, previousPlayers?: any[]): MockAnimationPlayer;
animate(element: any, keyframes: Array<ɵStyleDataMap>, duration: number, delay: number, easing: string, previousPlayers?: any[]): MockAnimationPlayer;
// (undocumented)
computeStyle(element: any, prop: string, defaultValue?: string): string;
// (undocumented)
Expand All @@ -31,13 +29,11 @@ export class MockAnimationDriver implements AnimationDriver {

// @public (undocumented)
export class MockAnimationPlayer extends NoopAnimationPlayer {
constructor(element: any, keyframes: {
[key: string]: string | number;
}[], duration: number, delay: number, easing: string, previousPlayers: any[]);
constructor(element: any, keyframes: Array<ɵStyleDataMap>, duration: number, delay: number, easing: string, previousPlayers: any[]);
// (undocumented)
beforeDestroy(): void;
// (undocumented)
currentSnapshot: ɵStyleData;
currentSnapshot: ɵStyleDataMap;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I like the StyleData as a symbol name a bit more. The Map part leaks the implementation detail into the name (for ex. we'd need to change the name if we later decide to use an array).

This is a very minor thing, not a blocker for this PR :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually agree, but we still use the old symbol. We'd need a new name. I'll think on it for a potential refactor after this PR.

// (undocumented)
delay: number;
// (undocumented)
Expand All @@ -53,17 +49,13 @@ export class MockAnimationPlayer extends NoopAnimationPlayer {
// (undocumented)
hasStarted(): boolean;
// (undocumented)
keyframes: {
[key: string]: string | number;
}[];
keyframes: Array<ɵStyleDataMap>;
// (undocumented)
play(): void;
// (undocumented)
previousPlayers: any[];
// (undocumented)
previousStyles: {
[key: string]: string | number;
};
previousStyles: ɵStyleDataMap;
// (undocumented)
reset(): void;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/animations/browser/src/dsl/animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, AnimationMetadataType, AnimationOptions, ɵStyleDataMap} from '@angular/animations';

import {AnimationDriver} from '../render/animation_driver';
import {ENTER_CLASSNAME, LEAVE_CLASSNAME, normalizeStyles} from '../util';
Expand All @@ -29,13 +29,13 @@ export class Animation {
}

buildTimelines(
element: any, startingStyles: ɵStyleData|ɵStyleData[],
destinationStyles: ɵStyleData|ɵStyleData[], options: AnimationOptions,
element: any, startingStyles: ɵStyleDataMap|Array<ɵStyleDataMap>,
destinationStyles: ɵStyleDataMap|Array<ɵStyleDataMap>, options: AnimationOptions,
subInstructions?: ElementInstructionMap): AnimationTimelineInstruction[] {
const start = Array.isArray(startingStyles) ? normalizeStyles(startingStyles) :
<ɵStyleData>startingStyles;
<ɵStyleDataMap>startingStyles;
const dest = Array.isArray(destinationStyles) ? normalizeStyles(destinationStyles) :
<ɵStyleData>destinationStyles;
<ɵStyleDataMap>destinationStyles;
const errors: any = [];
subInstructions = subInstructions || new ElementInstructionMap();
const result = buildAnimationTimelines(
Expand Down
8 changes: 4 additions & 4 deletions packages/animations/browser/src/dsl/animation_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, AnimationMetadataType, AnimationOptions, ɵStyleDataMap} from '@angular/animations';

const EMPTY_ANIMATION_OPTIONS: AnimationOptions = {};

Expand Down Expand Up @@ -46,8 +46,8 @@ export interface StateAst extends Ast<AnimationMetadataType.State> {
}

export interface TransitionAst extends Ast<AnimationMetadataType.Transition> {
matchers: ((fromState: string, toState: string, element: any, params: {[key: string]:
any}) => boolean)[];
matchers: Array<(
(fromState: string, toState: string, element: any, params: {[key: string]: any}) => boolean)>;
animation: Ast<AnimationMetadataType>;
queryCount: number;
depCount: number;
Expand All @@ -67,7 +67,7 @@ export interface AnimateAst extends Ast<AnimationMetadataType.Animate> {
}

export interface StyleAst extends Ast<AnimationMetadataType.Style> {
styles: (ɵStyleData|string)[];
styles: Array<(ɵStyleDataMap | string)>;
easing: string|null;
offset: number|null;
containsDynamicStyles: boolean;
Expand Down
102 changes: 48 additions & 54 deletions packages/animations/browser/src/dsl/animation_ast_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* 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, AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationMetadataType, AnimationOptions, AnimationQueryMetadata, AnimationQueryOptions, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata, AUTO_STYLE, style, ɵStyleData} from '@angular/animations';
import {AnimateTimings, AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationMetadataType, AnimationOptions, AnimationQueryMetadata, AnimationQueryOptions, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata, AUTO_STYLE, style, ɵStyleDataMap} from '@angular/animations';

import {AnimationDriver} from '../render/animation_driver';
import {getOrSetAsInMap} from '../render/shared';
import {copyObj, extractStyleParams, iteratorToArray, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, normalizeAnimationEntry, resolveTiming, SUBSTITUTION_EXPR_START, validateStyleParams, visitDslNode} from '../util';
import {getOrSetDefaultValue} from '../render/shared';
import {convertToMap, copyObj, extractStyleParams, iteratorToArray, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, normalizeAnimationEntry, resolveTiming, SUBSTITUTION_EXPR_START, validateStyleParams, visitDslNode} 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';
Expand Down Expand Up @@ -75,8 +75,8 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {

private _resetContextStyleTimingState(context: AnimationAstBuilderContext) {
context.currentQuerySelector = ROOT_SELECTOR;
context.collectedStyles = {};
context.collectedStyles[ROOT_SELECTOR] = {};
context.collectedStyles = new Map<string, Map<string, StyleTimeTuple>>();
context.collectedStyles.set(ROOT_SELECTOR, new Map());
context.currentTime = 0;
}

Expand Down Expand Up @@ -129,11 +129,10 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {
if (styleAst.containsDynamicStyles) {
const missingSubs = new Set<string>();
const params = astParams || {};
styleAst.styles.forEach(value => {
if (isObject(value)) {
const stylesObj = value as any;
Object.keys(stylesObj).forEach(prop => {
extractStyleParams(stylesObj[prop]).forEach(sub => {
styleAst.styles.forEach(style => {
if (style instanceof Map) {
style.forEach(value => {
extractStyleParams(value).forEach(sub => {
if (!params.hasOwnProperty(sub)) {
missingSubs.add(sub);
}
Expand Down Expand Up @@ -206,9 +205,9 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {
AnimateAst {
const timingAst = constructTimingAst(metadata.timings, context.errors);
context.currentAnimateTimings = timingAst;

let styleAst: StyleAst|KeyframesAst;
let styleMetadata: AnimationMetadata = metadata.styles ? metadata.styles : style({});
let styleMetadata: AnimationStyleMetadata|AnimationKeyframesSequenceMetadata =
metadata.styles ? metadata.styles : style({});
if (styleMetadata.type == AnimationMetadataType.Keyframes) {
styleAst = this.visitKeyframes(styleMetadata as AnimationKeyframesSequenceMetadata, context);
} else {
Expand Down Expand Up @@ -245,37 +244,32 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {

private _makeStyleAst(metadata: AnimationStyleMetadata, context: AnimationAstBuilderContext):
StyleAst {
const styles: (ɵStyleData|string)[] = [];
if (Array.isArray(metadata.styles)) {
(metadata.styles as (ɵStyleData | string)[]).forEach(styleTuple => {
if (typeof styleTuple == 'string') {
if (styleTuple == AUTO_STYLE) {
styles.push(styleTuple);
} else {
context.errors.push(`The provided style string value ${styleTuple} is not allowed.`);
}
} else {
const styles: Array<(ɵStyleDataMap | string)> = [];
const metadataStyles = Array.isArray(metadata.styles) ? metadata.styles : [metadata.styles];

for (let styleTuple of metadataStyles) {
if (typeof styleTuple === 'string') {
if (styleTuple === AUTO_STYLE) {
styles.push(styleTuple);
} else {
context.errors.push(`The provided style string value ${styleTuple} is not allowed.`);
}
});
} else {
styles.push(metadata.styles);
} else {
styles.push(convertToMap(styleTuple));
}
}

let containsDynamicStyles = false;
let collectedEasing: string|null = null;
styles.forEach(styleData => {
if (isObject(styleData)) {
const styleMap = styleData as ɵStyleData;
const easing = styleMap['easing'];
if (easing) {
collectedEasing = easing as string;
delete styleMap['easing'];
if (styleData instanceof Map) {
if (styleData.has('easing')) {
collectedEasing = styleData.get('easing') as string;
styleData.delete('easing');
}
if (!containsDynamicStyles) {
for (let prop in styleMap) {
const value = styleMap[prop];
if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
for (let value of styleData.values()) {
if (value!.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
containsDynamicStyles = true;
break;
}
Expand Down Expand Up @@ -303,17 +297,19 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {
}

ast.styles.forEach(tuple => {
if (typeof tuple == 'string') return;
if (typeof tuple === 'string') return;

Object.keys(tuple).forEach(prop => {
tuple.forEach((value, prop) => {
if (!this._driver.validateStyleProperty(prop)) {
context.errors.push(`The provided animation property "${
prop}" is not a supported CSS property for animations`);
Comment on lines 304 to 305
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jessicajaniuk In PR #44729 I am adding a delete tuple[prop] here, after the PR has been merged please remember to update it to tuple.delete(prop) whenever you can 🙂

Original discussion: https://github.com/angular/angular/pull/44729/files#r787206809

return;
}

const collectedStyles = context.collectedStyles[context.currentQuerySelector!];
const collectedEntry = collectedStyles[prop];
// This is guaranteed to have a defined Map at this querySelector location making it
// safe to add the assertion here. It is set as a default empty map in prior methods.
const collectedStyles = context.collectedStyles.get(context.currentQuerySelector!)!;
const collectedEntry = collectedStyles.get(prop);
let updateCollectedStyle = true;
if (collectedEntry) {
if (startTime != endTime && startTime >= collectedEntry.startTime &&
Expand All @@ -333,11 +329,11 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {
}

if (updateCollectedStyle) {
collectedStyles[prop] = {startTime, endTime};
collectedStyles.set(prop, {startTime, endTime});
}

if (context.options) {
validateStyleParams(tuple[prop], context.options, context.errors);
validateStyleParams(value, context.options, context.errors);
}
});
});
Expand Down Expand Up @@ -445,7 +441,7 @@ export class AnimationAstBuilderVisitor implements AnimationDslVisitor {
const [selector, includeSelf] = normalizeSelector(metadata.selector);
context.currentQuerySelector =
parentSelector.length ? (parentSelector + ' ' + selector) : selector;
getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {});
getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map());

const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
context.currentQuery = null;
Expand Down Expand Up @@ -513,36 +509,34 @@ export class AnimationAstBuilderContext {
public currentQuerySelector: string|null = null;
public currentAnimateTimings: TimingAst|null = null;
public currentTime: number = 0;
public collectedStyles: {[selectorName: string]: {[propName: string]: StyleTimeTuple}} = {};
public collectedStyles = new Map<string, Map<string, StyleTimeTuple>>();
public options: AnimationOptions|null = null;
constructor(public errors: string[]) {}
}

function consumeOffset(styles: ɵStyleData|string|(ɵStyleData | string)[]): number|null {
type OffsetStyles = string|ɵStyleDataMap;

function consumeOffset(styles: OffsetStyles|Array<OffsetStyles>): number|null {
if (typeof styles == 'string') return null;

let offset: number|null = null;

if (Array.isArray(styles)) {
styles.forEach(styleTuple => {
if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) {
const obj = styleTuple as ɵStyleData;
offset = parseFloat(obj['offset'] as string);
delete obj['offset'];
if (styleTuple instanceof Map && styleTuple.has('offset')) {
const obj = styleTuple as ɵStyleDataMap;
offset = parseFloat(obj.get('offset') as string);
obj.delete('offset');
}
});
} else if (isObject(styles) && styles.hasOwnProperty('offset')) {
} else if (styles instanceof Map && styles.has('offset')) {
const obj = styles;
offset = parseFloat(obj['offset'] as string);
delete obj['offset'];
offset = parseFloat(obj.get('offset') as string);
obj.delete('offset');
}
return offset;
}

function isObject(value: any): boolean {
return !Array.isArray(value) && typeof value == 'object';
}

function constructTimingAst(value: string|number|AnimateTimings, errors: string[]) {
let timings: AnimateTimings|null = null;
if (value.hasOwnProperty('duration')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationQueryMetadata, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata} from '@angular/animations';
import {AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationQueryMetadata, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata} from '@angular/animations';

export interface AnimationDslVisitor {
visitTrigger(node: AnimationTriggerMetadata, context: any): any;
Expand Down
Loading