@nish1896/rhf-mui-components
Version:
A suite of 25+ production-ready react-hook-form components built with material-ui. Fully typed, tree-shakable, and optimized for enterprise-grade forms.
133 lines (132 loc) • 5.26 kB
JavaScript
"use client";
import { RHFMuiConfigContext } from "../../config/ConfigProvider.js";
import { resolveLabelAboveControl } from "../../utils/control.js";
import FormControl from "../../common/FormControl.js";
import FormHelperText from "../../common/FormHelperText.js";
import FormLabel from "../../common/FormLabel.js";
import { coerceValue, getOptionValue, isKeyValueOption } from "../../utils/object.js";
import { fieldNameToLabel } from "../../utils/text-transform.js";
import { useFieldIds } from "../../utils/useFieldIds.js";
import { createElement, useContext } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Controller } from "react-hook-form";
import FormControlLabel from "@mui/material/FormControlLabel";
import MuiCheckbox from "@mui/material/Checkbox";
//#region src/mui/checkbox-group/index.tsx
const RHFCheckboxGroup = ({ fieldName, control, registerOptions, options, labelKey, valueKey, renderOptionLabel, getOptionDisabled, customOnChange, onValueChange, disabled: muiDisabled, label, showLabelAboveFormField, formLabelProps, hideLabel, checkboxProps, formControlLabelProps, required, helperText, errorMessage, hideErrorMessage, formHelperTextProps, onBlur: muiOnBlur, customIds }) => {
const { defaultFormControlLabelSx, allLabelsAboveFields } = useContext(RHFMuiConfigContext);
const { fieldId, labelId, helperTextId, errorId } = useFieldIds(fieldName, customIds);
const defaultFieldLabel = fieldNameToLabel(fieldName);
const fieldLabel = label ?? defaultFieldLabel;
const accessibleFieldLabel = typeof fieldLabel === "string" ? fieldLabel : defaultFieldLabel;
const isLabelAboveControl = resolveLabelAboveControl(showLabelAboveFormField, allLabelsAboveFields);
const { sx, ...otherFormControlLabelProps } = formControlLabelProps ?? {};
const appliedFormControlLabelSx = {
...defaultFormControlLabelSx,
...sx
};
return /* @__PURE__ */ jsx(Controller, {
name: fieldName,
control,
rules: registerOptions,
render: ({ field, fieldState: { error: fieldStateError } }) => {
const { value, onChange: rhfOnChange, onBlur: rhfOnBlur, disabled: rhfDisabled } = field;
const rhfValue = value ?? [];
const isDisabled = muiDisabled || rhfDisabled;
const fieldErrorMessage = fieldStateError?.message?.toString() ?? errorMessage;
const isError = !!fieldErrorMessage;
const showHelperTextElement = !!(helperText || isError && !hideErrorMessage);
const handleChange = (event, checked, optionValue) => {
const normalizedValue = coerceValue(event.target.value, optionValue);
if (customOnChange) {
customOnChange({
rhfOnChange,
toggledValue: normalizedValue,
checked,
currentValue: rhfValue,
event
});
return;
}
const newValue = checked ? rhfValue.includes(normalizedValue) ? rhfValue : [...rhfValue, normalizedValue] : rhfValue.filter((v) => v !== normalizedValue);
rhfOnChange(newValue);
onValueChange?.({
toggledValue: normalizedValue,
newValue,
event,
checked
});
};
return /* @__PURE__ */ jsxs(FormControl, {
component: "fieldset",
"aria-labelledby": !hideLabel ? labelId : void 0,
"aria-label": hideLabel ? accessibleFieldLabel : void 0,
error: isError,
disabled: isDisabled,
/**
* Trigger blur event only if focus is moving OUTSIDE
* the checkbox group, instead of calling onBlur for
* every checkbox.
*/
onBlur: (e) => {
const currentTarget = e.currentTarget;
const relatedTarget = e.relatedTarget;
if (!currentTarget.contains(relatedTarget)) {
rhfOnBlur();
muiOnBlur?.(e);
}
},
children: [
!hideLabel && /* @__PURE__ */ jsx(FormLabel, {
label: fieldLabel,
isVisible: isLabelAboveControl,
required,
error: isError,
disabled: isDisabled,
formLabelProps: {
...formLabelProps,
id: labelId,
component: "legend"
}
}),
options.map((option, idx) => {
const isObject = isKeyValueOption(option, labelKey, valueKey);
const opnValue = getOptionValue(option, valueKey);
const opnLabel = isObject ? String(option[labelKey]) : String(option);
const checked = rhfValue.includes(opnValue);
const isOptionDisabled = isDisabled || getOptionDisabled?.(option) || false;
return /* @__PURE__ */ createElement(FormControlLabel, {
...otherFormControlLabelProps,
key: `${opnValue}-${idx}`,
control: /* @__PURE__ */ jsx(MuiCheckbox, {
...checkboxProps,
id: `${fieldId}-${opnValue}`,
name: fieldName,
value: opnValue,
checked,
disabled: isOptionDisabled,
onChange: (e) => handleChange(e, e.target.checked, opnValue)
}),
label: renderOptionLabel?.(option) ?? opnLabel,
sx: appliedFormControlLabelSx,
disabled: isOptionDisabled
});
}),
/* @__PURE__ */ jsx(FormHelperText, {
error: isError,
errorMessage: fieldErrorMessage,
hideErrorMessage,
helperText,
showHelperTextElement,
formHelperTextProps: {
...formHelperTextProps,
id: isError ? errorId : helperTextId
}
})
]
});
}
});
};
//#endregion
export { RHFCheckboxGroup as default };