@nish1896/rhf-mui-components
Version:
A suite of 20+ reusable Material UI components for React Hook Form to minimize your time and effort in creating and styling forms
68 lines (67 loc) • 5.81 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useContext, useMemo } from 'react';
import { Controller } from 'react-hook-form';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Chip from '@mui/material/Chip';
import { RHFMuiConfigContext } from '../../config/ConfigProvider';
import { FormControl, FormLabel, FormLabelText, FormHelperText } from '../../mui/common';
import { fieldNameToLabel, isAboveMuiV5, keepLabelAboveFormField } from '../../utils';
import { countryList } from './countries';
const RHFCountrySelect = ({ fieldName, control, registerOptions, countries, preferredCountries, valueKey = 'iso', disabled, onValueChange, label, showLabelAboveFormField, formLabelProps, required, helperText, errorMessage, hideErrorMessage, formHelperTextProps, multiple, textFieldProps, displayFlagOnSelect, slotProps, ChipProps, ...otherAutoCompleteProps }) => {
const { allLabelsAboveFields } = useContext(RHFMuiConfigContext);
const isLabelAboveFormField = keepLabelAboveFormField(showLabelAboveFormField, allLabelsAboveFields);
const fieldLabel = label ?? fieldNameToLabel(fieldName);
const isError = Boolean(errorMessage);
const countryOptions = countries ?? countryList;
const countrySelectOptions = useMemo(() => {
let countriesToList = countryOptions;
let countriesToListAtTop = [];
if (preferredCountries?.length) {
countriesToListAtTop = countryOptions.filter(country => preferredCountries.includes(country.iso));
countriesToListAtTop.sort((a, b) => preferredCountries.indexOf(a.iso)
- preferredCountries.indexOf(b.iso));
countriesToList = countryOptions.filter(country => !preferredCountries.includes(country.iso));
}
return [...countriesToListAtTop, ...countriesToList];
}, [countryOptions, preferredCountries]);
const CountryMenuItem = ({ countryInfo }) => (_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx(Typography, { variant: "h5", component: "span", children: countryInfo.emoji }), _jsx(Typography, { children: countryInfo.name })] }));
return (_jsxs(FormControl, { error: isError, children: [_jsx(FormLabel, { label: fieldLabel, isVisible: isLabelAboveFormField, required: required, error: isError, formLabelProps: formLabelProps }), _jsx(Controller, { name: fieldName, control: control, rules: registerOptions, render: ({ field: { value, onChange, ...otherFieldProps } }) => {
const selectedCountries = multiple
? (value ?? [])
.map(val => countrySelectOptions.find(country => country[valueKey] === val))
.filter((country) => Boolean(country))
: countrySelectOptions.find(country => country[valueKey] === value) || null;
return (_jsx(Autocomplete, { ...otherFieldProps, id: fieldName, options: countrySelectOptions, multiple: multiple, value: selectedCountries, onChange: (event, newValue, reason, details) => {
const newValueKey = Array.isArray(newValue)
? (newValue ?? []).map(item => item[valueKey])
: (newValue)?.[valueKey] ?? '';
onChange(newValueKey);
if (onValueChange) {
onValueChange(newValue, event, reason, details);
}
}, autoHighlight: true, blurOnSelect: !multiple, disableCloseOnSelect: multiple, fullWidth: true, disabled: disabled, limitTags: 2, getLimitTagsText: more => more === 1 ? '+1 Country' : `+${more} Countries`, getOptionKey: option => option[valueKey], getOptionLabel: option => option.name, isOptionEqualToValue: (option, value) => option[valueKey] === value[valueKey], renderInput: params => {
const textFieldInputProps = {
...params.inputProps,
autoComplete: fieldName
};
return (_jsx(TextField, { ...textFieldProps, ...params, label: !isLabelAboveFormField ? (_jsx(FormLabelText, { label: fieldLabel, required: required })) : undefined, error: isError, ...(isAboveMuiV5
&& {
slotProps: {
htmlInput: textFieldInputProps,
}
}) }));
}, renderOption: ({ key, ...props }, option) => (_jsx(Box, { component: "li", sx: { display: 'flex', alignItems: 'center' }, ...props, children: _jsx(CountryMenuItem, { countryInfo: option }) }, key)), renderTags: (value, getTagProps) => value.map((option, index) => {
const { key, ...otherChipProps } = getTagProps({ index });
return (_jsx(Chip, { ...otherChipProps, label: displayFlagOnSelect
? _jsx(CountryMenuItem, { countryInfo: option })
: option.name, ...ChipProps }, key));
}), ...(isAboveMuiV5
? { slotProps }
: { ChipProps }), ...otherAutoCompleteProps }));
} }), _jsx(FormHelperText, { error: isError, errorMessage: errorMessage, hideErrorMessage: hideErrorMessage, helperText: helperText, formHelperTextProps: formHelperTextProps })] }));
};
export { countryList };
export default RHFCountrySelect;