@mui/x-data-grid
Version:
The community edition of the data grid component (MUI X).
380 lines (316 loc) • 13.8 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useCellEditing = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/material/utils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridFocusStateSelector = require("../focus/gridFocusStateSelector");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridEditRowsSelector = require("./gridEditRowsSelector");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function isPromise(promise) {
return typeof promise.then === 'function';
}
const useCellEditing = (apiRef, props) => {
var _props$experimentalFe2;
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridEditRows');
const buildCallback = callback => (...args) => {
if (props.editMode === _gridEditRowModel.GridEditModes.Cell) {
callback(...args);
}
};
const setCellMode = React.useCallback((id, field, mode) => {
if (apiRef.current.getCellMode(id, field) === mode) {
return;
}
logger.debug(`Switching cell id: ${id} field: ${field} to mode: ${mode}`);
apiRef.current.setState(state => {
const newEditRowsState = (0, _extends2.default)({}, state.editRows);
newEditRowsState[id] = (0, _extends2.default)({}, newEditRowsState[id]);
if (mode === _gridEditRowModel.GridCellModes.Edit) {
newEditRowsState[id][field] = {
value: apiRef.current.getCellValue(id, field)
};
} else {
delete newEditRowsState[id][field];
if (!Object.keys(newEditRowsState[id]).length) {
delete newEditRowsState[id];
}
}
return (0, _extends2.default)({}, state, {
editRows: newEditRowsState
});
});
apiRef.current.forceUpdate();
apiRef.current.publishEvent('cellModeChange', apiRef.current.getCellParams(id, field));
}, [apiRef, logger]);
const getCellMode = React.useCallback((id, field) => {
const editRowsState = (0, _gridEditRowsSelector.gridEditRowsStateSelector)(apiRef.current.state);
const isEditing = editRowsState[id] && editRowsState[id][field];
return isEditing ? _gridEditRowModel.GridCellModes.Edit : _gridEditRowModel.GridCellModes.View;
}, [apiRef]); // TODO v6: it should always return a promise
const commitCellChange = React.useCallback((params, event = {}) => {
var _props$experimentalFe;
const {
id,
field
} = params;
apiRef.current.unstable_runPendingEditCellValueMutation(id, field);
const model = apiRef.current.getEditRowsModel();
if (!model[id] || !model[id][field]) {
throw new Error(`MUI: Cell at id: ${id} and field: ${field} is not in edit mode.`);
}
const editCellProps = model[id][field];
const column = apiRef.current.getColumn(field);
const row = apiRef.current.getRow(id);
if ((_props$experimentalFe = props.experimentalFeatures) != null && _props$experimentalFe.preventCommitWhileValidating) {
const cellProps = model[id][field];
if (cellProps.isValidating || cellProps.error) {
return false;
}
}
const commitParams = (0, _extends2.default)({}, params, {
value: editCellProps.value
});
let hasError = !!editCellProps.error;
if (!hasError && typeof column.preProcessEditCellProps === 'function') {
const result = column.preProcessEditCellProps({
id,
row,
props: editCellProps
});
if (isPromise(result)) {
return result.then(newEditCellProps => {
apiRef.current.unstable_setEditCellProps({
id,
field,
props: newEditCellProps
});
if (newEditCellProps.error) {
return false;
}
apiRef.current.publishEvent('cellEditCommit', commitParams, event);
return true;
});
}
apiRef.current.unstable_setEditCellProps({
id,
field,
props: result
});
hasError = !!result.error;
}
if (!hasError) {
apiRef.current.publishEvent('cellEditCommit', commitParams, event);
return true;
}
return false;
}, [apiRef, (_props$experimentalFe2 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe2.preventCommitWhileValidating]);
const setCellEditingEditCellValue = React.useCallback(params => {
const column = apiRef.current.getColumn(params.field);
const row = apiRef.current.getRow(params.id);
return new Promise(resolve => {
let newEditCellProps = {
value: params.value
};
const model = apiRef.current.getEditRowsModel();
const editCellProps = model[params.id][params.field];
if (typeof column.preProcessEditCellProps !== 'function') {
apiRef.current.unstable_setEditCellProps((0, _extends2.default)({}, params, {
props: newEditCellProps
}));
resolve(true);
return;
} // setEditCellProps runs the value parser and returns the updated props
newEditCellProps = apiRef.current.unstable_setEditCellProps((0, _extends2.default)({}, params, {
props: (0, _extends2.default)({}, editCellProps, {
isValidating: true
})
}));
Promise.resolve(column.preProcessEditCellProps({
id: params.id,
row,
props: (0, _extends2.default)({}, newEditCellProps, {
value: apiRef.current.unstable_parseValue(params.id, params.field, params.value)
})
})).then(newEditCellPropsProcessed => {
apiRef.current.unstable_setEditCellProps((0, _extends2.default)({}, params, {
props: (0, _extends2.default)({}, newEditCellPropsProcessed, {
isValidating: false
})
}));
resolve(!newEditCellPropsProcessed.error);
});
});
}, [apiRef]);
const cellEditingApi = {
setCellMode,
getCellMode,
commitCellChange,
unstable_setCellEditingEditCellValue: setCellEditingEditCellValue
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, cellEditingApi, 'EditRowApi');
const handleCellKeyDown = React.useCallback(async (params, event) => {
// Wait until IME is settled for Asian languages like Japanese and Chinese
// TODO: `event.which` is depricated but this is a temporary workaround
if (event.which === 229) {
return;
}
const {
id,
field,
cellMode,
isEditable
} = params;
if (!isEditable) {
return;
}
const isEditMode = cellMode === _gridEditRowModel.GridCellModes.Edit;
const isModifierKeyPressed = event.ctrlKey || event.metaKey || event.altKey;
if (!isEditMode && (0, _keyboardUtils.isCellEnterEditModeKeys)(event) && !isModifierKeyPressed && !(event.key === ' ' && event.shiftKey)) {
apiRef.current.publishEvent('cellEditStart', params, event);
}
if (!isEditMode && (0, _keyboardUtils.isDeleteKeys)(event.key)) {
apiRef.current.setEditCellValue({
id,
field,
value: ''
});
apiRef.current.commitCellChange({
id,
field
}, event);
apiRef.current.publishEvent('cellEditStop', params, event);
}
if (isEditMode && (0, _keyboardUtils.isCellEditCommitKeys)(event.key)) {
const commitParams = {
id,
field
};
const isValid = await apiRef.current.commitCellChange(commitParams, event);
if (!isValid) {
return;
}
}
if (isEditMode && (0, _keyboardUtils.isCellExitEditModeKeys)(event.key)) {
apiRef.current.publishEvent('cellEditStop', params, event);
}
}, [apiRef]);
const handleCellDoubleClick = React.useCallback((params, event) => {
if (!params.isEditable) {
return;
}
apiRef.current.publishEvent('cellEditStart', params, event);
}, [apiRef]);
const commitPropsAndExit = async (params, event) => {
if (params.cellMode === _gridEditRowModel.GridCellModes.View) {
return;
}
await apiRef.current.commitCellChange(params, event);
apiRef.current.publishEvent('cellEditStop', params, event);
};
const handleCellFocusOut = (0, _utils.useEventCallback)((params, event) => {
commitPropsAndExit(params, event);
});
const handleColumnHeaderDragStart = (0, _utils.useEventCallback)(() => {
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (!cell) {
return;
}
const params = apiRef.current.getCellParams(cell.id, cell.field);
commitPropsAndExit(params, {});
});
const handleCellEditStart = React.useCallback((params, event) => {
if (!params.isEditable) {
return;
}
apiRef.current.setCellMode(params.id, params.field, _gridEditRowModel.GridCellModes.Edit);
if ((0, _keyboardUtils.isKeyboardEvent)(event) && (0, _keyboardUtils.isPrintableKey)(event)) {
apiRef.current.unstable_setEditCellProps({
id: params.id,
field: params.field,
props: {
value: ''
}
});
}
}, [apiRef]);
const handleCellEditStop = React.useCallback((params, event) => {
apiRef.current.setCellMode(params.id, params.field, _gridEditRowModel.GridCellModes.View);
if (!(0, _keyboardUtils.isKeyboardEvent)(event)) {
return;
}
if ((0, _keyboardUtils.isCellEditCommitKeys)(event.key)) {
apiRef.current.publishEvent('cellNavigationKeyDown', params, event);
return;
}
if (event.key === 'Escape' || (0, _keyboardUtils.isDeleteKeys)(event.key)) {
apiRef.current.setCellFocus(params.id, params.field);
}
}, [apiRef]);
const handleCellEditCommit = React.useCallback(params => {
const {
id,
field
} = params;
const model = apiRef.current.getEditRowsModel();
const {
value
} = model[id][field];
logger.debug(`Setting cell id: ${id} field: ${field} to value: ${value == null ? void 0 : value.toString()}`);
const row = apiRef.current.getRow(id);
if (row) {
const column = apiRef.current.getColumn(params.field);
let rowUpdate = (0, _extends2.default)({}, row, {
[field]: value
});
if (column.valueSetter) {
rowUpdate = column.valueSetter({
row,
value
});
}
apiRef.current.updateRows([rowUpdate]);
}
}, [apiRef, logger]);
const handleEditCellPropsChange = React.useCallback(params => {
const row = apiRef.current.getRow(params.id);
const column = apiRef.current.getColumn(params.field);
const editCellProps = column.preProcessEditCellProps ? column.preProcessEditCellProps({
id: params.id,
row,
props: params.props
}) : params.props;
if (isPromise(editCellProps)) {
editCellProps.then(newEditCellProps => {
apiRef.current.unstable_setEditCellProps((0, _extends2.default)({}, params, {
props: newEditCellProps
}));
});
} else {
apiRef.current.unstable_setEditCellProps((0, _extends2.default)({}, params, {
props: editCellProps
}));
}
}, [apiRef]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', buildCallback(handleCellKeyDown));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', buildCallback(handleCellDoubleClick));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', buildCallback(handleCellFocusOut));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', buildCallback(handleColumnHeaderDragStart));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellEditStart', buildCallback(handleCellEditStart));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellEditStop', buildCallback(handleCellEditStop));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellEditCommit', buildCallback(handleCellEditCommit));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'editCellPropsChange', buildCallback(handleEditCellPropsChange));
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellEditCommit', props.onCellEditCommit);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellEditStart', props.onCellEditStart);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellEditStop', props.onCellEditStop);
};
exports.useCellEditing = useCellEditing;