Appearance
Page lifecycle
Bridges the browser page's foreground/background lifecycle to the engine: pauses the loop when the tab or app goes to the background and resumes on return, emitting the elapsed time so offline progress can credit it. The browser-coupled half that keeps the core headless.
ts
import { pageLifecycle } from "@idlekitjs/browser/page-lifecycle";Usage
ts
engine.use(pageLifecycle());No options. From then on:
- tab hidden →
engine.pause()— frames stop, no battery burn, no throttled half-simulation; - tab visible → emits
resumewith the elapsed background milliseconds, thenengine.resume()— and the loop's first frame back has a zero delta, so there is no time jump.
The implementation listens to the Page Visibility API (visibilitychange / document.hidden). The name describes the bridge's responsibility: page foreground/background lifecycle into engine pause/resume.
Why opt-in?
Pausing on hidden tabs is policy, not physics. A game with a server clock, a music app, or a test harness may want the loop running. Core therefore only exposes pause()/resume(); when to call them is this bridge's opinion, and you opt into it. This is also what keeps document listeners out of @idlekitjs/core entirely.
The resume event
The elapsed time is broadcast on the engine bus:
ts
engine.events.on("resume", (elapsedMs) => {
console.log(`Welcome back! You were away ${Math.round(elapsedMs / 1000)}s`);
});offline-progress is the standard consumer, but your UI can listen too (a "welcome back" toast pairs well with the credit).
SSR / headless safety
In environments without document (Node, SSR, tests) the bridge is a no-op — engine.use(pageLifecycle()) is always safe, so shared wiring code needs no environment branches.
Cleanup
The bridge registers exactly one visibilitychange listener in setup and removes it in teardown — engine.dispose() leaves nothing behind.
Common pitfalls
- Installing offline-progress without page-lifecycle — same-session backgrounding won't be credited (only reloads). Install both.
- Pausing manually on top of it — the loop's pause is idempotent but your bookkeeping may not be; let the bridge own tab-driven pausing.
Related
- Offline progress — the consumer of
resume. - Simulation loop — pause/resume semantics.