/** * Returns a debounced version of fn that delays invocation until after * `delay` ms have elapsed since the last call. The returned function * exposes a `cancel()` method that DROPS (does not flush) the pending * trailing invocation — essential when the host context (a destroyed * component, an unmounted editor) shouldn't fire the trailing call. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function debounce void>( fn: T, delay: number ): T & { cancel: () => void } { let timer: ReturnType | undefined; const wrapped = ((...args: Parameters) => { if (timer !== undefined) clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); }) as T & { cancel: () => void }; wrapped.cancel = () => { if (timer !== undefined) { clearTimeout(timer); timer = undefined; } }; return wrapped; }