mui-dynamic-field
Version:
A dynamic and customizable input field component for React, built with Material UI & TypeScript.
183 lines (180 loc) • 4.89 kB
JavaScript
import { Box, Autocomplete, TextField, Typography } from '@mui/material';
import { useState } from 'react';
import { REGEX } from '../constants.js';
import { jsxs, jsx } from 'react/jsx-runtime';
const PhoneNumberInput = props => {
const {
color,
name,
error,
errorText,
label,
value,
handleChange,
disabled,
size,
countryCode,
countryCodeField,
countryCodes,
sx,
slotProps,
countryCodeFieldProps = {},
...restProps
} = props;
const {
sx: countryCodeFieldSx,
autoFocus,
...countryCodeFieldRestProps
} = countryCodeFieldProps;
const selectedOption = countryCodes?.find(c => c.value === countryCode);
const [inputValue, setInputValue] = useState("");
// useEffect(() => {
// if (!inputValue && selectedOption) {
// setInputValue(""); // keep input blank when not typing
// }
// }, [selectedOption]);
const showFlag = !inputValue && selectedOption?.shortCode;
return /*#__PURE__*/jsxs(Box, {
sx: {
display: "flex",
alignItems: "flex-start"
},
children: [!!countryCodes?.length && /*#__PURE__*/jsx(Autocomplete
// TODO: fix the rest props spread issue
, {
...countryCodeFieldRestProps,
id: "country-code-autocomplete",
options: countryCodes,
value: selectedOption,
inputValue: inputValue,
onInputChange: (_, newInputValue) => {
setInputValue(newInputValue);
},
getOptionLabel: () => "" // Always return empty label
,
filterOptions: (options, {
inputValue
}) => options.filter(opt => opt.label?.toLowerCase().includes(inputValue.toLowerCase())),
isOptionEqualToValue: (option, value) => {
const _option = option;
const _value = value;
return `${_option.label}${_option.value}` === `${_value.label}${_value.value}`;
},
onChange: (_, newValue) => {
if (!countryCodeField) return;
handleChange({
_key: countryCodeField,
value: newValue?.value
});
setInputValue("");
},
disableClearable: true,
disabled: disabled,
size: size,
slotProps: {
popper: {
sx: {
width: "fit-content !important",
maxWidth: 300
}
}
},
renderInput: params => /*#__PURE__*/jsxs(Box, {
sx: {
position: "relative",
width: 70
},
children: [showFlag && /*#__PURE__*/jsx(Box, {
component: "img",
src: `https://flagsapi.com/${selectedOption.shortCode}/flat/32.png`,
alt: "flag",
sx: {
position: "absolute",
left: 10,
top: "50%",
transform: "translateY(-50%)",
width: 24,
height: 24,
zIndex: 1,
pointerEvents: "none"
}
}), /*#__PURE__*/jsx(TextField, {
...params,
variant: "outlined",
sx: {
"& input": {
paddingLeft: showFlag ? "40px" : "12px"
}
},
autoFocus: autoFocus
})]
}),
renderOption: (props, option) => /*#__PURE__*/jsxs("li", {
...props,
children: [/*#__PURE__*/jsx("img", {
src: `https://flagsapi.com/${option.shortCode}/flat/32.png`,
style: {
width: 24,
height: 24,
marginRight: 8,
borderRadius: 4
},
alt: "flag"
}), option.label]
}),
sx: {
...countryCodeFieldSx,
"& .MuiAutocomplete-input": {
paddingLeft: "8px !important"
}
}
}), /*#__PURE__*/jsx(TextField, {
type: "tel",
fullWidth: true,
color: color,
error: error,
helperText: errorText,
label: label,
name: name,
disabled: disabled,
variant: "outlined",
value: value ?? "",
onChange: e => {
if (e.target.value.match(REGEX.NUMBERS.pattern) || !name) {
return;
}
handleChange({
_key: name,
value: e.target.value
});
},
size: size,
onWheel: e => e.target.blur(),
slotProps: {
...(slotProps || {}),
input: {
...(slotProps?.input || {}),
startAdornment: /*#__PURE__*/jsx(Typography, {
sx: {
color: "black !important",
whiteSpace: "nowrap"
},
children: selectedOption?.value
})
}
},
sx: {
"& .MuiOutlinedInput-root": {
paddingLeft: "7px !important"
},
"& input": {
paddingLeft: "4px !important"
},
...sx
},
...restProps
})]
});
};
export { PhoneNumberInput as default };
//# sourceMappingURL=PhoneNumberInput.js.map