@@ -17,7 +17,7 @@ import { useHistoryServiceDispatch, useResultsData } from './HistoryServiceProvi
1717 * | {kind: 'toggle-index'; index: number; reason?: string}
1818 * | {kind: 'expand-selected-to-index'; index: number; reason?: string}
1919 * | {kind: 'inc-or-dec-selected'; nextIndex: number; reason?: string}
20- * | {kind: 'select-next-or-prev '; index : number; reason?: string}
20+ * | {kind: 'move-selection '; direction: 'up' | 'down'; total : number; reason?: string}
2121 * | {kind: 'increment-selection'; direction: 'up' | 'down'; total: number; reason?: string}
2222 * | {kind: 'reset'; reason?: string}
2323 * } Action
@@ -40,11 +40,18 @@ export function SelectionProvider({ children }) {
4040 * @param {Action } evt
4141 */
4242 function dispatch ( evt ) {
43- console . log ( JSON . stringify ( evt ) ) ;
43+ console . log ( evt ) ;
4444 const next = reducer ( state . value , evt ) ;
4545 state . value = next ;
46+
47+ // after-effects?
48+ if ( evt . kind === 'move-selection' || evt . kind === 'increment-selection' ) {
49+ const match = document . querySelector ( `[aria-selected][data-index="${ state . value . focusedIndex } "]` ) ;
50+ match ?. scrollIntoView ( { block : 'nearest' , inline : 'nearest' } ) ;
51+ }
4652 }
4753 const dispatcher = useCallback ( dispatch , [ state , selected ] ) ;
54+
4855 return (
4956 < SelectionContext . Provider value = { selected } >
5057 < FocussedContext . Provider value = { focussed } >
@@ -59,7 +66,7 @@ export function useSelected() {
5966 return useContext ( SelectionContext ) ;
6067}
6168
62- export function useFocussedIndex ( ) {
69+ function useFocussedIndex ( ) {
6370 return useContext ( FocussedContext ) ;
6471}
6572
@@ -88,7 +95,21 @@ function reducer(prev, evt) {
8895 case 'reset' : {
8996 return { ...defaultState } ;
9097 }
91- case 'select-next-or-prev' :
98+ case 'move-selection' : {
99+ const { focusedIndex } = prev ;
100+ invariant ( focusedIndex !== null ) ;
101+ const delta = evt . direction === 'up' ? - 1 : 1 ;
102+ // either the last item, or current + 1
103+ const max = Math . min ( evt . total - 1 , focusedIndex + delta ) ;
104+ const newIndex = Math . max ( 0 , max ) ;
105+ const newSelected = new Set ( [ newIndex ] ) ;
106+ return {
107+ anchorIndex : newIndex ,
108+ focusedIndex : newIndex ,
109+ lastShiftRange : { start : null , end : null } ,
110+ selected : newSelected ,
111+ } ;
112+ }
92113 case 'select-index' : {
93114 const newSelected = new Set ( [ evt . index ] ) ;
94115 return {
@@ -167,11 +188,11 @@ function reducer(prev, evt) {
167188 } ;
168189 }
169190 case 'increment-selection' : {
170- const { focusedIndex } = prev ;
191+ const { focusedIndex, anchorIndex , lastShiftRange } = prev ;
171192 invariant ( focusedIndex !== null ) ;
172193 const delta = evt . direction === 'up' ? - 1 : 1 ;
173194 const newIndex = Math . max ( 0 , Math . min ( evt . total - 1 , focusedIndex + delta ) ) ;
174- const { anchorIndex , lastShiftRange } = prev ;
195+
175196 // Handle shift+arrow selection
176197 const newSelected = new Set ( prev . selected ) ;
177198
@@ -263,54 +284,39 @@ export function useRowInteractions(mainRef) {
263284 * @return {boolean } true if we handled this event
264285 */
265286 function handleKeyIntention ( intention ) {
266- // prettier-ignore
267- const direction = intention === 'shift+up' || intention === 'up'
268- ? - 1
269- : 1 ;
270-
287+ const total = results . value . items . length ;
271288 if ( focusedIndex . value === null ) return false ;
272- const newIndex = Math . max ( 0 , Math . min ( results . value . items . length - 1 , focusedIndex . value + direction ) ) ;
273289
274290 switch ( intention ) {
275291 case 'shift+down' : {
276292 dispatch ( {
277293 kind : 'increment-selection' ,
278294 direction : 'down' ,
279- total : results . value . items . length ,
295+ total,
280296 } ) ;
281- break ;
297+ return true ;
282298 }
283299 case 'shift+up' : {
284300 dispatch ( {
285301 kind : 'increment-selection' ,
286302 direction : 'up' ,
287- total : results . value . items . length ,
303+ total,
288304 } ) ;
289- break ;
305+ return true ;
290306 }
291307 case 'up' :
308+ dispatch ( { kind : 'move-selection' , direction : 'up' , total } ) ;
309+ return true ;
292310 case 'down' : {
293- dispatch ( { kind : 'select-next-or-prev ' , index : newIndex } ) ;
294- break ;
311+ dispatch ( { kind : 'move-selection ' , direction : 'down' , total } ) ;
312+ return true ;
295313 }
296314 case 'delete' : {
297315 if ( selected . value . size === 0 ) break ;
298316 historyDispatch ( { kind : 'delete-entries-by-index' , value : [ ...selected . value ] } ) ;
299317 break ;
300318 }
301319 }
302-
303- switch ( intention ) {
304- case 'shift+down' :
305- case 'shift+up' :
306- case 'up' :
307- case 'down' : {
308- const match = document . querySelector ( `[aria-selected][data-index="${ newIndex } "]` ) ;
309- match ?. scrollIntoView ( { block : 'nearest' , inline : 'nearest' } ) ;
310- return true ;
311- }
312- }
313-
314320 return false ;
315321 }
316322 /**
0 commit comments