88
99import { computed } from '@angular/core' ;
1010import { KeyboardEventManager , PointerEventManager } from '../behaviors/event-manager' ;
11- import { ListFocus , ListFocusInputs } from '../behaviors/list-focus/list-focus' ;
12- import { ListNavigation , ListNavigationInputs } from '../behaviors/list-navigation/list-navigation' ;
13- import { ListSelection , ListSelectionInputs } from '../behaviors/list-selection/list-selection' ;
11+ import { List , ListInputs } from '../behaviors/list/list' ;
1412import { SignalLike } from '../behaviors/signal-like/signal-like' ;
1513import { RadioButtonPattern } from './radio-button' ;
1614
17- /** The selection operations that the radio group can perform. */
18- interface SelectOptions {
19- selectOne ?: boolean ;
20- }
21-
2215/** Represents the required inputs for a radio group. */
23- export type RadioGroupInputs < V > = Omit < ListNavigationInputs < RadioButtonPattern < V > > , 'wrap' > &
24- // Radio groups are always single-select.
25- Omit < ListSelectionInputs < RadioButtonPattern < V > , V > , 'multi' | 'selectionMode' > &
26- ListFocusInputs < RadioButtonPattern < V > > & {
27- /** Whether the radio group is disabled. */
28- disabled : SignalLike < boolean > ;
29- /** Whether the radio group is readonly. */
30- readonly : SignalLike < boolean > ;
31- } ;
16+ export type RadioGroupInputs < V > = Omit <
17+ ListInputs < RadioButtonPattern < V > , V > ,
18+ 'multi' | 'selectionMode' | 'wrap' | 'typeaheadDelay'
19+ > & {
20+ /** Whether the radio group is disabled. */
21+ disabled : SignalLike < boolean > ;
22+
23+ /** Whether the radio group is readonly. */
24+ readonly : SignalLike < boolean > ;
25+ } ;
3226
3327/** Controls the state of a radio group. */
3428export class RadioGroupPattern < V > {
35- /** Controls navigation for the radio group. */
36- navigation : ListNavigation < RadioButtonPattern < V > > ;
37-
38- /** Controls selection for the radio group. */
39- selection : ListSelection < RadioButtonPattern < V > , V > ;
40-
41- /** Controls focus for the radio group. */
42- focusManager : ListFocus < RadioButtonPattern < V > > ;
29+ /** The list behavior for the radio group. */
30+ readonly listBehavior : List < RadioButtonPattern < V > , V > ;
4331
4432 /** Whether the radio group is vertically or horizontally oriented. */
4533 orientation : SignalLike < 'vertical' | 'horizontal' > ;
4634
4735 /** Whether the radio group is disabled. */
48- disabled = computed ( ( ) => this . inputs . disabled ( ) || this . focusManager . isListDisabled ( ) ) ;
36+ disabled = computed ( ( ) => this . inputs . disabled ( ) || this . listBehavior . disabled ( ) ) ;
4937
5038 /** The currently selected radio button. */
51- selectedItem = computed ( ( ) => this . selection . selectedItems ( ) [ 0 ] ) ;
39+ selectedItem = computed ( ( ) => this . listBehavior . selectionBehavior . selectedItems ( ) [ 0 ] ) ;
5240
5341 /** Whether the radio group is readonly. */
5442 readonly = computed ( ( ) => this . selectedItem ( ) ?. disabled ( ) || this . inputs . readonly ( ) ) ;
5543
5644 /** The tabindex of the radio group (if using activedescendant). */
57- tabindex = computed ( ( ) => this . focusManager . getListTabindex ( ) ) ;
45+ tabindex = computed ( ( ) => this . listBehavior . tabindex ( ) ) ;
5846
5947 /** The id of the current active radio button (if using activedescendant). */
60- activedescendant = computed ( ( ) => this . focusManager . getActiveDescendant ( ) ) ;
48+ activedescendant = computed ( ( ) => this . listBehavior . activedescendant ( ) ) ;
6149
6250 /** The key used to navigate to the previous radio button. */
6351 prevKey = computed ( ( ) => {
@@ -82,21 +70,21 @@ export class RadioGroupPattern<V> {
8270 // Readonly mode allows navigation but not selection changes.
8371 if ( this . readonly ( ) ) {
8472 return manager
85- . on ( this . prevKey , ( ) => this . prev ( ) )
86- . on ( this . nextKey , ( ) => this . next ( ) )
87- . on ( 'Home' , ( ) => this . first ( ) )
88- . on ( 'End' , ( ) => this . last ( ) ) ;
73+ . on ( this . prevKey , ( ) => this . listBehavior . prev ( ) )
74+ . on ( this . nextKey , ( ) => this . listBehavior . next ( ) )
75+ . on ( 'Home' , ( ) => this . listBehavior . first ( ) )
76+ . on ( 'End' , ( ) => this . listBehavior . last ( ) ) ;
8977 }
9078
9179 // Default behavior: navigate and select on arrow keys, home, end.
9280 // Space/Enter also select the focused item.
9381 return manager
94- . on ( this . prevKey , ( ) => this . prev ( { selectOne : true } ) )
95- . on ( this . nextKey , ( ) => this . next ( { selectOne : true } ) )
96- . on ( 'Home' , ( ) => this . first ( { selectOne : true } ) )
97- . on ( 'End' , ( ) => this . last ( { selectOne : true } ) )
98- . on ( ' ' , ( ) => this . selection . selectOne ( ) )
99- . on ( 'Enter' , ( ) => this . selection . selectOne ( ) ) ;
82+ . on ( this . prevKey , ( ) => this . listBehavior . prev ( { selectOne : true } ) )
83+ . on ( this . nextKey , ( ) => this . listBehavior . next ( { selectOne : true } ) )
84+ . on ( 'Home' , ( ) => this . listBehavior . first ( { selectOne : true } ) )
85+ . on ( 'End' , ( ) => this . listBehavior . last ( { selectOne : true } ) )
86+ . on ( ' ' , ( ) => this . listBehavior . selectOne ( ) )
87+ . on ( 'Enter' , ( ) => this . listBehavior . selectOne ( ) ) ;
10088 } ) ;
10189
10290 /** The pointerdown event manager for the radio group. */
@@ -105,27 +93,22 @@ export class RadioGroupPattern<V> {
10593
10694 if ( this . readonly ( ) ) {
10795 // Navigate focus only in readonly mode.
108- return manager . on ( e => this . goto ( e ) ) ;
96+ return manager . on ( e => this . listBehavior . goto ( this . _getItem ( e ) ! ) ) ;
10997 }
11098
11199 // Default behavior: navigate and select on click.
112- return manager . on ( e => this . goto ( e , { selectOne : true } ) ) ;
100+ return manager . on ( e => this . listBehavior . goto ( this . _getItem ( e ) ! , { selectOne : true } ) ) ;
113101 } ) ;
114102
115103 constructor ( readonly inputs : RadioGroupInputs < V > ) {
116104 this . orientation = inputs . orientation ;
117105
118- this . focusManager = new ListFocus ( inputs ) ;
119- this . navigation = new ListNavigation ( {
106+ this . listBehavior = new List ( {
120107 ...inputs ,
121108 wrap : ( ) => false ,
122- focusManager : this . focusManager ,
123- } ) ;
124- this . selection = new ListSelection ( {
125- ...inputs ,
126109 multi : ( ) => false ,
127110 selectionMode : ( ) => 'follow' ,
128- focusManager : this . focusManager ,
111+ typeaheadDelay : ( ) => 0 , // Radio groups do not support typeahead.
129112 } ) ;
130113 }
131114
@@ -143,32 +126,6 @@ export class RadioGroupPattern<V> {
143126 }
144127 }
145128
146- /** Navigates to the first enabled radio button in the group. */
147- first ( opts ?: SelectOptions ) {
148- this . _navigate ( opts , ( ) => this . navigation . first ( ) ) ;
149- }
150-
151- /** Navigates to the last enabled radio button in the group. */
152- last ( opts ?: SelectOptions ) {
153- this . _navigate ( opts , ( ) => this . navigation . last ( ) ) ;
154- }
155-
156- /** Navigates to the next enabled radio button in the group. */
157- next ( opts ?: SelectOptions ) {
158- this . _navigate ( opts , ( ) => this . navigation . next ( ) ) ;
159- }
160-
161- /** Navigates to the previous enabled radio button in the group. */
162- prev ( opts ?: SelectOptions ) {
163- this . _navigate ( opts , ( ) => this . navigation . prev ( ) ) ;
164- }
165-
166- /** Navigates to the radio button associated with the given pointer event. */
167- goto ( event : PointerEvent , opts ?: SelectOptions ) {
168- const item = this . _getItem ( event ) ;
169- this . _navigate ( opts , ( ) => this . navigation . goto ( item ) ) ;
170- }
171-
172129 /**
173130 * Sets the radio group to its default initial state.
174131 *
@@ -179,7 +136,7 @@ export class RadioGroupPattern<V> {
179136 let firstItem : RadioButtonPattern < V > | null = null ;
180137
181138 for ( const item of this . inputs . items ( ) ) {
182- if ( this . focusManager . isFocusable ( item ) ) {
139+ if ( this . listBehavior . isFocusable ( item ) ) {
183140 if ( ! firstItem ) {
184141 firstItem = item ;
185142 }
@@ -208,14 +165,6 @@ export class RadioGroupPattern<V> {
208165 return violations ;
209166 }
210167
211- /** Safely performs a navigation operation and updates selection if needed. */
212- private _navigate ( opts : SelectOptions = { } , operation : ( ) => boolean ) {
213- const moved = operation ( ) ;
214- if ( moved && opts . selectOne ) {
215- this . selection . selectOne ( ) ;
216- }
217- }
218-
219168 /** Finds the RadioButtonPattern associated with a pointer event target. */
220169 private _getItem ( e : PointerEvent ) : RadioButtonPattern < V > | undefined {
221170 if ( ! ( e . target instanceof HTMLElement ) ) {
0 commit comments