import React, { FC, memo, useEffect, useRef, useState, } from 'react'; export const AlertType = { WARNING: 'warning', ERROR: 'error', } as const; export type AlertType = typeof AlertType[keyof typeof AlertType]; export type AlertInfo = { type?: AlertType message?: string } type ClosableTextInputProps = { isShown: boolean placeholder?: string inputValidator?(text: string): AlertInfo | Promise | null onPressEnter?(): void onClickOutside?(): void } const ClosableTextInput: FC = memo((props: ClosableTextInputProps) => { const inputRef = useRef(null); const [currentAlertInfo, setAlertInfo] = useState(null); const onChangeHandler = async(e) => { if (props.inputValidator == null) { return } const alertInfo = await props.inputValidator(e.target.value); setAlertInfo(alertInfo); }; const onPressEnter = () => { if (props.onPressEnter == null) { return; } props.onPressEnter(); }; const onKeyDownHandler = (e) => { switch (e.key) { case 'Enter': onPressEnter(); break; default: break; } }; /* * Hide when click outside the ref */ const onBlurHandler = () => { if (props.onClickOutside == null) { return; } props.onClickOutside(); }; // didMount useEffect(() => { // autoFocus if (inputRef?.current == null) { return; } inputRef.current.focus(); }); // TODO: improve style return (
{currentAlertInfo != null && (

{/* eslint-disable-next-line max-len */} {currentAlertInfo.type != null ? currentAlertInfo.type : AlertType.ERROR}: {currentAlertInfo.message != null ? currentAlertInfo.message : 'Invalid value' }

)}
); }); export default ClosableTextInput;