UNPKG

@mui/x-data-grid

Version:

The community edition of the data grid component (MUI X).

411 lines (348 loc) 14.2 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import _extends from "@babel/runtime/helpers/esm/extends"; import _regeneratorRuntime from "@babel/runtime/regenerator"; import * as React from 'react'; import { useEventCallback } from '@mui/material/utils'; import { useGridApiOptionHandler, useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; import { GridCellModes, GridEditModes } from '../../../models/gridEditRowModel'; import { isKeyboardEvent, isPrintableKey, isCellEnterEditModeKeys, isCellExitEditModeKeys, isCellEditCommitKeys, isDeleteKeys } from '../../../utils/keyboardUtils'; import { useGridLogger } from '../../utils/useGridLogger'; import { gridFocusCellSelector } from '../focus/gridFocusStateSelector'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { gridEditRowsStateSelector } from './gridEditRowsSelector'; function isPromise(promise) { return typeof promise.then === 'function'; } export var useCellEditing = function useCellEditing(apiRef, props) { var _props$experimentalFe2; var logger = useGridLogger(apiRef, 'useGridEditRows'); var buildCallback = function buildCallback(callback) { return function () { if (props.editMode === GridEditModes.Cell) { callback.apply(void 0, arguments); } }; }; var setCellMode = React.useCallback(function (id, field, mode) { if (apiRef.current.getCellMode(id, field) === mode) { return; } logger.debug("Switching cell id: ".concat(id, " field: ").concat(field, " to mode: ").concat(mode)); apiRef.current.setState(function (state) { var newEditRowsState = _extends({}, state.editRows); newEditRowsState[id] = _extends({}, newEditRowsState[id]); if (mode === 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 _extends({}, state, { editRows: newEditRowsState }); }); apiRef.current.forceUpdate(); apiRef.current.publishEvent('cellModeChange', apiRef.current.getCellParams(id, field)); }, [apiRef, logger]); var getCellMode = React.useCallback(function (id, field) { var editRowsState = gridEditRowsStateSelector(apiRef.current.state); var isEditing = editRowsState[id] && editRowsState[id][field]; return isEditing ? GridCellModes.Edit : GridCellModes.View; }, [apiRef]); // TODO v6: it should always return a promise var commitCellChange = React.useCallback(function (params) { var _props$experimentalFe; var event = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var id = params.id, field = params.field; apiRef.current.unstable_runPendingEditCellValueMutation(id, field); var model = apiRef.current.getEditRowsModel(); if (!model[id] || !model[id][field]) { throw new Error("MUI: Cell at id: ".concat(id, " and field: ").concat(field, " is not in edit mode.")); } var editCellProps = model[id][field]; var column = apiRef.current.getColumn(field); var row = apiRef.current.getRow(id); if ((_props$experimentalFe = props.experimentalFeatures) != null && _props$experimentalFe.preventCommitWhileValidating) { var cellProps = model[id][field]; if (cellProps.isValidating || cellProps.error) { return false; } } var commitParams = _extends({}, params, { value: editCellProps.value }); var hasError = !!editCellProps.error; if (!hasError && typeof column.preProcessEditCellProps === 'function') { var result = column.preProcessEditCellProps({ id: id, row: row, props: editCellProps }); if (isPromise(result)) { return result.then(function (newEditCellProps) { apiRef.current.unstable_setEditCellProps({ id: id, field: field, props: newEditCellProps }); if (newEditCellProps.error) { return false; } apiRef.current.publishEvent('cellEditCommit', commitParams, event); return true; }); } apiRef.current.unstable_setEditCellProps({ id: id, field: 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]); var setCellEditingEditCellValue = React.useCallback(function (params) { var column = apiRef.current.getColumn(params.field); var row = apiRef.current.getRow(params.id); return new Promise(function (resolve) { var newEditCellProps = { value: params.value }; var model = apiRef.current.getEditRowsModel(); var editCellProps = model[params.id][params.field]; if (typeof column.preProcessEditCellProps !== 'function') { apiRef.current.unstable_setEditCellProps(_extends({}, params, { props: newEditCellProps })); resolve(true); return; } // setEditCellProps runs the value parser and returns the updated props newEditCellProps = apiRef.current.unstable_setEditCellProps(_extends({}, params, { props: _extends({}, editCellProps, { isValidating: true }) })); Promise.resolve(column.preProcessEditCellProps({ id: params.id, row: row, props: _extends({}, newEditCellProps, { value: apiRef.current.unstable_parseValue(params.id, params.field, params.value) }) })).then(function (newEditCellPropsProcessed) { apiRef.current.unstable_setEditCellProps(_extends({}, params, { props: _extends({}, newEditCellPropsProcessed, { isValidating: false }) })); resolve(!newEditCellPropsProcessed.error); }); }); }, [apiRef]); var cellEditingApi = { setCellMode: setCellMode, getCellMode: getCellMode, commitCellChange: commitCellChange, unstable_setCellEditingEditCellValue: setCellEditingEditCellValue }; useGridApiMethod(apiRef, cellEditingApi, 'EditRowApi'); var handleCellKeyDown = React.useCallback( /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(params, event) { var id, field, cellMode, isEditable, isEditMode, isModifierKeyPressed, commitParams, isValid; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (!(event.which === 229)) { _context.next = 2; break; } return _context.abrupt("return"); case 2: id = params.id, field = params.field, cellMode = params.cellMode, isEditable = params.isEditable; if (isEditable) { _context.next = 5; break; } return _context.abrupt("return"); case 5: isEditMode = cellMode === GridCellModes.Edit; isModifierKeyPressed = event.ctrlKey || event.metaKey || event.altKey; if (!isEditMode && isCellEnterEditModeKeys(event) && !isModifierKeyPressed && !(event.key === ' ' && event.shiftKey)) { apiRef.current.publishEvent('cellEditStart', params, event); } if (!isEditMode && isDeleteKeys(event.key)) { apiRef.current.setEditCellValue({ id: id, field: field, value: '' }); apiRef.current.commitCellChange({ id: id, field: field }, event); apiRef.current.publishEvent('cellEditStop', params, event); } if (!(isEditMode && isCellEditCommitKeys(event.key))) { _context.next = 16; break; } commitParams = { id: id, field: field }; _context.next = 13; return apiRef.current.commitCellChange(commitParams, event); case 13: isValid = _context.sent; if (isValid) { _context.next = 16; break; } return _context.abrupt("return"); case 16: if (isEditMode && isCellExitEditModeKeys(event.key)) { apiRef.current.publishEvent('cellEditStop', params, event); } case 17: case "end": return _context.stop(); } } }, _callee); })); return function (_x, _x2) { return _ref.apply(this, arguments); }; }(), [apiRef]); var handleCellDoubleClick = React.useCallback(function (params, event) { if (!params.isEditable) { return; } apiRef.current.publishEvent('cellEditStart', params, event); }, [apiRef]); var commitPropsAndExit = /*#__PURE__*/function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(params, event) { return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (!(params.cellMode === GridCellModes.View)) { _context2.next = 2; break; } return _context2.abrupt("return"); case 2: _context2.next = 4; return apiRef.current.commitCellChange(params, event); case 4: apiRef.current.publishEvent('cellEditStop', params, event); case 5: case "end": return _context2.stop(); } } }, _callee2); })); return function commitPropsAndExit(_x3, _x4) { return _ref2.apply(this, arguments); }; }(); var handleCellFocusOut = useEventCallback(function (params, event) { commitPropsAndExit(params, event); }); var handleColumnHeaderDragStart = useEventCallback(function () { var cell = gridFocusCellSelector(apiRef); if (!cell) { return; } var params = apiRef.current.getCellParams(cell.id, cell.field); commitPropsAndExit(params, {}); }); var handleCellEditStart = React.useCallback(function (params, event) { if (!params.isEditable) { return; } apiRef.current.setCellMode(params.id, params.field, GridCellModes.Edit); if (isKeyboardEvent(event) && isPrintableKey(event)) { apiRef.current.unstable_setEditCellProps({ id: params.id, field: params.field, props: { value: '' } }); } }, [apiRef]); var handleCellEditStop = React.useCallback(function (params, event) { apiRef.current.setCellMode(params.id, params.field, GridCellModes.View); if (!isKeyboardEvent(event)) { return; } if (isCellEditCommitKeys(event.key)) { apiRef.current.publishEvent('cellNavigationKeyDown', params, event); return; } if (event.key === 'Escape' || isDeleteKeys(event.key)) { apiRef.current.setCellFocus(params.id, params.field); } }, [apiRef]); var handleCellEditCommit = React.useCallback(function (params) { var id = params.id, field = params.field; var model = apiRef.current.getEditRowsModel(); var value = model[id][field].value; logger.debug("Setting cell id: ".concat(id, " field: ").concat(field, " to value: ").concat(value == null ? void 0 : value.toString())); var row = apiRef.current.getRow(id); if (row) { var column = apiRef.current.getColumn(params.field); var rowUpdate = _extends({}, row, _defineProperty({}, field, value)); if (column.valueSetter) { rowUpdate = column.valueSetter({ row: row, value: value }); } apiRef.current.updateRows([rowUpdate]); } }, [apiRef, logger]); var handleEditCellPropsChange = React.useCallback(function (params) { var row = apiRef.current.getRow(params.id); var column = apiRef.current.getColumn(params.field); var editCellProps = column.preProcessEditCellProps ? column.preProcessEditCellProps({ id: params.id, row: row, props: params.props }) : params.props; if (isPromise(editCellProps)) { editCellProps.then(function (newEditCellProps) { apiRef.current.unstable_setEditCellProps(_extends({}, params, { props: newEditCellProps })); }); } else { apiRef.current.unstable_setEditCellProps(_extends({}, params, { props: editCellProps })); } }, [apiRef]); useGridApiEventHandler(apiRef, 'cellKeyDown', buildCallback(handleCellKeyDown)); useGridApiEventHandler(apiRef, 'cellDoubleClick', buildCallback(handleCellDoubleClick)); useGridApiEventHandler(apiRef, 'cellFocusOut', buildCallback(handleCellFocusOut)); useGridApiEventHandler(apiRef, 'columnHeaderDragStart', buildCallback(handleColumnHeaderDragStart)); useGridApiEventHandler(apiRef, 'cellEditStart', buildCallback(handleCellEditStart)); useGridApiEventHandler(apiRef, 'cellEditStop', buildCallback(handleCellEditStop)); useGridApiEventHandler(apiRef, 'cellEditCommit', buildCallback(handleCellEditCommit)); useGridApiEventHandler(apiRef, 'editCellPropsChange', buildCallback(handleEditCellPropsChange)); useGridApiOptionHandler(apiRef, 'cellEditCommit', props.onCellEditCommit); useGridApiOptionHandler(apiRef, 'cellEditStart', props.onCellEditStart); useGridApiOptionHandler(apiRef, 'cellEditStop', props.onCellEditStop); };