52 lines
1.8 KiB
JavaScript
52 lines
1.8 KiB
JavaScript
import { executeCallbacks } from "svelte-toolbelt";
|
|
import { on } from "svelte/events";
|
|
// Using global state to avoid multiple listeners.
|
|
let isUsingKeyboard = $state(false);
|
|
/**
|
|
* Detects whether the user is currently using the keyboard
|
|
* or not by listening to keyboard and pointer events. Uses shared global
|
|
* state to avoid listener duplication.
|
|
*/
|
|
export class IsUsingKeyboard {
|
|
static _refs = 0; // Reference counting to avoid multiple listeners.
|
|
static _cleanup;
|
|
constructor() {
|
|
$effect(() => {
|
|
if (IsUsingKeyboard._refs === 0) {
|
|
IsUsingKeyboard._cleanup = $effect.root(() => {
|
|
const callbacksToDispose = [];
|
|
const handlePointer = (_) => {
|
|
isUsingKeyboard = false;
|
|
};
|
|
const handleKeydown = (_) => {
|
|
isUsingKeyboard = true;
|
|
};
|
|
callbacksToDispose.push(on(document, "pointerdown", handlePointer, {
|
|
capture: true,
|
|
}), on(document, "pointermove", handlePointer, {
|
|
capture: true,
|
|
}), on(document, "keydown", handleKeydown, {
|
|
capture: true,
|
|
}));
|
|
// Don't forget to spread and call twice.
|
|
return executeCallbacks(...callbacksToDispose);
|
|
});
|
|
}
|
|
IsUsingKeyboard._refs++;
|
|
return () => {
|
|
IsUsingKeyboard._refs--;
|
|
if (IsUsingKeyboard._refs === 0) {
|
|
isUsingKeyboard = false;
|
|
IsUsingKeyboard._cleanup?.();
|
|
}
|
|
};
|
|
});
|
|
}
|
|
get current() {
|
|
return isUsingKeyboard;
|
|
}
|
|
set current(value) {
|
|
isUsingKeyboard = value;
|
|
}
|
|
}
|