render-dom
Import from @pierre/ecs/modules/render-dom.
DOM-backed renderer primitives for ECS games.
V1 scope: stable entity-to-node bookkeeping, optional z-order via
RenderOrderDef, orphan cleanup, and deterministic data-entity-id
attributes for hit-testing.
interface DomRenderContext { root: HTMLElement; world: EcsWorld;}
interface DomRenderable { tag?: string; className?: string; text?: string; attributes?: Record<string, string>; dataset?: Record<string, string>; style?: Record<string, string>; hidden?: boolean;}
const DomRenderableDef: ComponentDef<DomRenderable>;
interface DomRendererOptions { reconcile?: (args: { entityId: EntityId; node: HTMLElement; renderable: DomRenderable; world: EcsWorld; }) => void;}
class DomRenderer implements Renderer<DomRenderContext> { constructor(options?: DomRendererOptions); render(ctx: DomRenderContext): void;}
function entityAtPoint(x: number, y: number, root?: Element): EntityId | null;Picking
Section titled “Picking”entityAtPoint(clientX, clientY, root?) answers “which entity is under the
pointer?” for anything DomRenderer drew. It asks the browser for the topmost
element at the point and walks up to the nearest node carrying
data-entity-id, so a hit on a node’s child text still resolves to the entity.
import { entityAtPoint } from '@pierre/ecs/modules/render-dom';
const container = document.getElementById('game')!;container.addEventListener('pointerdown', (ev) => { const id = entityAtPoint(ev.clientX, ev.clientY, container); if (id !== null) console.log('picked entity', id);});- Coordinates are client pixels (
clientX/clientY), what the browser hit-tests in. - Pass
rootto ignore entities rendered outside it — a second renderer on the page, or an overlay. - An element with
pointer-events: noneis invisible to the browser’s hit test. Put a dragged node in a layer styled that way so the drop target under it stays pickable.
- The renderer always writes
data-entity-idand keeps that attribute engine-owned. - V1 intentionally supports only
textcontent, notinnerHTML. - Attribute validation rejects
on*,srcdoc, and class/style duplicates; useclassName,dataset, andstylefields instead. - Nodes are absolutely positioned using
left/topfromPositionDef; thestyleobject rejectsleft,top, andpositionbecause those keys are engine-owned. reconcileruns after base reconciliation and can be used for per-entity adjustments (for example, zone-based layout overrides in DOM-heavy UIs).
Dependencies
Section titled “Dependencies”modules/transform—PositionDeffor each node’sleft/top.modules/render-canvas2d—RenderOrderDeffor z-order.