import { ref, onUnmounted } from 'vue'; /** * Creates a debounced version of a function * @param {Function} fn - The function to debounce * @param {number} delay - The delay in milliseconds * @returns {Function} - The debounced function */ export const useDebounceFn = (fn, delay = 300) => { if (typeof fn !== 'function') { throw new Error('First argument must be a function'); } // Store the timeout ID for cleanup const timeoutId = ref(null); // Clean up any pending timeouts when the component is unmounted onUnmounted(() => { if (timeoutId.value) { clearTimeout(timeoutId.value); } }); // Return the debounced function return (...args) => { // Clear previous timeout if exists if (timeoutId.value) { clearTimeout(timeoutId.value); } // Set a new timeout timeoutId.value = setTimeout(() => { fn(...args); timeoutId.value = null; }, delay); }; }; /** * Creates a throttled version of a function * @param {Function} fn - The function to throttle * @param {number} delay - The delay in milliseconds * @returns {Function} - The throttled function */ export const useThrottleFn = (fn, delay = 300) => { if (typeof fn !== 'function') { throw new Error('First argument must be a function'); } // Store the last execution time const lastExecution = ref(0); // Store the timeout ID for cleanup const timeoutId = ref(null); // Clean up any pending timeouts when the component is unmounted onUnmounted(() => { if (timeoutId.value) { clearTimeout(timeoutId.value); } }); // Return the throttled function return (...args) => { const now = Date.now(); const elapsed = now - lastExecution.value; // Clear any existing timeout if (timeoutId.value) { clearTimeout(timeoutId.value); } // If enough time has passed, execute immediately if (elapsed >= delay) { lastExecution.value = now; fn(...args); } else { // Otherwise, schedule execution for when the delay has passed timeoutId.value = setTimeout(() => { lastExecution.value = Date.now(); fn(...args); timeoutId.value = null; }, delay - elapsed); } }; }; export default useDebounceFn;