@@ -6,21 +6,19 @@ import {
66 HostListener ,
77 Inject ,
88 Input ,
9- OnChanges ,
109 OnDestroy ,
1110 OnInit ,
1211 Output ,
1312 PLATFORM_ID ,
14- Renderer2 ,
15- SimpleChanges
13+ Renderer2
1614} from '@angular/core' ;
17- import { animate , state , style , transition , trigger } from '@angular/animations' ;
15+ import { DOCUMENT , isPlatformBrowser } from '@angular/common' ;
16+ import { animate , AnimationEvent , state , style , transition , trigger } from '@angular/animations' ;
1817import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
1918import { Subscription } from 'rxjs' ;
2019
21- import { OffcanvasService } from '../offcanvas.service' ;
2220import { BackdropService } from '../../backdrop/backdrop.service' ;
23- import { DOCUMENT , isPlatformBrowser } from '@angular/common ' ;
21+ import { OffcanvasService } from '../offcanvas.service ' ;
2422
2523let nextId = 0 ;
2624
@@ -29,29 +27,30 @@ let nextId = 0;
2927 animations : [
3028 trigger ( 'showHide' , [
3129 state (
32- 'true ' ,
30+ 'visible ' ,
3331 style ( {
34- visibility : 'visible'
32+ // visibility: 'visible'
3533 } )
3634 ) ,
3735 state (
38- 'false ' ,
36+ 'hidden ' ,
3937 style ( {
40- visibility : 'hidden'
38+ // visibility: 'hidden'
4139 } )
4240 ) ,
43- transition ( 'true => false ' , [ animate ( '300ms' ) ] )
41+ transition ( 'visible < => * ' , [ animate ( '300ms' ) ] )
4442 ] )
4543 ] ,
4644 templateUrl : './offcanvas.component.html' ,
4745 styleUrls : [ './offcanvas.component.scss' ] ,
4846 exportAs : 'cOffcanvas'
4947} )
50- export class OffcanvasComponent implements OnChanges , OnInit , OnDestroy {
48+ export class OffcanvasComponent implements OnInit , OnDestroy {
49+
5150 static ngAcceptInputType_scroll : BooleanInput ;
5251
5352 constructor (
54- @Inject ( DOCUMENT ) private document : any ,
53+ @Inject ( DOCUMENT ) private document : Document ,
5554 @Inject ( PLATFORM_ID ) private platformId : any ,
5655 private renderer : Renderer2 ,
5756 private hostElement : ElementRef ,
@@ -96,6 +95,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
9695 private _scroll = false ;
9796
9897 @Input ( ) id = `offcanvas-${ this . placement } -${ nextId ++ } ` ;
98+
9999 /**
100100 * Default role for offcanvas. [docs]
101101 * @type string
@@ -113,32 +113,32 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
113113 /**
114114 * Toggle the visibility of offcanvas component.
115115 * @type boolean
116+ * @default false
116117 */
117118 @Input ( )
118119 set visible ( value : boolean ) {
119120 this . _visible = coerceBooleanProperty ( value ) ;
120- if ( value ) {
121+ if ( this . _visible ) {
121122 this . setBackdrop ( this . backdrop ) ;
122123 this . setFocus ( ) ;
123124 } else {
124125 this . setBackdrop ( false ) ;
125126 }
126- this . setScroll ( ) ;
127127 this . visibleChange . emit ( value ) ;
128128 }
129129
130130 get visible ( ) : boolean {
131131 return this . _visible ;
132132 }
133133
134- private _visible ! : boolean ;
134+ private _visible : boolean = false ;
135135
136136 /**
137137 * Event triggered on visible change.
138138 */
139139 @Output ( ) visibleChange = new EventEmitter < boolean > ( ) ;
140140
141- private activeBackdrop ! : any ;
141+ private activeBackdrop ! : HTMLDivElement ;
142142 private scrollbarWidth ! : string ;
143143
144144 private stateToggleSubscription ! : Subscription ;
@@ -149,7 +149,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
149149 return {
150150 offcanvas : true ,
151151 [ `offcanvas-${ this . placement } ` ] : ! ! this . placement ,
152- show : this . visible
152+ show : this . show
153153 } ;
154154 }
155155
@@ -164,8 +164,47 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
164164 }
165165
166166 @HostBinding ( '@showHide' )
167- get animateType ( ) : boolean {
168- return this . visible ;
167+ get animateTrigger ( ) : string {
168+ return this . visible ? 'visible' : 'hidden' ;
169+ }
170+
171+ get show ( ) : boolean {
172+ return this . visible && this . _show ;
173+ }
174+
175+ set show ( value : boolean ) {
176+ this . _show = value ;
177+ }
178+
179+ private _show = false ;
180+
181+ @HostListener ( '@showHide.start' , [ '$event' ] )
182+ animateStart ( event : AnimationEvent ) {
183+ const scrollbarWidth = this . scrollbarWidth ;
184+ if ( event . toState === 'visible' ) {
185+ if ( ! this . scroll ) {
186+ this . renderer . setStyle ( this . document . body , 'overflow' , 'hidden' ) ;
187+ this . renderer . setStyle ( this . document . body , 'padding-right' , scrollbarWidth ) ;
188+ }
189+ this . renderer . addClass ( this . hostElement . nativeElement , 'showing' ) ;
190+ } else {
191+ this . renderer . addClass ( this . hostElement . nativeElement , 'hiding' ) ;
192+ }
193+ }
194+
195+ @HostListener ( '@showHide.done' , [ '$event' ] )
196+ animateDone ( event : AnimationEvent ) {
197+ setTimeout ( ( ) => {
198+ if ( event . toState === 'visible' ) {
199+ this . renderer . removeClass ( this . hostElement . nativeElement , 'showing' ) ;
200+ }
201+ if ( event . toState === 'hidden' ) {
202+ this . renderer . removeClass ( this . hostElement . nativeElement , 'hiding' ) ;
203+ this . renderer . removeStyle ( this . document . body , 'overflow' ) ;
204+ this . renderer . removeStyle ( this . document . body , 'paddingRight' ) ;
205+ }
206+ } ) ;
207+ this . show = this . visible ;
169208 }
170209
171210 @HostListener ( 'document:keydown' , [ '$event' ] )
@@ -181,22 +220,17 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
181220 }
182221
183222 ngOnInit ( ) : void {
184- this . setScroll ( ) ;
185223 this . scrollbarWidth = this . backdropService . scrollbarWidth ;
186224 this . stateToggleSubscribe ( ) ;
225+ // hotfix to avoid end offcanvas flicker on first render
226+ this . renderer . setStyle ( this . hostElement . nativeElement , 'display' , 'flex' ) ;
187227 }
188228
189229 ngOnDestroy ( ) : void {
190230 this . offcanvasService . toggle ( { show : false , id : this . id } ) ;
191231 this . stateToggleSubscribe ( false ) ;
192232 }
193233
194- ngOnChanges ( changes : SimpleChanges ) : void {
195- if ( changes [ 'scroll' ] ) {
196- this . setScroll ( ) ;
197- }
198- }
199-
200234 private stateToggleSubscribe ( subscribe : boolean = true ) : void {
201235 if ( subscribe ) {
202236 this . stateToggleSubscription =
@@ -237,18 +271,4 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
237271 setTimeout ( ( ) => this . hostElement . nativeElement . focus ( ) ) ;
238272 }
239273 }
240-
241- setScroll ( ) {
242- if ( this . visible ) {
243- if ( ! this . scroll ) {
244- this . renderer . setStyle ( this . document . body , 'overflow' , 'hidden' ) ;
245- this . renderer . setStyle ( this . document . body , 'paddingRight.px' , '0' ) ;
246- }
247- return ;
248- }
249- if ( ! this . scroll ) {
250- this . renderer . removeStyle ( this . document . body , 'overflow' ) ;
251- this . renderer . removeStyle ( this . document . body , 'paddingRight' ) ;
252- }
253- }
254274}
0 commit comments