UNPKG

@mui/x-data-grid

Version:

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

358 lines (299 loc) 14.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridRowEditing = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _utils = require("@mui/material/utils"); var _useGridApiMethod = require("../../utils/useGridApiMethod"); var _gridEditRowModel = require("../../../models/gridEditRowModel"); var _useGridSelector = require("../../utils/useGridSelector"); var _gridColumnsSelector = require("../columns/gridColumnsSelector"); var _gridEditRowsSelector = require("./gridEditRowsSelector"); var _gridFocusStateSelector = require("../focus/gridFocusStateSelector"); var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler"); 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; } const useGridRowEditing = (apiRef, props) => { var _props$experimentalFe2, _props$experimentalFe4; const focusTimeout = React.useRef(null); const nextFocusedCell = React.useRef(null); const columns = (0, _useGridSelector.useGridSelector)(apiRef, _gridColumnsSelector.gridColumnDefinitionsSelector); const buildCallback = callback => (...args) => { if (props.editMode === _gridEditRowModel.GridEditModes.Row) { callback(...args); } }; const setRowMode = React.useCallback((id, mode) => { if (mode === apiRef.current.getRowMode(id)) { return; } apiRef.current.setState(state => { const newEditRowsState = (0, _extends2.default)({}, state.editRows); if (mode === _gridEditRowModel.GridRowModes.Edit) { newEditRowsState[id] = {}; columns.forEach(column => { const cellParams = apiRef.current.getCellParams(id, column.field); if (cellParams.isEditable) { newEditRowsState[id][column.field] = { value: cellParams.value }; } }); } else { delete newEditRowsState[id]; } return (0, _extends2.default)({}, state, { editRows: newEditRowsState }); }); apiRef.current.forceUpdate(); }, [apiRef, columns]); const getRowMode = React.useCallback(id => { if (props.editMode === _gridEditRowModel.GridEditModes.Cell) { return _gridEditRowModel.GridRowModes.View; } const editRowsState = (0, _gridEditRowsSelector.gridEditRowsStateSelector)(apiRef.current.state); return editRowsState[id] ? _gridEditRowModel.GridRowModes.Edit : _gridEditRowModel.GridRowModes.View; }, [apiRef, props.editMode]); const commitRowChange = React.useCallback((id, event = {}) => { var _props$experimentalFe; if (props.editMode === _gridEditRowModel.GridEditModes.Cell) { throw new Error(`MUI: You can't commit changes when the edit mode is 'cell'.`); } apiRef.current.unstable_runPendingEditCellValueMutation(id); const model = apiRef.current.getEditRowsModel(); const editRowProps = model[id]; if (!editRowProps) { throw new Error(`MUI: Row at id: ${id} is not being edited.`); } if ((_props$experimentalFe = props.experimentalFeatures) != null && _props$experimentalFe.preventCommitWhileValidating) { const isValid = Object.keys(editRowProps).reduce((acc, field) => { return acc && !editRowProps[field].isValidating && !editRowProps[field].error; }, true); if (!isValid) { return false; } } const hasFieldWithError = Object.values(editRowProps).some(value => !!value.error); if (hasFieldWithError) { return false; } const fieldsWithValidator = Object.keys(editRowProps).filter(field => { const column = apiRef.current.getColumn(field); return typeof column.preProcessEditCellProps === 'function'; }); if (fieldsWithValidator.length > 0) { const row = apiRef.current.getRow(id); const validatorErrors = fieldsWithValidator.map(async field => { const column = apiRef.current.getColumn(field); const newEditCellProps = await Promise.resolve(column.preProcessEditCellProps({ id, row, props: editRowProps[field] })); apiRef.current.unstable_setEditCellProps({ id, field, props: newEditCellProps }); return newEditCellProps.error; }); return Promise.all(validatorErrors).then(errors => { if (errors.some(error => !!error)) { return false; } apiRef.current.publishEvent('rowEditCommit', id, event); return true; }); } apiRef.current.publishEvent('rowEditCommit', id, event); return true; }, [apiRef, props.editMode, (_props$experimentalFe2 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe2.preventCommitWhileValidating]); const setRowEditingEditCellValue = React.useCallback(params => { const model = apiRef.current.getEditRowsModel(); const editRow = model[params.id]; const row = apiRef.current.getRow(params.id); let isValid = true; return new Promise(resolve => { Object.keys(editRow).forEach(async field => { const column = apiRef.current.getColumn(field); let editCellProps = field === params.field ? { value: params.value } : editRow[field]; // setEditCellProps runs the value parser and returns the updated props editCellProps = apiRef.current.unstable_setEditCellProps({ id: params.id, field, props: (0, _extends2.default)({}, editCellProps, { isValidating: true }) }); if (column.preProcessEditCellProps) { editCellProps = await Promise.resolve(column.preProcessEditCellProps({ id: params.id, row, props: (0, _extends2.default)({}, editCellProps, { value: field === params.field ? apiRef.current.unstable_parseValue(params.id, field, params.value) : editCellProps.value }) })); } if (editCellProps.error) { isValid = false; } apiRef.current.unstable_setEditCellProps({ id: params.id, field, props: (0, _extends2.default)({}, editCellProps, { isValidating: false }) }); }); resolve(isValid); }); }, [apiRef]); const rowEditingApi = { setRowMode, getRowMode, commitRowChange, unstable_setRowEditingEditCellValue: setRowEditingEditCellValue }; (0, _useGridApiMethod.useGridApiMethod)(apiRef, rowEditingApi, '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 { cellMode, isEditable } = params; if (!isEditable) { return; } const isEditMode = cellMode === _gridEditRowModel.GridCellModes.Edit; const rowParams = apiRef.current.getRowParams(params.id); if (isEditMode) { if (event.key === 'Enter') { var _props$experimentalFe3; // TODO: check the return before firing 'rowEditStop' // On cell editing, it won't exits the edit mode with error const isValid = await apiRef.current.commitRowChange(params.id); if (!isValid && (_props$experimentalFe3 = props.experimentalFeatures) != null && _props$experimentalFe3.preventCommitWhileValidating) { return; } apiRef.current.publishEvent('rowEditStop', rowParams, event); } else if (event.key === 'Escape') { apiRef.current.publishEvent('rowEditStop', rowParams, event); } } else if (event.key === 'Enter') { apiRef.current.publishEvent('rowEditStart', rowParams, event); } }, [apiRef, (_props$experimentalFe4 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe4.preventCommitWhileValidating]); const handleCellDoubleClick = React.useCallback((params, event) => { if (!params.isEditable) { return; } const rowParams = apiRef.current.getRowParams(params.id); apiRef.current.publishEvent('rowEditStart', rowParams, event); }, [apiRef]); const handleEditCellPropsChange = React.useCallback(params => { const row = apiRef.current.getRow(params.id); const model = apiRef.current.getEditRowsModel(); const editRow = model[params.id]; Object.keys(editRow).forEach(async field => { const column = apiRef.current.getColumn(field); if (column.preProcessEditCellProps) { const editCellProps = field === params.field ? params.props : editRow[field]; const newEditCellProps = await Promise.resolve(column.preProcessEditCellProps({ id: params.id, row, props: editCellProps })); apiRef.current.unstable_setEditCellProps({ id: params.id, field, props: newEditCellProps }); } else if (field === params.field) { apiRef.current.unstable_setEditCellProps(params); } }); }, [apiRef]); const handleRowEditStart = React.useCallback(params => { apiRef.current.setRowMode(params.id, _gridEditRowModel.GridRowModes.Edit); }, [apiRef]); const handleRowEditStop = React.useCallback((params, event) => { apiRef.current.setRowMode(params.id, _gridEditRowModel.GridRowModes.View); if (event.key === 'Enter') { apiRef.current.publishEvent('cellNavigationKeyDown', params, event); } }, [apiRef]); const handleRowEditCommit = React.useCallback(id => { const model = apiRef.current.getEditRowsModel(); const editRow = model[id]; if (!editRow) { throw new Error(`MUI: Row at id: ${id} is not being edited.`); } const row = apiRef.current.getRow(id); if (row) { let rowUpdate = (0, _extends2.default)({}, row); Object.keys(editRow).forEach(field => { const column = apiRef.current.getColumn(field); const value = editRow[field].value; if (column.valueSetter) { rowUpdate = column.valueSetter({ row: rowUpdate, value }); } else { rowUpdate[field] = value; } }); apiRef.current.updateRows([rowUpdate]); } }, [apiRef]); const handleCellFocusIn = React.useCallback(params => { nextFocusedCell.current = params; }, []); const commitPropsAndExit = async (params, event) => { if (params.cellMode === _gridEditRowModel.GridCellModes.View) { return; } nextFocusedCell.current = null; focusTimeout.current = setTimeout(async () => { var _nextFocusedCell$curr; if (((_nextFocusedCell$curr = nextFocusedCell.current) == null ? void 0 : _nextFocusedCell$curr.id) !== params.id) { await apiRef.current.commitRowChange(params.id, event); const rowParams = apiRef.current.getRowParams(params.id); apiRef.current.publishEvent('rowEditStop', rowParams, 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, {}); }); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', buildCallback(handleCellKeyDown)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', buildCallback(handleCellDoubleClick)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'editCellPropsChange', buildCallback(handleEditCellPropsChange)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowEditStart', buildCallback(handleRowEditStart)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowEditStop', buildCallback(handleRowEditStop)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowEditCommit', buildCallback(handleRowEditCommit)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusIn', buildCallback(handleCellFocusIn)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', buildCallback(handleCellFocusOut)); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', buildCallback(handleColumnHeaderDragStart)); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowEditCommit', props.onRowEditCommit); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowEditStart', props.onRowEditStart); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowEditStop', props.onRowEditStop); }; exports.useGridRowEditing = useGridRowEditing;