rvx
Version:
A signal based rendering library
96 lines • 2.87 kB
JavaScript
import { Context } from "../core/context.js";
import { ENV } from "../core/env.js";
import { isolate } from "../core/isolate.js";
import { teardown } from "../core/lifecycle.js";
import { $, watch } from "../core/signals.js";
export class Tasks {
#pendingCount = 0;
#pending = $(false);
#restoreFocus;
#parent;
constructor(parent, options) {
this.#parent = parent;
this.#restoreFocus = options?.restoreFocus ?? (parent ? parent.#restoreFocus : true);
if (this.#restoreFocus) {
const env = ENV.current;
let last = null;
watch(this.#pending, pending => {
if (pending) {
last = env.document.activeElement;
}
else if (last && env.document.activeElement === env.document.body) {
const target = last;
queueMicrotask(() => {
if (last === target && env.document.activeElement === env.document.body) {
target.focus?.();
}
});
}
});
}
}
#setPending() {
this.#pendingCount++;
this.#pending.value = true;
}
#unsetPending() {
this.#pendingCount--;
this.#pending.value = this.#pendingCount > 0;
}
get parent() {
return this.#parent;
}
get selfPending() {
return this.#pending.value;
}
get pending() {
return (this.#parent?.pending ?? false) || this.#pending.value;
}
setPending() {
this.#setPending();
let disposed = false;
teardown(() => {
if (!disposed) {
disposed = true;
this.#unsetPending();
}
});
}
waitFor(source) {
if (typeof source === "function") {
this.#setPending();
void (async () => {
try {
return await isolate(source);
}
catch (error) {
void Promise.reject(error);
}
finally {
this.#unsetPending();
}
})();
}
else if (source instanceof Promise) {
this.#setPending();
void source.then(() => this.#unsetPending(), () => this.#unsetPending());
}
}
static fork(options) {
return new Tasks(TASKS.current, options);
}
}
export const TASKS = new Context();
export function isSelfPending() {
return TASKS.current?.selfPending ?? false;
}
export function isPending() {
return TASKS.current?.pending ?? false;
}
export function setPending() {
TASKS.current?.setPending();
}
export function waitFor(source) {
TASKS.current?.waitFor(source);
}
//# sourceMappingURL=tasks.js.map