UNPKG

@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
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;