UNPKG

@mui/x-data-grid

Version:

The Community plan edition of the Data Grid components (MUI X).

163 lines (162 loc) 6.17 kB
import { GridSignature } from "../../utils/useGridApiEventHandler.js"; import { GRID_ROOT_GROUP_ID } from "../rows/gridRowsUtils.js"; import { gridFilteredRowsLookupSelector } from "../filter/gridFilterSelector.js"; import { gridSortedRowIdsSelector } from "../sorting/gridSortingSelector.js"; import { selectedIdsLookupSelector } from "./gridRowSelectionSelector.js"; import { gridRowTreeSelector } from "../rows/gridRowsSelector.js"; import { createSelector } from "../../../utils/createSelector.js"; export const ROW_SELECTION_PROPAGATION_DEFAULT = { parents: false, descendants: false }; function getGridRowGroupSelectableDescendants(apiRef, groupId) { const rowTree = gridRowTreeSelector(apiRef); const sortedRowIds = gridSortedRowIdsSelector(apiRef); const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); const groupNode = rowTree[groupId]; if (!groupNode || groupNode.type !== 'group') { return []; } const descendants = []; const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1; for (let index = startIndex; index < sortedRowIds.length && rowTree[sortedRowIds[index]]?.depth > groupNode.depth; index += 1) { const id = sortedRowIds[index]; if (filteredRowsLookup[id] !== false && apiRef.current.isRowSelectable(id)) { descendants.push(id); } } return descendants; } // TODO v8: Use `createSelectorV8` export function getCheckboxPropsSelector(groupId, autoSelectParents) { return createSelector(gridRowTreeSelector, gridSortedRowIdsSelector, gridFilteredRowsLookupSelector, selectedIdsLookupSelector, (rowTree, sortedRowIds, filteredRowsLookup, rowSelectionLookup) => { const groupNode = rowTree[groupId]; if (!groupNode || groupNode.type !== 'group') { return { isIndeterminate: false, isChecked: rowSelectionLookup[groupId] === groupId }; } if (rowSelectionLookup[groupId] === groupId) { return { isIndeterminate: false, isChecked: true }; } let selectableDescendantsCount = 0; let selectedDescendantsCount = 0; const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1; for (let index = startIndex; index < sortedRowIds.length && rowTree[sortedRowIds[index]]?.depth > groupNode.depth; index += 1) { const id = sortedRowIds[index]; if (filteredRowsLookup[id] !== false) { selectableDescendantsCount += 1; if (rowSelectionLookup[id] !== undefined) { selectedDescendantsCount += 1; } } } return { isIndeterminate: selectedDescendantsCount > 0 && (selectedDescendantsCount < selectableDescendantsCount || rowSelectionLookup[groupId] === undefined), isChecked: autoSelectParents ? selectedDescendantsCount > 0 : rowSelectionLookup[groupId] === groupId }; }); } export function isMultipleRowSelectionEnabled(props) { if (props.signature === GridSignature.DataGrid) { // DataGrid Community has multiple row selection enabled only if checkbox selection is enabled. return props.checkboxSelection && props.disableMultipleRowSelection !== true; } return !props.disableMultipleRowSelection; } const getRowNodeParents = (tree, id) => { const parents = []; let parent = id; while (parent != null && parent !== GRID_ROOT_GROUP_ID) { const node = tree[parent]; if (!node) { return parents; } parents.push(parent); parent = node.parent; } return parents; }; const getFilteredRowNodeSiblings = (tree, filteredRows, id) => { const node = tree[id]; if (!node) { return []; } const parent = node.parent; if (parent == null) { return []; } const parentNode = tree[parent]; return parentNode.children.filter(childId => childId !== id && filteredRows[childId] !== false); }; export const findRowsToSelect = (apiRef, tree, selectedRow, autoSelectDescendants, autoSelectParents, addRow) => { const filteredRows = gridFilteredRowsLookupSelector(apiRef); const selectedIdsLookup = selectedIdsLookupSelector(apiRef); const selectedDescendants = new Set([]); if (!autoSelectDescendants && !autoSelectParents) { return; } if (autoSelectDescendants) { const rowNode = tree[selectedRow]; if (rowNode?.type === 'group') { const descendants = getGridRowGroupSelectableDescendants(apiRef, selectedRow); descendants.forEach(rowId => { addRow(rowId); selectedDescendants.add(rowId); }); } } if (autoSelectParents) { const checkAllDescendantsSelected = rowId => { if (selectedIdsLookup[rowId] !== rowId && !selectedDescendants.has(rowId)) { return false; } const node = tree[rowId]; if (node?.type !== 'group') { return true; } return node.children.every(checkAllDescendantsSelected); }; const traverseParents = rowId => { const siblings = getFilteredRowNodeSiblings(tree, filteredRows, rowId); if (siblings.length === 0 || siblings.every(checkAllDescendantsSelected)) { const rowNode = tree[rowId]; const parent = rowNode.parent; if (parent != null && parent !== GRID_ROOT_GROUP_ID && apiRef.current.isRowSelectable(parent)) { addRow(parent); selectedDescendants.add(parent); traverseParents(parent); } } }; traverseParents(selectedRow); } }; export const findRowsToDeselect = (apiRef, tree, deselectedRow, autoSelectDescendants, autoSelectParents, removeRow) => { const selectedIdsLookup = selectedIdsLookupSelector(apiRef); if (!autoSelectParents && !autoSelectDescendants) { return; } if (autoSelectParents) { const allParents = getRowNodeParents(tree, deselectedRow); allParents.forEach(parent => { const isSelected = selectedIdsLookup[parent] === parent; if (isSelected) { removeRow(parent); } }); } if (autoSelectDescendants) { const rowNode = tree[deselectedRow]; if (rowNode?.type === 'group') { const descendants = getGridRowGroupSelectableDescendants(apiRef, deselectedRow); descendants.forEach(descendant => { removeRow(descendant); }); } } };