8
8
9
9
import { computed } from '@angular/core' ;
10
10
import { 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' ;
14
12
import { SignalLike } from '../behaviors/signal-like/signal-like' ;
15
13
import { RadioButtonPattern } from './radio-button' ;
16
14
17
- /** The selection operations that the radio group can perform. */
18
- interface SelectOptions {
19
- selectOne ?: boolean ;
20
- }
21
-
22
15
/** 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
+ } ;
32
26
33
27
/** Controls the state of a radio group. */
34
28
export 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 > ;
43
31
44
32
/** Whether the radio group is vertically or horizontally oriented. */
45
33
orientation : SignalLike < 'vertical' | 'horizontal' > ;
46
34
47
35
/** Whether the radio group is disabled. */
48
- disabled = computed ( ( ) => this . inputs . disabled ( ) || this . focusManager . isListDisabled ( ) ) ;
36
+ disabled = computed ( ( ) => this . inputs . disabled ( ) || this . listBehavior . disabled ( ) ) ;
49
37
50
38
/** The currently selected radio button. */
51
- selectedItem = computed ( ( ) => this . selection . selectedItems ( ) [ 0 ] ) ;
39
+ selectedItem = computed ( ( ) => this . listBehavior . selectionBehavior . selectedItems ( ) [ 0 ] ) ;
52
40
53
41
/** Whether the radio group is readonly. */
54
42
readonly = computed ( ( ) => this . selectedItem ( ) ?. disabled ( ) || this . inputs . readonly ( ) ) ;
55
43
56
44
/** The tabindex of the radio group (if using activedescendant). */
57
- tabindex = computed ( ( ) => this . focusManager . getListTabindex ( ) ) ;
45
+ tabindex = computed ( ( ) => this . listBehavior . tabindex ( ) ) ;
58
46
59
47
/** The id of the current active radio button (if using activedescendant). */
60
- activedescendant = computed ( ( ) => this . focusManager . getActiveDescendant ( ) ) ;
48
+ activedescendant = computed ( ( ) => this . listBehavior . activedescendant ( ) ) ;
61
49
62
50
/** The key used to navigate to the previous radio button. */
63
51
prevKey = computed ( ( ) => {
@@ -82,21 +70,21 @@ export class RadioGroupPattern<V> {
82
70
// Readonly mode allows navigation but not selection changes.
83
71
if ( this . readonly ( ) ) {
84
72
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 ( ) ) ;
89
77
}
90
78
91
79
// Default behavior: navigate and select on arrow keys, home, end.
92
80
// Space/Enter also select the focused item.
93
81
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 ( ) ) ;
100
88
} ) ;
101
89
102
90
/** The pointerdown event manager for the radio group. */
@@ -105,27 +93,22 @@ export class RadioGroupPattern<V> {
105
93
106
94
if ( this . readonly ( ) ) {
107
95
// 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 ) ! ) ) ;
109
97
}
110
98
111
99
// 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 } ) ) ;
113
101
} ) ;
114
102
115
103
constructor ( readonly inputs : RadioGroupInputs < V > ) {
116
104
this . orientation = inputs . orientation ;
117
105
118
- this . focusManager = new ListFocus ( inputs ) ;
119
- this . navigation = new ListNavigation ( {
106
+ this . listBehavior = new List ( {
120
107
...inputs ,
121
108
wrap : ( ) => false ,
122
- focusManager : this . focusManager ,
123
- } ) ;
124
- this . selection = new ListSelection ( {
125
- ...inputs ,
126
109
multi : ( ) => false ,
127
110
selectionMode : ( ) => 'follow' ,
128
- focusManager : this . focusManager ,
111
+ typeaheadDelay : ( ) => 0 , // Radio groups do not support typeahead.
129
112
} ) ;
130
113
}
131
114
@@ -143,32 +126,6 @@ export class RadioGroupPattern<V> {
143
126
}
144
127
}
145
128
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
-
172
129
/**
173
130
* Sets the radio group to its default initial state.
174
131
*
@@ -179,7 +136,7 @@ export class RadioGroupPattern<V> {
179
136
let firstItem : RadioButtonPattern < V > | null = null ;
180
137
181
138
for ( const item of this . inputs . items ( ) ) {
182
- if ( this . focusManager . isFocusable ( item ) ) {
139
+ if ( this . listBehavior . isFocusable ( item ) ) {
183
140
if ( ! firstItem ) {
184
141
firstItem = item ;
185
142
}
@@ -208,14 +165,6 @@ export class RadioGroupPattern<V> {
208
165
return violations ;
209
166
}
210
167
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
-
219
168
/** Finds the RadioButtonPattern associated with a pointer event target. */
220
169
private _getItem ( e : PointerEvent ) : RadioButtonPattern < V > | undefined {
221
170
if ( ! ( e . target instanceof HTMLElement ) ) {
0 commit comments