2024-02-13 17:10:48 -05:00
|
|
|
import classNames from 'classnames';
|
2024-06-02 20:58:11 +03:00
|
|
|
import React, {
|
|
|
|
type DetailedHTMLProps,
|
|
|
|
type InputHTMLAttributes,
|
|
|
|
useState,
|
|
|
|
useCallback,
|
|
|
|
forwardRef
|
|
|
|
} from 'react';
|
2024-02-13 01:09:08 -05:00
|
|
|
|
|
|
|
import './emby-input.scss';
|
|
|
|
|
2024-06-02 20:58:11 +03:00
|
|
|
interface InputProps
|
|
|
|
extends DetailedHTMLProps<
|
|
|
|
InputHTMLAttributes<HTMLInputElement>,
|
|
|
|
HTMLInputElement
|
|
|
|
> {
|
|
|
|
id: string;
|
|
|
|
label?: string;
|
2024-02-13 01:09:08 -05:00
|
|
|
}
|
|
|
|
|
2024-06-01 18:42:01 -04:00
|
|
|
const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
|
({ id, label, className, onBlur, onFocus, ...props }, ref) => {
|
|
|
|
const [isFocused, setIsFocused] = useState(false);
|
|
|
|
|
|
|
|
const onBlurInternal = useCallback(
|
2024-06-02 20:58:11 +03:00
|
|
|
(e: React.FocusEvent<HTMLInputElement, Element>) => {
|
2024-06-01 18:42:01 -04:00
|
|
|
setIsFocused(false);
|
|
|
|
onBlur?.(e);
|
|
|
|
},
|
|
|
|
[onBlur]
|
|
|
|
);
|
|
|
|
|
|
|
|
const onFocusInternal = useCallback(
|
2024-06-02 20:58:11 +03:00
|
|
|
(e: React.FocusEvent<HTMLInputElement, Element>) => {
|
2024-06-01 18:42:01 -04:00
|
|
|
setIsFocused(true);
|
|
|
|
onFocus?.(e);
|
|
|
|
},
|
|
|
|
[onFocus]
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<label
|
|
|
|
htmlFor={id}
|
|
|
|
className={classNames('inputLabel', {
|
2024-02-13 01:09:08 -05:00
|
|
|
inputLabelUnfocused: !isFocused,
|
|
|
|
inputLabelFocused: isFocused
|
2024-06-01 18:42:01 -04:00
|
|
|
})}
|
|
|
|
>
|
|
|
|
{label}
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
ref={ref}
|
|
|
|
id={id}
|
|
|
|
className={classNames('emby-input', className)}
|
|
|
|
onBlur={onBlurInternal}
|
|
|
|
onFocus={onFocusInternal}
|
|
|
|
{...props}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
Input.displayName = 'Input';
|
2024-02-13 01:09:08 -05:00
|
|
|
|
|
|
|
export default Input;
|