62 lines
1.7 KiB
JavaScript
62 lines
1.7 KiB
JavaScript
import { extract } from "../extract/index.js";
|
|
import { watch } from "../watch/watch.svelte.js";
|
|
/**
|
|
* Wrapper for `setInterval` with controls for pausing and resuming.
|
|
*
|
|
* @see https://runed.dev/docs/utilities/use-interval
|
|
*
|
|
* @param delay - The interval in milliseconds between executions
|
|
* @param options - Configuration options
|
|
* @returns Object with pause, resume, reset methods, counter and isActive state
|
|
*/
|
|
export function useInterval(delay, options = {}) {
|
|
const { immediate = true, immediateCallback = false, callback } = options;
|
|
let intervalId = $state(null);
|
|
let counter = $state(0);
|
|
const delay$ = $derived(extract(delay));
|
|
const isActive = $derived(intervalId !== null);
|
|
function runCallback() {
|
|
counter++;
|
|
callback?.(counter);
|
|
}
|
|
function createInterval() {
|
|
intervalId = setInterval(runCallback, delay$);
|
|
}
|
|
const pause = () => {
|
|
if (intervalId === null)
|
|
return;
|
|
clearInterval(intervalId);
|
|
intervalId = null;
|
|
};
|
|
const resume = () => {
|
|
if (intervalId !== null)
|
|
return;
|
|
if (immediateCallback)
|
|
runCallback();
|
|
createInterval();
|
|
};
|
|
if (immediate) {
|
|
resume();
|
|
}
|
|
// Sync interval's delay with the prop
|
|
watch(() => delay$, () => {
|
|
if (!isActive)
|
|
return;
|
|
pause();
|
|
createInterval();
|
|
});
|
|
// Cleanup on disposal
|
|
$effect(() => pause);
|
|
return {
|
|
pause,
|
|
resume,
|
|
reset: () => (counter = 0),
|
|
get isActive() {
|
|
return isActive;
|
|
},
|
|
get counter() {
|
|
return counter;
|
|
},
|
|
};
|
|
}
|