@@ -144,6 +144,7 @@ export function Table({
144144 const [ selectionAnchor , setSelectionAnchor ] = useState < CellCoord | null > ( null )
145145 const [ selectionFocus , setSelectionFocus ] = useState < CellCoord | null > ( null )
146146 const [ checkedRows , setCheckedRows ] = useState ( EMPTY_CHECKED_ROWS )
147+ const [ allRowsSelected , setAllRowsSelected ] = useState ( false )
147148 const [ isColumnSelection , setIsColumnSelection ] = useState ( false )
148149 const lastCheckboxRowRef = useRef < string | null > ( null )
149150 const isColumnSelectionRef = useRef ( false )
@@ -380,21 +381,14 @@ export function Table({
380381 } , [ dropTargetColumnName , dragColumnName , dropSide , displayColumns , columnWidths ] )
381382
382383 const isAllRowsSelected = useMemo ( ( ) => {
383- if ( checkedRows . size > 0 && rows . length > 0 && checkedRows . size >= rows . length ) {
384- for ( const row of rows ) {
385- if ( ! checkedRows . has ( row . id ) ) return false
386- }
387- return true
384+ if ( rows . length === 0 ) return false
385+ if ( allRowsSelected ) return true
386+ if ( checkedRows . size < rows . length ) return false
387+ for ( let i = 0 ; i < rows . length ; i ++ ) {
388+ if ( ! checkedRows . has ( rows [ i ] . id ) ) return false
388389 }
389- return (
390- normalizedSelection !== null &&
391- rows . length > 0 &&
392- normalizedSelection . startRow === 0 &&
393- normalizedSelection . endRow === rows . length - 1 &&
394- normalizedSelection . startCol === 0 &&
395- normalizedSelection . endCol === displayColumns . length - 1
396- )
397- } , [ checkedRows , normalizedSelection , displayColumns . length , rows ] )
390+ return true
391+ } , [ allRowsSelected , checkedRows , rows ] )
398392
399393 const isAllRowsSelectedRef = useRef ( isAllRowsSelected )
400394 isAllRowsSelectedRef . current = isAllRowsSelected
@@ -411,6 +405,9 @@ export function Table({
411405 const checkedRowsRef = useRef ( checkedRows )
412406 checkedRowsRef . current = checkedRows
413407
408+ const allRowsSelectedRef = useRef ( allRowsSelected )
409+ allRowsSelectedRef . current = allRowsSelected
410+
414411 columnsRef . current = displayColumns
415412 schemaColumnsRef . current = columns
416413 workflowGroupsRef . current = tableWorkflowGroups
@@ -499,10 +496,13 @@ export function Table({
499496 }
500497
501498 const checked = checkedRowsRef . current
499+ const allChecked = allRowsSelectedRef . current
502500 const currentRows = rowsRef . current
503501 let snapshots : DeletedRowSnapshot [ ] = [ ]
504502
505- if ( checked . size > 0 && checked . has ( contextRow . id ) ) {
503+ if ( allChecked ) {
504+ snapshots = collectRowSnapshots ( currentRows )
505+ } else if ( checked . size > 0 && checked . has ( contextRow . id ) ) {
506506 snapshots = collectRowSnapshots ( currentRows . filter ( ( r ) => checked . has ( r . id ) ) )
507507 } else {
508508 const sel = computeNormalizedSelection ( selectionAnchorRef . current , selectionFocusRef . current )
@@ -678,6 +678,7 @@ export function Table({
678678 const handleCellMouseDown = useCallback (
679679 ( rowIndex : number , colIndex : number , shiftKey : boolean ) => {
680680 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
681+ setAllRowsSelected ( false )
681682 setIsColumnSelection ( false )
682683 lastCheckboxRowRef . current = null
683684 if ( shiftKey && selectionAnchorRef . current ) {
@@ -713,11 +714,17 @@ export function Table({
713714 ? currentRows . findIndex ( ( r ) => r . id === lastCheckboxRowRef . current )
714715 : - 1
715716
717+ const wasAllSelected = allRowsSelectedRef . current
718+ if ( wasAllSelected ) {
719+ allRowsSelectedRef . current = false
720+ setAllRowsSelected ( false )
721+ }
722+
716723 if ( lastIdx !== - 1 ) {
717724 const from = Math . min ( lastIdx , rowIndex )
718725 const to = Math . max ( lastIdx , rowIndex )
719726 setCheckedRows ( ( prev ) => {
720- const next = new Set ( prev )
727+ const next = wasAllSelected ? new Set ( currentRows . map ( ( r ) => r . id ) ) : new Set ( prev )
721728 for ( let i = from ; i <= to ; i ++ ) {
722729 const r = currentRows [ i ]
723730 if ( r ) next . add ( r . id )
@@ -726,7 +733,7 @@ export function Table({
726733 } )
727734 } else {
728735 setCheckedRows ( ( prev ) => {
729- const next = new Set ( prev )
736+ const next = wasAllSelected ? new Set ( currentRows . map ( ( r ) => r . id ) ) : new Set ( prev )
730737 if ( next . has ( targetId ) ) next . delete ( targetId )
731738 else next . add ( targetId )
732739 return next
@@ -740,6 +747,7 @@ export function Table({
740747 setSelectionAnchor ( null )
741748 setSelectionFocus ( null )
742749 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
750+ setAllRowsSelected ( false )
743751 setIsColumnSelection ( false )
744752 lastCheckboxRowRef . current = null
745753 } , [ ] )
@@ -750,6 +758,7 @@ export function Table({
750758
751759 setEditingCell ( null )
752760 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
761+ setAllRowsSelected ( false )
753762 lastCheckboxRowRef . current = null
754763
755764 if ( shiftKey && isColumnSelectionRef . current && selectionAnchorRef . current ) {
@@ -769,6 +778,7 @@ export function Table({
769778
770779 setEditingCell ( null )
771780 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
781+ setAllRowsSelected ( false )
772782 lastCheckboxRowRef . current = null
773783
774784 setSelectionAnchor ( { rowIndex : 0 , colIndex : startColIndex } )
@@ -784,6 +794,7 @@ export function Table({
784794 if ( rws . length === 0 || currentCols . length === 0 ) return
785795 setEditingCell ( null )
786796 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
797+ setAllRowsSelected ( true )
787798 lastCheckboxRowRef . current = null
788799 suppressFocusScrollRef . current = true
789800 setSelectionAnchor ( { rowIndex : 0 , colIndex : 0 } )
@@ -876,6 +887,7 @@ export function Table({
876887 setSelectionAnchor ( null )
877888 setSelectionFocus ( null )
878889 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
890+ setAllRowsSelected ( false )
879891 setIsColumnSelection ( false )
880892 } , [ ] )
881893
@@ -1340,6 +1352,7 @@ export function Table({
13401352 setSelectionAnchor ( null )
13411353 setSelectionFocus ( null )
13421354 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1355+ setAllRowsSelected ( false )
13431356 setIsColumnSelection ( false )
13441357 lastCheckboxRowRef . current = null
13451358 return
@@ -1353,6 +1366,7 @@ export function Table({
13531366 suppressFocusScrollRef . current = true
13541367 setEditingCell ( null )
13551368 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1369+ setAllRowsSelected ( false )
13561370 lastCheckboxRowRef . current = null
13571371 setSelectionAnchor ( { rowIndex : 0 , colIndex : 0 } )
13581372 setSelectionFocus ( {
@@ -1371,6 +1385,7 @@ export function Table({
13711385 if ( lastRow < 0 ) return
13721386 e . preventDefault ( )
13731387 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1388+ setAllRowsSelected ( false )
13741389 lastCheckboxRowRef . current = null
13751390 setSelectionAnchor ( { rowIndex : 0 , colIndex : a . colIndex } )
13761391 setSelectionFocus ( { rowIndex : lastRow , colIndex : a . colIndex } )
@@ -1385,24 +1400,29 @@ export function Table({
13851400 if ( currentCols . length === 0 ) return
13861401 e . preventDefault ( )
13871402 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1403+ setAllRowsSelected ( false )
13881404 lastCheckboxRowRef . current = null
13891405 setIsColumnSelection ( false )
13901406 setSelectionAnchor ( { rowIndex : a . rowIndex , colIndex : 0 } )
13911407 setSelectionFocus ( { rowIndex : a . rowIndex , colIndex : currentCols . length - 1 } )
13921408 return
13931409 }
13941410
1395- if ( ( e . key === 'Delete' || e . key === 'Backspace' ) && checkedRowsRef . current . size > 0 ) {
1411+ if (
1412+ ( e . key === 'Delete' || e . key === 'Backspace' ) &&
1413+ ( checkedRowsRef . current . size > 0 || allRowsSelectedRef . current )
1414+ ) {
13961415 if ( editingCellRef . current ) return
13971416 if ( ! canEditRef . current ) return
13981417 e . preventDefault ( )
13991418 const checked = checkedRowsRef . current
1419+ const allChecked = allRowsSelectedRef . current
14001420 const currentRows = rowsRef . current
14011421 const currentCols = columnsRef . current
14021422 const undoCells : Array < { rowId : string ; data : Record < string , unknown > } > = [ ]
14031423 const batchUpdates : Array < { rowId : string ; data : Record < string , unknown > } > = [ ]
14041424 for ( const row of currentRows ) {
1405- if ( ! checked . has ( row . id ) ) continue
1425+ if ( ! allChecked && ! checked . has ( row . id ) ) continue
14061426 const updates : Record < string , unknown > = { }
14071427 const previousData : Record < string , unknown > = { }
14081428 for ( const col of currentCols ) {
@@ -1482,6 +1502,7 @@ export function Table({
14821502 if ( e . key === 'Tab' ) {
14831503 e . preventDefault ( )
14841504 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1505+ setAllRowsSelected ( false )
14851506 setIsColumnSelection ( false )
14861507 lastCheckboxRowRef . current = null
14871508 setSelectionAnchor ( moveCell ( anchor , cols . length , totalRows , e . shiftKey ? - 1 : 1 ) )
@@ -1492,6 +1513,7 @@ export function Table({
14921513 if ( [ 'ArrowUp' , 'ArrowDown' , 'ArrowLeft' , 'ArrowRight' ] . includes ( e . key ) ) {
14931514 e . preventDefault ( )
14941515 setCheckedRows ( ( prev ) => ( prev . size === 0 ? prev : EMPTY_CHECKED_ROWS ) )
1516+ setAllRowsSelected ( false )
14951517 setIsColumnSelection ( false )
14961518 lastCheckboxRowRef . current = null
14971519 const focus = selectionFocusRef . current ?? anchor
@@ -1670,14 +1692,15 @@ export function Table({
16701692 if ( editingCellRef . current ) return
16711693
16721694 const checked = checkedRowsRef . current
1695+ const allChecked = allRowsSelectedRef . current
16731696 const cols = columnsRef . current
16741697 const currentRows = rowsRef . current
16751698
1676- if ( checked . size > 0 ) {
1699+ if ( allChecked || checked . size > 0 ) {
16771700 e . preventDefault ( )
16781701 const lines : string [ ] = [ ]
16791702 for ( const row of currentRows ) {
1680- if ( ! checked . has ( row . id ) ) continue
1703+ if ( ! allChecked && ! checked . has ( row . id ) ) continue
16811704 const cells : string [ ] = cols . map ( ( col ) => {
16821705 const value : unknown = row . data [ col . name ]
16831706 if ( value === null || value === undefined ) return ''
@@ -1721,16 +1744,17 @@ export function Table({
17211744 if ( ! canEditRef . current ) return
17221745
17231746 const checked = checkedRowsRef . current
1747+ const allChecked = allRowsSelectedRef . current
17241748 const cols = columnsRef . current
17251749 const currentRows = rowsRef . current
17261750 const undoCells : Array < { rowId : string ; data : Record < string , unknown > } > = [ ]
17271751 const batchUpdates : Array < { rowId : string ; data : Record < string , unknown > } > = [ ]
17281752
1729- if ( checked . size > 0 ) {
1753+ if ( allChecked || checked . size > 0 ) {
17301754 e . preventDefault ( )
17311755 const lines : string [ ] = [ ]
17321756 for ( const row of currentRows ) {
1733- if ( ! checked . has ( row . id ) ) continue
1757+ if ( ! allChecked && ! checked . has ( row . id ) ) continue
17341758 const cells : string [ ] = cols . map ( ( col ) => {
17351759 const value : unknown = row . data [ col . name ]
17361760 if ( value === null || value === undefined ) return ''
@@ -2425,6 +2449,8 @@ export function Table({
24252449 const contextRow = contextMenu . isOpen ? contextMenu . row : null
24262450 if ( ! contextRow ) return 1
24272451
2452+ if ( allRowsSelected ) return Math . max ( rows . length , 1 )
2453+
24282454 if ( checkedRows . size > 0 && checkedRows . has ( contextRow . id ) ) {
24292455 let count = 0
24302456 for ( const row of rows ) {
@@ -2442,7 +2468,7 @@ export function Table({
24422468 const start = Math . max ( 0 , sel . startRow )
24432469 const end = Math . min ( rows . length - 1 , sel . endRow )
24442470 return Math . max ( end - start + 1 , 1 )
2445- } , [ contextMenu . isOpen , contextMenu . row , checkedRows , normalizedSelection , rows ] )
2471+ } , [ contextMenu . isOpen , contextMenu . row , allRowsSelected , checkedRows , normalizedSelection , rows ] )
24462472
24472473 const pendingUpdate = updateRowMutation . isPending ? updateRowMutation . variables : null
24482474
@@ -2756,7 +2782,7 @@ export function Table({
27562782 onContextMenu = { handleRowContextMenu }
27572783 onCellMouseDown = { handleCellMouseDown }
27582784 onCellMouseEnter = { handleCellMouseEnter }
2759- isRowChecked = { checkedRows . has ( row . id ) }
2785+ isRowChecked = { allRowsSelected || checkedRows . has ( row . id ) }
27602786 onRowToggle = { handleRowToggle }
27612787 runningCount = { runningByRowId . get ( row . id ) ?? 0 }
27622788 hasWorkflowColumns = { hasWorkflowColumns }
@@ -3109,13 +3135,7 @@ const DataRow = React.memo(function DataRow({
31093135} : DataRowProps ) {
31103136 const sel = normalizedSelection
31113137 const isMultiCell = sel !== null && ( sel . startRow !== sel . endRow || sel . startCol !== sel . endCol )
3112- const isRowSelectedByRange =
3113- sel !== null &&
3114- rowIndex >= sel . startRow &&
3115- rowIndex <= sel . endRow &&
3116- sel . startCol === 0 &&
3117- sel . endCol === columns . length - 1
3118- const isRowSelected = isRowChecked || isRowSelectedByRange
3138+ const isRowSelected = isRowChecked
31193139
31203140 return (
31213141 < tr onContextMenu = { ( e ) => onContextMenu ( e , row ) } >
0 commit comments