Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdf78e4f826

README.md

edui.app (module)

The edui reactive core. An App owns one ui.* screen and turns the string-callback-id protocol into ordinary closures.

ui.* dispatches interaction through string ids because closures cannot cross the FFI boundary: a widget carries props.onClick = "<id>", and the screen's registered env receives onCallback(id, data). An App hides that — during a build it allocates an id per closure and records id→closure, and its single onCallback looks the id up, calls the closure, and rebuilds.

Surface

  • new(screenName, opts?) -> App — opts.layer is a render-layer mask applied via ui.setScreenRenderLayer on first register; opts.callbackKey overrides the env key.
  • App:mount(builderFn) — register the callback env, run the first build. builderFn(app) -> widgetTree is re-run on every rebuild.
  • App:cb(closure, key?) -> id — the id to place in a widget's on* prop. Pass a stable key so the id survives a rebuild, which is required for anything the renderer tracks by id (focus, drag, ui.widgetState).
  • App:dispatch(id, data) -> handled — what the broadcast calls. Returns false for an id belonging to another surface so a host can keep routing.
  • App:markDirty() / App:rebuild() — a rebuild requested during a build is coalesced into a single follow-up, so a handler that mutates state and a builder that reads it never recurse.
  • App:unmount() — release the env and unregister the screen.
  • current() — the app whose builder is running right now, or nil outside a build. The edui primitives read this, which is why an author passes a closure and never threads the app through every call.

Builder errors are logged rather than thrown, so one bad build never wedges the editor.

local edui = require("modules.edui")
local app = edui.createApp("myPanel")
app:mount(function(a)
    return {
        type = "vertical",
        children = {
            { type = "button", props = {
                text = "Save",
                onClick = a:cb(function() save() end, "save"),
            } },
        },
    }
end)