UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

116 lines (115 loc) 3.57 kB
"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, maxWait } = typeof options === "number" ? { delay: options, flushOnUnmount: false, leading: false, maxWait: void 0 } : options; const handleCallback = useCallbackRef(callback); const debounceTimerRef = useRef(0); const maxWaitTimerRef = useRef(0); const latestArgsRef = useRef(null); const lastCallback = useMemo(() => { const currentCallback = Object.assign((...args) => { window.clearTimeout(debounceTimerRef.current); latestArgsRef.current = args; const isFirstCall = currentCallback._isFirstCall; currentCallback._isFirstCall = false; function clearTimeoutAndLeadingRef() { window.clearTimeout(debounceTimerRef.current); window.clearTimeout(maxWaitTimerRef.current); debounceTimerRef.current = 0; maxWaitTimerRef.current = 0; currentCallback._isFirstCall = true; currentCallback._hasPendingCallback = false; } function startMaxWaitTimer() { if (maxWait !== void 0 && maxWaitTimerRef.current === 0) maxWaitTimerRef.current = window.setTimeout(() => { if (debounceTimerRef.current !== 0) { const latestArgs = latestArgsRef.current; clearTimeoutAndLeadingRef(); handleCallback(...latestArgs); } }, maxWait); } 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); startMaxWaitTimer(); return; } if (leading && !isFirstCall) { currentCallback._hasPendingCallback = true; 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); startMaxWaitTimer(); return; } currentCallback._hasPendingCallback = true; const flush = () => { if (debounceTimerRef.current !== 0) { clearTimeoutAndLeadingRef(); handleCallback(...args); } }; const cancel = () => { clearTimeoutAndLeadingRef(); }; currentCallback.flush = flush; currentCallback.cancel = cancel; debounceTimerRef.current = window.setTimeout(flush, delay); startMaxWaitTimer(); }, { flush: () => {}, cancel: () => {}, isPending: () => currentCallback._hasPendingCallback, _isFirstCall: true, _hasPendingCallback: false }); return currentCallback; }, [ handleCallback, delay, leading, maxWait ]); useEffect(() => () => { if (flushOnUnmount) lastCallback.flush(); else lastCallback.cancel(); }, [lastCallback, flushOnUnmount]); return lastCallback; } //#endregion export { useDebouncedCallback }; //# sourceMappingURL=use-debounced-callback.mjs.map