@nish1896/rhf-mui-components
Version:
A suite of 20+ production-ready react-hook-form components built with material-ui. Fully typed, tree-shakable, and optimized for enterprise-grade forms.
108 lines (107 loc) • 4.59 kB
JavaScript
"use client";
import { RHFMuiConfigContext } from "../../config/ConfigProvider.js";
import { keepLabelAboveFormField } from "../../utils/control.js";
import { validateFileList } from "../../utils/file.js";
import { fieldNameToLabel } from "../../utils/text-transform.js";
import { useFieldIds } from "../../utils/useFieldIds.js";
import FormControl from "../../common/FormControl.js";
import FormHelperText from "../../common/FormHelperText.js";
import FormLabel from "../../common/FormLabel.js";
import FileItem from "./components/FileItem.js";
import HiddenInput from "./components/HiddenInput.js";
import UploadButton from "./components/UploadButton.js";
import { Fragment, useContext } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Controller } from "react-hook-form";
import Box from "@mui/material/Box";
//#region src/mui/file-uploader/index.tsx
const RHFFileUploader = ({ fieldName, control, registerOptions, accept, multiple, maxFiles, maxSize, hideFileList = false, showFileSize = false, renderUploadButton, renderFileItem, onValueChange, disabled: muiDisabled, onUploadError, label, showLabelAboveFormField, formLabelProps, required, helperText, errorMessage, hideErrorMessage, formHelperTextProps, fullWidth = false }) => {
const { fieldId, labelId, helperTextId, errorId } = useFieldIds(fieldName);
const { allLabelsAboveFields } = useContext(RHFMuiConfigContext);
const fieldLabel = label ?? fieldNameToLabel(fieldName);
const isLabelAboveFormField = keepLabelAboveFormField(showLabelAboveFormField, allLabelsAboveFields);
const isError = !!errorMessage;
const showHelperTextElement = !!helperText || isError && !hideErrorMessage;
return /* @__PURE__ */ jsxs(FormControl, {
fullWidth,
error: isError,
children: [/* @__PURE__ */ jsx(FormLabel, {
label: fieldLabel,
isVisible: isLabelAboveFormField,
required,
error: isError,
formLabelProps: {
id: labelId,
htmlFor: fieldId,
...formLabelProps
}
}), /* @__PURE__ */ jsx(Controller, {
name: fieldName,
control,
rules: registerOptions,
render: ({ field: { name: rhfFieldName, value: rhfValue, onChange: rhfOnChange, onBlur: rhfOnBlur, ref: rhfRef } }) => {
const handleFileChange = (event) => {
const fileList = event.target.files;
event.target.value = "";
if (!fileList || fileList.length === 0) {
rhfOnChange(null);
onValueChange?.(null, event);
return;
}
const { acceptedFiles, rejectedFiles, errors } = validateFileList(fileList, accept, maxSize, maxFiles);
if (errors && errors.length > 0 && rejectedFiles && rejectedFiles.length > 0) onUploadError?.(errors, rejectedFiles);
const selectedFiles = multiple ? acceptedFiles.length > 0 ? acceptedFiles : null : acceptedFiles[0] ?? null;
rhfOnChange(selectedFiles);
onValueChange?.(selectedFiles, event);
};
const removeFile = (index) => {
if (multiple && Array.isArray(rhfValue)) {
const newFiles = rhfValue.filter((_, i) => i !== index);
rhfOnChange(newFiles.length > 0 ? newFiles : null);
} else rhfOnChange(null);
};
const InputComponent = /* @__PURE__ */ jsx(HiddenInput, {
id: fieldId,
name: rhfFieldName,
type: "file",
ref: rhfRef,
accept,
multiple,
onChange: handleFileChange,
onBlur: rhfOnBlur,
disabled: muiDisabled,
"aria-labelledby": isLabelAboveFormField ? labelId : void 0,
"aria-describedby": showHelperTextElement ? isError ? errorId : helperTextId : void 0,
"aria-invalid": isError
});
return /* @__PURE__ */ jsxs(Fragment, { children: [
renderUploadButton ? renderUploadButton(InputComponent) : /* @__PURE__ */ jsx(UploadButton, {
label: fieldLabel,
fieldName: `btn_${fieldId}`,
disabled: muiDisabled,
children: InputComponent
}),
/* @__PURE__ */ jsx(FormHelperText, {
error: isError,
errorMessage,
hideErrorMessage,
helperText,
showHelperTextElement,
formHelperTextProps: {
id: isError ? errorId : helperTextId,
...formHelperTextProps
}
}),
!hideFileList && rhfValue && /* @__PURE__ */ jsx(Box, { children: (Array.isArray(rhfValue) ? rhfValue : [rhfValue]).map((file, index) => /* @__PURE__ */ jsx(Fragment, { children: renderFileItem ? renderFileItem(file, index) : /* @__PURE__ */ jsx(FileItem, {
index,
file,
showFileSize,
removeFile
}) }, `${file.name}-${file.lastModified}-${index}`)) })
] });
}
})]
});
};
//#endregion
export { RHFFileUploader as default };