@@ -7,14 +7,14 @@ import { shouldUseCloseWatcher } from '@utils/hardware-back-button';
77import type { Attributes } from '@utils/helpers' ;
88import { inheritAriaAttributes , assert , clamp , isEndSide as isEnd } from '@utils/helpers' ;
99import { menuController } from '@utils/menu-controller' ;
10- import { getPresentedOverlay } from '@utils/overlays' ;
10+ import { BACKDROP , ESCAPE , GESTURE , getPresentedOverlay } from '@utils/overlays' ;
1111import { hostContext } from '@utils/theme' ;
1212
1313import { config } from '../../global/config' ;
1414import { getIonMode } from '../../global/ionic-global' ;
1515import type { Animation , Gesture , GestureDetail } from '../../interface' ;
1616
17- import type { MenuChangeEventDetail , MenuI , MenuType , Side } from './menu-interface' ;
17+ import type { MenuChangeEventDetail , MenuCloseEventDetail , MenuI , MenuType , Side } from './menu-interface' ;
1818
1919const iosEasing = 'cubic-bezier(0.32,0.72,0,1)' ;
2020const mdEasing = 'cubic-bezier(0.0,0.0,0.2,1)' ;
@@ -179,7 +179,7 @@ export class Menu implements ComponentInterface, MenuI {
179179 /**
180180 * Emitted when the menu is about to be closed.
181181 */
182- @Event ( ) ionWillClose ! : EventEmitter < void > ;
182+ @Event ( ) ionWillClose ! : EventEmitter < MenuCloseEventDetail > ;
183183 /**
184184 * Emitted when the menu is open.
185185 */
@@ -188,7 +188,7 @@ export class Menu implements ComponentInterface, MenuI {
188188 /**
189189 * Emitted when the menu is closed.
190190 */
191- @Event ( ) ionDidClose ! : EventEmitter < void > ;
191+ @Event ( ) ionDidClose ! : EventEmitter < MenuCloseEventDetail > ;
192192
193193 /**
194194 * Emitted when the menu state is changed.
@@ -322,23 +322,9 @@ export class Menu implements ComponentInterface, MenuI {
322322 }
323323 }
324324
325- @Listen ( 'click' , { capture : true } )
326- onBackdropClick ( ev : any ) {
327- // TODO(FW-2832): type (CustomEvent triggers errors which should be sorted)
328- if ( this . _isOpen && this . lastOnEnd < ev . timeStamp - 100 ) {
329- const shouldClose = ev . composedPath ? ! ev . composedPath ( ) . includes ( this . menuInnerEl ) : false ;
330-
331- if ( shouldClose ) {
332- ev . preventDefault ( ) ;
333- ev . stopPropagation ( ) ;
334- this . close ( ) ;
335- }
336- }
337- }
338-
339325 onKeydown ( ev : KeyboardEvent ) {
340326 if ( ev . key === 'Escape' ) {
341- this . close ( ) ;
327+ this . close ( undefined , ESCAPE ) ;
342328 }
343329 }
344330
@@ -375,8 +361,8 @@ export class Menu implements ComponentInterface, MenuI {
375361 * it returns `false`.
376362 */
377363 @Method ( )
378- close ( animated = true ) : Promise < boolean > {
379- return this . setOpen ( false , animated ) ;
364+ close ( animated = true , role ?: string ) : Promise < boolean > {
365+ return this . setOpen ( false , animated , role ) ;
380366 }
381367
382368 /**
@@ -393,8 +379,8 @@ export class Menu implements ComponentInterface, MenuI {
393379 * If the operation can't be completed successfully, it returns `false`.
394380 */
395381 @Method ( )
396- setOpen ( shouldOpen : boolean , animated = true ) : Promise < boolean > {
397- return menuController . _setOpen ( this , shouldOpen , animated ) ;
382+ setOpen ( shouldOpen : boolean , animated = true , role ?: string ) : Promise < boolean > {
383+ return menuController . _setOpen ( this , shouldOpen , animated , role ) ;
398384 }
399385
400386 private trapKeyboardFocus ( ev : Event , doc : Document ) {
@@ -438,13 +424,13 @@ export class Menu implements ComponentInterface, MenuI {
438424 }
439425 }
440426
441- async _setOpen ( shouldOpen : boolean , animated = true ) : Promise < boolean > {
427+ async _setOpen ( shouldOpen : boolean , animated = true , role ?: string ) : Promise < boolean > {
442428 // If the menu is disabled or it is currently being animated, let's do nothing
443429 if ( ! this . _isActive ( ) || this . isAnimating || shouldOpen === this . _isOpen ) {
444430 return false ;
445431 }
446432
447- this . beforeAnimation ( shouldOpen ) ;
433+ this . beforeAnimation ( shouldOpen , role ) ;
448434
449435 await this . loadAnimation ( ) ;
450436 await this . startAnimation ( shouldOpen , animated ) ;
@@ -459,7 +445,7 @@ export class Menu implements ComponentInterface, MenuI {
459445 return false ;
460446 }
461447
462- this . afterAnimation ( shouldOpen ) ;
448+ this . afterAnimation ( shouldOpen , role ) ;
463449
464450 return true ;
465451 }
@@ -542,7 +528,7 @@ export class Menu implements ComponentInterface, MenuI {
542528 }
543529
544530 private onWillStart ( ) : Promise < void > {
545- this . beforeAnimation ( ! this . _isOpen ) ;
531+ this . beforeAnimation ( ! this . _isOpen , GESTURE ) ;
546532 return this . loadAnimation ( ) ;
547533 }
548534
@@ -624,11 +610,11 @@ export class Menu implements ComponentInterface, MenuI {
624610
625611 this . animation
626612 . easing ( 'cubic-bezier(0.4, 0.0, 0.6, 1)' )
627- . onFinish ( ( ) => this . afterAnimation ( shouldOpen ) , { oneTimeCallback : true } )
613+ . onFinish ( ( ) => this . afterAnimation ( shouldOpen , GESTURE ) , { oneTimeCallback : true } )
628614 . progressEnd ( playTo ? 1 : 0 , this . _isOpen ? 1 - newStepValue : newStepValue , 300 ) ;
629615 }
630616
631- private beforeAnimation ( shouldOpen : boolean ) {
617+ private beforeAnimation ( shouldOpen : boolean , role ?: string ) {
632618 assert ( ! this . isAnimating , '_before() should not be called while animating' ) ;
633619
634620 // this places the menu into the correct location before it animates in
@@ -671,11 +657,11 @@ export class Menu implements ComponentInterface, MenuI {
671657 if ( shouldOpen ) {
672658 this . ionWillOpen . emit ( ) ;
673659 } else {
674- this . ionWillClose . emit ( ) ;
660+ this . ionWillClose . emit ( { role } ) ;
675661 }
676662 }
677663
678- private afterAnimation ( isOpen : boolean ) {
664+ private afterAnimation ( isOpen : boolean , role ?: string ) {
679665 // keep opening/closing the menu disabled for a touch more yet
680666 // only add listeners/css if it's enabled and isOpen
681667 // and only remove listeners/css if it's not open
@@ -731,13 +717,26 @@ export class Menu implements ComponentInterface, MenuI {
731717 }
732718
733719 // emit close event
734- this . ionDidClose . emit ( ) ;
720+ this . ionDidClose . emit ( { role } ) ;
735721
736722 // undo focus trapping so multiple menus don't collide
737723 document . removeEventListener ( 'focus' , this . handleFocus , true ) ;
738724 }
739725 }
740726
727+ private onBackdropTap = ( ev : any ) => {
728+ // TODO(FW-2832): type (CustomEvent triggers errors which should be sorted)
729+ if ( this . _isOpen && this . lastOnEnd < ev . timeStamp - 100 ) {
730+ const shouldClose = ev . composedPath ? ! ev . composedPath ( ) . includes ( this . menuInnerEl ) : false ;
731+
732+ if ( shouldClose ) {
733+ ev . preventDefault ( ) ;
734+ ev . stopPropagation ( ) ;
735+ this . close ( undefined , BACKDROP ) ;
736+ }
737+ }
738+ } ;
739+
741740 private updateState ( ) {
742741 const isActive = this . _isActive ( ) ;
743742 if ( this . gesture ) {
@@ -767,7 +766,7 @@ export class Menu implements ComponentInterface, MenuI {
767766 * If the menu is disabled then we should
768767 * forcibly close the menu even if it is open.
769768 */
770- this . afterAnimation ( false ) ;
769+ this . afterAnimation ( false , GESTURE ) ;
771770 }
772771 }
773772
@@ -793,18 +792,13 @@ export class Menu implements ComponentInterface, MenuI {
793792 'menu-pane-visible' : isPaneVisible ,
794793 'split-pane-side' : hostContext ( 'ion-split-pane' , el ) ,
795794 } }
795+ onIonBackdropTap = { this . onBackdropTap }
796796 >
797797 < div class = "menu-inner" part = "container" ref = { ( el ) => ( this . menuInnerEl = el ) } >
798798 < slot > </ slot >
799799 </ div >
800800
801- < ion-backdrop
802- ref = { ( el ) => ( this . backdropEl = el ) }
803- class = "menu-backdrop"
804- tappable = { false }
805- stopPropagation = { false }
806- part = "backdrop"
807- />
801+ < ion-backdrop ref = { ( el ) => ( this . backdropEl = el ) } class = "menu-backdrop" tappable = { true } part = "backdrop" />
808802 </ Host >
809803 ) ;
810804 }
0 commit comments