material-you-react/src/primitive-components/input-components/text-field/text-field.tsx

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']),
};