@@ -21,6 +21,7 @@ export class OPContextMenuService {
2121
2222 // Allow temporarily disabling the close handler
2323 private isOpening = false ;
24+ private openSeq = 0 ;
2425
2526 constructor (
2627 readonly FocusHelper :FocusHelperService ,
@@ -83,20 +84,33 @@ export class OPContextMenuService {
8384 */
8485 public show ( menu :OpContextMenuHandler , event :Event , component :ComponentType < unknown > = OPContextMenuComponent ) :void {
8586 this . close ( ) ;
87+ this . isOpening = true ;
88+
89+ // eslint-disable-next-line no-plusplus
90+ const seq = ++ this . openSeq ;
8691
8792 // Create a portal for the given component class and render it
88- this . isOpening = true ;
8993 const portal = new ComponentPortal ( component , null , this . injectorFor ( menu . locals ) ) ;
9094 this . bodyPortalHost . attach ( portal ) ;
9195 this . portalHostElement . style . display = 'block' ;
9296 this . active = menu ;
9397
94- setTimeout ( ( ) => {
95- this . reposition ( event ) ;
96- // Focus on the first element
97- this . active ?. onOpen ( this . activeMenu ) ;
98- this . isOpening = false ;
99- } ) ;
98+ void this . reposition ( event )
99+ . then ( ( ) => {
100+ // Defer onOpen to the next frame to ensure DOM/styles are applied
101+ if ( this . active && this . openSeq === seq ) {
102+ requestAnimationFrame ( ( ) => {
103+ if ( this . active && this . openSeq === seq ) {
104+ this . active . onOpen ( this . activeMenu ) ;
105+ }
106+ } ) ;
107+ }
108+ } )
109+ . finally ( ( ) => {
110+ if ( this . openSeq === seq ) {
111+ this . isOpening = false ;
112+ }
113+ } ) ;
100114 }
101115
102116 public isActive ( menu :OpContextMenuHandler ) :boolean {
@@ -118,12 +132,12 @@ export class OPContextMenuService {
118132 this . active = null ;
119133 }
120134
121- public reposition ( event :Event ) :void {
135+ public reposition ( event :Event ) :Promise < void > {
122136 if ( ! this . active ) {
123- return ;
137+ return Promise . resolve ( ) ;
124138 }
125139
126- this . active . computePosition ( this . activeMenu , event )
140+ return this . active . computePosition ( this . activeMenu , event )
127141 . then ( ( { x, y } ) => {
128142 Object . assign ( this . activeMenu . style , {
129143 left : `${ x } px` ,
0 commit comments