'use client'; import { useRef } from 'react'; interface Props { value: string; // "HH:MM" onChange: (value: string) => void; className?: string; } function addMinutes(time: string, delta: number): string { const [h, m] = time.split(':').map(Number); const total = ((h * 60 + m + delta) % (24 * 60) + 24 * 60) % (24 * 60); const pad = (n: number) => String(n).padStart(2, '0'); return `${pad(Math.floor(total / 60))}:${pad(total % 60)}`; } export default function TimePicker5({ value, onChange, className = '' }: Props) { const valueRef = useRef(value); valueRef.current = value; const intervalRef = useRef | null>(null); const timeoutRef = useRef | null>(null); function startRepeat(delta: number) { onChange(addMinutes(valueRef.current, delta)); timeoutRef.current = setTimeout(() => { const hourDelta = delta > 0 ? 60 : -60; intervalRef.current = setInterval(() => { onChange(addMinutes(valueRef.current, hourDelta)); }, 350); }, 400); } function stopRepeat() { if (timeoutRef.current !== null) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } if (intervalRef.current !== null) { clearInterval(intervalRef.current); intervalRef.current = null; } } function buttonProps(delta: number) { return { type: 'button' as const, tabIndex: -1, onMouseDown: () => startRepeat(delta), onMouseUp: stopRepeat, onMouseLeave: stopRepeat, onTouchStart: (e: React.TouchEvent) => { e.preventDefault(); startRepeat(delta); }, onTouchEnd: stopRepeat, }; } return (
{ if (e.key === 'ArrowUp') { e.preventDefault(); onChange(addMinutes(value, 5)); } if (e.key === 'ArrowDown') { e.preventDefault(); onChange(addMinutes(value, -5)); } }} className={`flex items-center border-2 border-gray-400 rounded-lg bg-white focus:border-blue-500 focus:outline-none select-none ${className}`} > {value}
); }