import React from "react"; import { type Period, type TimePickerType, getArrowByType, getDateByType, setDateByType, } from "./time-picker-utils"; import { Input } from "@/src/components/ui/input"; import { cn } from "@/src/utils/tailwind"; export interface TimePickerInputProps extends React.InputHTMLAttributes { picker: TimePickerType; date: Date | undefined; setDate: (date: Date | undefined) => void; period?: Period; onRightFocus?: () => void; onLeftFocus?: () => void; } const TimePickerInput = React.forwardRef< HTMLInputElement, TimePickerInputProps >( ( { className, type = "tel", value, id, name, date = new Date(new Date().setHours(0, 0, 0, 0)), setDate, onChange, onKeyDown, picker, period, onLeftFocus, onRightFocus, ...props }, ref, ) => { const [flag, setFlag] = React.useState(false); const [prevIntKey, setPrevIntKey] = React.useState("0"); /** * allow the user to enter the second digit within 2 seconds * otherwise start again with entering first digit */ React.useEffect(() => { if (flag) { const timer = setTimeout(() => { setFlag(false); }, 2000); return () => clearTimeout(timer); } }, [flag]); const calculatedValue = React.useMemo(() => { return getDateByType(date, picker); }, [date, picker]); const calculateNewValue = (key: string) => { /* * If picker is '12hours' and the first digit is 0, then the second digit is automatically set to 1. * The second entered digit will break the condition and the value will be set to 10-12. */ if (picker === "12hours") { if (flag && calculatedValue.slice(1, 2) === "1" && prevIntKey === "0") return "0" + key; } return !flag ? "0" + key : calculatedValue.slice(1, 2) + key; }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Tab") return; e.preventDefault(); if (e.key === "ArrowRight") onRightFocus?.(); if (e.key === "ArrowLeft") onLeftFocus?.(); if (["ArrowUp", "ArrowDown"].includes(e.key)) { const step = e.key === "ArrowUp" ? 1 : -1; const newValue = getArrowByType(calculatedValue, step, picker); if (flag) setFlag(false); setDate(setDateByType(new Date(date), newValue, picker, period)); } if (e.key >= "0" && e.key <= "9") { if (picker === "12hours") setPrevIntKey(e.key); const newValue = calculateNewValue(e.key); if (flag) onRightFocus?.(); setFlag((prev) => !prev); setDate(setDateByType(new Date(date), newValue, picker, period)); } }; return ( { e.preventDefault(); onChange?.(e); }} type={type} inputMode="decimal" onKeyDown={(e) => { onKeyDown?.(e); handleKeyDown(e); }} {...props} /> ); }, ); TimePickerInput.displayName = "TimePickerInput"; export { TimePickerInput };