88
99import { computed } from '@angular/core' ;
1010import { KeyboardEventManager , PointerEventManager } from '../behaviors/event-manager' ;
11- import { ListFocus , ListFocusInputs , ListFocusItem } from '../behaviors/list-focus/list-focus' ;
12- import {
13- ListNavigation ,
14- ListNavigationInputs ,
15- ListNavigationItem ,
16- } from '../behaviors/list-navigation/list-navigation' ;
17- import {
18- ListSelection ,
19- ListSelectionInputs ,
20- ListSelectionItem ,
21- } from '../behaviors/list-selection/list-selection' ;
2211import {
2312 ExpansionItem ,
2413 ExpansionControl ,
@@ -27,12 +16,11 @@ import {
2716} from '../behaviors/expansion/expansion' ;
2817import { SignalLike } from '../behaviors/signal-like/signal-like' ;
2918import { LabelControl , LabelControlOptionalInputs } from '../behaviors/label/label' ;
19+ import { List , ListInputs , ListItem } from '../behaviors/list/list' ;
3020
3121/** The required inputs to tabs. */
3222export interface TabInputs
33- extends ListNavigationItem ,
34- ListSelectionItem < string > ,
35- ListFocusItem ,
23+ extends Omit < ListItem < string > , 'searchTerm' > ,
3624 Omit < ExpansionItem , 'expansionId' | 'expandable' > {
3725 /** The parent tablist that controls the tab. */
3826 tablist : SignalLike < TabListPattern > ;
@@ -58,6 +46,9 @@ export class TabPattern {
5846 /** The html element that should receive focus. */
5947 readonly element : SignalLike < HTMLElement > ;
6048
49+ /** The text used by the typeahead search. */
50+ readonly searchTerm = ( ) => '' ; // Unused because tabs do not support typeahead.
51+
6152 /** Whether this tab has expandable content. */
6253 readonly expandable = computed ( ( ) => this . expansion . expandable ( ) ) ;
6354
@@ -68,15 +59,13 @@ export class TabPattern {
6859 readonly expanded = computed ( ( ) => this . expansion . isExpanded ( ) ) ;
6960
7061 /** Whether the tab is active. */
71- readonly active = computed ( ( ) => this . inputs . tablist ( ) . focusManager . activeItem ( ) === this ) ;
62+ readonly active = computed ( ( ) => this . inputs . tablist ( ) . listBehavior . activeItem ( ) === this ) ;
7263
7364 /** Whether the tab is selected. */
74- readonly selected = computed (
75- ( ) => ! ! this . inputs . tablist ( ) . selection . inputs . value ( ) . includes ( this . value ( ) ) ,
76- ) ;
65+ readonly selected = computed ( ( ) => ! ! this . inputs . tablist ( ) . inputs . value ( ) . includes ( this . value ( ) ) ) ;
7766
7867 /** The tabindex of the tab. */
79- readonly tabindex = computed ( ( ) => this . inputs . tablist ( ) . focusManager . getItemTabindex ( this ) ) ;
68+ readonly tabindex = computed ( ( ) => this . inputs . tablist ( ) . listBehavior . getItemTabindex ( this ) ) ;
8069
8170 /** The id of the tabpanel associated with the tab. */
8271 readonly controls = computed ( ( ) => this . inputs . tabpanel ( ) ?. id ( ) ) ;
@@ -136,27 +125,14 @@ export class TabPanelPattern {
136125 }
137126}
138127
139- /** The selection operations that the tablist can perform. */
140- interface SelectOptions {
141- select ?: boolean ;
142- }
143-
144128/** The required inputs for the tablist. */
145- export type TabListInputs = ListNavigationInputs < TabPattern > &
146- Omit < ListSelectionInputs < TabPattern , string > , 'multi' > &
147- ListFocusInputs < TabPattern > &
129+ export type TabListInputs = Omit < ListInputs < TabPattern , string > , 'multi' | 'typeaheadDelay' > &
148130 Omit < ListExpansionInputs , 'multiExpandable' | 'expandedIds' | 'items' > ;
149131
150132/** Controls the state of a tablist. */
151133export class TabListPattern {
152- /** Controls navigation for the tablist. */
153- readonly navigation : ListNavigation < TabPattern > ;
154-
155- /** Controls selection for the tablist. */
156- readonly selection : ListSelection < TabPattern , string > ;
157-
158- /** Controls focus for the tablist. */
159- readonly focusManager : ListFocus < TabPattern > ;
134+ /** The list behavior for the tablist. */
135+ readonly listBehavior : List < TabPattern , string > ;
160136
161137 /** Controls expansion for the tablist. */
162138 readonly expansionManager : ListExpansion ;
@@ -168,10 +144,10 @@ export class TabListPattern {
168144 readonly disabled : SignalLike < boolean > ;
169145
170146 /** The tabindex of the tablist. */
171- readonly tabindex = computed ( ( ) => this . focusManager . getListTabindex ( ) ) ;
147+ readonly tabindex = computed ( ( ) => this . listBehavior . tabindex ( ) ) ;
172148
173149 /** The id of the current active tab. */
174- readonly activedescendant = computed ( ( ) => this . focusManager . getActiveDescendant ( ) ) ;
150+ readonly activedescendant = computed ( ( ) => this . listBehavior . activedescendant ( ) ) ;
175151
176152 /** Whether selection should follow focus. */
177153 readonly followFocus = computed ( ( ) => this . inputs . selectionMode ( ) === 'follow' ) ;
@@ -195,30 +171,29 @@ export class TabListPattern {
195171 /** The keydown event manager for the tablist. */
196172 readonly keydown = computed ( ( ) => {
197173 return new KeyboardEventManager ( )
198- . on ( this . prevKey , ( ) => this . prev ( { select : this . followFocus ( ) } ) )
199- . on ( this . nextKey , ( ) => this . next ( { select : this . followFocus ( ) } ) )
200- . on ( 'Home' , ( ) => this . first ( { select : this . followFocus ( ) } ) )
201- . on ( 'End' , ( ) => this . last ( { select : this . followFocus ( ) } ) )
202- . on ( ' ' , ( ) => this . _select ( { select : true } ) )
203- . on ( 'Enter' , ( ) => this . _select ( { select : true } ) ) ;
174+ . on ( this . prevKey , ( ) => this . listBehavior . prev ( { select : this . followFocus ( ) } ) )
175+ . on ( this . nextKey , ( ) => this . listBehavior . next ( { select : this . followFocus ( ) } ) )
176+ . on ( 'Home' , ( ) => this . listBehavior . first ( { select : this . followFocus ( ) } ) )
177+ . on ( 'End' , ( ) => this . listBehavior . last ( { select : this . followFocus ( ) } ) )
178+ . on ( ' ' , ( ) => this . listBehavior . select ( ) )
179+ . on ( 'Enter' , ( ) => this . listBehavior . select ( ) ) ;
204180 } ) ;
205181
206182 /** The pointerdown event manager for the tablist. */
207183 readonly pointerdown = computed ( ( ) => {
208- return new PointerEventManager ( ) . on ( e => this . goto ( e , { select : true } ) ) ;
184+ return new PointerEventManager ( ) . on ( e =>
185+ this . listBehavior . goto ( this . _getItem ( e ) ! , { select : true } ) ,
186+ ) ;
209187 } ) ;
210188
211189 constructor ( readonly inputs : TabListInputs ) {
212190 this . disabled = inputs . disabled ;
213191 this . orientation = inputs . orientation ;
214192
215- this . focusManager = new ListFocus ( inputs ) ;
216- this . navigation = new ListNavigation ( { ...inputs , focusManager : this . focusManager } ) ;
217-
218- this . selection = new ListSelection ( {
193+ this . listBehavior = new List ( {
219194 ...inputs ,
220195 multi : ( ) => false ,
221- focusManager : this . focusManager ,
196+ typeaheadDelay : ( ) => 0 , // Tabs do not support typeahead.
222197 } ) ;
223198
224199 this . expansionManager = new ListExpansion ( {
@@ -240,7 +215,7 @@ export class TabListPattern {
240215 let firstItemIndex : number | undefined ;
241216
242217 for ( const [ index , item ] of this . inputs . items ( ) . entries ( ) ) {
243- if ( ! this . focusManager . isFocusable ( item ) ) continue ;
218+ if ( ! this . listBehavior . isFocusable ( item ) ) continue ;
244219
245220 if ( firstItemIndex === undefined ) {
246221 firstItemIndex = index ;
@@ -270,48 +245,7 @@ export class TabListPattern {
270245 }
271246 }
272247
273- /** Navigates to the first option in the tablist. */
274- first ( opts ?: SelectOptions ) {
275- this . navigation . first ( ) ;
276- this . _select ( opts ) ;
277- }
278-
279- /** Navigates to the last option in the tablist. */
280- last ( opts ?: SelectOptions ) {
281- this . navigation . last ( ) ;
282- this . _select ( opts ) ;
283- }
284-
285- /** Navigates to the next option in the tablist. */
286- next ( opts ?: SelectOptions ) {
287- this . navigation . next ( ) ;
288- this . _select ( opts ) ;
289- }
290-
291- /** Navigates to the previous option in the tablist. */
292- prev ( opts ?: SelectOptions ) {
293- this . navigation . prev ( ) ;
294- this . _select ( opts ) ;
295- }
296-
297- /** Navigates to the given item in the tablist. */
298- goto ( event : PointerEvent , opts ?: SelectOptions ) {
299- const item = this . _getItem ( event ) ;
300-
301- if ( item ) {
302- this . navigation . goto ( item ) ;
303- this . _select ( opts ) ;
304- }
305- }
306-
307- /** Handles updating selection for the tablist. */
308- private _select ( opts ?: SelectOptions ) {
309- if ( opts ?. select ) {
310- this . selection . selectOne ( ) ;
311- this . expansionManager . open ( this . focusManager . activeItem ( ) ) ;
312- }
313- }
314-
248+ /** Returns the tab item associated with the given pointer event. */
315249 private _getItem ( e : PointerEvent ) {
316250 if ( ! ( e . target instanceof HTMLElement ) ) {
317251 return ;
0 commit comments