svecosystem / runed

Magical utilities for your Svelte applications (WIP)
https://runed.dev
MIT License
461 stars 23 forks source link

Feature Request: IsIdle #59

Closed Tyson910 closed 2 months ago

Tyson910 commented 3 months ago

Describe the feature in detail (code, mocks, or screenshots encouraged)

IsIdle rune to track whether the user is being inactive.

Here's how I imagine the implementation would look like:

/**
 * Tracks whether the user is being inactive.
 * @see {@link https://runed.dev/docs/utilities/is-idle}
 */
export class IsIdle {
    #idle = $state<boolean>();
    #timer = $state<number>();
    #timeout = $state<number>();
    #events: (keyof WindowEventMap)[];

    constructor(timeout: number = 500, options: Partial<typeof DEFAULT_OPTIONS> = DEFAULT_OPTIONS) {
        this.#events = options?.events || ["keypress", "mousemove", "touchmove", "click", "scroll"];
        this.#idle = options?.initialState || false;
        this.#timeout = timeout;

        $effect(() => {
            this.#events.forEach((event) => document.addEventListener(event, this.reset));

            // remove event listeners onUnmount
            return () => {
                this.#events.forEach((event) => document.removeEventListener(event, this.reset));
            };
        });
    }

  // allow consumer to manually reset state
    reset() {
        this.#idle = false;

        if (this.#timer) {
            window.clearTimeout(this.#timer);
        }

        this.#timer = window.setTimeout(() => {
            this.#idle = true;
        }, this.#timeout);
    }

    get current() {
        return this.#idle;
    }
}

What type of pull request would this be?

New Feature

Provide relevant links or additional information.

This implementation could follow the UseIdle hook created by VueUse or Mantine

huntabyte commented 3 months ago

Hey @Tyson910, I think this looks like a very nice utility to have!

Are you open to contributing or would you like one of us to run with it?

Tyson910 commented 3 months ago

@huntabyte I'll get a PR open based on the above implementation