@mantine/hooks
Version:
A collection of 50+ hooks for state and UI management
92 lines (91 loc) • 2.7 kB
JavaScript
"use client";
import { useCallbackRef } from "../utils/use-callback-ref/use-callback-ref.mjs";
import { useEffect, useMemo, useRef } from "react";
//#region packages/@mantine/hooks/src/use-debounced-callback/use-debounced-callback.ts
function useDebouncedCallback(callback, options) {
const { delay, flushOnUnmount, leading } = typeof options === "number" ? {
delay: options,
flushOnUnmount: false,
leading: false
} : options;
const handleCallback = useCallbackRef(callback);
const debounceTimerRef = useRef(0);
const lastCallback = useMemo(() => {
const currentCallback = Object.assign((...args) => {
window.clearTimeout(debounceTimerRef.current);
const isFirstCall = currentCallback._isFirstCall;
currentCallback._isFirstCall = false;
function clearTimeoutAndLeadingRef() {
window.clearTimeout(debounceTimerRef.current);
debounceTimerRef.current = 0;
currentCallback._isFirstCall = true;
}
if (leading && isFirstCall) {
handleCallback(...args);
const resetLeadingState = () => {
clearTimeoutAndLeadingRef();
};
const flush = () => {
if (debounceTimerRef.current !== 0) {
clearTimeoutAndLeadingRef();
handleCallback(...args);
}
};
const cancel = () => {
clearTimeoutAndLeadingRef();
};
currentCallback.flush = flush;
currentCallback.cancel = cancel;
debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);
return;
}
if (leading && !isFirstCall) {
const flush = () => {
if (debounceTimerRef.current !== 0) {
clearTimeoutAndLeadingRef();
handleCallback(...args);
}
};
const cancel = () => {
clearTimeoutAndLeadingRef();
};
currentCallback.flush = flush;
currentCallback.cancel = cancel;
const resetLeadingState = () => {
clearTimeoutAndLeadingRef();
};
debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);
return;
}
const flush = () => {
if (debounceTimerRef.current !== 0) {
clearTimeoutAndLeadingRef();
handleCallback(...args);
}
};
const cancel = () => {
clearTimeoutAndLeadingRef();
};
currentCallback.flush = flush;
currentCallback.cancel = cancel;
debounceTimerRef.current = window.setTimeout(flush, delay);
}, {
flush: () => {},
cancel: () => {},
_isFirstCall: true
});
return currentCallback;
}, [
handleCallback,
delay,
leading
]);
useEffect(() => () => {
if (flushOnUnmount) lastCallback.flush();
else lastCallback.cancel();
}, [lastCallback, flushOnUnmount]);
return lastCallback;
}
//#endregion
export { useDebouncedCallback };
//# sourceMappingURL=use-debounced-callback.mjs.map