@@ -6,21 +6,19 @@ import {
66HostListener ,
77Inject ,
88Input ,
9- OnChanges ,
109OnDestroy ,
1110OnInit ,
1211Output ,
1312PLATFORM_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;
2927animations :[
3028trigger ( 'showHide' , [
3129state (
32- 'true ' ,
30+ 'visible ' ,
3331style ( {
34- visibility :'visible'
32+ // visibility: 'visible'
3533} )
3634) ,
3735state (
38- 'false ' ,
36+ 'hidden ' ,
3937style ( {
40- visibility :'hidden'
38+ // visibility: 'hidden'
4139} )
4240) ,
43- transition ( 'true =>false ' , [ animate ( '300ms' ) ] )
41+ transition ( 'visible < =>* ' , [ animate ( '300ms' ) ] )
4442] )
4543] ,
4644templateUrl :'./offcanvas.component.html' ,
4745styleUrls :[ './offcanvas.component.scss' ] ,
4846exportAs :'cOffcanvas'
4947} )
50- export class OffcanvasComponent implements OnChanges , OnInit , OnDestroy {
48+ export class OffcanvasComponent implements OnInit , OnDestroy {
49+
5150static ngAcceptInputType_scroll :BooleanInput ;
5251
5352constructor (
54- @Inject ( DOCUMENT ) private document :any ,
53+ @Inject ( DOCUMENT ) private document :Document ,
5554 @Inject ( PLATFORM_ID ) private platformId :any ,
5655private renderer :Renderer2 ,
5756private hostElement :ElementRef ,
@@ -96,6 +95,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
9695private _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 ( )
118119set visible ( value :boolean ) {
119120this . _visible = coerceBooleanProperty ( value ) ;
120- if ( value ) {
121+ if ( this . _visible ) {
121122this . setBackdrop ( this . backdrop ) ;
122123this . setFocus ( ) ;
123124} else {
124125this . setBackdrop ( false ) ;
125126}
126- this . setScroll ( ) ;
127127this . visibleChange . emit ( value ) ;
128128}
129129
130130get visible ( ) :boolean {
131131return 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 ;
142142private scrollbarWidth ! :string ;
143143
144144private stateToggleSubscription ! :Subscription ;
@@ -149,7 +149,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
149149return {
150150offcanvas :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
183222ngOnInit ( ) :void {
184- this . setScroll ( ) ;
185223this . scrollbarWidth = this . backdropService . scrollbarWidth ;
186224this . stateToggleSubscribe ( ) ;
225+ // hotfix to avoid end offcanvas flicker on first render
226+ this . renderer . setStyle ( this . hostElement . nativeElement , 'display' , 'flex' ) ;
187227}
188228
189229ngOnDestroy ( ) :void {
190230this . offcanvasService . toggle ( { show :false , id :this . id } ) ;
191231this . stateToggleSubscribe ( false ) ;
192232}
193233
194- ngOnChanges ( changes :SimpleChanges ) :void {
195- if ( changes [ 'scroll' ] ) {
196- this . setScroll ( ) ;
197- }
198- }
199-
200234private stateToggleSubscribe ( subscribe :boolean = true ) :void {
201235if ( subscribe ) {
202236this . stateToggleSubscription =
@@ -237,18 +271,4 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
237271setTimeout ( ( ) => 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}