@toolpad/core
Version:
Dashboard framework powered by Material UI.
311 lines (310 loc) • 11.8 kB
JavaScript
'use client';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CrudForm = CrudForm;
var React = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _invariant = _interopRequireDefault(require("invariant"));
var _Box = _interopRequireDefault(require("@mui/material/Box"));
var _Button = _interopRequireDefault(require("@mui/material/Button"));
var _Checkbox = _interopRequireDefault(require("@mui/material/Checkbox"));
var _FormControl = _interopRequireDefault(require("@mui/material/FormControl"));
var _FormControlLabel = _interopRequireDefault(require("@mui/material/FormControlLabel"));
var _FormGroup = _interopRequireDefault(require("@mui/material/FormGroup"));
var _FormHelperText = _interopRequireDefault(require("@mui/material/FormHelperText"));
var _Grid = _interopRequireDefault(require("@mui/material/Grid"));
var _InputLabel = _interopRequireDefault(require("@mui/material/InputLabel"));
var _MenuItem = _interopRequireDefault(require("@mui/material/MenuItem"));
var _Select = _interopRequireDefault(require("@mui/material/Select"));
var _TextField = _interopRequireDefault(require("@mui/material/TextField"));
var _AdapterDayjs = require("@mui/x-date-pickers/AdapterDayjs");
var _DatePicker = require("@mui/x-date-pickers/DatePicker");
var _DateTimePicker = require("@mui/x-date-pickers/DateTimePicker");
var _LocalizationProvider = require("@mui/x-date-pickers/LocalizationProvider");
var _dayjs = _interopRequireDefault(require("dayjs"));
var _context = require("../shared/context");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/**
*
* Demos:
*
* - [CRUD](https://mui.com/toolpad/core/react-crud/)
*
* API:
*
* - [CrudForm API](https://mui.com/toolpad/core/api/crud-form)
*/
function CrudForm(props) {
const {
formState,
onFieldChange,
onSubmit,
onReset,
submitButtonLabel,
slots,
slotProps
} = props;
const formValues = formState.values;
const formErrors = formState.errors;
const crudContext = React.useContext(_context.CrudContext);
const dataSource = props.dataSource ?? crudContext.dataSource;
(0, _invariant.default)(dataSource, 'No data source found.');
const {
fields
} = dataSource;
const [, submitAction, isSubmitting] = React.useActionState(async () => {
try {
await onSubmit(formValues);
} catch (error) {
return error;
}
return null;
}, null);
const handleTextFieldChange = React.useCallback(event => {
onFieldChange(event.target.name, event.target.value);
}, [onFieldChange]);
const handleNumberFieldChange = React.useCallback(event => {
onFieldChange(event.target.name, Number(event.target.value));
}, [onFieldChange]);
const handleCheckboxFieldChange = React.useCallback((event, checked) => {
onFieldChange(event.target.name, checked);
}, [onFieldChange]);
const handleDateFieldChange = React.useCallback(name => value => {
if (value?.isValid()) {
onFieldChange(name, value.toISOString() ?? null);
} else if (formValues[name]) {
onFieldChange(name, null);
}
}, [formValues, onFieldChange]);
const handleSelectFieldChange = React.useCallback(event => {
onFieldChange(event.target.name, event.target.value);
}, [onFieldChange]);
const renderField = React.useCallback(formField => {
const {
field,
type,
headerName
} = formField;
const fieldValue = formValues[field];
const fieldError = formErrors[field];
let fieldElement = null;
if (!type || type === 'string') {
const TextFieldComponent = slots?.textField ?? _TextField.default;
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsx)(TextFieldComponent, {
value: fieldValue ?? '',
onChange: handleTextFieldChange,
name: field,
label: headerName,
error: !!fieldError,
helperText: fieldError ?? ' ',
fullWidth: true,
...slotProps?.textField
});
}
if (type === 'number') {
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
value: fieldValue ?? '',
onChange: handleNumberFieldChange,
name: field,
type: "number",
label: headerName,
error: !!fieldError,
helperText: fieldError ?? ' ',
fullWidth: true
});
}
if (type === 'boolean') {
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_FormControl.default, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_FormControlLabel.default, {
name: field,
control: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Checkbox.default, {
size: "large",
checked: fieldValue,
onChange: handleCheckboxFieldChange
}),
label: headerName
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormHelperText.default, {
error: !!fieldError,
children: fieldError ?? ' '
})]
});
}
if (type === 'date') {
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsx)(_LocalizationProvider.LocalizationProvider, {
dateAdapter: _AdapterDayjs.AdapterDayjs,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DatePicker.DatePicker, {
value: fieldValue ? (0, _dayjs.default)(fieldValue) : null,
onChange: handleDateFieldChange(field),
name: field,
label: headerName,
slotProps: {
textField: {
error: !!fieldError,
helperText: fieldError ?? ' ',
fullWidth: true
}
}
})
});
}
if (type === 'dateTime') {
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsx)(_LocalizationProvider.LocalizationProvider, {
dateAdapter: _AdapterDayjs.AdapterDayjs,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DateTimePicker.DateTimePicker, {
value: fieldValue ? (0, _dayjs.default)(fieldValue) : null,
onChange: handleDateFieldChange(field),
name: field,
label: headerName,
slotProps: {
textField: {
error: !!fieldError,
helperText: fieldError ?? ' ',
fullWidth: true
}
}
})
});
}
if (type === 'singleSelect') {
const {
getOptionValue,
getOptionLabel,
valueOptions
} = formField;
if (valueOptions && Array.isArray(valueOptions)) {
const labelId = `${field}-label`;
fieldElement = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_FormControl.default, {
error: !!fieldError,
fullWidth: true,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_InputLabel.default, {
id: labelId,
children: headerName
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Select.default, {
value: fieldValue ?? '',
onChange: handleSelectFieldChange,
labelId: labelId,
name: field,
label: headerName,
defaultValue: "",
fullWidth: true,
children: valueOptions.map(option => {
let optionValue = option;
let optionLabel = option;
if (typeof option !== 'string' && typeof option !== 'number') {
optionValue = getOptionValue ? getOptionValue(option) : option.value;
optionLabel = getOptionLabel ? getOptionLabel(option) : option.label;
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MenuItem.default, {
value: optionValue,
children: optionLabel
}, optionValue);
})
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormHelperText.default, {
children: fieldError ?? ' '
})]
});
}
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Grid.default, {
size: {
xs: 12,
sm: 6
},
sx: {
display: 'flex'
},
children: fieldElement
}, field);
}, [formErrors, formValues, handleCheckboxFieldChange, handleDateFieldChange, handleNumberFieldChange, handleSelectFieldChange, handleTextFieldChange, slotProps?.textField, slots]);
const handleReset = React.useCallback(async () => {
if (onReset) {
await onReset(formValues);
}
}, [formValues, onReset]);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
component: "form",
action: submitAction,
noValidate: true,
autoComplete: "off",
onReset: handleReset,
sx: {
width: '100%'
},
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_FormGroup.default, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Grid.default, {
container: true,
spacing: 2,
sx: {
mb: 2,
width: '100%'
},
children: fields.filter(({
field
}) => field !== 'id').map(renderField)
})
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
sx: {
display: 'flex',
justifyContent: 'flex-end'
},
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
type: "submit",
variant: "contained",
size: "large",
loading: isSubmitting,
children: submitButtonLabel
})
})]
});
}
process.env.NODE_ENV !== "production" ? CrudForm.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* Server-side [data source](https://mui.com/toolpad/core/react-crud/#data-sources).
*/
dataSource: _propTypes.default.object,
/**
* Form state object, including field values and errors.
*/
formState: _propTypes.default.shape({
errors: _propTypes.default.object.isRequired,
values: _propTypes.default.object.isRequired
}).isRequired,
/**
* Callback fired when a form field is changed.
*/
onFieldChange: _propTypes.default.func.isRequired,
/**
* Callback fired when the form is reset.
*/
onReset: _propTypes.default.func,
/**
* Callback fired when the form is submitted.
*/
onSubmit: _propTypes.default.func.isRequired,
/**
* The props used for each slot inside.
* @default {}
*/
slotProps: _propTypes.default.shape({
textField: _propTypes.default.object
}),
/**
* The components used for each slot inside.
* @default {}
*/
slots: _propTypes.default.shape({
textField: _propTypes.default.elementType
}),
/**
* Text for form submit button.
*/
submitButtonLabel: _propTypes.default.string.isRequired
} : void 0;
;