@@ -27,17 +27,14 @@ const SELECTORS = {
2727export default {
2828 mounted ( ) {
2929 this . initialize ( )
30- this . syncSelectionFromInput ( )
3130 } ,
3231
3332 updated ( ) {
3433 this . initialize ( )
35- this . syncSelectionFromInput ( )
3634 } ,
3735
3836 reconnected ( ) {
3937 this . initialize ( )
40- this . syncSelectionFromInput ( )
4138 } ,
4239
4340 destroyed ( ) {
@@ -48,6 +45,8 @@ export default {
4845 this . cleanup ( )
4946 this . setupElements ( )
5047 this . setupEventListeners ( )
48+ this . syncDisabledState ( )
49+ this . syncSelectionFromInput ( )
5150 this . el . setAttribute ( 'data-prima-ready' , 'true' )
5251 } ,
5352
@@ -75,9 +74,15 @@ export default {
7574 this . syncSelectedState ( option )
7675 } ,
7776
77+ syncDisabledState ( ) {
78+ const disabled = this . el . getAttribute ( 'data-disabled' ) === 'true'
79+ this . refs . button . disabled = disabled
80+ if ( disabled && this . isListboxVisible ( ) ) this . hideListbox ( )
81+ } ,
82+
7883 setupEventListeners ( ) {
7984 this . listeners = [
80- [ this . refs . button , 'click' , this . handleToggle . bind ( this ) ] ,
85+ [ this . refs . button , 'click' , this . toggleListbox . bind ( this ) ] ,
8186 [ document , 'click' , this . handleClickOutside . bind ( this ) ] ,
8287 [ this . refs . listbox , 'mouseover' , this . handleMouseOver . bind ( this ) ] ,
8388 [ this . refs . listbox , 'click' , this . handleListboxClick . bind ( this ) ] ,
@@ -110,6 +115,8 @@ export default {
110115 } ,
111116
112117 handleKeydown ( e ) {
118+ if ( this . refs . button . disabled ) return
119+
113120 const keyHandlers = {
114121 [ KEYS . ARROW_UP ] : ( ) => this . navigateUp ( e ) ,
115122 [ KEYS . ARROW_DOWN ] : ( ) => this . navigateDown ( e ) ,
@@ -231,10 +238,6 @@ export default {
231238 this . setFocus ( matchingOptions [ nextIndex ] )
232239 } ,
233240
234- handleToggle ( ) {
235- this . toggleListbox ( )
236- } ,
237-
238241 handleClickOutside ( e ) {
239242 if ( this . isListboxVisible ( ) && ! this . refs . button . contains ( e . target ) && ! this . refs . listbox . contains ( e . target ) ) {
240243 this . hideListbox ( )
@@ -249,6 +252,8 @@ export default {
249252 } ,
250253
251254 handleListboxClick ( e ) {
255+ if ( this . refs . button . disabled ) return
256+
252257 const option = e . target . closest ( SELECTORS . OPTION )
253258 if ( option && option . getAttribute ( 'aria-disabled' ) !== 'true' ) {
254259 this . selectOption ( option )
@@ -271,9 +276,7 @@ export default {
271276 this . refs . value . textContent = option . getAttribute ( 'data-display' )
272277 } ,
273278
274- // Mount-time sync only: the displayed value is rendered by the caller and is
275- // already correct on first paint, so only the ARIA/visual selection markers
276- // are synced here - the value itself is left untouched.
279+ // Sync selection markers without changing the caller-rendered displayed value.
277280 syncSelectedState ( option ) {
278281 this . el . querySelector ( SELECTORS . SELECTED_OPTION ) ?. removeAttribute ( 'aria-selected' )
279282 this . el . querySelectorAll ( '[data-selected]' ) . forEach ( el => el . removeAttribute ( 'data-selected' ) )
@@ -349,6 +352,8 @@ export default {
349352 } ,
350353
351354 showListboxAndFocus ( optionToFocus ) {
355+ if ( this . refs . button . disabled ) return
356+
352357 // Wrapper pattern: Show wrapper first (display:block) so Floating UI can measure it,
353358 // then position it, then trigger inner listbox transition. This prevents the listbox
354359 // from briefly appearing at wrong position before jumping to correct position.
0 commit comments