@@ -29,7 +29,10 @@ import {FocusKeyManager} from '../core/a11y/focus-key-manager';
2929import { MdMenuPanel } from './menu-panel' ;
3030import { Subscription } from 'rxjs/Subscription' ;
3131import { transformMenu , fadeInItems } from './menu-animations' ;
32- import { ESCAPE } from '../core/keyboard/keycodes' ;
32+ import { ESCAPE , LEFT_ARROW , RIGHT_ARROW } from '../core/keyboard/keycodes' ;
33+ import { merge } from 'rxjs/observable/merge' ;
34+ import { Observable } from 'rxjs/Observable' ;
35+ import { Direction } from '../core' ;
3336
3437
3538@Component ( {
@@ -59,6 +62,12 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
5962 /** Current state of the panel animation. */
6063 _panelAnimationState : 'void' | 'enter-start' | 'enter' = 'void' ;
6164
65+ /** Whether the menu is a sub-menu or a top-level menu. */
66+ isSubmenu : boolean = false ;
67+
68+ /** Layout direction of the menu. */
69+ direction : Direction ;
70+
6271 /** Position of the menu in the X axis. */
6372 @Input ( )
6473 get xPosition ( ) { return this . _xPosition ; }
@@ -109,30 +118,45 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
109118 }
110119
111120 /** Event emitted when the menu is closed. */
112- @Output ( ) close = new EventEmitter < void > ( ) ;
121+ @Output ( ) close = new EventEmitter < void | 'click' | 'keydown' > ( ) ;
113122
114123 constructor ( private _elementRef : ElementRef ) { }
115124
116125 ngAfterContentInit ( ) {
117126 this . _keyManager = new FocusKeyManager ( this . items ) . withWrap ( ) ;
118- this . _tabSubscription = this . _keyManager . tabOut . subscribe ( ( ) => this . _emitCloseEvent ( ) ) ;
127+ this . _tabSubscription = this . _keyManager . tabOut . subscribe ( ( ) => this . close . emit ( 'keydown' ) ) ;
119128 }
120129
121130 ngOnDestroy ( ) {
122131 if ( this . _tabSubscription ) {
123132 this . _tabSubscription . unsubscribe ( ) ;
124133 }
125134
126- this . _emitCloseEvent ( ) ;
135+ this . close . emit ( ) ;
127136 this . close . complete ( ) ;
128137 }
129138
139+ /** Stream that emits whenever the hovered menu item changes. */
140+ hover ( ) : Observable < MdMenuItem > {
141+ return merge ( ...this . items . map ( item => item . hover ) ) ;
142+ }
143+
130144 /** Handle a keyboard event from the menu, delegating to the appropriate action. */
131145 _handleKeydown ( event : KeyboardEvent ) {
132146 switch ( event . keyCode ) {
133147 case ESCAPE :
134- this . _emitCloseEvent ( ) ;
135- return ;
148+ this . close . emit ( 'keydown' ) ;
149+ break ;
150+ case LEFT_ARROW :
151+ if ( this . isSubmenu && this . direction === 'ltr' ) {
152+ this . close . emit ( 'keydown' ) ;
153+ }
154+ break ;
155+ case RIGHT_ARROW :
156+ if ( this . isSubmenu && this . direction === 'rtl' ) {
157+ this . close . emit ( 'keydown' ) ;
158+ }
159+ break ;
136160 default :
137161 this . _keyManager . onKeydown ( event ) ;
138162 }
@@ -146,14 +170,6 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
146170 this . _keyManager . setFirstItemActive ( ) ;
147171 }
148172
149- /**
150- * This emits a close event to which the trigger is subscribed. When emitted, the
151- * trigger will close the menu.
152- */
153- _emitCloseEvent ( ) : void {
154- this . close . emit ( ) ;
155- }
156-
157173 /**
158174 * It's necessary to set position-based classes to ensure the menu panel animation
159175 * folds out from the correct direction.
0 commit comments