Files
simply_cpq/website/node_modules/@base-ui/utils/useIdleCallback.mjs
T
2026-08-07 21:39:30 +02:00

54 lines
1.9 KiB
JavaScript

'use client';
import { useRefWithInit } from "./useRefWithInit.mjs";
import { useOnMount } from "./useOnMount.mjs";
const supportsIdleCallback = typeof requestIdleCallback === 'function';
// Macrotask fallback for environments without `requestIdleCallback` (e.g. older Safari).
// It runs after the current task (and thus the current commit), but — unlike
// `requestIdleCallback` — is not guaranteed to run after the next paint.
const requestCallback = supportsIdleCallback ? requestIdleCallback : fn => setTimeout(fn, 0);
const cancelCallback = supportsIdleCallback ? cancelIdleCallback : clearTimeout;
export class IdleCallback {
static create() {
return new IdleCallback();
}
currentId = null;
/**
* Schedules `fn` to run asynchronously after the current task (and thus the current commit),
* clearing any previously scheduled call. With native `requestIdleCallback` the callback runs
* during idle time after the next paint; the `setTimeout(0)` fallback runs after the current task
* but is not guaranteed to run after the next paint.
*/
start(fn) {
this.clear();
this.currentId = requestCallback(() => {
this.currentId = null;
fn();
});
}
clear = () => {
if (this.currentId !== null) {
cancelCallback(this.currentId);
this.currentId = null;
}
};
disposeEffect = () => {
return this.clear;
};
}
/**
* A `requestIdleCallback` with automatic cleanup and guard, mirroring `useTimeout`.
*
* Returns an imperative scheduler that runs a callback during idle time, after the current commit
* and paint. In environments without `requestIdleCallback` it falls back to a macrotask
* (`setTimeout(0)`), which runs after the current commit but is not guaranteed to run after the
* next paint.
*/
export function useIdleCallback() {
const idleCallback = useRefWithInit(IdleCallback.create).current;
useOnMount(idleCallback.disposeEffect);
return idleCallback;
}