UNPKG

@mui/x-data-grid

Version:

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

596 lines (584 loc) 27.7 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridRowSelection = exports.rowSelectionStateInitializer = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback")); var _signature = require("../../../constants/signature"); var _useGridEvent = require("../../utils/useGridEvent"); var _useGridApiMethod = require("../../utils/useGridApiMethod"); var _useGridLogger = require("../../utils/useGridLogger"); var _useGridSelector = require("../../utils/useGridSelector"); var _gridRowsSelector = require("../rows/gridRowsSelector"); var _gridRowSelectionSelector = require("./gridRowSelectionSelector"); var _gridFocusStateSelector = require("../focus/gridFocusStateSelector"); var _gridFilterSelector = require("../filter/gridFilterSelector"); var _colDef = require("../../../colDef"); var _gridEditRowModel = require("../../../models/gridEditRowModel"); var _keyboardUtils = require("../../../utils/keyboardUtils"); var _useGridVisibleRows = require("../../utils/useGridVisibleRows"); var _constants = require("../../../internals/constants"); var _gridClasses = require("../../../constants/gridClasses"); var _domUtils = require("../../../utils/domUtils"); var _utils = require("./utils"); var _gridRowSelectionManager = require("../../../models/gridRowSelectionManager"); var _pagination = require("../pagination"); const emptyModel = { type: 'include', ids: new Set() }; const rowSelectionStateInitializer = (state, props) => (0, _extends2.default)({}, state, { rowSelection: props.rowSelection ? props.rowSelectionModel ?? emptyModel : emptyModel }); /** * @requires useGridRows (state, method) - can be after * @requires useGridParamsApi (method) - can be after * @requires useGridFocus (state) - can be after * @requires useGridKeyboardNavigation (`cellKeyDown` event must first be consumed by it) */ exports.rowSelectionStateInitializer = rowSelectionStateInitializer; const useGridRowSelection = (apiRef, props) => { const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridSelection'); const runIfRowSelectionIsEnabled = React.useCallback(callback => (...args) => { if (props.rowSelection) { callback(...args); } }, [props.rowSelection]); const applyAutoSelection = props.signature !== _signature.GridSignature.DataGrid && (props.rowSelectionPropagation?.parents || props.rowSelectionPropagation?.descendants); const propRowSelectionModel = React.useMemo(() => { return props.rowSelectionModel; }, [props.rowSelectionModel]); const lastRowToggled = React.useRef(null); apiRef.current.registerControlState({ stateId: 'rowSelection', propModel: propRowSelectionModel, propOnChange: props.onRowSelectionModelChange, stateSelector: _gridRowSelectionSelector.gridRowSelectionStateSelector, changeEvent: 'rowSelectionChange' }); const { checkboxSelection, disableRowSelectionOnClick, isRowSelectable: propIsRowSelectable } = props; const canHaveMultipleSelection = (0, _utils.isMultipleRowSelectionEnabled)(props); const tree = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridRowTreeSelector); const isNestedData = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridRowMaximumTreeDepthSelector) > 1; const expandMouseRowRangeSelection = React.useCallback(id => { let endId = id; const startId = lastRowToggled.current ?? id; const isSelected = apiRef.current.isRowSelected(id); if (isSelected) { const visibleRowIds = (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef); const startIndex = visibleRowIds.findIndex(rowId => rowId === startId); const endIndex = visibleRowIds.findIndex(rowId => rowId === endId); if (startIndex === endIndex) { return; } if (startIndex > endIndex) { endId = visibleRowIds[endIndex + 1]; } else { endId = visibleRowIds[endIndex - 1]; } } lastRowToggled.current = id; apiRef.current.selectRowRange({ startId, endId }, !isSelected); }, [apiRef]); const getRowsToBeSelected = (0, _useEventCallback.default)(() => { const rowsToBeSelected = props.pagination && props.checkboxSelectionVisibleOnly && props.paginationMode === 'client' ? (0, _pagination.gridPaginatedVisibleSortedGridRowIdsSelector)(apiRef) : (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef); return rowsToBeSelected; }); /* * API METHODS */ const setRowSelectionModel = React.useCallback((model, reason) => { if (props.signature === _signature.GridSignature.DataGrid && !canHaveMultipleSelection && (model.type !== 'include' || model.ids.size > 1)) { throw new Error(['MUI X: `rowSelectionModel` can only contain 1 item in DataGrid.', 'You need to upgrade to DataGridPro or DataGridPremium component to unlock multiple selection.'].join('\n')); } const currentModel = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); if (currentModel !== model) { logger.debug(`Setting selection model`); apiRef.current.setState(state => (0, _extends2.default)({}, state, { rowSelection: props.rowSelection ? model : emptyModel }), reason); } }, [apiRef, logger, props.rowSelection, props.signature, canHaveMultipleSelection]); const isRowSelected = React.useCallback(id => { const selectionManager = (0, _gridRowSelectionSelector.gridRowSelectionManagerSelector)(apiRef); return selectionManager.has(id); }, [apiRef]); const isRowSelectable = React.useCallback(id => { if (props.rowSelection === false) { return false; } if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) { return false; } const rowNode = (0, _gridRowsSelector.gridRowNodeSelector)(apiRef, id); if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow') { return false; } return true; }, [apiRef, props.rowSelection, propIsRowSelectable]); const getSelectedRows = React.useCallback(() => (0, _gridRowSelectionSelector.gridRowSelectionIdsSelector)(apiRef), [apiRef]); const selectRow = React.useCallback((id, isSelected = true, resetSelection = false) => { if (!apiRef.current.isRowSelectable(id)) { return; } lastRowToggled.current = id; if (resetSelection) { logger.debug(`Setting selection for row ${id}`); const newSelectionModel = { type: 'include', ids: new Set() }; const addRow = rowId => { newSelectionModel.ids.add(rowId); }; if (isSelected) { addRow(id); if (applyAutoSelection) { (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow); } } apiRef.current.setRowSelectionModel(newSelectionModel, 'singleRowSelection'); } else { logger.debug(`Toggling selection for row ${id}`); const selectionModel = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); const newSelectionModel = { type: selectionModel.type, ids: new Set(selectionModel.ids) }; const selectionManager = (0, _gridRowSelectionManager.createRowSelectionManager)(newSelectionModel); selectionManager.unselect(id); const addRow = rowId => { selectionManager.select(rowId); }; const removeRow = rowId => { selectionManager.unselect(rowId); }; if (isSelected) { addRow(id); if (applyAutoSelection) { (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow); } } else if (applyAutoSelection) { (0, _utils.findRowsToDeselect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, removeRow); } const isSelectionValid = newSelectionModel.type === 'include' && newSelectionModel.ids.size < 2 || canHaveMultipleSelection; if (isSelectionValid) { apiRef.current.setRowSelectionModel(newSelectionModel, 'singleRowSelection'); } } }, [apiRef, logger, applyAutoSelection, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents, canHaveMultipleSelection]); const selectRows = React.useCallback((ids, isSelected = true, resetSelection = false) => { logger.debug(`Setting selection for several rows`); if (props.rowSelection === false) { return; } const selectableIds = new Set(); for (let i = 0; i < ids.length; i += 1) { const id = ids[i]; if (apiRef.current.isRowSelectable(id)) { selectableIds.add(id); } } const currentSelectionModel = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); let newSelectionModel; if (resetSelection) { newSelectionModel = { type: 'include', ids: selectableIds }; if (isSelected) { const selectionManager = (0, _gridRowSelectionManager.createRowSelectionManager)(newSelectionModel); if (applyAutoSelection) { const addRow = rowId => { selectionManager.select(rowId); }; for (const id of selectableIds) { (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow); } } } else { newSelectionModel.ids = new Set(); } if (currentSelectionModel.type === newSelectionModel.type && newSelectionModel.ids.size === currentSelectionModel.ids.size && Array.from(newSelectionModel.ids).every(id => currentSelectionModel.ids.has(id))) { return; } } else { newSelectionModel = { type: currentSelectionModel.type, ids: new Set(currentSelectionModel.ids) }; const selectionManager = (0, _gridRowSelectionManager.createRowSelectionManager)(newSelectionModel); const addRow = rowId => { selectionManager.select(rowId); }; const removeRow = rowId => { selectionManager.unselect(rowId); }; for (const id of selectableIds) { if (isSelected) { selectionManager.select(id); if (applyAutoSelection) { (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow); } } else { removeRow(id); if (applyAutoSelection) { (0, _utils.findRowsToDeselect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, removeRow); } } } } const isSelectionValid = newSelectionModel.type === 'include' && newSelectionModel.ids.size < 2 || canHaveMultipleSelection; if (isSelectionValid) { apiRef.current.setRowSelectionModel(newSelectionModel, 'multipleRowsSelection'); } }, [logger, applyAutoSelection, canHaveMultipleSelection, apiRef, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents, props.rowSelection]); const getPropagatedRowSelectionModel = React.useCallback(inputSelectionModel => { if (!isNestedData || !applyAutoSelection || inputSelectionModel.ids.size === 0 && inputSelectionModel.type === 'include') { return inputSelectionModel; } const propagatedSelectionModel = { type: inputSelectionModel.type, ids: new Set(inputSelectionModel.ids) }; const selectionManager = (0, _gridRowSelectionManager.createRowSelectionManager)(propagatedSelectionModel); const addRow = rowId => { selectionManager.select(rowId); }; for (const id of inputSelectionModel.ids) { (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow, selectionManager); } return propagatedSelectionModel; }, [apiRef, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents, isNestedData, applyAutoSelection]); const selectRowRange = React.useCallback(({ startId, endId }, isSelected = true, resetSelection = false) => { if (!apiRef.current.getRow(startId) || !apiRef.current.getRow(endId)) { return; } logger.debug(`Expanding selection from row ${startId} to row ${endId}`); // Using rows from all pages allow to select a range across several pages const allPagesRowIds = (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef); const startIndex = allPagesRowIds.indexOf(startId); const endIndex = allPagesRowIds.indexOf(endId); const [start, end] = startIndex > endIndex ? [endIndex, startIndex] : [startIndex, endIndex]; const rowsBetweenStartAndEnd = allPagesRowIds.slice(start, end + 1); apiRef.current.selectRows(rowsBetweenStartAndEnd, isSelected, resetSelection); }, [apiRef, logger]); const selectionPublicApi = { selectRow, setRowSelectionModel, getSelectedRows, isRowSelected, isRowSelectable }; const selectionPrivateApi = { selectRows, selectRowRange, getPropagatedRowSelectionModel }; (0, _useGridApiMethod.useGridApiMethod)(apiRef, selectionPublicApi, 'public'); (0, _useGridApiMethod.useGridApiMethod)(apiRef, selectionPrivateApi, props.signature === _signature.GridSignature.DataGrid ? 'private' : 'public'); /* * EVENTS */ const isFirstRender = React.useRef(true); const removeOutdatedSelection = React.useCallback((sortModelUpdated = false) => { if (isFirstRender.current) { return; } const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); const rowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef); const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef); const filteredRowsLookup = (0, _gridFilterSelector.gridFilteredRowsLookupSelector)(apiRef); const isNonExistent = id => { if (props.filterMode === 'server') { return !rowsLookup[id]; } return !rowTree[id] || filteredRowsLookup[id] === false; }; const newSelectionModel = { type: currentSelection.type, ids: new Set(currentSelection.ids) }; const selectionManager = (0, _gridRowSelectionManager.createRowSelectionManager)(newSelectionModel); let hasChanged = false; for (const id of currentSelection.ids) { if (isNonExistent(id)) { if (props.keepNonExistentRowsSelected) { continue; } selectionManager.unselect(id); hasChanged = true; continue; } if (!props.rowSelectionPropagation?.parents) { continue; } const node = tree[id]; if (node?.type === 'group') { const isAutoGenerated = node.isAutoGenerated; if (isAutoGenerated) { selectionManager.unselect(id); hasChanged = true; continue; } // Keep previously selected tree data parents selected if all their children are filtered out if (!node.children.every(childId => filteredRowsLookup[childId] === false)) { selectionManager.unselect(id); hasChanged = true; } } } // For nested data, on row tree updation (filtering, adding rows, etc.) when the selection is // not empty, we need to re-run scanning of the tree to propagate the selection changes // Example: A parent whose de-selected children are filtered out should now be selected const shouldReapplyPropagation = isNestedData && props.rowSelectionPropagation?.parents && (newSelectionModel.ids.size > 0 || // In case of exclude selection, newSelectionModel.ids.size === 0 means all rows are selected newSelectionModel.type === 'exclude'); if (hasChanged || shouldReapplyPropagation && !sortModelUpdated) { if (shouldReapplyPropagation) { if (newSelectionModel.type === 'exclude') { const unfilteredSelectedRowIds = getRowsToBeSelected(); const selectedRowIds = []; for (let i = 0; i < unfilteredSelectedRowIds.length; i += 1) { const rowId = unfilteredSelectedRowIds[i]; if ((props.keepNonExistentRowsSelected || !isNonExistent(rowId)) && selectionManager.has(rowId)) { selectedRowIds.push(rowId); } } apiRef.current.selectRows(selectedRowIds, true, true); } else { apiRef.current.selectRows(Array.from(newSelectionModel.ids), true, true); } } else { apiRef.current.setRowSelectionModel(newSelectionModel, 'multipleRowsSelection'); } } }, [apiRef, isNestedData, props.rowSelectionPropagation?.parents, props.keepNonExistentRowsSelected, props.filterMode, tree, getRowsToBeSelected]); const handleSingleRowSelection = React.useCallback((id, event) => { const hasCtrlKey = event.metaKey || event.ctrlKey; // multiple selection is only allowed if: // - it is a checkboxSelection // - it is a keyboard selection // - Ctrl is pressed const isMultipleSelectionDisabled = !checkboxSelection && !hasCtrlKey && !(0, _keyboardUtils.isKeyboardEvent)(event); const resetSelection = !canHaveMultipleSelection || isMultipleSelectionDisabled; const isSelected = apiRef.current.isRowSelected(id); const selectedRowsCount = (0, _gridRowSelectionSelector.gridRowSelectionCountSelector)(apiRef); // Clicking on a row should toggle the selection except when a range of rows is already selected and the selection should reset // In that case, we want to keep the current row selected (https://github.com/mui/mui-x/pull/15509#discussion_r1878082687) const shouldStaySelected = selectedRowsCount > 1 && resetSelection; const newSelectionState = shouldStaySelected || !isSelected; apiRef.current.selectRow(id, newSelectionState, resetSelection); }, [apiRef, canHaveMultipleSelection, checkboxSelection]); const handleRowClick = React.useCallback((params, event) => { if (disableRowSelectionOnClick) { return; } const field = event.target.closest(`.${_gridClasses.gridClasses.cell}`)?.getAttribute('data-field'); if (field === _colDef.GRID_CHECKBOX_SELECTION_COL_DEF.field) { // click on checkbox should not trigger row selection return; } if (field === _constants.GRID_DETAIL_PANEL_TOGGLE_FIELD) { // click to open the detail panel should not select the row return; } if (field) { const column = apiRef.current.getColumn(field); if (column?.type === _colDef.GRID_ACTIONS_COLUMN_TYPE) { return; } } const rowNode = (0, _gridRowsSelector.gridRowNodeSelector)(apiRef, params.id); if (rowNode.type === 'pinnedRow') { return; } if (event.shiftKey && canHaveMultipleSelection) { expandMouseRowRangeSelection(params.id); } else { handleSingleRowSelection(params.id, event); } }, [disableRowSelectionOnClick, canHaveMultipleSelection, apiRef, expandMouseRowRangeSelection, handleSingleRowSelection]); const preventSelectionOnShift = React.useCallback((params, event) => { if (canHaveMultipleSelection && event.shiftKey) { window.getSelection()?.removeAllRanges(); } }, [canHaveMultipleSelection]); const handleRowSelectionCheckboxChange = React.useCallback((params, event) => { if (canHaveMultipleSelection && event.nativeEvent.shiftKey) { expandMouseRowRangeSelection(params.id); } else { apiRef.current.selectRow(params.id, params.value, !canHaveMultipleSelection); } }, [apiRef, expandMouseRowRangeSelection, canHaveMultipleSelection]); const toggleAllRows = React.useCallback(value => { const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef); const quickFilterModel = (0, _gridFilterSelector.gridQuickFilterValuesSelector)(apiRef); const hasFilters = filterModel.items.length > 0 || quickFilterModel?.some(val => val.length); if (!props.isRowSelectable && !props.checkboxSelectionVisibleOnly && (!isNestedData || props.rowSelectionPropagation?.descendants) && !hasFilters) { apiRef.current.setRowSelectionModel({ type: value ? 'exclude' : 'include', ids: new Set() }, 'multipleRowsSelection'); } else { apiRef.current.selectRows(getRowsToBeSelected(), value); } }, [apiRef, getRowsToBeSelected, props.checkboxSelectionVisibleOnly, props.isRowSelectable, props.rowSelectionPropagation?.descendants, isNestedData]); const handleHeaderSelectionCheckboxChange = React.useCallback(params => { toggleAllRows(params.value); }, [toggleAllRows]); const handleCellKeyDown = React.useCallback((params, event) => { // Get the most recent cell mode because it may have been changed by another listener if (apiRef.current.getCellMode(params.id, params.field) === _gridEditRowModel.GridCellModes.Edit) { return; } // Ignore portal // Do not apply shortcuts if the focus is not on the cell root component if ((0, _domUtils.isEventTargetInPortal)(event)) { return; } if ((0, _keyboardUtils.isNavigationKey)(event.key) && event.shiftKey) { // The cell that has focus after the keyboard navigation const focusCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef); if (focusCell && focusCell.id !== params.id) { event.preventDefault(); const isNextRowSelected = apiRef.current.isRowSelected(focusCell.id); if (!canHaveMultipleSelection) { apiRef.current.selectRow(focusCell.id, !isNextRowSelected, true); return; } const newRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(focusCell.id); const previousRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(params.id); let start; let end; if (newRowIndex > previousRowIndex) { if (isNextRowSelected) { // We are navigating to the bottom of the page and adding selected rows start = previousRowIndex; end = newRowIndex - 1; } else { // We are navigating to the bottom of the page and removing selected rows start = previousRowIndex; end = newRowIndex; } } else { // eslint-disable-next-line no-lonely-if if (isNextRowSelected) { // We are navigating to the top of the page and removing selected rows start = newRowIndex + 1; end = previousRowIndex; } else { // We are navigating to the top of the page and adding selected rows start = newRowIndex; end = previousRowIndex; } } const visibleRows = (0, _useGridVisibleRows.getVisibleRows)(apiRef); const rowsBetweenStartAndEnd = []; for (let i = start; i <= end; i += 1) { rowsBetweenStartAndEnd.push(visibleRows.rows[i].id); } apiRef.current.selectRows(rowsBetweenStartAndEnd, !isNextRowSelected); return; } } if (event.key === ' ' && event.shiftKey) { event.preventDefault(); handleSingleRowSelection(params.id, event); return; } if (String.fromCharCode(event.keyCode) === 'A' && (event.ctrlKey || event.metaKey)) { event.preventDefault(); toggleAllRows(true); } }, [apiRef, canHaveMultipleSelection, handleSingleRowSelection, toggleAllRows]); const syncControlledState = (0, _useEventCallback.default)(() => { if (!props.rowSelection) { apiRef.current.setRowSelectionModel(emptyModel); return; } if (propRowSelectionModel === undefined) { return; } if (!applyAutoSelection || !isNestedData || propRowSelectionModel.type === 'include' && propRowSelectionModel.ids.size === 0) { apiRef.current.setRowSelectionModel(propRowSelectionModel); return; } const newSelectionModel = apiRef.current.getPropagatedRowSelectionModel(propRowSelectionModel); if (newSelectionModel.type !== propRowSelectionModel.type || newSelectionModel.ids.size !== propRowSelectionModel.ids.size || !Array.from(propRowSelectionModel.ids).every(id => newSelectionModel.ids.has(id))) { apiRef.current.setRowSelectionModel(newSelectionModel); return; } apiRef.current.setRowSelectionModel(propRowSelectionModel); }); (0, _useGridEvent.useGridEvent)(apiRef, 'sortedRowsSet', runIfRowSelectionIsEnabled(() => removeOutdatedSelection(true))); (0, _useGridEvent.useGridEvent)(apiRef, 'filteredRowsSet', runIfRowSelectionIsEnabled(() => removeOutdatedSelection())); (0, _useGridEvent.useGridEvent)(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick)); (0, _useGridEvent.useGridEvent)(apiRef, 'rowSelectionCheckboxChange', runIfRowSelectionIsEnabled(handleRowSelectionCheckboxChange)); (0, _useGridEvent.useGridEvent)(apiRef, 'headerSelectionCheckboxChange', handleHeaderSelectionCheckboxChange); (0, _useGridEvent.useGridEvent)(apiRef, 'cellMouseDown', runIfRowSelectionIsEnabled(preventSelectionOnShift)); (0, _useGridEvent.useGridEvent)(apiRef, 'cellKeyDown', runIfRowSelectionIsEnabled(handleCellKeyDown)); /* * EFFECTS */ React.useEffect(() => { syncControlledState(); }, [apiRef, propRowSelectionModel, props.rowSelection, syncControlledState]); const isStateControlled = propRowSelectionModel != null; React.useEffect(() => { if (isStateControlled || !props.rowSelection || typeof isRowSelectable !== 'function') { return; } // props.isRowSelectable changed const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); if (currentSelection.type !== 'include') { return; } const selectableIds = new Set(); for (const id of currentSelection.ids) { if (isRowSelectable(id)) { selectableIds.add(id); } } if (selectableIds.size < currentSelection.ids.size) { apiRef.current.setRowSelectionModel({ type: currentSelection.type, ids: selectableIds }); } }, [apiRef, isRowSelectable, isStateControlled, props.rowSelection]); React.useEffect(() => { if (!props.rowSelection || isStateControlled) { return; } const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef); if (!canHaveMultipleSelection && (currentSelection.type === 'include' && currentSelection.ids.size > 1 || currentSelection.type === 'exclude')) { // See https://github.com/mui/mui-x/issues/8455 apiRef.current.setRowSelectionModel(emptyModel); } }, [apiRef, canHaveMultipleSelection, checkboxSelection, isStateControlled, props.rowSelection]); React.useEffect(() => { runIfRowSelectionIsEnabled(removeOutdatedSelection); }, [removeOutdatedSelection, runIfRowSelectionIsEnabled]); React.useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; } }, []); }; exports.useGridRowSelection = useGridRowSelection;