"use client"; import React, { useCallback, useEffect, useRef, useState } from "react"; import { TextField, TextFieldProps } from "./TextField"; type TextFieldChangeEvent = React.ChangeEvent; export function DebouncedTextField(props: TextFieldProps) { const [internalValue, setInternalValue] = useState(props.value ?? ""); const lastSentValueRef = useRef(props.value ?? ""); const timerRef = useRef | undefined>(undefined); // Sync state with props.value when it changes externally useEffect(() => { const externalValue = props.value ?? ""; if (externalValue !== lastSentValueRef.current) { setInternalValue(externalValue); lastSentValueRef.current = externalValue; } }, [props.value]); // Cleanup timer on unmount useEffect(() => { return () => { if (timerRef.current) clearTimeout(timerRef.current); }; }, []); const flushChange = useCallback((value: T | string, event?: TextFieldChangeEvent) => { if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = undefined; } if (value !== props.value && props.onChange) { lastSentValueRef.current = value; const e = { ...event, target: { ...event?.target, value: value, name: props.name } } as TextFieldChangeEvent; props.onChange(e); } }, [props.value, props.onChange, props.name]); const internalOnChange = useCallback((event: TextFieldChangeEvent) => { const newValue = event.target.value; setInternalValue(newValue); if (timerRef.current) clearTimeout(timerRef.current); const eventCopy = { ...event, target: { ...event?.target, name: event?.target?.name } }; timerRef.current = setTimeout(() => { flushChange(newValue, eventCopy as TextFieldChangeEvent); }, 150); }, [flushChange]); const internalOnBlur = useCallback((event: React.FocusEvent) => { flushChange(internalValue, event as TextFieldChangeEvent); props.onBlur?.(event); }, [internalValue, flushChange, props.onBlur]); return ; }