Getting Started

    npm install bireactive
    

    A cell is a writable reactive value. derive builds a read-only value from others; effect runs a side effect whenever what it reads changes. Dependencies are tracked automatically — just read a value to subscribe to it.

    import { cell, derive, effect } from "bireactive";

    const celsius = cell(20);
    const fahrenheit = derive(() => (celsius.value * 9) / 5 + 32);

    effect(() => console.log(`${celsius.value}°C = ${fahrenheit.value}°F`));
    // logs: 20°C = 68°F

    celsius.value = 100; // logs: 100°C = 212°F

    Writing a derived value is an error — it has no inverse:

    fahrenheit.value = 32; // ✗ throws: cannot write to a computed
    

    A lens is a derivation with an inverse, so the derived end is writable and the change flows back to the source. A two-argument backward function may read the current source; a one-argument one reconstructs it from the view alone.

    import { cell } from "bireactive";

    const celsius = cell(20);
    const fahrenheit = celsius.lens(
    c => (c * 9) / 5 + 32,
    f => ((f - 32) * 5) / 9,
    );

    fahrenheit.value = 212;
    celsius.value; // 100

    This is the core idea. Where two-way data binding wires up ad-hoc setters, a lens is a single composable object whose forward and backward directions stay in sync by construction.

    Values also come as small classes — Num, Vec, Box, Color, and more — whose fields and operators are themselves lenses, so you can read and write deep into them.

    import { vec, mean } from "bireactive";

    const a = vec(0, 0);
    const b = vec(10, 0);

    const mid = mean([a, b]); // writable midpoint
    mid.value = { x: 5, y: 10 }; // drag the midpoint up…
    a.value; // { x: 0, y: 10 } — both ends move to keep it the midpoint

    // Fields are lenses too:
    a.x.value = 3; // writes straight through to `a`

    Use effect to push values somewhere — the DOM, a canvas, the console. The effect re-runs only when something it read actually changes.

    import { cell, effect } from "bireactive";

    const label = cell("hello");
    const el = document.querySelector("#out")!;

    effect(() => {
    el.textContent = label.value;
    });

    label.value = "world"; // the element updates

    For richer output, see the Rendering group ( Diagram and the DOM helpers) and the live demo gallery.

    • Overview — a map of every capability.
    • Browse this reference by domain: Reactivity, Values, Lenses, Animation, Shapes, Rendering.
    • Demo gallery — interactive examples.