@@ -13,6 +13,7 @@ import {ListFocus} from '../list-focus/list-focus';
1313
1414type TestItem = ListSelectionItem < number > & {
1515 disabled : WritableSignal < boolean > ;
16+ selectable : WritableSignal < boolean > ;
1617} ;
1718type TestInputs = Partial < ListSelectionInputs < TestItem , number > > & {
1819 numItems ?: number ;
@@ -40,6 +41,7 @@ function getItems(length: number): Signal<TestItem[]> {
4041 value : signal ( i ) ,
4142 id : signal ( `${ i } ` ) ,
4243 disabled : signal ( false ) ,
44+ selectable : signal ( true ) ,
4345 element : signal ( { focus : ( ) => { } } as HTMLElement ) ,
4446 index : signal ( i ) ,
4547 } ;
@@ -83,6 +85,14 @@ describe('List Selection', () => {
8385 expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
8486 } ) ;
8587
88+ it ( 'should not select non-selectable items' , ( ) => {
89+ const selection = getSelection ( ) ;
90+ const items = selection . inputs . items ( ) as TestItem [ ] ;
91+ items [ 0 ] . selectable . set ( false ) ;
92+ selection . select ( ) ; // []
93+ expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
94+ } ) ;
95+
8696 it ( 'should do nothing to already selected items' , ( ) => {
8797 const selection = getSelection ( ) ;
8898 selection . select ( ) ; // [0]
@@ -106,6 +116,15 @@ describe('List Selection', () => {
106116 selection . deselect ( ) ; // [0]
107117 expect ( selection . inputs . value ( ) ) . toEqual ( [ 0 ] ) ;
108118 } ) ;
119+
120+ it ( 'should not deselect non-selectable items' , ( ) => {
121+ const selection = getSelection ( ) ;
122+ const items = selection . inputs . items ( ) as TestItem [ ] ;
123+ selection . select ( ) ; // [0]
124+ items [ 0 ] . selectable . set ( false ) ;
125+ selection . deselect ( ) ; // [0]
126+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 0 ] ) ;
127+ } ) ;
109128 } ) ;
110129
111130 describe ( '#toggle' , ( ) => {
@@ -121,6 +140,14 @@ describe('List Selection', () => {
121140 selection . toggle ( ) ; // []
122141 expect ( selection . inputs . value ( ) . length ) . toBe ( 0 ) ;
123142 } ) ;
143+
144+ it ( 'should not toggle non-selectable items' , ( ) => {
145+ const selection = getSelection ( ) ;
146+ const items = selection . inputs . items ( ) as TestItem [ ] ;
147+ items [ 0 ] . selectable . set ( false ) ;
148+ selection . toggle ( ) ; // []
149+ expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
150+ } ) ;
124151 } ) ;
125152
126153 describe ( '#toggleOne' , ( ) => {
@@ -145,6 +172,14 @@ describe('List Selection', () => {
145172 selection . toggleOne ( ) ; // [1]
146173 expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 ] ) ;
147174 } ) ;
175+
176+ it ( 'should not toggle non-selectable items' , ( ) => {
177+ const selection = getSelection ( ) ;
178+ const items = selection . inputs . items ( ) as TestItem [ ] ;
179+ items [ 0 ] . selectable . set ( false ) ;
180+ selection . toggleOne ( ) ; // []
181+ expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
182+ } ) ;
148183 } ) ;
149184
150185 describe ( '#selectAll' , ( ) => {
@@ -159,6 +194,14 @@ describe('List Selection', () => {
159194 selection . selectAll ( ) ;
160195 expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
161196 } ) ;
197+
198+ it ( 'should not select non-selectable items' , ( ) => {
199+ const selection = getSelection ( { multi : signal ( true ) } ) ;
200+ const items = selection . inputs . items ( ) as TestItem [ ] ;
201+ items [ 1 ] . selectable . set ( false ) ;
202+ selection . selectAll ( ) ;
203+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 0 , 2 , 3 , 4 ] ) ;
204+ } ) ;
162205 } ) ;
163206
164207 describe ( '#deselectAll' , ( ) => {
@@ -175,6 +218,15 @@ describe('List Selection', () => {
175218 selection . deselectAll ( ) ;
176219 expect ( selection . inputs . value ( ) . length ) . toBe ( 0 ) ;
177220 } ) ;
221+
222+ it ( 'should not deselect non-selectable items' , ( ) => {
223+ const selection = getSelection ( { multi : signal ( true ) } ) ;
224+ const items = selection . inputs . items ( ) as TestItem [ ] ;
225+ selection . selectAll ( ) ; // [0, 1, 2, 3, 4]
226+ items [ 1 ] . selectable . set ( false ) ;
227+ selection . deselectAll ( ) ; // [1]
228+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 ] ) ;
229+ } ) ;
178230 } ) ;
179231
180232 describe ( '#toggleAll' , ( ) => {
@@ -200,6 +252,16 @@ describe('List Selection', () => {
200252 selection . toggleAll ( ) ;
201253 expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
202254 } ) ;
255+
256+ it ( 'should ignore non-selectable items when determining if all items are selected' , ( ) => {
257+ const selection = getSelection ( { multi : signal ( true ) } ) ;
258+ const items = selection . inputs . items ( ) as TestItem [ ] ;
259+ items [ 0 ] . selectable . set ( false ) ;
260+ selection . toggleAll ( ) ;
261+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 , 2 , 3 , 4 ] ) ;
262+ selection . toggleAll ( ) ;
263+ expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
264+ } ) ;
203265 } ) ;
204266
205267 describe ( '#selectOne' , ( ) => {
@@ -221,6 +283,14 @@ describe('List Selection', () => {
221283 expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
222284 } ) ;
223285
286+ it ( 'should not select non-selectable items' , ( ) => {
287+ const selection = getSelection ( { multi : signal ( true ) } ) ;
288+ const items = selection . inputs . items ( ) as TestItem [ ] ;
289+ items [ 0 ] . selectable . set ( false ) ;
290+ selection . selectOne ( ) ; // []
291+ expect ( selection . inputs . value ( ) ) . toEqual ( [ ] ) ;
292+ } ) ;
293+
224294 it ( 'should do nothing to already selected items' , ( ) => {
225295 const selection = getSelection ( { multi : signal ( true ) } ) ;
226296 selection . selectOne ( ) ; // [0]
@@ -313,6 +383,16 @@ describe('List Selection', () => {
313383 expect ( selection . inputs . value ( ) ) . toEqual ( [ 0 , 2 ] ) ;
314384 } ) ;
315385
386+ it ( 'should not select a non-selectable item' , ( ) => {
387+ const selection = getSelection ( { multi : signal ( true ) } ) ;
388+ const items = selection . inputs . items ( ) as TestItem [ ] ;
389+ items [ 1 ] . selectable . set ( false ) ;
390+ selection . select ( ) ; // [0]
391+ selection . inputs . focusManager . focus ( items [ 2 ] ) ;
392+ selection . selectRange ( ) ; // [0, 2]
393+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 0 , 2 ] ) ;
394+ } ) ;
395+
316396 it ( 'should not deselect a disabled item' , ( ) => {
317397 const selection = getSelection ( { multi : signal ( true ) } ) ;
318398 const items = selection . inputs . items ( ) as TestItem [ ] ;
@@ -331,6 +411,21 @@ describe('List Selection', () => {
331411 selection . selectRange ( ) ; // [0, 1]
332412 expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 , 0 ] ) ;
333413 } ) ;
414+
415+ it ( 'should not deselect a non-selectable item' , ( ) => {
416+ const selection = getSelection ( { multi : signal ( true ) } ) ;
417+ const items = selection . inputs . items ( ) as TestItem [ ] ;
418+ selection . select ( items [ 1 ] ) ; // [1]
419+ items [ 1 ] . selectable . set ( false ) ;
420+ selection . select ( ) ; // [0, 1]
421+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 , 0 ] ) ;
422+ selection . inputs . focusManager . focus ( items [ 2 ] ) ;
423+ selection . selectRange ( ) ; // [0, 1, 2]
424+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 , 0 , 2 ] ) ;
425+ selection . inputs . focusManager . focus ( items [ 0 ] ) ;
426+ selection . selectRange ( ) ; // [0, 1]
427+ expect ( selection . inputs . value ( ) ) . toEqual ( [ 1 , 0 ] ) ;
428+ } ) ;
334429 } ) ;
335430
336431 describe ( '#beginRangeSelection' , ( ) => {
0 commit comments