@@ -50,57 +50,55 @@ function getGridRowGroupSelectableDescendants(
50
50
return descendants ;
51
51
}
52
52
53
- // TODO v8: Use `createSelectorV8`
54
- export function getCheckboxPropsSelector ( groupId : GridRowId , autoSelectParents : boolean ) {
55
- return createSelector (
56
- gridRowTreeSelector ,
57
- gridSortedRowIdsSelector ,
58
- gridFilteredRowsLookupSelector ,
59
- selectedIdsLookupSelector ,
60
- ( rowTree , sortedRowIds , filteredRowsLookup , rowSelectionLookup ) => {
61
- const groupNode = rowTree [ groupId ] ;
62
- if ( ! groupNode || groupNode . type !== 'group' ) {
63
- return {
64
- isIndeterminate : false ,
65
- isChecked : rowSelectionLookup [ groupId ] === groupId ,
66
- } ;
67
- }
53
+ export const checkboxPropsSelector = createSelector (
54
+ gridRowTreeSelector ,
55
+ gridFilteredRowsLookupSelector ,
56
+ gridRowSelectionManagerSelector ,
57
+ (
58
+ rowTree ,
59
+ filteredRowsLookup ,
60
+ rowSelectionManager ,
61
+ { groupId, autoSelectParents } : { groupId : GridRowId ; autoSelectParents : boolean } ,
62
+ ) => {
63
+ const groupNode = rowTree [ groupId ] ;
64
+ if ( ! groupNode || groupNode . type !== 'group' || rowSelectionManager . has ( groupId ) ) {
65
+ return {
66
+ isIndeterminate : false ,
67
+ isChecked : rowSelectionManager . has ( groupId ) ,
68
+ } ;
69
+ }
68
70
69
- if ( rowSelectionLookup [ groupId ] === groupId ) {
70
- return {
71
- isIndeterminate : false ,
72
- isChecked : true ,
73
- } ;
74
- }
71
+ let hasSelectedDescendant = false ;
72
+ let hasUnSelectedDescendant = false ;
75
73
76
- let selectableDescendantsCount = 0 ;
77
- let selectedDescendantsCount = 0 ;
78
- const startIndex = sortedRowIds . findIndex ( ( id ) => id === groupId ) + 1 ;
79
- for (
80
- let index = startIndex ;
81
- index < sortedRowIds . length && rowTree [ sortedRowIds [ index ] ] ?. depth > groupNode . depth ;
82
- index += 1
74
+ const traverseDescendants = ( itemToTraverseId : GridRowId ) => {
75
+ if (
76
+ filteredRowsLookup [ itemToTraverseId ] === false ||
77
+ // Perf: Skip checking the rest of the descendants if we already
78
+ // know that there is a selected and an unselected descendant
79
+ ( hasSelectedDescendant && hasUnSelectedDescendant )
83
80
) {
84
- const id = sortedRowIds [ index ] ;
85
- if ( filteredRowsLookup [ id ] !== false ) {
86
- selectableDescendantsCount += 1 ;
87
- if ( rowSelectionLookup [ id ] !== undefined ) {
88
- selectedDescendantsCount += 1 ;
89
- }
90
- }
81
+ return ;
91
82
}
92
- return {
93
- isIndeterminate :
94
- selectedDescendantsCount > 0 &&
95
- ( selectedDescendantsCount < selectableDescendantsCount ||
96
- rowSelectionLookup [ groupId ] === undefined ) ,
97
- isChecked : autoSelectParents
98
- ? selectedDescendantsCount > 0
99
- : rowSelectionLookup [ groupId ] === groupId ,
100
- } ;
101
- } ,
102
- ) ;
103
- }
83
+ const node = rowTree [ itemToTraverseId ] ;
84
+ if ( node ?. type === 'group' ) {
85
+ node . children . forEach ( traverseDescendants ) ;
86
+ }
87
+ if ( rowSelectionManager . has ( itemToTraverseId ) ) {
88
+ hasSelectedDescendant = true ;
89
+ } else {
90
+ hasUnSelectedDescendant = true ;
91
+ }
92
+ } ;
93
+
94
+ traverseDescendants ( groupId ) ;
95
+
96
+ return {
97
+ isIndeterminate : hasSelectedDescendant && hasUnSelectedDescendant ,
98
+ isChecked : autoSelectParents ? hasSelectedDescendant && ! hasUnSelectedDescendant : false ,
99
+ } ;
100
+ } ,
101
+ ) ;
104
102
105
103
export function isMultipleRowSelectionEnabled (
106
104
props : Pick <
0 commit comments