Skip to content

@idlekitjs/dom

DOM rendering and binding helpers for IdleKit games. It is optional and owns DOM concerns only.

What it provides

  • Renderer, the dependency-tracked binding runner used by createEngine.
  • bindText, bindClass, bindVisible and bindDisabled.
  • bindEach for keyed list rendering, also available from @idlekitjs/dom/bind-each.
  • The Binding type, re-exported from @idlekitjs/types.

When to use it

Use @idlekitjs/dom when your game renders directly to the browser DOM. Skip it for headless tests, server-side simulations, canvas renderers or framework UIs that read engine.state directly.

Basic usage

ts
import { createEngine } from "@idlekitjs/core";
import { createRafScheduler } from "@idlekitjs/browser/raf-scheduler";
import { Renderer, bindText } from "@idlekitjs/dom";

const renderer = new Renderer();
const engine = createEngine<State>({
  initialState,
  renderer,
  scheduler: createRafScheduler(),
});

const coins = document.querySelector<HTMLElement>("#coins")!;
renderer.add(bindText(coins, () => Math.floor(engine.state.coins).toString()));

engine.start();

Keyed dynamic children use bindEach:

ts
import { bindEach } from "@idlekitjs/dom/bind-each";

renderer.add(
  bindEach(list, {
    items: () => rows,
    key: (row) => row.id,
    create: () => document.createElement("li"),
    update: (element, row) => {
      element.textContent = row.label;
    },
  }),
);

Boundaries

@idlekitjs/dom renders or binds UI. It does not own gameplay rules, browser lifecycle, frame scheduling policies, persistence or save timing.

The dependency direction is dom -> core, never core -> dom. Browser runtime bridges such as createRafScheduler, pageLifecycle and screen helpers live in @idlekitjs/browser.