@@ -131,50 +131,77 @@ export default class AbstractMenu extends Component {
131131 return i === currentIndex ? null : i ;
132132 }
133133
134- const currentIndex = children . indexOf ( selectedItem ) ;
134+ const currentIndex = selectedItem ? selectedItem . index : - 1 ;
135135 const nextEnabledChildIndex = findNextEnabledChildIndex ( currentIndex ) ;
136136
137137 if ( nextEnabledChildIndex !== null ) {
138138 this . setState ( {
139- selectedItem : children [ nextEnabledChildIndex ] ,
139+ selectedItem : {
140+ index : nextEnabledChildIndex ,
141+ // We need to know the type of the selected item, so we can
142+ // check it during render and tryToOpenSubMenu.
143+ type : children [ nextEnabledChildIndex ] . type
144+ } ,
140145 forceSubMenuOpen : false
141146 } ) ;
142147 }
143148 } ;
144149
145- onChildMouseMove = ( child ) => {
146- if ( this . state . selectedItem !== child ) {
147- this . setState ( { selectedItem : child , forceSubMenuOpen : false } ) ;
150+ onChildMouseMove = ( child , itemIndex ) => {
151+ if ( this . state . selectedItem === null || this . state . selectedItem . index !== itemIndex ) {
152+ this . setState ( {
153+ selectedItem : {
154+ index : itemIndex ,
155+ type : child . type
156+ } ,
157+ forceSubMenuOpen : false
158+ } ) ;
148159 }
149160 } ;
150161
151162 onChildMouseLeave = ( ) => {
152163 this . setState ( { selectedItem : null , forceSubMenuOpen : false } ) ;
153164 } ;
154165
155- renderChildren = children => React . Children . map ( children , ( child ) => {
156- const props = { } ;
157- if ( ! React . isValidElement ( child ) ) return child ;
158- if ( [ MenuItem , this . getSubMenuType ( ) ] . indexOf ( child . type ) < 0 ) {
159- // Maybe the MenuItem or SubMenu is capsuled in a wrapper div or something else
160- props . children = this . renderChildren ( child . props . children ) ;
161- return React . cloneElement ( child , props ) ;
162- }
163- props . onMouseLeave = this . onChildMouseLeave . bind ( this ) ;
164- if ( child . type === this . getSubMenuType ( ) ) {
165- // special props for SubMenu only
166- props . forceOpen = this . state . forceSubMenuOpen && ( this . state . selectedItem === child ) ;
167- props . forceClose = this . handleForceClose ;
168- props . parentKeyNavigationHandler = this . handleKeyNavigation ;
169- }
170- if ( ! child . props . divider && this . state . selectedItem === child ) {
171- // special props for selected item only
172- props . selected = true ;
173- props . ref = ( ref ) => { this . seletedItemRef = ref ; } ;
166+ renderChildren = ( children , childIndexRef = { value : - 1 } ) =>
167+ React . Children . map ( children , ( child ) => {
168+ let currentChildIndexRef = childIndexRef ;
169+ const props = { } ;
170+ if ( ! React . isValidElement ( child ) ) return child ;
171+
172+ if ( [ MenuItem , this . getSubMenuType ( ) ] . indexOf ( child . type ) < 0 ) {
173+ // Maybe the MenuItem or SubMenu is capsuled in a wrapper div or something else
174+ props . children = this . renderChildren ( child . props . children , currentChildIndexRef ) ;
175+ return React . cloneElement ( child , props ) ;
176+ }
177+
178+ // At this point we know that this is a menu item and we are going to
179+ // render it. We need to increment the child index and assign it as
180+ // the item index.
181+ let itemIndex = null ;
182+ if ( ! child . props . divider ) {
183+ // A MenuItem can be a divider. Do not increment the value if it's.
184+ itemIndex = ++ currentChildIndexRef . value ;
185+ }
186+
187+ props . onMouseLeave = this . onChildMouseLeave . bind ( this ) ;
188+ if ( child . type === this . getSubMenuType ( ) ) {
189+ // special props for SubMenu only
190+ props . forceOpen = this . state . forceSubMenuOpen &&
191+ ( this . state . selectedItem && this . state . selectedItem . index === itemIndex ) ;
192+ props . forceClose = this . handleForceClose ;
193+ props . parentKeyNavigationHandler = this . handleKeyNavigation ;
194+ }
195+ if ( ! child . props . divider &&
196+ ( this . state . selectedItem && this . state . selectedItem . index === itemIndex ) ) {
197+ // special props for selected item only
198+ props . selected = true ;
199+ props . ref = ( ref ) => { this . seletedItemRef = ref ; } ;
200+ return React . cloneElement ( child , props ) ;
201+ }
202+
203+ // onMouseMove is only needed for non selected items
204+ props . onMouseMove = ( ) => this . onChildMouseMove ( child , itemIndex ) ;
174205 return React . cloneElement ( child , props ) ;
175- }
176- // onMouseMove is only needed for non selected items
177- props . onMouseMove = ( ) => this . onChildMouseMove ( child ) ;
178- return React . cloneElement ( child , props ) ;
179- } ) ;
206+ } ) ;
180207}
0 commit comments