@@ -166,7 +166,7 @@ SelectAllHeaderRenderer.propTypes = {
166166 isCellSelected : PropTypes . bool ,
167167} ;
168168
169- function SelectableHeaderRenderer ( { column, selectedColumns , onSelectedColumnsChange , isCellSelected} ) {
169+ function SelectableHeaderRenderer ( { column, isSelected , onColumnSelected , isCellSelected} ) {
170170 const cellRef = useRef ( ) ;
171171 const eventBus = useContext ( QueryToolEventsContext ) ;
172172 const dataGridExtras = useContext ( DataGridExtrasContext ) ;
@@ -175,18 +175,10 @@ function SelectableHeaderRenderer({column, selectedColumns, onSelectedColumnsCha
175175 dataGridExtras . onSelectedCellChange ?. ( null ) ;
176176 }
177177
178- const onClick = ( ) => {
179- const newSelectedCols = new Set ( selectedColumns ) ;
180- if ( newSelectedCols . has ( column . idx ) ) {
181- newSelectedCols . delete ( column . idx ) ;
182- } else {
183- newSelectedCols . add ( column . idx ) ;
184- }
185- onSelectedColumnsChange ( newSelectedCols ) ;
178+ const onClick = ( e ) => {
179+ onColumnSelected ( column . idx , isSelected , ( e . nativeEvent ) . shiftKey ) ;
186180 } ;
187181
188- const isSelected = selectedColumns . has ( column . idx ) ;
189-
190182 useLayoutEffect ( ( ) => {
191183 if ( ! isCellSelected ) return ;
192184 cellRef . current ?. focus ( { preventScroll : true } ) ;
@@ -215,8 +207,8 @@ function SelectableHeaderRenderer({column, selectedColumns, onSelectedColumnsCha
215207}
216208SelectableHeaderRenderer . propTypes = {
217209 column : PropTypes . object ,
218- selectedColumns : PropTypes . objectOf ( Set ) ,
219- onSelectedColumnsChange : PropTypes . func ,
210+ isSelected : PropTypes . bool ,
211+ onColumnSelected : PropTypes . func ,
220212 isCellSelected : PropTypes . bool ,
221213} ;
222214
@@ -305,9 +297,9 @@ function RowNumColFormatter({row, rowKeyGetter, rowIdx, dataChangeStore, onSelec
305297 } else if ( rowKey in ( dataChangeStore ?. deleted || { } ) ) {
306298 rownum = rownum + '-' ;
307299 }
308- return ( < div className = 'QueryTool-rowNumCell' onClick = { ( ) => {
300+ return ( < div className = 'QueryTool-rowNumCell' onClick = { ( e ) => {
309301 onSelectedColumnsChange ( new Set ( ) ) ;
310- onRowSelectionChange ( { type : 'ROW' , row : row , checked : ! isRowSelected , isShiftClick : false } ) ;
302+ onRowSelectionChange ( { type : 'ROW' , row : row , checked : ! isRowSelected , isShiftClick : ( e . nativeEvent ) . shiftKey } ) ;
311303 } } onKeyDown = { ( ) => { /* already taken care by parent */ } } >
312304 { rownum }
313305 </ div > ) ;
@@ -320,13 +312,16 @@ RowNumColFormatter.propTypes = {
320312 onSelectedColumnsChange : PropTypes . func ,
321313} ;
322314
323- function formatColumns ( columns , dataChangeStore , selectedColumns , onSelectedColumnsChange , rowKeyGetter ) {
315+ function formatColumns ( columns , dataChangeStore , selectedColumns , onColumnSelected , onSelectedColumnsChange , rowKeyGetter ) {
324316 let retColumns = [
325317 ...columns ,
326318 ] ;
327319
328- const HeaderRenderer = ( props ) => {
329- return < SelectableHeaderRenderer { ...props } selectedColumns = { selectedColumns } onSelectedColumnsChange = { onSelectedColumnsChange } /> ;
320+ const HeaderRenderer = ( { column, ...props } ) => {
321+ return < SelectableHeaderRenderer { ...props } column = { column } isSelected = { selectedColumns . has ( column . idx ) } onColumnSelected = { onColumnSelected } /> ;
322+ } ;
323+ HeaderRenderer . propTypes = {
324+ column : PropTypes . object ,
330325 } ;
331326
332327 for ( const [ idx , col ] of retColumns . entries ( ) ) {
@@ -377,7 +372,26 @@ function getColumnWidth(column, rows, canvas, columnWidthBy) {
377372export default function QueryToolDataGrid ( { columns, rows, totalRowCount, dataChangeStore,
378373 onSelectedCellChange, selectedColumns, onSelectedColumnsChange, columnWidthBy, startRowNum, ...props } ) {
379374 const [ readyColumns , setReadyColumns ] = useState ( [ ] ) ;
375+ const [ lastSelectedColumn , setLastSelectedColumn ] = useState ( null ) ;
380376 const eventBus = useContext ( QueryToolEventsContext ) ;
377+ const onColumnSelected = ( columnIdx , isSelected , isShiftClick ) => {
378+ const newSelectedCols = new Set ( selectedColumns ) ;
379+ const start = isShiftClick && lastSelectedColumn ? Math . min ( columnIdx , lastSelectedColumn ) : columnIdx ;
380+ const end = isShiftClick && lastSelectedColumn ? Math . max ( columnIdx , lastSelectedColumn ) : columnIdx ;
381+ for ( let i = start ; i <= end ; i ++ ) {
382+ if ( isSelected ) {
383+ newSelectedCols . delete ( i ) ;
384+ }
385+ else {
386+ newSelectedCols . add ( i ) ;
387+ }
388+ }
389+
390+ props . onSelectedRowsChange ( new Set ( ) ) ;
391+ setLastSelectedColumn ( columnIdx ) ;
392+ onSelectedColumnsChange ( newSelectedCols ) ;
393+ } ;
394+
381395 const onSelectedColumnsChangeWrapped = ( arg ) => {
382396 props . onSelectedRowsChange ( new Set ( ) ) ;
383397 onSelectedColumnsChange ( arg ) ;
@@ -411,12 +425,12 @@ export default function QueryToolDataGrid({columns, rows, totalRowCount, dataCha
411425
412426 useEffect ( ( ) => {
413427 let initCols = initialiseColumns ( columns , rows , totalRowCount , columnWidthBy ) ;
414- setReadyColumns ( formatColumns ( initCols , dataChangeStore , selectedColumns , onSelectedColumnsChangeWrapped , props . rowKeyGetter ) ) ;
428+ setReadyColumns ( formatColumns ( initCols , dataChangeStore , selectedColumns , onColumnSelected , onSelectedColumnsChangeWrapped , props . rowKeyGetter ) ) ;
415429 } , [ columns ] ) ;
416430
417431 useEffect ( ( ) => {
418432 setReadyColumns ( ( prevCols ) => {
419- return formatColumns ( prevCols , dataChangeStore , selectedColumns , onSelectedColumnsChangeWrapped , props . rowKeyGetter ) ;
433+ return formatColumns ( prevCols , dataChangeStore , selectedColumns , onColumnSelected , onSelectedColumnsChangeWrapped , props . rowKeyGetter ) ;
420434 } ) ;
421435 } , [ dataChangeStore , selectedColumns ] ) ;
422436
0 commit comments