Packages
Mirage Engine is a pnpm monorepo. mirage-engine is the package you normally
install; the rest are published so you can pick just one piece.
| Package | npm | Depends on |
|---|---|---|
mirage-engine | ↗ (opens in a new tab) | core, painter, sandwich |
@mirage-engine/core | ↗ (opens in a new tab) | painter, dom-tracker, wasm-compute |
@mirage-engine/painter | ↗ (opens in a new tab) | three (peer) |
@mirage-engine/dom-tracker | ↗ (opens in a new tab) | — |
@mirage-engine/sandwich | ↗ (opens in a new tab) | dom-tracker |
@mirage-engine/wasm-compute | internal | Rust / wasm-bindgen |
@mirage-engine/core
Everything except the facade. Use it if you are building your own wrapper.
import { Engine, WasmSynchronizer } from "@mirage-engine/core";
import type { CoreConfig, SceneNode, Quality } from "@mirage-engine/core";Engine
| Method | Signature | Notes |
|---|---|---|
constructor | (target, config: CoreConfig) | Injects styles, resolves container, builds Renderer + Syncer |
start | (): Promise<void> | Boots wasm, starts the tracker |
stop | (): void | Stops the tracker |
dispose | (): void | Stops and disposes the renderer |
getTracker | (): Tracker | Underlying DOM tracker |
getCanvas | (): HTMLCanvasElement | Mounted canvas |
updateUniforms | (el, uniforms): void | Fast-path uniform write |
Also exported: the full type surface (SceneNode, NodeRect, Visibility,
THREE_LAYERS, ATTR_* constants, DIRTY_* flags, WASM_STRIDE and the
OFFSET_* indices).
@mirage-engine/painter
DOM-accurate Three.js materials, standalone. No DOM observation — you supply the styles.
import { Painter, TextGenerator, createBoxMaterial } from "@mirage-engine/painter";Painter
Painter.create(
type: "BOX" | "TEXT",
styles: BoxStyles | TextStyles,
content: string,
width: number,
height: number,
quality?: number,
texture?: THREE.Texture | null,
shaderHooks?: ShaderHooks,
): THREE.Material
Painter.update(material, type, styles, content, width, height, quality?, texture?): void
Painter.forceUpdateUniforms(material: THREE.ShaderMaterial, values: BoxUniformValues): voidimport * as THREE from "three";
import { Painter } from "@mirage-engine/painter";
const material = Painter.create("BOX", {
backgroundColor: "rgb(20, 20, 30)",
backgroundImage: "linear-gradient(45deg, #f00, #00f)",
opacity: 1,
zIndex: 0,
borderRadius: "16px",
borderColor: "rgba(255,255,255,0.2)",
borderWidth: "2px",
boxShadow: "0 8px 24px rgba(0,0,0,0.4)",
}, "", 320, 180);
const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material);
mesh.scale.set(320, 180, 1);TextGenerator
A THREE.MeshBasicMaterial subclass that paints text onto a CanvasTexture.
const mat = new TextGenerator("Hello", textStyles, 200, 40, 2);
mat.updateText("Goodbye", textStyles, 200, 40);
mat.dispose();CSS parsers
parsePixelValue, parseColor, splitByComma, parseLinearGradient and
parseBoxShadow are exported for reuse. They accept the string forms
getComputedStyle returns.
import { parseLinearGradient } from "@mirage-engine/painter";
parseLinearGradient("linear-gradient(45deg, red 0%, blue 100%)");
// { angle: 0.785…, stops: [ { color, alpha, stop }, … ] }@mirage-engine/dom-tracker
Batched DOM observation with no rendering opinion. Zero dependencies.
import { Tracker, extractFromStyle } from "@mirage-engine/dom-tracker";
const tracker = new Tracker(document.body, { resizeDebounce: { delay: 200 } });
tracker.onLayoutChange.add((mask, deletions) => { /* … */ });
tracker.onStyleChange.add((styles) => { /* Map<HTMLElement, StyleData> */ });
tracker.onRender.add(() => { /* every frame */ });
tracker.start();| Hook | Payload | Fires |
|---|---|---|
onBeforeRender | — | Every frame, first |
onLayoutChange | (mask: number, deletions: Set<HTMLElement>) | Only when the tree is dirty |
onScrollChange | (scrollX, scrollY) | When window scroll changed |
onStyleChange | Map<HTMLElement, StyleData> | When inline styles mutated |
onRender | — | Every frame, last |
Each hook is a Set, so add / delete manage subscriptions.
Mirage itself subscribes to onLayoutChange, onStyleChange and onRender.
onScrollChange fires but has no built-in subscriber — it is there for you.
@mirage-engine/sandwich
DOM teleportation: lift elements above a canvas while keeping page layout intact.
import { SandwichRenderer } from "@mirage-engine/sandwich";
const sandwich = new SandwichRenderer({ frontSelector: "[data-hud]" });
sandwich.init();| Method | Purpose |
|---|---|
init() | Create layers, hijack front elements, wire hooks, start the tracker |
useTracker(tracker) | Reuse an existing tracker instead of creating one |
Mirage calls useTracker(engine.getTracker()) automatically so both share one
requestAnimationFrame loop.
@mirage-engine/wasm-compute
Rust crate compiled with wasm-pack. Not meant for direct use.
pub struct MemoryManager { /* Vec<f32> */ }
impl MemoryManager {
pub fn new(capacity: usize) -> MemoryManager;
pub fn get_pointer(&self) -> *const f32;
pub fn get_length(&self) -> usize;
pub fn update_physics(&mut self, node_count: usize);
}Layout is five floats per node:
[ parentIndex, localX, localY, worldX, worldY ]update_physics walks nodes in order, adding each parent's world position to
the child's local offset. Because extraction emits parents before children, one
forward pass resolves the whole tree.