feat(animations): provide support for offline compilation
This commit is contained in:
34
modules/@angular/compiler-cli/integrationtest/src/animate.ts
Normal file
34
modules/@angular/compiler-cli/integrationtest/src/animate.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import {Component, trigger, state, animate, transition, style} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: "animate-cmp",
|
||||
animations: [
|
||||
trigger('openClose', [
|
||||
state('closed, void',
|
||||
style({ height:"0px", color: "maroon", borderColor: "maroon" })),
|
||||
state('open',
|
||||
style({ height:"*", borderColor:"green", color:"green" })),
|
||||
transition("* => *", animate(500))
|
||||
])
|
||||
],
|
||||
template: `
|
||||
<button (click)="setAsOpen()">Open</button>
|
||||
<button (click)="setAsClosed()">Closed</button>
|
||||
<hr />
|
||||
<div @openClose="stateExpression">
|
||||
Look at this box
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class AnimateCmp {
|
||||
stateExpression:string;
|
||||
constructor() {
|
||||
this.setAsClosed();
|
||||
}
|
||||
setAsOpen() {
|
||||
this.stateExpression = 'open';
|
||||
}
|
||||
setAsClosed() {
|
||||
this.stateExpression = 'closed';
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
require('reflect-metadata');
|
||||
require('@angular/platform-server/src/parse5_adapter.js').Parse5DomAdapter.makeCurrent();
|
||||
require('zone.js/dist/zone-node.js');
|
||||
require('zone.js/dist/long-stack-trace-zone.js');
|
||||
|
||||
import {AnimateCmpNgFactory} from '../src/animate.ngfactory';
|
||||
import {AUTO_STYLE, ReflectiveInjector, DebugElement, getDebugNode} from '@angular/core';
|
||||
import {browserPlatform, BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
|
||||
|
||||
describe("template codegen output", () => {
|
||||
it("should apply the animate states to the element", (done) => {
|
||||
const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS,
|
||||
browserPlatform().injector);
|
||||
var comp = AnimateCmpNgFactory.create(appInjector);
|
||||
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
|
||||
|
||||
// the open-close-container is a child of the main container
|
||||
// if the template changes then please update the location below
|
||||
var targetDebugElement = <DebugElement>debugElement.children[3];
|
||||
|
||||
comp.instance.setAsOpen();
|
||||
comp.changeDetectorRef.detectChanges();
|
||||
|
||||
setTimeout(() => {
|
||||
expect(targetDebugElement.styles['height']).toEqual(AUTO_STYLE);
|
||||
expect(targetDebugElement.styles['borderColor']).toEqual('green');
|
||||
expect(targetDebugElement.styles['color']).toEqual('green');
|
||||
|
||||
comp.instance.setAsClosed();
|
||||
comp.changeDetectorRef.detectChanges();
|
||||
|
||||
setTimeout(() => {
|
||||
expect(targetDebugElement.styles['height']).toEqual("0px");
|
||||
expect(targetDebugElement.styles['borderColor']).toEqual('maroon');
|
||||
expect(targetDebugElement.styles['color']).toEqual('maroon');
|
||||
done();
|
||||
}, 0);
|
||||
}, 0);
|
||||
});
|
||||
});
|
@ -19,6 +19,7 @@ export class NodeReflectorHost implements StaticReflectorHost, ImportGenerator {
|
||||
coreDecorators: '@angular/core/src/metadata',
|
||||
diDecorators: '@angular/core/src/di/decorators',
|
||||
diMetadata: '@angular/core/src/di/metadata',
|
||||
animationMetadata: '@angular/core/src/animation/metadata',
|
||||
provider: '@angular/core/src/di/provider'
|
||||
};
|
||||
}
|
||||
|
@ -20,6 +20,14 @@ import {
|
||||
SelfMetadata,
|
||||
SkipSelfMetadata,
|
||||
InjectMetadata,
|
||||
trigger,
|
||||
state,
|
||||
transition,
|
||||
sequence,
|
||||
group,
|
||||
animate,
|
||||
style,
|
||||
keyframes
|
||||
} from "@angular/core";
|
||||
import {ReflectorReader} from "./core_private";
|
||||
|
||||
@ -50,7 +58,7 @@ export interface StaticReflectorHost {
|
||||
getStaticSymbol(declarationFile: string, name: string): StaticSymbol;
|
||||
|
||||
angularImportLocations():
|
||||
{coreDecorators: string, diDecorators: string, diMetadata: string, provider: string};
|
||||
{coreDecorators: string, diDecorators: string, diMetadata: string, animationMetadata: string, provider: string};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,8 +189,19 @@ export class StaticReflector implements ReflectorReader {
|
||||
});
|
||||
}
|
||||
|
||||
private registerFunction(type: StaticSymbol, fn: any): void {
|
||||
this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => {
|
||||
let argValues: any[] = [];
|
||||
args.forEach((arg, index) => {
|
||||
let argValue = this.simplify(context, arg);
|
||||
argValues.push(argValue);
|
||||
});
|
||||
return fn.apply(null, argValues);
|
||||
});
|
||||
}
|
||||
|
||||
private initializeConversionMap(): void {
|
||||
const {coreDecorators, diDecorators, diMetadata, provider} = this.host.angularImportLocations();
|
||||
const {coreDecorators, diDecorators, diMetadata, animationMetadata, provider} = this.host.angularImportLocations();
|
||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(provider, 'Provider'), Provider);
|
||||
|
||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Host'),
|
||||
@ -235,6 +254,15 @@ export class StaticReflector implements ReflectorReader {
|
||||
SkipSelfMetadata);
|
||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'OptionalMetadata'),
|
||||
OptionalMetadata);
|
||||
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'trigger'), trigger);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'state'), state);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'transition'), transition);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'style'), style);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'animate'), animate);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'keyframes'), keyframes);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'sequence'), sequence);
|
||||
this.registerFunction(this.host.findDeclaration(animationMetadata, 'group'), group);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
@ -15,6 +15,8 @@ import {
|
||||
StaticSymbol
|
||||
} from '@angular/compiler-cli/src/static_reflector';
|
||||
|
||||
import {transition, sequence, group, trigger, state, style, animate, keyframes} from '@angular/core';
|
||||
|
||||
describe('StaticReflector', () => {
|
||||
let noContext = new StaticSymbol('', '');
|
||||
let host: StaticReflectorHost;
|
||||
@ -62,6 +64,19 @@ describe('StaticReflector', () => {
|
||||
expect(annotation.selector).toEqual('my-hero-detail');
|
||||
expect(annotation.directives)
|
||||
.toEqual([[host.findDeclaration('angular2/src/common/directives/ng_for', 'NgFor')]]);
|
||||
expect(annotation.animations).toEqual([
|
||||
trigger("myAnimation", [
|
||||
state("state1", style({ "background": "white" })),
|
||||
transition("* => *", sequence([
|
||||
group([
|
||||
animate("1s 0.5s", keyframes([
|
||||
style({ "background": "blue"}),
|
||||
style({ "background": "red"})
|
||||
]))
|
||||
])
|
||||
]))
|
||||
])
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw and exception for unsupported metadata versions', () => {
|
||||
@ -252,6 +267,7 @@ class MockReflectorHost implements StaticReflectorHost {
|
||||
coreDecorators: 'angular2/src/core/metadata',
|
||||
diDecorators: 'angular2/src/core/di/decorators',
|
||||
diMetadata: 'angular2/src/core/di/metadata',
|
||||
animationMetadata: 'angular2/src/core/animation/metadata',
|
||||
provider: 'angular2/src/core/di/provider'
|
||||
};
|
||||
}
|
||||
@ -405,11 +421,100 @@ class MockReflectorHost implements StaticReflectorHost {
|
||||
"name": "FORM_DIRECTIVES",
|
||||
"module": "angular2/src/common/forms/directives"
|
||||
}
|
||||
],
|
||||
"animations": [{
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic": "reference",
|
||||
"name": "trigger",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments": [
|
||||
"myAnimation",
|
||||
[{ "__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic": "reference",
|
||||
"name": "state",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments": [
|
||||
"state1",
|
||||
{ "__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic": "reference",
|
||||
"name": "style",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments": [
|
||||
{ "background":"white" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"transition",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments": [
|
||||
"* => *",
|
||||
{
|
||||
"__symbolic":"call",
|
||||
"expression":{
|
||||
"__symbolic":"reference",
|
||||
"name":"sequence",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[[{ "__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"group",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[[{
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"animate",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[
|
||||
"1s 0.5s",
|
||||
{ "__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"keyframes",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[[{ "__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"style",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[ { "background": "blue"} ]
|
||||
}, {
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic":"reference",
|
||||
"name":"style",
|
||||
"module": "angular2/src/core/animation/metadata"
|
||||
},
|
||||
"arguments":[ { "background": "red"} ]
|
||||
}]]
|
||||
}
|
||||
]
|
||||
}]]
|
||||
}]]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}]
|
||||
}]
|
||||
}],
|
||||
"members": {
|
||||
"hero": [
|
||||
{
|
||||
|
Reference in New Issue
Block a user