Created
March 4, 2020 14:43
-
-
Save gcmatheusj/c46a3e13de6d51db028f3e938fb53ded to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as React from 'react'; | |
| import MUIOutlinedInput from '@material-ui/core/OutlinedInput'; | |
| import FormControl from '@material-ui/core/FormControl'; | |
| import styled, { css } from 'styled-components'; | |
| import { connect, FormikContext, getIn } from 'formik'; | |
| import FormHelperText from '@material-ui/core/FormHelperText'; | |
| import MaskedInput from 'react-text-mask'; | |
| import InputAdornment from '@material-ui/core/InputAdornment'; | |
| import Visibility from '@material-ui/icons/Visibility'; | |
| import VisibilityOff from '@material-ui/icons/VisibilityOff'; | |
| import IconButton from '@material-ui/core/IconButton'; | |
| import CurrencyInput from 'react-currency-input'; | |
| import { isValuesFromFormikEquals } from './utils'; | |
| import { getMask, MASK_TYPES } from '../../utils/masks'; | |
| import Label from './Label'; | |
| import { TextFieldProps } from '@material-ui/core/TextField'; | |
| const OutlinedInput = styled(MUIOutlinedInput)` | |
| width: 100%; | |
| ${(props) => | |
| props.prefix !== undefined && | |
| css` | |
| .MuiOutlinedInput-root fieldset { | |
| margin-left: 10px; | |
| } | |
| .MuiInputBase-input { | |
| margin-left: 0; | |
| } | |
| align-self: flex-end; | |
| width: calc(100% - 30px); | |
| `} | |
| `; | |
| const InputWrapper = styled(FormControl)` | |
| display: flex; | |
| flex-direction: column; | |
| margin: 3px 0 !important; | |
| .MuiOutlinedInput-notchedOutline { | |
| border-radius: 4px; | |
| } | |
| .MuiCard-root { | |
| box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); | |
| border-radius: 10px; | |
| } | |
| color: #00467e; | |
| font-size: 14px; | |
| p.MuiFormHelperText-root { | |
| margin-top: 3px !important; | |
| } | |
| input { | |
| font-size: 14px; | |
| } | |
| `; | |
| const PrefixContainer = styled.div` | |
| display: flex; | |
| width: 100%; | |
| justify-content: space-between; | |
| align-items: center; | |
| `; | |
| interface FormikPartProps { | |
| formik: FormikContext<{}>; | |
| } | |
| interface Props { | |
| label: string; | |
| name: string; | |
| mask?: string; | |
| type?: string; | |
| required?: boolean; | |
| prefix?: string; | |
| min?: number | string; | |
| max?: number | string; | |
| disabled?: boolean; | |
| placeholder?: string; | |
| handleBlur?: () => void; | |
| } | |
| const Mask = ({ inputRef, mask, ...props }) => ( | |
| <MaskedInput | |
| {...props} | |
| ref={(ref) => { | |
| inputRef(ref ? ref.inputElement : null); | |
| }} | |
| mask={getMask(mask)} | |
| /> | |
| ); | |
| const MemoizedMask = React.memo(Mask); | |
| const CurrencyMask = ({ inputRef, ...props }) => { | |
| const ref = React.useRef(null); | |
| React.useEffect(() => { | |
| inputRef(ref.current.theInput); | |
| }, [inputRef]); | |
| return <CurrencyInput {...props} ref={ref} type="tel" />; | |
| }; | |
| const getCustomProps = ({ | |
| mask, | |
| type, | |
| name, | |
| setFieldValue, | |
| showPassword, | |
| setShowPassword, | |
| }) => { | |
| if (mask === MASK_TYPES.MONEY) { | |
| return { | |
| onChange: (_, maskedValue) => setFieldValue(name, maskedValue), | |
| inputComponent: CurrencyMask as React.FunctionComponent, | |
| inputProps: { | |
| prefix: 'R$ ', | |
| decimalSeparator: ',', | |
| thousandSeparator: '.', | |
| allowEmpty: true, | |
| }, | |
| }; | |
| } | |
| if (type === 'password') { | |
| const passwordProps = { | |
| type: showPassword ? 'text' : 'password', | |
| endAdornment: ( | |
| <InputAdornment position="end"> | |
| <IconButton onClick={() => setShowPassword(!showPassword)}> | |
| {showPassword ? <Visibility /> : <VisibilityOff />} | |
| </IconButton> | |
| </InputAdornment> | |
| ), | |
| }; | |
| if (showPassword) { | |
| return { | |
| ...passwordProps, | |
| type: 'text', | |
| }; | |
| } | |
| return passwordProps; | |
| } | |
| if (mask) { | |
| return { | |
| inputComponent: MemoizedMask, | |
| }; | |
| } | |
| return {}; | |
| }; | |
| const TextInput: React.FunctionComponent<Props & | |
| FormikPartProps & | |
| TextFieldProps> = ({ | |
| label, | |
| name, | |
| type, | |
| mask, | |
| required, | |
| formik, | |
| ...props | |
| }) => { | |
| const [showPassword, setShowPassword] = React.useState(false); | |
| const [hasFocused, setHasFocused] = React.useState(false); | |
| const { | |
| values, | |
| errors, | |
| handleChange, | |
| handleBlur, | |
| touched, | |
| setFieldValue, | |
| } = formik; | |
| const value = getIn(values, name); | |
| const error = getIn(errors, name); | |
| const hasTouched = getIn(touched, name) || hasFocused; | |
| const onChange = (e) => { | |
| if (type !== 'number') return handleChange(e); | |
| if (props.min !== undefined) { | |
| if (Number.parseInt(e.target.value) <= props.min) return setFieldValue(name, props.min) | |
| } | |
| return handleChange(e); | |
| }; | |
| const onBlur = (e) => { | |
| handleBlur(e); | |
| if (props.handleBlur) props.handleBlur(); | |
| }; | |
| return ( | |
| <InputWrapper disabled={props.disabled}> | |
| <Label htmlFor={name}> {`${label} ${required ? '*' : ''}`} </Label> | |
| <PrefixContainer> | |
| {props.prefix} | |
| <OutlinedInput | |
| id={name} | |
| margin="dense" | |
| name={name} | |
| labelWidth={0} | |
| onChange={onChange} | |
| onBlur={onBlur} | |
| onFocus={() => setHasFocused(true)} | |
| value={value} | |
| error={hasTouched && !!error} | |
| type={type} | |
| prefix={props.prefix} | |
| inputProps={{ | |
| mask, | |
| ...props, | |
| }} | |
| {...getCustomProps({ | |
| mask, | |
| type, | |
| name, | |
| showPassword, | |
| setShowPassword, | |
| ...formik, | |
| ...props, | |
| })} | |
| /> | |
| </PrefixContainer> | |
| <FormHelperText error={hasTouched && !!error}> | |
| {hasTouched && error} | |
| </FormHelperText> | |
| </InputWrapper> | |
| ); | |
| }; | |
| export default connect<Props, {}>( | |
| React.memo(TextInput, isValuesFromFormikEquals), | |
| ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment