2022-07-26 10:58:28 +00:00
|
|
|
import React, { useCallback } from 'react';
|
2022-08-11 13:32:44 +00:00
|
|
|
import TextareaAutosize from 'react-textarea-autosize';
|
2022-09-13 07:36:00 +00:00
|
|
|
import { makeStyles } from 'tss-react/mui';
|
2022-07-26 10:58:28 +00:00
|
|
|
|
2022-07-27 08:40:34 +00:00
|
|
|
import { isMobileBrowser } from '../../../environment/utils';
|
|
|
|
import Icon from '../../../icons/components/Icon';
|
2022-09-06 17:32:20 +00:00
|
|
|
import { IconCloseCircle } from '../../../icons/svg';
|
2022-07-27 08:40:34 +00:00
|
|
|
import { withPixelLineHeight } from '../../../styles/functions.web';
|
2022-10-20 09:11:27 +00:00
|
|
|
import { IInputProps } from '../types';
|
2022-07-26 10:58:28 +00:00
|
|
|
|
2022-10-20 09:11:27 +00:00
|
|
|
interface IProps extends IInputProps {
|
2022-08-04 08:26:13 +00:00
|
|
|
accessibilityLabel?: string;
|
|
|
|
autoFocus?: boolean;
|
2022-07-26 10:58:28 +00:00
|
|
|
bottomLabel?: string;
|
|
|
|
className?: string;
|
2022-08-11 13:32:44 +00:00
|
|
|
iconClick?: () => void;
|
2022-08-01 07:04:36 +00:00
|
|
|
id?: string;
|
2022-08-04 08:26:13 +00:00
|
|
|
maxLength?: number;
|
2022-08-11 13:32:44 +00:00
|
|
|
maxRows?: number;
|
|
|
|
minRows?: number;
|
2022-08-01 07:04:36 +00:00
|
|
|
name?: string;
|
2022-08-04 08:26:13 +00:00
|
|
|
onKeyPress?: (e: React.KeyboardEvent) => void;
|
2022-10-27 08:36:50 +00:00
|
|
|
readOnly?: boolean;
|
2023-01-30 09:35:21 +00:00
|
|
|
required?: boolean;
|
2022-08-11 13:32:44 +00:00
|
|
|
textarea?: boolean;
|
2022-07-26 10:58:28 +00:00
|
|
|
type?: 'text' | 'email' | 'number' | 'password';
|
|
|
|
}
|
|
|
|
|
2022-11-15 07:50:22 +00:00
|
|
|
const useStyles = makeStyles()(theme => {
|
2022-07-26 10:58:28 +00:00
|
|
|
return {
|
|
|
|
inputContainer: {
|
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'column'
|
|
|
|
},
|
|
|
|
|
|
|
|
label: {
|
|
|
|
color: theme.palette.text01,
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
2022-09-13 07:36:00 +00:00
|
|
|
marginBottom: theme.spacing(2),
|
2022-07-26 10:58:28 +00:00
|
|
|
|
|
|
|
'&.is-mobile': {
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
fieldContainer: {
|
|
|
|
position: 'relative',
|
|
|
|
display: 'flex'
|
|
|
|
},
|
|
|
|
|
|
|
|
input: {
|
|
|
|
backgroundColor: theme.palette.ui03,
|
2022-10-26 06:09:58 +00:00
|
|
|
background: theme.palette.ui03,
|
2022-07-26 10:58:28 +00:00
|
|
|
color: theme.palette.text01,
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
|
|
|
padding: '10px 16px',
|
|
|
|
borderRadius: theme.shape.borderRadius,
|
|
|
|
border: 0,
|
|
|
|
height: '40px',
|
|
|
|
boxSizing: 'border-box',
|
|
|
|
width: '100%',
|
|
|
|
|
|
|
|
'&::placeholder': {
|
|
|
|
color: theme.palette.text02
|
|
|
|
},
|
|
|
|
|
|
|
|
'&:focus': {
|
|
|
|
outline: 0,
|
|
|
|
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
|
|
|
},
|
|
|
|
|
|
|
|
'&:disabled': {
|
|
|
|
color: theme.palette.text03
|
|
|
|
},
|
|
|
|
|
|
|
|
'&.is-mobile': {
|
|
|
|
height: '48px',
|
|
|
|
padding: '13px 16px',
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
|
|
|
},
|
|
|
|
|
2022-08-11 13:32:44 +00:00
|
|
|
'&.icon-input': {
|
|
|
|
paddingLeft: '46px'
|
|
|
|
},
|
|
|
|
|
2022-07-26 10:58:28 +00:00
|
|
|
'&.error': {
|
|
|
|
boxShadow: `0px 0px 0px 2px ${theme.palette.textError}`
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
icon: {
|
|
|
|
position: 'absolute',
|
2022-08-11 13:32:44 +00:00
|
|
|
top: '50%',
|
|
|
|
transform: 'translateY(-50%)',
|
2022-07-26 10:58:28 +00:00
|
|
|
left: '16px'
|
|
|
|
},
|
|
|
|
|
2022-08-11 13:32:44 +00:00
|
|
|
iconClickable: {
|
|
|
|
cursor: 'pointer'
|
2022-07-26 10:58:28 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
clearableInput: {
|
|
|
|
paddingRight: '46px'
|
|
|
|
},
|
|
|
|
|
|
|
|
clearButton: {
|
|
|
|
position: 'absolute',
|
|
|
|
right: '16px',
|
|
|
|
top: '10px',
|
|
|
|
cursor: 'pointer',
|
|
|
|
backgroundColor: theme.palette.action03,
|
|
|
|
border: 0,
|
|
|
|
padding: 0
|
|
|
|
},
|
|
|
|
|
|
|
|
bottomLabel: {
|
2022-09-13 07:36:00 +00:00
|
|
|
marginTop: theme.spacing(2),
|
2022-07-26 10:58:28 +00:00
|
|
|
...withPixelLineHeight(theme.typography.labelRegular),
|
|
|
|
color: theme.palette.text02,
|
|
|
|
|
|
|
|
'&.is-mobile': {
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortRegular)
|
|
|
|
},
|
|
|
|
|
|
|
|
'&.error': {
|
|
|
|
color: theme.palette.textError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2022-10-20 09:11:27 +00:00
|
|
|
const Input = React.forwardRef<any, IProps>(({
|
2022-08-04 08:26:13 +00:00
|
|
|
accessibilityLabel,
|
|
|
|
autoFocus,
|
2022-07-26 10:58:28 +00:00
|
|
|
bottomLabel,
|
|
|
|
className,
|
|
|
|
clearable = false,
|
|
|
|
disabled,
|
|
|
|
error,
|
|
|
|
icon,
|
2022-08-11 13:32:44 +00:00
|
|
|
iconClick,
|
2022-08-01 07:04:36 +00:00
|
|
|
id,
|
2022-07-26 10:58:28 +00:00
|
|
|
label,
|
2022-08-04 08:26:13 +00:00
|
|
|
maxLength,
|
2022-08-11 13:32:44 +00:00
|
|
|
maxRows,
|
|
|
|
minRows,
|
2022-08-01 07:04:36 +00:00
|
|
|
name,
|
2022-07-26 10:58:28 +00:00
|
|
|
onChange,
|
2022-08-04 08:26:13 +00:00
|
|
|
onKeyPress,
|
2022-07-26 10:58:28 +00:00
|
|
|
placeholder,
|
2022-10-27 08:36:50 +00:00
|
|
|
readOnly = false,
|
2023-01-30 09:35:21 +00:00
|
|
|
required,
|
2022-08-11 13:32:44 +00:00
|
|
|
textarea = false,
|
2022-07-26 10:58:28 +00:00
|
|
|
type = 'text',
|
|
|
|
value
|
2022-10-20 09:11:27 +00:00
|
|
|
}: IProps, ref) => {
|
2022-09-13 07:36:00 +00:00
|
|
|
const { classes: styles, cx } = useStyles();
|
2022-07-26 10:58:28 +00:00
|
|
|
const isMobile = isMobileBrowser();
|
|
|
|
|
2022-09-08 09:52:36 +00:00
|
|
|
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>
|
2022-10-27 08:36:50 +00:00
|
|
|
onChange?.(e.target.value), []);
|
2022-07-26 10:58:28 +00:00
|
|
|
|
2022-10-27 08:36:50 +00:00
|
|
|
const clearInput = useCallback(() => onChange?.(''), []);
|
2022-07-26 10:58:28 +00:00
|
|
|
|
2022-09-13 07:36:00 +00:00
|
|
|
return (
|
|
|
|
<div className = { cx(styles.inputContainer, className) }>
|
|
|
|
{label && <span className = { cx(styles.label, isMobile && 'is-mobile') }>{label}</span>}
|
|
|
|
<div className = { styles.fieldContainer }>
|
|
|
|
{icon && <Icon
|
|
|
|
{ ...(iconClick ? { tabIndex: 0 } : {}) }
|
|
|
|
className = { cx(styles.icon, iconClick && styles.iconClickable) }
|
|
|
|
onClick = { iconClick }
|
2022-07-26 10:58:28 +00:00
|
|
|
size = { 20 }
|
2022-09-13 07:36:00 +00:00
|
|
|
src = { icon } />}
|
|
|
|
{textarea ? (
|
|
|
|
<TextareaAutosize
|
|
|
|
aria-label = { accessibilityLabel }
|
|
|
|
autoFocus = { autoFocus }
|
|
|
|
className = { cx(styles.input, isMobile && 'is-mobile',
|
|
|
|
error && 'error', clearable && styles.clearableInput, icon && 'icon-input') }
|
|
|
|
disabled = { disabled }
|
|
|
|
{ ...(id ? { id } : {}) }
|
2023-01-30 09:35:21 +00:00
|
|
|
maxLength = { maxLength }
|
2022-09-13 07:36:00 +00:00
|
|
|
maxRows = { maxRows }
|
|
|
|
minRows = { minRows }
|
|
|
|
name = { name }
|
|
|
|
onChange = { handleChange }
|
|
|
|
onKeyPress = { onKeyPress }
|
|
|
|
placeholder = { placeholder }
|
2022-10-27 08:36:50 +00:00
|
|
|
readOnly = { readOnly }
|
2022-09-13 07:36:00 +00:00
|
|
|
ref = { ref }
|
2023-01-30 09:35:21 +00:00
|
|
|
required = { required }
|
2022-09-13 07:36:00 +00:00
|
|
|
value = { value } />
|
|
|
|
) : (
|
|
|
|
<input
|
|
|
|
aria-label = { accessibilityLabel }
|
|
|
|
autoFocus = { autoFocus }
|
|
|
|
className = { cx(styles.input, isMobile && 'is-mobile',
|
|
|
|
error && 'error', clearable && styles.clearableInput, icon && 'icon-input') }
|
|
|
|
disabled = { disabled }
|
|
|
|
{ ...(id ? { id } : {}) }
|
|
|
|
maxLength = { maxLength }
|
|
|
|
name = { name }
|
|
|
|
onChange = { handleChange }
|
|
|
|
onKeyPress = { onKeyPress }
|
|
|
|
placeholder = { placeholder }
|
2022-10-27 08:36:50 +00:00
|
|
|
readOnly = { readOnly }
|
2022-09-13 07:36:00 +00:00
|
|
|
ref = { ref }
|
2023-01-30 09:35:21 +00:00
|
|
|
required = { required }
|
2022-09-13 07:36:00 +00:00
|
|
|
type = { type }
|
|
|
|
value = { value } />
|
|
|
|
)}
|
|
|
|
{clearable && !disabled && value !== '' && <button className = { styles.clearButton }>
|
|
|
|
<Icon
|
|
|
|
onClick = { clearInput }
|
|
|
|
size = { 20 }
|
|
|
|
src = { IconCloseCircle } />
|
|
|
|
</button>}
|
|
|
|
</div>
|
|
|
|
{bottomLabel && (
|
|
|
|
<span className = { cx(styles.bottomLabel, isMobile && 'is-mobile', error && 'error') }>
|
|
|
|
{bottomLabel}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-07-26 10:58:28 +00:00
|
|
|
</div>
|
2022-09-13 07:36:00 +00:00
|
|
|
);
|
2022-08-11 13:32:44 +00:00
|
|
|
});
|
2022-07-26 10:58:28 +00:00
|
|
|
|
|
|
|
export default Input;
|