@neo4j-ndl/react
Version:
React implementation of Neo4j Design System
162 lines • 5.67 kB
JavaScript
;
/**
*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.useDebounceCallback = useDebounceCallback;
const react_1 = require("react");
const createDebouncedFunction = (callback, delay, options) => {
var _a, _b;
let timeoutId;
let maxWaitTimeoutId;
let lastArgs;
let result;
const isLeading = (_a = options.leading) !== null && _a !== void 0 ? _a : false;
const isTrailing = (_b = options.trailing) !== null && _b !== void 0 ? _b : true;
const maxWait = options.maxWait;
const clearTimers = () => {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
timeoutId = undefined;
}
if (maxWaitTimeoutId !== undefined) {
clearTimeout(maxWaitTimeoutId);
maxWaitTimeoutId = undefined;
}
};
const invoke = () => {
if (lastArgs === undefined) {
return result;
}
const args = lastArgs;
lastArgs = undefined;
result = callback(...args);
return result;
};
const scheduleTrailing = () => {
if (!isTrailing) {
if (isLeading) {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
timeoutId = undefined;
}, delay);
}
return;
}
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
timeoutId = undefined;
if (maxWaitTimeoutId !== undefined) {
clearTimeout(maxWaitTimeoutId);
maxWaitTimeoutId = undefined;
}
invoke();
}, delay);
};
const scheduleMaxWait = () => {
if (maxWait === undefined || maxWaitTimeoutId !== undefined) {
return;
}
maxWaitTimeoutId = setTimeout(() => {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
timeoutId = undefined;
}
maxWaitTimeoutId = undefined;
invoke();
}, maxWait);
};
const debounced = (...args) => {
const isFirstInvocationInBurst = timeoutId === undefined && maxWaitTimeoutId === undefined;
lastArgs = args;
if (isLeading && isFirstInvocationInBurst) {
result = callback(...args);
lastArgs = undefined;
}
scheduleTrailing();
scheduleMaxWait();
return result;
};
const cancel = () => {
clearTimers();
lastArgs = undefined;
};
const flush = () => {
clearTimers();
return invoke();
};
const isPending = () => timeoutId !== undefined ||
maxWaitTimeoutId !== undefined ||
lastArgs !== undefined;
return { cancel, debounced, flush, isPending };
};
/**
* Local override for usehooks-ts useDebounceCallback.
*
* This keeps one debounced function instance across rerenders (unless delay/options change)
* while always calling the latest callback. It avoids resetting debounce timing when
* inline callbacks are recreated every render.
*/
function useDebounceCallback(func, delay = 500, options = {}) {
var _a, _b;
const latestCallbackRef = (0, react_1.useRef)(func);
const debouncedStateRef = (0, react_1.useRef)(undefined);
const isLeading = (_a = options.leading) !== null && _a !== void 0 ? _a : false;
const isTrailing = (_b = options.trailing) !== null && _b !== void 0 ? _b : true;
const maxWait = options.maxWait;
(0, react_1.useEffect)(() => {
latestCallbackRef.current = func;
}, [func]);
(0, react_1.useEffect)(() => {
return () => {
var _a;
(_a = debouncedStateRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
};
}, []);
const debouncedState = (0, react_1.useMemo)(() => {
var _a;
(_a = debouncedStateRef.current) === null || _a === void 0 ? void 0 : _a.cancel();
const nextDebouncedState = createDebouncedFunction((...args) => latestCallbackRef.current(...args), delay, {
leading: isLeading,
maxWait,
trailing: isTrailing,
});
debouncedStateRef.current = nextDebouncedState;
return nextDebouncedState;
}, [delay, isLeading, isTrailing, maxWait]);
return (0, react_1.useMemo)(() => {
const wrapped = ((...args) => debouncedState.debounced(...args));
wrapped.cancel = () => {
debouncedState.cancel();
};
wrapped.flush = () => {
return debouncedState.flush();
};
wrapped.isPending = () => {
return debouncedState.isPending();
};
return wrapped;
}, [debouncedState]);
}
//# sourceMappingURL=index.js.map