Markus on PR #629 — the cancel-not-flush contract is what the PersonMentionEditor onDestroy path relies on. Spell it out so future callers can rely on the same guarantee. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
26 lines
904 B
TypeScript
26 lines
904 B
TypeScript
/**
|
|
* 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<T extends (...args: any[]) => void>(
|
|
fn: T,
|
|
delay: number
|
|
): T & { cancel: () => void } {
|
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
const wrapped = ((...args: Parameters<T>) => {
|
|
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;
|
|
}
|