parent
59c8b6b95e
commit
ccd127de44
@ -0,0 +1,173 @@
|
|||||||
|
import { ChangeEvent, useState } from 'react';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Noop } from '../../types/Util';
|
||||||
|
import { useHTMLDirection } from '../../util/i18n';
|
||||||
|
import { SessionIconButton } from '../icon';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
label?: string;
|
||||||
|
error?: string;
|
||||||
|
type?: string;
|
||||||
|
value?: string;
|
||||||
|
placeholder: string;
|
||||||
|
maxLength?: number;
|
||||||
|
enableShowHide?: boolean;
|
||||||
|
onValueChanged?: (value: string) => any;
|
||||||
|
onEnterPressed?: any;
|
||||||
|
autoFocus?: boolean;
|
||||||
|
ref?: any;
|
||||||
|
inputDataTestId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledInputWithLabelContainer = styled.label`
|
||||||
|
height: 46.5px;
|
||||||
|
width: 280px;
|
||||||
|
font-family: var(--font-default);
|
||||||
|
color: var(--text-primary-color);
|
||||||
|
|
||||||
|
padding: 2px 0 2px 0;
|
||||||
|
transition: opacity var(--default-duration);
|
||||||
|
opacity: 1;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
label {
|
||||||
|
line-height: 14px;
|
||||||
|
opacity: 0;
|
||||||
|
color: var(--text-primary-color);
|
||||||
|
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 11px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.filled {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
color: var(--danger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
height: 14px;
|
||||||
|
width: 280px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--input-text-color);
|
||||||
|
|
||||||
|
font-family: var(--font-default);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 14px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--input-text-placeholder-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const LabelItem = (props: { inputValue: string; label?: string }) => {
|
||||||
|
return (
|
||||||
|
<StyledInputWithLabelContainer
|
||||||
|
htmlFor="session-input-floating-label"
|
||||||
|
className={classNames(props.inputValue !== '' ? 'filled' : '')}
|
||||||
|
>
|
||||||
|
{props.label}
|
||||||
|
</StyledInputWithLabelContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ErrorItem = (props: { error: string | undefined }) => {
|
||||||
|
return (
|
||||||
|
<StyledInputWithLabelContainer
|
||||||
|
htmlFor="session-input-floating-label"
|
||||||
|
className={classNames('filled error')}
|
||||||
|
>
|
||||||
|
{props.error}
|
||||||
|
</StyledInputWithLabelContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ShowHideButton = (props: { toggleForceShow: Noop }) => {
|
||||||
|
const htmlDirection = useHTMLDirection();
|
||||||
|
const position = htmlDirection === 'ltr' ? { right: '0px' } : { left: '0px' };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SessionIconButton
|
||||||
|
iconType="eye"
|
||||||
|
iconSize="medium"
|
||||||
|
onClick={props.toggleForceShow}
|
||||||
|
style={{ position: 'absolute', top: '50%', transform: 'translateY(-50%)', ...position }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SessionInput2 = (props: Props) => {
|
||||||
|
const {
|
||||||
|
autoFocus,
|
||||||
|
placeholder,
|
||||||
|
type,
|
||||||
|
value,
|
||||||
|
maxLength,
|
||||||
|
enableShowHide,
|
||||||
|
error,
|
||||||
|
label,
|
||||||
|
onValueChanged,
|
||||||
|
inputDataTestId,
|
||||||
|
} = props;
|
||||||
|
const [inputValue, setInputValue] = useState('');
|
||||||
|
const [forceShow, setForceShow] = useState(false);
|
||||||
|
|
||||||
|
const correctType = forceShow ? 'text' : type;
|
||||||
|
|
||||||
|
const updateInputValue = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const val = e.target.value;
|
||||||
|
setInputValue(val);
|
||||||
|
if (onValueChanged) {
|
||||||
|
onValueChanged(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledInputWithLabelContainer>
|
||||||
|
{error ? (
|
||||||
|
<ErrorItem error={props.error} />
|
||||||
|
) : (
|
||||||
|
<LabelItem inputValue={inputValue} label={label} />
|
||||||
|
)}
|
||||||
|
<input
|
||||||
|
id="session-input-floating-label"
|
||||||
|
type={correctType}
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
maxLength={maxLength}
|
||||||
|
autoFocus={autoFocus}
|
||||||
|
data-testid={inputDataTestId}
|
||||||
|
onChange={updateInputValue}
|
||||||
|
style={{ paddingInlineEnd: enableShowHide ? '30px' : undefined }}
|
||||||
|
// just in case onChange isn't triggered
|
||||||
|
onBlur={updateInputValue}
|
||||||
|
onKeyDown={event => {
|
||||||
|
if (event.key === 'Enter' && props.onEnterPressed) {
|
||||||
|
props.onEnterPressed();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{enableShowHide && (
|
||||||
|
<ShowHideButton
|
||||||
|
toggleForceShow={() => {
|
||||||
|
setForceShow(!forceShow);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</StyledInputWithLabelContainer>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,3 @@
|
|||||||
|
import { SessionInput2 } from './SessionInput2';
|
||||||
|
|
||||||
|
export { SessionInput2 };
|
Loading…
Reference in New Issue