Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

tree

Recursive expandable tree. Each node renders as a clickable row (chevron + optional icon + label, indented by depth * indentPx, with optional right-side action buttons). Clicking the chevron emits <onToggle>-<key>; clicking the label emits <onSelect>-<key>. The tree itself is stateless — toggle/select state lives in the caller's state.

Exports

  • tree(nodes, opts?) -> Node — render a list of root nodes into a vbox of rows. Reached via the module's __call metamethod.
  • tree.fromFlat: (items, opts?) -> (roots, nodeById) — re-exports the fromFlat sub-module that builds recursive nodes from a flat parent-pointer list.

Node shape:

  • { key, label, children?, expandable?, expanded?, icon?, actions?, payload? }

Usage

local Z = { tree = require("@builtin::modules.zui.widget.tree") }

local function buildTree()
    return Z.tree(state.nodes, {
        onSelect    = "ent-select",
        onToggle    = "ent-toggle",
        selectedKey = state.selectedId,
    })
end

app:on("^ent%-select%-(.+)$", function(_v, _id, key)
    state.selectedId = key
end)
app:on("^ent%-toggle%-(.+)$", function(_v, _id, key)
    state.expanded[key] = not state.expanded[key]
end)

Notes

  • The module returns a callable table — tree(...) works as a function, and tree.fromFlat(...) reaches the sub-module. This is a dynamic-dispatch shape; the typed function directive is skipped here per the module-conversion spec rule 7.
  • A row gets a chevron when it has children OR when expandable == true (lazy-load: the caller fetches children on the toggle event).
  • actions callback ids are emitted verbatim — no key suffixing — so a row-level action ("× delete") reads as the same callback whether invoked from the tree, a context menu, or a toolbar.
  • Hard depth cap (32) protects against accidentally cyclic node data.