2021-01-19 15:55:44 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import classnames from 'classnames';
|
2023-03-02 14:26:00 +00:00
|
|
|
import { forwardRef, useState } from '@wordpress/element';
|
2023-04-19 16:53:26 +00:00
|
|
|
import { decodeEntities } from '@wordpress/html-entities';
|
2023-03-02 14:26:00 +00:00
|
|
|
import type { InputHTMLAttributes } from 'react';
|
2021-01-19 15:55:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2021-07-02 09:24:07 +00:00
|
|
|
import Label from '../label';
|
2021-01-19 15:55:44 +00:00
|
|
|
import './style.scss';
|
|
|
|
|
2021-05-19 09:55:15 +00:00
|
|
|
interface TextInputProps
|
|
|
|
extends Omit<
|
|
|
|
InputHTMLAttributes< HTMLInputElement >,
|
|
|
|
'onChange' | 'onBlur'
|
|
|
|
> {
|
|
|
|
id: string;
|
|
|
|
ariaLabel?: string;
|
2022-11-10 10:05:41 +00:00
|
|
|
label?: string | undefined;
|
|
|
|
ariaDescribedBy?: string | undefined;
|
2021-05-19 09:55:15 +00:00
|
|
|
screenReaderLabel?: string;
|
|
|
|
help?: string;
|
|
|
|
feedback?: boolean | JSX.Element;
|
2022-11-10 10:05:41 +00:00
|
|
|
autoComplete?: string | undefined;
|
2021-05-19 09:55:15 +00:00
|
|
|
onChange: ( newValue: string ) => void;
|
|
|
|
onBlur?: ( newValue: string ) => void;
|
|
|
|
}
|
|
|
|
|
2021-06-07 09:16:47 +00:00
|
|
|
const TextInput = forwardRef< HTMLInputElement, TextInputProps >(
|
2021-01-19 15:55:44 +00:00
|
|
|
(
|
|
|
|
{
|
|
|
|
className,
|
|
|
|
id,
|
|
|
|
type = 'text',
|
|
|
|
ariaLabel,
|
|
|
|
ariaDescribedBy,
|
|
|
|
label,
|
|
|
|
screenReaderLabel,
|
|
|
|
disabled,
|
|
|
|
help,
|
|
|
|
autoCapitalize = 'off',
|
|
|
|
autoComplete = 'off',
|
|
|
|
value = '',
|
|
|
|
onChange,
|
|
|
|
required = false,
|
2021-05-19 09:55:15 +00:00
|
|
|
onBlur = () => {
|
|
|
|
/* Do nothing */
|
|
|
|
},
|
2021-01-19 15:55:44 +00:00
|
|
|
feedback,
|
2021-06-07 09:16:47 +00:00
|
|
|
...rest
|
2021-01-19 15:55:44 +00:00
|
|
|
},
|
|
|
|
ref
|
|
|
|
) => {
|
|
|
|
const [ isActive, setIsActive ] = useState( false );
|
2021-05-20 16:56:56 +00:00
|
|
|
|
2021-01-19 15:55:44 +00:00
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={ classnames(
|
|
|
|
'wc-block-components-text-input',
|
|
|
|
className,
|
|
|
|
{
|
2021-05-20 16:56:56 +00:00
|
|
|
'is-active': isActive || value,
|
2021-01-19 15:55:44 +00:00
|
|
|
}
|
|
|
|
) }
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type={ type }
|
|
|
|
id={ id }
|
2023-04-19 16:53:26 +00:00
|
|
|
value={ decodeEntities( value ) }
|
2021-01-19 15:55:44 +00:00
|
|
|
ref={ ref }
|
|
|
|
autoCapitalize={ autoCapitalize }
|
|
|
|
autoComplete={ autoComplete }
|
|
|
|
onChange={ ( event ) => {
|
|
|
|
onChange( event.target.value );
|
|
|
|
} }
|
|
|
|
onFocus={ () => setIsActive( true ) }
|
2021-05-19 09:55:15 +00:00
|
|
|
onBlur={ ( event ) => {
|
|
|
|
onBlur( event.target.value );
|
2021-01-19 15:55:44 +00:00
|
|
|
setIsActive( false );
|
|
|
|
} }
|
|
|
|
aria-label={ ariaLabel || label }
|
|
|
|
disabled={ disabled }
|
|
|
|
aria-describedby={
|
|
|
|
!! help && ! ariaDescribedBy
|
|
|
|
? id + '__help'
|
|
|
|
: ariaDescribedBy
|
|
|
|
}
|
|
|
|
required={ required }
|
2021-06-07 09:16:47 +00:00
|
|
|
{ ...rest }
|
2021-01-19 15:55:44 +00:00
|
|
|
/>
|
|
|
|
<Label
|
|
|
|
label={ label }
|
|
|
|
screenReaderLabel={ screenReaderLabel || label }
|
|
|
|
wrapperElement="label"
|
|
|
|
wrapperProps={ {
|
|
|
|
htmlFor: id,
|
|
|
|
} }
|
|
|
|
htmlFor={ id }
|
|
|
|
/>
|
|
|
|
{ !! help && (
|
|
|
|
<p
|
|
|
|
id={ id + '__help' }
|
|
|
|
className="wc-block-components-text-input__help"
|
|
|
|
>
|
|
|
|
{ help }
|
|
|
|
</p>
|
|
|
|
) }
|
|
|
|
{ feedback }
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
export default TextInput;
|