@obinexusltd/obix-reactive
v0.1.0
Published
Reactive rendering layer for OBIX with automatic DOM updates and subscription-based state management
Maintainers
Readme
@obinexusltd/obix-reactive
Reactive rendering for OBIX components.
OBIX components are plain data objects with { state, actions, render }. This
package wraps that contract with a small render loop so actions update state,
notify subscribers, and update the mounted DOM automatically.
Install
npm install @obinexusltd/obix-reactive @obinexusltd/obixQuick Start
import { createReactive } from "@obinexusltd/obix-reactive";
import { createButton } from "@obinexusltd/obix";
const button = createButton({ label: "Click" });
const app = document.getElementById("app");
const { dispatch, getState } = createReactive(button, app);
dispatch("click");
console.log(getState());When a container is provided, createReactive mounts immediately. Each
dispatch(actionName, ...args) call runs the component action, stores a new
state revision, re-renders the container, and notifies subscribers.
Component Contract
interface ObixComponent<S> {
name: string;
state: S;
actions: Record<string, (state: S, ...args: unknown[]) => S>;
render: (state: S) => string;
}Actions should be pure and return a new state object. render should be
deterministic: the same state should always produce the same HTML string.
Delegated Events
The wrapper attaches one listener per event type and dispatches actions from OBIX data attributes. This avoids re-attaching listeners after every render.
<button data-obix-action="increment">Count</button>const counter = createReactive(component, document.getElementById("app"));By default the runtime delegates click, input, change, and submit.
Supported attributes include:
data-obix-action="increment"data-action="increment"data-obix-click="increment"data-click-action="increment"
For custom selectors, pass event bindings:
createReactive(component, app, {
events: [
{
event: "click",
selector: "[data-save]",
action: "save",
preventDefault: true
}
]
});API
const reactive = createReactive(component, container, options);The returned controller exposes:
state: current state snapshotdispatch(actionName, ...args): run an action and auto-rendersubscribe(listener): listen to state changes, returnsunsubscribemount(container?): render and attach delegated listenershydrate(container?): attach delegated listeners without replacing HTMLunmount(): remove delegated listeners and stop DOM updatesrender(state?): render to an HTML string without mutating the DOMgetState(): return the current stategetHistory(): return revision historyhalt()/resume(): pause and resume render notificationsundo(): restore the previous revisiondestroy(): cleanup subscriptions, listeners, and lifecycle state
Testing
Run the Vitest suite with:
npm testRun the focused unit test file with:
npm run test:unitVitest files import describe, it, and expect from vitest, so they should
not be executed directly with tsx or npx .\src\__tests__\index.test.ts.
For a direct executable check, use:
npm run smoke
# or
npx tsx src/smoke.tsRun the package build, focused tests, and smoke check together with:
npm run verifyServer Rendering
No DOM is required until mount or hydrate is called.
const reactive = createReactive(component);
const html = reactive.render();Design Notes
@obinexusltd/obix-reactive is the standalone reactive layer described in the
OBIX bottleneck documentation. It does not replace the component runtime or JSX
adapter. It sits at the application boundary and turns OBIX's plain data
components into interactive UI without React, Vue, or Svelte.
