@@ -30,6 +30,15 @@ export interface ComboboxInputs<T extends ListItem<V>, V> {
3030
3131 /** The value of the first matching item in the popup. */
3232 firstMatch : SignalLike < V | undefined > ;
33+
34+ /** Whether the combobox is disabled. */
35+ disabled : SignalLike < boolean > ;
36+
37+ /** Whether the combobox is read-only. */
38+ readonly : SignalLike < boolean > ;
39+
40+ /** Whether the combobox is in a right-to-left context. */
41+ textDirection : SignalLike < 'rtl' | 'ltr' > ;
3342}
3443
3544/** An interface that allows combobox popups to expose the necessary controls for the combobox. */
@@ -119,10 +128,12 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
119128 isFocused = signal ( false ) ;
120129
121130 /** The key used to navigate to the previous item in the list. */
122- expandKey = computed ( ( ) => 'ArrowRight' ) ; // TODO: RTL support.
131+ expandKey = computed ( ( ) => ( this . inputs . textDirection ( ) === 'rtl' ? 'ArrowLeft' : 'ArrowRight' ) ) ;
123132
124133 /** The key used to navigate to the next item in the list. */
125- collapseKey = computed ( ( ) => 'ArrowLeft' ) ; // TODO: RTL support.
134+ collapseKey = computed ( ( ) =>
135+ this . inputs . textDirection ( ) === 'rtl' ? 'ArrowRight' : 'ArrowLeft' ,
136+ ) ;
126137
127138 /** The ID of the popup associated with the combobox. */
128139 popupId = computed ( ( ) => this . inputs . popupControls ( ) ?. id ( ) || null ) ;
@@ -204,16 +215,24 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
204215
205216 /** Handles keydown events for the combobox. */
206217 onKeydown ( event : KeyboardEvent ) {
207- this . keydown ( ) . handle ( event ) ;
218+ if ( ! this . inputs . disabled ( ) && ! this . inputs . readonly ( ) ) {
219+ this . keydown ( ) . handle ( event ) ;
220+ }
208221 }
209222
210223 /** Handles pointerup events for the combobox. */
211224 onPointerup ( event : PointerEvent ) {
212- this . pointerup ( ) . handle ( event ) ;
225+ if ( ! this . inputs . disabled ( ) && ! this . inputs . readonly ( ) ) {
226+ this . pointerup ( ) . handle ( event ) ;
227+ }
213228 }
214229
215230 /** Handles input events for the combobox. */
216231 onInput ( event : Event ) {
232+ if ( this . inputs . disabled ( ) || this . inputs . readonly ( ) ) {
233+ return ;
234+ }
235+
217236 const inputEl = this . inputs . inputEl ( ) ;
218237
219238 if ( ! inputEl ) {
@@ -233,12 +252,17 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
233252 }
234253 }
235254
255+ /** Handles focus in events for the combobox. */
236256 onFocusIn ( ) {
237257 this . isFocused . set ( true ) ;
238258 }
239259
240260 /** Handles focus out events for the combobox. */
241261 onFocusOut ( event : FocusEvent ) {
262+ if ( this . inputs . disabled ( ) || this . inputs . readonly ( ) ) {
263+ return ;
264+ }
265+
242266 if (
243267 ! ( event . relatedTarget instanceof HTMLElement ) ||
244268 ! this . inputs . containerEl ( ) ?. contains ( event . relatedTarget )
@@ -261,6 +285,7 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
261285 }
262286 }
263287
288+ /** The first matching item in the combobox. */
264289 firstMatch = computed ( ( ) => {
265290 // TODO(wagnermaciel): Consider whether we should not provide this default behavior for the
266291 // listbox. Instead, we may want to allow users to have no match so that typing does not focus
@@ -275,6 +300,7 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
275300 . find ( i => i . value ( ) === this . inputs . firstMatch ( ) ) ;
276301 } ) ;
277302
303+ /** Handles filtering logic for the combobox. */
278304 onFilter ( ) {
279305 // TODO(wagnermaciel)
280306 // When the user first interacts with the combobox, the popup will lazily render for the first
@@ -315,6 +341,7 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
315341 }
316342 }
317343
344+ /** Highlights the currently selected item in the combobox. */
318345 highlight ( ) {
319346 const inputEl = this . inputs . inputEl ( ) ;
320347 const item = this . inputs . popupControls ( ) ?. getSelectedItem ( ) ;
@@ -374,11 +401,13 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
374401 this . _navigate ( ( ) => this . inputs . popupControls ( ) ?. last ( ) ) ;
375402 }
376403
404+ /** Collapses the currently focused item in the combobox. */
377405 collapseItem ( ) {
378406 const controls = this . inputs . popupControls ( ) as ComboboxTreeControls < T , V > ;
379407 this . _navigate ( ( ) => controls ?. collapseItem ( ) ) ;
380408 }
381409
410+ /** Expands the currently focused item in the combobox. */
382411 expandItem ( ) {
383412 const controls = this . inputs . popupControls ( ) as ComboboxTreeControls < T , V > ;
384413 this . _navigate ( ( ) => controls ?. expandItem ( ) ) ;
0 commit comments