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

111 lines (110 loc) 7.17 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * Code Reference - * https://react-international-phone.vercel.app/docs/Advanced%20Usage/useWithUiLibs */ import { useContext } from 'react'; import { Controller } from 'react-hook-form'; import TextField from '@mui/material/TextField'; import InputAdornment from '@mui/material/InputAdornment'; import Divider from '@mui/material/Divider'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import Typography from '@mui/material/Typography'; import { defaultCountries, FlagImage, parseCountry, usePhoneInput } from 'react-international-phone'; import { RHFMuiConfigContext } from '../../config/ConfigProvider'; import { FormControl, FormLabel, FormLabelText, FormHelperText } from '../../mui/common'; import { fieldNameToLabel, keepLabelAboveFormField, isAboveMuiV5 } from '../../utils'; import 'react-international-phone/style.css'; const RHFPhoneInput = ({ fieldName, control, registerOptions, required, value, onValueChange, label, showLabelAboveFormField, formLabelProps, helperText, errorMessage, hideErrorMessage, formHelperTextProps, disabled, phoneInputProps, slotProps, ...rest }) => { const { allLabelsAboveFields } = useContext(RHFMuiConfigContext); const isError = Boolean(errorMessage); const fieldLabel = label ?? fieldNameToLabel(fieldName); const isLabelAboveFormField = keepLabelAboveFormField(showLabelAboveFormField, allLabelsAboveFields); const { countries, hideDropdown, preferredCountries, forceDialCode, ...otherPhoneInputProps } = phoneInputProps ?? {}; const countryOptions = countries ?? defaultCountries; let countriesToList = countryOptions; let countriesToListAtTop = []; /** * Render preferred countries at the top of the list. * Preferred countries will maintain the order in which they were * specified in the props, while other countries will be sorted * alphabetically. */ if (preferredCountries?.length) { countriesToListAtTop = countryOptions.filter(country => preferredCountries.includes(parseCountry(country).iso2)); countriesToListAtTop.sort((a, b) => { return (preferredCountries.indexOf(parseCountry(a).iso2) - preferredCountries.indexOf(parseCountry(b).iso2)); }); countriesToList = countryOptions.filter(country => !preferredCountries.includes(parseCountry(country).iso2)); } const { inputValue, handlePhoneValueChange, inputRef, country, setCountry } = usePhoneInput({ ...otherPhoneInputProps, value, onChange: (phoneData) => { if (onValueChange) { onValueChange(phoneData); } }, countries: countryOptions, preferredCountries, forceDialCode: hideDropdown ?? forceDialCode }); 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, defaultValue: inputValue, render: ({ field }) => { const startAdornment = (_jsx(InputAdornment, { position: "start", style: { marginRight: '2px', marginLeft: '-8px' }, children: _jsxs(Select, { MenuProps: { style: { height: '300px', width: '360px', top: '10px', left: '-34px' }, transformOrigin: { vertical: 'top', horizontal: 'left' } }, sx: { width: 'max-content', fieldset: { display: 'none' }, '&.Mui-focused:has(div[aria-expanded="false"])': { fieldset: { display: 'block' } }, '.MuiSelect-select': { padding: '8px', paddingRight: '24px !important' }, svg: { right: 0 } }, value: country.iso2, disabled: disabled || hideDropdown, onChange: e => { setCountry(e.target.value); }, renderValue: value => (_jsx(FlagImage, { iso2: value, style: { display: 'flex' } })), children: [countriesToListAtTop.map(c => { const countryInfo = parseCountry(c); return (_jsxs(MenuItem, { value: countryInfo.iso2, children: [_jsx(FlagImage, { iso2: countryInfo.iso2, style: { marginRight: '8px' } }), _jsx(Typography, { marginRight: "8px", children: countryInfo.name }), _jsxs(Typography, { color: "gray", children: ["+", countryInfo.dialCode] })] }, countryInfo.iso2)); }), countriesToListAtTop.length > 0 && _jsx(Divider, {}), countriesToList.map(c => { const countryInfo = parseCountry(c); return (_jsxs(MenuItem, { value: countryInfo.iso2, children: [_jsx(FlagImage, { iso2: countryInfo.iso2, style: { marginRight: '8px' } }), _jsx(Typography, { marginRight: "8px", children: countryInfo.name }), _jsxs(Typography, { color: "gray", children: ["+", countryInfo.dialCode] })] }, countryInfo.iso2)); })] }) })); return (_jsx(TextField, { ...field, ...rest, value: inputValue, autoComplete: fieldName, type: "tel", onChange: e => { handlePhoneValueChange(e); field.onChange(e.target.value); }, inputRef: ref => { field.ref(ref); inputRef.current = ref; }, label: !isLabelAboveFormField ? _jsx(FormLabelText, { label: fieldLabel, required: required }) : undefined, error: isError, disabled: disabled, ...(isAboveMuiV5 ? { slotProps: { ...slotProps, input: { startAdornment } } } : { InputProps: { startAdornment } }) })); } }), _jsx(FormHelperText, { error: isError, errorMessage: errorMessage, hideErrorMessage: hideErrorMessage, helperText: helperText, formHelperTextProps: formHelperTextProps })] })); }; export default RHFPhoneInput;