/** * The delay (in ms) used for debounced search inputs across the plugin, * matching `useUserSearch`'s existing 300ms debounce. */ export const SEARCH_DEBOUNCE_MS = 300 /** * Delay `callback` until `wait` ms have passed without another call. * * Preserves the `this` binding of the call site, so it works both as a * standalone function and as a method on a petite-vue scope object (where * `this` is the scope itself). Exposes `cancel()` so callers (e.g. a "clear * search" handler) can drop a pending invocation before firing an immediate * one of their own. * * @param callback - The function to debounce * @param wait - The delay in ms to wait after the last call before invoking `callback` * @returns The debounced function, with an attached `cancel()` method */ export function debounce void>(callback: T, wait: number): T & { cancel: () => void } { let timer: ReturnType | undefined function debounced(this: unknown, ...args: Parameters) { clearTimeout(timer) timer = setTimeout(() => callback.apply(this, args), wait) } debounced.cancel = () => clearTimeout(timer) // `debounced` matches `T`'s parameters but TypeScript cannot prove the // generic relation, so assert it to keep `cancel()` in the public signature. return debounced as unknown as T & { cancel: () => void } }