11import { Controller } from "@hotwired/stimulus" ;
2- import { computePosition , flip , shift , offset } from "@floating-ui/dom" ;
2+ import {
3+ computePosition ,
4+ flip ,
5+ shift ,
6+ offset ,
7+ autoUpdate ,
8+ } from "@floating-ui/dom" ;
39
410export default class extends Controller {
511 static targets = [ "trigger" , "content" , "menuItem" ] ;
@@ -12,17 +18,34 @@ export default class extends Controller {
1218 type : Object ,
1319 default : { } ,
1420 } ,
15- }
21+ } ;
1622
1723 connect ( ) {
1824 this . boundHandleKeydown = this . #handleKeydown. bind ( this ) ; // Bind the function so we can remove it later
1925 this . selectedIndex = - 1 ;
26+
27+ this . #setupAutoUpdate( ) ;
28+ }
29+
30+ disconnect ( ) {
31+ if ( this . autoUpdateCleanup ) {
32+ this . autoUpdateCleanup ( ) ;
33+ }
34+ }
35+
36+ #setupAutoUpdate( ) {
37+ this . autoUpdateCleanup = autoUpdate (
38+ this . triggerTarget ,
39+ this . contentTarget ,
40+ this . #computeTooltip. bind ( this ) ,
41+ ) ;
2042 }
2143
2244 #computeTooltip( ) {
2345 computePosition ( this . triggerTarget , this . contentTarget , {
2446 placement : this . optionsValue . placement || "top" ,
2547 middleware : [ flip ( ) , shift ( ) , offset ( 8 ) ] ,
48+ strategy : this . optionsValue . strategy || "absolute" ,
2649 } ) . then ( ( { x, y } ) => {
2750 Object . assign ( this . contentTarget . style , {
2851 left : `${ x } px` ,
@@ -40,14 +63,16 @@ export default class extends Controller {
4063 }
4164
4265 toggle ( ) {
43- this . contentTarget . classList . contains ( "hidden" ) ? this . #open( ) : this . close ( ) ;
66+ this . contentTarget . classList . contains ( "hidden" )
67+ ? this . #open( )
68+ : this . close ( ) ;
4469 }
4570
4671 #open( ) {
4772 this . openValue = true ;
4873 this . #deselectAll( ) ;
4974 this . #addEventListeners( ) ;
50- this . #computeTooltip( )
75+ this . #computeTooltip( ) ;
5176 this . contentTarget . classList . remove ( "hidden" ) ;
5277 }
5378
@@ -59,15 +84,17 @@ export default class extends Controller {
5984
6085 #handleKeydown( e ) {
6186 // return if no menu items (one line fix for)
62- if ( this . menuItemTargets . length === 0 ) { return ; }
87+ if ( this . menuItemTargets . length === 0 ) {
88+ return ;
89+ }
6390
64- if ( e . key === ' ArrowDown' ) {
91+ if ( e . key === " ArrowDown" ) {
6592 e . preventDefault ( ) ;
6693 this . #updateSelectedItem( 1 ) ;
67- } else if ( e . key === ' ArrowUp' ) {
94+ } else if ( e . key === " ArrowUp" ) {
6895 e . preventDefault ( ) ;
6996 this . #updateSelectedItem( - 1 ) ;
70- } else if ( e . key === ' Enter' && this . selectedIndex !== - 1 ) {
97+ } else if ( e . key === " Enter" && this . selectedIndex !== - 1 ) {
7198 e . preventDefault ( ) ;
7299 this . menuItemTargets [ this . selectedIndex ] . click ( ) ;
73100 }
@@ -76,7 +103,7 @@ export default class extends Controller {
76103 #updateSelectedItem( direction ) {
77104 // Check if any of the menuItemTargets have aria-selected="true" and set the selectedIndex to that index
78105 this . menuItemTargets . forEach ( ( item , index ) => {
79- if ( item . getAttribute ( ' aria-selected' ) === ' true' ) {
106+ if ( item . getAttribute ( " aria-selected" ) === " true" ) {
80107 this . selectedIndex = index ;
81108 }
82109 } ) ;
@@ -99,22 +126,24 @@ export default class extends Controller {
99126 #toggleAriaSelected( element , isSelected ) {
100127 // Add or remove attribute
101128 if ( isSelected ) {
102- element . setAttribute ( ' aria-selected' , ' true' ) ;
129+ element . setAttribute ( " aria-selected" , " true" ) ;
103130 } else {
104- element . removeAttribute ( ' aria-selected' ) ;
131+ element . removeAttribute ( " aria-selected" ) ;
105132 }
106133 }
107134
108135 #deselectAll( ) {
109- this . menuItemTargets . forEach ( item => this . #toggleAriaSelected( item , false ) ) ;
136+ this . menuItemTargets . forEach ( ( item ) =>
137+ this . #toggleAriaSelected( item , false ) ,
138+ ) ;
110139 this . selectedIndex = - 1 ;
111140 }
112141
113142 #addEventListeners( ) {
114- document . addEventListener ( ' keydown' , this . boundHandleKeydown ) ;
143+ document . addEventListener ( " keydown" , this . boundHandleKeydown ) ;
115144 }
116145
117146 #removeEventListeners( ) {
118- document . removeEventListener ( ' keydown' , this . boundHandleKeydown ) ;
147+ document . removeEventListener ( " keydown" , this . boundHandleKeydown ) ;
119148 }
120149}
0 commit comments