This commit is contained in:
eewing
2026-02-17 14:10:16 -06:00
parent 2bca5834c5
commit cf73cd3b4c
11246 changed files with 1690552 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
export * from "./is-idle.svelte.js";
+1
View File
@@ -0,0 +1 @@
export * from "./is-idle.svelte.js";
+38
View File
@@ -0,0 +1,38 @@
import type { MaybeGetter } from "../../internal/types.js";
import { type ConfigurableDocument, type ConfigurableWindow } from "../../internal/configurable-globals.js";
export type IsIdleOptions = ConfigurableDocument & ConfigurableWindow & {
/**
* The events that should set the idle state to `true`
*
* @default ['mousemove', 'mousedown', 'resize', 'keydown', 'touchstart', 'wheel']
*/
events?: MaybeGetter<(keyof WindowEventMap)[]>;
/**
* The timeout in milliseconds before the idle state is set to `true`. Defaults to 60 seconds.
*
* @default 60000
*/
timeout?: MaybeGetter<number>;
/**
* Detect document visibility changes
*
* @default false
*/
detectVisibilityChanges?: MaybeGetter<boolean>;
/**
* The initial state of the idle property
*
* @default false
*/
initialState?: boolean;
};
/**
* Tracks whether the user is being inactive.
* @see {@link https://runed.dev/docs/utilities/is-idle}
*/
export declare class IsIdle {
#private;
constructor(_options?: IsIdleOptions);
get lastActive(): number;
get current(): boolean;
}
+63
View File
@@ -0,0 +1,63 @@
import { extract } from "../extract/index.js";
import { useDebounce } from "../use-debounce/index.js";
import { useEventListener } from "../use-event-listener/use-event-listener.svelte.js";
import { defaultWindow, } from "../../internal/configurable-globals.js";
const DEFAULT_EVENTS = [
"keypress",
"mousemove",
"touchmove",
"click",
"scroll",
];
const DEFAULT_OPTIONS = {
events: DEFAULT_EVENTS,
initialState: false,
timeout: 60000,
};
/**
* Tracks whether the user is being inactive.
* @see {@link https://runed.dev/docs/utilities/is-idle}
*/
export class IsIdle {
#current = $state(false);
#lastActive = $state(Date.now());
constructor(_options) {
const opts = {
...DEFAULT_OPTIONS,
..._options,
};
const window = opts.window ?? defaultWindow;
const document = opts.document ?? window?.document;
const timeout = $derived(extract(opts.timeout));
const events = $derived(extract(opts.events));
const detectVisibilityChanges = $derived(extract(opts.detectVisibilityChanges));
this.#current = opts.initialState;
const debouncedReset = useDebounce(() => {
this.#current = true;
}, () => timeout);
debouncedReset();
const handleActivity = () => {
this.#current = false;
this.#lastActive = Date.now();
debouncedReset();
};
useEventListener(() => window, () => events, () => {
handleActivity();
}, { passive: true });
$effect(() => {
if (!detectVisibilityChanges || !document)
return;
useEventListener(document, ["visibilitychange"], () => {
if (document.hidden)
return;
handleActivity();
});
});
}
get lastActive() {
return this.#lastActive;
}
get current() {
return this.#current;
}
}