104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
|
'use client';
|
||
|
|
||
|
import React, { forwardRef, useState } from 'react';
|
||
|
import { bool, string } from 'prop-types';
|
||
|
import { type TextFieldInterface } from './text-field.types';
|
||
|
|
||
|
export const TextField = forwardRef<HTMLInputElement, TextFieldInterface>(
|
||
|
(
|
||
|
{
|
||
|
variant = 'filled',
|
||
|
withAfterIcon,
|
||
|
withBeforeIcon,
|
||
|
supportingText,
|
||
|
...props
|
||
|
},
|
||
|
ref,
|
||
|
) => {
|
||
|
const [raised, setRaised] = useState<boolean>(
|
||
|
props.placeholder ?? false,
|
||
|
);
|
||
|
|
||
|
const callback = (e: any): 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,
|
||
|
withBeforeIcon: bool,
|
||
|
withAfterIcon: bool,
|
||
|
className: string,
|
||
|
variant: string,
|
||
|
placeholder: string,
|
||
|
supportingText: string,
|
||
|
};
|