119 lines
3.0 KiB
TypeScript
119 lines
3.0 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { v4 } from 'uuid';
|
|
import Keyboard from '../keyboard/Keyboard';
|
|
|
|
export default function Input(props: {
|
|
type?: string;
|
|
topKeyboard?: boolean;
|
|
value: number | string;
|
|
min?: number;
|
|
max?: number;
|
|
step?: number;
|
|
placeholder?: string;
|
|
className?: string;
|
|
disabled?: boolean;
|
|
onChange?: (value: string) => void;
|
|
onBlur?: (value: string) => void;
|
|
}) {
|
|
const [guid] = useState(v4());
|
|
const ref = useRef<HTMLInputElement>(null);
|
|
const keyboardRef = useRef<HTMLDivElement>(null);
|
|
const blurRef = useRef<boolean>(false);
|
|
const [isFocused, setFocused] = useState(false);
|
|
const [showKeyboard, setShowKeyboard] = useState(false);
|
|
const unfocusTimerRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
|
const clearUnfocusTimer = useCallback(() => {
|
|
if (unfocusTimerRef.current !== null) {
|
|
clearTimeout(unfocusTimerRef.current);
|
|
unfocusTimerRef.current = null;
|
|
}
|
|
}, []);
|
|
|
|
const scheduleUnfocus = useCallback(() => {
|
|
clearUnfocusTimer();
|
|
|
|
unfocusTimerRef.current = setTimeout(() => {
|
|
blurRef.current = false;
|
|
ref.current?.blur();
|
|
}, 5e3);
|
|
}, [clearUnfocusTimer]);
|
|
|
|
useEffect(() => {
|
|
if (isFocused) {
|
|
scheduleUnfocus();
|
|
Coherent.trigger('FOCUS_INPUT_FIELD', guid, '', '', '', false);
|
|
} else {
|
|
clearUnfocusTimer();
|
|
Coherent.trigger('UNFOCUS_INPUT_FIELD', guid);
|
|
}
|
|
|
|
return () => {
|
|
clearUnfocusTimer();
|
|
};
|
|
}, [isFocused, guid, scheduleUnfocus, clearUnfocusTimer]);
|
|
|
|
return (
|
|
<>
|
|
<input
|
|
id={guid}
|
|
ref={ref}
|
|
type={props.type ? props.type : 'text'}
|
|
min={props.min}
|
|
max={props.max}
|
|
step={props.step}
|
|
placeholder={props.placeholder}
|
|
disabled={props.disabled}
|
|
onFocus={() => {
|
|
if (!isFocused) {
|
|
setFocused(true);
|
|
setShowKeyboard(true);
|
|
ref.current?.select();
|
|
}
|
|
}}
|
|
onBlur={(e) => {
|
|
if (blurRef.current && isFocused) {
|
|
ref.current?.focus();
|
|
} else {
|
|
props.onBlur?.(e.target.value);
|
|
setShowKeyboard(false);
|
|
setFocused(false);
|
|
ref.current?.blur();
|
|
}
|
|
blurRef.current = false;
|
|
}}
|
|
onChange={(e) => {
|
|
if (props.onChange) {
|
|
props.onChange(e.target.value);
|
|
}
|
|
if (isFocused) {
|
|
scheduleUnfocus();
|
|
}
|
|
}}
|
|
value={props.value}
|
|
className={props.className}
|
|
/>
|
|
{showKeyboard && (
|
|
<Keyboard
|
|
ref={keyboardRef}
|
|
top={props.topKeyboard}
|
|
value={String(props.value)}
|
|
blurRef={blurRef}
|
|
onInput={(value) => {
|
|
props.onChange && props.onChange(value);
|
|
|
|
if (isFocused) {
|
|
scheduleUnfocus();
|
|
}
|
|
}}
|
|
onClose={() => {
|
|
setShowKeyboard(false);
|
|
setFocused(false);
|
|
ref.current?.blur();
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|