@@ -14,9 +14,15 @@ import {
14
14
} from '@angular/core' ;
15
15
import { AnimationBuilder , AnimationPlayer , useAnimation } from '@angular/animations' ;
16
16
17
- import { collapseAnimation , expandAnimation } from './collapse.animations' ;
18
17
import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
19
18
19
+ import {
20
+ collapseAnimation ,
21
+ collapseHorizontalAnimation ,
22
+ expandAnimation ,
23
+ expandHorizontalAnimation
24
+ } from './collapse.animations' ;
25
+
20
26
// todo
21
27
// tslint:disable-next-line:no-conflicting-lifecycle
22
28
@Directive ( {
@@ -25,6 +31,7 @@ import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
25
31
} )
26
32
export class CollapseDirective implements OnChanges , OnDestroy , DoCheck , AfterViewInit {
27
33
34
+ static ngAcceptInputType_horizontal : BooleanInput ;
28
35
static ngAcceptInputType_navbar : BooleanInput ;
29
36
30
37
private _animate = true ;
@@ -39,6 +46,18 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
39
46
return this . _animate ;
40
47
}
41
48
49
+ /**
50
+ * Set horizontal collapsing to transition the width instead of height.
51
+ */
52
+ @Input ( )
53
+ set horizontal ( value : boolean ) {
54
+ this . _horizontal = coerceBooleanProperty ( value ) ;
55
+ }
56
+ get horizontal ( ) : boolean {
57
+ return this . _horizontal ;
58
+ }
59
+ private _horizontal : boolean = false ;
60
+
42
61
private _visible = false ;
43
62
/**
44
63
* Toggle the visibility of collapsible element.
@@ -66,11 +85,11 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
66
85
/**
67
86
* @ignore
68
87
*/
69
- @Input ( ) duration = '400ms ' ;
88
+ @Input ( ) duration = '350ms ' ;
70
89
/**
71
90
* @ignore
72
91
*/
73
- @Input ( ) transition = 'ease-in-out ' ;
92
+ @Input ( ) transition = 'ease' ;
74
93
/**
75
94
* Event emitted on visibility change. [docs]
76
95
* @type string
@@ -79,32 +98,45 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
79
98
80
99
private player ! : AnimationPlayer ;
81
100
private readonly host : HTMLElement ;
101
+ private scrollHeight ! : number ;
102
+ private scrollWidth ! : number ;
103
+ private collapsing : boolean = false ;
82
104
83
105
constructor (
84
106
private hostElement : ElementRef ,
85
107
private renderer : Renderer2 ,
86
108
private animationBuilder : AnimationBuilder
87
109
) {
88
110
this . host = this . hostElement . nativeElement ;
89
- this . renderer . setStyle ( this . host , 'display' , 'none' ) ;
111
+ this . setDisplay ( false ) ;
90
112
}
91
113
92
114
@HostBinding ( 'class' )
93
115
get hostClasses ( ) : any {
94
116
return {
95
117
'navbar-collapse' : this . navbar ,
96
- show : this . visible
118
+ show : this . visible ,
119
+ 'collapse-horizontal' : this . horizontal ,
120
+ collapsing : this . collapsing
121
+ // collapse: !this.collapsing
97
122
} ;
98
123
}
99
124
125
+ ngAfterViewInit ( ) : void {
126
+ if ( this . visible ) {
127
+ this . toggle ( ) ;
128
+ }
129
+ }
130
+
100
131
ngOnDestroy ( ) : void {
101
132
this . destroyPlayer ( ) ;
102
133
}
103
134
104
135
ngOnChanges ( changes : SimpleChanges ) : void {
105
136
if ( changes [ 'visible' ] ) {
106
- // tslint:disable-next-line:no-unused-expression
107
- ( ! changes [ 'visible' ] . firstChange || ! changes [ 'visible' ] . currentValue ) && this . toggle ( changes [ 'visible' ] . currentValue ) ;
137
+ if ( ! changes [ 'visible' ] . firstChange || ! changes [ 'visible' ] . currentValue ) {
138
+ this . toggle ( changes [ 'visible' ] . currentValue ) ;
139
+ }
108
140
}
109
141
}
110
142
@@ -115,39 +147,57 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
115
147
}
116
148
117
149
toggle ( visible = this . visible ) : void {
118
- if ( visible ) {
119
- this . renderer . removeStyle ( this . host , 'display' ) ;
120
- }
121
- this . visible = visible ;
150
+ this . setDisplay ( true ) ;
122
151
this . createPlayer ( visible ) ;
123
- this . player . play ( ) ;
152
+ this . visible = visible ;
153
+ this . player ?. play ( ) ;
124
154
}
125
155
126
156
destroyPlayer ( ) : void {
127
- if ( this . player ) {
128
- this . player . destroy ( ) ;
129
- }
157
+ this . player ?. destroy ( ) ;
130
158
}
131
159
132
160
createPlayer ( visible : boolean = this . visible ) : void {
133
- if ( this . player ) {
161
+ if ( this . player ?. hasStarted ( ) ) {
134
162
this . destroyPlayer ( ) ;
135
163
}
136
164
137
165
let animationFactory ;
138
166
139
167
const duration = this . animate ? this . duration : '0ms' ;
140
168
169
+ const expand = this . horizontal ? expandHorizontalAnimation : expandAnimation ;
170
+ const collapse = this . horizontal ? collapseHorizontalAnimation : collapseAnimation ;
171
+
141
172
animationFactory = this . animationBuilder . build (
142
- useAnimation ( visible ? expandAnimation : collapseAnimation , { params : { time : duration , easing : this . transition } } )
173
+ useAnimation ( visible ? expand : collapse , { params : { time : duration , easing : this . transition } } )
143
174
) ;
144
175
145
176
this . player = animationFactory . create ( this . host ) ;
146
- this . player . onStart ( ( ) => { this . collapseChange . emit ( visible ? 'opening' : 'collapsing' ) ; } ) ;
147
- this . player . onDone ( ( ) => { this . collapseChange . emit ( visible ? 'open' : 'collapsed' ) ; } ) ;
177
+ this . player . onStart ( ( ) => {
178
+ this . setMaxSize ( ) ;
179
+ this . collapsing = true ;
180
+ this . collapseChange . emit ( visible ? 'opening' : 'collapsing' ) ;
181
+ } ) ;
182
+ this . player . onDone ( ( ) => {
183
+ this . collapsing = false ;
184
+ this . collapseChange . emit ( visible ? 'open' : 'collapsed' ) ;
185
+ } ) ;
148
186
}
149
187
150
- ngAfterViewInit ( ) : void {
151
- this . toggle ( ) ;
188
+ setMaxSize ( ) {
189
+ setTimeout ( ( ) => {
190
+ if ( this . horizontal ) {
191
+ this . scrollWidth = this . host . scrollWidth ;
192
+ this . scrollWidth > 0 && this . renderer . setStyle ( this . host , 'maxWidth' , `${ this . scrollWidth } px` ) ;
193
+ // } else {
194
+ // this.scrollHeight = this.host.scrollHeight;
195
+ // this.scrollHeight > 0 && this.renderer.setStyle(this.host, 'maxHeight', `${this.scrollHeight}px`);
196
+ }
197
+ } ) ;
198
+ }
199
+
200
+ setDisplay ( display : boolean ) {
201
+ display ? this . renderer . removeStyle ( this . host , 'display' ) : this . renderer . setStyle ( this . host , 'display' , 'none' ) ;
152
202
}
153
203
}
0 commit comments