100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
'use client';
|
|
|
|
import { bool, oneOf, string } from 'prop-types';
|
|
import { TextFieldInterface } from './text-field.types';
|
|
import React, { FocusEvent, forwardRef, useState } from 'react';
|
|
|
|
export const TextField = forwardRef<HTMLInputElement, TextFieldInterface>(
|
|
(
|
|
{
|
|
variant = 'filled',
|
|
withAfterIcon,
|
|
withBeforeIcon,
|
|
supportingText,
|
|
...props
|
|
},
|
|
ref,
|
|
) => {
|
|
const [raised, setRaised] = useState<boolean>(!!props.placeholder);
|
|
|
|
const callback = (e: FocusEvent<HTMLInputElement>): void => {
|
|
if (
|
|
e.type === 'blur' &&
|
|
e.target.value.length === 0 &&
|
|
!props.placeholder
|
|
) {
|
|
setRaised(false);
|
|
} else if (e.type === 'focus') {
|
|
setRaised(true);
|
|
}
|
|
};
|
|
|
|
const iconStyles =
|
|
withBeforeIcon && withAfterIcon
|
|
? 'with-before-icon with-after-icon'
|
|
: withBeforeIcon
|
|
? 'with-before-icon'
|
|
: withAfterIcon
|
|
? 'with-after-icon'
|
|
: '';
|
|
|
|
return (
|
|
<span>
|
|
<div className={`m3 m3-text-field ${variant}`.trimEnd()}>
|
|
{variant === 'outlined' && (
|
|
<fieldset>
|
|
<legend className={raised ? 'raised' : ''}>
|
|
<span>Label</span>
|
|
</legend>
|
|
</fieldset>
|
|
)}
|
|
{withBeforeIcon && (
|
|
<span className={'m3-icon icon-before'}>
|
|
{withBeforeIcon && 'search'}
|
|
</span>
|
|
)}
|
|
<input
|
|
ref={ref}
|
|
{...props}
|
|
className={`${props.className ?? ''} ${iconStyles}`.trim()}
|
|
onBlur={event => {
|
|
callback(event);
|
|
if (props.onBlur) {
|
|
props.onBlur(event);
|
|
}
|
|
}}
|
|
onFocus={event => {
|
|
callback(event);
|
|
if (props.onFocus) {
|
|
props.onFocus(event);
|
|
}
|
|
}}
|
|
/>
|
|
<label className={raised ? 'raised' : ''}>
|
|
{props.children ?? 'Label'}
|
|
</label>
|
|
<span className={'m3-text-field-state-layer'} />
|
|
{withAfterIcon && (
|
|
<span className={'m3-icon'}>
|
|
{withAfterIcon && 'cancel'}
|
|
</span>
|
|
)}
|
|
</div>
|
|
{supportingText !== '' && (
|
|
<span className={'m3-text-field-supporting-text'}>
|
|
{supportingText}
|
|
</span>
|
|
)}
|
|
</span>
|
|
);
|
|
},
|
|
);
|
|
|
|
TextField.propTypes = {
|
|
children: string,
|
|
withAfterIcon: bool,
|
|
withBeforeIcon: bool,
|
|
supportingText: string,
|
|
variant: oneOf(['filled', 'outlined']),
|
|
};
|