@@ -10,7 +10,11 @@ import {VscElement} from '../includes/VscElement';
1010import styles from './vscode-list-item.styles' ;
1111import { classMap } from 'lit/directives/class-map.js' ;
1212import { listContext , type ListContext } from '../vscode-list/list-context' ;
13- import { initPathTrackerProps } from '../vscode-list/helpers' ;
13+ import {
14+ findAncestorOnSpecificLevel ,
15+ initPathTrackerProps ,
16+ selectItemAndAllVisibleDescendants ,
17+ } from '../vscode-list/helpers' ;
1418
1519const BASE_INDENT = 3 ;
1620const ARROW_CONTAINER_WIDTH = 30 ;
@@ -36,13 +40,20 @@ export class VscodeListItem extends VscElement {
3640 branch = false ;
3741
3842 @property ( { type : Boolean , reflect : true } )
39- closed = false ;
43+ open = false ;
4044
4145 @property ( { type : Number , reflect : true } )
4246 level = 0 ;
4347
4448 @property ( { type : Boolean , reflect : true } )
45- selected = false ;
49+ set selected ( val : boolean ) {
50+ this . _selected = val ;
51+ this . _listContextState . selectedItems . add ( this ) ;
52+ }
53+ get selected ( ) : boolean {
54+ return this . _selected ;
55+ }
56+ private _selected = false ;
4657
4758 @property ( { type : Number , reflect : true } )
4859 tabIndex = - 1 ;
@@ -51,8 +62,10 @@ export class VscodeListItem extends VscElement {
5162 private _listContextState : ListContext = {
5263 arrows : false ,
5364 indent : 8 ,
65+ multiSelect : false ,
5466 selectedItems : new Set ( ) ,
5567 focusedItem : null ,
68+ prevFocusedItem : null ,
5669 focusItem : ( ) => {
5770 return ;
5871 } ,
@@ -96,6 +109,37 @@ export class VscodeListItem extends VscElement {
96109 }
97110 }
98111
112+ private _selectRange ( ) {
113+ const prevFocused = this . _listContextState . prevFocusedItem ;
114+
115+ if ( ! prevFocused || prevFocused === this ) {
116+ return ;
117+ }
118+
119+ const prevFocusedLevel = + ( prevFocused . dataset . level ?? '' ) ;
120+ const focusedLevel = + ( this . dataset . level ?? '' ) ;
121+
122+ let closestAncestor : VscodeListItem | null ;
123+
124+ if ( focusedLevel > prevFocusedLevel ) {
125+ closestAncestor = findAncestorOnSpecificLevel ( this , prevFocusedLevel ) ;
126+ } else if ( focusedLevel < prevFocusedLevel ) {
127+ closestAncestor = findAncestorOnSpecificLevel ( prevFocused , focusedLevel ) ;
128+ } else {
129+ closestAncestor = prevFocused ;
130+ }
131+
132+ const from = + ( closestAncestor ?. dataset . index ?? '' ) ;
133+ const to = + ( this . dataset . index ?? '' ) ;
134+
135+ for ( let i = from ; i <= to ; i ++ ) {
136+ const li = this . parentElement ?. querySelector (
137+ `:scope > [data-index="${ i } "]`
138+ ) as VscodeListItem ;
139+ selectItemAndAllVisibleDescendants ( li ) ;
140+ }
141+ }
142+
99143 private _mainSlotChange ( ) {
100144 this . _initiallyAssignedListItems . forEach ( ( li ) => {
101145 li . setAttribute ( 'slot' , 'children' ) ;
@@ -120,6 +164,8 @@ export class VscodeListItem extends VscElement {
120164 this . _listContextState . focusedItem !== this
121165 ) {
122166 this . _listContextState . focusedItem . tabIndex = - 1 ;
167+ this . _listContextState . prevFocusedItem =
168+ this . _listContextState . focusedItem ;
123169 this . _listContextState . focusedItem = null ;
124170 }
125171
@@ -130,10 +176,17 @@ export class VscodeListItem extends VscElement {
130176 ev . stopPropagation ( ) ;
131177
132178 const isCtrlDown = ev . ctrlKey ;
179+ const isShiftDown = ev . shiftKey ;
180+
181+ if ( isShiftDown ) {
182+ this . _selectRange ( ) ;
183+ return ;
184+ }
185+
133186 this . _selectItem ( isCtrlDown ) ;
134187
135188 if ( this . branch && ! ( this . _listContextState . multiSelect && isCtrlDown ) ) {
136- this . closed = ! this . closed ;
189+ this . open = ! this . open ;
137190 }
138191
139192 this . _focusItem ( this ) ;
@@ -152,12 +205,6 @@ export class VscodeListItem extends VscElement {
152205 this . removeEventListener ( 'focus' , this . _handleComponentFocus ) ;
153206 }
154207
155- willUpdate ( changedProperties : PropertyValues < this> ) : void {
156- if ( changedProperties . has ( 'selected' ) && this . selected ) {
157- this . _listContextState . selectedItems . add ( this ) ;
158- }
159- }
160-
161208 render ( ) : TemplateResult {
162209 const { arrows, indent, hasBranchItem} = this . _listContextState ;
163210 let indentation = BASE_INDENT + this . level * indent ;
@@ -176,18 +223,18 @@ export class VscodeListItem extends VscElement {
176223 ? html `< div
177224 class =${ classMap ( {
178225 'arrow-container' : true ,
179- 'icon-rotated' : ! this . closed ,
226+ 'icon-rotated' : this . open ,
180227 } ) }
181228 >
182229 ${ arrowIcon }
183230 </ div > `
184231 : nothing }
185232 < div class ="icon-container ">
186233 < slot name ="icon "> </ slot >
187- ${ this . branch && this . closed
234+ ${ this . branch && ! this . open
188235 ? html `< slot name ="icon-branch "> </ slot > `
189236 : nothing }
190- ${ this . branch && ! this . closed
237+ ${ this . branch && this . open
191238 ? html `< slot name ="icon-branch-opened "> </ slot > `
192239 : nothing }
193240 ${ ! this . branch ? html `< slot name ="icon-leaf "> </ slot > ` : nothing }
0 commit comments