Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit594389f

Browse files
feat(core): add enter and leave animation instructions
This adds the instructions to support enter and leave animations on nodes.
1 parentfc8247d commit594389f

File tree

21 files changed

+1235
-19
lines changed

21 files changed

+1235
-19
lines changed

‎goldens/public-api/core/index.api.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ export interface AfterViewInit {
8181
// @public
8282
exportconst ANIMATION_MODULE_TYPE:InjectionToken<"NoopAnimations"|"BrowserAnimations">;
8383

84+
// @public (undocumented)
85+
exporttypeAnimationCallbackEvent= {
86+
target:Element;
87+
animationComplete:Function;
88+
};
89+
90+
// @public (undocumented)
91+
exporttypeAnimationFunction= (event:AnimationCallbackEvent)=>void;
92+
93+
// @public
94+
exportconst ANIMATIONS_DISABLED:InjectionToken<boolean>;
95+
8496
// @public
8597
exportconst APP_BOOTSTRAP_LISTENER:InjectionToken<readonly ((compRef:ComponentRef<any>)=>void)[]>;
8698

@@ -667,6 +679,25 @@ export class ElementRef<T = any> {
667679
nativeElement:T;
668680
}
669681

682+
// @public
683+
exportclassElementRegistry {
684+
// (undocumented)
685+
add(el:Element,value:string|string[]|Function,animateWrapperFn:AnimationClassFunction):void;
686+
addCallback(el:Element,value:AnimationFunction,animateWrapperFn:AnimationEventFunction):void;
687+
addClasses(details:AnimationDetails,classes:string|string[]):void;
688+
addResolver(details:AnimationDetails,resolver:Function):void;
689+
// (undocumented)
690+
animate(el:Element,removeFn:Function):void;
691+
// (undocumented)
692+
has(el:Element):boolean;
693+
// (undocumented)
694+
remove(el:Element):void;
695+
// (undocumented)
696+
static ɵfac: ɵɵFactoryDeclaration<ElementRegistry,never>;
697+
// (undocumented)
698+
static ɵprov: ɵɵInjectableDeclaration<ElementRegistry>;
699+
}
700+
670701
// @public
671702
exportabstractclassEmbeddedViewRef<C>extendsViewRef {
672703
abstract context:C;

‎packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ describe('type check blocks', () => {
2121
expect(tcb('{{hello}} {{world}}')).toContain('"" + (((this).hello)) + (((this).world));');
2222
});
2323

24-
it('should generate an animationin function call',()=>{
25-
constTEMPLATE='<p (animate.enter)="animateFn($event)"></p>';
24+
it('should generate an animationleave function call',()=>{
25+
constTEMPLATE='<p (animate.leave)="animateFn($event)"></p>';
2626
constresults=tcb(TEMPLATE);
2727
expect(results).toContain(
2828
'($event: i1.AnimationCallbackEvent): any => { (this).animateFn($event); };',

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/animations/GOLDEN_PARTIAL.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
148148
/****************************************************************************************************
149149
* PARTIAL FILE: animate_enter_with_event_listener.d.ts
150150
****************************************************************************************************/
151+
import{AnimationCallbackEvent}from'@angular/core';
151152
import*asi0from"@angular/core";
152153
exportdeclareclassMyComponent{
153-
slideFn(event:any):void;
154+
slideFn(event:AnimationCallbackEvent):void;
154155
staticɵfac:i0.ɵɵFactoryDeclaration<MyComponent,never>;
155156
staticɵcmp:i0.ɵɵComponentDeclaration<MyComponent,"my-component",never,{},{},never,never,true,never>;
156157
}
@@ -258,9 +259,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
258259
/****************************************************************************************************
259260
* PARTIAL FILE: animate_leave_with_event_listener.d.ts
260261
****************************************************************************************************/
262+
import{AnimationCallbackEvent}from'@angular/core';
261263
import*asi0from"@angular/core";
262264
exportdeclareclassMyComponent{
263-
fadeFn(event:any):void;
265+
fadeFn(event:AnimationCallbackEvent):void;
264266
staticɵfac:i0.ɵɵFactoryDeclaration<MyComponent,never>;
265267
staticɵcmp:i0.ɵɵComponentDeclaration<MyComponent,"my-component",never,{},{},never,never,true,never>;
266268
}

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/animations/animate_enter_with_event_listener.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{Component}from'@angular/core';
1+
import{Component,AnimationCallbackEvent}from'@angular/core';
22

33
@Component({
44
selector:'my-component',
@@ -9,7 +9,7 @@ import {Component} from '@angular/core';
99
`,
1010
})
1111
exportclassMyComponent{
12-
slideFn(event:any){
12+
slideFn(event:AnimationCallbackEvent){
1313
event.target.classList.add('slide-in');
1414
}
1515
}

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/animations/animate_leave_with_event_listener.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{Component}from'@angular/core';
1+
import{Component,AnimationCallbackEvent}from'@angular/core';
22

33
@Component({
44
selector:'my-component',
@@ -9,7 +9,7 @@ import {Component} from '@angular/core';
99
`,
1010
})
1111
exportclassMyComponent{
12-
fadeFn(event:any){
12+
fadeFn(event:AnimationCallbackEvent){
1313
event.target.classList.add('fade-out');
1414
}
1515
}

‎packages/core/src/animation.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
*@license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import{Injectable}from'./di';
10+
11+
exporttypeAnimationCallbackEvent={target:Element;animationComplete:Function};
12+
exporttypeAnimationFunction=(event:AnimationCallbackEvent)=>void;
13+
exporttypeAnimationEventFunction=(
14+
el:Element,
15+
value:AnimationFunction,
16+
)=>AnimationRemoveFunction;
17+
exporttypeAnimationClassFunction=(
18+
el:Element,
19+
value:Set<string>|null,
20+
resolvers:Function[]|undefined,
21+
)=>AnimationRemoveFunction;
22+
exporttypeAnimationRemoveFunction=(removeFn:VoidFunction)=>void;
23+
24+
exportinterfaceLongestAnimation{
25+
animationName:string|undefined;
26+
propertyName:string|undefined;
27+
duration:number;
28+
}
29+
30+
exportinterfaceAnimationDetails{
31+
classes:Set<string>|null;
32+
classFns?:Function[];
33+
animateFn:AnimationRemoveFunction;
34+
}
35+
36+
/**
37+
* Registers elements for delayed removal action for animation in the case
38+
* that `animate.leave` is used. This stores the target element and any
39+
* classes, class resolvers, and callback functions that may be needed
40+
* to apply the removal animation, and then stashes the actual element
41+
* removal function from the dom renderer to be called after the
42+
* animation is finished.
43+
*/
44+
@Injectable({providedIn:'root'})
45+
exportclassElementRegistry{
46+
privateoutElements=newMap<Element,AnimationDetails>();
47+
48+
remove(el:Element):void{
49+
this.outElements.delete(el);
50+
}
51+
52+
/** Used when animate.leave is only applying classes */
53+
addClasses(details:AnimationDetails,classes:string|string[]):void{
54+
constclassList=typeofclasses==='string' ?[classes] :classes;
55+
for(letklassofclassList){
56+
details.classes?.add(klass);
57+
}
58+
}
59+
60+
/** Used when animate.leave is applying classes via a bound attribute
61+
* which requires resolving the binding function at the right time
62+
* to get the proper class list. There may be multiple resolvers due
63+
* to composition via host bindings.
64+
*/
65+
addResolver(details:AnimationDetails,resolver:Function):void{
66+
if(!details.classFns){
67+
details.classFns=[resolver];
68+
}else{
69+
details.classFns?.push(resolver);
70+
}
71+
}
72+
73+
/** Used when `animate.leave` is using the function signature and will have a
74+
* callback function, rather than a list of classes.
75+
*/
76+
addCallback(
77+
el:Element,
78+
value:AnimationFunction,
79+
animateWrapperFn:AnimationEventFunction,
80+
):void{
81+
constdetails=this.outElements.get(el)??{classes:null,animateFn:()=>{}};
82+
details.animateFn=animateWrapperFn(el,value);
83+
this.outElements.set(el,details);
84+
}
85+
86+
// Used when `animate.leave` is using classes.
87+
add(el:Element,value:string|string[]|Function,animateWrapperFn:AnimationClassFunction){
88+
constdetails=this.outElements.get(el)??{
89+
classes:newSet<string>(),
90+
animateFn:():void=>{},
91+
};
92+
if(typeofvalue==='function'){
93+
this.addResolver(details,value);
94+
}else{
95+
this.addClasses(details,value);
96+
}
97+
details.animateFn=animateWrapperFn(el,details.classes,details.classFns);
98+
this.outElements.set(el,details);
99+
}
100+
101+
has(el:Element):boolean{
102+
returnthis.outElements.has(el);
103+
}
104+
105+
// This is called by the dom renderer to actually initiate the animation
106+
// using the animateFn stored in the registry. The DOM renderer passes in
107+
// the removal function to be fired off when the animation finishes.
108+
animate(el:Element,removeFn:Function):void{
109+
if(!this.outElements.has(el))return;
110+
constdetails=this.outElements.get(el)!;
111+
consttimeout=setTimeout(()=>removeFn(),4000);
112+
details.animateFn(()=>removeFn(timeout));
113+
}
114+
}

‎packages/core/src/application/application_tokens.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,15 @@ export const IMAGE_CONFIG = new InjectionToken<ImageConfig>(ngDevMode ? 'ImageCo
164164
providedIn:'root',
165165
factory:()=>IMAGE_CONFIG_DEFAULTS,
166166
});
167+
168+
/**
169+
* A [DI token](api/core/InjectionToken) that enables or disables all in and out animations.
170+
*@publicApi
171+
*/
172+
exportconstANIMATIONS_DISABLED=newInjectionToken<boolean>(
173+
ngDevMode ?'AnimationsDisabled' :'',
174+
{
175+
providedIn:'root',
176+
factory:()=>false,
177+
},
178+
);

‎packages/core/src/core.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export {
5555
PLATFORM_ID,
5656
ANIMATION_MODULE_TYPE,
5757
CSP_NONCE,
58+
ANIMATIONS_DISABLED,
5859
}from'./application/application_tokens';
5960
export{
6061
APP_INITIALIZER,
@@ -121,6 +122,7 @@ export {booleanAttribute, numberAttribute} from './util/coercion';
121122
export{REQUEST,REQUEST_CONTEXT,RESPONSE_INIT}from'./application/platform_tokens';
122123
export{DOCUMENT}from'./document';
123124
export{provideNgReflectAttributes}from'./ng_reflect';
125+
export{AnimationCallbackEvent,AnimationFunction}from'./animation';
124126

125127
import{global}from'./util/global';
126128
if(typeofngDevMode!=='undefined'&&ngDevMode){

‎packages/core/src/core_private_export.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,4 @@ export {getComponentDef as ɵgetComponentDef} from './render3/def_getters';
172172
export{DEHYDRATED_BLOCK_REGISTRYasɵDEHYDRATED_BLOCK_REGISTRY}from'./defer/registry';
173173
export{TimerSchedulerasɵTimerScheduler}from'./defer/timer_scheduler';
174174
export{ɵassertType}from'./type_checking';
175+
export{ElementRegistry}from'./animation';

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp