44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
66 * You may obtain a copy of the License at
7- *
87 * http://www.apache.org/licenses/LICENSE-2.0
98 *
109 * Unless required by applicable law or agreed to in writing, software
1817
1918export default function ( Base ) {
2019 return class extends Base {
20+ // Initialization and state management
2121 _init ( ) {
2222 super . _init ( ) ;
2323 this . isEditing = false ;
@@ -27,73 +27,94 @@ export default function (Base) {
2727 this . isEditing = ! this . isEditing ;
2828 }
2929
30+ _unfocus ( ) {
31+ this . isEditing = false ;
32+ super . _unfocus ( ) ;
33+ }
34+
35+ // Item manipulation and transition handling
3036 _swapItemArrayPos ( array , current , previous ) {
3137 [ array [ current ] , array [ previous ] ] = [ array [ previous ] , array [ current ] ] ;
3238 super . selectedIndex = current ;
3339 }
3440
35- _unfocus ( ) {
36- this . isEditing = false ;
37- super . _unfocus ( ) ;
41+ _getPositionValue ( item , axis ) {
42+ return item . transition ( axis )
43+ ? item . transition ( axis ) . targetValue
44+ : item [ axis ] ;
45+ }
46+
47+ _waitForTransition ( item , axis ) {
48+ return new Promise ( resolve =>
49+ item . _getTransition ( axis ) . on ( 'finish' , resolve )
50+ ) ;
3851 }
3952
53+ // Selection and focus management
4054 get selectedIndex ( ) {
41- return this . _selectedIndex ;
55+ return super . selectedIndex ;
4256 }
57+
4358 set selectedIndex ( index ) {
44- if ( ! this . isEditing ) {
45- super . selectedIndex = index ;
46- return ;
47- }
4859 if (
49- this . selectedIndex >= this . items . length - 1 &&
50- index > this . selectedIndex
60+ ! this . isEditing ||
61+ ( this . selectedIndex >= this . items . length - 1 &&
62+ index > this . selectedIndex )
5163 ) {
64+ if ( ! this . isEditing ) {
65+ super . selectedIndex = index ;
66+ }
5267 return ;
5368 }
69+
5470 const currentItem = this . selected ;
5571 this . prevSelected = currentItem ;
5672 const nextItem = this . items [ index ] ;
5773 const previousIndex = this . selectedIndex ;
58- const oldPosX = currentItem . transition ( 'x' )
59- ? currentItem . transition ( 'x' ) . targetValue
60- : currentItem . x ;
61- const oldPosY = currentItem . transition ( 'y' )
62- ? currentItem . transition ( 'y' ) . targetValue
63- : currentItem . y ;
64- const newPosX = nextItem . transition ( 'x' )
65- ? nextItem . transition ( 'x' ) . targetValue
66- : nextItem . x ;
67- const newPosY = nextItem . transition ( 'y' )
68- ? nextItem . transition ( 'y' ) . targetValue
69- : nextItem . y ;
74+
75+ const oldPos = {
76+ x : this . _getPositionValue ( currentItem , 'x' ) ,
77+ y : this . _getPositionValue ( currentItem , 'y' )
78+ } ;
79+ const newPos = {
80+ x : this . _getPositionValue ( nextItem , 'x' ) ,
81+ y : this . _getPositionValue ( nextItem , 'y' )
82+ } ;
83+ const previousCurrentItemZIndex = currentItem . zIndex ;
84+ currentItem . zIndex = previousCurrentItemZIndex + 1 ; // Current item should appear to be on top of other items
7085
7186 this . _swapItemArrayPos ( this . items , index , previousIndex ) ;
87+ currentItem . setSmooth ( 'x' , newPos . x ) ;
88+ currentItem . setSmooth ( 'y' , newPos . y ) ;
89+ nextItem . setSmooth ( 'x' , oldPos . x ) ;
90+ nextItem . setSmooth ( 'y' , oldPos . y ) ;
7291
73- // self invoking async function that waits for setSmooth calls to complete before triggering
74- // render and signaling selected changed event.
75- // This allows time for items to be in their final position before the row component check world context
76- // to identify items off screen to trigger scrolling
7792 ( async ( ) => {
78- await currentItem . setSmooth ( 'x' , newPosX ) ;
79- await currentItem . setSmooth ( 'y' , newPosY ) ;
80- await nextItem . setSmooth ( 'x' , oldPosX ) ;
81- await nextItem . setSmooth ( 'y' , oldPosY ) ;
93+ await Promise . all ( [
94+ this . _waitForTransition ( currentItem , 'x' ) ,
95+ this . _waitForTransition ( currentItem , 'y' ) ,
96+ this . _waitForTransition ( nextItem , 'x' ) ,
97+ this . _waitForTransition ( nextItem , 'y' )
98+ ] ) ;
99+
100+ currentItem . zIndex = previousCurrentItemZIndex ; // Reset zIndex
101+
82102 if (
83103 ! this . Items . children . length ||
84- ! this . Items . children [ index ] ||
85- ! this . Items . children [ index ] . skipFocus
104+ ! this . Items . children [ index ] ?. skipFocus
86105 ) {
87- if ( this . selected ) {
88- this . _selectedIndex = index ;
89- this . _render ( this . selected , this . prevSelected ) ;
90- this . signal ( 'selectedChange' , this . selected , this . prevSelected ) ;
91- }
92- // Don't call refocus until after a new render in case of a situation like Plinko nav
93- // where we don't want to focus the previously selected item and need to get the new one first
106+ this . _selectedIndex = index ;
107+ this . _render ( this . selected , this . prevSelected ) ;
108+ this . signal ( 'selectedChange' , this . selected , this . prevSelected ) ;
94109 this . _refocus ( ) ;
95110 }
96111 } ) ( ) ;
97112 }
113+
114+ _selectedChange ( selected , prevSelected ) {
115+ if ( this . isEditing ) return ;
116+ this . _render ( selected , prevSelected ) ;
117+ this . signal ( 'selectedChange' , selected , prevSelected ) ;
118+ }
98119 } ;
99120}
0 commit comments